2011-10-31 62 views
10

说明


我的申请记录从手机麦克风的声音。我正在使用android标准类(android.media.AudioRecord)来做到这一点。应用程序有2个按钮“开始”和“停止”当我按下开始按钮,应用程序启动记录,当我按下停止应用程序停止录音并给我回缓冲区,与以.wav格式的语音数据。一切正常。语音检测在Android应用程序

问题


我想改变我的应用程序以这种方式,当应用程序启动开始分析声音从麦克风来,如果用户保持沉默申请继续分析从麦克风收入有益的工作,如果用户开始通话应用程序开始到记录来自麦克风的声音,然后用户完成通话应用程序停止记录并将相同的缓冲区返回给我,语音数据为.wav格式。

问题


  1. 我怎样才能检测到用户开始谈
  2. 我怎样才能检测到用户停止交谈
+1

我认为你必须自己完成绝大部分的音效工作--Android的确提供了一些有限的功能来访问麦克风和录音,但没有任何重大的计算或语音文本。 – Noah

+0

@sqrfv感谢您的评论,+1任何其他建议? –

回答

24

只需添加此代码你的应用程序,你会发现何时用户开始讲话和何时停止。

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++; 

    } 
} 

检查这个link

+0

我试过这段代码但它不适用于我我得到的例外如下 请帮我解决这个问题 – Dipali

+0

04-06 15:03:01.729:E/AndroidRuntime(16174):引起: java.lang.IllegalArgumentException:0Hz不是支持的采样率。在Android.media.AudioRecord.audioParamCheck(AudioRecord.java:265) 04-06 15:03:01.729:E/AndroidRuntime(16174):E/AndroidRuntime(16174):在android.media.AudioRecord上的\t。 (AudioRecord.java:223) 04-06 15:03:01。729:E/AndroidRuntime(16174):\t at com.test.recording.RecordingActivity.onCreate(RecordingActivity.java:32) 04-06 15:03:01.729:E/AndroidRuntime(16174):\t at android.app .ActivityThread.performLaunchActivity(ActivityThread.java:1615) – Dipali

+0

private static final int RECORDER_SAMPLERATE 哪个值我应该在这里? '' 私有静态INT RECORDER_SAMPLERATE = 8000;'' 私有静态INT RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;' 私有静态诠释RECORDER_AUDIO_ENCODING = – Dipali

2

最好使用私有静态final int RECORDER_SAMPLERAT = 8000; 它适用于我。我认为它会帮助你

7

我已经回答了一个类似的问题之前,一种方法是使用记录和录音字节上的语音功率分析过程的线程,有一个示例代码您的参考:http://musicg.googlecode.com/files/musicg_android_demo.zip

+0

你能解释或指向我的某个地方了解音频检测是如何工作的。具体来说,'RecorderThread'中的方法'getFrameBytes'? – asloob

1

当我更换totalAbsValue += Math.abs(sample)/(numberOfReadBytes/2) by totalAbsValue += (float)Math.abs(sample)/((float)numberOfReadBytes/(float)2)然后它工作正常。