@@ -38,7 +38,7 @@ pacman -S git wget gcc make cmake tar unzip zip curl | |||
*If the build fails for you, please report the issue with a detailed error message to help the portability of Rack.* | |||
Clone this repository with `git clone https://github.com/VCVRack/Rack.git` and `cd Rack`. | |||
Make sure there are no spaces in your absolute path, as this breaks many build systems. | |||
Make sure there are no spaces in your absolute path, as this breaks the Makefile-based build system. | |||
Clone submodules. | |||
@@ -5,17 +5,19 @@ | |||
- [Forum](https://community.vcvrack.com/) | |||
- [Facebook page](https://www.facebook.com/vcvrack/) | |||
- [Twitter](https://twitter.com/vcvrack) | |||
- [Github issue tracker (features, bugs, and developer discussions)](https://github.com/VCVRack/Rack/issues) | |||
- [Github issue tracker](https://github.com/VCVRack/Rack/issues) | |||
- [Youtube](https://www.youtube.com/c/VCVRack) | |||
- [Instagram](https://www.instagram.com/vcvrack/) | |||
- [Facebook user group](https://www.facebook.com/groups/vcvrack/) | |||
- [Facebook developer group](https://www.facebook.com/groups/2035785263299933/) | |||
- [Facebook French user group](https://www.facebook.com/groups/2069785583250645/) | |||
- [Facebook Italian user group](https://www.facebook.com/groups/vcvitalia/) | |||
- [Switched On Rack blog](http://www.switchedonrack.com/) | |||
- [Discord](https://discord.gg/wxa89Mh) | |||
- [MuffWiggler thread](https://www.muffwiggler.com/forum/viewtopic.php?t=186899) | |||
- [KVR Audio thread](https://www.kvraudio.com/forum/viewtopic.php?f=23&t=489230) | |||
- [Hispasonic thread (Español)](https://www.hispasonic.com/foros/foro-vcv-rack/516252) | |||
- [Hispasonic thread (Spanish)](https://www.hispasonic.com/foros/foro-vcv-rack/516252) | |||
- [Patchstorage](https://patchstorage.com/platform/vcv-rack/) | |||
- [Discord](https://discord.gg/wxa89Mh) | |||
- [Switched On Rack collaboration albums](https://switchedonrack.bandcamp.com/) | |||
- [Reddit](https://www.reddit.com/r/vcvrack/) | |||
- [IRC](http://webchat.freenode.net?channels=%23VCVRack) |
@@ -6,12 +6,12 @@ One of its many applications is to generate and process audio from virtual/digit | |||
There are many online resources and books for learning DSP. | |||
- [Digital signal processing Wikipedia](https://en.wikipedia.org/wiki/Digital_signal_processing): An overview of the entire field. | |||
- [Seeing Circles, Sines, and Signals](https://jackschaedler.github.io/circles-sines-signals/): A visual and interactive introduction to DSP. | |||
- [Julius O. Smith III Online Books](https://ccrma.stanford.edu/~jos/) ([Index](https://ccrma.stanford.edu/~jos/GlobalJOSIndex.html)): Thousands of topics on audio DSP and relevant mathematics, neatly organized into easy-to-digest but sufficiently deep pages and examples. | |||
- [Mathematics of the Discrete Fourier Transform (DFT)](https://ccrma.stanford.edu/~jos/mdft/) | |||
- [Introduction to Digital Filters](https://ccrma.stanford.edu/~jos/filters/) | |||
- [Physical Audio Signal Processing](https://ccrma.stanford.edu/~jos/pasp/) | |||
- [Spectral Audio Signal Processing](https://ccrma.stanford.edu/~jos/sasp/) | |||
- [Seeing Circles, Sines, and Signals](https://jackschaedler.github.io/circles-sines-signals/): A visual and interactive introduction to DSP. | |||
- [The Scientist and Engineer's Guide to Digital Signal Processing](http://dspguide.com/) by Steven W. Smith: Free online book covering general DSP topics. | |||
- [The Art of VA Filter Design](http://www.native-instruments.com/fileadmin/ni_media/downloads/pdf/VAFilterDesign_2.0.0a.pdf) (PDF) by Vadim Zavalishin: Huge collection of deep topics in digital/analog filter design and analog filter modeling. | |||
- [DSPRelated.com](https://www.dsprelated.com/): Articles, news, and blogs about basic and modern DSP topics. | |||
@@ -81,10 +81,10 @@ When running Rack in development mode, it is your current working directory inst | |||
## Will Rack be ported to iOS or Android? | |||
It is not planned. Many issues would need to be addressed. | |||
- Tablet and phone users don't normally use mice, so a touch driver would need to be written. | |||
- Tablet and phone users don't normally use mice, so a touch driver would need to be written. If GLFW is still used, [touch support](https://github.com/glfw/glfw/issues/42) would need to be added to the library. | |||
- There is no user-managed filesystem on iOS, and forcing users to mess with the filesystem is bad UX on Android, so plugin folders and patch files would need to be managed entirely by Rack itself. | |||
- There is no OpenGL on mobile devices, so the OpenGL ES driver would need to be used and tested. | |||
- RtAudio and RtMidi don't have iOS Core Audio/MIDI or Android HAL/OpenSL ES backends, so they would need to be added and tested. | |||
- Apple does not allow apps distributed through the store to download and execute code, so either all plugins would need to be included in the distributable, or it could only be distributed on jailbroken iOS devices, which is an absurd user requirement. | |||
- Such a port would be very expensive to develop, if possible at all, so it would need to be sold commercially. Some plugins (proprietary, GPL, etc) would need special licensing agreements in order to be included in the package, which would increase the product's cost to pay for them or simply decrease the size of the third-party plugin collection. | |||
- Such a port would be very expensive to develop, so it would need to be sold commercially. Some plugins (proprietary, GPL, etc) would need special licensing agreements in order to be included in the package. Some plugins would increase the cost of the product if included in the package. Others would simply be omitted from the third-party plugin collection. | |||
- The friction for a developer to build and test their plugins on iOS/Android is significantly higher than the three desktop OS's, which may decrease their willingness to develop Rack plugins. |
@@ -8,7 +8,7 @@ Change `#include "rack.hpp"` to `#include "rack0.hpp"` | |||
Create a `plugin.json` manifest file for your plugin and all modules based on the [Template manifest](https://github.com/VCVRack/Template/blob/v1/plugin.json) (TODO add actual manifest template/guide). | |||
Remove `SLUG` and `VERSION` from the `Makefile`, since they are now defined in `plugin.json`. | |||
Remove `SLUG` and `VERSION` from the `Makefile` and ` p->slug = ...` and `p->version = ...` from your plugin's main `.cpp` file, since they are now defined in `plugin.json`. | |||
For each module, change the `Model::create` call | |||
```cpp | |||
@@ -21,54 +21,42 @@ Model *modelMyModule = Model::create<MyModule, MyModuleWidget>("MyModule"); | |||
Make the following string replacements (requires Perl). | |||
``` | |||
perl -p -i -e "s/Model::create/createModel/g" src/*.cpp | |||
perl -p -i -e "s/ParamWidget::create/createParam/g" src/*.cpp | |||
perl -p -i -e "s/ModuleLightWidget::create/createLight/g" src/*.cpp | |||
perl -p -i -e "s/Port::create/createPort/g" src/*.cpp | |||
perl -p -i -e "s/Port::OUTPUT/PortWidget::OUTPUT/g" src/*.cpp | |||
perl -p -i -e "s/Port::INPUT/PortWidget::INPUT/g" src/*.cpp | |||
perl -p -i -e "s/Widget::create/createWidget/g" src/*.cpp | |||
perl -p -i -e "s/MenuLabel::create/createMenuLabel/g" src/*.cpp | |||
perl -p -i -e "s/MenuItem::create/createMenuItem/g" src/*.cpp | |||
perl -p -i -e "s/toJson/dataToJson/g" src/*.cpp | |||
perl -p -i -e "s/fromJson/dataFromJson/g" src/*.cpp | |||
perl -pi -e "s/Model::create/createModel/g" src/*.cpp | |||
perl -pi -e "s/ParamWidget::create/createParam/g" src/*.cpp | |||
perl -pi -e "s/ModuleLightWidget::create/createLight/g" src/*.cpp | |||
perl -pi -e "s/Port::create/createPort/g" src/*.cpp | |||
perl -pi -e "s/Port::OUTPUT/PortWidget::OUTPUT/g" src/*.cpp | |||
perl -pi -e "s/Port::INPUT/PortWidget::INPUT/g" src/*.cpp | |||
perl -pi -e "s/Widget::create/createWidget/g" src/*.cpp | |||
perl -pi -e "s/MenuLabel::create/createMenuLabel/g" src/*.cpp | |||
perl -pi -e "s/MenuItem::create/createMenuItem/g" src/*.cpp | |||
perl -pi -e "s/toJson/dataToJson/g" src/*.cpp | |||
perl -pi -e "s/fromJson/dataFromJson/g" src/*.cpp | |||
``` | |||
If your plugin uses any of Rack's `dsp/*.hpp` headers, remove the `#include` statements since they are now automatically included. | |||
For most plugins, this should do it. | |||
Compiling should generate hundreds of deprecation warnings, but it might succeed. | |||
If not, continue to the next section. | |||
If not, read the compile error, and don't hesitate to ask questions in the VCV community forum or GitHub issue tracker. | |||
## The right way: using the Rack v1 API | |||
First follow the above section using the compatibility header. | |||
First complete the above section using the compatibility header as a first step. | |||
Change `#include "rack0.hpp"` back to `#include "rack.hpp"` | |||
Once it is able to compile, change `#include "rack0.hpp"` back to `#include "rack.hpp"` | |||
Change | |||
```cpp | |||
addInput(createPort<...>(..., PortWidget::INPUT, ...)); | |||
to | |||
addInput(createInput<...>(..., ...)); | |||
``` | |||
```cpp | |||
addOutput(createPort<...>(..., PortWidget::OUTPUT, ...)); | |||
to | |||
addOutput(createOutput<...>(..., ...)); | |||
``` | |||
```cpp | |||
engineGetSampleRate() | |||
to | |||
app()->engine->getSampleRate() | |||
perl -pi -e "s/engineGetSampleRate/app()->engine->getSampleRate/g" src/*.cpp | |||
perl -pi -e "s/engineGetSampleTime/app()->engine->getSampleTime/g" src/*.cpp | |||
perl -pi -e "s/, PortWidget::INPUT//g" src/*.cpp | |||
perl -pi -e "s/addInput\(createPort/addInput(createInput/g" src/*.cpp | |||
perl -pi -e "s/, PortWidget::OUTPUT//g" src/*.cpp | |||
perl -pi -e "s/addOutput\(createPort/addOutput(createOutput/g" src/*.cpp | |||
perl -pi -e "s/randomUniform/random::uniform/g" src/*.cpp | |||
perl -pi -e "s/randomNormal/random::normal/g" src/*.cpp | |||
``` | |||
```cpp | |||
engineGetSampleTime() | |||
to | |||
app()->engine->getSampleTime() | |||
``` | |||
Add the `dsp::` prefix. | |||
TODO |
@@ -84,7 +84,7 @@ Before releasing your plugin, read the [Rack licenses](https://github.com/VCVRac | |||
If you are considering "porting" a hardware module to the VCV Rack platform, it is a good idea to ask the creator first. | |||
It may be illegal, immoral, or cause unpleasant relationships to copy certain intellectual property without permission. | |||
## Packaging | |||
## Building | |||
Make sure the VERSION and SLUG are correct in your Makefile, and run `make dist`. | |||
A ZIP package is generated in `dist/` for your architecture. | |||
@@ -23,3 +23,9 @@ Build with | |||
make html | |||
The output should be generated in `_build/html`. | |||
## License | |||
All documentation text in this repository is licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). | |||
Images such as screenshots and logos are licensed by their respective owner. |
@@ -25,21 +25,30 @@ If your module is capable of applying >1x gain to an input, it is a good idea to | |||
In Eurorack, many modules are triggered by reaching a particular rising slope threshold. | |||
However, because of the [Gibbs phenomenon](https://en.wikipedia.org/wiki/Gibbs_phenomenon), a digital emulation will falsely retrigger many times if the trigger source is bandlimited (e.g. by using a virtual VCO square wave as a trigger input or a hardware trigger through an audio interface.) | |||
Trigger inputs in Rack should be triggered by a [Schmitt trigger](https://en.wikipedia.org/wiki/Schmitt_trigger) with a low threshold of about **0.1V** and a high threshold of around **1 to 2V**. | |||
Therefore, trigger inputs in Rack should be triggered by a [Schmitt trigger](https://en.wikipedia.org/wiki/Schmitt_trigger) with a low threshold of about **0.1V** and a high threshold of around **1 to 2V**. | |||
Rack plugins can implement this using `SchmittTrigger` from `digital.hpp` with `schmittTrigger.process(rescale(x, 0.1f, 2.f, 0.f, 1.f))` | |||
Trigger sources should produce **10V** with a duration of 1 millisecond. | |||
Trigger sources should produce **10V** with a duration of **1ms**. | |||
An easy way to hold a trigger for this duration is to use `PulseGenerator` from `digital.hpp` with `pulseGenerator.trigger(1e-3f)`. | |||
Gates should produce **10V** when active. | |||
## Timing | |||
Each cable in Rack induces a 1-sample delay of its carried signal from the output port to the input port. | |||
This means that it is not guaranteed that two signals generated simultaneously will arrive at their destinations at the same time if the number of cables in each signal's chain is different. | |||
For example, a pulse sent through a utility module and then to a sequencer's CLOCK input will arrive one sample later than the same pulse sent directly to the sequencer's RESET input. | |||
This will cause the sequencer to reset to step 1, and one sample later, advance to step 2, which is undesirable behavior. | |||
Therefore, modules with a CLOCK and RESET input, or similar variants, should ignore CLOCK triggers up to **1ms** after receiving a RESET trigger. | |||
## Pitch and Frequencies | |||
Modules should use the **1V/oct** (volt per octave) standard for CV control of frequency information. | |||
In this standard, the relationship between frequency \\(f\\) and voltage \\(V\\) is \\(f = f_0 \cdot 2^{V}\\), where \\(f_0\\) is the baseline frequency. | |||
Your module might have a frequency knob which may offset \\(V\\). | |||
Audio-rate oscillators should use a baseline of the note C4 ("middle C", MIDI note 60, \\(f_0 =\\) 261.626 Hz). | |||
Low-frequency oscillators and clock generators should use 120 BPM (\\(f_0 =\\) 2 Hz). | |||
At its default position, audio-rate oscillators should use a baseline of the note C4 ("middle C", MIDI note 60, \\(f_0\\) = 261.6256 Hz = `dsp::FREQ_C4`). | |||
Low-frequency oscillators and clock generators should use 120 BPM (\\(f_0\\) = 2 Hz). | |||
## NaNs and Infinity | |||