2011-10-31 88 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)然後它工作正常。