iOS 開發 音頻格式轉換(pcm -> mp3)

WJUploadVoiceInfoObject
  • voiceLocalPcmPath (pcm格式文件路徑)
  • oiceLocalMp3Path (mp3文件路徑)
+ (void)convertPCMToMp3:(id<WJUploadVoiceInfoObject>)infoObject
                success:(void(^)(NSString *mp3Path))success
                failure:(void(^)(NSError *error))failure {
    
    NSString *mp3FilePath = infoObject.voiceLocalMp3Path;
    NSString *pcmFilePath = infoObject.voiceLocalPcmPath;
    @try {
        int read,write;
        // 只讀方式打開被轉換音頻文件
        FILE *pcm = fopen([pcmFilePath cStringUsingEncoding:1], "rb");
        
        if (!pcm) {
            return;
        }
        
        // 刪除頭,否則在前一秒鐘會有雜音
        fseek(pcm, 4 * 1024, SEEK_CUR);
        // 只寫方式打開生成的MP3文件
        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的配置要跟AVAudioRecorder的配置一致,否則會造成轉換不成功
        lame_t lame = lame_init();
        // 採樣率需要和百度語音一致(百度16k,mp3一般是雙聲道的,設置8k)
        lame_set_in_samplerate(lame, 8000.0);
        
        lame_set_VBR(lame, vbr_default);
        lame_init_params(lame);
        
        do {
            //以二進制形式讀取文件中的數據
            read = (int)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);
            }
            
            /*
             * 二進制形式寫數據到文件中
             *
             * mp3_buffer:數據輸出到文件的緩衝區首地址
             * write:一個數據塊的字節數
             * 1:指定一次輸出數據塊的個數
             * mp3:文件指針
             */
            fwrite(mp3_buffer, write, 1, mp3);
        } while (read != 0);
        
        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
    } @catch (NSException *exception) {
        WJLog(@"%@", [exception description]);
        if (failure) {
            failure(nil);
        }
    } @finally {
        WJLog(@"PCM轉換MP3轉換成功");
        if (success) {
            success(mp3FilePath);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章