带有一个wave的简单Waveout API [英] Simple Waveout API with one wave
问题描述
亲爱的朋友们,
我使用C ++进行编程,并且在我的PC上运行waveout API时遇到问题。任何人都可以帮助我获得正确的代码以使其正常工作吗?我正在使用VSC ++ Express!我已经包含了stdio.h,windows.h和winmm.lib!我会饶有帮助!
Dear friends,
I am programming in C++ and have a problem with waveout API to run on my PC. Could anybody help me to get the code right to get it work properly please ? I am using VSC++ Express! I have included stdio.h, windows.h, and winmm.lib ! I will apreciated evry help !
#define SOUNDBUFF 65536;
WAVEFORMATEX wf;
WAVEHDR whdr;
HWAVEOUT hWaveOut;
LPSTR lpData;
float clpData[65536];
int main(void)
{
FILE *f = fopen("c:/JP8080.wav","rb")
fwrite(&clpdata, 2, 1, sizeof(clpdata), f);
wf.wFormatTag=WAVE_FORMAT_PCM;
wf.nChannels=2;
wf.nSamplesPerSec=44100;
wf.nAvgBytesPerSec=(44100*4);
wf.nBlockAlign=(2*16)/8;
wf.wBitsPerSample=16;
wf.cbSize=0;
whdr.lpData = clpData;
whdr.dwBufferLength = SOUNDBUFF;
whdr.dwFlags = 0;
whdr.dwLoops = 0;
do {
} while (!(whdr.dwFlags & WHDR_DONE));
waveOutOpen(&hWaveOut,WAVE_MAPPER,&wf,0,0,CALLBACK_NULL);
waveOutPrepareHeader(hWaveOut,&whdr,sizeof(whdr));
waveOutWrite(hWaveOut,&whdr,sizeof(whdr));
do {
} while (!(whdr.dwFlags & WHDR_DONE));
waveOutUnprepareHeader(hWaveOut,&whdr,sizeof(whdr));
waveOutClose(hWaveOut);
return 0;
}
推荐答案
在我写任何其他内容之前,请允许我说明这是一个如何不代码的完美示例! ! (但它确实对我测试过的2个文件起作用 - 令人惊讶的是)
我写这篇文章的方式和我16岁的时候写的一样 - 它是所有的狗'鸟'粗糙粗糙,便宜 - 便宜
我应该注意到需要一个空的while while循环。 - 我们只是不断轮询WaveOutWrite是否在wh.dwFlags中设置了WHDR_DONE位
但是,你应该知道WAV格式不仅仅包含原始数据 - 它包含播放所需的信息,它还可能包括压缩和许多其他内容。
我鞭打这个使用: http://www.sonicspot.com/guide/wavefiles.html [ ^ ]
当然,MSDN ..
此代码是在使用Win7的系统上创建的。请相应地调整wav文件的路径。
Before I write anything else, let me state that this is a perfect example of HOW NOT TO CODE!! (but it does function for the 2 files I tested with - surprisingly)
I've written this in much the same way I wrote everything when I was 16 - it's all Dog 'n' Bird..... Rough-Rough, Cheap-Cheap
I should note that 1 of the empty do while loops IS needed. - We're just continually polling to see if WaveOutWrite has set the WHDR_DONE bit in wh.dwFlags
However, you should be aware that the WAV format holds so much more than just raw data - it holds information needed for playback, it may also include compression and a plethora of other things.
I whipped this up using: http://www.sonicspot.com/guide/wavefiles.html[^]
And of course, MSDN..
This code is created on a system with Win7. Please, adjust the path to the wav file accordingly.
#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>
typedef struct wavFileHeader
{
long chunkId; //"RIFF" (0x52,0x49,0x46,0x46)
long chunkSize; // (fileSize - 8) - could also be thought of as bytes of data in file following this field (bytesRemaining)
long riffType; // "WAVE" (0x57415645)
};
typedef struct fmtChunk
{
long chunkId; // "fmt " - (0x666D7420)
long chunkDataSize; // 16 + extra format bytes
short compressionCode; // 1 - 65535
short numChannels; // 1 - 65535
long sampleRate; // 1 - 0xFFFFFFFF
long avgBytesPerSec; // 1 - 0xFFFFFFFF
short blockAlign; // 1 - 65535
short significantBitsPerSample; // 2 - 65535
short extraFormatBytes; // 0 - 65535
};
typedef struct wavChunk
{
long chunkId;
long chunkDataSize;
};
char *readFileData(char *szFilename, long &dataLengthOut)
{
FILE *fp = fopen(szFilename, "rb");
long len;
char *buffer;
fseek(fp, 0, SEEK_END);
len = ftell(fp);
fseek(fp, 0, SEEK_SET);
buffer = (char*) calloc(1, len+1);
fread(buffer, 1, len, fp);
fclose(fp);
dataLengthOut = len;
return buffer;
}
void parseWav(char *data)
{
long *mPtr;
void *tmpPtr;
char *buffer;
WAVEFORMATEX wf;
WAVEHDR wh;
HWAVEOUT hWaveOut;
fmtChunk mFmtChunk;
wavChunk mDataChunk;
mPtr = (long*)data;
if ( mPtr[0] == 0x46464952) // little endian check for 'RIFF'
{
mPtr += 3;
if (mPtr[0] == 0x20746D66) // little endian for "fmt "
{
// printf("Format chunk found\n");
tmpPtr = mPtr;
memcpy(&mFmtChunk, tmpPtr, sizeof(mFmtChunk));
tmpPtr += 8;
tmpPtr += mFmtChunk.chunkDataSize;
mPtr = (long*)tmpPtr;
if (mPtr[0] == 0x61746164) // little endian for "data"
{
// printf("Data chunk found\n");
tmpPtr = mPtr;
memcpy(&mDataChunk, tmpPtr, sizeof(mDataChunk));
mPtr += 2;
buffer = (char*) malloc(mDataChunk.chunkDataSize);
memcpy(buffer, mPtr, mDataChunk.chunkDataSize);
printf("sampleRate: %d\n", mFmtChunk.sampleRate);
wf.wFormatTag = mFmtChunk.compressionCode;
wf.nChannels = mFmtChunk.numChannels;
wf.nSamplesPerSec = mFmtChunk.sampleRate;
wf.nAvgBytesPerSec = mFmtChunk.avgBytesPerSec;
wf.nBlockAlign = mFmtChunk.blockAlign;
wf.wBitsPerSample = mFmtChunk.significantBitsPerSample;
wf.cbSize = mFmtChunk.extraFormatBytes;
wh.lpData = buffer;
wh.dwBufferLength = mDataChunk.chunkDataSize;
wh.dwFlags = 0;
wh.dwLoops = 0;
waveOutOpen(&hWaveOut,WAVE_MAPPER,&wf,0,0,CALLBACK_NULL);
waveOutPrepareHeader(hWaveOut,&wh,sizeof(wh));
waveOutWrite(hWaveOut,&wh,sizeof(wh));
do {}
while (!(wh.dwFlags & WHDR_DONE));
waveOutUnprepareHeader(hWaveOut,&wh,sizeof(wh));
waveOutClose(hWaveOut);
free(buffer);
}
}
}
else
printf("INvalid WAV\n");
}
int main()
{
char *filename = "c:/windows/media/tada.wav";
char *buffer;
long fileSize;
buffer = readFileData(filename, fileSize);
parseWav(buffer);
free(buffer);
return 0;
}
编辑:我刚刚玩了这个代码,发现了很多我的恐怖 - 在发布版本运行后播放声音时程序挂起 - (从未将其作为调试版本翻过来)
似乎编译器正在优化空的do while循环 - 没有意识到我的源代码之外的代码将修改wh.dwFlags
解决方案是这样添加volatile关键字:
I just played with this code some more, discovering much to my horror - that the program hung after playing the sound when the release version was run -(never flicked it over from being a debug build)
It seems that the compiler was optimizing the empty do while loop - not realizing that code outside of my source was going to modify wh.dwFlags
The solution was to add the volatile keyword thusly:
volatile WAVEHDR wh;
和任何使用& wh的用法如下:
and to cast any use of &wh like so:
(wavehdr_tag*)&wh
此代码已有近4年的历史,但我很满意。它是WaveOut函数的第一个例子,我可以开始工作。
我需要另外修改才能完成这项工作。
一些.wav文件有一个我们需要跳过的信息块。
我必须在数据(0x61746164)的测试前插入这段代码:
This code is nearly 4 years old already, but I am pleased with it. Its the first example with WaveOut functions that I could get to work.
I needed another modification to make this work.
Some .wav files have an info block that we need to skip.
I had to insert this code just in front of the test for "data" (0x61746164):
if (mPtr[0] == 0x5453494C) { // little endian for "LIST"
// skip info chunk
memcpy(&mDataChunk, tmpPtr, sizeof(mDataChunk));
tmpPtr = (void*) (((char*) tmpPtr ) + 8 + mDataChunk.chunkDataSize);
mPtr = (long*)tmpPtr;
}
if (mPtr[0] == 0x61746164)
我的编译器( Borland CBuilder 6)抱怨这一行的语法:
Also my compiler (Borland CBuilder 6) complained about the syntax of this line:
tmpPtr += 8;
我必须将其更改为:
I had to change it to:
tmpPtr = (void*) ((char*) tmpPtr ) + 8;
这篇关于带有一个wave的简单Waveout API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!