Skip to content

Latest commit

 

History

History
 
 

prologue

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

prologue SDK Source and Template Projects

日本語

Overview

All source files needed to build custom oscillators and effects for the prologue synthesizer exist under this directory.

Compatibility Notes

Firmware version >= 2.00 is required to run user units built with SDK version 1.1-0.

Overall Structure:

Setting up the Development Environment

Legacy Method

  1. Clone this repository and initialize/update submodules.
 $ git clone https://github.com/korginc/logue-sdk.git
 $ cd logue-sdk
 $ git submodule update --init
  1. Install toolchain: GNU Arm Embedded Toolchain
  2. Install other utilties:
    1. GNU Make
    2. Info-ZIP
    3. logue-cli (optional)

Docker Build Environment

Refer to Docker-based Build Environment.

Building the Demo Oscillator (Waves)

Waves is a morphing wavetable oscillator that uses the wavetables provided by the custom oscillator API. It is a good example of how to use API functions, declare edit menu parameters and use parameter values of various types. See waves/ for code and details.

Build Using Legacy Method

  1. move into the project directory.
$ cd logue-sdk/platform/prologue/waves/
  1. run make to build the project.
$ make
Compiler Options
<path>/logue-sdk/tools/gcc/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -DTHUMB_PRESENT -g -Os -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant -fcheck-new -std=c11 -mstructure-size-boundary=8 -W -Wall -Wextra -Wa,-alms=<path>/logue-sdk/platform/prologue/waves/build/lst/ -DSTM32F401xC -DCORTEX_USE_FPU=TRUE -DARM_MATH_CM4 -D__FPU_PRESENT -I. -I<path>/logue-sdk/platform/prologue/waves/inc -I<path>/logue-sdk/platform/prologue/waves/inc/api -I<path>/logue-sdk/platform/prologue/inc -I<path>/logue-sdk/platform/prologue/inc/dsp -I<path>/logue-sdk/platform/prologue/inc/utils -I<path>/logue-sdk/platform/prologue/../ext/CMSIS/CMSIS/Include

Compiling _unit.c
Compiling waves.cpp
Linking <path>/logue-sdk/platform/prologue/waves/build/waves.elf
Creating <path>/logue-sdk/platform/prologue/waves/build/waves.hex
Creating <path>/logue-sdk/platform/prologue/waves/build/waves.bin
Creating <path>/logue-sdk/platform/prologue/waves/build/waves.dmp

   text	   data	    bss	    dec	    hex	filename
   2040	      4	    144	   2188	    88c	<path>/logue-sdk/platform/prologue/waves/build/waves.elf

Creating <path>/logue-sdk/platform/prologue/waves/build/waves.list
Done
  1. To generate the final packaged file (.prlgunit), run make install.
$ make install
Packaging to <path>/logue-sdk/platform/prologue/waves/build/waves.prlgunit
Deploying to <path>/logue-sdk/platform/prologue/waves/waves.prlgunit
Done
  1. A .prlgunit file is generated. This is the final product.

Build Using Docker Container

  1. Execute docker/run_interactive.sh
 $ docker/run_interactive.sh
 user@logue-sdk $ 

1.1. (optional) List buildable projects

user@logue-sdk:~$ build -l --prologue
- prologue/dummy-delfx
- prologue/dummy-modfx
- prologue/dummy-osc
- prologue/dummy-revfx
- prologue/waves
  1. Use the build command with the the desired project's path (E.g. prologue/waves)
 user@logue-sdk:~$ build prologue/waves
 >> Initializing prologue development environment.
 Note: run 'env -r' to reset the environment
 >> Building /workspace/prologue/waves
 Compiler Options
 /usr/bin/arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -DTHUMB_PRESENT -g -Os -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant -fcheck-new -std=c11 -mstructure-size-boundary=8 -W -Wall -Wextra -Wa,-alms=/workspace/prologue/waves/build/lst/ -DSTM32F401xC -DCORTEX_USE_FPU=TRUE -DARM_MATH_CM4 -D__FPU_PRESENT -I. -I/workspace/prologue/waves/inc -I/workspace/prologue/waves/inc/api -I/workspace/prologue/inc -I/workspace/prologue/inc/dsp -I/workspace/prologue/inc/utils -I/workspace/ext/CMSIS/CMSIS/Include

 Compiling _unit.c
 Compiling waves.cpp
 cc1: warning: option '-mstructure-size-boundary' is deprecated
 Linking /workspace/prologue/waves/build/waves.elf
 Creating /workspace/prologue/waves/build/waves.bin
 Creating /workspace/prologue/waves/build/waves.hex
 Creating /workspace/prologue/waves/build/waves.dmp
 Creating /workspace/prologue/waves/build/waves.list
 
    text	   data	    bss	    dec	    hex	filename
    2032	      4	    144	   2180	    884	/workspace/prologue/waves/build/waves.elf
 
 Done
 
 >> Installing /workspace/prologue/waves
 Packaging to /workspace/prologue/waves/build/waves.prlgunit
 Deploying to /workspace/prologue/waves/waves.prlgunit
 Done
 
 >> Resetting environment
 >> Cleaning up prologue development environment.

