2012-04-27 92 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)); 
} 
}