I am writing an application where I get sound data using low-latency ASIO card. The low-latency means that I get only 128 samples per batch, for 48k sample rate. From the ASIO card, I get raw samples in 32-bit signed integer range.
Now I want to listen to the sound coming through the ASIO card, but not on the ASIO card, but on the default output device in Windows. I am using waveOutWrite set up with WAVE_FORMAT_PCM and the same characteristics as the ASIO input. I call it every time I get a new 128-sample long batch. Now, because Wav format does not allow for 32-bit integer samples, I downgrade them to 16-bits.
HWAVEOUT waveOut;
void startListening(){
WAVEFORMATEX format;
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 1;
format.nSamplesPerSec = sampleRate;
format.nAvgBytesPerSec = sampleRate * 2;
format.nBlockAlign = 2;
format.wBitsPerSample = 16;
format.cbSize = 0;
MMRESULT result = waveOutOpen(waveOut, WAVE_MAPPER, &format, 0, 0, CALLBACK_NULL);
if(result != MMSYSERR_NOERROR){
return;
}
}
typedef struct{
short *buffer;
int length;
HWAVEOUT waveOut;
} ListenInfo;
void newListeningData(void *buffer, int length){
ListenInfo *listenInfo = new ListenInfo();
listenInfo->buffer = new short[length];
listenInfo->length = length;
listenInfo->waveOut = *waveOut;
if(bitrate == 32){
int *bufferInt = (int *)buffer;
for(int i = 0; i < length; i++){
listenInfo->buffer[i] = (bufferInt[i]);
}
CreateThread(NULL, 0, &(listen), listenInfo, 0, NULL);
}
else if(bitrate == 16){
memcpy(listenInfo->buffer, (short *)buffer, length * 2);
CreateThread(NULL, 0, &(listen), listenInfo, 0, NULL);
}
else{
printf("%d: Bitrate is not 16 or 32!\n", index);
}
}
DWORD WINAPI listen(__in LPVOID lpParameter){
ListenInfo *info = (ListenInfo *)lpParameter;
WAVEHDR header;
memset(&header, 0, sizeof(WAVEHDR));
header.dwBufferLength = info->length;
header.lpData = (char *)(info->buffer);
MMRESULT result = waveOutPrepareHeader(info->waveOut, &header, sizeof(WAVEHDR));
result = waveOutWrite(info->waveOut, &header, sizeof(WAVEHDR));
while(waveOutUnprepareHeader(info->waveOut, &header, sizeof(WAVEHDR)) == WAVERR_STILLPLAYING){
Sleep(10);
}
delete[] info->buffer;
delete info;
return 0;
}
The problem is that I can hear only severe clipping and squeaking. The sound is distorted beyond recognition. I know it is not a synchronization error, because I also save the samples into a wav file with the same characteristics and the sound is distorted in the same way.
How can I convert signed 32-bit samples into something that waveOutWrite can play?
The problem was cause by the fact that I was using different bitrate than I was led to believe I was using. When I modified the WAVEFORMATEX with correct values, it worked!