4bbfdcceff
audio-surface.el / image-surface.el: own-core additive-synthesis WAV and
raster-PNG renderers (integer-only DSP, since EL has no floats), rendered
from learned engram signatures via a pluggable surface-profile
abstraction (surface-profile.el). audio-demo.el / image-demo.el are
drivers. NOTE: demo files hardcode absolute paths to this worktree's own
directory — will need a path fixup before landing.
elp/projector/ is a Python package the author's own README marks as
"STAGING/PROOF-OF-SHAPE — not the deliverable", superseded by the native
.el surface-profile work above; kept as a validated architecture proof.
Generated output (elp/faculty/{out,sig}, elp/projector/out,
__pycache__) intentionally excluded.
154 lines
7.3 KiB
EmacsLisp
154 lines
7.3 KiB
EmacsLisp
// surface-profile.el - Surface profile data and accessors.
|
|
//
|
|
// THE NATIVE EFFERENT SEAM: surface = a pluggable PROFILE, using the exact same
|
|
// slot-map mechanism as language-profile.el. A language profile tells the
|
|
// realizer HOW to shape a natural-language surface (word order, morphology); a
|
|
// SURFACE profile tells the realizer WHICH surface to project meaning onto
|
|
// (markdown, docx, html, plain, or a non-text medium like symbolic music).
|
|
//
|
|
// The generalization is exact: realize_lang(form, profile) already renders a
|
|
// SemForm parameterized by a [String] profile read via lang_get. Surface is one
|
|
// more axis of that same profile vector. One frame (sem_frame), one plan step
|
|
// (sem_to_spec), one render (realize) — the surface is DATA, not a code path,
|
|
// precisely as language is data. Adding a surface means adding a profile, no
|
|
// engine change. This is the multimodal projector, native: geometry -> any
|
|
// surface, the efferent twin of ingest.
|
|
//
|
|
// Surface slot keys:
|
|
// surface - "markdown" | "docx" | "html" | "plain" | "midi" | "image"
|
|
// modality - "text" | "audio" | "image" | "video"
|
|
// media_type - MIME type of the emitted surface
|
|
// head_open - string prepended to a heading (e.g. "## " for markdown)
|
|
// head_close - string appended to a heading (e.g. "" for markdown, "</h2>" for html)
|
|
// emph_open - string opening emphasis (e.g. "*")
|
|
// emph_close - string closing emphasis (e.g. "*")
|
|
// item_mark - list-item marker (e.g. "- ")
|
|
// para_sep - paragraph separator (e.g. "\n\n")
|
|
//
|
|
// For a TEXT modality the render composes these markers around the surface that
|
|
// the EXISTING realizer produces (realize_lang / sem_realize). For a non-text
|
|
// modality (audio/image) the profile declares modality + media_type and the
|
|
// render dispatches to the medium projector, which reads the SAME frame's
|
|
// geometry (its intent/affect/structure) and projects it onto sound or pixels —
|
|
// deterministic-from-meaning, nothing invented. That dispatch point is where a
|
|
// music profile or image profile conforms, native, no parallel layer.
|
|
|
|
// -- Constructor -------------------------------------------------------------
|
|
|
|
fn surface_profile(surface: String, modality: String, media_type: String, head_open: String, head_close: String, emph_open: String, emph_close: String, item_mark: String, para_sep: String) -> [String] {
|
|
let r: [String] = native_list_empty()
|
|
let r = native_list_append(r, "surface")
|
|
let r = native_list_append(r, surface)
|
|
let r = native_list_append(r, "modality")
|
|
let r = native_list_append(r, modality)
|
|
let r = native_list_append(r, "media_type")
|
|
let r = native_list_append(r, media_type)
|
|
let r = native_list_append(r, "head_open")
|
|
let r = native_list_append(r, head_open)
|
|
let r = native_list_append(r, "head_close")
|
|
let r = native_list_append(r, head_close)
|
|
let r = native_list_append(r, "emph_open")
|
|
let r = native_list_append(r, emph_open)
|
|
let r = native_list_append(r, "emph_close")
|
|
let r = native_list_append(r, emph_close)
|
|
let r = native_list_append(r, "item_mark")
|
|
let r = native_list_append(r, item_mark)
|
|
let r = native_list_append(r, "para_sep")
|
|
let r = native_list_append(r, para_sep)
|
|
return r
|
|
}
|
|
|
|
// -- Accessor (same convention as lang_get; standalone so this is a leaf) -----
|
|
|
|
fn surface_get(profile: [String], key: String) -> String {
|
|
let n: Int = native_list_len(profile)
|
|
let i: Int = 0
|
|
while i < n - 1 {
|
|
let k: String = native_list_get(profile, i)
|
|
if str_eq(k, key) {
|
|
return native_list_get(profile, i + 1)
|
|
}
|
|
let i = i + 2
|
|
}
|
|
return ""
|
|
}
|
|
|
|
fn surface_is_text(profile: [String]) -> Bool {
|
|
return str_eq(surface_get(profile, "modality"), "text")
|
|
}
|
|
|
|
// -- Built-in TEXT surface profiles ------------------------------------------
|
|
|
|
// Markdown: headings with "## ", emphasis with "*", "- " list items.
|
|
fn surface_profile_markdown() -> [String] {
|
|
return surface_profile("markdown", "text", "text/markdown", "## ", "", "*", "*", "- ", "\n\n")
|
|
}
|
|
|
|
// Plain text: no markup at all — headings become bare uppercase-free lines.
|
|
fn surface_profile_plain() -> [String] {
|
|
return surface_profile("plain", "text", "text/plain", "", "", "", "", " - ", "\n\n")
|
|
}
|
|
|
|
// HTML: block-level heading/emphasis tags.
|
|
fn surface_profile_html() -> [String] {
|
|
return surface_profile("html", "text", "text/html", "<h2>", "</h2>", "<em>", "</em>", "<li>", "\n")
|
|
}
|
|
|
|
// docx: WordprocessingML is structural, not inline-markup; the head/emph slots
|
|
// carry the run/style intent that the OOXML emitter maps to <w:pStyle>. Declared
|
|
// here so docx is a first-class surface on the same seam.
|
|
fn surface_profile_docx() -> [String] {
|
|
return surface_profile("docx", "text", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "Heading2:", "", "b:", "", "bullet:", "\n")
|
|
}
|
|
|
|
// -- Built-in NON-TEXT surface profiles (the multimodal seam) ----------------
|
|
|
|
// Symbolic music (MIDI): modality=audio. The render dispatches to the music
|
|
// projector, which reads the SAME frame's intent/affect and projects it to
|
|
// pitch/rhythm — deterministic-from-meaning. head/emph slots are empty because
|
|
// the medium is not textual; media_type names the surface. A music profile
|
|
// (scale/mode/instrument) is layered onto this by the audio agent, native.
|
|
fn surface_profile_midi() -> [String] {
|
|
return surface_profile("midi", "audio", "audio/midi", "", "", "", "", "", "")
|
|
}
|
|
|
|
// Synthesized audio (WAV): modality=audio, peer to midi. The richer audio
|
|
// surface — the render SUPERPOSES ingested tonal primitives (sine at f0*n per an
|
|
// ingested instrument signature) into PCM, own-core, exactly as midi writes an
|
|
// SMF via struct. A music profile (scale/mode/instrument/adsr) layers onto this
|
|
// as its own [String] slot-map read by the same getter. Same frame -> midi OR
|
|
// audio, interchangeable; this is the audio agent's native conforming point.
|
|
fn surface_profile_audio() -> [String] {
|
|
return surface_profile("audio", "audio", "audio/wav", "", "", "", "", "", "")
|
|
}
|
|
|
|
// Image (raster): modality=image. Documented seam — the render dispatches to the
|
|
// image projector, the efferent twin of image ingest, reading the same frame.
|
|
fn surface_profile_image() -> [String] {
|
|
return surface_profile("image", "image", "image/png", "", "", "", "", "", "")
|
|
}
|
|
|
|
// -- Composition helpers: wrap realized TEXT with the surface's markers -------
|
|
//
|
|
// These take text the EXISTING realizer already produced and shape it for the
|
|
// surface. They add NO content — pure surface typography over faithful text,
|
|
// exactly as the language profile adds no content, only linguistic form.
|
|
|
|
fn surface_heading(profile: [String], text: String) -> String {
|
|
let o: String = surface_get(profile, "head_open")
|
|
let c: String = surface_get(profile, "head_close")
|
|
return o + text + c
|
|
}
|
|
|
|
fn surface_emph(profile: [String], text: String) -> String {
|
|
let o: String = surface_get(profile, "emph_open")
|
|
let c: String = surface_get(profile, "emph_close")
|
|
return o + text + c
|
|
}
|
|
|
|
// A section: a heading + a paragraph separator + the (already realized) body.
|
|
fn surface_section(profile: [String], heading: String, body: String) -> String {
|
|
let sep: String = surface_get(profile, "para_sep")
|
|
return surface_heading(profile, heading) + sep + body
|
|
}
|