Amplified AudioRecord not working on Samsung device

I wrote code to record an audio file with AudioRecordand when I write a file to an SD card, I make two versions.

Version 1 The recorded file is saved on the SD card as it is.

Version 2 I use the Gain function for the recorded file and save it to the SD card.

This works amazingly on Sony Ericson mobile phones. Also, the sound volume increases significantly.

But I'm trying my best to get it working on Samsung devices.

when I play the recorded file it sounds like Talking Tom: P

Initially, I thought that Samusung did not like the combinations that I used to create AudioRecorder.

So, I used the following approach, in which I loop into an accessible configuration and use the best configuration to initialize AudioRecord.

public AudioRecord findAudioRecord() {
    for (int rate: mSampleRates) {
        for (short audioFormat: new short[] {
            AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT
        }) {
            for (short channelConfig: new short[] {
                AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO
            }) {
                try {
                    Log.i("vipul", "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig);
                    int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);

                    if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                        // check if we can instantiate and have a success
                        AudioRecord recorder = new AudioRecord(
                        AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);

                        if (recorder.getState() == AudioRecord.STATE_INITIALIZED) return recorder;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    return null;
}

Below is the code that works well on Sony mobile phones. But the struggle to work with Samsung devices.

public class EnvironmentRecorder extends Activity implements OnClickListener {

    private static final int RECORDER_BPP = 16;
    private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
    private static final String AUDIO_RECORDER_FOLDER = "MyRecorder";
    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 Button start, stop;
    private AudioRecord recorder = null;
    private int bufferSize = 0;
    private Thread recordingThread = null;
    private boolean isRecording = false;
    private static int[] mSampleRates = new int[] {
        8000, 11025, 22050, 44100
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        start = (Button) findViewById(R.id.start);
        stop = (Button) findViewById(R.id.stop);
        start.setOnClickListener(this);
        stop.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.start:
            startRecord();
            break;
        case R.id.stop:
            stopRecording();
            break;
        }
    }

    public EnvironmentRecorder() {

        try {
            bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

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

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

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

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

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

        return (file.getAbsolutePath() + "/" + "Gained" + 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);
    }

    public AudioRecord findAudioRecord() {
        for (int rate: mSampleRates) {
            for (short audioFormat: new short[] {
                AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT
            }) {
                for (short channelConfig: new short[] {
                    AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO
                }) {
                    try {
                        Log.v("vipul", "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig);
                        int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);

                        if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                            // check if we can instantiate and have a success
                            AudioRecord recorder = new AudioRecord(
                            AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);

                            if (recorder.getState() == AudioRecord.STATE_INITIALIZED) return recorder;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return null;
    }

    public void startRecord() {
        /*
         * recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
         * RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING,
         * bufferSize);
         */

        recorder = findAudioRecord();

        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) {
            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();
            }
        }
    }

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

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

            recorder = null;
            recordingThread = null;
            copyWaveFile(getTempFilename(), getFilename1(), getFilename2());
            deleteTempFile();
        }

    }

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

        file.delete();
    }

    private void copyWaveFile(String inFilename, String outFileName1, String outFileName2) {
        FileInputStream in = null;
        FileOutputStream out1 = null, out2 = 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);
            out1 = new FileOutputStream(outFileName1);
            out2 = new FileOutputStream(outFileName2);
            totalAudioLen = in .getChannel().size();
            totalDataLen = totalAudioLen + 36;

            WriteWaveFileHeader(out1, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate);
            WriteWaveFileHeader(out2, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate);

            while ( in .read(data) != -1) {

                out1.write(data); // Writing Non-Gained Data

                float rGain = 2.5f;
                for (int i = 0; i < data.length / 2; i++) {

                    short curSample = getShort(data[i * 2], data[i * 2 + 1]);
                    if (rGain != 1) {
                        // apply gain
                        curSample *= rGain;
                        // convert back from short sample that was "gained" to
                        // byte data
                        byte[] a = getByteFromShort(curSample);
                        // modify buffer to contain the gained sample
                        data[i * 2] = a[0];
                        data[i * 2 + 1] = a[1];
                    }

                }

                out2.write(data); // Writing Gained Data
            }
            out1.close();
            out2.close(); in .close();

            Toast.makeText(this, "Done!!", Toast.LENGTH_LONG).show();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private short getShort(byte argB1, byte argB2) {
        return (short)((argB1 & 0xff) | (argB2 << 8));

    }

    private byte[] getByteFromShort(short x) {
        // variant 1 - noise
        byte[] a = new byte[2];
        a[0] = (byte)(x & 0xff);
        a[1] = (byte)((x >> 8) & 0xff);

        // variant 2 - noise and almost broke my ears - very loud
        // ByteBuffer buffer = ByteBuffer.allocate(2);
        // buffer.putShort(x);
        // buffer.flip();

        return a;
    }

    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';
        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';
        header[13] = 'm';
        header[14] = 't';
        header[15] = ' ';
        header[16] = 16;
        header[17] = 0;
        header[18] = 0;
        header[19] = 0;
        header[20] = 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);
        header[33] = 0;
        header[34] = RECORDER_BPP;
        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);
    }

}

I would like to know if I need to add an additional site to make AudioRecord convenient for Samsung devices.

+5
source share
2 answers

We are also struggling with audio recording on some Samsung Android devices. Unfortunately, it seems to be very broken, since even different versions of the same phone model behave differently with the same code base.

Here are my current findings, hoping you find something useful:

1. Broken initialization:

, , , , , Samsung Galaxy Young Ace Android 2.3 , AudioRecord, , , . reset .

2.

Galaxy Ace, @11025Hz, 16- . Ace AudioRecord , "". , , - !

3. .

Galaxy Young Galaxy Ace @44,100 ( , ) , . , ( , consecuent "jageddnes" ).

4. 44,100 .

Galaxy Young Galaxy Ace @44,100 . ( , ), . @8,000Hz, 16,000Hz 48,000Hz . , Android, 44 100 - , .

5. OpenSL .

NDK OpenSL . , AudioRecorder OpenSL, , .

, , - , .

- , , , . =)

+6

u, . .

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));
    }
}
}
+1

All Articles