Reputation: 19
I have function for resampling one channel of audio (as a float
array):
int resample_and_save(float *audio_input, int input_sample_rate, int output_sample_rate, int input_num_of_samples, const char *output_file) {
AVChannelLayout ch_layout = AV_CHANNEL_LAYOUT_MONO;
SwrContext *swr_ctx = swr_alloc();
uint8_t **resampled_data = NULL;
float *audio_output = NULL;
int ret = SUCCESS;
if (!swr_ctx) {
fprintf(stderr, "Could not allocate resampler context\n");
return ERROR_NOTENOUGH_MEMORY;
}
av_opt_set_chlayout(swr_ctx, "in_chlayout", &ch_layout, 0);
av_opt_set_int(swr_ctx, "in_sample_rate", input_sample_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
av_opt_set_chlayout(swr_ctx, "out_chlayout", &ch_layout, 0);
av_opt_set_int(swr_ctx, "out_sample_rate", output_sample_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
if ((ret = swr_init(swr_ctx)) < 0) {
ret = handle_av_error(ret);
goto cleanup;
}
int output_samples_count = av_rescale_rnd(swr_get_delay(swr_ctx, input_sample_rate) + input_num_of_samples, output_sample_rate, input_sample_rate, AV_ROUND_UP);
ret = av_samples_alloc_array_and_samples(&resampled_data, NULL, 1, output_samples_count, AV_SAMPLE_FMT_FLT, 0);
if (ret < 0) {
ret = handle_av_error(ret);
goto cleanup;
}
const uint8_t *in_samples[1] = { (const uint8_t *)audio_input };
int frame_count = swr_convert(swr_ctx, resampled_data, output_samples_count, in_samples, input_num_of_samples);
if (frame_count < 0) {
fprintf(stderr, "Error while resampling\n");
ret = ERROR_UNKNOWN;
goto cleanup;
}
while (1) {
int frame_count_flush = swr_convert(swr_ctx, resampled_data, output_samples_count, NULL, 0);
if (frame_count_flush <= 0) {
break;
}
frame_count += frame_count_flush;
}
audio_output = (float *)malloc(frame_count * sizeof(float));
if (!audio_output) {
fprintf(stderr, "Could not allocate memory for output\n");
ret = ERROR_NOTENOUGH_MEMORY;
goto cleanup;
}
memcpy(audio_output, resampled_data[0], frame_count);
ret = write_wav(output_file, audio_output, frame_count, output_sample_rate);
cleanup:
if (resampled_data != NULL)
av_freep(&resampled_data[0]);
swr_free(&swr_ctx);
if (audio_output != NULL)
free(audio_output);
return ret;
}
write_wav
:
int write_wav(const char *filename, float *samples, int num_samples, int sample_rate) {
FILE *file = fopen(filename, "wb");
if (!file) {
fprintf(stderr, "Unable to open file for writing\n");
return ERROR_UNKNOWN;
}
unsigned char header[44] = {
'R','I','F','F', // RIFF
0,0,0,0, // Chunk size (to be filled later)
'W','A','V','E', // WAVE
'f','m','t',' ', // fmt
16,0,0,0, // Subchunk1Size (16 for PCM)
1,0, // AudioFormat (1 for PCM)
1,0, // NumChannels (1 for mono)
0,0,0,0, // SampleRate (to be filled later)
0,0,0,0, // ByteRate (to be filled later)
4,0, // BlockAlign (4 bytes per sample frame for float)
32,0, // BitsPerSample (32 for float samples)
'd','a','t','a', // Subchunk2ID
0,0,0,0 // Subchunk2Size (to be filled later)
};
int byte_rate = sample_rate * 4;
int subchunk2_size = num_samples * 4;
int chunk_size = 36 + subchunk2_size;
memcpy(header + 24, &sample_rate, 4);
memcpy(header + 28, &byte_rate, 4);
memcpy(header + 40, &subchunk2_size, 4);
memcpy(header + 4, &chunk_size, 4);
fwrite(header, sizeof(header), 1, file);
fwrite(samples, sizeof(float), num_samples, file);
fclose(file);
return 0;
}
When I play the audio (even one-channel audio), there is a lot of noise on it, like there are missing samples. How can I fix it?
This is how original audio looks (24000 hz
):
And this is a resampled audio (48000 hz
):
Upvotes: 0
Views: 73