aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2023-09-15 20:21:35 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2023-09-15 21:17:08 +0300
commit0b47e7cf9bb7b77fa28a02aea1964540b81a7c84 (patch)
treeb1b0be0317d594cac680bf69d3857253f7f0341c
parent7fc0f17fb37326c86a83627b856a5b75f522c090 (diff)
downloadapplause2-0b47e7cf9bb7b77fa28a02aea1964540b81a7c84.tar.gz
documentation update
-rw-r--r--README.md4
-rw-r--r--TODO35
-rw-r--r--applause.lua6
-rw-r--r--dssi.lua2
-rw-r--r--evdev.lua5
-rw-r--r--sndfile-stream.lua1
6 files changed, 34 insertions, 19 deletions
diff --git a/README.md b/README.md
index 685efd3..082d8de 100644
--- a/README.md
+++ b/README.md
@@ -44,7 +44,7 @@ Example (one channel):
echo -ne "25 \nStream.SinOsc(440):play()" | socat -,ignoreeof TCP:127.0.0.1:10000"
-See also `client.tes` for a SciTECO integration.
+See also `client.tes` for a [SciTECO](https://github.com/rhaberkorn/sciteco) integration.
# Joysticks and Gamepads
@@ -68,3 +68,5 @@ to expose them as MIDI events.
* [midicontroller](https://sourceforge.net/projects/midicontrol/) for producing MIDI CC events
* MIDI Tracker ???
* evtest to find and test HID devices
+* listplugins and analyseplugin to inspect LADSPA plugins
+* dssi_list_plugins and dssi_analyse_plugin to inspect DSSI plugins
diff --git a/TODO b/TODO
index 619459e..c157b61 100644
--- a/TODO
+++ b/TODO
@@ -3,14 +3,9 @@
* Stream:foreach() cannot be interrupted
Perhaps C core should export an interrupted variable that we can check from Lua.
For Stream:play() this is solved differently.
-* Stream:gtick() is not real-time safe but called from tick functions currently.
- This could be resolved by letting gtick() return an initializer function and only
- this initializer function will return the tick function.
- Streams could implement a get_tick_init() method and Stream:gtick() would continue
- to exist as a shortcut.
-* EvdevStream("TrackPoint"):evrel('REL_X'):scale(440,880):SinOsc():play()
- Afterwards even Stream.SinOsc(880):play() will stutter.
- However, this seems to happen only with the builtin speakers and with other programs as well.
+* SndfileStream(...):sub(...) does not work for multi-channel audio files.
+ The reason is that SubStream ticks in gtick() to seek in the source stream
+ which cannot work in cached streams (SndfileStream:ctor() caches for multi-channel streams).
# Features
@@ -26,22 +21,29 @@
* Multi-core support via GStreamer-like queue:
https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-plugins/html/gstreamer-plugins-queue.html
* Stream optimizer
- * Automatic caching (finding identical subtrees)
+ * Automatic caching (finding identical subtrees).
+ * Removing contraproductive caching, e.g. after plain number streams, MIDIStream, EvdevStream...
* Automatic paralellization
* Automatic eager evaluation of small Streams independant of real-time input.
- * Resolving Stream:sub() by alternative means, e.g. specifying an osciallator phase or
- passing in a seek to a SndfileStream.
+ * Moving Stream:evabs() and Stream:sub() closer down the source, so we can make
+ use of per-class optimizations.
* ...
+* Allow stringified timestamps everywhere, where we currently accept lengths in samples. tosamples()?
* Github pages (LDoc documentation).
They can be automatically pushed by a Github action.
Since they will always be public, copyright questions should be resolved first.
# Improvements
-* add optional Stream:gtickCtx() (or Stream:get_tick_init()) containing potentially real-time unsafe code.
- Higher-order streams call Stream:gtickCtx() for all dependant streams only
- once in their own gtickCtx() function.
- This will allow gtick() to be called in tick-functions (that must be real-time safe).
+* Stream:gtick() is currently not real-time safe but called from tick functions
+ (either to reset the stream or to start is whenever this cannot be prepared for in the parent gtick()).
+ This is especially a problem for SndfileStream.
+ We must somehow avoid all costly operations in gtick(), doing them in ctor() instead.
+ Furthermore, we could theoretically avoid table lookups in gtick() by binding
+ Stream attributes to local variables.
+ This could be achieved most easily by assigning self.gtick to a lambda in ctor().
+ Furthermore, tick() functions should always cache self.gtick, so as to avoid
+ table lookups.
* It could be useful to pass a timestamp (in samples) into the tick function.
This will simplify some calculations and allows resetting a stream elegantly (for instance in RepeatStream).
It will also speed up seeks, as in SubStream.
@@ -63,3 +65,6 @@
The reduced accuracy shouldn't hurt us much.
* Allow building LuaJIT with -DLUAJIT_ENABLE_LUA52COMPAT.
This will enable #Stream and we may implement an __ipairs metamethod.
+* Per-class optimizations.
+ * SndfileStream:sub() for seeking in sound files.
+ * EvdevStream:evabs() for retrieving the minimum/maximum values automatically.
diff --git a/applause.lua b/applause.lua
index 08d0415..2d86aa6 100644
--- a/applause.lua
+++ b/applause.lua
@@ -90,7 +90,7 @@ end
samplerate = 44100
--- Convert seconds to sample numbers
--- These are functions, so we can round the result
+-- These are functions, so we can round the result.
-- automatically.
-- @number[opt=1] x Number of seconds
-- @treturn int Number of samples
@@ -1709,7 +1709,9 @@ function SubStream:gtick()
-- overwritable gtick_seek(). Problem as always is that
-- this would have to chain to substreams.
-- Perhaps, it would be wiser to let this be handled by
- -- an optimizer stage that resolves Stream:sub-calls.
+ -- an optimizer stage that resolves Stream:sub()-calls.
+ -- @fixme Actually, this is plain wrong and does not work
+ -- if self.stream is cached.
for _ = 1, self.i-1 do tick() end
local i = self.i
diff --git a/dssi.lua b/dssi.lua
index ce6ca47..7c44c01 100644
--- a/dssi.lua
+++ b/dssi.lua
@@ -546,6 +546,8 @@ DSSIStream = DeriveClass(Stream)
--
-- @fixme We could simplify things by just assuming a flat array of
-- input ports.
+-- @todo We have everything to provide in-program plugin listing and introspection.
+-- E.g. DSSIStream.list().
function DSSIStream:ctor(file, midi_event_stream, ...)
local plugin_file, label = file:match("^([^:]+):(.+)")
plugin_file = plugin_file or file
diff --git a/evdev.lua b/evdev.lua
index 4eba28c..eb1a78b 100644
--- a/evdev.lua
+++ b/evdev.lua
@@ -62,10 +62,12 @@ EvdevStream = DeriveClass(Stream)
-- @treturn EvdevStream
-- A stream of C structures, describing the event in detail.
-- Its fields will be 0 if no event ocurred.
--- @todo Document the C structure as a Lua table.
-- @see Stream:evrel
-- @see Stream:evabs
-- @see Stream:evkey
+-- @todo Document the C structure as a Lua table.
+-- @todo We could introduce something like EvdevStream.list() to get at least some
+-- introspection without having to call evtest.
function EvdevStream:ctor(id, grab)
local grab = grab == nil or grab
@@ -158,6 +160,7 @@ end
-- @fixme min and max can be read from the properties of the corresponding code.
-- This would however require us to do all postprocessing already in EvdevStream:gtick()
-- or even in applause_evdev_new().
+-- Or simply overwrite this function in EvdevStream as an optimization.
function Stream:evabs(code, min, max)
code = ffi.cast("enum applause_evdev_abs", code)
diff --git a/sndfile-stream.lua b/sndfile-stream.lua
index 248f82a..1c394b8 100644
--- a/sndfile-stream.lua
+++ b/sndfile-stream.lua
@@ -52,6 +52,7 @@ function SndfileStream:gtick()
-- read pointer which is important when reusing the stream.
-- NOTE: We could do this with a single handle per object but
-- by maintaining our own read position and seeking before reading.
+ -- @fixme On the downside, this gtick() is not real-time safe.
local handle = sndfile:new(self.filename, "SFM_READ",
self.samplerate, self.channel_no, self.format)