IPhone Extended Audio File Services, mp3 & # 8594; PCM & # 8594; mp3

I would like to use the Core Audio extended audio file infrastructure to read an mp3 file, treat it as PCM, and then write the modified file as an mp3 file. I can convert the mp3 file to PCM, but CANNOT write the PCM file back to mp3.

I followed and analyzed the Apple ExtAudioFileConvertTest sample, and also could not get it to work. The point of failure is when I set the client format for the output file (set to the canonical type PCM). This is not with the error "fmt?" if the target output type is set to mp3.

Is it possible to make mp3 β†’ PCM β†’ mp3 on iPhone? If I delete the error line by setting kExtAudioFileProperty_ClientDataFormat for the output file, the code is not with "pkd?" when I try to write to the output file later. So basically I have 2 errors:

1) "fmt?" when trying to set kExtAudioFileProperty_ClientDataFormat for the output file

2) "pkd?" when trying to write to the output file

Here is the code to configure the files:

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

And the code for reading / writing:

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;
}
+3
source share

Source: https://habr.com/ru/post/1771434/


All Articles