neowinston
neowinston

Reputation: 7764

How to show a progress bar while encoding to .mp3, using LAME on the iPhone?

I'm using LAME to encode a .caf audio file to .mp3 on my iPhone app.

All works perfectly and I'm just having a difficult time trying to figure out how to log the progress of the audio file conversion to .mp3, to simultaneously show the progress to the user with an UIProgressView.

I'm using this code (a little bit modified from the original written by Deepak Soni (available here):

NSArray *dirPaths;
NSString *docsDir;

dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
_mp3FilePath = [docsDir stringByAppendingPathComponent:@"file.mp3"];

NSString* cafFile = [[NSBundle mainBundle] pathForResource:@"background" ofType:@"caf"];
char cstr[512] = {0};
[cafFile getCString:cstr maxLength:512 encoding:NSASCIIStringEncoding];


@try {
    int read, write;
    FILE *pcm = fopen([cafFile cStringUsingEncoding:1], "rb");
    FILE *mp3 = fopen([_mp3FilePath cStringUsingEncoding:1], "wb");
    const int PCM_SIZE = 8192;
    const int MP3_SIZE = 8192;
    short int pcm_buffer[PCM_SIZE*2];
    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);

    NSFileManager *fileManger = [NSFileManager defaultManager];
    NSData *data = [fileManger contentsAtPath:cafFile];
    NSString* str = [NSString stringWithFormat:@"%d K",[data length]/1024];
    NSLog(@"size of caf=%@",str);

    printf("Using LAME v%s\n", get_lame_version());

    do {
        read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
        if (read == 0)
            write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
        else
            write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);

        fwrite(mp3_buffer, write, 1, mp3);

    } while (read != 0);

    lame_close(lame);
    fclose(mp3);
    fclose(pcm);
}
@catch (NSException *exception) {
    NSLog(@"%@",[exception description]);
}
@finally {
    //Detrming the size of mp3 file
    NSFileManager *fileManger = [NSFileManager defaultManager];
    NSData *data = [fileManger contentsAtPath:_mp3FilePath];
    NSString* str = [NSString stringWithFormat:@"%d K",[data length]/1024];
    NSLog(@"size of mp3=%@",str);
}

Upvotes: 1

Views: 810

Answers (1)

neowinston
neowinston

Reputation: 7764

I had to use lame_set_num_samples , and only then lame_get_num_samples would work properly, like so:

    int sampleRate = 44100;
    int bitsPerSample = 16;
    int numberOfChannels = 2;

    lame_t lame = lame_init();
    lame_set_in_samplerate(lame, 44100);
    lame_set_VBR(lame, vbr_default);
    lame_init_params(lame);

    NSString* cafFile = [[NSBundle mainBundle] pathForResource:@"background" ofType:@"caf"];
    char cstr[512] = {0};
    [cafFile getCString:cstr maxLength:512 encoding:NSASCIIStringEncoding];

    int fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:cafFile error:nil] fileSize];
    int duration = (fileSize * 8) / (sampleRate * bitsPerSample * numberOfChannels);

    lame_set_num_samples(lame, (duration * sampleRate));
    lame_get_num_samples(lame);

    int percent     = 0;
    int samp_rate   = lame_get_out_samplerate(lame);
    int frameNum    = lame_get_frameNum(lame);
    int totalframes = lame_get_totalframes(lame);

    if (frameNum < totalframes) {
            percent = (int) (100. * frameNum / totalframes + 0.5);
        }
        else {
            percent = 100;
        }

    float progress = (float) percent/100;

    dispatch_async(dispatch_get_main_queue(), ^{

           self.percentageLabel.text = [NSString stringWithFormat:@"%d%%",percent];
           self.progressBar.progress =  progress;

        });

Upvotes: 2

Related Questions