below is the code I use for an iPhone application that does exactly the same thing. The code is in Objective-C++ but I have lots of comments in it. This code is executed inside the callback function of a recording queue. I am sure that a similar approach exists for the Android platform.
This approach works very nice in almost every acoustic environment I have used it and it is used in our app. You can download it to test it if you want.
Try implementing it in the android platform and you are done!
// If there are some audio samples in the audio buffer of the recording queue
if (inNumPackets > 0) {
// The following 4 lines of code are vector functions that compute
// the average power of the current audio samples.
// Go [here][2] to view documentation about them.
vDSP_vflt16((SInt16*)inBuffer->mAudioData, 1, aqr->currentFrameSamplesArray, 1, inNumPackets);
vDSP_vabs(aqr->currentFrameSamplesArray, 1, aqr->currentFrameSamplesArray, 1, inNumPackets);
vDSP_vsmul(aqr->currentFrameSamplesArray, 1, &aqr->divider, aqr->currentFrameSamplesArray, 1, inNumPackets);
vDSP_sve(aqr->currentFrameSamplesArray, 1, &aqr->instantPower, inNumPackets);
// InstantPower holds the energy for the current audio samples
aqr->instantPower /= (CGFloat)inNumPackets;
// S.O.S. Avoid +-infs, NaNs add a small number to InstantPower
aqr->instantPower = log10f(aqr->instantPower + 0.001f);
// InstantAvgPower holds the energy for a bigger window
// of time than InstantPower
aqr->instantAvgPower = aqr->instantAvgPower * 0.95f + 0.05f * aqr->instantPower;
// AvgPower holds the energy for an even bigger window
// of time than InstantAvgPower
aqr->avgPower = aqr->avgPower * 0.97f + 0.03f * aqr->instantAvgPower;
// This is the ratio that tells us when to record
CGFloat ratio = aqr->avgPower / aqr->instantPower;
// If we are not already writing to an audio file and
// the ratio is bigger than a specific hardcoded value
// (this value has to do with the quality of the microphone
// of the device. I have set it to 1.5 for an iPhone) then start writing!
if (!aqr->writeToFile && ratio > aqr->recordingThreshold) {
aqr->writeToFile = YES;
}
if (aqr->writeToFile) {
// write packets to file
XThrowIfError(AudioFileWritePackets(aqr->mRecordFile, FALSE, inBuffer->mAudioDataByteSize,
inPacketDesc, aqr->mRecordPacket, &inNumPackets, inBuffer->mAudioData),
"AudioFileWritePackets failed");
aqr->mRecordPacket += inNumPackets;
// Now if we are recording but the instantAvgPower is lower
// than avgPower then we increase the countToStopRecording counter
if (aqr->instantAvgPower < aqr->avgPower) {
aqr->countToStopRecording++;
}
// or else set him to 0.
else {
aqr->countToStopRecording = 0;
}
// If we have detected that there is not enough power in 30 consecutive
// audio sample buffers OR we have recorded TOO much audio
// (the user speaks for more than a threshold of time) stop recording
if (aqr->countToStopRecording > 30 || aqr->mRecordPacket > kMaxAudioPacketsDuration) {
aqr->countToStopRecording = 0;
aqr->writeToFile = NO;
// Notify the audio player that we finished recording
// and start playing the audio!!!
dispatch_async(dispatch_get_main_queue(), ^{[[NSNotificationCenter defaultCenter] postNotificationName:@"RecordingEndedPlayNow" object:nil];});
}
}
}
Best!