mackron / miniaudio

Audio playback and capture library written in C, in a single source file.
https://miniaud.io
Other
4.07k stars 361 forks source link

ma_copy_pcm_frames seems to be copying empty frames on certain callbacks #460

Closed dbajpeyi closed 2 years ago

dbajpeyi commented 2 years ago

Scenario

I am trying to:

  1. Playback a wav file with ma_decoder_read_pcm_frames,
  2. Copy the pcm frames from pOutput to an outputBuffer and,
  3. Write the outputBuffer using ma_encoder_write_pcm_frames

Seems like the copy ends up copying 0.0000 into certain equal sections of 480 frames. On inspecting the output on Audacity, this is clear:

Screenshot 2022-04-26 at 0 45 41

Here are the missing spots:

Screenshot 2022-04-26 at 0 56 43

My approach is here in this gist.

Debug info

DEBUG: Failed to initialize DirectSound backend.
DEBUG: Failed to initialize WinMM backend.
DEBUG: Attempting to initialize Core Audio backend...
DEBUG: Loading library: CoreFoundation.framework/CoreFoundation
DEBUG: Loading symbol: CFStringGetCString
DEBUG: Loading symbol: CFRelease
DEBUG: Loading library: CoreAudio.framework/CoreAudio
DEBUG: Loading symbol: AudioObjectGetPropertyData
DEBUG: Loading symbol: AudioObjectGetPropertyDataSize
DEBUG: Loading symbol: AudioObjectSetPropertyData
DEBUG: Loading symbol: AudioObjectAddPropertyListener
DEBUG: Loading symbol: AudioObjectRemovePropertyListener
DEBUG: Loading library: AudioUnit.framework/AudioUnit
DEBUG: Loading symbol: AudioComponentFindNext
DEBUG: Loading symbol: AudioComponentFindNext
DEBUG: Loading symbol: AudioComponentInstanceDispose
DEBUG: Loading symbol: AudioComponentInstanceNew
DEBUG: Loading symbol: AudioOutputUnitStart
DEBUG: Loading symbol: AudioOutputUnitStop
DEBUG: Loading symbol: AudioUnitAddPropertyListener
DEBUG: Loading symbol: AudioUnitGetPropertyInfo
DEBUG: Loading symbol: AudioUnitGetProperty
DEBUG: Loading symbol: AudioUnitSetProperty
DEBUG: Loading symbol: AudioUnitInitialize
DEBUG: Loading symbol: AudioUnitRender
DEBUG: System Architecture:
DEBUG:   Endian: LE
DEBUG:   SSE2:   YES
DEBUG:   AVX2:   NO
DEBUG:   NEON:   NO
INFO: [Core Audio]
INFO:   MacBook Pro Speakers (Playback)
INFO:     Format:      24-bit Signed Integer (Tightly Packed) -> 32-bit IEEE Floating Point
INFO:     Channels:    2 -> 2
INFO:     Sample Rate: 44100 -> 48000
INFO:     Buffer Size: 480*3 (1440)
INFO:     Conversion:
INFO:       Pre Format Conversion:  YES
INFO:       Post Format Conversion: NO
INFO:       Channel Routing:        NO
INFO:       Resampling:             YES
INFO:       Passthrough:            NO

What I found interesting is that there's for some reason resampling going on, although in my code I use the decoder's settings from the input file.

Also apologies in advance - I am a fresher when it comes to C and audio in C :) Any help would be a big learning experience for me :)

mackron commented 2 years ago

The problem is the way you're doing your pointer offsetting. You should instead make them void pointers and offset them with ma_get_bytes_per_frame(format, channels). In the callback you have this:

double* buffArr = *(buffer) + start;

That's wrong. Instead you should do something like this:

void* buffArr = ma_offset_ptr(*buffer, start * ma_get_bytes_per_frame(pDecoder->outputFormat, pDecoder->outputChannels));

That's assuming start is in PCM frames and not bytes, which it looks like it is if I'm reading it correctly.

Also, with your buffer allocation:

outputBuffer = malloc(buffLength * sizeof(*outputBuffer));

Change that this:

outputBuffer = malloc(buffLength * ma_get_bytes_per_frame(pDecoder->outputFormat, pDecoder->outputChannels));

The only reason this wasn't crashing is by coincidence. If you had passed in a file with, say, 4 channels, it would have crashed.

So to summarise, as a start I would replace all of your double* pointers with void* and offset with ma_offset_ptr() and ma_get_bytes_per_frame(). Once you've done that let me know if you have any other issues and we'll go from there.

dbajpeyi commented 2 years ago

Aha! Right I mixed up the idea of frames with bytes. Damn! Thank you for the hints, I will try this out and get back with results.

dbajpeyi commented 2 years ago

Alright! That worked out! Thank you so much for the help :)