Files
el/lang/runtime/el_peripheral_null.c
T
Neuron c26b6aac82
El SDK CI - dev / build-and-test (pull_request) Failing after 4m18s
organ: the rest of the peripheral moves into El
The speaker and the voice-fetch landed in the previous commit. This is the
remainder of the 939-line Swift program, ported, and the line it draws is
between DEVICE and ARITHMETIC rather than between languages.

Two things stay realizers, because they are the two things El cannot express
as arithmetic: handing a buffer to the DAC and waiting for it to drain
(el_audio_darwin.m), and asking the OS for samples off a mic or frames off a
camera (el_capture_darwin.m). Both are their own translation units declared
in el_runtime.h, never patches to el_runtime.c.

Everything else is El. WAV decode, LPC autocorrelation, Levinson-Durbin at
order 16, formant extraction off the all-pole envelope, source-filter
resynthesis, and the three descriptors are organ_dsp.el. Consent, disclosure
and the scene descriptor are organ.el. Barge-in, yield-or-hold, backchannel
and resume are organ_converse.el.

The organ never learns a word. Codes and phoneme geometry arrive from the
language side; the organ turns them into samples and gets the samples out the
speaker, and runs the same trip in reverse for the senses. No lexicon, no
grapheme-to-phoneme, by design.

Barge-in needed pause/resume and a real DAC position rather than a tick
counter, because "finish the buffer" is not barge-in and a queue holding
three buffers is a third of a second wrong about where it is. An injected
barge also had to fire once rather than stay true, which is otherwise a
livelock the moment a backchannel resumes.

Measured against the Swift on out/mic_room.wav: seconds, rms, peak, zcr,
centroid and F0 agree to every printed digit; formants F1-F5 and bandwidths
B1-B5 are identical. imitate cannot match bit-for-bit because the Swift
excites unvoiced frames with Double.random — two Swift runs correlate 0.957
with each other and El correlates 0.958 with Swift, so the port is as close
to the original as the original is to itself.

Verified end to end: consent fails closed on both locks, real mic capture
(16000 frames), real camera frame (1920x1080 -> 15 numbers), voiceprint,
imitate, hear-imitate, a voice learned by ear and fetched back out of the
engram, and all five converse paths with real audio. The binary contains
zero afplay/Swift strings and spawns no child process while speaking.
2026-08-16 16:42:41 -05:00

90 lines
3.9 KiB
C

/* el_peripheral_null.c — the no-device build of El's I/O organ.
*
* Every entry point declared in el_runtime.h's "Peripheral" block, implemented
* as an honest refusal. This is what a platform without an El audio/capture
* realizer links instead of el_audio_darwin.m + el_capture_darwin.m, so an El
* program that speaks or listens still COMPILES AND LINKS everywhere.
*
* The distinction that matters: these do not pretend. speaker_available() and
* mic_available() return 0, and every operation returns its failure sentinel.
* A program asking "can I speak here?" gets a truthful no, rather than a
* silence it would have to infer something from. Silent success is the failure
* mode this whole change exists to eliminate — El spent this entire codebase's
* history writing WAV files full of zeros and reporting ok=true, and nobody
* caught it because nothing ever said "there is no sound here".
*
* Compiled INSTEAD OF the Darwin realizers, never alongside them — the symbols
* are the same by design, which is the point: the El side never branches on
* platform, it branches on speaker_available().
*/
#include "el_runtime.h"
#if !defined(__APPLE__)
/* ── Speaker ─────────────────────────────────────────────────────────────── */
el_val_t speaker_available(void) { return (el_val_t)0; }
el_val_t speaker_name(void) { return EL_STR("none"); }
el_val_t speaker_play_pcm16(el_val_t samples, el_val_t sample_rate) {
(void)samples; (void)sample_rate;
return (el_val_t)0;
}
el_val_t speaker_play_wav(el_val_t path) {
(void)path;
return (el_val_t)0;
}
el_val_t speaker_play_pcm16_async(el_val_t samples, el_val_t sample_rate) {
(void)samples; (void)sample_rate;
return (el_val_t)0;
}
el_val_t speaker_play_wav_async(el_val_t path) {
(void)path;
return (el_val_t)0;
}
el_val_t speaker_pause(void) { return (el_val_t)0; }
el_val_t speaker_resume(void) { return (el_val_t)0; }
el_val_t speaker_playing(void) { return (el_val_t)0; }
el_val_t speaker_stop(void) { return (el_val_t)0; }
el_val_t speaker_played_frames(void) { return (el_val_t)0; }
/* WAV geometry is pure parsing and would work fine here, but reporting a
* duration for audio this build cannot play would invite a caller to sequence
* around a silence. Refuse consistently with the rest of the file. */
el_val_t wav_frames(el_val_t path) { (void)path; return (el_val_t)0; }
el_val_t wav_rate(el_val_t path) { (void)path; return (el_val_t)0; }
/* ── Microphone ──────────────────────────────────────────────────────────── */
el_val_t mic_available(void) { return (el_val_t)0; }
el_val_t mic_request_access(void) { return (el_val_t)0; }
/* Empty list, not 0: the contract says capture returns samples, and a caller
* iterating the result must find nothing rather than dereference a non-list. */
el_val_t mic_capture_pcm16(el_val_t seconds, el_val_t sample_rate) {
(void)seconds; (void)sample_rate;
return el_list_empty();
}
el_val_t mic_monitor_start(void) { return (el_val_t)0; }
el_val_t mic_monitor_rms(void) { return el_from_float(0.0); }
el_val_t mic_monitor_stop(void) { return (el_val_t)0; }
/* ── Camera ──────────────────────────────────────────────────────────────── */
el_val_t camera_available(void) { return (el_val_t)0; }
el_val_t camera_request_access(void) { return (el_val_t)0; }
el_val_t camera_capture_rgb(void) { return (el_val_t)0; }
el_val_t camera_capture_jpeg(el_val_t path) {
(void)path;
return (el_val_t)0;
}
#endif /* !__APPLE__ */