App 2.43.3: sound check on the Logs tab

One tap listens for 10 seconds with Android's audio analyser on the output
mix and reports the levels, to learn whether it hears Bluetooth, CarPlay and
radio before the Halloween pumpkin's light follows the music. Levels only, no
sound kept, no microphone. Heard a test tone on the emulator. Not tried on
the car.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
2026-10-31 13:17:41 +01:00
co-authored by Claude Opus 5.5
parent 024e40cd01
commit f84e18ef0e
12 changed files with 410 additions and 4 deletions
@@ -0,0 +1,78 @@
package com.evsuite.abrp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Test;
public class SoundLevelsTest {
private static byte[] wave(int... unsigned) {
byte[] out = new byte[unsigned.length];
for (int i = 0; i < out.length; i++) out[i] = (byte) unsigned[i];
return out;
}
@Test
public void silenceIsTheMiddleOfTheWaveform() {
assertEquals(0f, SoundLevels.peak(wave(128, 128, 128)), 0f);
assertEquals(0.5f, SoundLevels.peak(wave(128, 192, 128)), 0f);
assertEquals(0.5f, SoundLevels.peak(wave(128, 64, 128)), 0f);
assertEquals(1f, SoundLevels.peak(wave(0, 255)), 0f);
}
@Test
public void aFailedReadIsNotSilence() {
assertNull(SoundLevels.peak(null));
assertNull(SoundLevels.peak(new byte[0]));
assertNull(SoundLevels.band(null, 48000, 0f, 250f));
assertNull(SoundLevels.band(new byte[8], 0, 0f, 250f));
}
@Test
public void aBandAveragesItsOwnBins() {
// Eight values: DC and Nyquist, then bins 1 to 3, here 1000, 2000 and 3000 Hz.
byte[] fft = { 99, 99, 64, 0, 0, 32, 3, 4 };
assertEquals(0.5f, SoundLevels.band(fft, 8000, 500f, 1500f), 1e-6f);
assertEquals(0.25f, SoundLevels.band(fft, 8000, 2000f, 2500f), 1e-6f);
assertEquals(5f / 128f, SoundLevels.band(fft, 8000, 3000f, 4000f), 1e-6f);
assertEquals((0.5f + 0.25f) / 2f, SoundLevels.band(fft, 8000, 500f, 2500f), 1e-6f);
assertNull(SoundLevels.band(fft, 8000, 5000f, 6000f));
}
@Test
public void theVerdictTellsDeafFromNothingPlaying() {
SoundLevels.Summary none = new SoundLevels.Summary();
none.add(null, null, null, null, null);
assertEquals(SoundLevels.Verdict.NO_READING, none.verdict(true));
SoundLevels.Summary silent = new SoundLevels.Summary();
silent.add(0f, 0f, 0f, 0f, -9600);
silent.add(0.01f, 0f, 0f, 0f, -9600);
assertEquals(SoundLevels.Verdict.DEAF, silent.verdict(true));
assertEquals(SoundLevels.Verdict.NOTHING_PLAYING, silent.verdict(false));
}
@Test
public void onlyAMovingLevelIsHeard() {
SoundLevels.Summary steady = new SoundLevels.Summary();
steady.add(0.4f, 0.1f, 0.1f, 0.1f, -2000);
steady.add(0.41f, 0.1f, 0.1f, 0.1f, -2000);
assertEquals(SoundLevels.Verdict.STEADY, steady.verdict(true));
SoundLevels.Summary music = new SoundLevels.Summary();
music.add(0.1f, 0.2f, 0.1f, 0f, -3000);
music.add(0.6f, 0.4f, 0.3f, 0.1f, -1500);
assertEquals(SoundLevels.Verdict.HEARS, music.verdict(true));
}
@Test
public void theLineAveragesAndMarksWhatFailed() {
SoundLevels.Summary s = new SoundLevels.Summary();
s.add(0.1f, 0.2f, 0.1f, 0f, -3000);
s.add(null, null, null, null, null);
s.add(0.6f, 0.4f, 0.3f, 0.1f, -1500);
assertEquals("peak 0.10–0.60, bass 0.300, mid 0.200, treble 0.050, rms -1500 mB (2/3)", s.line());
assertEquals("peak —, bass —, mid —, treble —, rms — (0/0)", new SoundLevels.Summary().line());
}
}