美文网首页视频开发音视频
ios 回声消除,基于Audio Unit

ios 回声消除,基于Audio Unit

作者: huisedediao | 来源:发表于2017-11-28 16:24 被阅读1083次

2018.03.28

----- 好多同学私信不会用,GitHub项目添加了示例demo,具体使用参考demo
----- 添加了pcm转WAV的方法(我只是搬运工)

先说下为什么会有回声。

由于手机app(A端)需要一边录音一边播放声音。A端 在通过麦克风采集输入声音的时候,把手机正在播放的声音(由 B端 传输过来)也采集进去了,并将采集到的声音传到 B端 播放,因此在 B端 听起来除了有 A端 原本想要传的声音,还有 B端 之前传出去的声音,就造成了所谓的回声。

原理明白就好解决了,回声消除,就是将采集到的声音数据中的属于手机播放的那部分声音去除,Audio Unit 已经集成了回声消除功能,直接调用就行。
基于Audio Unit封装了一个回声消除的库,包括回声消除和对pcm数据进行播放。

传送门: XBEchoCancellation

使用:

获取麦克风输入:

XBEchoCancellation *echo = [XBEchoCancellation shared];
echo.bl_input = ^(AudioBufferList *bufferList) {
    AudioBuffer buffer = bufferList->mBuffers[0];
    // buffer即从麦克风获取到的数据,默认已经消除了回音
};
[echo startInput];

播放pcm音频数据:

XBEchoCancellation *echo = [XBEchoCancellation shared];
echo.bl_output = ^(AudioBufferList *bufferList, UInt32 inNumberFrames) {
    AudioBuffer buffer = bufferList->mBuffers[0];
    // 这里把要传给发声设备的pcm数据赋给buffer
};
[echo startOutput];

相关文章

