iPhone扩展音频文件服务,mp3 - > PCM - > mp3

问题描述:

我想使用Core Audio扩展音频文件服务框架来读取mp3文件,将其作为PCM处理,然后将修改后的文件写回mp3文件。我能够将mp3文件转换为PCM,但不能将PCM文件作为mp3文件。iPhone扩展音频文件服务,mp3 - > PCM - > mp3

我遵循并分析了Apple ExtAudioFileConvertTest示例,也无法使其工作。失败点是当我为输出文件设置客户端格式(设置为规范PCM类型)时。这会导致错误“fmt?”失败如果输出目标类型设置为mp3。

是否可以在iPhone上做mp3 - > PCM - > mp3?如果我删除失败的行,为输出文件设置kExtAudioFileProperty_ClientDataFormat,代码将失败,并显示“pkd?”。当我尝试稍后写入输出文件时。所以基本上我有2个错误:

1)“fmt?”当试图设置输出文件的kExtAudioFileProperty_ClientDataFormat

2)“pkd?”尝试写入到输出文件

这里的时候是成立的文件中的代码:

NSURL *fileUrl = [NSURL fileURLWithPath:sourceFilePath]; 
OSStatus error = noErr; 

// 
// Open the file 
// 
error = ExtAudioFileOpenURL((CFURLRef)fileUrl, &sourceFile); 

if(error){ 
    NSLog(@"AudioClip: Error opening file at %@. Error code %d", sourceFilePath, error); 
    return NO; 
} 

// 
// Store the number of frames in the file 
// 
SInt64 numberOfFrames = 0; 
UInt32 propSize = sizeof(SInt64); 
error = ExtAudioFileGetProperty(sourceFile, kExtAudioFileProperty_FileLengthFrames, &propSize, &numberOfFrames); 

if(error){ 
    NSLog(@"AudioClip: Error retreiving number of frames: %d", error); 
    [self closeAudioFile]; 
    return NO; 
} 

frameCount = numberOfFrames; 

// 
// Get the source file format info 
// 
propSize = sizeof(sourceFileFormat); 
memset(&sourceFileFormat, 0, sizeof(AudioStreamBasicDescription)); 

error = ExtAudioFileGetProperty(sourceFile, kExtAudioFileProperty_FileDataFormat, &propSize, &sourceFileFormat); 

if(error){ 
    NSLog(@"AudioClip: Error getting source audio file properties: %d", error); 
    [self closeAudioFile]; 
    return NO; 
} 

// 
// Set the format for our read. We read in PCM, clip, then write out mp3 
// 
memset(&readFileFormat, 0, sizeof(AudioStreamBasicDescription)); 

readFileFormat.mFormatID   = kAudioFormatLinearPCM; 
readFileFormat.mSampleRate   = 44100; 
readFileFormat.mFormatFlags   = kAudioFormatFlagsCanonical | kAudioFormatFlagIsNonInterleaved; 
readFileFormat.mChannelsPerFrame = 1; 
readFileFormat.mBitsPerChannel  = 8 * sizeof(AudioSampleType); 
readFileFormat.mFramesPerPacket  = 1; 
readFileFormat.mBytesPerFrame  = sizeof(AudioSampleType); 
readFileFormat.mBytesPerPacket  = sizeof(AudioSampleType); 
readFileFormat.mReserved   = 0; 

propSize = sizeof(readFileFormat); 
error = ExtAudioFileSetProperty(sourceFile, kExtAudioFileProperty_ClientDataFormat, propSize, &readFileFormat); 

if(error){ 
    NSLog(@"AudioClip: Error setting read format: %d", error); 
    [self closeAudioFile]; 
    return NO; 
} 

// 
// Set the format for the output file that we will write 
// 
propSize = sizeof(targetFileFormat); 
memset(&targetFileFormat, 0, sizeof(AudioStreamBasicDescription)); 

targetFileFormat.mFormatID   = kAudioFormatMPEGLayer3; 
targetFileFormat.mChannelsPerFrame = 1; 

