luvcraft/sound.lisp
How many seconds of sound the pump keeps queued ahead of the speaker.
Enough that a busy frame or a garbage collection does not run the queue dry, little enough that a pan or a gain change is heard within a blink.
Cells from the screen at which the film is heard at full volume; beyond it the sound falls off with the square of the distance.
True once a film that does not loop has all been handed to the sink.
The sink's frame count when the current pass through the film began.
Written by the render thread, read by the pump.
One film's soundtrack, playing.
Open pathname's soundtrack into a sink and start pumping it, or return
NIL for a silent film.
The pump: keep the sink fed until told to stop.
Stop the pump, then release the sink and the decoder.
Seconds into the current pass of the film, as heard.
Negative for the moment after a rewind while the previous pass's tail is still coming out of the speaker: the picture should hold its last frame until this comes round to zero.
Hear sound, which comes from world point source, at listener facing with
right as the ear-to-ear axis: set the gain by distance and the pan by
bearing.
Distance follows an inverse square past the reference distance -- a screen in the next field is a murmur, at the wall it is the film. Pan is constant power over the bearing's sine, so walking past the screen swings it from one ear to the other without a dip in the middle.
The bearing's sine: how far to the right the source lies, from -1 (hard left) to 1 (hard right). A source at the listener has no bearing and sits in the middle.
(screen device)Decode up to the picture that is due now and upload it. Return true if so. Pictures that came due while the last world frame was being drawn are decoded and discarded rather than shown, so the film keeps the world's time instead of the renderer's. A film with sound keeps the sound's time instead: the ear is the…
How many seconds of sound the pump keeps queued ahead of the speaker. Enough that a busy frame or a garbage collection does not run the queue dry, little enough that a pan or a gain change is heard within a blink.
Cells from the screen at which the film is heard at full volume; beyond it the sound falls off with the square of the distance.
One film's soundtrack, playing.
(pathname &key (loop-p t))Open PATHNAME's soundtrack into a sink and start pumping it, or return NIL for a silent film.
(pathname)Open PATHNAME's best audio stream and start a decoder for it. Returns an AUDIO-TRACK, or NIL when the file has no sound. The caller owns it and must CLOSE-AUDIO it.
(&key (rate 48000) (channels 2))Open a playback stream taking CHANNELS-channel float frames at RATE. The device is opened at whatever it prefers; SDL converts. Playback starts at once, so a sink with nothing queued is one playing silence.
(sound)(sink)(track)Test whether one compatible scalar is greater than another.
(track)Decode until TRACK's frame holds the next run of samples, or NIL at the end of the file.
(track &optional buffer)Return TRACK's current frame folded to mono single-floats, and how many. BUFFER is reused when it is large enough; otherwise a fresh one is made. The count is the number of samples written, which is what matters, since the buffer may be longer. Every sample format a decoder hands out is read here directly -- planar…
(sink samples count &key (left 1.0) (right 1.0))Queue COUNT mono SAMPLES for SINK, placed between the channels by LEFT and RIGHT. A two-channel sink gets the sample times LEFT on the left and times RIGHT on the right; any other channel count gets it times LEFT everywhere. This is where a point source becomes a stereo image: the film's sound is one signal, and its…
(track)(category control &rest arguments)Write one timestamped line about CATEGORY, formatted from CONTROL. CATEGORY is a keyword naming the subsystem -- :canvas, :watchdog, :vulkan -- so a reader can tell at a glance which machine is talking.
(sound)Logical conjunction of tests and raw truth values.
Logical negation of one test or raw truth value.
(sound)Seconds into the current pass of the film, as heard. Negative for the moment after a rewind while the previous pass's tail is still coming out of the speaker: the picture should hold its last frame until this comes round to zero.
Division of two represented quantities.
Subtraction or unary negation.
(sink)How many frames have gone out: pushed less still queued. This is the sink's clock, in frames at its own rate.
Convert one scalar float or unsigned value to a 32-bit float.
(sound source listener right)Hear SOUND, which comes from world point SOURCE, at LISTENER facing with RIGHT as the ear-to-ear axis: set the gain by distance and the pan by bearing. Distance follows an inverse square past the reference distance -- a screen in the next field is a murmur, at the wall it is the film. Pan is constant power over the…
The componentwise square root of a raw value.
Addition over compatible quantities.
Multiplication and scalar scaling.
Test whether one compatible scalar is at most another.
Test whether one compatible scalar is less than another.
A film's sound: decoded on its own thread, heard from where the player stands, and the clock the picture keeps time by.
The pump is one thread per playing film. It keeps a quarter second of sound queued in an SDL audio sink and otherwise sleeps; every push places the mono signal between the two channels according to the pan the render thread last computed, and the sink's own gain carries the distance. Two threads share three numbers -- gain, left, right -- each written whole and read whole, which is all the synchronisation a float needs.
The clock: frames the sink has actually played, minus the frame count at the last rewind, over the rate. That is the film's time as the ear hears it, and
advance-video-screenshows the picture that is due at it.