android voice recording - voice with background no

2019-09-05 10:15发布

问题:

I am developing an voice recording android application. For this I am using the following code. When I record and play it, I am getting recording voice with background noice. How can I get only recording voice. Can anyone help me?

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;

public class RecorderActivity extends Activity {
        private static final int RECORDER_BPP = 16;
        private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
        private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";
        private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
        private static final int RECORDER_SAMPLERATE = 44100;
        private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO;
        private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

        private AudioRecord recorder = null;
        private int bufferSize = 0;
        private Thread recordingThread = null;
        private boolean isRecording = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        setButtonHandlers();
        enableButtons(false);

        bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING);
    }

        private void setButtonHandlers() {
                ((Button)findViewById(R.id.btnStart)).setOnClickListener(btnClick);
        ((Button)findViewById(R.id.btnStop)).setOnClickListener(btnClick);
        }

        private void enableButton(int id,boolean isEnable){
                ((Button)findViewById(id)).setEnabled(isEnable);
        }

        private void enableButtons(boolean isRecording) {
                enableButton(R.id.btnStart,!isRecording);
                enableButton(R.id.btnStop,isRecording);
        }

        private String getFilename(){
                String filepath = Environment.getExternalStorageDirectory().getPath();
                File file = new File(filepath,AUDIO_RECORDER_FOLDER);

                if(!file.exists()){
                        file.mkdirs();
                }

                return (file.getAbsolutePath() + "/" + System.currentTimeMillis() + AUDIO_RECORDER_FILE_EXT_WAV);
        }

        private String getTempFilename(){
                String filepath = Environment.getExternalStorageDirectory().getPath();
                File file = new File(filepath,AUDIO_RECORDER_FOLDER);

                if(!file.exists()){
                        file.mkdirs();
                }

                File tempFile = new File(filepath,AUDIO_RECORDER_TEMP_FILE);

                if(tempFile.exists())
                        tempFile.delete();

                return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE);
        }

        private void startRecording(){
                recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
                                                RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize);

                recorder.startRecording();

                isRecording = true;

                recordingThread = new Thread(new Runnable() {

                        @Override
                        public void run() {
                                writeAudioDataToFile();
                        }
                },"AudioRecorder Thread");

                recordingThread.start();
        }

        private void writeAudioDataToFile(){
                byte data[] = new byte[bufferSize];
                String filename = getTempFilename();
                FileOutputStream os = null;

                try {
                        os = new FileOutputStream(filename);
                } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }

                int read = 0;

                if(null != os){
                        while(isRecording){
                                read = recorder.read(data, 0, bufferSize);

                                if(AudioRecord.ERROR_INVALID_OPERATION != read){
                                        try {
                                                os.write(data);
                                        } catch (IOException e) {
                                                e.printStackTrace();
                                        }
                                }
                        }

                        try {
                                os.close();
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                }
        }

        private void stopRecording(){
                if(null != recorder){
                        isRecording = false;

                        recorder.stop();
                        recorder.release();

                        recorder = null;
                        recordingThread = null;
                }

                copyWaveFile(getTempFilename(),getFilename());
                deleteTempFile();
        }

        private void deleteTempFile() {
                File file = new File(getTempFilename());

                file.delete();
        }

        private void copyWaveFile(String inFilename,String outFilename){
                FileInputStream in = null;
                FileOutputStream out = null;
                long totalAudioLen = 0;
                long totalDataLen = totalAudioLen + 36;
                long longSampleRate = RECORDER_SAMPLERATE;
                int channels = 2;
                long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels/8;

                byte[] data = new byte[bufferSize];

                try {
                        in = new FileInputStream(inFilename);
                        out = new FileOutputStream(outFilename);
                        totalAudioLen = in.getChannel().size();
                        totalDataLen = totalAudioLen + 36;

                        AppLog.logString("File size: " + totalDataLen);

                        WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
                                        longSampleRate, channels, byteRate);

                        while(in.read(data) != -1){
                                out.write(data);
                        }

                        in.close();
                        out.close();
                } catch (FileNotFoundException e) {
                        e.printStackTrace();
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }

        private void WriteWaveFileHeader(
                        FileOutputStream out, long totalAudioLen,
                        long totalDataLen, long longSampleRate, int channels,
                        long byteRate) throws IOException {

                byte[] header = new byte[44];

                header[0] = 'R';  // RIFF/WAVE header
                header[1] = 'I';
                header[2] = 'F';
                header[3] = 'F';
                header[4] = (byte) (totalDataLen & 0xff);
                header[5] = (byte) ((totalDataLen >> 8) & 0xff);
                header[6] = (byte) ((totalDataLen >> 16) & 0xff);
                header[7] = (byte) ((totalDataLen >> 24) & 0xff);
                header[8] = 'W';
                header[9] = 'A';
                header[10] = 'V';
                header[11] = 'E';
                header[12] = 'f';  // 'fmt ' chunk
                header[13] = 'm';
                header[14] = 't';
                header[15] = ' ';
                header[16] = 16;  // 4 bytes: size of 'fmt ' chunk
                header[17] = 0;
                header[18] = 0;
                header[19] = 0;
                header[20] = 1;  // format = 1
                header[21] = 0;
                header[22] = (byte) channels;
                header[23] = 0;
                header[24] = (byte) (longSampleRate & 0xff);
                header[25] = (byte) ((longSampleRate >> 8) & 0xff);
                header[26] = (byte) ((longSampleRate >> 16) & 0xff);
                header[27] = (byte) ((longSampleRate >> 24) & 0xff);
                header[28] = (byte) (byteRate & 0xff);
                header[29] = (byte) ((byteRate >> 8) & 0xff);
                header[30] = (byte) ((byteRate >> 16) & 0xff);
                header[31] = (byte) ((byteRate >> 24) & 0xff);
                header[32] = (byte) (2 * 16 / 8);  // block align
                header[33] = 0;
                header[34] = RECORDER_BPP;  // bits per sample
                header[35] = 0;
                header[36] = 'd';
                header[37] = 'a';
                header[38] = 't';
                header[39] = 'a';
                header[40] = (byte) (totalAudioLen & 0xff);
                header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
                header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
                header[43] = (byte) ((totalAudioLen >> 24) & 0xff);

                out.write(header, 0, 44);
        }

        private View.OnClickListener btnClick = new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                        switch(v.getId()){
                                case R.id.btnStart:{
                                        AppLog.logString("Start Recording");

                                        enableButtons(true);
                                        startRecording();

                                        break;
                                }
                                case R.id.btnStop:{
                                        AppLog.logString("Start Recording");

                                        enableButtons(false);
                                        stopRecording();

                                        break;
                                }
                        }
                }
        }; 
}

