Speex语音压缩和消除回声

/**
 * 录音类
 */
public  class AudioRecordUtil {

    private AudioRecord audioRecord;
    private final static int AUDIO_SOURCE= MediaRecorder.AudioSource.MIC;//录取源
    private final static int SAMPLE_RATE=8000;//采样率
    private final static int CHANNEL_CONFIG= AudioFormat.CHANNEL_IN_MONO;//声道配置,和日常左右声道的意思一样
    private final static int AUDIO_FORMAT=AudioFormat.ENCODING_PCM_16BIT;//音频量化所采用的方案
    private int minBufferSize;//最小的缓存长度
    private boolean isRecord=false;//用于标志循环中是否录音
    private int audioFrame;
    private Speex speex;
    private OnAudioStreamCallback onAudioStreamCallback;

    public void setOnAudioStreamCallback(OnAudioStreamCallback onAudioStreamCallback) {
        this.onAudioStreamCallback = onAudioStreamCallback;
    }

    public AudioRecordUtil(){

        minBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,CHANNEL_CONFIG,AUDIO_FORMAT);//获取最小的缓存长度
//        audioRecord = new AudioRecord(AUDIO_SOURCE, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, minBufferSize);//新建AudioRecord对象
        audioRecord= EchoCancel.createAudioRecorder(SAMPLE_RATE,CHANNEL_CONFIG,AUDIO_FORMAT,minBufferSize);
        speex = new Speex();
        speex.init();
        audioFrame=speex.getFrameSize();
        startRecord();
    }

    public synchronized void startRecord(){

        if(!isRecord){
            isRecord=true;
            audioRecord.startRecording();//开始录音
            new Thread(recordRunnable).start();//启动录音线程
        }
    }

    public synchronized void stopRecord(){
        if(isRecord){
            isRecord=false;
            audioRecord.stop();//停止录音
        }
    }

    Runnable recordRunnable = new Runnable() {
        @Override
        public void run() {
            while (isRecord){
                /******************录音(start)*************************/
                short[] audioData = new short[audioFrame];//新建数组用于保存录音数据;
                int readSize=audioRecord.read(audioData, 0, audioFrame);
                /******************录音(end)*************************/



                /*************音频编码压缩(start)*******************/
                byte encodeData[] = new byte[audioFrame];
                readSize = speex.echoCancellationEncode(audioData,encodeData);//进行回声消除和压缩
                /*************音频编码压缩(end)*******************/

                if(onAudioStreamCallback!=null){
                    onAudioStreamCallback.onAudioStream(encodeData,readSize);
                }
            }
        }
    };

    public interface OnAudioStreamCallback{
        void onAudioStream(byte audioData[],int len);
    }

}

 

 

/**
 * 播放类
 */
public class AudioTrackUtil {

    private AudioTrack audioTrack;
    private final static int STREAM_TYPE= AudioManager.STREAM_MUSIC;//播放方式
    private final static int SAMPLE_RATE=8000;//采样率
    private final static int CHANNEL_CONFIG= AudioFormat.CHANNEL_OUT_MONO;//声道配置,和日常左右声道的意思一样
    private final static int AUDIO_FORMAT=AudioFormat.ENCODING_PCM_16BIT;//音频量化所采用的方案
    private final static int MODE=AudioTrack.MODE_STREAM;//播放模式
    private int minBufferSize;//缓存音频的最小尺寸
    private boolean isPlay=false;
    private Queue<AudioData> audioDataQueue=new LinkedList<>();
    private Speex speex;
    private int audioFrame;
    

    public AudioTrackUtil(Context context){
        minBufferSize=AudioTrack.getMinBufferSize(SAMPLE_RATE,CHANNEL_CONFIG,AUDIO_FORMAT);
//        audioTrack = new AudioTrack(STREAM_TYPE,SAMPLE_RATE,CHANNEL_CONFIG,AUDIO_FORMAT,minBufferSize,MODE);
        audioTrack = EchoCancel.createAudioTrack(SAMPLE_RATE,CHANNEL_CONFIG,AUDIO_FORMAT,minBufferSize);
        if (audioTrack!=null) {
            EchoCancel.setplayertospeaker(context);
        }
        speex = new Speex();
        speex.init();
        audioFrame = speex.getFrameSize();
        startPlay();
    }

    public void startPlay(){
        if(!isPlay){
            isPlay=true;
            audioTrack.play();
            new Thread(playRunnable).start();
        }
    }

    public void stopPlay(){
        if(isPlay){
            isPlay = false;
            audioTrack.stop();
        }
    }

    public void write( byte[] audioData, int offsetInBytes, int sizeInBytes){
        AudioData data = new AudioData();
        data.setData(audioData);
        data.setLen(sizeInBytes);
        audioDataQueue.offer(data);
    }

    Runnable playRunnable=new Runnable() {
        @Override
        public void run() {
            while (isPlay){
                if(audioDataQueue!=null&&audioDataQueue.size()>0){
                    /**************读取数据(start)*********************/
                    AudioData data =audioDataQueue.poll();
                    if (data==null)
                    {
                        continue;
                    }
                    /**************读取数据(end)*********************/

                    /*************解码数据(start)**********************/
                    short[] decodeData=new short[audioFrame];
                    int size=speex.decode(data.getData(),decodeData,data.getLen());//数据进行解码
                    /*************解码数据(end)**********************/

                    speex.capture(decodeData);//采集回声,用于回声消除
                    audioTrack.write(decodeData,0,decodeData.length);

                }
            }
        }
    };
}
 

Demo下载链接:https://download.csdn.net/download/hengfeng430/12222581

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值