186 lines
7.6 KiB
Plaintext
186 lines
7.6 KiB
Plaintext
IMPORTANT LINKS {
|
|
https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
|
|
lowpass filter https://www.embeddedrelated.com/showarticle/779.php
|
|
https://github.com/ThePhD/sol2
|
|
https://github.com/cameron314/concurrentqueue
|
|
}
|
|
|
|
project data {
|
|
samples are held in memory as {
|
|
QString name, QUuid id (used as dictionary key) (?)
|
|
sample rate, channel count (1 or 2), length
|
|
probably QSharedPointer to raw float array (size=length*channels, non-interleaved)
|
|
}
|
|
}
|
|
|
|
parameters {
|
|
standard extensions {
|
|
tXX - set tween time (in ticks) for previous parameter
|
|
,XX - extra param bytes
|
|
}
|
|
|
|
InstrumentCore (stock instrument behavior) {
|
|
legato accepts tweens! must be first parameter entry
|
|
|
|
vXX - volume; 00 .. FF -> 0.0 .. 1.0 (accepts tweens)
|
|
pXX - panning; signed byte? 00 as center (accepts tweens)
|
|
gXX/GXX - glissando (pitch bend); g=down, G=up; relative semitones (accepts tweens)
|
|
}
|
|
|
|
global port (G) {
|
|
tXX - tempo (how to implement >255? fine tempo?)
|
|
}
|
|
}
|
|
|
|
TODO {
|
|
immediate frontburner {
|
|
- instrumentcore tweens (unordered_multimap...)
|
|
- iterator/reader abstraction for commands
|
|
- actual support for commands in InstrumentCore
|
|
node function to release unneeded old data when stopping playback?
|
|
}
|
|
|
|
# make knob notches more even (currently "previous value" is twice as big as any other step at px>1)
|
|
add standardized step values for knobs (int enum?)
|
|
|
|
include Arcon (rounded) for use as unified patchboard font?
|
|
|
|
bugs to fix {
|
|
-? graph connections sometimes spawn in duplicated :|
|
|
|
|
- on starting playback, sometimes a "thunk" sneaks into the waveform?
|
|
|
|
-? buffer underruns are being caused by some sync wonkiness between multiple workers
|
|
}
|
|
|
|
misc features needed before proper release {
|
|
song metadata (title, artist, comment, default bpm)
|
|
|
|
at *least* js plugin support, with lua+lv2 highly preferable
|
|
SAMPLES and SAMPLING
|
|
|
|
- gadget widgets (w/container) - at least a knob with nice range and such
|
|
|
|
different context menu for multiple selected nodes
|
|
pack/unpack selection to/from subgraph
|
|
|
|
proper playback controls and indicators
|
|
play from current pattern
|
|
|
|
pattern editor cells can have (dynamic) tool tips; set this up with port names, etc.
|
|
|
|
make the save routine displace the old file and write a new one
|
|
|
|
open file from command line argument
|
|
^ multi-document, single-instance (QLocalServer etc.)
|
|
}
|
|
|
|
gadgets and bundled things {
|
|
(the simple things:)
|
|
- gain and panning gadget
|
|
- note transpose
|
|
volume meter
|
|
|
|
"wrap clipper" (gain up, then wrap around +-1.0, then gain down)
|
|
|
|
Polyplexer (splits a single command input into several monophonic outputs and keeps track of individual notes between them)
|
|
|
|
probably three sorts of sampler (quick drum sequencer, quick single-sample "wavetable", then the full-on tracker sampler later on)
|
|
}
|
|
}
|
|
|
|
Xynamo (hybrid? synth) {
|
|
3? 5? oscillators; several different waveforms available, independent filtering, wavefolding and (hard) wrapping...
|
|
individually controllable??
|
|
rail system!
|
|
}
|
|
|
|
- dumb per-cycle atomic memory allocator from fixed pool for port buffer allocations
|
|
? can also set up a tlsf pool per worker; prefix allocations with single byte identifier indicating which one they came from,
|
|
? and defer freeing operations via message queues
|
|
|
|
resampler object {
|
|
one used internally for each note
|
|
reference to sample
|
|
wrap mode (flat, loop, pingpong)
|
|
double position (number of samples with fractional part)
|
|
}
|
|
|
|
gain slider/knob gadget: dBFS [10^(x / 20)]
|
|
scale from -60 to +6 in increments of .1, with linear fade to zero below -60
|
|
sine panning http://folk.ntnu.no/oyvinbra/delete/Lesson1Panning.html
|
|
though for vXX, it's perfectly sufficient to use mult^4
|
|
|
|
JS example of sine panning, -1.0 to +1.0 {
|
|
const m = 1.0/Math.cos(Math.PI*.25)
|
|
function f(x) {
|
|
var s = (x+1) * Math.PI * .25
|
|
return (Math.cos(s)*m) + " " + (Math.sin(s)*m)
|
|
}
|
|
}
|
|
|
|
plugin registry {
|
|
queuing function for static construction
|
|
PluginInfo base class, virtual function for creating a node of said plugin
|
|
(separate function for loading from save file?)
|
|
}
|
|
|
|
lv2 support: lilv (duh) for actual plugin loading, suil for UI embedding
|
|
|
|
eventually hook luajit up with TLSF allocator to aid in real time (maybe look at nedmalloc too)
|
|
(requires a patch to lib_aux.c, so static link/straight include?)
|
|
https://github.com/OpenMusicKontrollers/Tjost/blob/master/LuaJIT-2.0.3-rt.patch
|
|
to static link https://stackoverflow.com/a/30235934
|
|
|
|
graph+node+port system {
|
|
dependencies are a straight ordering, worked backwards from the mix output on port hookup change (graph-local)
|
|
this way, we don't bother processing anything that doesn't actually contribute to output in any way
|
|
|
|
before playback starts, playback thread assembles an expanded queue (graph has a function that recursively expands queue given a ref to a pre-reserved vector)
|
|
note: also preassemble a map of all unique channel names for note number purposes
|
|
can use the same logic to count active nodes (make sure to include the graph i/o ports unless implementing those another way? actually yeah, explicit pull operation)
|
|
... how will the worker threads tell when they've outpaced the queue, and how will they wait properly?
|
|
something something ready flags (all input nodes and containing graph; main graph and command ports always have the bit set)
|
|
|
|
graphs are also nodes
|
|
|
|
can use locks on processing node-ports since they'll basically never be contended; this allows for editing during playback
|
|
^ or just double-buffer the connections
|
|
UI thread takes full responsibility for both replacement and eventual collection; atomic bool marking is enough threadsafety to deflect the collection timer
|
|
have to signal playback thread that queues have been invalidated
|
|
...or just use locks and a flag since it's probably not worth the added complexity of implementing lockfree to avoid hangups when *fiddling with connections*
|
|
though we do want a queue system for plugin parameter changes! don't want xruns from fiddling with instruments or mixing
|
|
(most built-in gadgets can avoid this by nature of aligned power-of-two types (<=8bytes) inherently atomic on modern CPUs)
|
|
}
|
|
|
|
on-the-wire command format {
|
|
uint16_t noteId // for sending commands to the same note
|
|
int16_t note // note number >= 0, -1 for none, -2 note off, -3 hard cut
|
|
uint8_t numParams x {
|
|
uint8_t cmd
|
|
uint8_t amount
|
|
}
|
|
}
|
|
|
|
keybinds {
|
|
pattern editor {
|
|
note column {
|
|
( a-z, []\ ;' ,./ ) - "flat piano" in three octaves a la openMPT (maybe minus /)
|
|
shift - hold to transpose up one or two octaves while playing
|
|
1234567890 - assign octave
|
|
note off, hard cut?
|
|
}
|
|
param column {
|
|
symbol {
|
|
anything printable - set symbol and move to value
|
|
}
|
|
value {
|
|
minus - negate current value
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
to revert to stable repo copy of qt:
|
|
yay -S qt5-base qt5-declarative qt5-doc qt5-graphicaleffects qt5-location qt5-multimedia qt5-quickcontrols qt5-quickcontrols2 qt5-script qt5-sensors qt5-speech qt5-svg qt5-tools qt5-webchannel qt5-webengine qt5-websockets qt5-x11extras qt5-xmlpatterns
|