在iOS中使用LAME从PCM编码到MP3时单击

时间:2012-11-07 19:46:39

标签: ios audio mp3 pcm lame

我不是第一个遇到此类问题的人,但是,我无法解决这个问题。

我在iOS中将LinearPCM编码为MP3。虽然我在每个缓冲区之间遇到点击,但它正在工作。

memset(&mEncodedBuffer, 0, sizeof(mEncodedBuffer));

int encodedBytes = lame_encode_buffer(gfp, (short*)inBuffer->mAudioData,  NULL, inNumberPacketDescriptions, mEncodedBuffer, MP3_BUFFER_SIZE);

NSData* data = [NSData dataWithBytes:mEncodedBuffer length:encodedBytes];

然后,我使用缓冲区执行以下操作:

AudioQueueEnqueueBuffer(vc.recordState.queue, inBuffer, 0, NULL);

我在调用lame_encode_buffer之后尝试添加以下行:

encodedBytes += lame_encode_flush(gfp, mEncodedBuffer+encodedBytes, 0);

然而,这也会导致一个短暂的(我猜它在帧的末尾输入了一些0)。尝试这让我意识到我没有编码inBuffer-> mAudioData的最后一些音频数据包,这可能导致点击。但是,我不知道如何计算剩下多少个(如果我知道的话,我可以简单地将这些数据包保存在传入下一个缓冲区前面的“剩余”缓冲区中)。

以下是有关我的设置的更多信息:

我有以下inputFormat:

- (void)setupSourceAudioFormat:(AudioStreamBasicDescription*)format
 {
     format->mFormatID = kAudioFormatLinearPCM;

     format->mSampleRate = 44100;
     format->mFramesPerPacket = 1;
     format->mChannelsPerFrame = 1;
     format->mBytesPerFrame = 2;
     format->mBytesPerPacket = 2;
     format->mBitsPerChannel = 16;
     format->mReserved = 0;
     format->mFormatFlags = kLinearPCMFormatFlagIsBigEndian |
         kLinearPCMFormatFlagIsSignedInteger |
         kLinearPCMFormatFlagIsPacked;
 }

我这样设置了跛脚:

lame_t gfp = lame_init();
lame_set_num_channels(gfp, 1);
lame_set_in_samplerate(gfp, 44100);
lame_set_mode(gfp, MONO);
lame_set_brate(gfp, 64);
lame_init_params(gfp);

1 个答案:

答案 0 :(得分:3)

我每次编码缓冲区时都会调用lame_init()。

一旦我将该设置代码移出,只有在问题得到修复后才会被调用。

我想正在发生的事情是mp3必须一次编码至少1152帧,而lame_t编码器会跟踪上次调用时未编码的数据。所以lame_encode_buffer可以从我们离开的地方开始。

lame_encode_flush只应该在文件的最末端使用(或者最后几帧会被切断,除非帧的数量是1152的精确倍数 - 不太可能)。