2016-01-24 70 views
0

我正在使用swr_convert降低/提高傳入音頻的音調並將其存儲在.mp3中。爲了改變音調,我將出樣率除以一個因子。然而,所產生的聲音是輕微扭曲時,此因子大於1。這裏其他任何事情都有我的轉換代碼:C++ FFmpeg節距問題

... 

// 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被定義爲44100 這裏就是整個程序,如果有幫助:http://pastebin.com/5akEwNg4

的程序會生成一個帶有25個音高減小的音符.mp3。 這裏是一個失真的例子:http://www.stuffbydavid.com/dl/30256478.mp3

你能發現我的轉換有任何不正確的地方,或者我的方法改變了音調不正確嗎?有另一種方法嗎?

回答

2

您調用swr_convert()時NULL爲輸入flushes the internal queue,那(間接)導致失真(因爲在刷新之後提交新輸入)。您需要在循環中用有效的輸入輸出緩衝區(兩個非NULL)調用swr_convert,直到文件完成解碼,然後只有然後用最後一個NULL輸入刷新隊列。

+0

再次感謝羅納德! – david

+0

好的,這是我的新嘗試:http://pastebin.com/MBarj3xA 儘管如此,仍然扭曲的音頻,任何想法?謝謝。 – david

+0

你的fwrite()應該使用swr_convert()的返回值來派生多少個樣本來寫,我不認爲你想要調用av_samples_get_buffer_size()。 –