cocos2dx之 android/ios语音交互(二)

前端之家收集整理的这篇文章主要介绍了cocos2dx之 android/ios语音交互(二)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

经过一番折腾,终于找到了一种第三方库来转换android与iOS录音播放格式不兼容的问题。
思路:android/iOS手机录音传给服务器,参数(录音数据+手机端口类型),然后等到服务器广播数据给玩家,判断端口是android,将数据保存为为.amr格式,否则保存为.aac格式。不同手机端口调用相应端口函数
1、设置端口录音格式:
android–>.amr

public void record(){
        if (isRecording == true ) return;    

        recondPath = Environment.getExternalStorageDirectory().getAbsolutePath(); 
        recondPath += "/ione1.amr"; //录音格式

        File dirs = new File(recondPath);
        if (dirs.exists()){
           dirs.delete();
        }

        stopRecorder();         
        isRecording = true; 

        mRecorder = new MediaRecorder();          
        //设置音源为Micphone 
        mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 
        //设置封装格式
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB); 
        //设置编码格式 
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);         
        mRecorder. setAudioEncodingBitRate(8);//设置音频编码录音比特率
        mRecorder.setAudioChannels(1);//设置录制的音频通道数
        mRecorder.setAudioSamplingRate(8000); //设置音频采样率记录 
        mRecorder.setOutputFile(recondPath);    

        try {    
            mRecorder.prepare();    
        } catch (IOException e) {    
            Log.e(TAG,"prepare() Failed");
        }
        //录音 
        mRecorder.start();        
    }
    public boolean stopRecorder() {
         if( mRecorder == null ) return false;

        try{
            mRecorder.stop();    
            mRecorder.reset();
            mRecorder.release();    
            mRecorder = null;   
        }catch ( IllegalStateException e){
            e.printStackTrace();
        }

        return false;  
    }

ios–>.aac

-(void)startAudioRecording
{
    if(!isRecording)
    {
        [self init];

        isRecording = YES;
        NSLog(@"正在录音");

        NSMutableDictionary *dicM=[NSMutableDictionary dictionary];
        //设置录音格式
        [dicM setObject:@(kAudioFormatMPEG4AAC) forKey:AVFormatIDKey];//录音格式
        //设置录音采样率,8000是电话采样率,对于一般录音已经够了
        [dicM setObject:@(1600) forKey:AVSampleRateKey];
        //设置通道,这里采用单声道
        [dicM setObject:@(1) forKey:AVNumberOfChannelsKey];
        //每个采样点位数,分为8、16、24、32
        [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];
        //录音的质量
        [dicM setValue:[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityKey];
        //是否使用浮点数采样
        [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];

        recorder = [[AVAudioRecorder alloc] initWithURL:recordedFile settings:dicM error:nil];

        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
        [[AVAudioSession sharedInstance] setActive:YES error:nil];
        [self setSoundSession];
        [recorder peakPowerForChannel:0];

        [recorder prepareToRecord];
        [recorder record];
    }
}

2、接收服务器传来的需要播放的录音数据,根据不同端口录的音保存为数据相同录音格式:
android–>.amr
ios–>.aac

//服务器传来录音数据,保存在表voiceTab中 //voiceTab[index] = event.data
function MainScene:startPlayVoice()
    if self.isStartRecond  == false then -- 没有在录音
        if device.platform == "android" or device.platform == "ios" then --播放录音 
            local len = #voiceTab
            if len >= 1 then
                voicePlay( data )
            else
                print(" 录音播放完了 ")
            end
        end
    end
end
function voicePlay(data)
    if device.platform == "android" then
        local function callback(result)
            -- print("录音播放完成 " ) 
            ReturnRecordingPlayChange(result)
        end

        local path = writefileCheckRecond( data.voicebin,data.content )
        print("开始播放了 voicePlay ")
        local args = { 1,path,callback }
        local sigs = "(ILjava/lang/String;I)I"
        local luaj = require "cocos.cocos2d.luaj"
        local className = "com/cocos2dx/sample/LuaJavaBridge"
        local ok,ret  = luaj.callStaticMethod(className,"sendLuaToJavaAudioRecorPlay",args,sigs)
        if not ok then
            print("luaj error:",ret)
        else
            print("The ret is:",ret)
        end
    elseif device.platform == "ios" then
        local path = writefileCheckRecond( data.voicebin,data.content )
        print("开始播放了 voicePlay ",path)
        local i = iosAudioStartPlay( path ) 
    end
end
function writefileCheckRecond( data,platform )
    local path = device.writablePath.."netSprite/" --获取本地存储目录
    if not io.exists(path) then
        lfs.mkdir(path) --目录不存在,创建此目录
    end

    if platform == "android" then
        path = path.."recond.amr"
    elseif platform == "ios" then
        path = path.."recond.aac"
    else
        return;
    end

    print("写入完成:"..path)

    return path;
end

3、分析两端口录音互相播放的情况(A端口录音–>B端口播放)
android–>android:android玩家录音为.amr传给服务器,android玩家接收录音二进制数据保存的也是.amr格式,播放OK。

public void startPlay(String filePath,int luaFunc){
        if( isPlay == true)
        {
            Log.d("tag","正在播放中");
            return;
        }

        try {
            stopPlay();  

            isPlay = true;
            playLuaFun = luaFunc; 

            mPlayer = MediaPlayer.create(Cocos2dxActivity.getInstance(),Uri.parse(filePath));
            mPlayer.start();// 开始播放 

            mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
                @Override 
                public void onCompletion(MediaPlayer m) { 
                    Log.d("tag","播放完毕");                       
                    LuaJavaBridge.callbackLuaFun("1","ReturnRecordingPlayChange",index++);   
                    buySuccessJava(1);
                    Log.d(TAG,"playLuaFun = " + playLuaFun);

                    isPlay = false;
                    stopPlay();
                }
            });

        }catch(Exception e){  
            Log.e(TAG,"prepare() Failed");
        }
    }

