This is from the network and has not been tested:
There are two methods to solve this problem. The first method is to store files in the program directory in the format. caf file, the interface used is AVAssetReader, AVAssetWriter, AVAssetReaderAudioMixOutput, AVAssetWriterInput; the Code can refer to the http://www.subfurther.com/blog/2010/12/13/from-ipod-library-to-pcm-samples-in-far-fewer-steps-than-were-previously-necessary/ above said very clearly, and the code has been given;
However, this method is slow, and every time you read an audio file, A. caf file is generated in the program folder (The. caf file size is about ten times the size of the. caf file)
The second method is to directly partition the file content into the memory, which is mainly used for audio parsing:
// The input parameter is the AssetURL of the obtained MPMediaItem;
(Void) loadToMemory :( NSURL *) asset_url
{
NSError * reader_error = nil;
AVURLAsset * item_choosed_asset = [AVURLAsset URLAssetWithURL: asset_url opti *****: nil];
AVAssetReader * item_reader = [AVAssetReader assetReaderWithAsset: item_choosed_asset error: & reader_error];
If (reader_error ){
NSLog (@ "failed to creat asset reader, reason: % @", [reader_error description]);
Return;
}
NSArray * asset_tracks = [item_choosed_asset tracks];
AVAssetReaderAudioMixOutput * item_reader_output = [AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks: asset_tracks audioSettings: nil];
If ([item_reader canAddOutput: item_reader_output]) {
[Item_reader addOutput: item_reader_output];
} Else {
NSLog (@ "the reader can not add the output ");
}
UInt64 total_converted_bytes;
UInt64 converted_count;
UInt64 converted_sample_num;
Size_t sample_size;
Short * data_buffer = nil;
CMBlockBufferRef next_buffer_data = nil;
[Item_reader startReading];
While (item_reader.status = AVAssetReaderStatusReading ){
CMSampleBufferRef next_buffer = [item_reader_output copyNextSampleBuffer];
If (next_buffer ){
Total_converted_bytes = CMSampleBufferGetTotalSampleSize (next_buffer); // The total number of bytes of next_buffer;
Sample_size = CMSampleBufferGetSampleSize (next_buffer, 0); // the size of the sample with the serial number of 0 in next_buffer;
Converted_sample_num = CMSampleBufferGetNumSamples (next_buffer); // the total number of samples contained in next_buffer;
NSLog (@ "the number of samples is % f", (float) converted_sample_num );
NSLog (@ "the size of the sample is % f", (float) sample_size );
NSLog (@ "the size of the whole buffer is % f", (float) total_converted_bytes );
// Copy the data to the data_buffer varible;
// In this method, We parse nextSampleBuffer every time we get it, instead of loading all the files into the memory before parsing;
// The copyNextSampleBuffer method of AVAssetReaderOutput reads 8196 sample data each time (except for the last time). The data is stored in the memory in the short type (two bytes in one unit)
// The size of each sample is related to the number of audio channels, which can be obtained using CMSampleBufferGetSampleSize. Therefore, the data size obtained after each call of copyNextSampleBuffer is 8196 * sample_size (byte );
// Based on this, the space required each time we apply for data_buffer is also fixed, for (8196 * sample_size)/two short-type memory (each short occupies two bytes );
If (! Data_buffer ){
Data_buffer = new short [4096 * sample_size];
}
Next_buffer_data = CMSampleBufferGetDataBuffer (next_buffer );
OSStatus buffer_status = CMBlockBufferCopyDataBytes (next_buffer_data, 0, total_converted_bytes, data_buffer );
If (buffer_status! = KCMBlockBufferNoErr ){
NSLog (@ "something wrong happened when copying data bytes ");
}
/*
In this case, the audio data is stored in data_buffer, which is the original audio data (without any compression) and can be parsed or operated on.
*/
} Else {
NSLog (@ "total sameple size % d", converted_count );
Size_t total_data_length = CMBlockBufferGetDataLength (item_buffer );
NSLog (@ "item buffer length is % f", (float) total_data_length );
Break;
}
// CFRelease (next_buffer );
}
If (item_reader.status = AVAssetReaderStatusCompleted ){
NSLog (@ "read over ......");
} Else {
NSLog (@ "read failed ;");
}
}
Second, personal application testing, available for use.
MPMediaPickerController * pickerController = [[MPMediaPickerController alloc]
InitWithMediaTypes: MPMediaTypeMusic];
// PickerController. prompt = @ "Choose song ";
PickerController. allowsPickingMultipleItems = NO;
PickerController. delegate = self;
[Self presentModalViewController: pickerController animated: YES];
[PickerController release];
// Write the read data to the sandbox and use the path to obtain nsdata.
-(Void) mediaPicker :( MPMediaPickerController *) mediaPicker didPickMediaItems :( MPMediaItemCollection *) mediaItemCollection
{
NSArray * media_array = [mediaItemCollection items];
MPMediaItem * song_item = [media_array objectAtIndex: 0];
SongObject * song_object = [[SongObject alloc] init];
[Song_object setSong_name: [song_item valueForProperty: MPMediaItemPropertyTitle];
[Song_object setSinger_name: [song_item valueForKey: MPMediaItemPropertyPodcastTitle];
NSURL * url = [song_item valueForProperty: MPMediaItemPropertyAssetURL];
NSLog (@ "url is % @", url );
AVURLAsset * songAsset = [AVURLAsset URLAssetWithURL: url options: nil];
AVAssetExportSession * exporter = [[AVAssetExportSession alloc] initWithAsset: songAsset presetName: AVAssetExportPresetAppleM4A];
Exporter. outputFileType = @ "com. apple. m4a-audio ";
NSString * exportFile = [myDocumentsDirectory () stringByAppendingPathComponent: @ "exported. m4a"];
If ([[NSFileManager defaultManager] fileExistsAtPath: exportFile])
{
NSError * deleteErr = nil;
[[NSFileManager defaultManager] removeItemAtPath: exportFile error: & deleteErr];
If (deleteErr)
{
NSLog (@ "Can't delete % @: % @", exportFile, deleteErr );
}
}
// [SongAsset loadValuesAsynchronouslyForKeys: <# (NSArray *) #> completionHandler: <# ^ (void) handler #>]
NSURL * path_url = [NSURL fileURLWithPath: exportFile];
Exporter. outputURL = path_url;
[Exporter exportAsynchronouslyWithCompletionHandler: ^ {
Int exportStatus = exporter. status;
Switch (exportStatus)
{
Case AVAssetExportSessionStatusFailed:
{
// Log error to text view
NSError * exportError = exporter. error;
NSLog (@ "AVAssetExportSessionStatusFailed: % @", exportError );
Break;
}
Case AVAssetExportSessionStatusCompleted:
{
NSLog (@ "AVAssetExportSessionStatusCompleted ");
// Set up AVPlayer
NSData * data = [NSData dataWithContentsOfURL: path_url];
NSLog (@ "data is % @", data );
Break;
}
Case AVAssetExportSessionStatusUnknown:
{
NSLog (@ "AVAssetExportSessionStatusUnknown ");
Break;
}
Case AVAssetExportSessionStatusExporting:
{
NSLog (@ "AVAssetExportSessionStatusExporting ");
Break;
}
Case AVAssetExportSessionStatusCancelled:
{
NSLog (@ "AVAssetExportSessionStatusCancelled ");
Break;
}
Case AVAssetExportSessionStatusWaiting:
{
NSLog (@ "AVAssetExportSessionStatusWaiting ");
Break;
}
Default:
{
NSLog (@ "didn't get export status ");
Break;
}
}
}];
[Song_object release];
[MediaPicker dismissModalViewControllerAnimated: YES];
}
From cloud huaikong-abel