iOS 开发与安卓平台共通 实现录音文件的录制,上传,下载,播放

     目前因项目需要,接触到有关音频文件的录制,上传,下载,播放等功能,并且遇到过一些不能播放,不能下载等问题。

  一、功能:录音,播放   问题:录音成功之后文件不能播放

  #import <AVFoundation/AVFoundation.h> 
1、主要使用自带的AVFoundation类库,在.h文件中导入头文件
2、.h 声明
{
    AVAudioSession          *session;
    AVAudioPlayer           *player;
    AVAudioRecorder         *recorder;
}
@property(nonatomic,retain)NSURL            *recordedFile;
@property(nonatomic,retain)AVAudioPlayer    *player;
@property(nonatomic,retain)AVAudioRecorder  *recorder;
3、.m 实现

-(void)touchDown

{

    session = [AVAudioSessionsharedInstance];

//    session.delegate = self;

    NSError *sessionError;

    [sessionsetCategory:AVAudioSessionCategoryPlayAndRecorderror:&sessionError];

    

    if(session ==nil)

        NSLog(@"Error creating session: %@", [sessionErrordescription]);

    else

        [session setActive:YESerror:nil];

    //录音设置

    NSMutableDictionary *settings = [[NSMutableDictionaryalloc]init];

    //录音格式 无法使用

    [settings setValue :[NSNumbernumberWithInt:kAudioFormatLinearPCM]forKey:AVFormatIDKey];

    //采样率

    [settings setValue :[NSNumbernumberWithFloat:11025.0]forKey:AVSampleRateKey];//44100.0

    //通道数

    [settings setValue :[NSNumbernumberWithInt:2]forKey:AVNumberOfChannelsKey];

    //线性采样位数

    //[recordSettings setValue :[NSNumber numberWithInt:16] forKey: AVLinearPCMBitDepthKey];

    //音频质量,采样质量

    [settings setValue:[NSNumbernumberWithInt:AVAudioQualityMin]forKey:AVEncoderAudioQualityKey];

    

    recorder = [[AVAudioRecorderalloc]initWithURL:self.recordedFilesettings:settingserror:nil];

    recorder.meteringEnabled=YES;//如果要监控声波则必须设置为YES

    BOOL isRecording = [recorderisRecording];

    NSLog(@"isRecording%i",isRecording);

    if (!isRecording) {

        //首次使用应用时如果调用record方法会询问用户是否允许使用麦克风

        [recorderprepareToRecord];

        [recorder record];

        //设置定时检测

        _audioTimer = [NSTimerscheduledTimerWithTimeInterval:0target:selfselector:@selector(audioPictureChange)userInfo:nilrepeats:YES];

    }


}

4、将录音文件.mp3文件上传到服务器,所以需要设置录音格式为以上格式,接下来创建录音机。
5、将.caf 文件转成.mp3格式,主要使用三方的.a库 libmp3lame.a 静态库 

- (void)audio_PCMtoMP3

{

    NSString *cafFilePath = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/downloadFile.caf"];

    

    NSString *mp3FilePath = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/downloadFile.mp3"];

    

    NSFileManager* fileManager=[NSFileManagerdefaultManager];

    if([fileManager removeItemAtPath:mp3FilePath error:nil])

    {

        NSLog(@"删除");

    }

    @try {

        int read, write;

        

        FILE *pcm = fopen([cafFilePath cStringUsingEncoding:1],"rb"); //source 被转换的音频文件位置

        fseek(pcm, 4*1024, SEEK_CUR);                                  //skip file header

        FILE *mp3 = fopen([mp3FilePath cStringUsingEncoding:1],"wb"); //output 输出生成的Mp3文件位置

        

        const int PCM_SIZE =8192;

        const int MP3_SIZE =8192;

        short int pcm_buffer[PCM_SIZE*2];

        unsigned char mp3_buffer[MP3_SIZE];

//        

        lame_t lame = lame_init();

        lame_set_in_samplerate(lame,11025.0);

        lame_set_VBR(lame, vbr_default);

        lame_init_params(lame);

        

        do {

            read = fread(pcm_buffer, 2*sizeof(shortint), PCM_SIZE, pcm);

            if (read == 0)

                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);

            else

                write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);

            

            fwrite(mp3_buffer, write, 1, mp3);

            

        } while (read != 0);

        

        lame_close(lame);

        fclose(mp3);

        fclose(pcm);

    }

    @catch (NSException *exception) {

        NSLog(@"%@",[exceptiondescription]);

    }

     

    @finally {

        

        NSError *playerError;

        AVAudioPlayer *audioPlayer = [[AVAudioPlayeralloc]initWithContentsOfURL:[[NSURLalloc]initFileURLWithPath:mp3FilePath]error:&playerError];

        self.player = audioPlayer;

        player.volume =1.0f;

        if (player ==nil)

        {

            NSLog(@"ERror creating player: %@", [playerErrordescription]);

        }

        [[AVAudioSessionsharedInstance]setCategory:AVAudioSessionCategorySoloAmbienterror:nil];

        self.player.meteringEnabled=YES;

        player.delegate =self;

        

    }

    

}

