A small helpdesk system: an office Pixel running a patched GrapheneOS Dialer answers technician calls, records both call legs as separate channels, and a Ruby backend transcribes them through Whisper and files an AI summary against the caller. Squashed to a single commit for sharing. No credentials are included; secrets live outside the repo in /etc/helpdesk/env on the server or a gitignored .claude/env.local locally. See .claude/env.local.example for the shape. Start at README.md, then docs/architecture.md.
117 lines
5.8 KiB
Java
117 lines
5.8 KiB
Java
package com.android.dialer.helpdesk.util;
|
|
|
|
/**
|
|
* Standalone off-device test for {@link LegInterleaver}.
|
|
*
|
|
* <p>This is the code that decides whether dual-leg recording produces a real conversation or a
|
|
* plausible-looking file in which the two speakers drift apart. Its failure mode is quiet: a wrong
|
|
* alignment still yields playable stereo and a readable transcript, just with the operator's words
|
|
* sliding away from when they were said. So the interesting cases here are the uneven ones - legs
|
|
* delivering different amounts, a leg stalling, a leg arriving in odd-sized pieces.
|
|
*/
|
|
public class LegInterleaverTest {
|
|
static int pass = 0, fail = 0;
|
|
|
|
static void ok(String d) { pass++; System.out.println(" ok " + d); }
|
|
static void bad(String d, String got) { fail++; System.out.println(" FAIL " + d + " (got: " + got + ")"); }
|
|
static void eq(int got, int want, String d) {
|
|
if (got == want) ok(d); else bad(d, got + ", want " + want);
|
|
}
|
|
static void eqBytes(byte[] got, int len, int[] want, String d) {
|
|
if (len != want.length) { bad(d, "length " + len + ", want " + want.length); return; }
|
|
for (int i = 0; i < len; i++) {
|
|
if ((got[i] & 0xFF) != want[i]) { bad(d, "byte " + i + " = " + (got[i] & 0xFF) + ", want " + want[i]); return; }
|
|
}
|
|
ok(d);
|
|
}
|
|
static byte[] bytes(int... v) {
|
|
byte[] b = new byte[v.length];
|
|
for (int i = 0; i < v.length; i++) b[i] = (byte) v[i];
|
|
return b;
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
byte[] out = new byte[4096];
|
|
|
|
System.out.println("equal legs interleave left-sample-first");
|
|
LegInterleaver a = new LegInterleaver(64000);
|
|
a.offerUp(bytes(1, 2, 3, 4), 4); // two mono samples: [1,2] [3,4]
|
|
a.offerDown(bytes(9, 8, 7, 6), 4); // [9,8] [7,6]
|
|
eq(a.available(), 8, "two frames ready");
|
|
int n = a.drainInto(out, 0, out.length);
|
|
eqBytes(out, n, new int[] {1, 2, 9, 8, 3, 4, 7, 6}, "L,R,L,R with sample bytes kept in pairs");
|
|
eq(a.available(), 0, "nothing left over");
|
|
|
|
System.out.println("uneven legs: only frames present on BOTH sides are emitted");
|
|
LegInterleaver b = new LegInterleaver(64000);
|
|
b.offerUp(bytes(1, 1, 2, 2, 3, 3), 6); // three samples
|
|
b.offerDown(bytes(9, 9), 2); // one sample
|
|
eq(b.available(), 4, "one common frame only");
|
|
n = b.drainInto(out, 0, out.length);
|
|
eqBytes(out, n, new int[] {1, 1, 9, 9}, "the single common frame");
|
|
eq(b.available(), 0, "the uplink surplus is NOT emitted against silence");
|
|
b.offerDown(bytes(8, 8, 7, 7), 4); // downlink catches up
|
|
eq(b.available(), 8, "the retained surplus pairs up when its counterpart arrives");
|
|
n = b.drainInto(out, 0, out.length);
|
|
eqBytes(out, n, new int[] {2, 2, 8, 8, 3, 3, 7, 7}, "and interleaves in the original order");
|
|
|
|
System.out.println("a leg arriving in odd-sized pieces still aligns");
|
|
LegInterleaver c = new LegInterleaver(64000);
|
|
c.offerUp(bytes(1, 1), 2);
|
|
c.offerUp(bytes(2, 2), 2);
|
|
c.offerDown(bytes(9, 9, 8, 8), 4);
|
|
n = c.drainInto(out, 0, out.length);
|
|
eqBytes(out, n, new int[] {1, 1, 9, 9, 2, 2, 8, 8}, "two offers on one leg equal one on the other");
|
|
|
|
System.out.println("capacity is respected and the remainder is kept");
|
|
LegInterleaver d = new LegInterleaver(64000);
|
|
d.offerUp(bytes(1, 1, 2, 2), 4);
|
|
d.offerDown(bytes(9, 9, 8, 8), 4);
|
|
n = d.drainInto(out, 0, 4); // room for exactly one frame
|
|
eqBytes(out, n, new int[] {1, 1, 9, 9}, "only what fits is written");
|
|
eq(d.available(), 4, "the rest waits rather than being dropped");
|
|
n = d.drainInto(out, 0, out.length);
|
|
eqBytes(out, n, new int[] {2, 2, 8, 8}, "and comes out next time");
|
|
eq(d.drainInto(out, 0, 3), 0, "less than a whole frame of room writes nothing");
|
|
|
|
System.out.println("writing at an offset does not disturb what is already there");
|
|
LegInterleaver e = new LegInterleaver(64000);
|
|
e.offerUp(bytes(1, 1), 2);
|
|
e.offerDown(bytes(9, 9), 2);
|
|
out[0] = 77;
|
|
n = e.drainInto(out, 1, out.length - 1);
|
|
eq(out[0] & 0xFF, 77, "the byte before the offset is untouched");
|
|
eq(n, 4, "one frame written at the offset");
|
|
|
|
System.out.println("a stalled leg drops the OLDEST audio, keeping the channels in the present");
|
|
LegInterleaver f = new LegInterleaver(8); // room for 4 mono samples
|
|
f.offerUp(bytes(1, 1, 2, 2, 3, 3, 4, 4), 8); // fills it exactly
|
|
eq(f.droppedBytes(), 0, "at the cap, nothing dropped yet");
|
|
f.offerUp(bytes(5, 5), 2); // one over
|
|
eq(f.droppedBytes(), 2, "one sample discarded");
|
|
f.offerDown(bytes(9, 9), 2);
|
|
n = f.drainInto(out, 0, out.length);
|
|
// The oldest uplink sample [1,1] is gone, so the first frame pairs [2,2] with the live downlink.
|
|
eqBytes(out, n, new int[] {2, 2, 9, 9}, "the surviving audio is the most RECENT, not the backlog");
|
|
|
|
System.out.println("dropping never splits a sample in half");
|
|
LegInterleaver g = new LegInterleaver(5); // deliberately not a multiple of 2
|
|
g.offerUp(bytes(1, 1, 2, 2, 3, 3), 6);
|
|
eq(g.droppedBytes() % LegInterleaver.BYTES_PER_SAMPLE, 0,
|
|
"only whole samples are discarded (a half would swap every following byte pair)");
|
|
|
|
System.out.println("degenerate input is harmless");
|
|
LegInterleaver h = new LegInterleaver(64000);
|
|
eq(h.available(), 0, "nothing offered -> nothing available");
|
|
eq(h.drainInto(out, 0, out.length), 0, "draining an empty interleaver writes nothing");
|
|
h.offerUp(bytes(1, 1), 0);
|
|
eq(h.available(), 0, "a zero-length offer adds nothing");
|
|
h.offerUp(bytes(1, 1), 2);
|
|
eq(h.available(), 0, "one leg alone is never enough to emit a frame");
|
|
eq(h.drainInto(out, 0, -5), 0, "negative capacity writes nothing rather than throwing");
|
|
|
|
System.out.println();
|
|
System.out.println(pass + " passed, " + fail + " failed");
|
|
if (fail > 0) System.exit(1);
|
|
}
|
|
}
|