Question

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?

Was it helpful?

Solution

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top