Music sequencer and audio editor Tech - kit - https://guattari.tech/kit.git - stb - https://github.com/nothings/stb.git - sokol_app - https://github.com/floooh/sokol.git - nanovg - https://github.com/memononen/nanovg.git - miniaudio - https://github.com/mackron/miniaudio.git Algorithms - Cooley-Tukey FFT - Biquad filter Primary design Basic UI - Bus list - Bus units - Track editor - Sheet editor +---------+ +-----------------------------------+ +-[ Bus A ]-------+ [+]Bus A ^ | [ track 1 ====== ] ^ [+] Arpeggiator ^ |---------| | | | [x] ** *** | [+]Bus B | | [ track 2 ============== ] | | [ ] <--> ++ | |---------| | | |-----------------| [+]Master v | v [+] Synth | [+]-------+ +<--------------------------------->+ | ^ ^ ^ [ ] | | / \ / \ / [x] | +----[ track 2 ]--------------------------------+ | V V [o] | |F > ^ |-----------------| |E > x x x x x | [+] Reverb | |D > x x x x x | | <-----> [x] [u] | |C > x x x x x x x v | v +--|<------------------------------------------>+ [+]---------------+ Modularity Music and audio features will be implemented as a separate library with no external dependencies. UI and audio devices will be distinct modules which can be replaced. Sheet data /---------------------\ | | | Note | | | | time : i64 | | duration : i64 | | frequency : f64 | | amplitude : f64 | | flavor : f64 | | | \---------------------/ Unlike MIDI, we will allow to set any floating-point value for the note frequency. Time is defined as a sample index and therefore is relative to the sample rate. Processing A unit is a processing entity. for each unit: output[channel, time] = eval(inputs, channel, sample_rate, time) Unlike VST, time for a processing routine is one of explicit parameters. The processing routine can access any samples of inputs. This approach allows to evaluate samples non-sequentially, and even do some tricks like time-reverse effects. Changing the sample rate is also quite simple. Global matrix /---------------------------\ | Matrix | | | | (connections data) | | A.out[0] -> B.in[0] |-----------------+ | B.out[0] -> Master.in[0] |----------------+| | B.out[1] -> Master.in[1] | || \---------------------------/ || ^ | ^^ ||(in[0], in[1]) | | || || | | ||(out[0], out[1]) vv /----------\ | | /----------\ /-----------\ | Module A |---+ +-->| Module B | | Master | | (sheet) | (out[0]) (in[0]) | (synth) | | (limiter) | \----------/ \----------/ \-----------/ The global matrix manages the information about connections between units. Each unit can communicate to others through the global matrix. Each unit can have inputs and outputs for sheet and signal channels. To get data from a producing unit, the receiving unit will request the data from the global matrix using the input index. The global matrix will resolve the producing unit by input index, and request data from it. The evaluation startes from the master and gradually reaches all required units. Global modifiers Special units can affect all regular units, filtered by some criteria. This will allow to do some global changes, e.g. change the musical scale of the entire composition. Customization In the matrix mode, any inputs and outputs can be connected. A custom unit can be created with code editor and JIT-compilation.