问题描述
亲爱的朋友们,
我使用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;
}
推荐答案
#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
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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!