Adaptive Physical Communication System (APCS)

Performance

How fast each channel is, where the time goes, and how the app keeps the UI smooth while it decodes camera frames or audio in real time. All the numbers come from the formulas in the code or from the test suite’s measurements. The derivations are in Calculations.

Back to the documentation index.


Contents

  1. Channel speeds
  2. Transfer time tables
  3. Where Light time goes
  4. Where Sound time goes
  5. CPU and threading
  6. Memory
  7. Battery and heat
  8. App size
  9. Measured results
  10. Tuning for speed

1. Channel speeds

The Nominal column is calculated from each profile’s timing. Estimated goodput multiplies it by the decode rates measured in the camera and room simulators and by the fountain overhead. The ranges are recommendations. None of these columns comes from a study across many phones, so real devices can be faster or slower; see Known Issues §6.

Channel Nominal Estimated goodput Recommended range
Light, Auto (v8–v12, 12 fps) 1.9–4.0 KB/s ≈1.3–2.5 KB/s 15–40 cm
Light, Safe (v8, 8 fps) 1.28 KB/s ≈0.9 KB/s Weak cameras
Light, Fast (v17, 12 fps) 7.2 KB/s ≈2.5 KB/s if the camera keeps up Good cameras only
Sound, Rugged / Safe / Standard / Fast 10.8 / 18.1 / 27.0 / 35.8 B/s ≈80% of nominal after fountain overhead 0.3–2 m
Sound, Silent Robust / Silent (inaudible) 3.4 / 5.0 B/s ≈80% of nominal 0.1–0.5 m, phone-dependent
Vibration (experimental) ≈0.52 B/s raw Not measured: real transfers usually fail (Known Issues §2.8) Touching

Light is about 35–70× faster than the fastest Sound profile. That’s why photos and videos go by Light.


2. Transfer time tables

Light (Auto, typical camera):

Payload ETA
Text message ≈1 s
2 KB photo sample (3.4 KB envelope after re-encode) ≈3 s
5 KB photo sample (8.6 KB) ≈5 s
20 KB photo sample (33 KB) ≈16–17 s
80 KB video ≈38 s
140 KB video ≈65 s
120 KiB photo (compression cap) ≈57 s

Sound:

Payload Rugged Safe Standard Fast Silent Silent Robust
“sos” (10 B) 11.9 s 10.6 s 9.5 s 7.2 s 19.1 s 28.6 s
100-character text (107 B) 20.8 s 15.9 s 11.8 s 8.9 s 43 s 64 s
500 B 65 s 42 s 28 s 21 s 2.3 min 3.5 min
2 KB photo sample (3.4 KB) ≈6.7 min ≈4.0 min ≈2.8 min ≈2.1 min too slow too slow

These are the expected times (⌈1.25·K⌉ + 2 frames). When every frame lands, a receiver finishes after exactly K frames: “sos” is one frame, 2.4 s on Standard and 4.8 s on Silent.

Vibration (calculated; the channel is experimental and real transfers usually fail): “hi” ≈73 s, “hello” ≈79 s, a full 48-byte packet ≈148 s.


3. Where Light time goes

per displayed frame (83 ms at 12 fps):
  sender:   LT symbol (XOR of up to ~21 blocks) + APCF header + CRC-32   < 1 ms
            QR matrix with fixed mask 0                                  ≈ 4 ms   (15–40 ms with mask search)
            paint (merged dark runs, no anti-aliasing)                   ≈ 1 frame
  receiver: camera capture (30 fps)                                      33 ms apart
            Y-plane copy of a 706×706 crop                               ≈ 0.5 MB memmove
            zxing2 decode in the isolate                                  tens of ms
            LT ingest (incremental Gauss-Jordan)                          < 1 ms (K = 422)

The bottleneck is the camera’s decode rate, not the CPU. A frame is lost when:

The fountain code turns all of these into “a bit more time” instead of failure. Auto density keeps the QR version where the decode rate stays high: v8 about 70%, v12 about 55%, v17 about 31%, v20 about 13% in the camera simulator.


