Meugiwara
Meugiwara

Reputation: 769

How to convert stereo sound to mono with FFmpeg?

I use the FFmpeg library for a personnal project and I need help about one thing. I have a music file in stereo sound and I want to convert this stereo sound to mono sound ? Is it possible with this library ? Is there a function inside to do this job ? My project is in C/C++.

I searched on the Doxygen documentation on the FFmpeg website and on this forum but I didn't find something interesting.

Thanks for reading !

Upvotes: 62

Views: 83415

Answers (3)

user1810087
user1810087

Reputation: 5334

As I mentioned in the comment, you could resample it yourself. It depends on what you already have and what format you use. I cannot give you code which would work instantly, but give you an example (pseudo/real code mix).

After you encoded the frame, and have done the things you have to do, your data buffer will be filled with the audio. Now it depends how your format is (see here) and how many channels you have. Let's assume it is signed 16bit stereo, than your buffer would look like:

+-----+-----+-----+-----+-----+
| LS1 | RS1 | LS2 | RS2 | ... |
+-----+-----+-----+-----+-----+
// LS = LEFT SAMPLE 16 Bit
// RS = RIGHT SAMPLE 16 Bit

Now iterate through the buffer and calculate left and right sample together.

for(int i=0; i<sample_size; i+=2) {
    auto r = (static_cast<int32_t>(buffer[i]) + buffer[i+1]) / 2;
    buffer[i] = buffer[i+1] = r;
}

Upvotes: 1

Neeraj Shukla
Neeraj Shukla

Reputation: 1581

You can just use ffmpeg. Direct command is present for the purpose-

ffmpeg -i stereo.flac -ac 1 mono.flac

Would convert your stereo file into mono channel. For more details, you can look at this page-

https://trac.ffmpeg.org/wiki/AudioChannelManipulation

Upvotes: 120

Steve M
Steve M

Reputation: 9794

Use swr_convert from libswresample to convert between formats. Something like:

#include "libswresample/swresample.h"

au_convert_ctx = swr_alloc();

out_channel_layout = AV_CH_LAYOUT_MONO;
out_sample_fmt = AV_SAMPLE_FMT_S16;
out_sample_rate = 44100;
out_channels = av_get_channel_layout_nb_channels(out_channel_layout);

in_sample_fmt = pCodecCtx->sample_fmt;
in_channel_layout=av_get_default_channel_layout(pCodecCtx->channels);

au_convert_ctx=swr_alloc_set_opts(au_convert_ctx,out_channel_layout, out_sample_fmt, out_sample_rate,
            in_channel_layout, in_sample_fmt, pCodecCtx->sample_rate, 0, NULL);
swr_init(au_convert_ctx);
//Generate your frame of original audio, then use swr_convert to convert to mono,
//converted number of samples will now be in out_buffer.
int converted = swr_convert(au_convert_ctx, &out_buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)&pFrame->data , pFrame->nb_samples);
//...
swr_free(&au_convert_ctx);

to get you started. This will convert whatever the original format happens to be to 44100 kHz mono. You could also use pCodecCtx->sample_rate as the output sample rate as well.

It's the most flexible and easiest solution.

Upvotes: 9

Related Questions