2012-04-27 91 views
1

我的應用程序使用LAME將原始pcm數據編碼爲mp3。但我有一個問題 - 輸出的MP3包含持續一段時間的「點擊」。類似的東西:將pcm轉換爲mp3(使用LAME)會在mp3文件中產生「點擊」

聲音......「咔嚓」的聲音。「咔嚓」一聲..「點擊」等...

我已經試過LAME的不同版本,並試圖改變許多LAME設置,但不成功。我的應用程序也可以將pcm轉換爲wav和ogg,但這種轉換器不會導致「點擊」。

有一個編碼代碼(PCM輸入包含一個信道的數據,PCM已經重新採樣到44100 FREQ):

初始化:

lame = lame_init(); 
lame_set_in_samplerate(lame, 44100); 
lame_set_VBR(lame, vbr_abr);//vbr_default 
lame_init_params(lame); 

//Samples count (do not have any effect on output) 
dwSamples=1024; 

//mp3 buffer size, if it do not equals dwSamples*2 than output sound getting scaled 
dwMP3Buffer=dwSamples*2; 

pMP3Buffer = new BYTE[dwMP3Buffer]; 

書寫PCM數據

int Mp3Stream :: Write(short * _data, int _size) 
{ 
    if (_size > 0) 
    { 
     for(int curPos = 0; curPos < _size; curPos += dwMP3Buffer) 
     { 
      //int size = dwMP3Buffer; 

      //if (_size - curPos < dwMP3Buffer) 
      // size = _size - curPos; 

      int bytes = lame_encode_buffer(lame, (short *)((char *)_data + curPos), (short *)((char *)_data + curPos), dwSamples, pMP3Buffer, 0); 

      IPF_TRACE(1, "MP3 encoder wrote "<<bytes<<" bytes"); 

      if (bytes<0) 
      { 
       IPF_TRACE(1, "MP3 encoding failed with code "<<bytes); 
       return bytes; 
      } 

      BOOL bResult = WriteFile(hFile, pMP3Buffer, bytes, &bw, NULL); 

      if (!bResult || bytes != bw) 
      { 
       IPF_TRACE(1, "MP3 write to file failed with code "<<bytes); 
      } 
     }; 
    } 
} 

敲定

int bytes = lame_encode_flush(lame, pMP3Buffer, 0); 
    if (bytes<0) 
{ 
    IPF_TRACE(1, "MP3 flush failed with code "<<bytes); 
} 
BOOL bResult = WriteFile(hFile, pMP3Buffer, bytes, &bw, NULL); 
if (!bResult || bytes != bw) 
{ 
    IPF_TRACE(1, "MP3 write to file failed with code "<<bytes); 
} 
int ret = lame_close(lame); 
if (ret < 0) 
{ 
    IPF_TRACE(1, "MP3 lame close failed with code "<<ret); 
} 
delete []pMP3Buffer; 
+0

我有同樣的問題和解決方案在這裏:http://stackoverflow.com/questions/13277042/clicks-while -using-lame-to-encode-from-pcm-to-mp3-in-ios – Jeff 2016-01-27 22:49:45

回答

1

聲音 - >點擊 - >聲音 - >點擊模式很可能意味着您一次只寫入緩衝區的一半,另一半對於Write調用中的每個循環都保持爲零。

原因是您的循環增量器基於dwSamples * 2的dwMP3Buffer值。

for(int curPos = 0; curPos < _size; curPos += dwMP3Buffer){ 

這意味着你實際上並沒有編碼所有的輸入值,因爲dwMP3Buffer是你的兩倍實際上傳遞給lame_encode_buffer調用(dwSamples)的樣本數量。

lame_encode_buffer(lame, (short *)((char *)_data + curPos), 
        (short *)((char *)_data + curPos), dwSamples, pMP3Buffer, 0); 

嘗試改變環路增量爲以下內容:

for(int curPos = 0; curPos < _size; curPos += dwSamples){ 
+0

當使用Windows ACM將WAV編碼爲MP3時,我們曾經遇到類似的問題 - 它沒有處理整個輸入緩衝區,而我們丟棄了調用之間的剩餘字節。 – 2012-04-27 06:46:01

0

我會嘗試設置

dwSamples = 1152 

1152 - 是音頻幀大小(樣本)爲MPEG1Audio編碼器。它通過幀多塊

1

試試這個樣子LAME處理數據,

void AQRecorder::MyInputBufferHandler( void *        inUserData, 
           AudioQueueRef      inAQ, 
           AudioQueueBufferRef     inBuffer, 
           const AudioTimeStamp *    inStartTime, 
           UInt32        inNumPackets, 
           const AudioStreamPacketDescription* inPacketDesc) 
{ 
AQRecorder *aqr = (AQRecorder *)inUserData; 
// NSLog(@"%f",inStartTime->mSampleTime); 
try 
{ 
    if (inNumPackets > 0) 
    { 
     AudioFileWritePackets(aqr->mRecordFile, FALSE, inBuffer->mAudioDataByteSize, inPacketDesc, aqr->mRecordPacket, &inNumPackets, inBuffer->mAudioData); 

     aqr->mRecordPacket += inNumPackets; 

     int MP3_SIZE =inBuffer->mAudioDataByteSize * 4; 
     unsigned char mp3_buffer[MP3_SIZE]; 
     AppDelegate *delegate =[[UIApplication sharedApplication]delegate]; 
     lame_t lame = lame_init(); 
     lame_set_in_samplerate(lame, 44100); 
     lame_set_VBR(lame, vbr_default); 
     lame_init_params(lame); 

    //    int encodedBytes=lame_encode_buffer_interleaved(lame, (short int *)inBuffer->mAudioData , inNumPackets, mp3_buffer, MP3_SIZE); 


     int encodedBytes = lame_encode_buffer(lame, (short*)inBuffer->mAudioData, (short*)inBuffer->mAudioData, inNumPackets, mp3_buffer, MP3_SIZE); 

     [delegate.mp3AudioData appendBytes:mp3_buffer length:encodedBytes]; 

     if (inBuffer->mAudioDataByteSize != 0) { 
     } 
     else 
     { 
      int encode=lame_encode_flush(lame, mp3_buffer, MP3_SIZE); 
      [delegate.mp3AudioData appendBytes:mp3_buffer length:encode]; 
     } 
     lame_close(lame); 
    } 

    if (aqr->IsRunning()) 
    { 
     AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL); 
    } 
} catch (CAXException e) 
{ 
char buf[256]; 
fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf)); 
} 
}