Skip to content

Commit

Permalink
Microphone disconnection detection
Browse files Browse the repository at this point in the history
  • Loading branch information
VoidXH committed Jul 31, 2024
1 parent 70f4979 commit b535c30
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 27 deletions.
32 changes: 16 additions & 16 deletions Cavern.QuickEQ/Utilities/GraphUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static class GraphUtils {
/// <param name="action">Performed action</param>
public static void ForEachLin<T>(T[] source, double startFreq, double endFreq, FrequencyFunction<T> action) {
double step = (endFreq - startFreq) / (source.Length - 1);
for (int entry = 0; entry < source.Length; ++entry) {
for (int entry = 0; entry < source.Length; entry++) {
action(startFreq + step * entry, ref source[entry]);
}
}
Expand All @@ -36,7 +36,7 @@ public static void ForEachLin<T>(T[] source, double startFreq, double endFreq, F
/// <param name="action">Performed action</param>
public static void ForEachLog<T>(T[] source, double startFreq, double endFreq, FrequencyFunction<T> action) {
double mul = Math.Pow(10, (Math.Log10(endFreq) - Math.Log10(startFreq)) / (source.Length - 1));
for (int i = 0; i < source.Length; ++i) {
for (int i = 0; i < source.Length; i++) {
action(startFreq, ref source[i]);
startFreq *= mul;
}
Expand All @@ -48,7 +48,7 @@ public static void ForEachLog<T>(T[] source, double startFreq, double endFreq, F
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AddSlope(this float[] curve, float slope) {
float mul = 1f / curve.Length;
for (int i = 0; i < curve.Length; ++i) {
for (int i = 0; i < curve.Length; i++) {
curve[i] += slope * mul;
}
}
Expand All @@ -58,7 +58,7 @@ public static void AddSlope(this float[] curve, float slope) {
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ConvertFromDecibels(float[] curve) {
for (int i = 0; i < curve.Length; ++i) {
for (int i = 0; i < curve.Length; i++) {
curve[i] = (float)Math.Pow(10, curve[i] * .05f);
}
}
Expand All @@ -75,7 +75,7 @@ public static void ConvertFromDecibels(float[] curve) {
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ConvertToDecibels(float[] curve, float minimum) {
for (int i = 0; i < curve.Length; ++i) {
for (int i = 0; i < curve.Length; i++) {
curve[i] = 20 * (float)Math.Log10(curve[i]);
if (curve[i] < minimum) { // this is also true if curve[i] == 0
curve[i] = minimum;
Expand All @@ -95,7 +95,7 @@ public static float[] ConvertToGraph(Complex[] response, double startFreq, doubl
float[] graph = new float[resultSize];
double step = Math.Pow(10, (Math.Log10(endFreq) - Math.Log10(startFreq)) / (graph.Length - 1)),
positioner = response.Length / (double)sampleRate;
for (int i = 0; i < graph.Length; ++i) {
for (int i = 0; i < graph.Length; i++) {
graph[i] = response[(int)(startFreq * positioner)].Magnitude;
startFreq *= step;
}
Expand All @@ -116,7 +116,7 @@ public static float[] ConvertToGraph(float[] response, double startFreq, double
float[] graph = new float[resultSize];
double step = Math.Pow(10, (Math.Log10(endFreq) - Math.Log10(startFreq)) / graph.Length),
positioner = response.Length * 2 / (double)sampleRate;
for (int i = 0; i < graph.Length; ++i) {
for (int i = 0; i < graph.Length; i++) {
graph[i] = response[(int)(startFreq * positioner)];
startFreq *= step;
}
Expand Down Expand Up @@ -151,7 +151,7 @@ public static float Correlation(float[] x, float[] y, int start, int end) {
public static (float min, float max) GetLimits(float[] values) {
float min = values[0];
float max = values[0];
for (int i = 1; i < values.Length; ++i) {
for (int i = 1; i < values.Length; i++) {
if (max < values[i]) {
max = values[i];
}
Expand Down Expand Up @@ -182,7 +182,7 @@ public static float Max(this float[] graph) {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Normalize(float[] graph) {
float avg = graph.Average();
for (int i = 0; i < graph.Length; ++i) {
for (int i = 0; i < graph.Length; i++) {
graph[i] -= avg;
}
}
Expand All @@ -193,7 +193,7 @@ public static void Normalize(float[] graph) {
public static float[] Scale(float[] source, int newLength) {
float[] result = new float[newLength];
float scale = source.Length / (float)newLength--;
for (int pos = 0; pos < newLength; ++pos) {
for (int pos = 0; pos < newLength; pos++) {
result[pos] = WaveformUtils.GetPeakSigned(source, (int)(pos * scale), (int)((pos + 1) * scale));
}
return result;
Expand All @@ -205,7 +205,7 @@ public static float[] Scale(float[] source, int newLength) {
public static float[] Scale(float[] source, int newLength, int sourceStart, int sourceEnd) {
float[] result = new float[newLength];
float scale = (sourceEnd - sourceStart) / (float)newLength--;
for (int pos = 0; pos < newLength; ++pos) {
for (int pos = 0; pos < newLength; pos++) {
result[pos] =
WaveformUtils.GetPeakSigned(source, sourceStart + (int)(pos * scale), sourceStart + (int)((pos + 1) * scale));
}
Expand All @@ -220,18 +220,18 @@ public static float[] SmoothUniform(float[] source, int windowSize) {
lastBlock = length - windowSize;
float[] smoothed = new float[length--];
float average = 0;
for (int sample = 0; sample < windowSize; ++sample) {
for (int sample = 0; sample < windowSize; sample++) {
average += source[sample];
}
for (int sample = 0; sample < windowSize; ++sample) {
for (int sample = 0; sample < windowSize; sample++) {
smoothed[sample] = average / (sample + windowSize);
average += source[sample + windowSize];
}
for (int sample = windowSize; sample < lastBlock; ++sample) {
for (int sample = windowSize; sample < lastBlock; sample++) {
average += source[sample + windowSize] - source[sample - windowSize];
smoothed[sample] = average / (windowSize * 2);
}
for (int sample = lastBlock; sample <= length; ++sample) {
for (int sample = lastBlock; sample <= length; sample++) {
average -= source[sample - windowSize];
smoothed[sample] = average / (length - sample + windowSize);
}
Expand Down Expand Up @@ -268,7 +268,7 @@ public static float[] SmoothGraph(float[] samples, float startFreq, float endFre
endGraph = SmoothGraph(samples, startFreq, endFreq, endOctave),
output = new float[samples.Length];
float positioner = 1f / samples.Length;
for (int i = 0; i < samples.Length; ++i) {
for (int i = 0; i < samples.Length; i++) {
output[i] = QMath.Lerp(startGraph[i], endGraph[i], i * positioner);
}
return output;
Expand Down
10 changes: 10 additions & 0 deletions CavernUnity DLL/Input/InputDeviceBlockReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public class InputDeviceBlockReader : MonoBehaviour {
/// </summary>
public event AudioBlockDelegate Callback;

/// <summary>
/// Called when the microphone is not recording anymore for any reason.
/// </summary>
public event Action OnMicrophoneDisconnected;

/// <summary>
/// Recording has successfully started.
/// </summary>
Expand Down Expand Up @@ -133,6 +138,11 @@ void Update() {
if (buffer == null) {
return;
}
if (!MultiplatformMicrophone.IsRecording(activeDevice)) {
buffer = null;
OnMicrophoneDisconnected?.Invoke();
return;
}

int pos = MultiplatformMicrophone.GetPosition(activeDevice),
interval = blockSize - overlap;
Expand Down
15 changes: 12 additions & 3 deletions Tests/Test.Cavern.QuickEQ/Consts/TestUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,23 @@
internal static class TestUtils {
/// <summary>
/// Test if an <paramref name="array"/> between the given limits is strictly monotonously decreasing,
/// but allowing an error margin of <paramref name="epsilon"/>.
/// but allowing an error margin of <paramref name="delta"/>.
/// </summary>
public static void AssertDecrease(float[] array, int from, int to, float epsilon) {
public static void AssertDecrease(float[] array, int from, int to, float delta) {
for (int i = from + 1; i < to; i++) {
if (array[i - 1] + epsilon <= array[i]) {
if (array[i - 1] + delta <= array[i]) {
Assert.Fail();
}
}
}

/// <summary>
/// Test if all values of both arrays are in the expected margin of error (<paramref name="delta"/>) from each other.
/// </summary>
public static void AssertArrayEquals(float[] expected, float[] actual, float delta) {
for (int i = 0; i < expected.Length; i++) {
Assert.AreEqual(expected[i], actual[i], delta);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ public class SyntheticBiquadCrossover_Tests {
/// Tests if <see cref="SyntheticBiquadCrossover"/> generates correct impulse responses.
/// </summary>
[TestMethod, Timeout(1000)]
public void ImpulseResponse() => Utils.ImpulseResponse(new SyntheticBiquadCrossover(null, null), 0.47490564f, 0.5231629f);
public void ImpulseResponse() => Utils.ImpulseResponse(new SyntheticBiquadCrossover(null, null), .474857f, .52310514f);
}
}
6 changes: 3 additions & 3 deletions Tests/Test.Cavern.QuickEQ/MovingAverage_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ public class MovingAverage_Tests {
/// Tests if <see cref="MovingAverage"/> works as intended.
/// </summary>
[TestMethod, Timeout(1000)]
public void Test() {
public void MovingAverage() {
MovingAverage average = new MovingAverage(3);
float[] first = { 1, 0, 4 };
average.AddFrame(first);
Equals(average.Average, first);
average.AddFrame(new float[] { 2, 0, 4 });
average.AddFrame(new float[] { 3, 3, 4 });
average.AddFrame([2, 0, 4]);
average.AddFrame([3, 3, 4]);
Equals(average.Average, new float[] { 2, 1, 4 });
}
}
Expand Down
8 changes: 4 additions & 4 deletions Tests/Test.Cavern.QuickEQ/Windowing_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ public void Symmetry() {
/// <summary>
/// A correct example of the Hann window's bounding area.
/// </summary>
static readonly float[] hannResult = {
static readonly float[] hannResult = [
0, 0.0954915f, 0.34549153f, 0.65450853f, 0.90450853f, 1, 0.9045085f, 0.65450853f, 0.34549144f, 0.09549138f
};
];

/// <summary>
/// A correct example of the Tukey window's bounding area.
/// </summary>
static readonly float[] tukeyResult = {
static readonly float[] tukeyResult = [
0, 0.9045085f, 1, 1, 1, 1, 1, 1, 1, 0.904508233f
};
];
}
}

0 comments on commit b535c30

Please sign in to comment.