Reputation: 11
My app using LAME to encode raw pcm data to mp3. But i have a problem - output mp3 contains "clicks" in persistent period of time. Something like that:
sound... "click" sound.. "click" sound.. "click" etc...
I have tried different versions of LAME and tried change many LAME settings but not succeed. My app also can convert pcm to wav and ogg, but this converters do not results that "clicks".
There is a encoding code (pcm input contains one channel data, pcm already resampled to 44100 freq):
Initialization:
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];
Writing pcm data
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);
}
};
}
}
Finalizing
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;
Upvotes: 1
Views: 5376
Reputation: 5384
Try this,
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));
}
}
Upvotes: 1
Reputation: 98
I would try to set
dwSamples = 1152
1152 - is the audio frame size (in samples) for MPEG1Audio encoder. It looks like LAME processes data by frame-multiple chunks
Upvotes: 0
Reputation: 3363
The Sound -> Click -> Sound -> Click pattern most likely means you are only writing half of your buffer at a time and the other half is remaining zero'd out for each loop inside the Write call.
The reason for this is that your loop incrementer is based on the dwMP3Buffer value of dwSamples*2.
for(int curPos = 0; curPos < _size; curPos += dwMP3Buffer){
This means you aren't actually encoding all of your input values since dwMP3Buffer is twice the number of samples you actually pass to the lame_encode_buffer call (dwSamples).
lame_encode_buffer(lame, (short *)((char *)_data + curPos),
(short *)((char *)_data + curPos), dwSamples, pMP3Buffer, 0);
Try changing the loop incrementer to the following:
for(int curPos = 0; curPos < _size; curPos += dwSamples){
Upvotes: 1