转换完成之后设置播放器,注意,播放器初始化的URL必须是录音文件的URL,保证路径存在录音数据,要不会出现播放器创建失败。
 
二、功能:上传录音文件  问题:上传文件之后不能播放
此次上传文件主要使用的是表单上传 使用 NSURLConnection 

    NSString * urlString=[NSStringstringWithFormat:@"http://%@%@.shtml",SERVER_IP_ADDRESS,path];

    NSMutableURLRequest* request=[[NSMutableURLRequestalloc]initWithURL:[NSURLURLWithString:urlString]cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheDatatimeoutInterval:0];

    // 设置请求类型为post请求

    [request setHTTPMethod:@"POST"];

    // 设置头部数据,指定了http post请求的编码方式为multipart/form-data(上传文件必须用这个)。

    [request setValue:[NSStringstringWithFormat:@"multipart/form-data; boundary=%@",BOUNDARY]forHTTPHeaderField:@"Content-Type"];

    NSMutableData * body=[NSMutableDatadata];

    /** 遍历字典将字典中的键值对转换成请求格式:

     --Boundary+72D4CD655314C423

     Content-Disposition: form-data; name="empId"

     

     254

     --Boundary+72D4CD655314C423

     Content-Disposition: form-data; name="shopId"

     

     18718

     */

//设置请求体内容 遍历字典中的内容 设置成表单上传格式

    [param enumerateKeysAndObjectsUsingBlock:^(id key,id obj,BOOL *stop) {

        NSMutableString *fieldStr = [NSMutableStringstring];

        [fieldStr appendString:[NSStringstringWithFormat:@"--%@\r\n",BOUNDARY]];

        [fieldStr appendString:[NSStringstringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key]];

        [fieldStr appendString:[NSStringstringWithFormat:@"%@\r\n", obj]];

        [body appendData:[fieldStr dataUsingEncoding:NSUTF8StringEncoding]];

        //        NSLog(@"表单数据:%@",fieldStr);

    }];

 [body appendData:[[NSStringstringWithFormat:@"--%@\r\n",BOUNDARY]dataUsingEncoding:NSUTF8StringEncoding]];

       NSString * contentdis = [NSStringstringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",@"fileMap",@""];

        NSString * contentType = [NSStringstringWithFormat:@"Content-Type: image/jpeg\r\n\r\n" ];

        [body appendData:[contentdis dataUsingEncoding:NSUTF8StringEncoding]];

        [body appendData:[contentType dataUsingEncoding:NSUTF8StringEncoding]];

        [body appendData:[[NSStringstringWithFormat:@"\r\n"]dataUsingEncoding:NSUTF8StringEncoding]];

    /**拼装成格式:

     --Boundary+72D4CD655314C423--

     */

    NSString *endString = [NSStringstringWithFormat:@"--%@--\r\n",BOUNDARY];

    [body appendData:[endStringdataUsingEncoding:NSUTF8StringEncoding]];

    // 设置request的请求体

    [request setHTTPBody:body];

    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueuemainQueue]completionHandler:^(NSURLResponse *response,NSData *data,NSError *connectionError) {

        [SVProgressHUDdismiss];

        if (data!=nil) {

            //        NSLog(@"data:%@",data);

            NSDictionary *dic = [NSJSONSerializationJSONObjectWithData:dataoptions:NSJSONReadingMutableContainerserror:nil];

            

            //                NSLog(@"dic:%@",response);

            block(dic,nil);

            

        }else{

            block(nil,connectionError);

        }

       

    }];

三、 从服务器下载录音文件
  

-(void)loading:(NSString *)fileUrlString

