diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 0f149194..e55f337d 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9] + python-version: [3.7, 3.8, 3.9, 3.10-dev] steps: - uses: actions/checkout@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 230bea56..1784121c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,12 @@ CHANGELOG Next Release ----- -* Daisy support +* metadata json for generator config +* add trig attribute type +* Daisy platform support +* DPF cleanup + meta + trig +* documentation update +* DPF makefiles + meaningful values + docs 0.1.2 ----- diff --git a/README.md b/README.md index cf029131..5e6316dc 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ ![Build Status](https://github.com/Wasted-Audio/hvcc/actions/workflows/python.yml/badge.svg) -:warning: This is an attempt to modernize `hvcc` to work with `python3` and add some additional targets. :warning: +This is an attempt to modernize `hvcc` to work with `python3` and add some additional targets. -:warning: Not all functionality is being tested. Feedback is appreciated. :warning: +Not all functionality is being tested. Bugreports and feedback are appreciated. # Heavy Compiler Collection (hvcc) @@ -85,27 +85,22 @@ Available generator options: * `c` * `bela` +* `daisy` +* `dpf` * `fabric` * `js` * `pdext` * `unity` -* `daisy` -* `dpf` - * `vst2` - * `lv2` - * `jack` * `wwise` - ### `-p` Search Paths `hvcc` will iterate through various directories when resolving patch objects and abstractions. The `-p` or `--search_paths` argument can be used to add additional folders for `hvcc` to look in. -This can be handy when using a third-party patch library for example https://github.com/enzienaudio/heavylib. +This can be handy when using a third-party patch library for example https://github.com/Wasted-Audio/heavylib. `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth -p "[~/Workspace/Projects/Enzien/heavylib/, ~/Desktop/myLib/]"` - ### `-m` Meta Data `hvcc` can take extra meta-data via a supplied json file. It depends on the generator which fields are supported. @@ -132,15 +127,14 @@ Displays all the available parameters and options for hvcc. - [Supported frameworks](/docs/01.introduction.md#supported-frameworks) - [Licensing](/docs/01.introduction.md#licensing) * [Getting Started](/docs/02.getting_started.md) -* [Unity](/docs/05.unity.md) -* [Wwise](/docs/06.wwise.md) -* [Javascript](/docs/07.javascript.md) -* [DPF](/docs/08.dpf.md) -* [MIDI](/docs/09.midi.md) -* [C API](/docs/10.c.md) -* [C++ API](/docs/11.cpp.md) -* [Heavy Lang Info](/docs/12.heavy_lang.md) -* [Heavy IR Info](/docs/13.heavy_ir_lang.md) +* [Generators](/docs/03.generators.md) +* [MIDI](/docs/04.midi.md) +* [C API](/docs/05.c.md) +* [C++ API](/docs/06.cpp.md) +* [Heavy Lang Info](/docs/07.heavy_lang.md) +* [Heavy IR Info](/docs/08.heavy_ir_lang.md) +* [Supported vanilla objects](/docs/09.supported_vanilla_objects) +* [Supported vanilla objects](/docs/10.unsupported_vanilla_objects) ## Contact There are several places where heavy/hvcc conversation is happening: diff --git a/docs/01.introduction.md b/docs/01.introduction.md index 153d8474..494e9e84 100644 --- a/docs/01.introduction.md +++ b/docs/01.introduction.md @@ -18,9 +18,8 @@ However it's important to note that Pd is merely used as a front-end authoring e Heavy can interpret and convert a subset of features from Pure Data patches: -* [Supported Pd objects](14.Supported_vanilla_objects.md) -* [Unsupported Pd objects](15.Unsupported_vanilla_objects.md) - +* [Supported Pd objects](09.supported_vanilla_objects.md) +* [Unsupported Pd objects](10.unsupported_vanilla_objects.md) ## Supported Platforms * Windows 8, 10 and WSA @@ -60,3 +59,7 @@ The files that `hvcc` generates are split into two types: * [Static](https://github.com/Wasted-Audio/hvcc/tree/master/hvcc/generators/ir2c/static): this code is independent of the input patch contents and provides the basic DSP functionality with which generated output can link against. It has a [BSD](https://github.com/Wasted-Audio/hvcc/blob/master/hvcc/generators/ir2c/static/HeavyContext.hpp#L2) licence. * Generated: this relates to all the source files that use information about the input patch, for example `Heavy_{{name}}.cpp`. By default all these files will have a `Copyright (c) 2018 Enzien Audio, Ltd` header, but this can be modified with the [user copyright argument](../README.md#--copyright-user-copyright). + +## How to start patching for heavy + +See the [Getting started](02.getting_started.md) page on more information about how to construct compatible pure data patches. \ No newline at end of file diff --git a/docs/02.getting_started.md b/docs/02.getting_started.md old mode 100755 new mode 100644 index 495a76bb..da9a6195 --- a/docs/02.getting_started.md +++ b/docs/02.getting_started.md @@ -1,6 +1,5 @@ # Getting Started - ## Audio Input/Output To receive audio input into your patch add an `[adc~]` object. @@ -20,6 +19,14 @@ Receivers not annotated with `@hv_param` are still completely functional, they s ![params](img/docs_exposed_params.png) +### Parameter Type + +An optional parameter type can be set to which generator implementations can program custom features. The default type is `float`. + +For example, `[r toggle @hvparam 0 1 1 bool]`. + +See the [DPF docs](03.gen.dpf.md#parameter-types) for more information on how parameter types can be integrated into a generator. + ### Output Parameters In the same manner as above, all (control) `[send]` and `[s]` objects annotated with `@hv_param` will be exposed as **output** parameters. @@ -39,7 +46,21 @@ For example, `[r bang @hv_event]` will show up as a button called "bang" in the ![events_unity](img/docs_exposed_events_unity.png) -See the [Unity docs](05.unity.md#exposing-and-sending-events) for more information on exposing events and controlling them. +See the [Unity docs](03.gen.unity.md#exposing-and-sending-events) for more information on exposing events and controlling them. + +## Metadata +Some generators, like Daisy and DPF, enable support for extra configuration metadata.json file using the `-m`. It depends on the generator what is supported. See the [DPF docs](03.gen.dpf.md#metadata) for more information on setting meta data for plugins. + + +Simple Daisy example that selects the desired board to build for: + +```json +{ + "daisy": { + "board": "seed" + } +} +``` ## Errors If there's an incompatibility within the patch, Heavy will generate an error message. @@ -53,4 +74,4 @@ Heavy will also perform patch analysis to look for common mistakes and inconsite ## Reporting Issues -If you experience any problems or have some thoughts on how to improve heavy make sure to browse and contribute to our [public issue tracker](https://github.com/enzienaudio/heavy/issues). +If you experience any problems or have some thoughts on how to improve heavy make sure to browse and contribute to our [public issue tracker](https://github.com/Wasted-Audio/hvcc/issues). diff --git a/docs/03.gen.daisy.md b/docs/03.gen.daisy.md new file mode 100644 index 00000000..2b3349a2 --- /dev/null +++ b/docs/03.gen.daisy.md @@ -0,0 +1,18 @@ +# Daisy + +Currently daisy platform is supported for: + +* `seed` +* `pod` +* `petal` +* `patch` + +Which can be configured using the `-m` metadata.json `daisy.board` setting: + +```json +{ + "daisy": { + "board": "seed" + } +} +``` diff --git a/docs/03.gen.dpf.md b/docs/03.gen.dpf.md new file mode 100644 index 00000000..b674f7c7 --- /dev/null +++ b/docs/03.gen.dpf.md @@ -0,0 +1,70 @@ +# DPF + +Heavy can generate LV2 and VST2 plugins from your patch using the [Distrho Plugin Framework](https://github.com/DISTRHO/DPF). It can be either a synth (output-only) or an effect (input and output), supports an arbitrary number of parameters, and can process midi events. + +## Defining Parameters +Each [exposed parameter](02.getting_started.md#exposing-parameters) will automatically generate a slider in the plugin interface. + +## MIDI Control +In order to receive MIDI note on and off events, as well as control change messages, the `[notein]` and `[ctlin]` objects should be used, respectively. + +![notein](img/docs_notein.png) + +## Parameter Types +In DPF a parameter can get an optional type configured. The default type is `float`. Other assignable types are `bool` - for toggling a value - and `trig` - for momentary signals. + +![dpf](img/docs_param_type.png) + +The following dpf jinja templating: + +```jinja + parameter.hints = kParameterIsAutomable + {% if v.attributes.type == 'bool': %} + | kParameterIsBoolean + {% elif v.attributes.type == 'trig': %} + | kParameterIsTrigger + {% endif %}; +``` + +Generates the subsequent plugin code: + +```c++ + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; +// or + parameter.hints = kParameterIsAutomable | kParameterIsTrigger; +``` + +## Metadata + +An accomponying metadata.json file can be included to set additional plugin settings. + +The `project` flag creates a `README.md` and `Makefile` in the root of the project output, but may conflict with other generators. + +Each of these are optional and have either a default value or are entirely optional (description and homepage). Midi i/o ports are on by default, but can be set to `0` and they will be disabled - currently `midi_input` always has to be on!. + + +```json +{ + "dpf": { + "project": true, + "description": "super simple test patch", + "maker": "nobody", + "homepage": "https://wasted.audio/plugin/dpf_example", + "plugin_uri": "lv2://wasted.audio/lv2/dpf_example", + "version": "6, 6, 6", + "license": "WTFPL", + "midi_input": 1, + "midi_output": 0, + "plugin_formats": [ + "lv2_dsp", + "vst", + "jack" + ] + } +} +``` + +## Notes +* The `[notein]` object is the only supported means of receiving MIDI note events (i.e. Note On and Note Off). Arguments to the object (e.g. to specify the channel number) will be ignored. +* The `[ctlin]` object is the only supported means of receiving MIDI control change events. Arguments to the object (e.g. to filter which CC event is delivered) will be ignored. +* If you are compiling from source, make sure to read the included `README.md` file in the root directory. diff --git a/docs/04.fabric.md b/docs/03.gen.fabric.md old mode 100755 new mode 100644 similarity index 100% rename from docs/04.fabric.md rename to docs/03.gen.fabric.md diff --git a/docs/07.javascript.md b/docs/03.gen.javascript.md old mode 100755 new mode 100644 similarity index 100% rename from docs/07.javascript.md rename to docs/03.gen.javascript.md diff --git a/docs/06.wwise.md b/docs/03.gen.md old mode 100755 new mode 100644 similarity index 100% rename from docs/06.wwise.md rename to docs/03.gen.md diff --git a/docs/05.unity.md b/docs/03.gen.unity.md old mode 100755 new mode 100644 similarity index 100% rename from docs/05.unity.md rename to docs/03.gen.unity.md diff --git a/docs/03.generators.md b/docs/03.generators.md new file mode 100644 index 00000000..e086770d --- /dev/null +++ b/docs/03.generators.md @@ -0,0 +1,12 @@ +# Generators + +HVCC supports a number of dedicated generators that can help to wrap the heavy c/cpp output into a pluggable format: + +* `Bela` +* [Daisy](03.gen.daisy.md) +* [DPF](03.gen.dpf.md) +* [Fabric](03.gen.fabric.md) +* [Javascript](03.gen.javascript.md) +* `Pdext` +* [Wwise](03.gen.wwise.md) +* [Unity](03.gen.unity.md) \ No newline at end of file diff --git a/docs/03.uploader.md b/docs/03.uploader.md deleted file mode 100644 index 9e13a789..00000000 --- a/docs/03.uploader.md +++ /dev/null @@ -1,121 +0,0 @@ -# Uploader - -:warning: The heavy Uploader tool is no longer supported :warning: - -## Getting Started -A command-line Python script is available to help automate Heavy builds. It can upload patches, including abstractions, and place the results in the desired location. Any assets that are available through the website, including binary builds, are accessible for download. The script can also be integrated into IDE build processes, such as Xcode and Visual Studio. - -* Make sure [Python 2.x](https://www.python.org/downloads/) is installed. Do not use Python 3. - -In a command-line application like Terminal, first make sure `pip` is installed: -``` -sudo easy_install pip -``` - -Install the latest uploader script: -``` -sudo pip install hv-uploader -``` - -Updating the uploader script: -``` -sudo pip install hv-uploader -U -``` - -For more information see the package repository here: https://github.com/enzienaudio/hv-uploader - -## Basic Usage -The most straightfoward use of the Uploader is to submit a patch, potentially consisting of many abstractions, and download C source code. This can easily be achieved with the following command line on OSX or Unix: - -``` -hv-uploader /path/to/patch --out /path/to/output --name heavy -``` - -On Windows paths may need to be quoted if there are spaces in any of the directory names: - -``` -hv-uploader "C:\path\to\patch directory" --out "C:\path\to\output" --name heavy -``` - -* The name of the patch, in this case "heavy", must be the same as an existing project on the Heavy website. If a similarly-named project does not exist, the uploader will fail. -* The input to the uploader must be a directory, and the root patch in that directory must be called `_main.pd`. -* All `.pd` files in the `/path/to/patch` will be uploaded, including subdirectories. In this way abstractions can also be included in the project. Files outside of the given root directory will not be uploaded. - -The uploader will report basic basic statistics on success, e.g.: - -``` -c files placed in /path/to/output -Job URL: https://enzienaudio.com/h/dev/heavy/5KFkg -Total request time: 444ms -Heavy version: 2308 -``` - -## Framework Generators -The source code for other frameworks can be downloaded with the `--gen` keyword. For instance the `vst2-src` argument downloads the VST source code. - -``` -hv-uploader /path/to/patch --out /path/to/output --name heavy --gen vst2-src -``` - -Available generators are: -* `c-src`: C/C++ source code (default if `-g` or `--gen` is not passed) -* `fabric-src`: Fabric plugin source code -* `unity-src`: Unity plugin source code -* `vst2-src`: VST2 Windows 32bit plugin -* `wwise-src`: Wwise plugin source code -* `web-local`: Javascript lib minified with example WebAudio implementation -* `web-js`: Javascript lib minified, gzipped, ready for hosting - -The `-b` keyword allows multiple frameworks to be downloaded simultaneously and each placed in their own unique directories. - -``` -hv-uploader /path/to/patch --out /path/to/output --name heavy --gen vst2-src unity-src -b -``` - -In this case the output would look like: -``` -unity files placed in /path/to/output/unity -vst2 files placed in /path/to/output/vst2 -Job URL: https://enzienaudio.com/h/dev/heavy/qQmmj -Total request time: 903ms -Heavy release: r2016.07.05 -``` - -## Downloading Binaries -The same `--gen` (or `-g`) keyword can be used to download compiled binaries from Heavy. The full list of supported framework/binary combinations are: -* `fabric-android-armv7a`: Fabric Android armv7a plugin -* `fabric-macos-x64`: Fabric macOS 64bit plugin -* `fabric-win-x64`: Fabric Windows 64bit plugin -* `fabric-win-x86`: Fabric Windows 32bit plugin -* `unity-android-armv7a`: Unity Android armv7a plugins -* `unity-linux-x64`: Unity Linux 64bit plugins -* `unity-macos-x64`: Unity macOS 64bit plugins -* `unity-win-x64`: Unity Windows 64bit plugins -* `unity-win-x86`: Unity Windows 32bit plugins -* `vst2-linux-x64`: VST2 Windows 32bit plugin -* `vst2-macos-x64`: VST2 Windows 32bit plugin -* `vst2-win-x64`: VST2 Windows 32bit plugin -* `vst2-win-x86`: VST2 Windows 32bit plugin -* `wwise-ios-armv7a`: Wwise iOS armv7a plugin -* `wwise-linux-x64`: Wwise Linux 64bit plugin -* `wwise-macos-x64`: Wwise macOS 64bit plugin -* `wwise-win-x64`: Wwise Windows 64bit plugin -* `wwise-win-x86`: Wwise Windows 32bit plugin - -For instance, exporting a generated VST binary directly to the system's VST directory is as simple as: - -``` -hv-uploader /path/to/patch --out /path/to/vst/directory --name heavy --gen vst2-macos-x64 -``` - -## Stable Releases -Heavy supports a limited set of stable releases which can be selected using the optional `-r` or `--release` flags. While Heavy itself is constantly being developed and refined, changes in the internal function or public API may not be suitable or desirable at all points in the application development. The flag requests that a patch be compiled with a specific release of Heavy. If no flag is passed then the most current release of Heavy is used. Currently available releases are listed at [https://enzienaudio.com/a/releases](https://enzienaudio.com/a/releases) which returns a JSON object suitable for automated parsing. Stable releases will not be deprecated before the date indicated. - -``` -hv-uploader /path/to/patch --out /path/to/output --name heavy --release r2016.07.05 -``` - -## Notes -* The uploader returns a specific error code in case something goes wrong. Use the code to trigger specific behavior in a shell script. See the source code for more details. -* The uploader can also be called directly from a python script. See the source code for more details. -* See a description of all flags with `hv-uploader --help`. diff --git a/docs/04.midi.md b/docs/04.midi.md new file mode 100755 index 00000000..0fda26dc --- /dev/null +++ b/docs/04.midi.md @@ -0,0 +1,116 @@ +# MIDI I/O + +In PureData there are objects to handle interfacing with a machines MIDI device. + +**heavy** doesn't provide cross-platform implementation for MIDI I/O as the requirements tend to change depending on the platform or framework being used. + +Instead, it provides wrappers around these objects that route the data to specific hard-coded receivers/parameters in the patch context. For example a `[notein]` object will be replaced by a `[r __hv_notein]` receiver with input data split into its constituent parts and routed to the appropriate outlet. + +`[notein]` wrapper implementation: + +![notein](img/docs_midi_notein.png) + + +## Inputs + +The following Pd objects are mapped to their corresponding heavy parameter. + +| Pd object | heavy param | +| --------- | -------------- | +| [notein] | __hv_notein | +| [ctlin] | __hv_ctlin | +| [pgmin] | __hv_pgmin | +| [bendin] | __hv_bendin | +| [touchin] | __hv_touchin | + + +## Outputs + +The same principle applies for sending MIDI data out of the heavy context. If you add a [noteout] object there'll be a corresponding sendhook callback with a message containing the MIDI data sent by the patch. + +| Pd object | heavy sendhook | +| --------- | -------------- | +| [noteout] | __hv_noteout | +| [ctlout] | __hv_ctlout | +| [pgmout] | __hv_pgmout | +| [bendout] | __hv_bendout | +| [touchout] | __hv_touchout | + +## Note! + +`It is generally the users responsibility to convert to and from the MIDI byte data to the float values used by heavy.` + +Some framework targets like [DPF](03.gen.dpf.md) already have implementations available. However, if you're integrating the C/C++ code on a custom platform then you'll need to provide your own conversion process. + +Here's the `DPF` implementation as an example: + +```cpp +void {{class_name}}::run(const float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) +{ + uint32_t framesDone = 0; + uint32_t curEventIndex = 0; + + _context->process((float**)inputs, outputs, frames); + + while (framesDone < frames) + { + while (curEventIndex < midiEventCount && framesDone == midiEvents[curEventIndex].frame) + { + if (midiEvents[curEventIndex].size > MidiEvent::kDataSize) + continue; + + int status = midiEvents[curEventIndex].data[0]; + int command = status & 0xF0; + int channel = status & 0x0F; + int data1 = midiEvents[curEventIndex].data[1]; + int data2 = midiEvents[curEventIndex].data[2]; + + switch (command) { + case 0x80: // note off + case 0x90: { // note on + _context->sendMessageToReceiverV(0x67E37CA3, // __hv_notein + 1000.0*frames/getSampleRate(), "fff", + (float) data1, // pitch + (float) data2, // velocity + (float) channel); + break; + } + case 0xB0: { // control change + _context->sendMessageToReceiverV(0x41BE0F9C, // __hv_ctlin + 1000.0*frames/getSampleRate(), "fff", + (float) data2, // value + (float) data1, // controller number + (float) channel); + break; + } + case 0xC0: { // program change + _context->sendMessageToReceiverV(0x2E1EA03D, // __hv_pgmin, + 1000.0*frames/getSampleRate(), "ff", + (float) data1, + (float) channel); + break; + } + case 0xD0: { // aftertouch + _context->sendMessageToReceiverV(0x553925BD, // __hv_touchin + 1000.0*frames/getSampleRate(), "ff", + (float) data1, + (float) channel); + break; + } + case 0xE0: { // pitch bend + hv_uint32_t value = (((hv_uint32_t) data2) << 7) | ((hv_uint32_t) data1); + _context->sendMessageToReceiverV(0x3083F0F7, // __hv_bendin + 1000.0*frames/getSampleRate(), "ff", + (float) value, + (float) channel); + break; + } + default: break; + } + curEventIndex++; + } + framesDone++; + } +} +``` + diff --git a/docs/10.c.md b/docs/05.c.md old mode 100755 new mode 100644 similarity index 99% rename from docs/10.c.md rename to docs/05.c.md index c9911285..843a290a --- a/docs/10.c.md +++ b/docs/05.c.md @@ -2,7 +2,7 @@ The Heavy C API is the lowest-level programming interface to a Heavy patch. It allows a high degree of control over all aspects of its function, and its performance and debugging can be greatly influenced by use of platform-specific compiler options. This is the place to be for the maximum amount of control over how the patch executes on a device. -The C API is functionally equivalent to the [C++ API](11.cpp.md). +The C API is functionally equivalent to the [C++ API](06.cpp.md). ## Patch names diff --git a/docs/11.cpp.md b/docs/06.cpp.md similarity index 97% rename from docs/11.cpp.md rename to docs/06.cpp.md index 1ab18e78..15a76d1b 100644 --- a/docs/11.cpp.md +++ b/docs/06.cpp.md @@ -1,8 +1,8 @@ # C++ API -The Heavy C++ API is equivalent to the [C API](10.c.md). Its usage is a matter of preference, but may make the organisation of systems with multiple context types and instances easier. +The Heavy C++ API is equivalent to the [C API](05.c.md). Its usage is a matter of preference, but may make the organisation of systems with multiple context types and instances easier. -The pure virtual interface class to all Heavy contexts is called `HeavyContextInterface` and is defined in [HeavyContextInterface.hpp](https://github.com/Wasted-Audio/heavy/blob/master/src/HeavyContextInterface.hpp). The patch-specific header is `Heavy_example.hpp`. +The pure virtual interface class to all Heavy contexts is called `HeavyContextInterface` and is defined in [HeavyContextInterface.hpp](https://github.com/Wasted-Audio/hvcc/blob/develop/hvcc/generators/ir2c/static/HeavyContextInterface.hpp). The patch-specific header is `Heavy_example.hpp`. ## Heavy C++ API diff --git a/docs/12.heavy_lang.md b/docs/07.heavy_lang.md similarity index 100% rename from docs/12.heavy_lang.md rename to docs/07.heavy_lang.md diff --git a/docs/08.dpf.md b/docs/08.dpf.md deleted file mode 100755 index 5fecd21a..00000000 --- a/docs/08.dpf.md +++ /dev/null @@ -1,17 +0,0 @@ -# DPF - -Heavy can generate LV2 and VST2 plugins from your patch using the [Distrho Plugin Framework](https://github.com/DISTRHO/DPF). It can be either a synth (output-only) or an effect (input and output), supports an arbitrary number of parameters, and can process midi events. - -## Defining Parameters -Each [exposed parameter](02.getting_started.md#exposing-parameters) will automatically generate a slider in the plugin interface. - -## MIDI Control -In order to receive MIDI note on and off events, as well as control change messages, the `[notein]` and `[ctlin]` objects should be used, respectively. - -![notein](img/docs_notein.png) - - -## Notes -* The `[notein]` object is the only supported means of receiving MIDI note events (i.e. Note On and Note Off). Arguments to the object (e.g. to specify the channel number) will be ignored. -* The `[ctlin]` object is the only supported means of receiving MIDI control change events. Arguments to the object (e.g. to filter which CC event is delivered) will be ignored. -* If you are compiling from source, make sure to read the included `README.md` file in the root directory. diff --git a/docs/13.heavy_ir_lang.md b/docs/08.heavy_ir_lang.md similarity index 100% rename from docs/13.heavy_ir_lang.md rename to docs/08.heavy_ir_lang.md diff --git a/docs/09.midi.md b/docs/09.midi.md deleted file mode 100755 index e7c6f431..00000000 --- a/docs/09.midi.md +++ /dev/null @@ -1,50 +0,0 @@ -# MIDI I/O - -In PureData there are objects to handle interfacing with a machines MIDI device. - -**heavy** doesn't provide cross-platform implementation for MIDI I/O as the requirements tend to change depending on the platform or framework being used. - -Instead, it provides wrappers around these objects that route the data to specific hard-coded receivers/parameters in the patch context. For example a `[notein]` object will be replaced by a `[r __hv_notein]` receiver with input data split into its constituent parts and routed to the appropriate outlet. - -`[notein]` wrapper implementation: - -![notein](img/docs_midi_notein.png) - - -## Inputs - -The following Pd objects are mapped to their corresponding heavy parameter. - -| Pd object | heavy param | -| --------- | -------------- | -| [notein] | __hv_notein | -| [ctlin] | __hv_ctlin | -| [pgmin] | __hv_pgmin | -| [bendin] | __hv_bendin | -| [touchin] | __hv_touchin | - - -## Outputs - -The same principle applies for sending MIDI data out of the heavy context. If you add a [noteout] object there'll be a corresponding sendhook callback with a message containing the MIDI data sent by the patch. - -| Pd object | heavy sendhook | -| --------- | -------------- | -| [noteout] | __hv_noteout | -| [ctlout] | __hv_ctlout | -| [pgmout] | __hv_pgmout | -| [bendout] | __hv_bendout | -| [touchout] | __hv_touchout | - -## Note! - -`It is generally the users responsibility to convert to and from the MIDI byte data to the float values used by heavy.` - -Some framework targets like `dpf` already have implementations available. However, if you're integrating the C/C++ code on a custom platform then you'll need to provide your own conversion process. - -Here's the `dpf` implementation as an example: - -``` - -``` - diff --git a/docs/14.Supported_vanilla_objects.md b/docs/09.supported_vanilla_objects.md similarity index 96% rename from docs/14.Supported_vanilla_objects.md rename to docs/09.supported_vanilla_objects.md index 1b0df69b..71277e27 100644 --- a/docs/14.Supported_vanilla_objects.md +++ b/docs/09.supported_vanilla_objects.md @@ -2,7 +2,7 @@ These are all the objects that hvcc is able to parse. -A here is a list of [unsupported Pd objects](15.Unsupported_vanilla_objects.md). +A here is a list of [unsupported Pd objects](10.Unsupported_vanilla_objects.md). ### Message Objects ``` diff --git a/docs/15.Unsupported_vanilla_objects.md b/docs/10.unsupported_vanilla_objects.md similarity index 92% rename from docs/15.Unsupported_vanilla_objects.md rename to docs/10.unsupported_vanilla_objects.md index 62cbb75c..1be8b784 100644 --- a/docs/15.Unsupported_vanilla_objects.md +++ b/docs/10.unsupported_vanilla_objects.md @@ -2,7 +2,7 @@ These are all the objects that hvcc is not able to parse. It will give errors if you use them. -A here is a list of [supported Pd objects](14.Supported_vanilla_objects.md). +A here is a list of [supported Pd objects](09.Supported_vanilla_objects.md). ### Message Objects ``` diff --git a/docs/img/docs_dpf_example.png b/docs/img/docs_dpf_example.png new file mode 100644 index 00000000..fe01e8c9 Binary files /dev/null and b/docs/img/docs_dpf_example.png differ diff --git a/docs/img/docs_param_type.png b/docs/img/docs_param_type.png new file mode 100644 index 00000000..e153df9f Binary files /dev/null and b/docs/img/docs_param_type.png differ diff --git a/examples/dpf/README.md b/examples/dpf/README.md index 226bd3f1..726cb37e 100644 --- a/examples/dpf/README.md +++ b/examples/dpf/README.md @@ -1,22 +1,13 @@ # Distrho Plugin Format Generator example help -DPF generator supports extra configuration via a supplied meta-data file. Each of these are optional and have either a default value or are entirely optional (description and homepage). Midi i/o ports are on by default, but can be set to `0` and they will be disabled. +To build the sample run hvcc with the DPF generator and metadata option on an output directory: -```json -{ - "dpf": { - "description": "super simple test patch", - "maker": "nobody", - "homepage": "https://wasted.audio/plugin/test", - "plugin_uri": "lv2://wasted.audio/lv2/testplugin", - "version": "6, 6, 6", - "license": "WTFPL", - "midi_input": 0, - "midi_output": 1, - "plugin_formats": [ - "lv2_dsp", - "vst" - ] - } -} +```bash +$ mkdir dpf_example +$ hvcc dpf_example.pd -o dpf_example/ -g dpf -n dpf_example -m dpf_example.json +$ cd dpf_example/ +$ git clone https://github.com/DISTRHO/DPF.git dpf +$ make ``` + +The binaries will be in `bin/` \ No newline at end of file diff --git a/examples/dpf/dpf_example.json b/examples/dpf/dpf_example.json new file mode 100644 index 00000000..b1e21ed0 --- /dev/null +++ b/examples/dpf/dpf_example.json @@ -0,0 +1,18 @@ +{ + "dpf": { + "project": true, + "description": "super simple test patch", + "maker": "nobody", + "homepage": "https://wasted.audio/plugin/dpf_example", + "plugin_uri": "lv2://wasted.audio/lv2/dpf_example", + "version": "6, 6, 6", + "license": "WTFPL", + "midi_input": 1, + "midi_output": 0, + "plugin_formats": [ + "lv2_dsp", + "vst", + "jack" + ] + } +} \ No newline at end of file diff --git a/examples/dpf/dpf_example.pd b/examples/dpf/dpf_example.pd new file mode 100644 index 00000000..18b3bc2c --- /dev/null +++ b/examples/dpf/dpf_example.pd @@ -0,0 +1,21 @@ +#N canvas 268 61 512 452 12; +#X obj 89 84 r freq @hv_param 100 2000 500; +#X obj 89 167 osc~; +#X obj 89 275 *~; +#X obj 89 308 dac~; +#X obj 150 111 r gain @hv_param 0 1 0.5; +#X msg 150 140 \$1 100; +#X obj 150 169 line~; +#X obj 89 194 *~; +#X obj 150 215 r mute_toggle @hv_param 0 1 1 bool; +#X obj 150 244 r mute_momentary @hv_param 0 1 0 trig; +#X connect 0 0 1 0; +#X connect 1 0 7 0; +#X connect 2 0 3 0; +#X connect 2 0 3 1; +#X connect 4 0 5 0; +#X connect 5 0 6 0; +#X connect 6 0 7 1; +#X connect 7 0 2 0; +#X connect 8 0 2 1; +#X connect 9 0 2 1; diff --git a/examples/example.pd b/examples/example.pd new file mode 100644 index 00000000..bdb4f72f --- /dev/null +++ b/examples/example.pd @@ -0,0 +1,15 @@ +#N canvas 441 234 462 370 12; +#X obj 85 85 r freq @hv_param 100 2000 500; +#X obj 85 177 osc~; +#X obj 85 211 *~; +#X obj 86 250 dac~; +#X obj 147 122 r gain @hv_param 0 1 0.5; +#X msg 147 151 \$1 100; +#X obj 147 176 line~; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X connect 2 0 3 0; +#X connect 2 0 3 1; +#X connect 4 0 5 0; +#X connect 5 0 6 0; +#X connect 6 0 2 1; diff --git a/hvcc/__init__.py b/hvcc/__init__.py index c7680b13..de03146d 100644 --- a/hvcc/__init__.py +++ b/hvcc/__init__.py @@ -247,7 +247,7 @@ def compile_dataflow(in_path, out_dir, patch_name=None, patch_meta_file=None, if "bela" in generators: if verbose: print("--> Generating Bela plugin") - results["c2fabric"] = c2bela.c2bela.compile( + results["c2bela"] = c2bela.c2bela.compile( c_src_dir=c_src_dir, out_dir=os.path.join(out_dir, "bela"), patch_name=patch_name, diff --git a/hvcc/generators/c2dpf/c2dpf.py b/hvcc/generators/c2dpf/c2dpf.py index 38c284a6..1876455a 100644 --- a/hvcc/generators/c2dpf/c2dpf.py +++ b/hvcc/generators/c2dpf/c2dpf.py @@ -36,6 +36,7 @@ def compile(clazz, c_src_dir, out_dir, externs, dpf_meta = patch_meta.get("dpf", {}) else: dpf_meta = {} + dpf_project = dpf_meta.get('project') copyright_c = copyright_manager.get_copyright_for_c(copyright) # copyright_plist = copyright or u"Copyright {0} Enzien Audio, Ltd." \ @@ -50,6 +51,9 @@ def compile(clazz, c_src_dir, out_dir, externs, # copy over static files shutil.copytree(os.path.join(os.path.dirname(__file__), "static"), out_dir) + if dpf_project: + shutil.copy(os.path.join(os.path.dirname(__file__), "static/README.md"), f'{out_dir}/../') + # copy over generated C source files source_dir = os.path.join(out_dir, "source") shutil.copytree(c_src_dir, source_dir) @@ -100,15 +104,19 @@ def compile(clazz, c_src_dir, out_dir, externs, # ====================================================================================== # Linux - # - # linux_path = os.path.join(out_dir, "linux") - # os.makedirs(linux_path) + # plugin makefile with open(os.path.join(source_dir, "Makefile"), "w") as f: f.write(env.get_template("Makefile").render( name=patch_name, - meta=dpf_meta, - class_name=f"HeavyDPF_{patch_name}")) + meta=dpf_meta)) + + # project makefile + if dpf_project: + with open(os.path.join(source_dir, "../../Makefile"), "w") as f: + f.write(env.get_template("Makefile.project").render( + name=patch_name, + meta=dpf_meta)) buildjson.generate_json( out_dir, diff --git a/hvcc/generators/c2dpf/static/README.md b/hvcc/generators/c2dpf/static/README.md index b74d0d08..95dad597 100644 --- a/hvcc/generators/c2dpf/static/README.md +++ b/hvcc/generators/c2dpf/static/README.md @@ -6,29 +6,21 @@ This output is for the Distrho Plugin Format ([DPF](https://github.com/DISTRHO/D Make sure you have a (recent) DPF in the root of your output directory -`$ git clone https://github.com/DISTRHO/DPF.git /dpf` +```bash +$ cd +$ git clone https://github.com/DISTRHO/DPF.git dpf +``` Then compile the plugins from the source folder: -`$ cd /plugin/source/ && make` +```bash +$ make +``` -This will result in an `/bin/` folder with all binary assets. +This will result in an `bin/` folder with all binary assets. -## LV2 - -After this you will likely have to create the `.ttl` files for the LV2 version. First make sure you have a functioning `lv2_ttl_generator`: - -`$ cd /dpf/utils/lv2-ttl-generator && make` - -Then run it on your LV2 build from the binary directory and move the files into the target dir: - -`$ cd bin/ && ../dpf/utils/lv2_ttl_generator .lv2/_dsp.so && mv *ttl .lv2/` - -You can now add your `.lv2/` forder to your local `~/.lv2/` directory. - -## VST2 - -The VST2, `bin/-vst.so`, can be placed directly into your `~/.vst/` dir and accessed by your DAW of choice. +* LV2 - move `bin/.lv2/` folder to your local `~/.lv2/` dir +* VST2 - move `bin/-vst.so`, can be placed directly into your `~/.vst/` dir ## Jack diff --git a/hvcc/generators/c2dpf/templates/HeavyDPF.cpp b/hvcc/generators/c2dpf/templates/HeavyDPF.cpp index 40c05901..509f4336 100644 --- a/hvcc/generators/c2dpf/templates/HeavyDPF.cpp +++ b/hvcc/generators/c2dpf/templates/HeavyDPF.cpp @@ -7,21 +7,12 @@ START_NAMESPACE_DISTRHO -static float scaleParameterForIndex(uint32_t index, float value) -{ - switch (index) { - {% for k, v in receivers %} - case {{loop.index-1}}: return ({{v.attributes.max-v.attributes.min}}f*value) + {{v.attributes.min}}f; // {{v.display}} - {% endfor %} - default: return 0.0f; - } -} {{class_name}}::{{class_name}}() : Plugin(HV_LV2_NUM_PARAMETERS, 0, 0) { {% for k, v in receivers %} - _parameters[{{loop.index-1}}] = {{(v.attributes.default-v.attributes.min)/(v.attributes.max-v.attributes.min)}}f; // {{v.display}} + _parameters[{{loop.index-1}}] = {{v.attributes.default}}f; {% endfor %} } @@ -45,13 +36,14 @@ void {{class_name}}::initParameter(uint32_t index, Parameter& parameter) {% elif v.attributes.type == 'trig': %} | kParameterIsTrigger {% endif %}; - parameter.ranges.def = {{(v.attributes.default-v.attributes.min)/(v.attributes.max-v.attributes.min)}}f; + parameter.ranges.min = {{v.attributes.min}}f; + parameter.ranges.max = {{v.attributes.max}}f; + parameter.ranges.def = {{v.attributes.default}}f; break; {% endfor %} } {% endif %} _context = nullptr; - // // sampleRateChanged(0.0f); // initialise sample rate sampleRateChanged(44100.0f); // set sample rate to some default } @@ -75,7 +67,7 @@ void {{class_name}}::setParameterValue(uint32_t index, float value) case {{loop.index-1}}: { _context->sendFloatToReceiver( Heavy_{{name}}::Parameter::In::{{k|upper}}, - scaleParameterForIndex(index, value)); + value); break; } {% endfor %} diff --git a/hvcc/generators/c2dpf/templates/Makefile.project b/hvcc/generators/c2dpf/templates/Makefile.project new file mode 100644 index 00000000..b15947f7 --- /dev/null +++ b/hvcc/generators/c2dpf/templates/Makefile.project @@ -0,0 +1,45 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# +# Modified by Wasted Audio +# + +include dpf/Makefile.base.mk + +all: libs plugin gen + +define MISSING_SUBMODULES_ERROR + +Cannot find DGL! Please run "make submodules" to clone the missing submodules, then retry building the plugin. + +endef + +# -------------------------------------------------------------- +submodules: + git submodule update --init --recursive + +libs: + +plugin: libs + $(MAKE) all -C plugin/source + +gen: plugins dpf/utils/lv2_ttl_generator + @$(CURDIR)/dpf/utils/generate-ttl.sh +ifeq ($(MACOS),true) + @$(CURDIR)/dpf/utils/generate-vst-bundles.sh +endif + +dpf/utils/lv2_ttl_generator: + $(MAKE) -C dpf/utils/lv2-ttl-generator + +# -------------------------------------------------------------- + +clean: + $(MAKE) clean -C dpf/utils/lv2-ttl-generator + $(MAKE) clean -C plugin/source + +# -------------------------------------------------------------- + +.PHONY: plugins diff --git a/hvcc/generators/c2fabric/c2fabric.py b/hvcc/generators/c2fabric/c2fabric.py index 63d3297c..6725ad12 100644 --- a/hvcc/generators/c2fabric/c2fabric.py +++ b/hvcc/generators/c2fabric/c2fabric.py @@ -30,19 +30,22 @@ class c2fabric: def filter_xcode_copy(clazz, s): """Return a copyref hash suitable for use in an Xcode project file. """ - return hashlib.md5(s + "_copy").hexdigest().upper()[0:24] + s = hashlib.md5(f"{s}_copy".encode('utf-8')) + return s.hexdigest().upper()[0:24] @classmethod def filter_xcode_build(clazz, s): """Return a build hash suitable for use in an Xcode project file. """ - return hashlib.md5(s + "_build").hexdigest().upper()[0:24] + s = hashlib.md5(f"{s}_build".encode('utf-8')) + return s.hexdigest().upper()[0:24] @classmethod def filter_xcode_fileref(clazz, s): """Return a fileref hash suitable for use in an Xcode project file. """ - return hashlib.md5(s + "_fileref").hexdigest().upper()[0:24] + s = hashlib.md5(f"{s}_fileref".encode('utf-8')) + return s.hexdigest().upper()[0:24] @classmethod def filter_templates(clazz, template_name):