Search code examples
iphoneiosmp3pcmlame

Convert audio Linear pcm to mp3 ( using LAME ) Low ,Medium,High audio Quality setting


I am encoding a LinearPCM to MP3 in iOS.I'm trying to encode the raw PCM data from microphone to MP3 using AudioToolbox framework and Lame.And although everything seems to run fine if i record an audio it is converted to mp3 with the help of lame encoding concept while play the recorded mp3 audio file working fine.now i want to convert audio(using lame) like low,medium,high quality mp3 file. i don't know exact setting(sample rate,bit depth,bit rate, chennal,quality) while lame conversion process

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

Solution

  • Try this,

    Low quality:

    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
            NSMutableDictionary *dictAudioQuality =[[NSMutableDictionary alloc]init];
            [dictAudioQuality setValue:@"Low" forKey:@"audioquality"];
            [dictAudioQuality setValue:@"11025" forKey:@"samplerate"];
            [dictAudioQuality setValue:@"16" forKey:@"bitdepth"];
            [dictAudioQuality setValue:@"120" forKey:@"bitrate"];
            [dictAudioQuality setValue:@"1" forKey:@"channel"];
    

    Medium Quality:

     AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
            NSMutableDictionary *dictAudioQuality =[[NSMutableDictionary alloc]init];
            [dictAudioQuality setValue:@"Medium" forKey:@"audioquality"];
            [dictAudioQuality setValue:@"22050" forKey:@"samplerate"];
            [dictAudioQuality setValue:@"16" forKey:@"bitdepth"];
            [dictAudioQuality setValue:@"240" forKey:@"bitrate"];
            [dictAudioQuality setValue:@"1" forKey:@"channel"];
    

    High Quality:

    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
            NSMutableDictionary *dictAudioQuality =[[NSMutableDictionary alloc]init];
            [dictAudioQuality setValue:@"High" forKey:@"audioquality"];
            [dictAudioQuality setValue:@"44100" forKey:@"samplerate"];
            [dictAudioQuality setValue:@"24" forKey:@"bitdepth"];
            [dictAudioQuality setValue:@"320" forKey:@"bitrate"];
            [dictAudioQuality setValue:@"2" forKey:@"channel"];
    

    AQRecorder.m Start Record

    void AQRecorder::StartRecord(CFStringRef inRecordFile)
    {
    int i, bufferByteSize;
    UInt32 size;
    
    delegate =[[UIApplication sharedApplication]delegate];
    nSampleRate =[[delegate.dictMP3Quality valueForKey:@"samplerate"] intValue];
    nBitRate =[[delegate.dictMP3Quality valueForKey:@"bitrate"] intValue];
    nChannel =[[delegate.dictMP3Quality valueForKey:@"channel"] intValue];
    
    try {
    
        UInt32 category = kAudioSessionCategory_RecordAudio;
    
        OSStatus error = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);
        if (error) printf("couldn't set audio category!");
    
        // specify the recording format
        SetupAudioFormat(kAudioFormatLinearPCM);
    
        // create the queue
        XThrowIfError(AudioQueueNewInput(
                                         &mRecordFormat,
                                         MyInputBufferHandler,
                                         this /* userData */,
                                         NULL /* run loop */, NULL /* run loop mode */,
                                         0 /* flags */, &mQueue), "AudioQueueNewInput failed");
    
        // get the record format back from the queue's audio converter --
        // the file may require a more specific stream description than was necessary to create the encoder.
        mRecordPacket = 0;
    
        size = sizeof(mRecordFormat);
        XThrowIfError(AudioQueueGetProperty(mQueue, kAudioQueueProperty_StreamDescription,
                                            &mRecordFormat, &size), "couldn't get queue's format");
    
        // copy the cookie first to give the file object as much info as we can about the data going in
        // not necessary for pcm, but required for some compressed audio
        CopyEncoderCookieToFile();
    
        // allocate and enqueue buffers
        bufferByteSize = ComputeRecordBufferSize(&mRecordFormat, kBufferDurationSeconds);   // enough bytes for half a second
        for (i = 0; i < kNumberRecordBuffers; ++i) {
            XThrowIfError(AudioQueueAllocateBuffer(mQueue, bufferByteSize, &mBuffers[i]),
                          "AudioQueueAllocateBuffer failed");
            XThrowIfError(AudioQueueEnqueueBuffer(mQueue, mBuffers[i], 0, NULL),
                          "AudioQueueEnqueueBuffer failed");
        }
        // start the queue
        mIsRunning = true;
        XThrowIfError(AudioQueueStart(mQueue, NULL), "AudioQueueStart failed");
    
        lame = lame_init();
        lame_set_in_samplerate(lame, mRecordFormat.mSampleRate);
        lame_set_out_samplerate(lame, nSampleRate);
        lame_set_num_channels(lame, nChannel);
        //  lame_set_brate(lame, nBitRate);
        lame_set_VBR(lame, vbr_default);
        lame_init_params(lame);
    }
    catch (CAXException e) {
        char buf[256];
        fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
    }
    catch (...) {
        fprintf(stderr, "An unknown error occurred\n");;
    }
    }
    

    AQRecorder::MyInputBufferHandler

    void AQRecorder::MyInputBufferHandler(  void *                              inUserData,
                                      AudioQueueRef                     inAQ,
                                      AudioQueueBufferRef                   inBuffer,
                                      const AudioTimeStamp *                inStartTime,
                                      UInt32                                inNumPackets,
                                      const AudioStreamPacketDescription*   inPacketDesc)
    {
    AQRecorder *aqr = (AQRecorder *)inUserData;
    try
    {
    
        if (inNumPackets > 0)
        {
            AudioFileWritePackets(aqr->mRecordFile, FALSE, inBuffer->mAudioDataByteSize, inPacketDesc, aqr->mRecordPacket, &inNumPackets, inBuffer->mAudioData);
    
            aqr->mRecordPacket += inNumPackets;
    
            int MP3_SIZE =inNumPackets * 4;
            unsigned char mp3_buffer[MP3_SIZE];
    
            memset(mp3_buffer, 0, sizeof(mp3_buffer));
        //  int encodedBytes=lame_encode_buffer_interleaved(lame, (short int*)inBuffer->mAudioData , inNumPackets, mp3_buffer, MP3_SIZE);
    
            int encodedBytes = lame_encode_buffer(aqr->lame, (short int*)inBuffer->mAudioData,  (short int*)inBuffer->mAudioData, inNumPackets, mp3_buffer, MP3_SIZE);
    
            [aqr->delegate.mp3AudioData appendBytes:mp3_buffer length:encodedBytes];
    
            if (inBuffer->mAudioDataByteSize != 0) {
            }
            else
            {
                int encode=lame_encode_flush(aqr->lame, mp3_buffer, MP3_SIZE);
                [aqr->delegate.mp3AudioData appendBytes:mp3_buffer length:encode];
            }
    
            {
                NSLog(@"------------");
                NSLog(@"%d",encodedBytes);
                NSLog(@"%lu",inNumPackets);
                NSLog(@"%d",MP3_SIZE);
                NSLog(@"------------");
            }
        }
    
        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));
    }
    }