Talking App like talking tom, Audio Recording didn't work on all devices
Asked Answered
B

3

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();
        }
    }
}
Beeline answered 9/4, 2015 at 9:18 Comment(9)
On what devices is it failing ? did you debug or have a log from a failing device ?Schilit
i just wanted to know whether your recording object was getting initialized ?Back
Yes definetly it is, its working fine for an hdpi device, QMobile, but while i run on samsung s4 it's continously listens and don't stop listening and for samsung tab 2, 7'' its not listening at all.Beeline
@arslanhaktic whether normal audio recording in default recorder working fine ?Back
as far as i can see you are doing too much processing on the same thread.. just read samples on that thread.. and processing part shift to other threadBack
@PreethiRao Thanks for your interest, but its working fine on one device and if i change the values its hearing sound from other devices. So i don't think that its an issue due to same thread.Beeline
@arslan haktic did u try recording and storing as a fineBack
Just try with a basic recording and check will it work ?Back
@arslanhaktic did u try recording normal audio and saving it in file ?Back
A
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.

Accommodative answered 13/4, 2015 at 16:36 Comment(1)
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?Heliotropin
B
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);
                        }
                    }
                }
            }
Back answered 20/4, 2015 at 7:6 Comment(2)
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. ThanksBeeline
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 ratesBack
S
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

Schilit answered 19/4, 2015 at 6:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.