iphone开发:读取音频

来源:未知 责任编辑:智问网络 发表时间:2013-11-04 19:43 点击:

此处来源于网络,没有测试:


已经解决,有两种方法,第一种是把文件转存到程序的目录下,转存的格式为.caf文件,使用的接口为AVAssetReader,AVAssetWriter,AVAssetReaderAudioMixOutput,AVAssetWriterInput;代码可以参考http://www.subfurther.com/blog/2010/12/13/from-ipod-library-to-pcm-samples-in-far-fewer-steps-than-were-previously-necessary/ 上面说的很清楚了,而且代码也已经给出;
但这种方法缺点是速度慢,而且每读一个音频文件,都会在程序文件夹下生成一个.caf文件(.caf 文件大小约是.mp3的十倍)
第二种方法是直接把文件内容分块读入内存,主要用于音频解析:

//传入参数就是获取到的MPMediaItem的AssetURL;
(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);//next_buffer的总字节数;
            sample_size=CMSampleBufferGetSampleSize(next_buffer, 0);//next_buffer中序号为0的sample的大小;
            converted_sample_num=CMSampleBufferGetNumSamples(next_buffer);//next_buffer中所含sample的总个数;
            
            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;
            //这种方法中,我们每获得一次nextSampleBuffer后就对其进行解析,而不是把文件全部载入内存后再进行解析;
            //AVAssetReaderOutput 的copyNextSampleBuffer方法每次读取8196个sample的数据(最后一次除外),这些数据是以short型存放在内存中(两字节为一单元)
            //每个sample的大小和音频的声道数相关,可以用CMSampleBufferGetSampleSize来获得,所以每次调用copyNextSampleBuffer后所获得的数据大小为8196*sample_size(byte);
            //据此,我们申请data_buffer时每次需要的空间也是固定的,为(8196*sample_size)/2个short型内存(每个short占两字节);
            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");
            }
            
                        /*
             此时音频的数据存储在data_buffer中,这些数据是音频原始数据(未经任何压缩),可以对其进行解析或其它操作
             */
 
        }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;");
    }
}

 


第二种,个人应用测试,可以使用。

 MPMediaPickerController *pickerController =    [[MPMediaPickerController alloc]
                                                         initWithMediaTypes: MPMediaTypeMusic];
            //pickerController.prompt = @"Choose song";
            pickerController.allowsPickingMultipleItems = NO;
            pickerController.delegate = self;
            [self presentModalViewController:pickerController animated:YES];
            [pickerController release];

 


//将读取出来的数据写入沙盒,然后再用路径得到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];
}

 


摘自 云怀空-abel

    发表评论
    请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
    用户名: 验证码:点击我更换图片
    最新评论 更多>>

    推荐热点

    • Lexical or Preprocessor Issue 'xxx.h
    • ios学习笔记(二)xcode 4.3.2下实现基本交互
    • ios版本的helloworld
    • iphone(object-c) 内存管理(3) 有效的内存管理 前半部分
    • ios学习笔记(一)xcode 4.3.2下创建第一个ios项目
    • UITableView一些方法
    • IOS类似iphone通讯录TableView的完整demo【附源码】
    • [iPhone中级]iPhone团购信息客户端的开发 (二)
    • iphone(object-c)内存管理(1)
    网站首页 - 友情链接 - 网站地图 - TAG标签 - RSS订阅 - 内容搜索
    Copyright © 2008-2015 计算机技术学习交流网. 版权所有

    豫ICP备11007008号-1