1
votes

I captured raw audio data stream together with its WAVEFORMATEXTENSIBLE struct. WAVEFORMATEXTENSIBLE is shown in the figure below:

The WAVEFORMATEXTENSIBLE struct

Following the standard of wav file, I tried to write the raw bits into a wav file. What I do is:

  1. write "RIFF".

  2. write a DWORD. (filesize - sizeof("RIFF") - sizeof(DWORD)).

=== WaveFormat Chunk ===

  1. write "WAVEfmt "

  2. write a DWORD. (size of the WAVEFORMATEXTENSIBLE struct)

  3. write the WAVEFORMATEXTENSIBLE struct.

=== Fact Chunk ===

  1. write "fact"

  2. write a DWORD. ( 4 )

  3. write a DWORD. ( num of samples in the stream, which should be sizeof(rawdata)*8/wBitsPerSample ).

=== Data Chunk ===

  1. write "data"

  2. write a DWORD (size of rawdata)

  3. write the raw data.

After getting the wav file from the above steps, I played the wav file with media player, there is no sound, playing with audacity will give me a distorted sound, I can hear that it is the correct audio I want, but the sound is distorted with noise.

The raw data can be find here

The wav file I generate is here

It is very confusing to me, because when I use the same method to convert IEEE-float data to wav file, it works just fine.

2
are you sure your raw data is 32 bit?Mark Heath
It should be, coz the WAVEFORMATEX structure say it is, and the WAVEFORMATEX is obtained from the IAudioClient.Min Lin
but is it 32 bit int or 32 bit float? that might account for the problem. You need to check your subtype GUID is correct (PCM or FLOAT)Mark Heath
I don't quite understand, these data are captured by hooking into the IAudioRenderClient, and intercept the getBuffer and releaseBuffer method. I get the WAVEFORMATEX structure from the coressponding IAudioClient, I think I should assume the WAVEFORMATEX is correct and use as it is.Min Lin
I'm not sure why initialize method on IAudioClient needs a waveformatex parameter, isn't it readily available from the GetMixFormat method? Sample codes always obtain waveformatex from GetMixFormat of IAudioClient, and pass it back to the initialize method of IAudioClient.Min Lin

2 Answers

0
votes

I figured this out, it seems the getbuffer releasebuffer cycle in IAudioRenderClient is putting raw data that has the format same as that passed into the initialize method of the IAudioClient.

The GetMixFormat in IAudioClient in my case is different from the format passed into the initialize method. I think GetMixFormat gets the format that the device supports.

IAudioClient should have done the conversion of format from the initialized format to the mixformat. I intercept the initialize method, get the format, and it works like a charm.

0
votes

I'm intercepting WASAPI to access the audio data and face the exact same issue where the generated audio file from the data sounds like the correct content but is very noisy somehow although the frame rate, sample width, number of channels etc. are set properly.

The SubFormat field of WAVEFORMATEXTENSIBLE shows that the data is actually KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, while I originally treat it as integers. According to this page, KSDATAFORMAT_SUBTYPE_IEEE_FLOAT is equivalent to WAVE_FORMAT_IEEE_FLOAT in WAVEFORMATEX. Hence, setting the "audio format" in the wav file's fmt chunk(normally starts in the 20th position) to WAVE_FORMAT_IEEE_FLOAT(which is 3) solved the problem. Remember to put it in little endian.

  • Original value of audio format enter image description here
  • After modification enter image description here