15

I am developing an application like talking tom, every thing is working fine just the audio recording making problems on some devices, Audio is also working fine on my hdpi device but whenever i run it on samsung tab 7 or tab 10 or any other phone, on some devices its continuously listening the audio and on some devices not listen at all, I am using following code for audio recording.

private int RECORDER_CHANNELS = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private int RECORDER_SAMPLERATE = 44100;
private byte RECORDER_BPP = (byte) 16;
private AudioRecord audioRecorder;
private int detectVoice= 350;

public class analyzeAudio extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        Log.e("Play", "on Pre");

    }

    @Override
    protected Void doInBackground(Void... voids) {

        try {
            // Get the minimum buffer size required for the successful creation of an AudioRecord object.
            int bufferSizeInBytes = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS,
                    RECORDER_AUDIO_ENCODING);

            bufferSizeInBytes = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
            // Initialize Audio Recorder.
            audioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, RECORDER_SAMPLERATE,
                    RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING, bufferSizeInBytes);

            // Start Recording.
            audioRecorder.startRecording();

            int numberOfReadBytes = 0;
            byte audioBuffer[] = new byte[bufferSizeInBytes];
            boolean recording = false;
            float tempFloatBuffer[] = new float[3];
            int tempIndex = 0;
            int totalReadBytes = 0;
            byte totalByteBuffer[] = new byte[60 * 44100 * 2];

            // While data come from microphone.
            boolean isListening = true;
            while (true) {
                float totalAbsValue = 0.0f;
                short sample = 0;

                numberOfReadBytes = audioRecorder.read(audioBuffer, 0, bufferSizeInBytes);

                // Analyze Sound.
                for (int i = 0; i < bufferSizeInBytes; i += 2) {
                    sample = (short) ((audioBuffer[i]) | audioBuffer[i + 1] << 8);
                    totalAbsValue += Math.abs(sample) / (numberOfReadBytes / 2);
                }

                // Analyze temp buffer.
                tempFloatBuffer[tempIndex % 3] = totalAbsValue;
                float temp = 0.0f;
                for (int i = 0; i < 3; ++i)
                    temp += tempFloatBuffer[i];

                if ((temp >= 0 && temp <= detectVoice) && recording == false) {
                    Log.i("TAG", "1");
                    tempIndex++;
                    continue;
                }

                if (temp > detectVoice && recording == false) {
                    Log.i("TAG", "2");
                    if (isPlaying) {
                        audioRecorder.release();
                        break;
                    }
                    recording = true;

                    if (isListening) {
                        finishIdleAnimation();
                        isListening = false;
                        isPlaying = true;
                        currentAnimationId = Constants.animHearout;
                        _index = 0;
                        if (_timer != null) {
                            _timer.cancel();
                        }
                        _timer = new Timer();
                        _timer.schedule(new TickClass(), 7, dealyTime(7, 1));

                    } else {
                        Log.e("Caceling", "Yes + isPlaying" + isPlaying);
                        new analyzeAudio().cancel(true);
                    }
                }

                if ((temp >= 0 && temp <= detectVoice) && recording == true) {
                    Log.i("TAG", "Save audio to file.");

                    // Save audio to file.
                    String filepath = Environment.getExternalStorageDirectory().getPath();
                    File file = new File(filepath, "AudioRecorder");
                    if (!file.exists())
                        file.mkdirs();

                    String fn = file.getAbsolutePath() + "/" + "temp" + ".wav";
                    long totalAudioLen = 0;
                    long totalDataLen = totalAudioLen + 36;
                    long longSampleRate = RECORDER_SAMPLERATE;
                    int channels = 1;
                    long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels / 8;
                    totalAudioLen = totalReadBytes;
                    totalDataLen = totalAudioLen + 36;
                    byte finalBuffer[] = new byte[totalReadBytes + 44];

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

                    for (int i = 0; i < totalReadBytes; ++i)
                        finalBuffer[44 + i] = totalByteBuffer[i];

                    FileOutputStream out;
                    try {
                        out = new FileOutputStream(fn);
                        try {
                            out.write(finalBuffer);
                            out.close();
                            isRecorded = true;
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                    } catch (FileNotFoundException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }


                    tempIndex++;
                    break;
                }

                // -> Recording sound here.
                Log.i("TAG", "Recording Sound.");
                for (int i = 0; i < numberOfReadBytes; i++)
                    totalByteBuffer[totalReadBytes + i] = audioBuffer[i];
                totalReadBytes += numberOfReadBytes;

                tempIndex++;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {

        Log.e("Play", "on POst");
        if (isRecorded) {
            currentAnimationId = Constants.animHearoutend;
            _index = 8;
            if (_timer != null) {
                _timer.cancel();
            }
            _timer = new Timer();
            _timer.schedule(new TickClass(), 4, dealyTime(4, 1));
            playFromSdCard();
        }
    }
}
arslan haktic
  • 4,348
  • 4
  • 22
  • 35

3 Answers3

6

If you force an arbitrary sample rate on a device wich doesen't support it, you are going to have troubles.

I suggest you to check and set a valid sample-rate for the running device (instead of hardcoding it to 44.1Khz).

Take a look here for some hints about how to check available sample-rates.

Community
  • 1
  • 1
bonnyz
  • 13,458
  • 5
  • 46
  • 70
  • I tried to follow the link you provided. I have written code above accordingly (i added that code to the question itself). But it is still not working? – NoviceMe Apr 13 '15 at 21:25
2

Put this code to check whether the samplerate and audio format supported in your device . Check the combination and see which one is working for you

private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 44100 };

    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.d(TAG, "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: "
                                    + channelConfig);
                            int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);

                            if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                                Log.d(TAG, "Found rate " + rate + "Hz, bits: " + audioFormat + ", channel: "
                                        + channelConfig);

                      Log.d(TAG, "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: "
                                    + channelConfig +" supported");


                            }
                        } catch (Exception e) {
                            Log.e(TAG, rate + "Exception, keep trying.",e);
                        }
                    }
                }
            }
Preethi Rao
  • 5,117
  • 1
  • 16
  • 29
  • 1
    Thanks for your answer but it found for all the sample rates. Now i get confused which one to use among these four. Can you please elaborate this. Thanks – arslan haktic Apr 30 '15 at 11:35
  • yeah it found for all samplerates that means it it supports all sample rates, larger the sample rate better the quality . U can use whichever you want. i just give you way to find out whether the device support sample rates – Preethi Rao Apr 30 '15 at 13:20
0

The code doesn't really check for error cases making it much harder to figure out what going wrong on those devices. Please do the following:

  1. Not related to the recording (but the playback) but it's better if you take care of the AudioFocus.. it might be lost and etc. All yop need to know is here http://developer.android.com/training/managing-audio/audio-focus.html
  2. Add calls to AudioRecord.getState() to verify the state
  3. Add calls to AudioRecord.getRecordingState () to verify the recording state
  4. In getMinBufferSize you need to check against ERROR_BAD_VALUE
  5. In the read calls you need to check against ERROR_INVALID_OPERATION and ERROR_BAD_VALUE
  6. You can use setRecordPositionUpdateListener to tell if the recording has progressed.

These steps + observing the system logcat will put you in a much better place to pinpoint the issue or provide us with the info to solve the problem

Shai Levy
  • 715
  • 9
  • 25