Alright, I hummed and hawed too much about this. I wrote a
trivial sndfile ecl lisp snippet. It's just one screen of
lisp that's mostly one of the sndfile examples. My dream is
that someone else could also try playing with it (as trivial
sound making goes). So I will talk about dependencies,
download the lisp files, building it, and an example synth
program which I will also inline here.
I'm on openbsd, so please divine this into your own package
manager:
pkg_add ecl libsndfile mpv lynx
I am just using system calls to mpv to play the notes, and
lynx to download the lisp. Ecl is the compiler, and
libsndfile is libsndfile. Now I'm going to use shell to
download some text files (ecl lisp source) using lynx.
```ksh
mkdir conspiracy # it's named conspiracy.
cd conspiracy
lynx
gopher://gopher.club/0/users/screwtape/conspiracy/build.ecl -dump \
> build.ecl
lynx
gopher://gopher.club/0/users/screwtape/conspiracy/conspiracy.ecl \
-dump > conspiracy.ecl
lynx
gopher://gopher.club/0/users/screwtape/conspiracy/foo.syn \
-dump > foo.syn # example
mkdir notes # note wavs will go into here.
```
At this juncture, you should probably lay eyes on what's in
each of those files so you know I'm not virusing you ;p.
They're not very big. For portability there's no pledge or
unveil.
```ksh
ecl --load build.ecl ## This builds an executable named sine
/sine --load foo.syn
```
foo.syn is actually just another lisp file that uses the
conspiracy.ecl built into ./sine.
The mechanism, which sucks and is slow but is extremely
general is to redefun the functions #'left-fun and
#'right-fun (float) -> float then call (my-get-note
"note-file-name" float-duration) -> lambda that makes a
system call to mpv to play the note.
So a "syn" lisp (or just in ./sine's repl) is like
```foo.syn
(defun left-fun (float)
(values (apply (make-sine 440) `(,float))))
(defun right-fun (float)
(values (apply (make-sine 660) `(,float))))
(setq *lambda-1* (my-get-note "test-note-1" 1.2))
(funcall *lambda-1*)
(defun left-fun (float)
(values (apply (make-sine 110) `(,float))))
(defun right-fun (float)
(values (apply (make-sine 55) `(,float))))
(setq *lambda-2* (my-get-note "test-note-2" 3.6))
(funcall *lambda-2*)
(funcall *lambda-1*)
(funcall *lambda-2*)
```
(ecl) async repeating can be like
(setq *process*
(mp:process-run-function 'example
(lambda ()
(loop for x below 10 do (sleep 1)
do (funcall *lambda-2*)))))
(mp:process-join *process*)
But I don't want to complicate things more here.