I’m using the code below to load and convert .wav files into my project’s native format (sample rate is proj->sample_rate
, and proj->fmt
is the SDL_AudioFormat
.)
It works perfectly most of the time, but it seems to break when upsampling (44.1 → 48kHz) large wav files. The first part of the file will convert fine, but at some seemingly arbitrary time (12m42s in the main test file I’m using), the converted signal becomes extremely distorted. The desired signal is still discernible through the noise, but barely. Here’s what the boundary between the correctly-converted signal and distorted portion looks like:
Anyone know what might be causing this? I’d be suspicious of type overflow somewhere in my code, but can’t find an error. The sanity-check print statements show reasonable values.
SDL_AudioSpec wav_spec;
uint8_t* audio_buf = NULL;
uint32_t audio_len_bytes = 0;
if (!(SDL_LoadWAV(filename, &wav_spec, &audio_buf, &audio_len_bytes))) {
fprintf(stderr, "Error loading wav %s: %s", filename, SDL_GetError());
return NULL;
}
SDL_AudioCVT wav_cvt;
int ret = SDL_BuildAudioCVT(&wav_cvt, wav_spec.format, wav_spec.channels, wav_spec.freq, proj->fmt, proj->channels, proj->sample_rate);
if (ret < 0) {
fprintf(stderr, "Error: unable to build SDL_AudioCVT. %s\n", SDL_GetError());
return NULL;
} else if (ret == 1) { // Needs conversion
fprintf(stderr, "Converting. Len mult: %d\n", wav_cvt.len_mult);
fprintf(stderr, "WAV specs: freq: %d, format: %s, channels: %d\n", wav_spec.freq, get_fmt_str(wav_spec.format), wav_spec.channels);
fprintf(stderr, "dst specs: freq: %d, format %s, channels: %d\n", proj->sample_rate, get_fmt_str(proj->fmt), proj->channels);
fprintf(stderr, "Len ratio: %f\n", wav_cvt.len_ratio);
wav_cvt.needed = 1;
wav_cvt.len = audio_len_bytes;
size_t alloc_len = (size_t)audio_len_bytes * wav_cvt.len_mult;
fprintf(stdout, "Alloc len: %lu\n", alloc_len);
wav_cvt.buf = malloc(alloc_len);
if (!wav_cvt.buf) {
fprintf(stderr, "ERROR: unable to allocate space for conversion buffer\n");
exit(1);
}
memcpy(wav_cvt.buf, audio_buf, audio_len_bytes);
if (SDL_ConvertAudio(&wav_cvt) < 0) {
fprintf(stderr, "Error: Unable to convert audio. %s\n", SDL_GetError());
return NULL;
}
audio_len_bytes *= wav_cvt.len_ratio;
} else if (ret == 0) { // No conversion needed
fprintf(stderr, "No conversion needed. copying directly to track.\n");
wav_cvt.buf = malloc(audio_len_bytes);
memcpy(wav_cvt.buf, audio_buf, audio_len_bytes);
} else {
fprintf(stderr, "Error: unexpected return value for SDL_BuildAudioCVT.\n");
return NULL;
}
Output:
Converting. Len mult: 8
WAV specs: freq: 44100, format: AUDIO_S16LSB, channels: 2
dst specs: freq: 48000, format AUDIO_S16LSB, channels: 2
Len ratio: 1.088435
Alloc len: 6117130240