Search code examples
androidaudioaudiorecordaudiotrackandroid-audiorecord

How to increase amplify AudioTrack?


I have the following code:

public class MainActivity extends Activity {
    private int freq = 8000;
    private AudioRecord audioRecord = null;
    private Thread Rthread = null;

    int PERMISSION_ALL = 1;
    String[] PERMISSIONS = {Manifest.permission.RECORD_AUDIO};

    private AudioTrack audioTrack = null;
    byte[] buffer = new byte[freq];
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(!hasPermissions(this, PERMISSIONS)){
            ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
        }

        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
        final int bufferSize = AudioRecord.getMinBufferSize(freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT);


        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                MediaRecorder.AudioEncoder.AMR_NB, bufferSize);

        audioTrack = new AudioTrack(AudioManager.ROUTE_HEADSET, freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                MediaRecorder.AudioEncoder.AMR_NB, bufferSize,
                AudioTrack.MODE_STREAM);

        LoudnessEnhancer enhancer = new LoudnessEnhancer(audioTrack.getAudioSessionId());

        enhancer.setTargetGain(100);
        enhancer.setEnabled(true);


        audioTrack.setPlaybackRate(freq);
        buffer = new byte[bufferSize];
        audioRecord.startRecording();
        Log.i("info", "Audio Recording started");
        audioTrack.play();
        Log.i("info", "Audio Playing started");
        Rthread = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        audioRecord.read(buffer, 0, bufferSize);
                        audioTrack.write(buffer, 0, buffer.length);

                    } catch (Throwable t) {
                        Log.e("Error", "Read write failed");
                        t.printStackTrace();
                    }
                }
            }
        });
        Rthread.start();
    }

    public static boolean hasPermissions(Context context, String... permissions) {
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }
}

This code is able to read input from the mic and play it back on a speaker/connected headphones. So far, so good. Now, I need to amplify the volume of the input. I've tried the solution proposed here, but I just end up getting really distorted audio. I also tried the LoudnessEnhancer, but it doesn't seem to have any effect.


Solution

  • Okay, I managed to get the LoudnessEnhancer working. I know it's a huge gain value in there, but I need a lot of gain on this one. Here's the updated code for anyone else who might have a similar problem.

    public class MainActivity extends Activity {
        private int freq = 8000;
        private AudioRecord audioRecord = null;
        private Thread Rthread = null;
    
        int PERMISSION_ALL = 1;
        String[] PERMISSIONS = {Manifest.permission.RECORD_AUDIO};
    
        private AudioTrack audioTrack = null;
        byte[] buffer = new byte[freq];
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            if(!hasPermissions(this, PERMISSIONS)){
                ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
            }
    
            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
            final int bufferSize = AudioRecord.getMinBufferSize(freq,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT);
    
    
            audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, freq,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    MediaRecorder.AudioEncoder.AMR_NB, bufferSize);
    
            audioTrack = new AudioTrack(AudioManager.ROUTE_HEADSET, freq,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    MediaRecorder.AudioEncoder.AMR_NB, bufferSize,
                    AudioTrack.MODE_STREAM);
    
            LoudnessEnhancer enhancer = new LoudnessEnhancer(audioTrack.getAudioSessionId());
            NoiseSuppressor.create(audioTrack.getAudioSessionId());
            AcousticEchoCanceler.create(audioTrack.getAudioSessionId());
    
            enhancer.setTargetGain(10000);
            enhancer.setEnabled(true);
    
    
            audioTrack.setPlaybackRate(freq);
            buffer = new byte[bufferSize];
            audioRecord.startRecording();
            Log.i("info", "Audio Recording started");
            audioTrack.play();
            Log.i("info", "Audio Playing started");
            Rthread = new Thread(new Runnable() {
                public void run() {
                    while (true) {
                        try {
                            audioRecord.read(buffer, 0, bufferSize);
                            audioTrack.write(buffer, 0, buffer.length);
    
                        } catch (Throwable t) {
                            Log.e("Error", "Read write failed");
                            t.printStackTrace();
                        }
                    }
                }
            });
            Rthread.start();
        }
    
        public static boolean hasPermissions(Context context, String... permissions) {
            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
                for (String permission : permissions) {
                    if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                        return false;
                    }
                }
            }
            return true;
        }
    }