AudioRecord 增益控制获得嘈杂的声音

Posted

技术标签:

【中文标题】AudioRecord 增益控制获得嘈杂的声音【英文标题】:AudioRecord gain control getting noisy sound 【发布时间】:2014-04-08 20:22:18 【问题描述】:

我经历了堆栈溢出问题apply gain with variation 与我想知道的相同但是找不到答案我尝试了他们在上面问题链接中提到的答案没有适当或准确的解决方案我仍然得到声音(比如对讲机)。任何做得好的人。

 public class Mediarec extends Activity 

public static final int SAMPLE_RATE = 16000;

private AudioRecord mRecorder;
private File mRecording;
private short[] mBuffer;
private final String startRecordingLabel = "Start recording";
private final String stopRecordingLabel = "Stop recording";
private boolean mIsRecording = false;
private ProgressBar mProgressBar;
short iGain= (short)1.0f;
CheckBox gain;

@Override
public void onCreate(final Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.fragment_mediarec);

    initRecorder();

    gain = (CheckBox) findViewById(R.id.checkBox1);
    mProgressBar = (ProgressBar) findViewById(R.id.progressBar);

    final Button button = (Button) findViewById(R.id.start);
    button.setText(startRecordingLabel);

    gain.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 

           @Override
           public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) 

               if(gain.isChecked())
               
                   
                   iGain = (short) Math.pow(10, 9.0 / 20.0 ) ;
                  // iGain = (short)2.0f;
               
               else
               
                   iGain = (short) Math.pow(10, 3 / 20.0 ) ;
               
           
        );
    
    button.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(final View v) 
            if (!mIsRecording) 
                button.setText(stopRecordingLabel);
                mIsRecording = true;
                mRecorder.startRecording();
                mRecording = getFile("raw");
                startBufferedWrite(mRecording);
            
            else 
                button.setText(startRecordingLabel);
                mIsRecording = false;
                mRecorder.stop();
                File waveFile = getFile("wav");
                try 
                    rawToWave(mRecording, waveFile);
                 catch (IOException e) 
                    Toast.makeText(Mediarec.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                
                Toast.makeText(Mediarec.this, "Recorded to " + waveFile.getName(),
                        Toast.LENGTH_SHORT).show();
            
        
    );


@Override
public void onDestroy() 
    mRecorder.release();
    super.onDestroy();


private void initRecorder() 
    int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT);
    mBuffer = new short[bufferSize];
    mRecorder = new AudioRecord(MediaRecorder.Audiosource.MIC, SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT, bufferSize);


private void startBufferedWrite(final File file) 
    new Thread(new Runnable() 
        @Override
        public void run() 
            DataOutputStream output = null;
            try 
                output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
                while (mIsRecording) 
                    double sum = 0;
                    int readSize = mRecorder.read(mBuffer, 0, mBuffer.length);
                    for (int i = 0; i < readSize; i++) 
                        output.writeShort(mBuffer[i]);
                        sum += mBuffer[i] * mBuffer[i];
                    
                    if (readSize > 0) 
                        final double amplitude = sum / readSize;
                        mProgressBar.setProgress((int) Math.sqrt(amplitude));
                    
                
             catch (IOException e) 
                Toast.makeText(Mediarec.this, e.getMessage(), Toast.LENGTH_SHORT).show();
             finally 
                mProgressBar.setProgress(0);
                if (output != null) 
                    try 
                        output.flush();
                     catch (IOException e) 
                        Toast.makeText(Mediarec.this, e.getMessage(), Toast.LENGTH_SHORT)
                                .show();
                     finally 
                        try 
                            output.close();
                         catch (IOException e) 
                            Toast.makeText(Mediarec.this, e.getMessage(), Toast.LENGTH_SHORT)
                                    .show();
                        
                    
                
            
        
    ).start();


private void rawToWave(final File rawFile, final File waveFile) throws IOException 

    byte[] rawData = new byte[(int) rawFile.length()];
    DataInputStream input = null;
    try 
        input = new DataInputStream(new FileInputStream(rawFile));
        input.read(rawData);
     finally 
        if (input != null) 
            input.close();
        
    

    DataOutputStream output = null;
    try 
        output = new DataOutputStream(new FileOutputStream(waveFile));
        // WAVE header
        // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
        writeString(output, "RIFF"); // chunk id
        writeInt(output, 36 + rawData.length); // chunk size
        writeString(output, "WAVE"); // format
        writeString(output, "fmt "); // subchunk 1 id
        writeInt(output, 16); // subchunk 1 size
        writeShort(output, (short) 1); // audio format (1 = PCM)
        writeShort(output, (short) 1); // number of channels
        writeInt(output, SAMPLE_RATE); // sample rate
        writeInt(output, SAMPLE_RATE * 2); // byte rate
        writeShort(output, (short) 2); // block align
        writeShort(output, (short) 16); // bits per sample
        writeString(output, "data"); // subchunk 2 id
        writeInt(output, rawData.length); // subchunk 2 size
        // Audio data (conversion big endian -> little endian)
        short[] shorts = new short[rawData.length / 2];
        ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
        ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2);
        
    
        for (short s : shorts) 
            
            //Apply Gain
            s *= iGain;
            
                             if(s>32767)
            
                s=32767;
            
            else if(s<-32768)
            
                s=-32768;
            
            bytes.putShort(s);
        
        output.write(bytes.array());
     finally 
        if (output != null) 
            output.close();
        
    


