ZoolWay
ZoolWay

Reputation: 5505

Writing WebRTC (AudioTrackSinkInterface) raw audio to disc

I'm trying to record the audio transferred by a WebRTC PeerConnection MediaStream. I added a sink to the audio track which implements AudioTrackSinkInterface. It implements the OnData method:

void TestAudioTrackSink::OnData(const void* audio_data, int bits_per_sample, int sample_rate, size_t number_of_channels, size_t number_of_frames) {
    size_t valueCount = number_of_channels * number_of_frames;
    int16_t *_data = (int16_t*)audio_data;

    f.write((char*)&_data, sizeof(int16_t) * valueCount);
    f.flush();
}

f is an ofstream. Bits per sample is 16, sample rate is 16000, channels is 1, frames is 160.

But when I open the created file with AudaCity raw import (signed 16bit PCM, little endian, mono, sample rate 16000) I am not getting meaningful audio.

How to I correctly write that raw audio date?

Upvotes: 5

Views: 2893

Answers (2)

ceztko
ceztko

Reputation: 15207

To add some more details to @ZoolWay already correct answer, I had file corruption issues when not opening the file in binary mode in Windows platform. In short, ensure the file has the ios_base::binary flag:

std::ofstream stream(LR"(D:\test.pcm)", ios_base::binary);

[...]

void TestAudioTrackSink::OnData(const void* audio_data, int bits_per_sample, int sample_rate, size_t number_of_channels, size_t number_of_frames)
{
    size_t number_of_bytes = number_of_channels * number_of_frames * sizeof(int16_t); //assuming bits_per_sample is 16      
    stream.write(reinterpret_cast<const char*>(audio_data), number_of_bytes);
    stream.flush();
}

Fixed the issue for me.

Upvotes: 0

ZoolWay
ZoolWay

Reputation: 5505

Turned out in the end I access the data where the pointer itself was stored and not where it was pointing to, a classic. The correct implementation of my method would look like:

void TestAudioTrackSink::OnData(const void* audio_data, int bits_per_sample, int sample_rate, size_t number_of_channels, size_t number_of_frames) {
    size_t number_of_bytes = number_of_channels * number_of_frames * sizeof(int16_t); //assuming bits_per_sample is 16      
    f.write(reinterpret_cast<const char*>(audio_data), number_of_bytes);
    f.flush();
}

Note: For more processing of webrtc native retrieved and sent audio data I am checking out a custom AudioDeviceModule now.

Upvotes: 4

Related Questions