Android实现录音静音降噪

本文实例为大家分享了Android实现录音静音降噪的具体代码,供大家参考,具体内容如下

需求:

客户反馈产品的录音里面很多杂音(因为我们把Codec的录音增益调至最大,且电路上没有专用的音频处理芯片、CPU直接接MIC(有包地))。在外壳、硬件不能修改的情况下,软件得想想办法尝试解决问题。

首先想到的是双麦降噪,原理大概是:一个主麦克风用来做通话,另一个收集环境噪音,对音频波形分析和相位操作,叠加到主麦克风的采样波形上,形成相位抵消,就降噪了。缺点是,两个麦克风不能距离太近,并且两个麦克风距离说话人的距离不能太远,太远了角度就很小了,根本无法分辨出来,另外,根据产品使用情况,上下麦克风各自都有几率称为主麦克风。所以实验测试出来的结果并没有很好。

考虑到录音噪音在有“人声”的时候是分辨不出来的、或者说影响很小,而在静音时有明显的环境噪声,因此想使用静音降噪的方法来规避问题。

本文只是简单的静音降噪,原理如下:考虑到启动录音时,要等待一段时间(比如0.5s)才会有人声,可根据这0.5s时间来预测噪声的大小(阈值),然后以此为基础来检测“人声”的起始点。在人声到来前,把所有音频数据设置为0,也就是做静音处理,所以这里叫静音降噪。而人声到来时,返回实际的音频数据(包括里面的噪声数据)。计算阈值的方法只是简单的求和平均。

下面代码在RK平台上hardware/alsa_sound/AudioStreamInALSA.cpp实现。

#define MUTE_NOISE_REDUCTION
#ifdef MUTE_NOISE_REDUCTION
bool enable_reduction_noise = false;    //由属性sys.is.audiorecord.only控制

int threshold_def = 0x400;    //默认阈值
int threshold = 0;    //自适应噪声阈值
int threshold_count = 0;    //计数,超过THRESHOLD_COUNT则使用threshold来检测“人声”
#define THRESHOLD_COUNT 10

#define MUTE_DELAY_COUNT 15        //播放人声后保留的音频帧数、不静音

#define AUDIO_BUFFER_NUM 4        //缓存音频数据的帧数
#define AUDIO_BUFFER_SIZE 1024    //一帧的音频数据大小
char *audio_buffer[AUDIO_BUFFER_NUM];    //audio_buffer用于缓存音频数据
char *audio_buffer_temp;    //用于交互音频数据
int audio_buffer_pos=0;
#endif

#ifdef MUTE_NOISE_REDUCTION
    {
        unsigned int value = 0;
        int is_voice = 0;
        static int is_mute_delay_count;
        //ALOGE("in_begin_swip_num:%d in_begin_narrow_num=%d",in_begin_swip_num,in_begin_narrow_num);        

         if(enable_reduction_noise && bytes > AUDIO_BUFFER_SIZE){
            bytes = AUDIO_BUFFER_SIZE;
        }

        if(enable_reduction_noise){
            unsigned char * buffer_temp=(unsigned char *)buffer;
            unsigned int total = 0;
            unsigned int total_count=0;
            unsigned int total_temp = 0;
            short data16;
            int j = 0;
            for(j=0; j<bytes; j=j+2){
                value = buffer_temp[j+1];    //第二个字节为高位数据
                value = (value<<8)+buffer_temp[j];    //获得一个16bit的音频数据
                data16 = value&0xFFFF;
                if( (data16 & 0x8000) == 0){//正数
                    total +=data16;        //思考:会不会溢出
                    total_count++;        //计数
                }
            }

            total_temp = total/total_count;
            if(total_temp > threshold_def){
                is_voice++;        //检测到人声
            }else {    //is noise
                if(threshold_count == 0){
                    threshold = total_temp;
                }else{
                    threshold = (threshold+total_temp)/2;
                }
                threshold_count++;
                if(threshold_count >= THRESHOLD_COUNT){
                    threshold_def = threshold*2;    //更新阈值,这里的2要对产品实验来确定。
                    threshold_count = THRESHOLD_COUNT;    //此后一直用新阈值,直到停止录音
                }
            }

            //is_mute_delay_count的意义是,如果前面播放了人声,那再停止说话之后继续保留MUTE_DELAY_COUNT的音频数据,这样不会“戛然而止”。
            if( is_voice != 0 ){
                is_mute_delay_count=MUTE_DELAY_COUNT;
            }else{
                if(is_mute_delay_count != 0)
                    is_mute_delay_count--;
            }

            //audio_buffer的意义:检测到人声,要返回说话前的一小段音频数据,否则声音从静音到人声有个POP声的跳跃。
            //这里用audio_buffer来缓存AUDIO_BUFFER_NUM帧数据。
            if(is_mute_delay_count == 0){//Mute in order to remove noise
                memcpy(audio_buffer[audio_buffer_pos], (char *)buffer, bytes);    //缓存音频
                memset(buffer, 0, bytes);    //返回静音数据
            }else {
                memcpy(audio_buffer_temp, (char *)buffer, bytes);
                memcpy((char *)buffer, audio_buffer[audio_buffer_pos], bytes);    //返回旧的音频数据
                memcpy(audio_buffer[audio_buffer_pos], (char *)audio_buffer_temp, bytes);     //保存新的音频数据
            }
            audio_buffer_pos++;
            if(audio_buffer_pos>=AUDIO_BUFFER_NUM)
                audio_buffer_pos=0;
        }
    }