网友评论

  • Tomychen:博主你好,我这边遇到一个问题:使用XBEchoCancellation进行录制,然后用AVAudioPlayer播放其他音乐,就会出现AVAudioPlayer播放的音乐声音很小的问题,不知道博主有没有遇到过?
    huisedediao:@Ctiy
    用AVAudioPlayer播放音乐前,设置下AudioSession
  • 强哥1号拖拉机1:博主,你好。我在使用你demo 的时候出现一个问题,看能不能帮忙解决一下。
    1,首先,我添加了背景音乐,我在点击开始录音的时候播放背景音乐,用扬声器播放出来。
    2,背景音乐播放时,我说话录音,40s后背景音乐播放完了,录音完成。
    3,最后点击播放录音的时候,发现录音不是很清晰,会出现说话断断续续,不连贯,偶尔出现一点点背景音乐。
    请问这是什么原因呢?是否有好的方法解决这个问题?谢谢!!!!!
    huisedediao:代码更新了,你试下。

    回调函数里不要做耗时的操作,包括分配内存,NSLog这些
  • jixiaojiid都被人抢了:[XBEchoCancellation shared].bl_output = ^(AudioBufferList *bufferList, UInt32 inNumberFrames) {
    AudioBuffer buffer = bufferList->mBuffers[0];

    char data[buffer.mDataByteSize];
    int len = readPcmData(data, buffer.mDataByteSize, newPcmData);

    memcpy(buffer.mData, data, len);

    };

    int readPcmData(char *data, int len, NSMutableData *dataStore)
    {
    NSData *subData = [dataStore subdataWithRange:NSMakeRange(_readerLength, len)];
    Byte *tempByte = (Byte *)[subData bytes];
    memcpy(data,tempByte,len);
    _readerLength = _readerLength + len;
    return len;
    }
    你好,我这样写什么声音都没有
    jixiaojiid都被人抢了:@huisedediao 检查过了,是一样的,是单声道
    huisedediao:@jixiaojiid都被人抢了
    检查下你音频的位数和码率是否和XBEchoCancellation设置的一样,检查下是否是单声道数据
  • 今年27:for (int i = 0 ; i < frames; i++) {
    NSData* out_data = [data subdataWithRange:NSMakeRange(i*_frame_size + 4, _frame_size)];
    int nDecodedByte = sizeof(short) * [_speex decode:(Byte*)out_data.bytes length:_frame_size output:out_buffer];
    NSData* decodeData = [NSData dataWithBytes:out_buffer length:nDecodedByte];
    // [_audioDataPlayer inputNewDataFromBuffer:(Byte*)out_buffer size:nDecodedByte];
    [XBEchoCancellation shared].bl_output = ^(AudioBufferList *bufferList, UInt32 inNumberFrames) {
    AudioBuffer buffer = bufferList->mBuffers[0];
    memcpy(buffer.mData, decodeData.bytes, nDecodedByte);
    buffer.mDataByteSize = nDecodedByte;
    NSLog(@"buffer:---->%d", nDecodedByte);

    };
    }
    我对收到的数据先要用speex解码,解码后再弄,请问这样对吗? 反正声音不对
    今年27:@丶QianYe 我是两个手机之间的通话,码率肯定是一样的,不过我正在尝试,目前就是有杂音
    huisedediao:@今年27
    检查下码率、位数是不是和库里的一样,不一样的话,对_frame_size进行调整。
    检查下声道数是不是单声道,双声道数据要先转成单声道。
  • Unity与iOS的灵魂小白:在吗 一直输出。 没有开启声音输出回调 怎么回事啊 步骤都是对的 能帮我解决下吗
  • WKX_iOS:大神,有Demo可以看嘛,不会使用啊,刚接触这一块,也不知道怎么在录音的时候调用,怎么输出到文件并保存在本地
    huisedediao:@WKX_iOS
    GitHub更新了demo,可以参考下
    WKX_iOS:Audio Unit怎么录音和播放呢,目前只会操作AVAudioRecorder,player这些简单的
  • Libero_8573:-(void)playAudioFrame:(uint8_t *)buf withSize:(uint32_t)bufSize{

    iosAudio.bl_output = ^(AudioBufferList *bufferList, UInt32 inNumberFrames) {
    AudioBuffer buffer = bufferList->mBuffers[0];

    //读取数据(数据从服务起来,已经做好了缓存),这里读取数据的方法看你是怎么写的

    //把pcm数据赋值给buffer,下面这两句就是你要的把数据和size传给buffer
    memcpy(buffer.mData, buf, bufSize);
    buffer.mDataByteSize = bufSize;

    };
    [iosAudio startOutput];

    }这样子还是播放声音不正常,采样率都是对的,求请教
    huisedediao:不好意思这段时间太忙,更新了demo,可以参考demo
  • 冬的天:-(void)decodeAudio:(char *)buffer Size:(unsigned int)size time:(unsigned int)time{

    XBEchoCancellation *echo = [XBEchoCancellation shared];
    echo.bl_output = ^(AudioBufferList *bufferList,UInt32 inNumberFrames){

    };
    [echo startOutput];
    }
    能请问一下我要怎么才能把我的buffer和size传进去?
    能帮下忙吗?谢谢🙏!
    huisedediao:更新了demo,可以参考下
    huisedediao:AudioBuffer buffer = bufferList->mBuffers[0];
    char data[buffer.mDataByteSize];

    //读取数据(数据从服务起来,已经做好了缓存),这里读取数据的方法看你是怎么写的
    int len = dataBuf->read_data(data, buffer.mDataByteSize);

    //把pcm数据赋值给buffer,下面这两句就是你要的把数据和size传给buffer
    memcpy(buffer.mData, data, len);
    buffer.mDataByteSize = len;
  • f9fd214fa70f:博主,实例化后并扬声器或听筒都没有声音输出,怎么用的?XBEchoCancellation *echo = [XBEchoCancellation shared];[echo startInput];[echo startOutput];
    huisedediao:@song_d6bc
    不是的。bl_input和bl_output是两个独立的回调。
    bl_input这个回调,获取到的是你手机麦克风采集到的声音,你可以通过下面的代码获取到数据和数据的长度,传给服务器或者需要接收这个数据的设备:
    AudioBuffer buffer = bufferList->mBuffers[0];
    SInt16 *editBuffer = (SInt16 *)buffer.mData;
    int length = buffer.mDataByteSize;

    bl_output这个回调,是用来播放pcm数据的。pcm数据一般是从你的服务器或者摄像头这类的设备传输过来的,首先你要读取到数据,然后通过memcpy函数把数据赋给buffer,下面的代码你参考下:
    char data[buffer.mDataByteSize];
    //读取数据(数据从服务起来,已经做好了缓存)
    int len = dataBuf->read_data(data, buffer.mDataByteSize);
    //把pcm数据赋值给buffer
    memcpy(buffer.mData, result, len);
    buffer.mDataByteSize = len;
    f9fd214fa70f:@丶QianYe 谢谢回复,因之前没有涉及音视频方向,不是很明白。pcm数据是从 echo.bl_input = ^(AudioBufferList *bufferList) {
    AudioBuffer buffer = bufferList->mBuffers[0];
    // buffer即从麦克风获取到的数据,默认已经消除了回音

    };里的AudioBuffer buffer 获取吗?怎么获取呢?又怎么赋值给bl_output 里的buffer呢?
    huisedediao:XBEchoCancellation *echo = [XBEchoCancellation shared];
    echo.bl_output = ^(AudioBufferList *bufferList, UInt32 inNumberFrames) {
    AudioBuffer buffer = bufferList->mBuffers[0];
    // 这里把要传给发声设备的pcm数据赋给buffer
    };
    想要有声音输出,在上面的回调里,你得把你的pcm数据赋给上面的buffer,调用startOutput即可。
    如果已经把数据赋值给buffer还是没声音或者都是杂音,看看声音数据的采样率、声道数和位数是不是和XBEchoCancellation默认的设置一样:
    #define kRate (XBEchoCancellationRate_8k) //采样率
    #define kChannels (1)//声道数
    #define kBits (16)//位数
  • 小mark哥:有用,谢谢。
  • huisedediao:关于播放pcm音频数据这块的回调解释下,因为有的小伙伴有疑问。
    Audio Unit播放pcm的回调方法里,给的是一个指针,也就是地址,Audio Unit会播放该地址的数据,我们只要把要播放的声音数据填充到该地址即可
    BryanHong:@丶QianYe 播放的时候同时录音,会出现录音有时候没录到的问题,怎么解决呢

本文标题:ios 回声消除,基于Audio Unit

本文链接:https://www.haomeiwen.com/subject/zgkebxtx.html