1. 程式人生 > >Speex語音壓縮和消除回聲

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);

                }
            }
        }
    };
}