0

I want to create an Android app in which I have to react if the amplitude of the microphone reaches a definite level.

Right now I'm using this Code:

MediaRecorder soundRecorder = new MediaRecorder();
soundRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
soundRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
soundRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
soundRecorder.setOutputFile("/dev/null");
soundRecorder.prepare();
soundRecorder.start();

int amplitude = 0;
while (amplitude < MyApp.this.ampToReact) {
    amplitude = soundRecorder.getMaxAmplitude();
}

But I know that this is very bad programming (and my app keeps crashing).

So I would like to create a listener with an onAmplitudeReachedDefiniteLevel() method to replace this ugly while loop.

jww
  • 97,681
  • 90
  • 411
  • 885
Nikolar
  • 11
  • 3

1 Answers1

1

Listener will only work if some code exists to detect the event. But you'll need to do this manually as far as I can tell. Rather, if you are repetitively sampling for something crossing a threshold, it may be best to poll using a timer.

What is the sample rate?

What is the lowest latency you need?

for example, at 44100 kHz, if you want to react with 1ms precision, then you only need to check every 44 samples.

Why don't you set a timer / callback, which is called every 1 ms? Then cancel the timer after you've 'reacted'? There are several ways of doing this. Here's one of them, using android Handler (untested - sorry if it needs tweaking!)

final int POLL_INTERVAL = 100; // milliseconds
Handler h = new Handler(); // this is where you feed in messages
OnClickListener startbuttonListener = new OnClickListener() {
  // for example, if you want to start listening after a button press:
  public void onClick(View v) { 
    h.postDelayed(poll, POLL_INTERVAL); // start running the poll loop
  }
};
Runnable poll = new Runnable() {
  public void run() {
    if(soundRecorder.getMaxAmplitude() > MyApp.this.ampToReact){
      h.postDelayed(soundTrigger, 0); // run your sound trigger if criterion met
    }else h.postDelayed(this, POLL_INTERVAL); // post this Runnable (i.e. poll) again
  }
}
Runnable soundTrigger = new Runnable() {
  public void run(){
    // TRIGGERED!
  }
}
Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58
  • Thank you for your quick reply! :) I don't have a problem doing this manually, but I have no idea how to do this. It would also be ok to have the data after a short period of time, but is'nt the app a waste of ressources if I keep polling until the sound starts? Because it could take multiple seconds to recieve that sound signal... – Nikolar Sep 14 '14 at 17:26
  • Yes that's correct, but you have to decide how wasteful to be! For example, if you're not interested in being millisecond-precise, then you could poll every 100 ms. – Sanjay Manohar Sep 14 '14 at 20:23