{

    receivedData=[[NSMutableDataalloc]init];

    NSString *fileName = [fileUrlString lastPathComponent];

    NSLog(@"fileName == %@",fileName);

    self.Mp3Name=fileName;

    NSURL *url =[NSURLURLWithString:fileUrlString];

    //创建NSURLRequest和NSURLConnection,并立即启动连接

    NSURLRequest *request = [[NSURLRequestalloc]initWithURL:urlcachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheDatatimeoutInterval:5.0f];

    NSURLConnection *connection = [[NSURLConnectionalloc]initWithRequest:requestdelegate:selfstartImmediately:YES];

    if (connection)

    {

        self.receivedData = [NSMutableDatadata];//初始化接收数据的缓存

    }

    else

    {

        NSLog(@"Bad Connection!");

        SHOW_ALERT(@"网络连接失败");

    }

    

}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

{

    [receivedData setLength:0];//置空数据

    long long mp3Size = [responseexpectedContentLength];//获取要下载的文件的长度

    NSLog(@"%lld",mp3Size);

    

}


//接收NSMutableData数据

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

{

//    NSLog(@"下载的data :%@",data);

    [receivedData appendData:data];

}


//接收完毕

- (void)connectionDidFinishLoading:(NSURLConnection *)connection

{

    [connection cancel];

    //在保存文件和播放文件之前可以做一些判断,保证程序的健壮行:例如:文件是否存在,接收的数据是否完整等处理,此处没加,使用时注意

    NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);

    NSString *documentsDirectory = [paths objectAtIndex:0];

    NSLog(@"mp3 path=%@",documentsDirectory);

    NSString *filePath = [documentsDirectorystringByAppendingPathComponent:self.Mp3Name];//mp3Name:你要保存的文件名称,包括文件类型。如果你知道文件类型的话,可以指定文件类型;如果事先不知道文件类型,可以在- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response中获取要下载的文件类型

    

    //在document下创建文件

    NSFileManager *fileManager = [NSFileManagerdefaultManager];

    //    if([fileManager removeItemAtPath:filePath error:nil])

    //    {

    //        NSLog(@"删除");

    //    }

    [fileManager createFileAtPath:filePathcontents:nilattributes:nil];

    NSLog(@"mp3 createFileAtPath path=%@",filePath);

    //将下载的数据,写入文件中

    [receivedDatawriteToFile:filePathatomically:YES];

    

    //播放下载下来的mp3文件

    [self playVoice:filePath];

    

    //如果下载的是图片则可以用下面的方法生成图片并显示 create image from data and set it to ImageView

    /*

     UIImage *image = [[UIImage alloc] initWithData:recvData];

     [imgView setImage:image];

     */

}

四、下载文件之后,创建播放器,播放下载的文件

#pragma mark  播放录音

-(void)toPlayAudio:(NSNotification *)text

{

    NSString *filePath=[text.userInfoobjectForKey:@"filePath"];

    NSError *error;

    //    NSData *audioData = [NSData dataWithContentsOfURL:[NSURL URLWithString:filePath]];

    NSData  *audioData=[NSDatadataWithContentsOfFile:filePathoptions:0error:&error];

    //    NSLog(@"sudioData:%@",audioData);

    

    NSError *audiError;

    //创建音频 播放器

    AVAudioPlayer * voicePlayer  = [[AVAudioPlayeralloc]initWithData:audioDataerror:&audiError];

    self.chatPlayer = voicePlayer;

    [chatPlayer setVolume:1];//设置音量大小

    self.chatPlayer.meteringEnabled=YES;

    self.chatPlayer.delegate=self;

    //显示录音时间

    float  cTime=chatPlayer.duration;

    int    time=(int)cTime;

    if (chatPlayer ==nil)

    {

        NSLog(@"ERror creating player: %@", [audiErrordescription]);

    }else{

        //If the track is playing, pause and achange playButton text to "Play"

        if([chatPlayerisPlaying])

        {

            [chatPlayer pause];

            if (markFromme) {

                _recordAudioImageV.image=[UIImageimageNamed:@"ic_bubble_normalr(1).png"];

            }else{

                _recordLeftImageV.image=[UIImageimageNamed:@"ic.png"];

            }

        }

        //If the track is not player, play the track and change the play button to "Pause"

        else

        {

            [chatPlayer prepareToPlay];

            [chatPlayer play];

            //播放时  打开定时器

            //开启定时器

            _chatTimer = [NSTimerscheduledTimerWithTimeInterval:0target:selfselector:@selector(playerPicChange)userInfo:nilrepeats:YES];

            [_chatTimer fire];

        }

    }

}

总结:1、在创建录音机之前要设置 AVAudioSession AVAudioSessionCategoryPlayAndRecord 状态。
2、创建播放器的时候必须保证是已存在录音data数据的路径,或者是完整的录音data数据。[[AVAudioPlayer allocinitWithData:audioData error:&audiError];
3、表单上传数据要注意表单格式













  




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值