Using unit Files

.prlgunit files are simple zip files containing the binary payload for the custom oscillator or effect and a metadata file. They can be loaded onto a prologue (or development board) using the logue-cli utility or the Librarian application.

Creating a New Project

  1. Create a copy of a template project for the module you are targetting (osc/modfx/delfx/revfx) and rename it to your convenience.
  2. Make sure the PLATFORMDIR variable at the top of the Makefile is set to point to the platform/ directory. This path will be used to locate external dependencies and required tools.
  3. Set your desired project name in project.mk. See the project.mk section for syntax details.
  4. Add source files to your new project and edit the project.mk file accordingly so that they are found during builds.
  5. Edit the manifest.json file and set the appropriate metadata for your project. See the manifest.json section for syntax details.

Project Structure

manifest.json

The manifest file consists essentially of a json dictionary like this one:

{
    "header" : 
    {
        "platform" : "prologue",
        "module" : "osc",
        "api" : "1.1-0",
        "dev_id" : 0,
        "prg_id" : 0,
        "version" : "1.0-0",
        "name" : "waves",
        "num_param" : 6,
        "params" : [
            ["Wave A",      0,  45,  ""],
            ["Wave B",      0,  43,  ""],
            ["Sub Wave",    0,  15,  ""],
            ["Sub Mix",     0, 100, "%"],
            ["Ring Mix",    0, 100, "%"],
            ["Bit Crush",   0, 100, "%"]
          ]
    }
}
  • platform (string) : Name of the target platform, should be set to prologue
  • module (string) : Keyword for the module targetted, should be one of the following: osc, modfx, delfx, revfx
  • api (string) : API version used. (format: MAJOR.MINOR-PATCH)
  • dev_id (int) : Developer ID, currently unused, set to 0
  • prg_id (int) : Program ID, currently unused, can be set for reference.
  • version (string) : Program version. (format: MAJOR.MINOR-PATCH)
  • name (string) : Program name. (will be displayed on the prologue)
  • num_params (int) : Number of parameters in edit menu. Only used for osc type projects, should be 0 for custom effects. Oscillators can have up to 6 custom parameters.
  • params (array) : Edit parameter descriptors. Only meaningful for osc type projects. Set to an empty array otherwise ([]).

Edit parameter descriptors are themselves arrays and should contain 4 values:

  1. name (string) : Up to about 10 characters can be displayed in the edit menu of the prologue.
  2. minimum value (int) : Value should be in -100,100 range.
  3. maximum value (int) : Value should be in -100,100 range and greater than minimum value.
  4. type (string) : "%" indicates a percentage type, an empty string indicates a typeless value.

In the case of typeless values, the minimum and maximum values should be positive. Also the displayed value will be offset by 1 such that a 0-9 range will be shown as 1-10 to the prologue's user.

project.mk

This file is included by the main Makefile to simplify customization.

The following variables are declared:

  • PROJECT : Project name. Will be used in the filename of build products.
  • UCSRC : C source files.
  • UCXXSRC : C++ source files.
  • UINCDIR : Header search paths.
  • UDEFS : Custom gcc define flags.
  • ULIB : Linker library flags.
  • ULIBDIR : Linker library search paths.

tests/

The tests/ directory contains very simple code that illustrates how to write oscillators and effects. They are not meant to do anything useful, nor claim to be optimized. You can refer to these as examples of how to use the different interfaces and test your setup.

Core API

Here's an overview of the core API for custom oscillator/effects.

Oscillators (osc)

