aboutsummaryrefslogtreecommitdiffhomepage
path: root/applause.lua
AgeCommit message (Collapse)AuthorFilesLines
2024-03-16Stream:gnuplot() now supports writing to an output filev0.1Robin Haberkorn1-2/+8
* Especially useful to generate PDF plots for my thesis.
2024-01-29revised Stream:resample() - it takes a stream factor now, so you can control ↵Robin Haberkorn1-19/+64
playpack speed * The old implementation was simple but severely limited: * the resample factor (playback speed) could only be scalar * for infinite source streams, the algorithm would require infinitely growing memory. The algorithm therefore also wasn't realtime-safe and quite slow (probably because of reallocations). * This could be made to work with stream-factors if the source stream is infinite, but we couldn't get rid of the memory requirements due to being based on IndexStream. * Instead, there is a custom ResampleStream now that backs Stream:resample(). It also performs linear interpolation but has constant memory requirements and works with factor-streams. Even for finite source streams and constant factors this implementation will be faster and more real-time safe. * You cannot play backwards, due to missing buffering. This can still be done manually using IndexStream if necessary.
2024-01-12Stream:gnuplot() supports plotting into Kitty terminals nowRobin Haberkorn1-0/+13
2023-12-19fft.lua: added support for Fourier analysis (FFT/IFFT)Robin Haberkorn1-0/+1
* Allows one-time analysis of arrays or short streams. * Transformation on real-time streams * Magnitude and phase extraction * Windowing (only Hamming for the time being).
2023-12-10added Stream:partition() operationRobin Haberkorn1-0/+53
* Inspired by APL's partition function, although this always partitions into chunks of the same size. * Meant to be used for real-time FFT analys and synthesis. * Added Stream:each() and Stream:reduce() as APL-like aliases for Stream:map() and Stream:fold().
2023-12-10updated Jupyter notebook documentation after ILua forkingRobin Haberkorn1-2/+2
2023-11-23fixed playing of muxed streams and improved error reporting during Stream:play()Robin Haberkorn1-5/+5
* This now preserves the original traceback.
2023-11-16improved interruption (SIGINT, CTRL+C) supportRobin Haberkorn1-21/+27
* Just like the original LuaJIT interpreter, this will use a hook to automatically raise an error from Lua code. * Unfortunately, as long as Jit compilation is enabled, this cannot reliably work. Therefore we still set an `interrupted` flag that must be polled from tight loops. * Instead of polling via applause_push_sample() which gave interruption-support only to Stream:play(), we now have a separate checkint() function. * checkint() should be manually added to all tight loops. * Stream:foreach() and everthing based on it is now also supporting interruptions (via checkint()). * This internally works via applause_is_interrupted(). A C function was exposed only because LuaJIT does not support volatile-qualifiers and would optimize away reads to the interrupted-flag. As a side effect, we can also reset the hook. * Flags set in signal handlers should be `volatile`. * Added likely() and unlikely() macros to C code. * Updated sample.ipynb Jupyter notebook: Everything important is now supported, albeit requiring custom ILua patches.
2023-11-15Added Jupyter-support to Stream:gnuplot()Robin Haberkorn1-1/+19
* Renders SVG into a cell instead of a separate window * currently requires some not-yet-merged patch for ILua (see https://github.com/guysv/ilua/issues/5)
2023-09-19added Stream:print() for tracking control values streamsRobin Haberkorn1-0/+19
2023-09-16minor SubStream optimizationRobin Haberkorn1-9/+11
2023-09-15fixed SubStream of cached streamsRobin Haberkorn1-4/+11
* in particular: SndfileStream(...):sub(...) for multi-channel audio files. * The fix is more of a workaround just like the initial skipping of samples by sub() is a workaround. I couldn't yet think of a way how to seek in streams elegantly.
2023-09-15documentation updateRobin Haberkorn1-2/+4
2023-09-13added LDoc documentationRobin Haberkorn1-154/+864
* gives a useful overview of everything supported right now * especially the type documentation is useful, as these things are not self-evident in Lua (because of dynamic typing). * The LDoc page can later be published as the Github pages of the project. This can even be done automatically by a Github action. However, we should first make sure that it's okay to publish the project before defending the thesis since Github pages will always be public even for private repositories. * Documentation of command-line parameters is lacking (TODO). * It may be possible to use types like "Stream(number)" to describe streams of numbers. The LDoc documentation mentions boxed types. Perhaps there can even be Streamable(number)? * We are also lacking good example programs and/or introductory material.
2023-09-09Stream:jdump() prints less unrelated traces nowRobin Haberkorn1-2/+6
2023-09-09cache the value in simple value streamsRobin Haberkorn1-1/+3
* analyzing the bytecode via tostream(...):jdump() has shown that this might be more efficient
2023-09-05sampleCache should be global so that the other Lua modules can access it ↵Robin Haberkorn1-1/+1
directly as well
2023-09-05moved common definitions into applause.hRobin Haberkorn1-20/+5
2023-09-05libsndfile related classes moved into sndfile-stream.luaRobin Haberkorn1-100/+1
2023-09-05factored out filters into filters.luaRobin Haberkorn1-371/+1
2023-09-05MIDI stuff has been moved into midi.luaRobin Haberkorn1-243/+1
* common definitions are now in midi.h
2023-09-05MIDIStream is now an ordinary class that caches internallyRobin Haberkorn1-21/+15
2023-09-05Added HID support via EvdevRobin Haberkorn1-6/+50
* This works for relative, absolute and keyboard devices * devices can be grabbed, so they do not interfere with the rest of the system
2017-10-21added DelayXStream (work in progress)Robin Haberkorn1-1/+50
2017-01-26revised MIDI supportRobin Haberkorn1-95/+59
* introduced MIDIStream which provides a raw stream of MIDI messages (mangled into a single integer). * MIDIVelocityStream has been replaced by MIDIStream:mvelocity() * MIDICCStream has been replaced by MIDIStream:CC() * MIDIStreams can be directly passed to DSSIStreams
2017-01-26added DSSI supportRobin Haberkorn1-1/+1
* The LADSPA module has been extended to support DSSI plugins as well. If DSSI support is detected, the first input stream is considered a MIDI event stream. * The MIDI event handling must be updated to allow streams of MIDI messages for this to be useful. * ladspa.lua has been subsequently renamed to dssi.lua
2016-09-27fixed the minus, div, mod and pow operations for streamsRobin Haberkorn1-8/+27
* this has long been broken. ZipStream implicitly assumes an associative operation when "inlining" nested ZipStreams. Since the above mentions operations are not associative, the result was a faulty calculation. Example: s1 - (s2 - s3) was calculated like (s1 - s2) - s3. * For the time being, the inlining is avoided by using unique lambdas.
2016-09-27MIDI primitive optimizations and added ntof() and fton() shortcutsRobin Haberkorn1-11/+20
2016-09-26added LADSPA plugin host (LADSPAStream and Stream:LADSPA())Robin Haberkorn1-1/+9
* E.g. LADSPAStream("sine", 880):play(). The sine plugin is currently twice as fast as the native Applause implementation even though a block size of 1 sample is used (ie. compared to Stream.SinOsc). * all LADSPA features should be supported * Takes arbitrary Streams as input and produces a normal Applause stream. * multi-channel output plugins supported * LADSPA port mapping is possible by array, by name and by argument list. * Even though LADSPAStream is not muxable (it is more like SndfileStream), every input stream or default value is currently converted to a Stream. This can be optimized by storing scalars in their own arrays. They don't have to be ticked.
2016-09-25fixed HPF, BPF and BRF filters and allow the quality factor to be a streamRobin Haberkorn1-23/+17
* all of these filters were ticking the input stream twice, effectively resulting in the input signal to be pitched. * the quality factor should be allowed to be a stream since there is no technical reason against it.
2016-09-25added Stream:tonumber() and Stream:tostring() and simplified the __tostring ↵Robin Haberkorn1-7/+6
metamethod
2016-09-25changed semantics of ZipStream (ie. multiply, add operators): the left ↵Robin Haberkorn1-110/+149
stream determines the length * this makes them compatible with the scalar operations like Stream:mul(), Stream:add() etc when the right stream is a scalar turned into an infinite stream. * Consequently, both operations could be merged: Stream:mul() and the __mul operator are now synonymous. The methods are kept since they are sometimes handy to avoid braces when writing from left to right. Since the old way of mapping a stream for scalars is still a bit faster compared to using a ZipStream, this method is still applied for scalars as an optimization. Both the methods and the operators will now work with scalars and arbitrary streams, though. * This means that many primitives based on scalar operations previously will now work with streams as well. This applies to Stream:scale(), Stream:ccscale(), Stream:mix(), Stream:pan() and even line(). * Added Stream:min() and Stream:max() as shortcuts for binary operations from the math package. * All the binary operations from the math and bit packages will work with streams now as well (without performance penalties). * Stream:clip() has been revised and works with stream arguments now as well. * Optimized ConcatStream, MapStream, ScanStream, FoldStream and esp. ZipStream. * The new ZipStream semantics allow for new useful idioms. For instance, to add an envelope to an infinite stream (stream*env), a SubStream was often necessary to restrict the resulting stream to the length of the envelope as in (stream*env):sub(1,env:len()). This can now be written more elegantly as (env*stream). To extend a stream to infinite length, you may still write 0+stream or stream..0
2016-09-15fixed SawOsc and support a scalar phase argument for all oscillatorsRobin Haberkorn1-13/+17
* SawOsc has been broken for a long time * phases are useful since they are trivial to implement at the Phasor level and cumbersome to emulate using SubStream (basically you would need :sub(sec(1)/freq*phase)). Also, this way, phases will work even for modulated frequencies or if the frequency is unknown. They should come with no additional runtime overhead.
2016-09-15fixed multichannel SndfileStreams and :toplot()Robin Haberkorn1-9/+11
2016-09-05added Stream:pan(), fixed typo in MuxableStream and improved ↵Robin Haberkorn1-3/+28
InstrumentStream for finite on-streams
2016-09-03SndfileStream() supports raw files now, by passing through samplerate, ↵Robin Haberkorn1-3/+20
channels and libsndfile format
2016-07-18fixed Stream:resample()Robin Haberkorn1-1/+1
2016-07-04added ntom() and mton() for converting from note names to MIDI numbers and ↵Robin Haberkorn1-15/+53
vice versa * mton() can handle MIDINoteStream values just like mtof() * both are exposed as Stream methods as well (e.g. Stream:mton()) * MIDIVelocityStream accepts note names now as well in addition to MIDI note numbers * added scoping to the cache used by mtof()
2016-07-04fixup: InstrumentStreamRobin Haberkorn1-4/+19
2016-07-03simplified code: the Streams.streams array is no longer mandatoryRobin Haberkorn1-79/+70
* properly named attributes can be used instead of putting all stream arguments into a `streams` attribute. This is no longer necessary since there is no more Stream:reset() method.
2016-07-03renamed Stream:tick() to Stream:gtick()Robin Haberkorn1-58/+58
* this function is not the tick function itself but rather a generator (returning the tick function). * Calling these methods gtick() is less confusing but still concise.
2016-07-03added InstrumentStream (Stream:instrument)Robin Haberkorn1-0/+58
* allows a stream of note velocities to trigger a note-on and note-off stream. * usually used on a MIDIVelocityStream * allows a single note to be triggered including attack, sustain and decay phases * by letting the note-on and note-off streams depend on the note/velocity stream, the note can use the NOTE ON velocity. * The InstrumentStream constructor will also accept functions on the note_stream, so it is possible to define the note-on/off streams depending on the velocity stream on a single line of source code. * A NOTE OFF velocity is currently not used, though that could be achieved by letting MIDIVelocityStream generate negative numbers for NOTE OFF velocities. * This will only work with a single note (ie. a fixed frequency); when wanting to play polyphony, users will have to mix many different InstrumentStreams, e.g. iota(69, 79):map(function(note) return MIDIVelocityStream(note, 1):instrument(function(v) return InstOn(note, v) end, InstOff(note)) end):fold(function(x,y) return x+y end):ravel()
2016-06-05revised stream syncing: stream samples are cached nowRobin Haberkorn1-81/+65
* the syncing had some serious issues: It was not possible to repeat a synced stream since its tick() iterators were not independant. E.g. Foo = Bar:sync(); (Foo..Foo):play() would not have the expected result (Bar..Bar):play() * syncing required the Stream.reset() mechanism * instead of syncing, we now do caching (CachedStream) in a dedicated sampleCache table. Instead of alternating the clock signal, the cache is now simply table.clear()ed for each output sample. This results in some allocation overhead on the first sample since sampleCache will not yet have its final size. (Although this overhead could be avoided by counting the number of cached streams recursively and allocating sampleCache using table.new()) * SndfileStream suffered from similar problems, it could not be repeated because every object's tick() shared the same handle. Instead every tick() now opens its own handle. This means that using the same SndfileStream multiple times no longer requires explicit syncing/caching and SndfileStreams can be repeated. On the down-side we must check whether the file changed after the initial object construction.
2016-06-01added a few APLish unicode shortcuts for some of the primitives/Stream methodsRobin Haberkorn1-1/+7
* Unicode identifiers allowed in LuaJIT 2 * We add the shortcuts directly to applause.lua but using Unicode escapes. Thus we don't have to maintain a separate file and we can still edit applause.lua using a non-UTF editor like SciTECO * Stream:sub (subtract) renamed to Stream:minus. This was previously overwritten by the SubStream wrapper.
2016-06-01implemented delay lines and echo effectRobin Haberkorn1-0/+51
* DelayStream must currently have a constant length (ie. duration) * Stream:mix() allows mixing two streams by a constant wet/dryness factor. 0 means only the first stream, while 1 is only the second stream. * Stream:echo() builds on this for an echo effect with constant delay and wetness factor. The source stream is automatically synced.
2016-01-25added line(), curve() and curves(): RTCmix-like "curve" generatorsRobin Haberkorn1-0/+32
* In contrast to RTcmix, they are calculated on-demand. Like any stream, they can be turned into a "lookup table" using :eval()
2016-01-25added DupMux() function and Stream:dupmux() methodRobin Haberkorn1-7/+19
These are useful whenever a single-channel stream should be muxed into multi-channel stream (e.g. mono to stereo signal)
2016-01-25added brown and pink noise streamsRobin Haberkorn1-3/+79
* benchmark() has been inmproved. * added Stream:benchmark()
2016-01-25multi-channel stream supportRobin Haberkorn1-87/+331
* This is implemented without introducing the notion of frames into the tick() methods since most multi-channel stream operations can be understood as duplicating the operation on each channel. * Instead there is only ONE explicitly multi-channel stream: MuxStream. It can be used to construct a multi-channel stream from various normal mono streams and is also used internally. * MuxStreams can still be used just like any other stream since the new base class MuxableStream will automatically apply the class constructors on each channel in order. The channels of streams being combined must be equal, unless mono streams are involved. * Mono-streams are automatically blown-up to multi-channel streams when involved in operations with a multi-channel stream. * The remaining multi-channel specific code has been isolated in Stream:foreach() which now receives frames instead of individual samples. * When playing() a multi-channel stream, the applause output ports are played in order. I.e. playing a mono-stream fills output_1. A stereo stream, output_1 and output_2. * The number of Jack output ports can be specified on the applause command line. * All system playback ports are tried to be connected to corresponding applause output ports.
2016-01-12make applause.lua reloadable using the reload() global functionRobin Haberkorn1-3/+18