private File getFile(final String suffix) 
    Time time = new Time();
    time.setToNow();
    return new File(Environment.getExternalStorageDirectory(), time.format("%Y%m%d%H%M%S") + "." + suffix);


private void writeInt(final DataOutputStream output, final int value) throws IOException 
    output.write(value >> 0);
    output.write(value >> 8);
    output.write(value >> 16);
    output.write(value >> 24);


private void writeShort(final DataOutputStream output, final short value) throws IOException 
    output.write(value >> 0);
    output.write(value >> 8);


private void writeString(final DataOutputStream output, final String value) throws IOException 
    for (int i = 0; i < value.length(); i++) 
        output.write(value.charAt(i));
    

声音非常小 寻找解决方案如何应用增益变化

【问题讨论】:

【参考方案1】:

这是音频增益或麦克风音量增益的完整代码

忽略部分与此无关的代码

public class MainActivity extends Activity 

public static final int SAMPLE_RATE = 16000;

private AudioRecord mRecorder;
private File mRecording;
private short[] mBuffer;
private final String startRecordingLabel = "Start recording";
private final String stopRecordingLabel = "Stop recording";
private boolean mIsRecording = false;
private ProgressBar mProgressBar;
float iGain = 1.0f;
CheckBox gain;

protected int bitsPerSamples = 16;

@Override
public void onCreate(final Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.fragment_main);

    initRecorder();

    Button bluetooth = (Button)findViewById(R.id.blue);
    gain = (CheckBox) findViewById(R.id.checkBox1);
    mProgressBar = (ProgressBar) findViewById(R.id.progressBar);

    final Button button = (Button) findViewById(R.id.start);
    button.setText(startRecordingLabel);

    bluetooth.setOnClickListener(new View.OnClickListener() 

        @Override
        public void onClick(View v) 
            // TODO Auto-generated method stub
            Intent i = new Intent("");
        
    );
    gain.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 

        @Override
        public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) 

            if (gain.isChecked()) 
                iGain = 5.0f;

             else 
                iGain = 2.0f;
            
        
    );

    button.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(final View v) 
            if (!mIsRecording) 
                button.setText(stopRecordingLabel);
                mIsRecording = true;
                mRecorder.startRecording();
                mRecording = getFile("raw");
                startBufferedWrite(mRecording);
             else 
                button.setText(startRecordingLabel);
                mIsRecording = false;
                mRecorder.stop();
                File waveFile = getFile("wav");
                try 
                    rawToWave(mRecording, waveFile);
                 catch (IOException e) 
                    Toast.makeText(MainActivity.this, e.getMessage(),
                            Toast.LENGTH_SHORT).show();
                
                Toast.makeText(MainActivity.this,
                        "Recorded to " + waveFile.getName(),
                        Toast.LENGTH_SHORT).show();
            
        
    );


@Override
public void onDestroy() 
    mRecorder.release();
    super.onDestroy();


private void initRecorder() 
    int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
            AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
    mBuffer = new short[bufferSize];
    mRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE,
            AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,
            bufferSize);


