Hi there,
I've encountered a strange issue with the waveOut API's and I'm not sure if its by design or if I'm missing something.
Basically If I open a device specifying that the default communication device is to be used, that device will always cause ducking/stream attenuation to occur for all future uses of said device. Even when I no longer specify that the default communications
device should be used.
I've found some crude sample code to try and explain:
#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, bool playDefaultComm)
{
long *mPtr;
char *tmpPtr;
char *buffer;
WAVEFORMATEX wf;
volatile 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 = (char*)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 = (char*)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;
if (playDefaultComm)
{
waveOutOpen(&hWaveOut, WAVE_MAPPER, &wf, 0, 0, WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE);
}
else
{
//Make sure the device ID is set to your default communications device.
waveOutOpen(&hWaveOut, 1, &wf, 0, 0, CALLBACK_NULL);
}
waveOutPrepareHeader(hWaveOut, (wavehdr_tag*)&wh, sizeof(wh));
waveOutWrite(hWaveOut, (wavehdr_tag*)&wh, sizeof(wh));
do {} while (!(wh.dwFlags & WHDR_DONE));
waveOutUnprepareHeader(hWaveOut, (wavehdr_tag*)&wh, sizeof(wh));
waveOutClose(hWaveOut);
free(buffer);
}
}
}
else
printf("INvalid WAV\n");
}
int main()
{
//choose your file to play
char *filename = "c:/windows/media/tada.wav";
char *buffer;
long fileSize;
buffer = readFileData(filename, fileSize);
//play the .wav using the default communications device.
//Ducks audio as expected
parseWav(buffer, true);
//play the .wav using the specified device. (continues to cause ducking for some reason)
parseWav(buffer, false);
free(buffer);
return 0;
}
If I call the parseWav(buffer,false) first, ducking will not occur.
Its only if I attempt to specify the default communications device that it continues to duck no matter what.
Thanks for your help,
Cathal
Edit:
To clarify what I'm trying to achieve:
I want to play two separate files on the same device.
One will cause ducking, the other will not.