android–>iOS:android玩家录音为.amr传给服务器,iOS玩家接收录音二进制数据保存为.amr格式,调用第三方库将格式.amr转.mav格式就播放OK。

-(void)playAudio
{
    if(!isPlay)
    {
        if([player isPlaying])
        {
            NSLog(@"停止录音播放");
            [player pause];
        }
        else
        {
            NSString *documentsDirectory= [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
            audioRecoderSavePath=[NSString stringWithFormat:@"%@/%@",documentsDirectory,@"netSprite/"];
            recoderName= [NSString stringWithFormat:@"%@",@"recond.amr"];
            tempRecoderPath=[NSString stringWithFormat:@"%@%@",audioRecoderSavePath,recoderName];

            fm = [NSFileManager defaultManager]; //创建文件管理对象
            if([fm fileExistsAtPath:tempRecoderPath] == NO)//判断文件是否存在
            {
                NSLog(@"文件不存在");

                recoderName= [NSString stringWithFormat:@"%@",@"recond.aac"];
                tempRecoderPath=[NSString stringWithFormat:@"%@%@",recoderName];
                isIos = true;
                [self startPlayAudio];
                return;
            }
            else
            {
                isIos = false;
                NSLog(@"文件存在");
            }

            NSString *recoderWavName= [NSString stringWithFormat:@"%@",@"recond.wav"];
            tempWavRecoderPath =[NSString stringWithFormat:@"%@%@",recoderWavName];
            //第三方库AudioConverter
            [AudioConverter convertAmrToWavAtPath:tempRecoderPath wavSavePath:tempWavRecoderPath asynchronize:YES completion:^(BOOL success,NSString * _Nullable resultPath) {
                if (success) {
                    NSLog(@"amr转wav成功!");

                    _wavFilePath = resultPath;

                    [self startPlayAudio];
                } else {
                   NSLog(@"amr转wav失败!");
                }
            }];
        }
    }
}

iOS –>android:ios玩家录音为.aac格式传给服务器,android玩家接收录音二进制数据保存为.aac格式,
android玩家播iOS录的.aac格式OK。

iOS–>iOS:ios玩家录音为.aac格式传给服务器,ios玩家接收录音二进制数据保存为.aac格式,ios玩家播iOS录的.aac格式OK。

参考:
http://www.jb51.cc/article/p-mcdpwusb-bpt.html
http://blog.csdn.net/adalu1986/article/details/50502387
http://www.jianshu.com/p/7dc01b48f8fc

猜你在找的Cocos2d-x相关文章