2013-02-08 52 views
1

我想检测'Whistle'声音。为此,我实施了http://code.google.com/p/musicg/在android中检测'Whistle'声音

源代码本身有问题。当您启动应用程序时,它已准备好收听,但当您返回并重新启动检测器线程时,它不会触发哨子检测。

DetectorThread.java

package weetech.wallpaper.services; 

import java.util.LinkedList; 

import weetech.wallpaper.utils.Debug; 
import android.media.AudioFormat; 
import android.media.AudioRecord; 

import com.musicg.api.WhistleApi; 
import com.musicg.wave.WaveHeader; 

public class DetectorThread extends Thread { 

private RecorderThread recorder; 
private WaveHeader waveHeader; 
private WhistleApi whistleApi; 
private Thread _thread; 

private LinkedList<Boolean> whistleResultList = new LinkedList<Boolean>(); 
private int numWhistles; 
private int totalWhistlesDetected = 0; 
private int whistleCheckLength = 3; 
private int whistlePassScore = 3; 

public DetectorThread(RecorderThread recorder) { 
    this.recorder = recorder; 
    AudioRecord audioRecord = recorder.getAudioRecord(); 

    int bitsPerSample = 0; 
    if (audioRecord.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) { 
     bitsPerSample = 16; 
    } else if (audioRecord.getAudioFormat() == AudioFormat.ENCODING_PCM_8BIT) { 
     bitsPerSample = 8; 
    } 

    int channel = 0; 
    // whistle detection only supports mono channel 
    if (audioRecord.getChannelConfiguration() == AudioFormat.CHANNEL_IN_MONO) { 
     channel = 1; 
    } 

    waveHeader = new WaveHeader(); 
    waveHeader.setChannels(channel); 
    waveHeader.setBitsPerSample(bitsPerSample); 
    waveHeader.setSampleRate(audioRecord.getSampleRate()); 
    whistleApi = new WhistleApi(waveHeader); 
} 

private void initBuffer() { 
    numWhistles = 0; 
    whistleResultList.clear(); 

    // init the first frames 
    for (int i = 0; i < whistleCheckLength; i++) { 
     whistleResultList.add(false); 
    } 
    // end init the first frames 
} 

public void start() { 
    _thread = new Thread(this); 
    _thread.start(); 
} 

public void stopDetection() { 
    _thread = null; 
} 

@Override 
public void run() { 
    Debug.e("", "DetectorThread started..."); 

    try { 
     byte[] buffer; 
     initBuffer(); 

     Thread thisThread = Thread.currentThread(); 
     while (_thread == thisThread) { 
      // detect sound 
      buffer = recorder.getFrameBytes(); 

      // audio analyst 
      if (buffer != null) { 
       // sound detected 
       // MainActivity.whistleValue = numWhistles; 

       // whistle detection 
       // System.out.println("*Whistle:"); 

       try { 
        boolean isWhistle = whistleApi.isWhistle(buffer); 
        Debug.e("", "isWhistle : " + isWhistle + " " 
          + buffer.length); 

        if (whistleResultList.getFirst()) { 
         numWhistles--; 
        } 

        whistleResultList.removeFirst(); 
        whistleResultList.add(isWhistle); 

        if (isWhistle) { 
         numWhistles++; 
        } 

        // Debug.e("", "numWhistles : " + numWhistles); 

        if (numWhistles >= whistlePassScore) { 
         // clear buffer 
         initBuffer(); 
         totalWhistlesDetected++; 

         Debug.e("", "totalWhistlesDetected : " 
           + totalWhistlesDetected); 

         if (onWhistleListener != null) { 
          onWhistleListener.onWhistle(); 
         } 
        } 
       } catch (Exception e) { 
        Debug.w("", "" + e.getCause()); 
       } 
       // end whistle detection 
      } else { 
       // Debug.e("", "no sound detected"); 
       // no sound detected 
       if (whistleResultList.getFirst()) { 
        numWhistles--; 
       } 
       whistleResultList.removeFirst(); 
       whistleResultList.add(false); 

       // MainActivity.whistleValue = numWhistles; 
      } 
      // end audio analyst 
     } 

     Debug.e("", "Terminating detector thread..."); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

private OnWhistleListener onWhistleListener; 

public void setOnWhistleListener(OnWhistleListener onWhistleListener) { 
    this.onWhistleListener = onWhistleListener; 
} 

public interface OnWhistleListener { 
    void onWhistle(); 
} 

public int getTotalWhistlesDetected() { 
    return totalWhistlesDetected; 
} 
} 

RecorderThread.java

public class RecorderThread { 

private AudioRecord audioRecord; 
private int channelConfiguration; 
private int audioEncoding; 
private int sampleRate; 
private int frameByteSize; // for 1024 fft size (16bit sample size) 
byte[] buffer; 

public RecorderThread() { 
    sampleRate = 44100; 
    frameByteSize = 1024 * 2; 

    channelConfiguration = AudioFormat.CHANNEL_IN_MONO; 
    audioEncoding = AudioFormat.ENCODING_PCM_16BIT; 

    int recBufSize = AudioRecord.getMinBufferSize(sampleRate, 
      channelConfiguration, audioEncoding); // need to be larger than 
                // size of a frame 
    audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 
      sampleRate, channelConfiguration, audioEncoding, recBufSize); 
    buffer = new byte[frameByteSize]; 
} 

public AudioRecord getAudioRecord() { 
    return audioRecord; 
} 

public boolean isRecording() { 
    if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) { 
     return true; 
    } 

    return false; 
} 

public void startRecording() { 
    try { 
     audioRecord.startRecording(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

public void stopRecording() { 
    try { 
     audioRecord.stop(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

public byte[] getFrameBytes() { 
    audioRecord.read(buffer, 0, frameByteSize); 

    // analyze sound 
    int totalAbsValue = 0; 
    short sample = 0; 
    float averageAbsValue = 0.0f; 

    for (int i = 0; i < frameByteSize; i += 2) { 
     sample = (short) ((buffer[i]) | buffer[i + 1] << 8); 
     totalAbsValue += Math.abs(sample); 
    } 
    averageAbsValue = totalAbsValue/frameByteSize/2; 

    Debug.e("", "averageAbsValue : " + averageAbsValue); 

    // no input 
    if (averageAbsValue < 30) { 
     return null; 
    } 

    return buffer; 
} 

} 

使用

public class DetectionService extends Service implements 
    OnWhistleListener { 

Handler handler; 
private DetectorThread detectorThread; 
private RecorderThread recorderThread; 

@Override 
public void onCreate() { 
    super.onCreate(); 
    handler = new Handler(); 

} 

@Override 
public IBinder onBind(Intent intent) { 
    return null; 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 

    try { 
     if (intent != null && intent.getExtras() != null) { 

      if (intent.getExtras().containsKey("action")) { 
       Debug.e("", "action : " + intent.getStringExtra("action")); 

       if (intent.getStringExtra("action").equals("start")) { 
        startWhistleDetection(); 
       } 

       if (intent.getStringExtra("action").equals("stop")) { 
        stopWhistleDetection(); 
        stopSelf(); 
       } 
      } 
     } else { 

      startWhistleDetection(); 
      Debug.e("", "intent is null OR intent.getExtras() is null"); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return super.onStartCommand(intent, flags, startId); 
} 

private void startWhistleDetection() { 

    try { 
     stopWhistleDetection(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    recorderThread = new RecorderThread(); 
    recorderThread.startRecording(); 
    detectorThread = new DetectorThread(recorderThread); 
    detectorThread.setOnWhistleListener(this); 
    detectorThread.start(); 

} 

private void stopWhistleDetection() { 
    if (detectorThread != null) { 
     detectorThread.stopDetection(); 
     detectorThread.setOnWhistleListener(null); 
     detectorThread = null; 
    } 

    if (recorderThread != null) { 
     recorderThread.stopRecording(); 
     recorderThread = null; 
    } 

} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 
} 

@Override 
public void onWhistle() { 
    Debug.e("", "onWhistle()"); 
} 

它检测哨第一次,直到你不停止服务。但停止后,再次启动它不会检测(不调用监听器)。我只是没有跟踪,可能是什么问题。

是否有任何问题录制? 任何人都可以尝试?有没有其他的API?

帮助!!谢谢

+0

@ClassStacker我跟踪的所有变量。但是如果你想追踪'music cg'库的变量,那么它有可能如何? –

+0

你不得不检查的第一件事是为什么whistzle检测不是_triggered_?意义,从你的代码触发? –

+0

@ClassStacker'Debug.e(“”,“onWhistle()”);'在初始化时被调用,但是我重新启动服务,它不会被调用。我尝试重置所有对象(所有对象)。我认为gramebytes不会正确返回'byte []'。我也试着改变输入通道。 –

回答

5

我投入了6个小时,:D令人难以置信的是,录音机在停止时不会被释放。停车后我刚刚释放记录器。

源代码有轻微的愚蠢错误。它不释放记录器。

public void stopRecording() { 
    try { 
     audioRecord.stop(); 
     audioRecord.release(); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

恭喜! :) –

+0

这段代码真是太棒了,能否请你告诉我如何使用这段代码,我无法彻底理解,通过服务,我可以理解,但在记录和检测的情况下,我可以'得到任何东西,它会如果给出提示如何使用此代码会有帮助。非常感谢你 –

+0

你好Bhavesh Hirpara。我使用上面的代码并开始主要活动的服务。但我总是得到averageAbsValue:0.0公共字节[] RecorderThread类的getFrameBytes()方法..........和@Override public void onWhistle(){ }永远不会触发 –

0

此代码是确定我

if (detectorThread != null) { 
      detectorThread.stopDetection(); 
      recorderThread.stopRecording(); 
    }