13

Description


My application record sound from phone microphone. I am using android standard classes (android.media.AudioRecord) to do that. Application have 2 buttons "Start" and "Stop" when I press start button application start record and when I press stop application stops recording and give me back buffer, with voice data in .wav format. All work fine.

Problem


I want to change my application in this way, when application start work it begin to analyze sound coming from microphone, if user keep silent application continue to analyze income sound from microphone, if user start to talk application begin to Record sound coming from microphone and then user finish talking application stops recording and give me back same buffer, with voice data in .wav format.

Question


  1. How I can detect that user start to talk
  2. How I can detect that user stop to talk
Community
  • 1
  • 1
Viktor Apoyan
  • 10,655
  • 22
  • 85
  • 147
  • 1
    I think you will have to do most of the sound work on your own - Android does provide some limited functions for accessing the mic and recording, but nothing that does heavy computation or speech to text. – Noah Oct 31 '11 at 14:34
  • @sqrfv thanks for comment, +1 Any other suggestion ? – Viktor Apoyan Oct 31 '11 at 14:39

3 Answers3

28

Just add this code to your application and you will detect when user start to speak and when he stops.

public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

    // 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
                                                         ); 
    // Initialize Audio Recorder.
    AudioRecord 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. 
    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 <= 350) && recording == false )
        {
            Log.i("TAG", "1");
            tempIndex++;
            continue;
        }

        if( temp > 350 && recording == false )
        {
            Log.i("TAG", "2");
            recording = true;
        }

        if( (temp >= 0 && temp <= 350) && 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() + "/" + System.currentTimeMillis() + ".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();
                    } 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++;

    }
}

Check this link.

Murtaza Khursheed Hussain
  • 15,176
  • 7
  • 58
  • 83
Viktor Apoyan
  • 10,655
  • 22
  • 85
  • 147
  • I tried this code but it is not working for me i am getting the exception as follows Please help me to come out from this problem – Dipali Apr 06 '12 at 09:35
  • 04-06 15:03:01.729: E/AndroidRuntime(16174): Caused by: java.lang.IllegalArgumentException: 0Hz is not a supported sample rate. 04-06 15:03:01.729: E/AndroidRuntime(16174): at android.media.AudioRecord.audioParamCheck(AudioRecord.java:265) 04-06 15:03:01.729: E/AndroidRuntime(16174): at android.media.AudioRecord.(AudioRecord.java:223) 04-06 15:03:01.729: E/AndroidRuntime(16174): at com.test.recording.RecordingActivity.onCreate(RecordingActivity.java:32) 04-06 15:03:01.729: E/AndroidRuntime(16174): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615) – Dipali Apr 06 '12 at 09:35
  • private static final int RECORDER_SAMPLERATE which value should i give it here??? – Dipali Apr 06 '12 at 09:39
  • Please help me as soon as possible – Dipali Apr 06 '12 at 09:42
  • 6
    @Dipali `private static final int RECORDER_BPP = 16;` `private static int RECORDER_SAMPLERATE = 8000;` `private static int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;` private static int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT; – Viktor Apoyan Aug 01 '12 at 07:20
  • @ViToBrothers can you explain or point me somewhere to understand how the audio analyzing is done? Specifically the code following the `// Analyze Sound.` and `// Analyze temp buffer.` comments. – asloob May 06 '13 at 06:48
  • Can i use this example to start an activity when a voice is detected? – Antonio Nov 07 '13 at 17:57
  • But the voice stored in .wav file is unable to read. Can you help me with that? – Sagar Shah Aug 21 '14 at 09:32
  • i created a new project and pasted the above exactly in that project but the log say "Recording Sound" and never stops and then crashes with not responding error; could you tell me the solution to this – Hunain Usman Jun 09 '15 at 06:45
  • 1
    Site can't be reached – Kumararaja Jan 04 '19 at 07:36
  • i get an error "startRecording() called on an uninitialized AudioRecord" – Kumararaja Jan 04 '19 at 09:31
  • This just hangs the phone. – Vijay E Oct 22 '20 at 09:03
  • @Kumararaja If you are running on Android 6 or above you have to write the runtime permission code for Record Audio and write storage – Bhargav Thanki Jun 28 '22 at 12:27
  • @VijayE Its because the code is executing on main thread and while loop keeps on running – Bhargav Thanki Jun 28 '22 at 12:27
2

it is better to used private static final int RECORDER_SAMPLERAT=8000; it works for me.I think it will help for you

Nikhil
  • 16,194
  • 20
  • 64
  • 81
Manori
  • 21
  • 2
1

when i replaced totalAbsValue += Math.abs( sample ) / (numberOfReadBytes/2) by totalAbsValue += (float)Math.abs( sample ) / ((float)numberOfReadBytes/(float)2) then it work fine.

Murtaza Khursheed Hussain
  • 15,176
  • 7
  • 58
  • 83