回答1:

Are you testing this with the emulator, or on an actual device (if so, which device)? The acoustic tuning (which includes gain control, noise reduction, etc) will be specific to a given platform and product, and is not something you can change.

Jellybean includes APIs to let applications apply certain acoustic filters on recordings, and a noise suppressor is one of those. However, by using that API you're limiting your app to only function correctly on devices running Jellybean or later (and not even all of those devices might actually implement this functionality).

Another possibility would be to include a noise suppressor in your app. I think e.g. Speex includes noise supressing functionality, but it's geared towards low-bitrate speech encoding.



回答2:

If you want to NoiseSuppressor then you can use this:

// The following would take effect only on Jelly Bean and higher.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        Log.i("Trying to clean up audio because running on SDK " + Build.VERSION.SDK_INT);

    if (noise && NoiseSuppressor.create(getAudioSessionId()) == null) {
        Log.i("NoiseSuppressor not present :(");
    } else {
        Log.i("NoiseSuppressor enabled!");
    }

    if (gain && AutomaticGainControl.create(getAudioSessionId()) == null) {
        Log.i("AutomaticGainControl not present :(");
    } else {
        Log.i("AutomaticGainControl enabled!");
    }

    if (echo && AcousticEchoCanceler.create(getAudioSessionId()) == null) {
        Log.i("AcousticEchoCanceler not present :(");
    } else {
        Log.i("AcousticEchoCanceler enabled!");
    }
}

This code can remove background noise , echo and gain.