[英]C++ FFmpeg pitch issue
I'm using swr_convert to lower/raise the pitch of incoming audio and store it in a .mp3. 我正在使用swr_convert降低/提高传入音频的音调并将其存储在.mp3中。 To change the pitch, I'm dividing the out sample rate by a factor. 为了改变音高,我将采样率除以一个因子。 However, the resulting audio is slightly distorted when this factor is anything other than 1. Here's my conversion code: 但是,当此因素不是1时,产生的音频会稍微失真。这是我的转换代码:
...
// Set up resample context
swrContext = swr_alloc();
if (!swrContext)
throw -15;
av_opt_set_int(swrContext, "in_channel_count", codecContext->channels, 0);
av_opt_set_int(swrContext, "in_channel_layout", codecContext->channel_layout, 0);
av_opt_set_int(swrContext, "in_sample_rate", codecContext->sample_rate, 0);
av_opt_set_sample_fmt(swrContext, "in_sample_fmt", codecContext->sample_fmt, 0);
av_opt_set_int(swrContext, "out_channel_count", STREAM_AUDIO_CHANNELS, 0);
av_opt_set_int(swrContext, "out_channel_layout", STREAM_AUDIO_CHANNEL_LAYOUT, 0);
av_opt_set_int(swrContext, "out_sample_rate", STREAM_AUDIO_SAMPLE_RATE / pitch, 0);
av_opt_set_sample_fmt(swrContext, "out_sample_fmt", STREAM_AUDIO_SAMPLE_FORMAT_GM, 0);
if (swr_init(swrContext))
throw -16;
// Allocate re-usable frame
frameDecoded = av_frame_alloc();
if (!frameDecoded)
throw -17;
frameDecoded->format = codecContext->sample_fmt;
frameDecoded->channel_layout = codecContext->channel_layout;
frameDecoded->channels = codecContext->channels;
frameDecoded->sample_rate = codecContext->sample_rate;
// Load frames
inPacket.data = NULL;
inPacket.size = 0;
int gotFrame, samples = 0;
while (av_read_frame(formatContext, &inPacket) >= 0) {
if (inPacket.stream_index != streamId)
continue;
if (avcodec_decode_audio4(codecContext, frameDecoded, &gotFrame, &inPacket) < 0)
throw -18;
if (!gotFrame)
continue;
// Begin conversion
if (swr_convert(swrContext, NULL, 0, (const uint8_t **)frameDecoded->data, frameDecoded->nb_samples) < 0)
throw -19;
while (swr_get_out_samples(swrContext, 0) >= RAW_AUDIO_FRAME_SIZE) {
// Allocate data
uint8_t **convertedData = NULL;
if (av_samples_alloc_array_and_samples(&convertedData, NULL, STREAM_AUDIO_CHANNELS, RAW_AUDIO_FRAME_SIZE, STREAM_AUDIO_SAMPLE_FORMAT_GM, 0) < 0)
throw -20;
// Convert
if (swr_convert(swrContext, convertedData, RAW_AUDIO_FRAME_SIZE, NULL, 0) < 0)
throw -21;
// Calculate buffer size
size_t bufferSize = av_samples_get_buffer_size(NULL, STREAM_AUDIO_CHANNELS, RAW_AUDIO_FRAME_SIZE, STREAM_AUDIO_SAMPLE_FORMAT_GM, 0);
if (bufferSize < 0)
throw -22;
fwrite(convertedData[0], 1, bufferSize, outStream);
av_free(convertedData);
}
}
...
STREAM_AUDIO_SAMPLE_RATE is defined as 44100. Here's the entire program if it helps: http://pastebin.com/5akEwNg4 STREAM_AUDIO_SAMPLE_RATE定义为44100。如果有帮助,请参见下面的整个程序: http ://pastebin.com/5akEwNg4
The program generates a .mp3 with 25 notes that decrease in pitch. 该程序将生成一个带有25个音调减小的.mp3。 Here's an example of the distortion: http://www.stuffbydavid.com/dl/30256478.mp3 这是失真的示例: http : //www.stuffbydavid.com/dl/30256478.mp3
Can you spot anything incorrect about my conversion, or is my method of changing the pitch incorrect? 您能发现关于我的转换的任何错误信息,还是我更改音高的方法不正确? Is there another way? 还有另一种方法吗?
Your call to swr_convert() with NULL as input flushes the internal queue and that (indirectly) causes the distortions (because after flushing you submit new input). 调用swr_convert()并以NULL作为输入将刷新内部队列,并(间接)导致变形(因为刷新后您提交了新输入)。 You need to call swr_convert with a valid input and output buffer (both non-NULL) in a loop until the file has finished decoding, and only then flush the queue with NULL input at the very end. 您需要,直到该文件已完成解码, 然后才在最后刷新队列与NULL输入回路与有效输入和输出缓冲(均为非NULL)调用swr_convert。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.