Increase volume output of recorded audio

Thanks to Hartmut and beworker for the solution. Hartmut's code did worked at near 12-14 dB. I did merged the code from the sonic library too to increase volume, but that increase too much noise and distortion, so I kept the volume at 1.5-2.0 and instead tried to increase gain. I got decent sound volume which doesn't sound too loud in phone, but when listened on a PC sounds loud enough. Looks like that's the farthest I could go.

I am posting my final code to increase the loudness. Be aware that using increasing mVolume increases too much noise. Try to increase gain instead.

private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener() {
        @Override
        public void onPeriodicNotification(AudioRecord recorder) {
            aRecorder.read(bBuffer, bBuffer.capacity()); // Fill buffer
            if (getState() != State.RECORDING)
                return;
            try {
                if (bSamples == 16) {
                    shBuffer.rewind();
                    int bLength = shBuffer.capacity(); // Faster than accessing buffer.capacity each time
                    for (int i = 0; i < bLength; i++) { // 16bit sample size
                        short curSample = (short) (shBuffer.get(i) * gain);
                        if (curSample > cAmplitude) { // Check amplitude
                            cAmplitude = curSample;
                        }
                        if(mVolume != 1.0f) {
                            // Adjust output volume.
                            int fixedPointVolume = (int)(mVolume*4096.0f);
                            int value = (curSample*fixedPointVolume) >> 12;
                            if(value > 32767) {
                                value = 32767;
                            } else if(value < -32767) {
                                value = -32767;
                            }
                            curSample = (short)value;
                            /*scaleSamples(outputBuffer, originalNumOutputSamples, numOutputSamples - originalNumOutputSamples,
                                    mVolume, nChannels);*/
                        }
                        shBuffer.put(curSample);
                    }
                } else { // 8bit sample size
                    int bLength = bBuffer.capacity(); // Faster than accessing buffer.capacity each time
                    bBuffer.rewind();
                    for (int i = 0; i < bLength; i++) {
                        byte curSample = (byte) (bBuffer.get(i) * gain);
                        if (curSample > cAmplitude) { // Check amplitude
                            cAmplitude = curSample;
                        }
                        bBuffer.put(curSample);
                    }
                }
                bBuffer.rewind();
                fChannel.write(bBuffer); // Write buffer to file
                payloadSize += bBuffer.capacity();
            } catch (IOException e) {
                e.printStackTrace();
                Log.e(NoobAudioRecorder.class.getName(), "Error occured in updateListener, recording is aborted");
                stop();
            }
        }

        @Override
        public void onMarkerReached(AudioRecord recorder) {
            // NOT USED
        }
    };

simple use MPEG_4 format

To increase the call recording volume use AudioManager as follows:

int deviceCallVol;
AudioManager audioManager;

Start Recording:

   audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
//get the current volume set
deviceCallVol = audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
//set volume to maximum
        audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), 0);

   recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
   recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
   recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
   recorder.setAudioEncodingBitRate(32);
   recorder.setAudioSamplingRate(44100);

Stop Recording:

//revert volume to initial state

 audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, deviceCallVol, 0);

You obviously have the AudioRecord stuff running, so I skip the decision for sampleRate and inputSource. The main point is that you need to appropriately manipulate each sample of your recorded data in your recording loop to increase the volume. Like so:

    int minRecBufBytes = AudioRecord.getMinBufferSize( sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT );
    // ...
    audioRecord = new AudioRecord( inputSource, sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, minRecBufBytes );

    // Setup the recording buffer, size, and pointer (in this case quadruple buffering)
    int recBufferByteSize = minRecBufBytes*2;
    byte[] recBuffer = new byte[recBufferByteSize];
    int frameByteSize = minRecBufBytes/2;
    int sampleBytes = frameByteSize;
    int recBufferBytePtr = 0;

    audioRecord.startRecording();

    // Do the following in the loop you prefer, e.g.
    while ( continueRecording ) {
        int reallySampledBytes = audioRecord.read( recBuffer, recBufferBytePtr, sampleBytes );

        int i = 0;
        while ( i < reallySampledBytes ) {
            float sample = (float)( recBuffer[recBufferBytePtr+i  ] & 0xFF
                                  | recBuffer[recBufferBytePtr+i+1] << 8 );

            // THIS is the point were the work is done:
            // Increase level by about 6dB:
            sample *= 2;
            // Or increase level by 20dB:
            // sample *= 10;
            // Or if you prefer any dB value, then calculate the gain factor outside the loop
            // float gainFactor = (float)Math.pow( 10., dB / 20. );    // dB to gain factor
            // sample *= gainFactor;

            // Avoid 16-bit-integer overflow when writing back the manipulated data:
            if ( sample >= 32767f ) {
                recBuffer[recBufferBytePtr+i  ] = (byte)0xFF;
                recBuffer[recBufferBytePtr+i+1] =       0x7F;
            } else if ( sample <= -32768f ) {
                recBuffer[recBufferBytePtr+i  ] =       0x00;
                recBuffer[recBufferBytePtr+i+1] = (byte)0x80;
            } else {
                int s = (int)( 0.5f + sample );  // Here, dithering would be more appropriate
                recBuffer[recBufferBytePtr+i  ] = (byte)(s & 0xFF);
                recBuffer[recBufferBytePtr+i+1] = (byte)(s >> 8 & 0xFF);
            }
            i += 2;
        }

        // Do other stuff like saving the part of buffer to a file
        // if ( reallySampledBytes > 0 ) { ... save recBuffer+recBufferBytePtr, length: reallySampledBytes

        // Then move the recording pointer to the next position in the recording buffer
        recBufferBytePtr += reallySampledBytes;

        // Wrap around at the end of the recording buffer, e.g. like so:
        if ( recBufferBytePtr >= recBufferByteSize ) {
            recBufferBytePtr = 0;
            sampleBytes = frameByteSize;
        } else {
            sampleBytes = recBufferByteSize - recBufferBytePtr;
            if ( sampleBytes > frameByteSize )
                sampleBytes = frameByteSize;
        }
    }