|
16 | 16 | package com.mobileer.oboetester; |
17 | 17 |
|
18 | 18 | import java.util.ArrayList; |
19 | | - |
| 19 | +import android.util.Log; |
20 | 20 | /** |
21 | 21 | * Analyze a recording and extract edges for latency analysis. |
22 | 22 | */ |
23 | 23 | public class TapLatencyAnalyser { |
24 | 24 | public static final int TYPE_TAP = 0; |
| 25 | + public static final int TYPE_TONE =1; |
25 | 26 | float[] mHighPassBuffer; |
26 | 27 |
|
27 | 28 | private float mDroop = 0.995f; |
@@ -90,25 +91,43 @@ private TapLatencyEvent[] scanForEdges(float[] peakBuffer, int numSamples) { |
90 | 91 | float fast = 0.0f; |
91 | 92 | final float slowCoefficient = 0.01f; |
92 | 93 | final float fastCoefficient = 0.10f; |
93 | | - float lowThreshold = EDGE_THRESHOLD; |
| 94 | + final float EDGE_THRESHOLD = 0.01f; // trigger threshold for tap |
| 95 | + final float REARM_FRACTION = 0.3f; // fraction of last peak to rearm |
| 96 | + final int MIN_TONE_DELAY = 2000; |
| 97 | + float lastPeak = 0.0f; |
94 | 98 | boolean armed = true; |
| 99 | + boolean tapDetected = false; |
| 100 | + boolean toneDetected = false; |
| 101 | + int lastTapIndex = -1; |
| 102 | + |
95 | 103 | int sampleIndex = 0; |
| 104 | + |
96 | 105 | for (float level : peakBuffer) { |
97 | | - slow = slow + (level - slow) * slowCoefficient; // low pass filter |
98 | | - fast = fast + (level - fast) * fastCoefficient; // low pass filter |
99 | | - if (armed && (fast > EDGE_THRESHOLD) && (fast > (2.0 * slow))) { |
100 | | - events.add(new TapLatencyEvent(TYPE_TAP, sampleIndex)); |
101 | | - armed = false; |
102 | | - // Set a new, lower threshold based on the height of the detected peak. |
103 | | - // This allows us to detect a second, smaller peak, but not to trigger |
104 | | - // on the smaller variations that occur after the initial peak. |
105 | | - lowThreshold = fast * LOW_FRACTION; |
106 | | - } |
107 | | - // Use hysteresis when rearming. |
108 | | - if (fast < lowThreshold) { |
109 | | - armed = true; |
110 | | - } |
111 | | - sampleIndex++; |
| 106 | + slow = slow + (level - slow) * slowCoefficient; // low pass filter |
| 107 | + fast = fast + (level - fast) * fastCoefficient; // low pass filter |
| 108 | + if (armed && !tapDetected && (fast > EDGE_THRESHOLD) && (fast > 2.0f * slow)) { |
| 109 | + Log.i("TTL", "TTL Event of TYPE_TAP detected at " + sampleIndex + " fast=" + fast); |
| 110 | + events.add(new TapLatencyEvent(TYPE_TAP, sampleIndex)); |
| 111 | + armed = false; |
| 112 | + tapDetected = true; |
| 113 | + lastPeak = fast; |
| 114 | + lastTapIndex = sampleIndex; |
| 115 | + } |
| 116 | + |
| 117 | + if (tapDetected && !toneDetected && !armed && (sampleIndex - lastTapIndex) > MIN_TONE_DELAY) { |
| 118 | + if ((fast > EDGE_THRESHOLD) && (fast > 1.5f * slow)) { |
| 119 | + Log.i("TTL", "TTL Event of TYPE_TONE detected at " + sampleIndex + " fast=" + fast); |
| 120 | + events.add(new TapLatencyEvent(TYPE_TONE, sampleIndex)); |
| 121 | + toneDetected = true; |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | + // Rearm only when signal has fallen enough |
| 126 | + if (!armed && (fast < lastPeak * REARM_FRACTION)) { |
| 127 | + Log.i("TTL", "Signal has settled, rearming now (fast=" + fast + ")"); |
| 128 | + armed = true; |
| 129 | + } |
| 130 | + sampleIndex++; |
112 | 131 | } |
113 | 132 | return events.toArray(new TapLatencyEvent[0]); |
114 | 133 | } |
|
0 commit comments