i am developing an audio player. I successfully get other information of the mp3 file. but is unable to get the album art of the mp3 file. using this code i get the mp3 file info.
- (NSDictionary *)songID3Tags
{
AudioFileID fileID = nil;
OSStatus error = noErr;
error = AudioFileOpenURL((CFURLRef)self.filePath, kAudioFileReadPermission, 0, &fileID);
if (error != noErr) {
NSLog(#"AudioFileOpenURL failed");
}
UInt32 id3DataSize = 0;
char *rawID3Tag = NULL;
error = AudioFileGetPropertyInfo(fileID, kAudioFilePropertyID3Tag, &id3DataSize, NULL);
if (error != noErr)
NSLog(#"AudioFileGetPropertyInfo failed for ID3 tag");
rawID3Tag = (char *)malloc(id3DataSize);
if (rawID3Tag == NULL)
NSLog(#"could not allocate %lu bytes of memory for ID3 tag", id3DataSize);
error = AudioFileGetProperty(fileID, kAudioFilePropertyID3Tag, &id3DataSize, rawID3Tag);
if( error != noErr )
NSLog(#"AudioFileGetPropertyID3Tag failed");
UInt32 id3TagSize = 0;
UInt32 id3TagSizeLength = 0;
error = AudioFormatGetProperty(kAudioFormatProperty_ID3TagSize, id3DataSize, rawID3Tag, &id3TagSizeLength, &id3TagSize);
if (error != noErr) {
NSLog( #"AudioFormatGetProperty_ID3TagSize failed" );
switch(error) {
case kAudioFormatUnspecifiedError:
NSLog( #"Error: audio format unspecified error" );
break;
case kAudioFormatUnsupportedPropertyError:
NSLog( #"Error: audio format unsupported property error" );
break;
case kAudioFormatBadPropertySizeError:
NSLog( #"Error: audio format bad property size error" );
break;
case kAudioFormatBadSpecifierSizeError:
NSLog( #"Error: audio format bad specifier size error" );
break;
case kAudioFormatUnsupportedDataFormatError:
NSLog( #"Error: audio format unsupported data format error" );
break;
case kAudioFormatUnknownFormatError:
NSLog( #"Error: audio format unknown format error" );
break;
default:
NSLog( #"Error: unknown audio format error" );
break;
}
}
CFDictionaryRef piDict = nil;
UInt32 piDataSize = sizeof(piDict);
error = AudioFileGetProperty(fileID, kAudioFilePropertyInfoDictionary, &piDataSize, &piDict);
if (error != noErr)
NSLog(#"AudioFileGetProperty failed for property info dictionary");
free(rawID3Tag);
return (NSDictionary*)piDict;
}
I know through kAudioFilePropertyAlbumArtwork i can get the album art of the mp3 file, but I do not know how to get it.
- (NSArray *)artworksForFileAtPath:(NSString *)path {
NSMutableArray *artworkImages = [NSMutableArray array];
NSURL *u = [NSURL fileURLWithPath:path];
AVURLAsset *a = [AVURLAsset URLAssetWithURL:u options:nil];
NSArray *artworks = [AVMetadataItem metadataItemsFromArray:a.commonMetadata withKey:AVMetadataCommonKeyArtwork keySpace:AVMetadataKeySpaceCommon];
for (AVMetadataItem *i in artworks)
{
NSString *keySpace = i.keySpace;
UIImage *im = nil;
if ([keySpace isEqualToString:AVMetadataKeySpaceID3])
{
NSDictionary *d = [i.value copyWithZone:nil];
im = [UIImage imageWithData:[d objectForKey:#"data"]];
}
else if ([keySpace isEqualToString:AVMetadataKeySpaceiTunes])
im = [UIImage imageWithData:[i.value copyWithZone:nil]];
if (im)
[artworkImages addObject:im];
}
NSLog(#"array description is %#", [artworkImages description]);
return artworkImages; }
The Above code return the album_art of the mp3 file. Where path is the audio file path.
Related
I am using the YouTube API in UIWebView.
I have created a NSString with the HTML5 player that I load in the UIWebView. Everything works perfectly on iPhone 5 and iPad.
But, if I test the app using an iPhone 4, the player returns the buffering state all the time. Only if I explicitly press the play button, the player starts playing, without stopping again for buffering. It seems that although the video has been buffered, the player still gives me this state.
Is anyone aware of this problem? Any idea?
Thank you very much in advance!!
In LBYouTubePlayerViewController.m file
Replace Following method on yr old Method....
then test...
-(NSURL*)_extractYouTubeURLFromFile:(NSString *)html error:(NSError *__autoreleasing *)error {
NSString *JSONStart = nil;
// NSString *JSONStartFull = #"ls.setItem('PIGGYBACK_DATA', \")]}'";
NSString *JSONStartFull = #"bootstrap_data = \")]}'";
NSString *JSONStartShrunk = [JSONStartFull stringByReplacingOccurrencesOfString:#" " withString:#""];
if ([html rangeOfString:JSONStartFull].location != NSNotFound)
JSONStart = JSONStartFull;
else if ([html rangeOfString:JSONStartShrunk].location != NSNotFound)
JSONStart = JSONStartShrunk;
if (JSONStart != nil) {
NSScanner* scanner = [NSScanner scannerWithString:html];
[scanner scanUpToString:JSONStart intoString:nil];
[scanner scanString:JSONStart intoString:nil];
NSString *JSON = nil;
[scanner scanUpToString:#"}\";" intoString:&JSON];
JSON = [NSString stringWithFormat:#"%#}",JSON]; // Add closing bracket } to get vallid JSON again
// [scanner scanUpToString:#"\");" intoString:&JSON];
JSON = [self _unescapeString:JSON];
NSError* decodingError = nil;
NSDictionary* JSONCode = nil;
// First try to invoke NSJSONSerialization (Thanks Mattt Thompson)
id NSJSONSerializationClass = NSClassFromString(#"NSJSONSerialization");
SEL NSJSONSerializationSelector = NSSelectorFromString(#"dataWithJSONObject:options:error:");
if (NSJSONSerializationClass && [NSJSONSerializationClass respondsToSelector:NSJSONSerializationSelector]) {
JSONCode = [NSJSONSerialization JSONObjectWithData:[JSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&decodingError];
}
else {
JSONCode = [JSON objectFromJSONStringWithParseOptions:JKParseOptionNone error:&decodingError];
}
if (decodingError) {
// Failed
*error = decodingError;
}
else {
// Success
NSDictionary *dict = [JSONCode objectForKey:#"content"];
NSDictionary *dictTemp = [dict objectForKey:#"video"];
NSArray* videos = [dictTemp objectForKey:#"fmt_stream_map"];
NSString* streamURL = nil;
if (videos.count) {
NSString* streamURLKey = #"url";
if (self.quality == LBYouTubePlayerQualityLarge) {
streamURL = [[videos objectAtIndex:0] objectForKey:streamURLKey];
}
else if (self.quality == LBYouTubePlayerQualityMedium) {
unsigned int index = MAX(0, videos.count-2);
streamURL = [[videos objectAtIndex:index] objectForKey:streamURLKey];
}
else {
streamURL = [[videos lastObject] objectForKey:streamURLKey];
}
}
if (streamURL) {
return [NSURL URLWithString:streamURL];
}
else {
*error = [NSError errorWithDomain:kLBYouTubePlayerControllerErrorDomain code:2 userInfo:[NSDictionary dictionaryWithObject:#"Couldn't find the stream URL." forKey:NSLocalizedDescriptionKey]];
}
}
}
else {
*error = [NSError errorWithDomain:kLBYouTubePlayerControllerErrorDomain code:3 userInfo:[NSDictionary dictionaryWithObject:#"The JSON data could not be found." forKey:NSLocalizedDescriptionKey]];
}
return nil;
}
So I want to make my app edit and save ID3 tags. I found on some site a long time ago on how to read them, here is this code in my app:
-(NSDictionary*)MP3InfoDictionary {
AudioFileID fileID = nil;
OSStatus err = noErr;
err = AudioFileOpenURL( (CFURLRef) self, kAudioFileReadPermission, 0, &fileID);
if (err != noErr) {
//NSLog(#"AudioFileOpenURL failed");
}
UInt32 id3DataSize = 0;
char * rawID3Tag = NULL;
err = AudioFileGetPropertyInfo(fileID, kAudioFilePropertyID3Tag, &id3DataSize, NULL);
if (err != noErr) {
NSLog(#"AudioFileGetPropeetyInfo failed for ID3 tag");
}
//NSLog(#"id3 data size is %lu bytes",id3DataSize);
rawID3Tag = (char *) malloc(id3DataSize);
if (rawID3Tag == NULL) {
//NSLog(#"could not allocated %lu bytes of memory for ID3 tag", id3DataSize);
}
err = AudioFileGetProperty(fileID, kAudioFilePropertyID3Tag, &id3DataSize, rawID3Tag);
if (err != noErr) {
NSLog(#"AudioFileGetProperty failed for ID3 tag");
}
//NSLog(#"read %lu bytes of ID3 info", id3DataSize);
CFDictionaryRef piDict = nil;
UInt32 piDataSize = sizeof(piDict);
free(rawID3Tag);
err = AudioFileGetProperty(fileID, kAudioFilePropertyInfoDictionary, &piDataSize, &piDict);
if (err != noErr) {
//NSLog(#"AudioFileGetProperty failed for property info dictionary");
}
//NSLog(#"Property info:%#", (NSDictionary*)piDict);
//CFShow(piDict);
NSDictionary *MP3InfoDictionary = (NSDictionary*)piDict;
if (MP3InfoDictionary != NULL) {
return MP3InfoDictionary;
}
return nil;
}
This code is in a NSURL category, the url is a file url of a mp3 in the documents directory of the iOS. It works 100%, I get all the titles, artwork, lyrics, etc. But now I want to save and overwrite values of the mp3 like artist, title, etc. On another post on here a guy posted that you use AudioFileSetProperty(), how do I use it correctly?
Apparently it's because of the kAudioFileReadPermission but It tells me that the mp3 is only readable, but that can't be true because another app I have can change ID3 tags and can on the same mp3 I've tried to edit.
EDIT:
See my first comment below. It appears AudioFile does not allow modifying the four types of files listed in the link.
I'm trying to get artwork of the mp3 file using these lines of code.
CFDataRef AlbumPic= nil;
UInt32 picDataSize = sizeof(picDataSize);
err =AudioFileGetGlobalInfo(kAudioFilePropertyAlbumArtwork, 0, NULL, &picDataSize, &AlbumPic);
if( err != noErr ) {
NSLog( #"error" );
}
NSData* imagedata= (__bridge NSData*)AlbumPic;
UIImage* image=[[UIImage alloc]initWithData:imagedata];
If I'm using:
NSLog (#"image %#, image");
or
NSLog (#"image %#, [image description]");
there is NULL.
How can I get artwork of mp3 file using kAudioFilePropertyAlbumArtwork?
The function you want is AudioFileGetProperty, not AudioFileGetGlobalInfo
Using the new asset library framework available in iOS 4 i see that I can get the url for a given video using the UIImagePickerControllerReferenceURL. The url returned is in the following format:
assets-library://asset/asset.M4V?id=1000000004&ext=M4V
I am trying to upload this video to a website so as a quick proof of concept I am trying the following
NSData *data = [NSData dataWithContentsOfURL:videourl];
[data writeToFile:tmpfile atomically:NO];
Data is never initialized in this case. Has anyone managed to access the url directly via the new assets library? Thanks for your help.
I use the following category on ALAsset:
static const NSUInteger BufferSize = 1024*1024;
#implementation ALAsset (Export)
- (BOOL) exportDataToURL: (NSURL*) fileURL error: (NSError**) error
{
[[NSFileManager defaultManager] createFileAtPath:[fileURL path] contents:nil attributes:nil];
NSFileHandle *handle = [NSFileHandle fileHandleForWritingToURL:fileURL error:error];
if (!handle) {
return NO;
}
ALAssetRepresentation *rep = [self defaultRepresentation];
uint8_t *buffer = calloc(BufferSize, sizeof(*buffer));
NSUInteger offset = 0, bytesRead = 0;
do {
#try {
bytesRead = [rep getBytes:buffer fromOffset:offset length:BufferSize error:error];
[handle writeData:[NSData dataWithBytesNoCopy:buffer length:bytesRead freeWhenDone:NO]];
offset += bytesRead;
} #catch (NSException *exception) {
free(buffer);
return NO;
}
} while (bytesRead > 0);
free(buffer);
return YES;
}
#end
This is not the best way to do this. I am answering this question in case another SO user comes across the same issue.
Basically my need was to be able to spool the video file to a tmp file so I can upload it to a website using ASIHTTPFormDataRequest. There is probably a way of streaming from the asset url to the ASIHTTPFormDataRequest upload but I could not figure it out. Instead I wrote the following function to drop the file to a tmp file to add to ASIHTTPFormDataRequest.
+(NSString*) videoAssetURLToTempFile:(NSURL*)url
{
NSString * surl = [url absoluteString];
NSString * ext = [surl substringFromIndex:[surl rangeOfString:#"ext="].location + 4];
NSTimeInterval ti = [[NSDate date]timeIntervalSinceReferenceDate];
NSString * filename = [NSString stringWithFormat: #"%f.%#",ti,ext];
NSString * tmpfile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
ALAssetRepresentation * rep = [myasset defaultRepresentation];
NSUInteger size = [rep size];
const int bufferSize = 8192;
NSLog(#"Writing to %#",tmpfile);
FILE* f = fopen([tmpfile cStringUsingEncoding:1], "wb+");
if (f == NULL) {
NSLog(#"Can not create tmp file.");
return;
}
Byte * buffer = (Byte*)malloc(bufferSize);
int read = 0, offset = 0, written = 0;
NSError* err;
if (size != 0) {
do {
read = [rep getBytes:buffer
fromOffset:offset
length:bufferSize
error:&err];
written = fwrite(buffer, sizeof(char), read, f);
offset += read;
} while (read != 0);
}
fclose(f);
};
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
NSLog(#"Can not get asset - %#",[myerror localizedDescription]);
};
if(url)
{
ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetslibrary assetForURL:url
resultBlock:resultblock
failureBlock:failureblock];
}
return tmpfile;
}
Here is a clean swift solution to get videos as NSData.
It uses the Photos framework as ALAssetLibrary is deprecated as of iOS9:
IMPORTANT
The Assets Library framework is deprecated as of iOS 9.0. Instead, use the Photos framework instead, which in iOS 8.0 and later provides more features and better performance for working with a user’s photo library. For more information, see Photos Framework Reference.
import Photos
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
self.dismissViewControllerAnimated(true, completion: nil)
if let referenceURL = info[UIImagePickerControllerReferenceURL] as? NSURL {
let fetchResult = PHAsset.fetchAssetsWithALAssetURLs([referenceURL], options: nil)
if let phAsset = fetchResult.firstObject as? PHAsset {
PHImageManager.defaultManager().requestAVAssetForVideo(phAsset, options: PHVideoRequestOptions(), resultHandler: { (asset, audioMix, info) -> Void in
if let asset = asset as? AVURLAsset {
let videoData = NSData(contentsOfURL: asset.URL)
// optionally, write the video to the temp directory
let videoPath = NSTemporaryDirectory() + "tmpMovie.MOV"
let videoURL = NSURL(fileURLWithPath: videoPath)
let writeResult = videoData?.writeToURL(videoURL, atomically: true)
if let writeResult = writeResult where writeResult {
print("success")
}
else {
print("failure")
}
}
})
}
}
}
There you go...
AVAssetExportSession* m_session=nil;
-(void)export:(ALAsset*)asset withHandler:(void (^)(NSURL* url, NSError* error))handler
{
ALAssetRepresentation* representation=asset.defaultRepresentation;
m_session=[AVAssetExportSession exportSessionWithAsset:[AVURLAsset URLAssetWithURL:representation.url options:nil] presetName:AVAssetExportPresetPassthrough];
m_session.outputFileType=AVFileTypeQuickTimeMovie;
m_session.outputURL=[NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"%f.mov",[NSDate timeIntervalSinceReferenceDate]]]];
[m_session exportAsynchronouslyWithCompletionHandler:^
{
if (m_session.status!=AVAssetExportSessionStatusCompleted)
{
NSError* error=m_session.error;
m_session=nil;
handler(nil,error);
return;
}
NSURL* url=m_session.outputURL;
m_session=nil;
handler(url,nil);
}];
}
You can use a different preset key if you wish to re-encode the movie (AVAssetExportPresetMediumQuality for example)
Here is the Objective C solution of Alonzo answer, Using photos framework
-(NSURL*)createVideoCopyFromReferenceUrl:(NSURL*)inputUrlFromVideoPicker{
NSURL __block *videoURL;
PHFetchResult *phAssetFetchResult = [PHAsset fetchAssetsWithALAssetURLs:#[inputUrlFromVideoPicker ] options:nil];
PHAsset *phAsset = [phAssetFetchResult firstObject];
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:nil resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
if ([asset isKindOfClass:[AVURLAsset class]]) {
NSURL *url = [(AVURLAsset *)asset URL];
NSLog(#"Final URL %#",url);
NSData *videoData = [NSData dataWithContentsOfURL:url];
// optionally, write the video to the temp directory
NSString *videoPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"%f.mp4",[NSDate timeIntervalSinceReferenceDate]]];
videoURL = [NSURL fileURLWithPath:videoPath];
BOOL writeResult = [videoData writeToURL:videoURL atomically:true];
if(writeResult) {
NSLog(#"video success");
}
else {
NSLog(#"video failure");
}
dispatch_group_leave(group);
// use URL to get file content
}
}];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
return videoURL;
}
this from Zoul's Answer
thanks
Similar Code in Xamarin C#
Xamarin C# Equivalent
IntPtr buffer = CFAllocator.Malloc.Allocate(representation.Size);
NSError error;
nuint buffered = representation.GetBytes(buffer, Convert.ToInt64(0.0),Convert.ToUInt32(representation.Size),out error);
NSData sourceData = NSData.FromBytesNoCopy(buffer,buffered,true);
NSFileManager fileManager = NSFileManager.DefaultManager;
NSFileAttributes attr = NSFileAttributes.FromDictionary(NSDictionary.FromFile(outputPath));
fileManager.CreateFile(outputPath, sourceData,attr);
I would like to use the Core Audio extended audio file services framework to read a mp3 file, process it as a PCM, then write the modified file back as a mp3 file. I am able to convert the mp3 file to PCM, but am NOT able to write the PCM file back as a mp3.
I have followed and analyzed the Apple ExtAudioFileConvertTest sample and also cannot get that to work. The failure point is when I set the client format for the output file(set to a canonical PCM type). This fails with error "fmt?" if the output target type is set to mp3.
Is it possible to do mp3 -> PCM -> mp3 on the iPhone? If I remove the failing line, setting the kExtAudioFileProperty_ClientDataFormat for the output file, the code fails 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 set up 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 to read/write:
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;
}
Apple doesn't supply an MP3 encoder- only a decoder. The source document is a bit outdated, but AFAIK it is still current: http://developer.apple.com/library/ios/#documentation/MusicAudio/Conceptual/CoreAudioOverview/SupportedAudioFormatsMacOSX/SupportedAudioFormatsMacOSX.html%23//apple_ref/doc/uid/TP40003577-CH7-SW1
I think your best bet might be to use AAC.