Age | Commit message (Collapse) | Author | Files | Lines |
|
* should speed up things since the C function calls can be inlined
* the C function does only rudimentary argument checking using assert()
since they are only called internally.
This means, calling it with wrong arguments can result in controlled
crashes. This will point to programming errors since the real argument
checking is done in Lua code at stream construction.
* The MIDI*Stream.getValue() functions have been kept as wrappers around
the native functions, to ease using them in other stream implementations
that want to support MIDI natively.
|
|
|
|
* the low-level C part is now implemented in a normal
C function applause_push_sample() which is called using the FFI
API
* this is supposedly faster than the old Lua/C way, but the
speed improvement seems to be miniscule.
However changes like this are still good since they simplify
the C core.
* speed improvements will probably be larger for the
MIDI*Stream functions since here we call Lua/C functions at
sample rate.
|
|
* the server is basically a second way to modify the Lua state of Applause
* concurrently to interactive input, messages can be sent over a TCP socket
which are evaluated just like command lines.
All stdout/stderr output is returned and the socket is closed.
* Server currently hardcoded at 127.0.0.1:10000
* Interruptions are currently not possible.
This would require another thread.
* The threading could be simplified by making the applause binary
a server-only application.
The Read-Eval-Print loop could then be a standalone LuaJIT script.
|
|
and print stack tracebacks
|
|
* all sub-substreams must now be in the `streams` attribute
|
|
and construction using the Class() idiom
* Class:instanceof() deprecates several fields like is_azipstream;
is_a_stream is still useful
* Constructors are now defined as ordinary methods (looks better)
* every object and class table now has a `base` field that points to the
base class since getmetatable() will no longer point to the base table/class.
* Objects can be constructed both using Class:new() and Class().
The old behaviour of stream() for serialization is used less frequently.
* Streams can be serialized using the Stream:eval() method.
I don't think that the object system should be tweaked even more to support
different metamethods for class tables and objects as it is quite convoluted already.
|
|
* could be used to introduce classes like SinOsc that are simply shortcuts
for some higher order stream (just like Stream.SinOsc is currently) but
can be instantiated consistently using SinOsc:new().
|
|
(or infinitely)
* this currently also works for very long streams without precalculating stuff
* On the other hand, after each iteration the target stream must be reinitialized.
This is not safe in generator functions (FIXME).
|
|
* we have to make sure that exactly the same function values are used
|
|
graph without recomputation
* Since it comes with an overhead, it has to be enabled by constructing a SyncedStream
or calling Stream:sync()
* Reusing samples works by sharing generator functions and caching samples until a clock signal changes.
The clock signal is currently a global variable "clock_signal" that oscillates between
true and false.
* This means that all sample generating methods like :play() or :totable() will have
to advance the clock using the global clockCycle() function.
It is a global function, so it can be invoked more or less efficiently by the :play()
implementation (currently using the old-school Lua/C API).
These restrictions might fall when using the LuaJIT way of interacting with
native code.
* Since playback must begin from the beginning for every :play(), an explicit reset()
mechanism has been introduced which can usually be ignored in Stream implementations.
It does however allow SyncedStream to reset the generator closure.
* SndfileStream has been simplified since now it is possible to keep the file handle
open. However as long as Stream synchronization is not automatic, SndfileStreams must
be explicitly synced when using one stream multiple times.
* Syncing is thought to be performed automatically by an optimizer when one object
is used more than once e.g. in a :play() call.
* Non-synced streams are currently slightly slower than before this commit,
probably because of the additional clockCycle() call.
|
|
|
|
|
|
* there are at most 128 different MIDI notes; mtof() will now also work
for all of them
* channels have origin 1 now in the public APIs.
This is what most applications seem to use, so in order to avoid
confusion it's probably a good idea to use it as well.
|
|
* MIDIVelocityStream will report the velocities on a particular
note. This can be used to build polyphonic instruments.
* MIDINoteStream will report all possible notes on a particular
channel. The velocity of the note last triggered is also encoded
into the stream values. This can be used to build simple
monophonic instruments.
* Map bit methods to stream methods, e.g. Stream:band()
Is especially useful for streams that encode multiple values
into single integers for performance reasons.
* mtof() and ftom() methods for converting from and to MIDI note
numbers. mtof() is very efficient since its values are all
precalculated in a lookup table.
* fixed tostring() method for streams smaller than 1024 samples
|
|
* MIDICCStream provides a stream of CC values as if
polled from the controller (this is emulated in
applause.c)
|
|
jack_get_buffer_size()
|
|
|
|
|
|
* more precisely, Stream:play() will now throw
an error whenever the process receices SIGINT.
* this allows us to interrupt long playbacks
|
|
in milliseconds
* default buffer size: 100ms
|
|
* allows the Lua thread to block when the ringbuffer is full
while keeping the realtime thread (jack_process()) realtime-safe.
Hopefully :-)
* since audio generation is usually faster than consumption
(if you don't want to have buffer underruns),
this fixes audio generation longer than BUFFER_SIZE (currently 1s)
|
|
|
|
* the call metamethod is most useful in compositions in order to
evaluate a stream to save computing power at runtime.
* this meant that in addition to adding () to a stream expression it
was necessary to convert the table to a stream (e.g. using tostream()).
* Now the totable() method converts to a pure table, while __call
returns a VectorStream. This means it will be sufficient to add "()"
in order to evaluate a stream eagerly
|
|
|
|
|
|
|
|
operations
|
|
|
|
|
|
|
|
|
|
* LPF, HPF, BPF, BRF filters are 2nd order Butterworth filters.
Derived verbatim from ChucK's implementation. This can probably
be optimized by caching the tan/cos functions.
Also, they do not yet handle frequency streams shorter than the
stream to filter.
* Basic wave forms are now Stream methods to allow concatenative style
of FM synthesis (or LFOs). To generate e.g. a sine wave with constant
frequency, you can still write Stream.SinOsc(440); or tostream(440):SinOsc()
|
|
This improves the real-time properties of sample generation
since it avoids CPU spkikes.
On the other hand, this may not be ideal as playing a long streams could have
non-constant space requirements now.
A proper solution would probably involve calling the garbage collector incrementally
during the play() loop.
|
|
* implements Stream:play() using Jack as the audio backend
|
|
|
|
* this improves performance by 10 times (both lua5.1 and luajit)
* also, when using luajit, there appears to be little peformance
loss when using stream compositions instead of maps (which are
sometimes even slower!?)
|
|
|