4. Where Sound time goes

per frame (Standard, 2.368 s):
  2 048-sample sync marker            46 ms
  25 data symbols × 4 096 samples     2.32 s
per burst: 120 ms of lead silence, then 2–4 frames back-to-back

5. CPU and threading

Work Thread Why it stays smooth
QR rendering UI thread Fixed mask (≈4 ms), integer module sizes, merged rectangles, repaint only when the bitmap changes
Camera frame extraction Camera callback (UI isolate) Y-plane row copies only; skipped entirely when the decoder is busy
QR decoding One long-lived background isolate TransferableTypedData (no copy), at most one frame in flight, 2 s reply timeout
LT decoding UI isolate Incremental: each symbol costs at most about K × K/32 word XORs (≈41 000 for K = 422), well under a millisecond
Audio capture and conversion Plugin thread → Dart PCM16 converted straight into a Float32List (no per-sample boxing)
Tone detection and RS decoding Dart isolate (UI) Goertzel on the needed bins only; RS is O(n·P) per frame
Live frequency readout, receiver Dart isolate (UI) Each mic chunk is only copied into a 1024-sample ring. The FFT (1024 points, precomputed twiddles and window, about 5 000 butterflies) runs only when the 80 ms UI throttle fires, so at most 12.5 times a second
Live frequency readout, sender UI isolate No audio analysis: the tone schedule is written while the burst is rendered (a few hundred segments), and each 50 ms tick is a binary search. The timer runs only while a burst is playing
Frequent UI updates UI isolate The readout has its own acousticSpectrumState notifier, so only its card rebuilds, not the screen
Timers UI isolate 80 ms receive poll, 500 ms metrics tick, 1 800 ms idle timer

Frames are dropped, not queued, when the decoder is busy. Queueing would add latency and memory without adding information, because the fountain only needs some frames, not all frames.


6. Memory

Item Size
One camera luminance crop ≈0.5 MB (706 × 706)
LT decoder, K = 422, 330-byte blocks ≈163 KB (coefficient rows + payload rows)
LT decoder, K = 1 133 ≈0.5 MB
Up to 3 concurrent Light sessions 3 × the above, worst case
Sound burst WAV (4 Standard frames) ≈0.8 MB PCM16
Largest envelope accepted by Light 8 MiB (soft cap); practical < 200 KB

7. Battery and heat


8. App size

Component Size
Universal release APK ≈58 MB
Bundled samples (16 photos + 9 videos) 1 238 839 B ≈ 1.2 MB
Branding assets (logo + mark) 103 925 B ≈ 100 KB

flutter build apk --split-per-abi produces much smaller per-architecture APKs; most of the universal size is the Flutter engine and native plugin libraries for every CPU architecture.


9. Measured results

From the test suite (Testing):

Measurement Result
2 KB file, Auto, typical camera, 30% frame loss Completes after 22 frames shown (13 decoded), ≈1.8 s
2 KB file, hard camera at 1.5× zoom Completes after 23 frames shown (14 decoded), ≈1.9 s
Old 800-byte density, hard camera 0 frames decoded in 20 s
40 KB photo / 30 KB video through real QR + zxing2 + LT at 30% loss Byte-exact
Fountain overhead (measured mean) 0–2.2 symbols
Full test suite 101 tests (100 run, 1 skipped), ≈39 s
Full optical density sweep (OPTICAL_SWEEP=1) ≈3 min 16 s

10. Tuning for speed

Situation Setting Gain
Good receiver camera, steady hands Light Standard or Fast Up to 2× on large files
Weak camera Light Safe + 2× zoom at 25 cm Completes instead of stalling
Quiet room, phones close Sound Fast 1.3× over Standard
Big file Always Light 35–70× over Sound Fast
Many receivers Light Auto (sparse codes) Every camera decodes independently; no extra time

More in Light Channel and Sound Channel.