private void startBufferedWrite(final File file) 
    new Thread(new Runnable() 
        @Override
        public void run() 
            DataOutputStream output = null;
            try 
                output = new DataOutputStream(new BufferedOutputStream(
                        new FileOutputStream(file)));
                while (mIsRecording) 
                    double sum = 0;

                    int readSize = mRecorder.read(mBuffer, 0,
                            mBuffer.length);

                    final int bytesPerSample = bitsPerSamples / 8;
                    final int emptySpace = 64 - bitsPerSamples;
                    int byteIndex = 0;
                    int byteIndex2 = 0;
                    int temp = 0;
                    int mLeftTemp = 0;
                    int mRightTemp = 0;
                    int a = 0;
                    int x = 0;

                    for (int frameIndex = 0; frameIndex < readSize; frameIndex++) 

                        for (int c = 0; c < 1; c++) 

                            if (iGain != 1) 

                                long accumulator = 0;
                                for (int b = 0; b < bytesPerSample; b++) 

                                    accumulator += ((long) (mBuffer[byteIndex++] & 0xFF)) << (b * 8 + emptySpace);
                                

                                double sample = ((double) accumulator / (double) Long.MAX_VALUE);
                                sample *= iGain;
                                int intValue = (int) ((double) sample * (double) Integer.MAX_VALUE);

                                for (int i = 0; i < bytesPerSample; i++) 
                                    mBuffer[i + byteIndex2] = (byte) (intValue >>> ((i + 2) * 8) & 0xff);
                                
                                byteIndex2 += bytesPerSample;

                            
                        // end for(channel)

                        // mBuffer[frameIndex] *=iGain;
                        if (mBuffer[frameIndex] > 32765) 
                            mBuffer[frameIndex] = 32767;

                         else if (mBuffer[frameIndex] < -32767) 
                            mBuffer[frameIndex] = -32767;
                        
                        output.writeShort(mBuffer[frameIndex]);
                        sum += mBuffer[frameIndex] * mBuffer[frameIndex];

                    

                    if (readSize > 0) 
                        final double amplitude = sum / readSize;
                        mProgressBar.setProgress((int) Math.sqrt(amplitude));
                    
                
             catch (IOException e) 
                Toast.makeText(MainActivity.this, e.getMessage(),
                        Toast.LENGTH_SHORT).show();
             finally 
                mProgressBar.setProgress(0);
                if (output != null) 
                    try 
                        output.flush();
                     catch (IOException e) 
                        Toast.makeText(MainActivity.this, e.getMessage(),
                                Toast.LENGTH_SHORT).show();
                     finally 
                        try 
                            output.close();
                         catch (IOException e) 
                            Toast.makeText(MainActivity.this, e.getMessage(),
                                    Toast.LENGTH_SHORT).show();
                        
                    
                
            
        
    ).start();


private void rawToWave(final File rawFile, final File waveFile)
        throws IOException 

    byte[] rawData = new byte[(int) rawFile.length()];
    DataInputStream input = null;
    try 

        input = new DataInputStream(new FileInputStream(rawFile));
        input.read(rawData);
     finally 
        if (input != null) 
            input.close();
        
    

    DataOutputStream output = null;
    try 
        output = new DataOutputStream(new FileOutputStream(waveFile));
        // WAVE header
        // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
        writeString(output, "RIFF"); // chunk id
        writeInt(output, 36 + rawData.length); // chunk size
        writeString(output, "WAVE"); // format
        writeString(output, "fmt "); // subchunk 1 id
        writeInt(output, 16); // subchunk 1 size
        writeShort(output, (short) 1); // audio format (1 = PCM)
        writeShort(output, (short) 1); // number of channels
        writeInt(output, SAMPLE_RATE); // sample rate
        writeInt(output, SAMPLE_RATE * 2); // byte rate
        writeShort(output, (short) 2); // block align
        writeShort(output, (short) 16); // bits per sample
        writeString(output, "data"); // subchunk 2 id
        writeInt(output, rawData.length); // subchunk 2 size
        // Audio data (conversion big endian -> little endian)
        short[] shorts = new short[rawData.length / 2];
        ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN)
                .asShortBuffer().get(shorts);
        ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2);

        for (short s : shorts) 

            // Apply Gain
            /*
             * s *= iGain; if(s>32767)  s=32767;  else if(s<-32768) 
             * s=-32768; 
             */
            bytes.putShort(s);
        
        output.write(bytes.array());
     finally 
        if (output != null) 
            output.close();
        
    


private File getFile(final String suffix) 
    Time time = new Time();
    time.setToNow();
    return new File(Environment.getExternalStorageDirectory(),
            time.format("%Y%m%d%H%M%S") + "." + suffix);






private void writeInt(final DataOutputStream output, final int value)
        throws IOException 
    output.write(value >> 0);
    output.write(value >> 8);
    output.write(value >> 16);
    output.write(value >> 24);


private void writeShort(final DataOutputStream output, final short value)
        throws IOException 
    output.write(value >> 0);
    output.write(value >> 8);


private void writeString(final DataOutputStream output, final String value)
        throws IOException 
    for (int i = 0; i < value.length(); i++) 
        output.write(value.charAt(i));
    


【讨论】:

以上是关于AudioRecord 增益控制获得嘈杂的声音的主要内容,如果未能解决你的问题,请参考以下文章

Android 4.4中AudioRecord用例 - 录制系统内置声音

Android:使用 audiorecord 类录制音频播放快进

Audiorecord.read() 中值的含义

MediaRecord录像声音小问题

MediaRecord录像声音小问题

AVAudioPlayer 多重声音嘈杂