Question

I am not the first to have this type of issue, however, I have no been able to solve it.

I am encoding a LinearPCM to MP3 in iOS. It is working though I am experiencing clicks between each buffer.

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];

Then, I do the following with the buffer:

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

I have tried adding the following line after calling lame_encode_buffer:

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

However, this will cause a blip also (I guess it input some 0's at the end of a frame). Trying that made me realize that I am not encoding some of the last audio packets of the inBuffer->mAudioData and that may be causing the click. However, I am not sure how to compute how many of those are left (if I knew, I could simply save these packets in a "left-over" buffer that is prepended to the incoming next buffer).

Here is a bit more information on my settings:

I have the following 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;
 }

and I setup lame this way:

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);
Was it helpful?

Solution

I previously called lame_init() each time I encoded a buffer.

Once I moved that setup code out to be called only once the issue was fixed.

I guess what is happening is that mp3 must encode at least 1152 frames at a time, and the lame_t encoder keeps track of data that was not encoded at the last call. So lame_encode_buffer can start where we left off.

lame_encode_flush should only be used at the very end of a file (or the last few frames would get chopped off, unless the number of frames was an exact multiple of 1152--unlikely).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top