Your main implementation file should include userosc.h and implement the following functions.

  • void OSC_INIT(uint32_t platform, uint32_t api): Called on instantiation of the oscillator. Use this callback to perform any required initializations. See inc/userprg.h for possible values of platform and api.

  • void OSC_CYCLE(const user_osc_param_t * const params, int32_t *yn, const uint32_t frames): This is where the waveform should be computed. This function is called every time a buffer of frames samples is required (1 sample per frame). Samples should be written to the yn buffer. Output samples should be formatted in Q31 fixed point representation.

    Note: Floating-point numbers can be converted to Q31 format using the f32_to_q31(f) macro defined in inc/utils/fixed_math.h. Also see inc/userosc.h for user_osc_param_t definition.

    Note: Buffer lengths up to 64 frames should be supported. However you can perform multiple passes on smaller buffers if you prefer. (Optimize for powers of two: 16, 32, 64)

  • void OSC_NOTEON(const user_osc_param_t * const params): Called whenever a note on event occurs.

  • void OSC_NOTEOFF(const user_osc_param_t * const params): Called whenever a note off event occurs.

  • void OSC_PARAM(uint16_t index, uint16_t value): Called whenever the user changes a parameter value.

For more details see the Oscillator Instance API reference. Also see the Oscillator Runtime API, Arithmetic Utilities and Common DSP Utilities for useful primitives.

Modulation Effects API (modfx)

Your main implementation file should include usermodfx.h and implement the following functions.

  • void MODFX_INIT(uint32_t platform, uint32_t api): Called on instantiation of the effect. Use this callback to perform any required initializations. See inc/userprg.h for possible values of platform and api.

  • void MODFX_PROCESS(const float *main_xn, float *main_yn, const float *sub_xn, float *sub_yn, uint32_t frames): This is where you should process the input samples. This function is called every time a buffer of frames samples is required (1 sample per frame). *_xn buffers denote inputs and *_yn denote output buffers, where you should write your results.

    Note: There are main_ and sub_ versions of the inputs and outputs in order to support the dual timbre feature of the prologue. On the prologue, both main and sub should be processed the same way in parallel. On other non-multitimbral platforms you can ignore sub_xn and sub_yn

    Note: Buffer lengths up to 64 frames should be supported. However you can perform multiple passes on smaller buffers if you prefer. (Optimize for powers of two: 16, 32, 64)

  • void MODFX_PARAM(uint8_t index, uint32_t value): Called whenever the user changes a parameter value.

For more details see the Modulation Effect Instance API reference. Also see the Effects Runtime API, Arithmetic Utilities and Common DSP Utilities for useful primitives.

Delay Effects API (delfx)

Your main implementation file should include userdelfx.h and implement the following functions.

  • void DELFX_INIT(uint32_t platform, uint32_t api): Called on instantiation of the effect. Use this callback to perform any required initializations. See inc/userprg.h for possible values of platform and api.

  • void DELFX_PROCESS(float *xn, uint32_t frames): This is where you should process the input samples. This function is called every time a buffer of frames samples is required (1 sample per frame). In this case xn is both the input and output buffer. Your results should be written in place mixed with the appropriate amount of dry and wet signal (e.g.: set via the shift-depth parameter).

    Note: Buffer lengths up to 64 frames should be supported. However you can perform multiple passes on smaller buffers if you prefer. (Optimize for powers of two: 16, 32, 64)

  • void DELFX_PARAM(uint8_t index, uint32_t value): Called whenever the user changes a parameter value.

For more details see the Delay Effect Instance API reference. Also see the Effects Runtime API, Arithmetic Utilities and Common DSP Utilities for useful primitives.

Reverb Effects API (revfx)

Your main implementation file should include userrevfx.h and implement the following functions.

  • void REVFX_INIT(uint32_t platform, uint32_t api): Called on instantiation of the effect. Use this callback to perform any required initializations. See inc/userprg.h for possible values of platform and api.

  • void REVFX_PROCESS(float *xn, uint32_t frames): This is where you should process the input samples. This function is called every time a buffer of frames samples is required (1 sample per frame). In this case xn is both the input and output buffer. Your results should be written in place mixed with the appropriate amount of dry and wet signal (e.g.: set via the shift-depth parameter).

    Note: Buffer lengths up to 64 frames should be supported. However you can perform multiple passes on smaller buffers if you prefer. (Optimize for powers of two: 16, 32, 64)

  • void REVFX_PARAM(uint8_t index, uint32_t value): Called whenever the user changes a parameter value.

For more details see the Reverb Effect Instance API reference. Also see the Effects Runtime API, Arithmetic Utilities and Common DSP Utilities for useful primitives.

Web Assembly Builds (experimental)

Emscripten builds for oscillators and a Web Audio player are available in the alpha/wasm-builds branch. This is still an experimental feature so some code may not work as expected.

Troubleshooting

Can't compile, missing CMSIS arm_math.h

The CMSIS submodule is likely not initialized or up to date. Make sure to run git submodule update --init to initialize and update all submodules.