// 
// Let the API fill in the rest 
// 
error = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &propSize, &targetFileFormat); 

if(error){ 
    NSLog(@"AudioClip: Error getting target file format info: %d", error); 
    [self closeAudioFile]; 
    return NO; 
} 

// 
// Create our target file 
// 
NSURL *writeURL = [NSURL fileURLWithPath:targetFilePath]; 

error = ExtAudioFileCreateWithURL((CFURLRef)writeURL, kAudioFileMP3Type, 
            &targetFileFormat, NULL, 
            kAudioFileFlags_EraseFile, 
            &targetFile); 

if(error){ 
    NSLog(@"AudioClip: Error opening target file for writing: %d", error); 
    [self closeAudioFile]; 
    return NO; 
} 


// 
// Set the client format for the output file the same as our client format for the input file 
// 
propSize = sizeof(readFileFormat); 
error = ExtAudioFileSetProperty(targetFile, kExtAudioFileProperty_ClientDataFormat, propSize, &readFileFormat); 

if(error){ 
    NSLog(@"AudioClip: Error, cannot set client format for output file: %d", error); 
    [self closeAudioFile]; 
    return NO; 
} 

和代码读/写:

NSInteger framesToRead = finalFrameNumber - startFrameNumber; 

while(framesToRead > 0){ 
    // 
    // Read frames into our data 
    // 
    short *data = (short *)malloc(framesToRead * sizeof(short)); 
    if(!data){ 
     NSLog(@"AudioPlayer: Cannot init memory for read buffer"); 
     [self notifyDelegateFailure]; 
     [self closeAudioFile]; 
     return; 
    } 

    AudioBufferList bufferList; 
    OSStatus error = noErr; 
    UInt32 loadedPackets = framesToRead; 

    bufferList.mNumberBuffers = 1; 
    bufferList.mBuffers[0].mNumberChannels = 1; 
    bufferList.mBuffers[0].mData = data; 
    bufferList.mBuffers[0].mDataByteSize = (framesToRead * sizeof(short)); 

    NSLog(@"AudioClip: Before read nNumberBuffers = %d, mNumberChannels = %d, mData = %p, mDataByteSize = %d", 
      bufferList.mNumberBuffers, bufferList.mBuffers[0].mNumberChannels, bufferList.mBuffers[0].mData, 
      bufferList.mBuffers[0].mDataByteSize); 

    error = ExtAudioFileRead(sourceFile, &loadedPackets, &bufferList); 

    if(error){ 
     NSLog(@"AudioClip: Error %d from ExtAudioFileRead", error); 
     [self notifyDelegateFailure]; 
     [self closeAudioFile]; 
     return; 
    } 

    // 
    // Now write the data to our file which will convert it into a mp3 file 
    // 

    NSLog(@"AudioClip: After read nNumberBuffers = %d, mNumberChannels = %d, mData = %p, mDataByteSize = %d", 
      bufferList.mNumberBuffers, bufferList.mBuffers[0].mNumberChannels, bufferList.mBuffers[0].mData, 
      bufferList.mBuffers[0].mDataByteSize); 

    error = ExtAudioFileWrite(targetFile, loadedPackets, &bufferList); 

    if(error){ 
     NSLog(@"AudioClip: Error %d from ExtAudioFileWrite", error); 
     [self notifyDelegateFailure]; 
     [self closeAudioFile]; 
     return; 
    } 

    framesToRead -= loadedPackets; 
} 

苹果并没有提供一个MP3编码器 - 只有一个解码器。源文件有点过时,但AFAIK它仍然是最新的:http://developer.apple.com/library/ios/#documentation/MusicAudio/Conceptual/CoreAudioOverview/SupportedAudioFormatsMacOSX/SupportedAudioFormatsMacOSX.html%23//apple_ref/doc/uid/TP40003577-CH7-SW1

我认为你最好的选择可能是使用AAC。