/*
* Copyright 2012 Greg Milette and Adam Stroud
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package root.gast.audio.interp;
import java.util.LinkedList;
import android.util.Log;
import root.gast.audio.processing.ZeroCrossing;
import root.gast.audio.record.AudioClipListener;
import root.gast.audio.util.AudioUtil;
/**
* track a history of frequencies, and determine if a new frequency is within
* the range of the ones in the history
*
* @author Greg Milette <<a
* href="mailto:gregorym@gmail.com">gregorym@gmail.com</a>>
*/
public class ConsistentFrequencyDetector implements AudioClipListener
{
private static final String TAG = "ConsistentFrequencyDetector";
private LinkedList<Integer> frequencyHistory;
private int rangeThreshold;
private int silenceThreshold;
public static final int DEFAULT_SILENCE_THRESHOLD = 2000;
private static final boolean DEBUG = false;
public ConsistentFrequencyDetector(int historySize, int rangeThreshold,
int silenceThreshold)
{
frequencyHistory = new LinkedList<Integer>();
// pre-fill so modification is easy
for (int i = 0; i < historySize; i++)
{
frequencyHistory.add(Integer.MAX_VALUE);
}
this.rangeThreshold = rangeThreshold;
this.silenceThreshold = silenceThreshold;
}
@Override
public boolean heard(short[] audioData, int sampleRate)
{
int frequency = ZeroCrossing.calculate(sampleRate, audioData);
frequencyHistory.addFirst(frequency);
// since history is always full, just remove the last
frequencyHistory.removeLast();
int range = calculateRange();
if (DEBUG)
{
Log.d(TAG, "range: " + range + " threshold " + rangeThreshold
+ " loud: " + AudioUtil.rootMeanSquared(audioData));
}
boolean heard = false;
if (range < rangeThreshold)
{
// only trigger it isn't silence
if (AudioUtil.rootMeanSquared(audioData) > silenceThreshold)
{
Log.d(TAG, "heard");
heard = true;
}
else
{
Log.d(TAG, "not loud enough");
}
}
return heard;
}
private int calculateRange()
{
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (Integer val : frequencyHistory)
{
if (val >= max)
{
max = val;
}
if (val < min)
{
min = val;
}
}
if (DEBUG)
{
StringBuilder sb = new StringBuilder();
for (Integer val : frequencyHistory)
{
sb.append(val).append(" ");
}
Log.d(TAG, sb.toString() + " [" + (max - min) + "]");
}
return max - min;
}
}