#endif

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • android实现来电静音示例(监听来电)

    复制代码 代码如下: private static int previousMuteMode = -1; /** * 来电静音 *  * @param context */private void toggleRingerMute(Context context){    AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);    if (previousMuteMode == -1) 

  • Android实现定时自动静音小助手

    定时静音助手的实现方法,供大家参考,具体内容如下 背景 突发奇想,刚好这学期刚上安卓课程,想设计一个时间助手.工作.学习中经常会被突如其来的电话所打扰,在上班,上课时这突如其来的铃声会惹来别人的反感,而只靠人们的记性是很难在准确的时间记得静音.如果一直静音,那么在休息时间又有可能漏接重要的电话.基于这种考虑,设计了这样一自动静音小助手,来帮助人们在忙碌的生活中定时静音,定时开启正常模式,简单方便. 界面设计 <?xml version="1.0" encoding="u

  • Android EasyPlayer声音自动停止、恢复,一键静音等功能

    Android EasyPlayer声音自动停止.恢复,一键静音等功能 我们在开发播放器时,可能会需要静音或者降低音量的功能.比如说某款音乐播放器,当在后台播放时,如果此时有另外的系统通知声音发出,可能播放器会把音量降低,系统声音结束后,再调高:如果有来电了,播放器可能会把音乐暂停,等通话结束后再继续播放.还有,比方说我们在某个场合放个视频,不料音量很大,会引来很多目光(很尴尬),这时候可能我们需要一键静音的功能.那这些功能我们应该如何实现呢? Android播放声音的类为AudioTrack,

  • android系统在静音模式下关闭camera拍照声音的方法

    话说为了防止偷拍,业内有不成文规定,手机公司在做camera时,点击拍照和录像键的时候,必须要有提示音.因此,google也就非常人性化的将播放拍照声音的函数,放到了cameraService中,防止开发者能开发出不响的camera,从而只要调用拍照函数,一定会响,这是写死在framework中的. 话说这个规定在当今有点不合时宜,这不,今天我收到测试提的一个BUG,说是公司的新需求,要求在静音模式下拍照声音也得取消.这么无耻的需求,也许就在我们中国最大的山寨手机公司才会提到.废话不多说,看看是

  • Android简单的利用MediaRecorder进行录音的实例代码

    复制代码 代码如下: package com.ppmeet; import java.io.IOException; import android.app.Activity;  import android.graphics.PixelFormat;  import android.media.MediaRecorder;  import android.os.Bundle;  import android.view.View;  import android.view.View.OnClick

  • Android实现静音检测功能

    本文实例为大家分享了Android实现静音检测的具体代码,供大家参考,具体内容如下 一.背景 做语音评测的时候需要在用户不说话的时候自动停止,这时候就需要判断什么时候不说话处于静音的状态. 二.原理 每次录音的时候可以根据录音的数据计算出音强,设定一个音强值为上限,当音强超过这个值的时候判断为非静音当小于这个值的时候判断为静音,当静音次数连续达到一定的次数的时候就停止录音. 三.代码实现 1.计算音强 /**   * 计算音量   *   * @param buffer 录音数据   * @re

  • Android给通知channel静音的方法实例

    目录 前言 静音 总结 前言 目前各个市场都要求targetsdkversion要不低于26,也就是android 8.0. 相应的影响很多功能,比如通知. 当targetsdkversion >= 26,需要为通知添加channel,如 manager = (NotificationManager) BaseApp.getAppContext() .getSystemService(Context.NOTIFICATION_SERVICE); if (Build.VERSION.SDK_INT

  • Android 判断网络状态对音频静音的实现方法

    在实际应用中,我们不希望在教室网络,打开游戏就显示较大的声音,进而影响上课质量.因此,就需要让app变得智能,让app可以根据使用者当前网络状态,自动进行静音等操作. 本次内容分为两部分:1. 识别网络环境 2. 实现app自动静音. 自动静音 /** * 实现静音功能 */ private void silentSwitchOn() { AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVI

  • Android音频录制MediaRecorder之简易的录音软件实现代码

    使用MediaRecorder的步骤:1.创建MediaRecorder对象2.调用MediRecorder对象的setAudioSource()方法设置声音的来源,一般传入MediaRecorder.MIC3.调用MediaRecorder对象的setOutputFormat()设置所录制的音频文件的格式4.调用MediaRecorder对象的setAudioRncoder().setAudioEncodingBitRate(int bitRate).setAudioSamlingRate(i

  • Android实现录音功能实现实例(MediaRecorder)

    本文介绍了Android实现录音的实例代码(MediaRecorder),分享给大家,具体如下: Android提供了两个API用于录音的实现:MediaRecorder 和 AudioRecord,各有优劣. 1.MediaRecorder 已经集成了录音.编码.压缩等,支持少量的录音音频格式,大概有.aac(API = 16) .amr .3gp 优点:大部分已经集成,直接调用相关接口即可,代码量小 缺点:无法实时处理音频:输出的音频格式不是很多,例如没有输出mp3格式文件 2.AudioR

随机推荐