From 1edb3ea1a81386ab05b096522fc346732670d901 Mon Sep 17 00:00:00 2001 From: Kautenja Date: Fri, 24 Apr 2020 16:50:02 -0500 Subject: [PATCH] implement Edges --- plugin.json | 13 +- res/Edges.svg | 247 ++++++++ src/Edges.cpp | 413 ++++++++++++ src/Edges/digital_oscillator.hpp | 378 +++++++++++ src/Edges/square_oscillator.hpp | 169 +++++ src/Edges/wavetables.hpp | 1020 ++++++++++++++++++++++++++++++ src/plugin.cpp | 1 + src/plugin.hpp | 1 + 8 files changed, 2241 insertions(+), 1 deletion(-) create mode 100644 res/Edges.svg create mode 100644 src/Edges.cpp create mode 100644 src/Edges/digital_oscillator.hpp create mode 100644 src/Edges/square_oscillator.hpp create mode 100644 src/Edges/wavetables.hpp diff --git a/plugin.json b/plugin.json index fa4eb83..a2335ae 100644 --- a/plugin.json +++ b/plugin.json @@ -230,6 +230,17 @@ "Hardware clone", "Polyphonic" ] + }, + { + "slug": "Edges", + "name": "Quad Chiptune Audio Generator", + "description": "Based on Mutable Instruments Edges", + "manualUrl": "https://mutable-instruments.net/modules/edges/manual/", + "modularGridUrl": "https://www.modulargrid.net/e/mutable-instruments-edges", + "tags": [ + "Oscillator", + "Hardware clone" + ] } ] -} \ No newline at end of file +} diff --git a/res/Edges.svg b/res/Edges.svg new file mode 100644 index 0000000..363c4cc --- /dev/null +++ b/res/Edges.svg @@ -0,0 +1,247 @@ + + + + Edges + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + quad chiptune audio generator + + + + \ No newline at end of file diff --git a/src/Edges.cpp b/src/Edges.cpp new file mode 100644 index 0000000..6551210 --- /dev/null +++ b/src/Edges.cpp @@ -0,0 +1,413 @@ +#include "plugin.hpp" +#include "Edges/digital_oscillator.hpp" +#include "Edges/square_oscillator.hpp" + +using simd::float_4; + +// --------------------------------------------------------------------------- +// MARK: Module +// --------------------------------------------------------------------------- + +/// the PWM values to cycle between +static const float SQUARE_PWM_VALUES[] = {0.5, 0.66, 0.75, 0.87, 0.95, 1.0}; + +struct Edges : Module { + enum ParamIds { + FREQ1_PARAM, + XMOD1_PARAM, + LEVEL1_PARAM, + FREQ2_PARAM, + XMOD2_PARAM, + LEVEL2_PARAM, + FREQ3_PARAM, + XMOD3_PARAM, + LEVEL3_PARAM, + FREQ4_PARAM, + LEVEL4_PARAM, + WAVEFORM1_PARAM, + WAVEFORM2_PARAM, + WAVEFORM3_PARAM, + WAVEFORM4_PARAM, + NUM_PARAMS + }; + enum InputIds { + GATE1_INPUT, + FREQ1_INPUT, + MOD1_INPUT, + GATE2_INPUT, + FREQ2_INPUT, + MOD2_INPUT, + GATE3_INPUT, + FREQ3_INPUT, + MOD3_INPUT, + GATE4_INPUT, + FREQ4_INPUT, + MOD4_INPUT, + NUM_INPUTS + }; + enum OutputIds { + WAVEFORM1_OUTPUT, + WAVEFORM2_OUTPUT, + WAVEFORM3_OUTPUT, + WAVEFORM4_OUTPUT, + MIX_OUTPUT, + NUM_OUTPUTS + }; + enum LightIds { + GATE1_LIGHT_GREEN, GATE1_LIGHT_RED, + GATE2_LIGHT_GREEN, GATE2_LIGHT_RED, + GATE3_LIGHT_GREEN, GATE3_LIGHT_RED, + GATE4_LIGHT_GREEN, GATE4_LIGHT_RED, + NUM_LIGHTS + }; + + Edges() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); + // setup waveform 1 parameters + configParam(FREQ1_PARAM, -36.0, 36.0, 0.0, "Channel 1 frequency", " Hz", dsp::FREQ_SEMITONE, dsp::FREQ_C4); + configParam(XMOD1_PARAM, 0.0, 1.0, 0.0, "Channel 1 to Channel 2 hard sync"); + configParam(LEVEL1_PARAM, 0.0, 1.0, 0.0, "Channel 1 level", "%", 0, 100); + // setup waveform 2 parameters + configParam(FREQ2_PARAM, -36.0, 36.0, 0.0, "Channel 2 frequency", " Hz", dsp::FREQ_SEMITONE, dsp::FREQ_C4); + configParam(XMOD2_PARAM, 0.0, 1.0, 0.0, "Channel 1 x Channel 2 ring modulation"); + configParam(LEVEL2_PARAM, 0.0, 1.0, 0.0, "Channel 2 level", "%", 0, 100); + // setup waveform 3 parameters + configParam(FREQ3_PARAM, -36.0, 36.0, 0.0, "Channel 3 frequency", " Hz", dsp::FREQ_SEMITONE, dsp::FREQ_C4); + configParam(XMOD3_PARAM, 0.0, 1.0, 0.0, "Channel 1 x Channel 3 ring modulation"); + configParam(LEVEL3_PARAM, 0.0, 1.0, 0.0, "Channel 3 level", "%", 0, 100); + // setup waveform 4 parameters + configParam(FREQ4_PARAM, -36.0, 36.0, 0.0, "Channel 4 frequency", " Hz", dsp::FREQ_SEMITONE, dsp::FREQ_C4); + configParam(LEVEL4_PARAM, 0.0, 1.0, 0.0, "Channel 4 level", "%", 0, 100); + // setup waveform selection parameters + configParam(WAVEFORM1_PARAM, 0.0, 1.0, 0.0, "Channel 1 select"); + configParam(WAVEFORM2_PARAM, 0.0, 1.0, 0.0, "Channel 2 select"); + configParam(WAVEFORM3_PARAM, 0.0, 1.0, 0.0, "Channel 3 select"); + configParam(WAVEFORM4_PARAM, 0.0, 1.0, 0.0, "Channel 4 select"); + } + + /// a type for the square wave oscillator + typedef SquareWaveOscillator<16, 16, float_4> Square; + /// a type for the digital oscillator + typedef DigitalOscillator Digital; + + /// channel 1 (square wave) + Square oscillator1; + /// channel 2 (square wave) + Square oscillator2; + /// channel 3 (square wave) + Square oscillator3; + /// channel 4 (digital selectable wave) + Digital oscillator4; + + /// a flag determining whether waveform 1's gate is open + bool is_gate1_open = true; + /// a flag determining whether waveform 2's gate is open + bool is_gate2_open = true; + /// a flag determining whether waveform 3's gate is open + bool is_gate3_open = true; + /// a flag determining whether waveform 4's gate is open + bool is_gate4_open = true; + + /// the voltage at 1V/oct port 1 + float_4 voct1_voltage = 0.f; + /// the voltage at 1V/oct port 2 + float_4 voct2_voltage = 0.f; + /// the voltage at 1V/oct port 3 + float_4 voct3_voltage = 0.f; + /// the voltage at 1V/oct port 4 + float voct4_voltage = 0.f; + + /// the mod voltage for mod port 1 + float_4 mod1_voltage = 0.f; + /// the mod voltage for mod port 2 + float_4 mod2_voltage = 0.f; + /// the mod voltage for mod port 3 + float_4 mod3_voltage = 0.f; + /// the mod voltage for mod port 4 + float mod4_voltage = 0.f; + + /// the state of oscillator 1 determined by the button + int osc1_state = 0; + /// the state of oscillator 2 determined by the button + int osc2_state = 0; + /// the state of oscillator 3 determined by the button + int osc3_state = 0; + + /// a Schmitt trigger for handling inputs to the waveform select 1 button + dsp::SchmittTrigger oscillator1Trigger; + /// a Schmitt trigger for handling inputs to the waveform select 2 button + dsp::SchmittTrigger oscillator2Trigger; + /// a Schmitt trigger for handling inputs to the waveform select 3 button + dsp::SchmittTrigger oscillator3Trigger; + /// a Schmitt trigger for handling inputs to the waveform select 4 button + dsp::SchmittTrigger oscillator4Trigger; + + /// Process the gate inputs to determine which waveforms are active. + /// Note that Gates are normalled, meaning that when a connection is active + /// at a higher level gate, the signal propagates to lower level gates that + /// are not connected + /// TODO: determine whether the 0.7V threshold from hardware specification + /// fits the software model + void process_gate_inputs() { + // the 0.7V threshold is from the hardware specification for Edges + is_gate1_open = inputs[GATE1_INPUT].getNormalVoltage(0.7f) >= 0.7f; + is_gate2_open = inputs[GATE2_INPUT].getNormalVoltage(is_gate1_open * 0.7f) >= 0.7f; + is_gate3_open = inputs[GATE3_INPUT].getNormalVoltage(is_gate2_open * 0.7f) >= 0.7f; + is_gate4_open = inputs[GATE4_INPUT].getNormalVoltage(is_gate3_open * 0.7f) >= 0.7f; + // set LEDs for each of the gates + lights[GATE1_LIGHT_GREEN].setBrightness(is_gate1_open); + lights[GATE2_LIGHT_GREEN].setBrightness(is_gate2_open); + lights[GATE3_LIGHT_GREEN].setBrightness(is_gate3_open); + lights[GATE4_LIGHT_GREEN].setBrightness(is_gate4_open); + } + + /// Process the 1V/oct inputs + void process_voct_inputs() { + voct1_voltage = inputs[FREQ1_INPUT].getNormalVoltageSimd(0, 0); + voct2_voltage = inputs[FREQ2_INPUT].getNormalVoltageSimd(voct1_voltage, 0); + voct3_voltage = inputs[FREQ3_INPUT].getNormalVoltageSimd(voct2_voltage, 0); + // get the normalled channel 4 input as a float + auto voct1_voltage_ = inputs[FREQ1_INPUT].getNormalVoltage(0, 0); + auto voct2_voltage_ = inputs[FREQ2_INPUT].getNormalVoltage(voct1_voltage_, 0); + auto voct3_voltage_ = inputs[FREQ3_INPUT].getNormalVoltage(voct2_voltage_, 0); + voct4_voltage = inputs[FREQ4_INPUT].getNormalVoltage(voct3_voltage_, 0); + // TODO: refactor to use the float_4 structure + // voct4_voltage = inputs[FREQ4_INPUT].getNormalVoltageSimd(voct3_voltage, 0); + } + + inline void process_mod_inputs() { + mod1_voltage = inputs[MOD1_INPUT].getNormalVoltageSimd(0, 0); + mod2_voltage = inputs[MOD2_INPUT].getNormalVoltageSimd(0, 0); + mod3_voltage = inputs[MOD3_INPUT].getNormalVoltageSimd(0, 0); + mod4_voltage = inputs[MOD4_INPUT].getNormalVoltage(0, 0); + } + + void process_buttons() { + // process a button press for oscillator 1 + if (oscillator1Trigger.process(params[WAVEFORM1_PARAM].getValue())) { + osc1_state = (osc1_state + 1) % 6; + if (osc1_state < 5) { + oscillator1.setPulseWidth(SQUARE_PWM_VALUES[osc1_state]); + } + } + // set PWM for oscillator 1 based on oscillator 4 frequency control + if (osc1_state == 5) { + oscillator1.setPulseWidth(inputs[FREQ4_INPUT].getNormalVoltage(10.f) / 10.f); + } + + // process a button press for oscillator 2 + if (oscillator2Trigger.process(params[WAVEFORM2_PARAM].getValue())) { + osc2_state = (osc2_state + 1) % 6; + if (osc2_state < 5) { + oscillator2.setPulseWidth(SQUARE_PWM_VALUES[osc2_state]); + } + } + // set PWM for oscillator 2 based on oscillator 4 frequency control + if (osc2_state == 5) { + oscillator2.setPulseWidth(inputs[FREQ4_INPUT].getNormalVoltage(10.f) / 10.f); + } + + // process a button press for oscillator 3 + if (oscillator3Trigger.process(params[WAVEFORM3_PARAM].getValue())) { + osc3_state = (osc3_state + 1) % 6; + if (osc3_state < 5) { + oscillator3.setPulseWidth(SQUARE_PWM_VALUES[osc3_state]); + } + } + // set PWM for oscillator 3 based on oscillator 4 frequency control + if (osc3_state == 5) { + oscillator3.setPulseWidth(inputs[FREQ4_INPUT].getNormalVoltage(10.f) / 10.f); + } + + // process a button press for oscillator 4 + if (oscillator4Trigger.process(params[WAVEFORM4_PARAM].getValue())) { + oscillator4.nextShape(); + } + } + + void process_xmod_switches() { + oscillator2.syncEnabled = params[XMOD1_PARAM].getValue(); + oscillator2.ringModulation = params[XMOD2_PARAM].getValue(); + oscillator3.ringModulation = params[XMOD3_PARAM].getValue(); + } + + void process_frequency(float sampleTime, int sampleRate) { + // set the pitch of oscillator 1 + float_4 pitch1 = params[FREQ1_PARAM].getValue() / 12.f; + pitch1 += voct1_voltage; + pitch1 += mod1_voltage; + oscillator1.setPitch(pitch1); + // set the pitch of oscillator 2 + float_4 pitch2 = params[FREQ2_PARAM].getValue() / 12.f; + pitch2 += voct2_voltage; + pitch2 += mod2_voltage; + oscillator2.setPitch(pitch2); + // set the pitch of oscillator 3 + float_4 pitch3 = params[FREQ3_PARAM].getValue() / 12.f; + pitch3 += voct3_voltage; + pitch3 += mod3_voltage; + oscillator3.setPitch(pitch3); + // set the pitch of oscillator 4 + // get the pitch for the 4th oscillator (12 notes/octave * 1V/octave) + auto twelve_volt_octave = 12 * (voct4_voltage + mod4_voltage); + // 61 is the base for C4 + uint16_t pitch4_int = 61 + params[FREQ4_PARAM].getValue() + twelve_volt_octave; + // get the microtone for the 4th oscillator as 7-bit integer + uint16_t pitch4_frac = 128 * (params[FREQ4_PARAM].getValue() - static_cast(params[FREQ4_PARAM].getValue())); + pitch4_frac += 128 * (twelve_volt_octave - static_cast(twelve_volt_octave)); + // set the pitch of oscillator 4 + oscillator4.setPitch((pitch4_int << 7) + pitch4_frac + 64); + + // Process the output voltage of each oscillator + oscillator1.process(sampleTime); + // sync oscillator 2 to oscillator 1, ring mod with oscillator 1 + // (hard sync is only applied if oscillator2.syncEnabled is true) + // (ring mod is only applied if oscillator2.ringModulation is true) + oscillator2.process(sampleTime, oscillator1.sqr(), oscillator1.sqr()); + // don't sync oscillator 3, ring mod with oscillator 1 + // (ring mod is only applied if oscillator3.ringModulation is true) + oscillator3.process(sampleTime, 0, oscillator1.sqr()); + oscillator4.process(sampleRate); + } + + void process_output() { + // set outputs for channel 1 if connected + if (outputs[WAVEFORM1_OUTPUT].isConnected()) + outputs[WAVEFORM1_OUTPUT].setVoltageSimd(is_gate1_open * 5.f * oscillator1.sqr(), 0); + // set outputs for channel 2 if connected + if (outputs[WAVEFORM2_OUTPUT].isConnected()) + outputs[WAVEFORM2_OUTPUT].setVoltageSimd(is_gate2_open * 5.f * oscillator2.sqr(), 0); + // set outputs for channel 3 if connected + if (outputs[WAVEFORM3_OUTPUT].isConnected()) + outputs[WAVEFORM3_OUTPUT].setVoltageSimd(is_gate3_open * 5.f * oscillator3.sqr(), 0); + // set outputs for channel 4 if connected + if (outputs[WAVEFORM4_OUTPUT].isConnected()) + outputs[WAVEFORM4_OUTPUT].setVoltageSimd(is_gate4_open * 5.f * oscillator4.getValue(), 0); + // create the mixed output if connected + if (outputs[MIX_OUTPUT].isConnected()) { + auto the_mix = is_gate1_open * oscillator1.sqr() * !outputs[WAVEFORM1_OUTPUT].isConnected() * params[LEVEL1_PARAM].getValue(); + the_mix += is_gate2_open * oscillator2.sqr() * !outputs[WAVEFORM2_OUTPUT].isConnected() * params[LEVEL2_PARAM].getValue(); + the_mix += is_gate3_open * oscillator3.sqr() * !outputs[WAVEFORM3_OUTPUT].isConnected() * params[LEVEL3_PARAM].getValue(); + the_mix += is_gate4_open * oscillator4.getValue() * !outputs[WAVEFORM4_OUTPUT].isConnected() * params[LEVEL4_PARAM].getValue(); + outputs[MIX_OUTPUT].setVoltageSimd(5.f * the_mix, 0); + } + } + + void process(const ProcessArgs &args) override { + process_gate_inputs(); + process_voct_inputs(); + process_mod_inputs(); + process_buttons(); + process_xmod_switches(); + process_frequency(args.sampleTime, args.sampleRate); + process_output(); + } +}; + +// --------------------------------------------------------------------------- +// MARK: Widget +// --------------------------------------------------------------------------- + +/// A menu item for controlling the quantization feature +template +struct EdgesQuantizerItem : MenuItem { + /// the oscillator to control the quantization of + T *oscillator; + + /// Respond to a menu action. + inline void onAction(const event::Action &e) override { + oscillator->isQuantized = not oscillator->isQuantized; + } + + /// Perform a step on the menu. + inline void step() override { + rightText = oscillator->isQuantized ? "✔" : ""; + MenuItem::step(); + } +}; + +/// The widget structure that lays out the panel of the module and the UI menus. +struct EdgesWidget : ModuleWidget { + EdgesWidget(Edges *module) { + setModule(module); + setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Edges.svg"))); + // add vanity screws + addChild(createWidget(Vec(15, 0))); + addChild(createWidget(Vec(270, 0))); + addChild(createWidget(Vec(15, 365))); + addChild(createWidget(Vec(270, 365))); + // add frequency knobs + addParam(createParam(Vec(122, 54), module, Edges::FREQ1_PARAM)); + addParam(createParam(Vec(122, 114), module, Edges::FREQ2_PARAM)); + addParam(createParam(Vec(122, 174), module, Edges::FREQ3_PARAM)); + addParam(createParam(Vec(122, 234), module, Edges::FREQ4_PARAM)); + // add XMOD switches + addParam(createParam(Vec(178, 64), module, Edges::XMOD1_PARAM)); + addParam(createParam(Vec(178, 124), module, Edges::XMOD2_PARAM)); + addParam(createParam(Vec(178, 184), module, Edges::XMOD3_PARAM)); + // add level knobs + addParam(createParam(Vec(245, 54), module, Edges::LEVEL1_PARAM)); + addParam(createParam(Vec(245, 114), module, Edges::LEVEL2_PARAM)); + addParam(createParam(Vec(245, 174), module, Edges::LEVEL3_PARAM)); + addParam(createParam(Vec(245, 234), module, Edges::LEVEL4_PARAM)); + // add waveform selection buttons + addParam(createParam(Vec(43, 320), module, Edges::WAVEFORM1_PARAM)); + addParam(createParam(Vec(67, 320), module, Edges::WAVEFORM2_PARAM)); + addParam(createParam(Vec(91, 320), module, Edges::WAVEFORM3_PARAM)); + addParam(createParam(Vec(115, 320), module, Edges::WAVEFORM4_PARAM)); + // add inputs for Gate + addInput(createInput(Vec(20, 62), module, Edges::GATE1_INPUT)); + addInput(createInput(Vec(20, 122), module, Edges::GATE2_INPUT)); + addInput(createInput(Vec(20, 182), module, Edges::GATE3_INPUT)); + addInput(createInput(Vec(20, 242), module, Edges::GATE4_INPUT)); + // add inputs for Frequency (1V/Oct) + addInput(createInput(Vec(58, 62), module, Edges::FREQ1_INPUT)); + addInput(createInput(Vec(58, 122), module, Edges::FREQ2_INPUT)); + addInput(createInput(Vec(58, 182), module, Edges::FREQ3_INPUT)); + addInput(createInput(Vec(58, 242), module, Edges::FREQ4_INPUT)); + // add inputs for Mod + addInput(createInput(Vec(90, 62), module, Edges::MOD1_INPUT)); + addInput(createInput(Vec(90, 122), module, Edges::MOD2_INPUT)); + addInput(createInput(Vec(90, 182), module, Edges::MOD3_INPUT)); + addInput(createInput(Vec(90, 242), module, Edges::MOD4_INPUT)); + // add outputs for each waveform + addOutput(createOutput(Vec(215, 62), module, Edges::WAVEFORM1_OUTPUT)); + addOutput(createOutput(Vec(215, 122), module, Edges::WAVEFORM2_OUTPUT)); + addOutput(createOutput(Vec(215, 182), module, Edges::WAVEFORM3_OUTPUT)); + addOutput(createOutput(Vec(215, 242), module, Edges::WAVEFORM4_OUTPUT)); + // add output for mix (all waveforms mixed) + addOutput(createOutput(Vec(253, 315), module, Edges::MIX_OUTPUT)); + // add an LED for each waveform selection button + addChild(createLight>(Vec(46, 300), module, Edges::GATE1_LIGHT_GREEN)); + addChild(createLight>(Vec(70, 300), module, Edges::GATE2_LIGHT_GREEN)); + addChild(createLight>(Vec(94, 300), module, Edges::GATE3_LIGHT_GREEN)); + addChild(createLight>(Vec(118, 300), module, Edges::GATE4_LIGHT_GREEN)); + } + + void appendContextMenu(Menu *menu) override { + Edges *module = dynamic_cast(this->module); + assert(module); + // add the menu for the Quantizer feature + menu->addChild(construct()); + menu->addChild(construct(&MenuLabel::text, "Quantizer")); + menu->addChild(construct>( + &MenuItem::text, "Channel 1", + &EdgesQuantizerItem::oscillator, &module->oscillator1 + )); + menu->addChild(construct>( + &MenuItem::text, "Channel 2", + &EdgesQuantizerItem::oscillator, &module->oscillator2 + )); + menu->addChild(construct>( + &MenuItem::text, "Channel 3", + &EdgesQuantizerItem::oscillator, &module->oscillator3 + )); + menu->addChild(construct>( + &MenuItem::text, "Channel 4", + &EdgesQuantizerItem::oscillator, &module->oscillator4 + )); + } +}; + + +Model *modelEdges = createModel("Edges"); diff --git a/src/Edges/digital_oscillator.hpp b/src/Edges/digital_oscillator.hpp new file mode 100644 index 0000000..2dc0d4f --- /dev/null +++ b/src/Edges/digital_oscillator.hpp @@ -0,0 +1,378 @@ + +#include "wavetables.hpp" +#include + +#ifndef DIGITAL_OSCILLATOR +#define DIGITAL_OSCILLATOR + +// --------------------------------------------------------------------------- +// MARK: 24-bit floating point +// --------------------------------------------------------------------------- + +/// A 24-bit floating point number +struct uint24_t { + /// the integral piece of the number + uint16_t integral; + /// the fractional piece of the number + uint8_t fractional; +}; + +/// Return the sum of two uint24_t values. +/// +/// @param left the left operand +/// @param right the right operand +/// @returns the sum of the left and right operands +/// +static inline uint24_t operator+(uint24_t left, uint24_t right) { + uint24_t result; + uint32_t leftv = (static_cast(left.integral) << 8) + left.fractional; + uint32_t rightv = (static_cast(right.integral) << 8) + right.fractional; + uint32_t sum = leftv + rightv; + result.integral = sum >> 8; + result.fractional = sum & 0xff; + return result; +} + +/// Perform a right shift operation in place. +/// +/// @param value a reference to the uint24_t to shift right in place +/// @returns a reference to value +/// +static inline uint24_t& operator>>=(uint24_t& value, uint8_t num_shifts) { + while (num_shifts--) { + uint32_t av = static_cast(value.integral) << 8; + av += value.fractional; + av >>= 1; + value.integral = av >> 8; + value.fractional = av & 0xff; + } + return value; +} + +// --------------------------------------------------------------------------- +// MARK: Interpolation +// --------------------------------------------------------------------------- + +/// Mix two 8-bit values. +/// +/// @param a the first value to mix +/// @param b the second value to mix +/// @param balance the mix between a (0) and b (255) +/// +static inline uint8_t mix(uint16_t a, uint16_t b, uint8_t balance) { + return (a * (255 - balance) + b * balance) >> 8; +} + +/// Interpolate between a sample from a wave table. +/// +/// @param table a pointer to the table to lookup samples in +/// @param phase the current phase in the wave table +/// +static inline uint8_t interpolate(const uint8_t* table, uint16_t phase) { + auto index = phase >> 7; + return mix(table[index], table[index + 1], phase & 0xff); +} + +/// Interpolate between two wave tables. +/// +/// @param table_a the first wave table +/// @param table_b the second wave table +/// @param phase the phase in the wave table +/// @param gain_a the gain for the first wave +/// @param gain_b the gain for the second wave +/// @returns a value interpolated between the two wave tables at the given phase +/// +static inline uint16_t interpolate( + const uint8_t* table_a, + const uint8_t* table_b, + uint16_t phase, + uint8_t gain_a, + uint8_t gain_b +) { + uint16_t result = 0; + result += interpolate(table_a, phase) * gain_a; + result += interpolate(table_b, phase) * gain_b; + return result; +} + +// --------------------------------------------------------------------------- +// MARK: Digital Oscillator +// --------------------------------------------------------------------------- + +/// The wave shapes for the digital oscillator +enum OscillatorShape { + OSC_SINE = 0, + OSC_TRIANGLE, + OSC_NES_TRIANGLE, + OSC_PITCHED_NOISE, + OSC_NES_NOISE_LONG, + OSC_NES_NOISE_SHORT, + NUM_DIGITAL_OSC // the total number of oscillators in the enumeration +}; + +/// TODO: document +static const uint8_t kMaxZone = 7; +/// TODO: document +static const int16_t kOctave = 12 * 128; +/// TODO: document +static const int16_t kPitchTableStart = 116 * 128; + +/// the native sample rate of the digital oscillator +static const float SAMPLE_RATE = 48000.f; + +/// A digital oscillator with triangle, NES triangle, NES noise, hold & sample +/// noise, and sine wave shapes. +template +class DigitalOscillator { + public: + /// whether note quantization is enabled + bool isQuantized = false; + /// Initialize a new digital oscillator. + DigitalOscillator() { intialize(); } + + /// Destroy an existing digital oscillator. + ~DigitalOscillator() { } + + /// Initialize the digital oscillator + void intialize() { + // set the pitch to the default value + setPitch(60 << 7); + // reset the wave shape to the first value + shape_ = OSC_SINE; + // set the gate to true (i.e., open) + setGate(true); + // reset the random number seed to 1 + rng_state_ = 1; + } + + /// Set the wave shape to a new value. + /// + /// @param shape_ the wave shape to select + /// + inline void setShape(OscillatorShape shape) { shape_ = shape; } + + /// Select the next wave shape. + inline void nextShape() { + auto next_shape = (static_cast(shape_) + 1) % NUM_DIGITAL_OSC; + shape_ = static_cast(next_shape); + } + + /// Set the pitch to a new value. + /// + /// @param pitch_ the pitch of the oscillator + /// + inline void setPitch(int16_t pitch) { + if (isQuantized) pitch = pitch & 0b1111111110000000; + pitch_ = pitch; + } + + /// Set the gate to a new value. + /// + /// @param gate_ the gate of the oscillator + /// + inline void setGate(bool gate) { gate_ = gate; } + + /// Set the CV Pulse Width to a new value. + /// + /// @param cv_pw_ the CV parameter for the pulse width + /// + inline void set_cv_pw(uint8_t cv_pw) { cv_pw_ = cv_pw; } + + /// Render a sample from the oscillator using current parameters. + void process(int sampleRate) { + if (gate_) { + computePhaseIncrement(sampleRate); + (this->*getRenderFunction(shape_))(); + } else { + renderSilence(); + } + } + + /// Get the value from the oscillator in the range [-1.0, 1.0] + inline T getValue() const { + // divide the 12-bit value by 4096.0 to normalize in [0.0, 1.0] + // multiply by 2 and subtract 1 to get the value in [-1.0, 1.0] + return 2 * (value / 4096.0) - 1; + } + + private: + /// a type for calling and storing render functions for the wave shapes + typedef void (DigitalOscillator::*RenderFunction)(); + + /// Get the render function for the given shape. + /// + /// @param shape the wave shape to return the render function for + /// @returns the render function for the given wave shape + /// + static inline RenderFunction getRenderFunction(OscillatorShape shape) { + // create a static constant array of the functions + static const RenderFunction function_table[] = { + &DigitalOscillator::renderSine, + &DigitalOscillator::renderBandlimitedTriangle, + &DigitalOscillator::renderBandlimitedTriangle, + &DigitalOscillator::renderNoise, + &DigitalOscillator::renderNoiseNES, + &DigitalOscillator::renderNoiseNES + }; + // lookup the wave using the shape enumeration + return function_table[shape]; + } + + /// the current shape of the wave produced by the oscillator + OscillatorShape shape_ = OSC_TRIANGLE; + /// the current pitch of the oscillator + int16_t pitch_ = 60 << 7; + /// the 12TET quantized note based on the oscillator pitch + uint8_t note_ = 0; + /// whether the gate is open + bool gate_ = true; + + /// the phase the oscillator is currently at + uint24_t phase_; + /// the change inn phase at the current processing step + uint24_t phase_increment_; + /// The random number generator state for generating random noise + uint16_t rng_state_ = 1; + /// A sample from the sine wave to use for the random noise generators + uint16_t sample_ = 0; + /// The auxiliary phase for the sine wave bit crusher + uint16_t aux_phase_ = 0; + /// The CV PW value for the sine wave bit crusher + uint8_t cv_pw_ = 0; + + /// The output value from the oscillator + uint16_t value = 0; + + /// Compute the increment in phased for the current step. + /// + /// @param sampleRate the sample rate to output audio at + /// + void computePhaseIncrement(int sampleRate) { + int16_t ref_pitch = pitch_ - kPitchTableStart; + uint8_t num_shifts = shape_ >= OSC_PITCHED_NOISE ? 0 : 1; + while (ref_pitch < 0) { + ref_pitch += kOctave; + ++num_shifts; + } + + uint24_t increment; + uint16_t pitch_lookup_index_integral = ref_pitch >> 4; + uint8_t pitch_lookup_index_fractional = ref_pitch << 4; + + uint16_t increment16 = lut_res_oscillator_increments[pitch_lookup_index_integral]; + uint16_t increment16_next = lut_res_oscillator_increments[pitch_lookup_index_integral + 1]; + // set the integral and fractional of the increment + uint32_t increment16_diff = increment16_next - increment16; + uint32_t pitch32 = pitch_lookup_index_fractional; + uint16_t integral_diff = (increment16_diff * pitch32) >> 8; + // set the integral based o the current sample rate + increment.integral = (SAMPLE_RATE / sampleRate) * increment16 + integral_diff; + increment.fractional = 0; + increment >>= num_shifts; + + // shift the 15-bit pitch over 7 bits to produce a byte, 12 is the min value + note_ = std::max(pitch_ >> 7, 12); + phase_increment_ = increment; + } + + /// Run the sample loop with given callback for the loop body. + /// + /// @param render_fn a callback function that accepts the phase and phase + /// increment as parameters + /// + template + inline void renderWrapper(Callable render_fn) { + uint24_t phase; + uint24_t phase_increment; + phase_increment.integral = phase_increment_.integral; + phase_increment.fractional = phase_increment_.fractional; + phase.integral = phase_.integral; + phase.fractional = phase_.fractional; + render_fn(phase, phase_increment); + phase_.integral = phase.integral; + phase_.fractional = phase.fractional; + } + + /// Render silence from the oscillator. + inline void renderSilence() { value = 0; } + + /// Render a sine wave from the oscillator. + void renderSine() { + uint16_t aux_phase_increment = lut_res_bitcrusher_increments[cv_pw_]; + renderWrapper([&, this](uint24_t& phase, uint24_t& phase_increment) { + phase = phase + phase_increment; + aux_phase_ += aux_phase_increment; + if (aux_phase_ < aux_phase_increment || !aux_phase_increment) { + sample_ = interpolate(wav_res_bandlimited_triangle_6, phase.integral) << 8; + } + value = sample_ >> 4; + }); + } + + /// Render a triangle wave from the oscillator. + void renderBandlimitedTriangle() { + uint8_t balance_index = ((note_ - 12) << 4) | ((note_ - 12) >> 4); + uint8_t gain_2 = balance_index & 0xf0; + uint8_t gain_1 = ~gain_2; + + uint8_t wave_index = balance_index & 0xf; + uint8_t base_resource_id = (shape_ == OSC_NES_TRIANGLE) + ? WAV_RES_BANDLIMITED_NES_TRIANGLE_0 + : WAV_RES_BANDLIMITED_TRIANGLE_0; + + const uint8_t* wave_1 = waveform_table[base_resource_id + wave_index]; + wave_index = std::min(wave_index + 1, kMaxZone); + const uint8_t* wave_2 = waveform_table[base_resource_id + wave_index]; + + renderWrapper([&](uint24_t& phase, uint24_t& phase_increment) { + phase = phase + phase_increment; + uint16_t sample = interpolate(wave_1, wave_2, phase.integral, gain_1, gain_2); + value = sample >> 4; + }); + } + + /// Render NES noise from the oscillator. + void renderNoiseNES() { + uint16_t rng_state = rng_state_; + uint16_t sample = sample_; + renderWrapper([&, this](uint24_t& phase, uint24_t& phase_increment) { + phase = phase + phase_increment; + if (phase.integral < phase_increment.integral) { + uint8_t tap = rng_state >> 1; + if (shape_ == OSC_NES_NOISE_SHORT) { + tap >>= 5; + } + uint8_t random_bit = (rng_state ^ tap) & 1; + rng_state >>= 1; + if (random_bit) { + rng_state |= 0x4000; + sample = 0x0300; + } else { + sample = 0x0cff; + } + } + value = sample; + }); + rng_state_ = rng_state; + sample_ = sample; + } + + /// Render sample and hold noise from the oscillator. + void renderNoise() { + uint16_t rng_state = rng_state_; + uint16_t sample = sample_; + renderWrapper([&](uint24_t& phase, uint24_t& phase_increment) { + phase = phase + phase_increment; + if (phase.integral < phase_increment.integral) { + rng_state = (rng_state >> 1) ^ (-(rng_state & 1) & 0xb400); + sample = rng_state & 0x0fff; + sample = 512 + ((sample * 3) >> 2); + } + value = sample; + }); + rng_state_ = rng_state; + sample_ = sample; + } +}; + +#endif // DIGITAL_OSCILLATOR diff --git a/src/Edges/square_oscillator.hpp b/src/Edges/square_oscillator.hpp new file mode 100644 index 0000000..dc15a71 --- /dev/null +++ b/src/Edges/square_oscillator.hpp @@ -0,0 +1,169 @@ + +#ifndef SQUARE_OSCILLATOR_HPP +#define SQUARE_OSCILLATOR_HPP + +// --------------------------------------------------------------------------- +// MARK: Square Oscillator +// --------------------------------------------------------------------------- + +/// An oscillator that generates a square wave +template +struct SquareWaveOscillator { + /// whether the oscillator is emulating an analog oscillator + bool analog = false; + /// TODO: document + bool soft = false; + /// whether the oscillator is synced to another oscillator + bool syncEnabled = false; + /// Whether ring modulation is enabled + bool ringModulation = false; + /// whether note quantization is enabled + bool isQuantized = false; + // For optimizing in serial code + int channels = 0; + + /// the value from the last oscillator synchronization + T lastSyncValue = 0.f; + /// the current phase in [0, 1] (2 * pi * phase) + T phase = 0.f; + /// the current frequency + T freq; + /// the current pulse width in [0, 1] + T pulseWidth = 0.5f; + /// the direction of the synchronization + T syncDirection = 1.f; + + /// a filter for producing an analog effect on the square wave + dsp::TRCFilter sqrFilter; + + /// the minimum-phase band-limited step generator for preventing aliasing + dsp::MinBlepGenerator sqrMinBlep; + + /// The current value of the square wave + T sqrValue = 0.f; + + /// Set the pitch of the oscillator to a new value. + /// + /// @param pitch the new pitch to set the oscillator to + /// + inline void setPitch(T pitch) { + // quantized the pitch to semitone if enabled + if (isQuantized) pitch = floor(pitch * 12) / 12.f; + // set the frequency based on the pitch + freq = dsp::FREQ_C4 * dsp::approxExp2_taylor5(pitch + 30) / 1073741824; + } + + /// Set the pulse width of the square wave to a new value. + /// + /// @param pulseWidth the new pulse width to set the square wave to + /// + inline void setPulseWidth(T pulseWidth) { + const float pwMin = 0.01f; + this->pulseWidth = simd::clamp(pulseWidth, pwMin, 1.f - pwMin); + } + + /// Process a sample for given change in time and sync value. + /// + /// @param deltaTime the change in time between samples + /// @param syncValue the value of the oscillator to sync to + /// @param modulator the value of the oscillator applying ring modulation + /// + void process(float deltaTime, T syncValue = 0, T modulator = 1) { + // Advance phase + T deltaPhase = simd::clamp(freq * deltaTime, 1e-6f, 0.35f); + if (soft) // Reverse direction + deltaPhase *= syncDirection; + else // Reset back to forward + syncDirection = 1.f; + phase += deltaPhase; + // Wrap phase + phase -= simd::floor(phase); + + // Jump sqr when crossing 0, or 1 if backwards + T wrapPhase = (syncDirection == -1.f) & 1.f; + T wrapCrossing = (wrapPhase - (phase - deltaPhase)) / deltaPhase; + int wrapMask = simd::movemask((0 < wrapCrossing) & (wrapCrossing <= 1.f)); + if (wrapMask) { + for (int i = 0; i < channels; i++) { + if (wrapMask & (1 << i)) { + T mask = simd::movemaskInverse(1 << i); + float p = wrapCrossing[i] - 1.f; + T x = mask & (2.f * syncDirection); + sqrMinBlep.insertDiscontinuity(p, x); + } + } + } + + // Jump sqr when crossing `pulseWidth` + T pulseCrossing = (pulseWidth - (phase - deltaPhase)) / deltaPhase; + int pulseMask = simd::movemask((0 < pulseCrossing) & (pulseCrossing <= 1.f)); + if (pulseMask) { + for (int i = 0; i < channels; i++) { + if (pulseMask & (1 << i)) { + T mask = simd::movemaskInverse(1 << i); + float p = pulseCrossing[i] - 1.f; + T x = mask & (-2.f * syncDirection); + sqrMinBlep.insertDiscontinuity(p, x); + } + } + } + + // Detect sync + // Might be NAN or outside of [0, 1) range + if (syncEnabled) { + T deltaSync = syncValue - lastSyncValue; + T syncCrossing = -lastSyncValue / deltaSync; + lastSyncValue = syncValue; + T sync = (0.f < syncCrossing) & (syncCrossing <= 1.f) & (syncValue >= 0.f); + int syncMask = simd::movemask(sync); + if (syncMask) { + if (soft) { + syncDirection = simd::ifelse(sync, -syncDirection, syncDirection); + } + else { + T newPhase = simd::ifelse(sync, (1.f - syncCrossing) * deltaPhase, phase); + // Insert minBLEP for sync + for (int i = 0; i < channels; i++) { + if (syncMask & (1 << i)) { + T mask = simd::movemaskInverse(1 << i); + float p = syncCrossing[i] - 1.f; + T x; + x = mask & (sqr(newPhase) - sqr(phase)); + sqrMinBlep.insertDiscontinuity(p, x); + } + } + phase = newPhase; + } + } + } + + // process the square wave value + sqrValue = sqr(phase); + sqrValue += sqrMinBlep.process(); + + if (analog) { // apply an analog filter + sqrFilter.setCutoffFreq(20.f * deltaTime); + sqrFilter.process(sqrValue); + sqrValue = sqrFilter.highpass() * 0.95f; + } + + if (ringModulation) { // apply ring modulation + sqrValue *= modulator; + } + } + + /// Calculate and return the value of the square wave for given phase. + /// + /// @param phase the phase of the wave in [0, 1] + /// @returns the value of the wave in [0, 1] + /// + inline T sqr(T phase) { return simd::ifelse(phase < pulseWidth, 1.f, -1.f); } + + /// Return the value of the square wave. + /// + /// @returns the value of the wave in [0, 1] + /// + inline T sqr() const { return sqrValue; } +}; + +#endif // SQUARE_OSCILLATOR_HPP diff --git a/src/Edges/wavetables.hpp b/src/Edges/wavetables.hpp new file mode 100644 index 0000000..83bd818 --- /dev/null +++ b/src/Edges/wavetables.hpp @@ -0,0 +1,1020 @@ + +#include + +#ifndef WAVETABLES_HPP +#define WAVETABLES_HPP + +// --------------------------------------------------------------------------- +// MARK: Wave tables +// --------------------------------------------------------------------------- + +#define LUT_RES_TIMER_COUNT 0 +#define LUT_RES_TIMER_COUNT_SIZE 97 +#define LUT_RES_OSCILLATOR_INCREMENTS 1 +#define LUT_RES_OSCILLATOR_INCREMENTS_SIZE 97 +#define LUT_RES_BITCRUSHER_INCREMENTS 2 +#define LUT_RES_BITCRUSHER_INCREMENTS_SIZE 256 +#define WAV_RES_BANDLIMITED_TRIANGLE_0 0 +#define WAV_RES_BANDLIMITED_TRIANGLE_0_SIZE 513 +#define WAV_RES_BANDLIMITED_TRIANGLE_1 1 +#define WAV_RES_BANDLIMITED_TRIANGLE_1_SIZE 513 +#define WAV_RES_BANDLIMITED_TRIANGLE_2 2 +#define WAV_RES_BANDLIMITED_TRIANGLE_2_SIZE 513 +#define WAV_RES_BANDLIMITED_TRIANGLE_3 3 +#define WAV_RES_BANDLIMITED_TRIANGLE_3_SIZE 513 +#define WAV_RES_BANDLIMITED_TRIANGLE_4 4 +#define WAV_RES_BANDLIMITED_TRIANGLE_4_SIZE 513 +#define WAV_RES_BANDLIMITED_TRIANGLE_5 5 +#define WAV_RES_BANDLIMITED_TRIANGLE_5_SIZE 513 +#define WAV_RES_BANDLIMITED_TRIANGLE_6 6 +#define WAV_RES_BANDLIMITED_TRIANGLE_6_SIZE 513 +#define WAV_RES_BANDLIMITED_TRIANGLE_7 7 +#define WAV_RES_BANDLIMITED_TRIANGLE_7_SIZE 513 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_0 8 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_0_SIZE 513 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_1 9 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_1_SIZE 513 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_2 10 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_2_SIZE 513 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_3 11 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_3_SIZE 513 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_4 12 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_4_SIZE 513 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_5 13 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_5_SIZE 513 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_6 14 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_6_SIZE 513 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_7 15 +#define WAV_RES_BANDLIMITED_NES_TRIANGLE_7_SIZE 513 + +// const uint16_t lut_res_timer_count[] = { +// 61156, 60716, 60279, 59846, 59415, 58988, 58563, 58142, +// 57724, 57308, 56896, 56487, 56080, 55677, 55276, 54879, +// 54484, 54092, 53703, 53316, 52933, 52552, 52174, 51799, +// 51426, 51056, 50689, 50324, 49962, 49603, 49246, 48891, +// 48540, 48190, 47844, 47500, 47158, 46819, 46482, 46147, +// 45815, 45486, 45158, 44834, 44511, 44191, 43873, 43557, +// 43244, 42933, 42624, 42317, 42013, 41711, 41410, 41113, +// 40817, 40523, 40232, 39942, 39655, 39370, 39086, 38805, +// 38526, 38249, 37974, 37700, 37429, 37160, 36893, 36627, +// 36364, 36102, 35842, 35584, 35328, 35074, 34822, 34571, +// 34323, 34076, 33831, 33587, 33346, 33106, 32868, 32631, +// 32396, 32163, 31932, 31702, 31474, 31248, 31023, 30800, +// 30578, +// }; + +const uint16_t lut_res_oscillator_increments[] = { + 18126, 18258, 18390, 18523, 18657, 18793, 18929, 19066, + 19204, 19343, 19484, 19625, 19767, 19910, 20054, 20200, + 20346, 20494, 20642, 20792, 20942, 21094, 21247, 21401, + 21556, 21712, 21870, 22028, 22188, 22348, 22510, 22674, + 22838, 23003, 23170, 23338, 23507, 23677, 23849, 24022, + 24196, 24371, 24548, 24726, 24905, 25085, 25267, 25450, + 25635, 25820, 26008, 26196, 26386, 26577, 26770, 26964, + 27159, 27356, 27554, 27754, 27955, 28157, 28361, 28567, + 28774, 28983, 29193, 29404, 29617, 29832, 30048, 30266, + 30485, 30706, 30928, 31153, 31378, 31606, 31835, 32065, + 32298, 32532, 32768, 33005, 33244, 33485, 33728, 33972, + 34218, 34466, 34716, 34968, 35221, 35476, 35733, 35992, + 36253, +}; + +const uint16_t lut_res_bitcrusher_increments[] = { + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 43805, 32897, 26338, 21960, 18830, 16481, 14653, + 13190, 11992, 10994, 10150, 9425, 8798, 8248, 7764, + 7333, 6947, 6600, 6286, 6000, 5740, 5501, 5281, + 5078, 4890, 4715, 4553, 4401, 4259, 4126, 4001, + 3883, 3772, 3668, 3569, 3475, 3386, 3301, 3221, + 3144, 3071, 3001, 2934, 2871, 2809, 2751, 2695, + 2641, 2589, 2539, 2491, 2445, 2401, 2358, 2317, + 2277, 2238, 2201, 2165, 2130, 2096, 2063, 2032, + 2001, 1971, 1942, 1914, 1886, 1860, 1834, 1809, + 1784, 1761, 1737, 1715, 1693, 1671, 1651, 1630, + 1610, 1591, 1572, 1553, 1535, 1518, 1501, 1484, + 1467, 1451, 1435, 1420, 1405, 1390, 1375, 1361, + 1347, 1334, 1320, 1307, 1295, 1282, 1270, 1258, + 1246, 1234, 1223, 1211, 1200, 1190, 1179, 1168, + 1158, 1148, 1138, 1129, 1119, 1110, 1100, 1091, + 1082, 1073, 1065, 1056, 1048, 1040, 1031, 1024, +}; + +const uint8_t wav_res_bandlimited_triangle_0[] = { + 2, 2, 5, 3, 6, 5, 8, 8, + 8, 11, 10, 12, 13, 13, 15, 16, + 17, 18, 18, 20, 21, 23, 22, 23, + 26, 26, 27, 28, 28, 31, 30, 33, + 32, 34, 35, 36, 36, 38, 39, 40, + 40, 41, 44, 42, 46, 45, 46, 48, + 48, 50, 50, 51, 53, 54, 54, 55, + 57, 58, 57, 61, 59, 62, 63, 63, + 64, 66, 67, 66, 69, 69, 71, 71, + 72, 74, 73, 76, 76, 78, 77, 79, + 81, 80, 83, 83, 84, 85, 85, 88, + 88, 89, 90, 91, 92, 93, 93, 96, + 96, 97, 98, 99, 99, 102, 102, 102, + 104, 106, 105, 107, 108, 108, 111, 110, + 111, 114, 113, 115, 116, 116, 118, 118, + 120, 120, 123, 121, 125, 123, 127, 126, + 127, 129, 130, 130, 131, 134, 132, 135, + 136, 136, 138, 138, 139, 141, 141, 143, + 143, 145, 144, 147, 148, 147, 150, 150, + 151, 152, 154, 154, 154, 157, 157, 159, + 158, 160, 162, 161, 164, 164, 164, 167, + 167, 168, 169, 170, 172, 171, 173, 174, + 176, 175, 177, 178, 179, 180, 181, 182, + 182, 184, 185, 186, 187, 187, 189, 189, + 192, 191, 192, 194, 195, 196, 196, 197, + 200, 199, 200, 203, 202, 203, 205, 206, + 207, 207, 208, 211, 209, 213, 212, 213, + 215, 215, 217, 217, 218, 220, 220, 221, + 223, 222, 225, 225, 226, 228, 227, 230, + 229, 232, 232, 234, 233, 236, 236, 237, + 238, 240, 240, 242, 241, 244, 245, 245, + 245, 249, 247, 249, 250, 251, 251, 253, + 253, 254, 253, 250, 252, 249, 249, 248, + 247, 246, 246, 243, 243, 243, 240, 241, + 238, 239, 237, 235, 236, 233, 234, 231, + 231, 230, 229, 228, 226, 227, 224, 224, + 224, 221, 221, 220, 219, 218, 217, 217, + 214, 215, 213, 212, 211, 211, 209, 208, + 207, 207, 205, 204, 204, 201, 202, 201, + 198, 199, 197, 196, 196, 194, 193, 192, + 192, 190, 189, 188, 188, 186, 186, 183, + 185, 181, 182, 181, 179, 178, 178, 177, + 175, 175, 173, 173, 171, 171, 169, 170, + 166, 168, 165, 164, 164, 163, 161, 161, + 160, 158, 158, 156, 156, 155, 153, 153, + 152, 150, 150, 149, 148, 146, 146, 145, + 143, 144, 141, 141, 140, 139, 138, 137, + 135, 136, 133, 134, 131, 131, 131, 128, + 128, 127, 126, 125, 124, 123, 122, 121, + 120, 118, 119, 117, 116, 114, 115, 113, + 112, 111, 110, 110, 107, 108, 106, 105, + 104, 103, 103, 101, 100, 100, 98, 97, + 96, 96, 94, 93, 93, 90, 91, 90, + 88, 86, 88, 84, 85, 83, 83, 81, + 80, 79, 79, 77, 77, 75, 75, 73, + 73, 71, 70, 70, 69, 68, 66, 65, + 65, 64, 63, 61, 60, 61, 58, 57, + 58, 54, 56, 53, 53, 51, 51, 50, + 48, 48, 46, 46, 45, 44, 42, 42, + 40, 40, 40, 37, 36, 37, 35, 33, + 34, 31, 32, 30, 28, 29, 26, 27, + 25, 24, 22, 23, 21, 19, 20, 17, + 17, 16, 15, 13, 14, 11, 11, 10, + 8, 9, 7, 6, 5, 4, 4, 3, + 1, +}; + +const uint8_t wav_res_bandlimited_triangle_1[] = { + 2, 4, 5, 6, 6, 7, 10, 8, + 12, 10, 14, 12, 15, 16, 15, 18, + 19, 18, 21, 21, 22, 24, 23, 26, + 25, 28, 28, 29, 30, 30, 33, 32, + 35, 34, 36, 37, 38, 38, 40, 41, + 41, 43, 44, 44, 46, 47, 46, 50, + 49, 50, 51, 53, 54, 53, 56, 57, + 56, 59, 59, 60, 61, 62, 63, 65, + 64, 67, 66, 68, 70, 69, 71, 72, + 73, 73, 76, 75, 76, 79, 78, 80, + 80, 82, 83, 83, 84, 86, 87, 87, + 88, 90, 90, 91, 93, 93, 94, 95, + 97, 97, 97, 100, 101, 100, 102, 103, + 104, 105, 106, 107, 108, 109, 109, 112, + 111, 113, 113, 115, 116, 117, 117, 119, + 119, 121, 121, 123, 123, 125, 125, 126, + 128, 128, 130, 130, 131, 132, 133, 135, + 134, 137, 137, 138, 139, 140, 141, 142, + 143, 144, 144, 147, 146, 148, 149, 150, + 150, 152, 153, 154, 154, 155, 157, 158, + 158, 160, 160, 162, 161, 165, 164, 165, + 166, 168, 167, 170, 171, 170, 173, 172, + 175, 175, 176, 177, 178, 179, 179, 182, + 182, 182, 184, 185, 186, 187, 187, 189, + 190, 190, 192, 193, 193, 194, 196, 197, + 197, 199, 199, 200, 202, 201, 205, 203, + 206, 206, 207, 209, 208, 211, 211, 212, + 213, 213, 216, 216, 217, 218, 218, 221, + 220, 222, 223, 223, 226, 225, 226, 229, + 228, 229, 231, 232, 232, 234, 234, 235, + 237, 238, 237, 240, 241, 240, 243, 243, + 245, 244, 246, 248, 248, 249, 250, 251, + 253, 254, 250, 251, 250, 249, 247, 247, + 246, 244, 245, 242, 241, 242, 239, 240, + 237, 237, 236, 235, 234, 233, 232, 230, + 231, 229, 229, 226, 226, 225, 225, 223, + 222, 221, 221, 218, 219, 218, 215, 216, + 215, 212, 214, 210, 211, 210, 208, 207, + 207, 206, 204, 203, 204, 201, 200, 200, + 199, 198, 196, 196, 195, 194, 192, 193, + 190, 190, 189, 187, 188, 186, 184, 185, + 183, 181, 182, 180, 179, 178, 177, 176, + 175, 175, 173, 172, 171, 171, 169, 168, + 167, 167, 165, 165, 163, 162, 162, 161, + 158, 160, 157, 156, 156, 155, 153, 153, + 151, 152, 148, 150, 147, 147, 146, 145, + 143, 144, 141, 141, 140, 138, 139, 137, + 136, 134, 135, 133, 131, 132, 130, 129, + 129, 126, 126, 126, 124, 123, 123, 120, + 121, 120, 117, 118, 117, 115, 114, 113, + 114, 110, 111, 110, 108, 108, 106, 106, + 104, 104, 103, 102, 100, 100, 98, 99, + 96, 96, 95, 93, 94, 91, 91, 91, + 88, 88, 87, 86, 85, 84, 83, 82, + 82, 79, 80, 78, 77, 76, 75, 75, + 73, 72, 72, 69, 71, 67, 68, 66, + 66, 64, 64, 62, 62, 60, 59, 60, + 57, 56, 56, 55, 53, 53, 52, 51, + 49, 49, 48, 46, 47, 44, 44, 43, + 42, 41, 40, 38, 39, 37, 36, 35, + 34, 33, 32, 31, 30, 30, 28, 27, + 26, 25, 25, 23, 22, 22, 20, 19, + 19, 17, 17, 15, 14, 14, 13, 11, + 10, 11, 7, 9, 6, 5, 6, 3, + 2, +}; + +const uint8_t wav_res_bandlimited_triangle_2[] = { + 2, 2, 4, 4, 6, 7, 7, 8, + 10, 11, 11, 12, 14, 14, 15, 17, + 18, 17, 20, 20, 22, 22, 23, 24, + 26, 25, 28, 28, 30, 29, 32, 31, + 34, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 44, 47, 47, 47, + 49, 50, 51, 52, 53, 53, 55, 56, + 56, 58, 59, 60, 60, 62, 62, 64, + 65, 65, 67, 68, 67, 71, 70, 71, + 73, 74, 73, 77, 75, 78, 79, 78, + 81, 82, 82, 83, 84, 86, 85, 88, + 89, 88, 91, 91, 92, 93, 94, 96, + 95, 98, 97, 100, 99, 102, 102, 102, + 105, 105, 105, 108, 107, 109, 110, 111, + 112, 113, 113, 115, 116, 117, 118, 118, + 120, 120, 123, 122, 123, 126, 124, 128, + 127, 129, 129, 131, 131, 133, 133, 135, + 135, 137, 137, 138, 140, 140, 142, 142, + 143, 145, 145, 146, 148, 148, 149, 150, + 151, 153, 153, 154, 155, 156, 157, 159, + 158, 161, 161, 161, 164, 164, 165, 165, + 168, 168, 168, 170, 172, 171, 173, 174, + 175, 175, 178, 177, 179, 179, 182, 181, + 182, 185, 184, 186, 186, 188, 189, 189, + 191, 192, 192, 193, 195, 196, 196, 197, + 199, 200, 199, 203, 201, 204, 204, 206, + 206, 207, 209, 209, 210, 211, 213, 213, + 214, 215, 216, 218, 217, 220, 220, 221, + 222, 223, 224, 225, 226, 228, 227, 229, + 230, 231, 232, 233, 233, 236, 235, 237, + 239, 237, 241, 240, 243, 242, 243, 246, + 245, 246, 249, 248, 250, 250, 252, 252, + 255, 253, 252, 251, 251, 249, 248, 247, + 247, 245, 245, 242, 243, 242, 240, 239, + 239, 237, 236, 236, 235, 233, 232, 232, + 230, 230, 229, 227, 227, 225, 225, 223, + 223, 222, 220, 220, 219, 217, 218, 214, + 216, 213, 213, 212, 211, 209, 209, 208, + 207, 206, 204, 205, 202, 203, 200, 200, + 199, 198, 197, 196, 195, 194, 193, 192, + 191, 190, 189, 188, 188, 185, 186, 184, + 183, 182, 181, 181, 179, 178, 177, 176, + 176, 174, 173, 173, 171, 170, 169, 169, + 168, 165, 166, 165, 163, 162, 162, 160, + 160, 158, 158, 156, 156, 154, 154, 152, + 152, 151, 149, 149, 147, 148, 144, 146, + 143, 143, 141, 142, 139, 139, 137, 138, + 135, 135, 133, 134, 132, 130, 130, 129, + 128, 127, 126, 125, 123, 124, 122, 121, + 119, 120, 118, 117, 115, 116, 114, 113, + 113, 110, 111, 108, 109, 107, 106, 106, + 103, 104, 102, 102, 100, 99, 98, 97, + 97, 96, 93, 94, 92, 92, 90, 90, + 88, 87, 87, 86, 84, 83, 83, 81, + 81, 80, 78, 78, 76, 76, 74, 74, + 73, 72, 70, 69, 70, 67, 67, 66, + 64, 64, 63, 62, 61, 59, 59, 59, + 56, 55, 56, 54, 52, 53, 50, 50, + 50, 47, 47, 47, 44, 44, 44, 41, + 42, 39, 40, 38, 37, 36, 35, 35, + 32, 33, 31, 30, 30, 27, 28, 27, + 24, 25, 23, 23, 20, 22, 18, 19, + 17, 17, 15, 15, 13, 12, 12, 11, + 8, 10, 7, 6, 6, 5, 3, 3, + 1, +}; + +const uint8_t wav_res_bandlimited_triangle_3[] = { + 2, 1, 3, 4, 4, 6, 7, 8, + 9, 10, 10, 12, 13, 13, 15, 16, + 17, 18, 18, 19, 22, 21, 22, 25, + 24, 25, 27, 28, 29, 29, 30, 32, + 33, 33, 35, 36, 35, 39, 38, 39, + 41, 41, 43, 43, 45, 45, 47, 47, + 48, 50, 50, 52, 52, 53, 55, 55, + 57, 56, 60, 58, 61, 61, 62, 63, + 65, 65, 67, 66, 69, 69, 70, 72, + 72, 72, 75, 76, 75, 77, 79, 79, + 80, 81, 82, 83, 84, 86, 85, 88, + 87, 90, 89, 92, 92, 92, 95, 95, + 95, 98, 97, 100, 99, 101, 103, 102, + 104, 105, 106, 107, 107, 110, 109, 111, + 112, 113, 114, 114, 116, 117, 118, 118, + 121, 120, 122, 122, 124, 125, 126, 126, + 128, 129, 129, 131, 132, 132, 134, 135, + 135, 137, 137, 139, 139, 141, 142, 142, + 144, 144, 146, 146, 148, 148, 150, 150, + 152, 152, 154, 154, 155, 157, 157, 159, + 159, 160, 162, 162, 164, 164, 165, 167, + 167, 168, 169, 171, 171, 172, 174, 174, + 175, 176, 178, 178, 179, 180, 181, 183, + 182, 185, 185, 187, 186, 188, 190, 190, + 190, 193, 193, 194, 195, 196, 198, 197, + 199, 200, 202, 201, 203, 204, 205, 207, + 206, 208, 209, 210, 211, 211, 214, 214, + 214, 216, 217, 218, 219, 220, 220, 223, + 222, 224, 224, 227, 226, 228, 229, 230, + 230, 232, 232, 235, 234, 236, 236, 238, + 239, 240, 240, 241, 243, 244, 245, 245, + 247, 248, 247, 250, 251, 252, 253, 252, + 255, 254, 253, 252, 251, 249, 249, 248, + 247, 245, 245, 245, 242, 242, 241, 240, + 238, 239, 236, 237, 234, 234, 234, 231, + 231, 230, 229, 228, 227, 226, 225, 224, + 223, 222, 221, 220, 220, 217, 217, 217, + 214, 215, 213, 211, 212, 211, 208, 208, + 208, 205, 206, 204, 203, 203, 201, 199, + 200, 199, 196, 197, 195, 194, 194, 192, + 191, 190, 190, 188, 187, 187, 185, 184, + 184, 182, 181, 181, 179, 179, 177, 176, + 176, 174, 174, 172, 171, 171, 170, 168, + 167, 167, 165, 165, 163, 163, 162, 160, + 159, 159, 158, 156, 156, 154, 154, 153, + 151, 151, 149, 150, 146, 148, 145, 144, + 145, 142, 142, 140, 140, 139, 138, 136, + 136, 135, 133, 134, 131, 131, 130, 128, + 128, 128, 125, 124, 125, 122, 123, 120, + 120, 119, 118, 117, 115, 116, 113, 114, + 111, 111, 110, 110, 107, 107, 106, 105, + 104, 104, 101, 101, 100, 100, 97, 97, + 97, 94, 95, 93, 91, 92, 90, 90, + 87, 87, 87, 85, 84, 83, 82, 82, + 79, 80, 78, 78, 75, 76, 74, 73, + 73, 71, 70, 69, 69, 67, 66, 66, + 64, 63, 63, 61, 60, 60, 58, 58, + 56, 55, 55, 53, 53, 51, 50, 50, + 48, 48, 46, 46, 45, 42, 44, 41, + 40, 40, 38, 38, 37, 35, 35, 33, + 33, 31, 31, 30, 28, 28, 27, 25, + 25, 24, 22, 22, 20, 21, 18, 17, + 18, 15, 15, 14, 12, 12, 11, 10, + 8, 9, 6, 6, 5, 3, 3, 2, + 2, +}; + +const uint8_t wav_res_bandlimited_triangle_4[] = { + 2, 1, 2, 2, 4, 4, 4, 7, + 6, 8, 10, 11, 11, 13, 14, 15, + 16, 17, 17, 19, 20, 21, 21, 22, + 24, 24, 25, 27, 27, 29, 29, 31, + 32, 33, 33, 35, 36, 36, 39, 38, + 39, 41, 42, 42, 44, 44, 45, 47, + 48, 48, 50, 51, 51, 53, 54, 54, + 56, 57, 58, 58, 60, 60, 63, 61, + 64, 65, 65, 67, 67, 69, 70, 70, + 72, 73, 74, 74, 76, 77, 78, 78, + 80, 80, 82, 83, 83, 85, 85, 87, + 88, 88, 90, 91, 91, 93, 94, 95, + 96, 96, 98, 98, 101, 99, 103, 102, + 104, 104, 106, 107, 107, 109, 110, 110, + 113, 112, 114, 114, 117, 116, 118, 118, + 120, 121, 122, 122, 123, 126, 125, 127, + 127, 129, 130, 131, 132, 132, 135, 134, + 135, 138, 137, 139, 140, 140, 142, 143, + 143, 145, 146, 146, 148, 149, 150, 150, + 153, 152, 154, 155, 156, 156, 158, 159, + 160, 160, 162, 163, 163, 165, 166, 166, + 169, 168, 170, 171, 171, 174, 173, 176, + 175, 176, 179, 178, 180, 181, 182, 182, + 184, 184, 186, 188, 187, 188, 191, 191, + 191, 194, 193, 195, 196, 197, 197, 200, + 199, 200, 203, 202, 204, 204, 206, 208, + 207, 209, 210, 210, 213, 213, 214, 215, + 215, 217, 218, 219, 219, 221, 222, 222, + 225, 223, 227, 227, 227, 230, 230, 231, + 232, 233, 234, 234, 237, 236, 238, 239, + 239, 240, 242, 243, 243, 246, 245, 248, + 248, 249, 251, 252, 252, 253, 253, 255, + 253, 254, 254, 253, 252, 252, 251, 249, + 249, 247, 246, 245, 244, 243, 242, 240, + 239, 240, 236, 238, 236, 235, 233, 234, + 232, 231, 231, 228, 229, 227, 225, 225, + 225, 222, 221, 222, 219, 219, 218, 217, + 215, 216, 214, 212, 213, 211, 210, 209, + 207, 208, 206, 204, 204, 203, 202, 201, + 199, 199, 198, 197, 196, 194, 195, 193, + 191, 192, 189, 190, 187, 188, 185, 185, + 183, 184, 181, 181, 180, 178, 179, 176, + 176, 175, 174, 173, 172, 171, 169, 170, + 167, 168, 165, 164, 165, 162, 162, 161, + 160, 158, 158, 157, 156, 155, 153, 154, + 151, 151, 151, 147, 149, 147, 145, 145, + 144, 142, 143, 140, 139, 140, 137, 137, + 136, 135, 133, 134, 131, 131, 130, 129, + 127, 127, 126, 125, 123, 123, 122, 120, + 121, 118, 117, 118, 115, 115, 114, 112, + 113, 110, 110, 109, 108, 106, 106, 105, + 103, 103, 101, 102, 99, 98, 99, 96, + 96, 94, 95, 92, 92, 91, 90, 88, + 88, 87, 85, 85, 84, 82, 82, 80, + 80, 79, 77, 78, 75, 74, 75, 72, + 72, 71, 70, 68, 68, 66, 66, 65, + 63, 62, 63, 60, 59, 59, 58, 57, + 55, 55, 54, 53, 52, 50, 49, 50, + 47, 46, 46, 45, 43, 43, 41, 40, + 40, 39, 38, 36, 37, 34, 33, 34, + 31, 31, 30, 28, 27, 27, 26, 23, + 24, 23, 21, 20, 20, 19, 18, 17, + 15, 16, 13, 13, 12, 11, 9, 8, + 7, 6, 5, 4, 3, 2, 2, 2, + 2, +}; + +const uint8_t wav_res_bandlimited_triangle_5[] = { + 2, 1, 1, 3, 2, 2, 3, 4, + 3, 6, 4, 7, 7, 8, 8, 10, + 11, 12, 13, 13, 16, 17, 17, 18, + 21, 21, 22, 24, 24, 27, 27, 28, + 30, 30, 33, 32, 35, 34, 37, 37, + 38, 40, 40, 42, 41, 44, 44, 46, + 45, 47, 48, 49, 50, 50, 52, 53, + 53, 54, 56, 56, 58, 57, 60, 60, + 62, 62, 63, 64, 66, 66, 68, 69, + 69, 71, 72, 74, 73, 76, 76, 77, + 79, 80, 80, 82, 84, 83, 85, 87, + 86, 89, 90, 89, 92, 92, 93, 95, + 95, 96, 98, 97, 100, 100, 101, 102, + 103, 104, 105, 106, 106, 109, 108, 110, + 111, 112, 113, 113, 115, 117, 116, 118, + 119, 121, 121, 122, 123, 125, 125, 127, + 128, 128, 131, 130, 133, 133, 134, 135, + 137, 137, 139, 139, 141, 142, 142, 143, + 146, 145, 147, 147, 149, 150, 150, 151, + 153, 154, 154, 155, 157, 156, 160, 158, + 160, 162, 162, 163, 164, 166, 165, 168, + 168, 170, 169, 173, 171, 175, 174, 176, + 177, 178, 179, 180, 181, 183, 183, 186, + 184, 188, 187, 190, 189, 192, 192, 192, + 196, 194, 196, 198, 198, 199, 200, 202, + 201, 203, 204, 205, 206, 206, 208, 208, + 210, 210, 211, 213, 213, 213, 217, 215, + 217, 219, 219, 220, 221, 223, 224, 224, + 227, 226, 229, 229, 230, 233, 233, 234, + 235, 237, 238, 240, 239, 242, 242, 245, + 243, 247, 246, 248, 248, 250, 249, 252, + 251, 252, 253, 252, 254, 254, 253, 254, + 254, 254, 254, 254, 253, 253, 253, 251, + 252, 251, 251, 248, 249, 248, 246, 246, + 245, 244, 242, 242, 240, 239, 238, 237, + 235, 235, 232, 233, 231, 228, 230, 226, + 226, 225, 224, 222, 221, 221, 220, 217, + 218, 216, 215, 214, 213, 213, 211, 210, + 210, 208, 208, 207, 205, 206, 203, 203, + 202, 201, 200, 200, 198, 197, 196, 195, + 195, 193, 192, 191, 191, 188, 188, 187, + 186, 185, 183, 182, 182, 180, 179, 179, + 176, 176, 174, 175, 172, 171, 171, 169, + 169, 166, 167, 165, 165, 162, 163, 161, + 160, 160, 157, 158, 157, 155, 154, 153, + 153, 152, 150, 150, 148, 149, 145, 147, + 144, 144, 142, 142, 141, 139, 139, 137, + 137, 135, 134, 134, 131, 132, 130, 128, + 128, 127, 126, 124, 123, 123, 120, 122, + 118, 118, 117, 116, 115, 114, 113, 111, + 112, 109, 109, 108, 107, 105, 106, 104, + 102, 103, 101, 100, 99, 98, 98, 95, + 97, 93, 94, 92, 91, 91, 89, 88, + 87, 87, 85, 83, 84, 81, 82, 79, + 78, 78, 77, 74, 75, 73, 72, 71, + 69, 70, 66, 68, 64, 65, 64, 62, + 61, 60, 60, 57, 58, 57, 55, 54, + 54, 52, 52, 50, 51, 48, 48, 47, + 46, 45, 45, 42, 43, 42, 39, 40, + 38, 38, 36, 35, 34, 33, 32, 30, + 30, 29, 27, 26, 24, 25, 21, 22, + 20, 18, 19, 15, 16, 13, 14, 12, + 10, 10, 9, 8, 6, 7, 5, 5, + 4, 3, 4, 1, 3, 2, 1, 2, + 2, +}; + +const uint8_t wav_res_bandlimited_triangle_6[] = { + 1, 2, 2, 1, 2, 1, 3, 1, + 2, 3, 2, 3, 2, 4, 3, 4, + 3, 5, 4, 6, 4, 6, 7, 5, + 8, 7, 8, 8, 9, 10, 10, 10, + 11, 12, 12, 13, 14, 14, 15, 15, + 17, 18, 17, 18, 21, 19, 22, 21, + 23, 24, 25, 25, 26, 27, 29, 29, + 30, 31, 32, 34, 33, 36, 36, 38, + 38, 40, 40, 42, 43, 44, 46, 46, + 47, 50, 49, 52, 52, 55, 54, 56, + 58, 59, 61, 60, 64, 64, 65, 67, + 68, 70, 71, 72, 74, 76, 76, 77, + 81, 80, 82, 84, 86, 86, 88, 90, + 91, 92, 95, 95, 97, 99, 100, 101, + 104, 104, 106, 109, 108, 111, 112, 114, + 116, 116, 119, 120, 122, 122, 125, 127, + 127, 130, 130, 132, 135, 135, 137, 139, + 140, 142, 142, 146, 145, 149, 149, 151, + 152, 154, 155, 157, 159, 160, 161, 163, + 164, 166, 168, 168, 171, 172, 172, 175, + 177, 177, 178, 181, 182, 183, 184, 187, + 186, 189, 191, 190, 193, 194, 196, 196, + 197, 201, 199, 202, 203, 205, 205, 206, + 208, 209, 211, 211, 212, 214, 215, 216, + 217, 218, 219, 220, 222, 222, 223, 225, + 225, 226, 228, 228, 229, 230, 231, 232, + 232, 234, 235, 235, 236, 236, 239, 237, + 240, 240, 240, 241, 242, 243, 243, 243, + 245, 245, 246, 246, 246, 247, 248, 248, + 249, 249, 249, 250, 250, 251, 250, 252, + 252, 251, 253, 252, 252, 254, 252, 254, + 253, 254, 253, 254, 254, 254, 253, 255, + 254, 254, 253, 255, 253, 255, 252, 255, + 253, 253, 253, 253, 252, 253, 252, 252, + 252, 251, 251, 250, 250, 251, 249, 248, + 250, 247, 248, 248, 245, 247, 246, 244, + 245, 244, 243, 242, 242, 242, 240, 239, + 240, 238, 238, 237, 236, 234, 236, 233, + 232, 233, 230, 231, 228, 229, 227, 227, + 225, 224, 223, 223, 221, 221, 218, 219, + 217, 215, 216, 213, 212, 212, 211, 208, + 208, 207, 205, 204, 204, 201, 200, 200, + 197, 197, 196, 193, 193, 191, 191, 188, + 187, 186, 185, 182, 183, 180, 178, 178, + 177, 174, 173, 171, 172, 167, 169, 165, + 164, 164, 161, 159, 159, 158, 154, 155, + 151, 152, 149, 148, 146, 145, 142, 143, + 140, 138, 138, 134, 135, 133, 130, 129, + 128, 126, 125, 123, 122, 119, 119, 117, + 116, 113, 112, 112, 108, 108, 106, 105, + 103, 102, 100, 98, 97, 96, 94, 93, + 90, 91, 87, 87, 86, 83, 82, 81, + 80, 78, 76, 75, 75, 71, 72, 69, + 68, 68, 64, 65, 63, 61, 61, 58, + 58, 57, 54, 54, 53, 51, 50, 49, + 47, 47, 46, 43, 43, 43, 39, 41, + 38, 37, 37, 35, 34, 33, 32, 32, + 29, 30, 28, 28, 25, 26, 25, 23, + 23, 22, 21, 20, 20, 19, 17, 17, + 17, 16, 14, 15, 13, 14, 11, 13, + 10, 11, 10, 9, 9, 9, 7, 8, + 7, 6, 7, 5, 5, 5, 5, 4, + 3, 5, 3, 3, 2, 4, 2, 2, + 2, 2, 2, 2, 2, 0, 3, 1, + 1, +}; + +const uint8_t wav_res_bandlimited_nes_triangle_0[] = { + 2, 2, 2, 2, 1, 2, 2, 0, + 3, 1, 1, 2, 2, 2, 1, 3, + 15, 15, 15, 16, 16, 16, 16, 16, + 18, 16, 18, 17, 18, 18, 18, 19, + 31, 32, 31, 33, 31, 33, 33, 32, + 33, 34, 32, 34, 34, 34, 33, 34, + 48, 47, 47, 47, 48, 48, 49, 47, + 49, 49, 49, 49, 49, 50, 49, 51, + 62, 64, 63, 64, 63, 64, 65, 64, + 64, 65, 65, 66, 64, 67, 64, 67, + 79, 78, 80, 79, 79, 80, 80, 80, + 80, 81, 80, 81, 81, 81, 82, 81, + 95, 95, 94, 96, 95, 96, 96, 95, + 97, 96, 97, 97, 96, 98, 98, 97, + 110, 111, 111, 111, 111, 112, 111, 112, + 112, 112, 113, 112, 112, 114, 113, 113, + 126, 127, 126, 127, 127, 127, 128, 127, + 129, 127, 128, 129, 129, 129, 128, 130, + 143, 141, 143, 143, 143, 143, 143, 144, + 144, 143, 144, 145, 144, 145, 145, 145, + 157, 159, 158, 158, 159, 159, 159, 159, + 160, 159, 161, 159, 161, 160, 161, 161, + 174, 174, 174, 174, 176, 174, 175, 175, + 176, 176, 175, 176, 177, 176, 176, 177, + 190, 190, 189, 191, 190, 191, 190, 191, + 191, 192, 191, 192, 192, 192, 192, 193, + 205, 206, 206, 206, 207, 206, 207, 206, + 208, 208, 206, 209, 208, 207, 210, 207, + 222, 222, 221, 222, 222, 223, 221, 224, + 222, 223, 223, 223, 224, 224, 223, 225, + 237, 237, 237, 238, 238, 238, 239, 239, + 238, 240, 239, 239, 241, 240, 240, 240, + 254, 254, 253, 253, 255, 254, 253, 255, + 253, 255, 253, 255, 253, 254, 253, 253, + 242, 239, 241, 239, 240, 240, 238, 240, + 238, 239, 238, 238, 238, 237, 238, 236, + 225, 223, 225, 222, 224, 224, 222, 222, + 224, 222, 222, 222, 221, 223, 221, 222, + 208, 208, 209, 207, 208, 208, 208, 206, + 207, 208, 205, 207, 207, 205, 205, 207, + 191, 194, 191, 192, 192, 192, 191, 191, + 190, 192, 190, 191, 189, 191, 189, 190, + 177, 176, 177, 175, 177, 176, 175, 176, + 175, 175, 175, 174, 175, 175, 173, 174, + 161, 161, 161, 159, 161, 160, 159, 160, + 159, 160, 158, 159, 158, 158, 159, 157, + 146, 144, 145, 144, 145, 144, 143, 145, + 142, 145, 142, 143, 143, 143, 142, 142, + 129, 130, 128, 129, 129, 128, 128, 128, + 127, 128, 127, 127, 127, 126, 127, 126, + 114, 112, 114, 112, 113, 112, 112, 112, + 112, 111, 112, 111, 112, 110, 110, 112, + 96, 99, 96, 98, 96, 97, 96, 97, + 95, 97, 95, 95, 96, 94, 95, 95, + 82, 80, 83, 80, 81, 80, 81, 80, + 81, 79, 80, 79, 79, 80, 79, 78, + 66, 66, 66, 65, 65, 65, 64, 66, + 63, 65, 64, 63, 65, 62, 64, 62, + 51, 49, 50, 49, 50, 48, 49, 49, + 48, 48, 47, 49, 47, 48, 46, 48, + 34, 33, 35, 33, 34, 32, 34, 33, + 33, 32, 32, 33, 32, 31, 32, 31, + 19, 19, 17, 18, 17, 18, 17, 16, + 17, 16, 17, 15, 16, 15, 16, 14, + 2, +}; + +const uint8_t wav_res_bandlimited_nes_triangle_1[] = { + 1, 7, 8, 6, 7, 4, 7, 6, + 8, 6, 5, 5, 8, 7, 7, 1, + 27, 20, 21, 21, 22, 21, 22, 21, + 22, 21, 22, 20, 22, 23, 21, 18, + 41, 36, 35, 36, 38, 37, 37, 35, + 37, 37, 37, 36, 36, 39, 36, 33, + 56, 51, 51, 51, 53, 53, 50, 52, + 52, 52, 52, 51, 52, 53, 52, 48, + 71, 67, 65, 67, 68, 68, 65, 68, + 66, 69, 66, 66, 67, 69, 67, 63, + 86, 82, 81, 82, 83, 83, 81, 81, + 84, 82, 82, 82, 81, 84, 83, 78, + 102, 96, 96, 98, 98, 98, 96, 97, + 98, 99, 96, 96, 98, 99, 98, 93, + 117, 111, 112, 113, 113, 112, 113, 111, + 114, 113, 112, 112, 113, 113, 114, 107, + 133, 127, 127, 127, 129, 127, 128, 127, + 129, 128, 127, 127, 128, 129, 128, 124, + 147, 142, 142, 143, 143, 144, 142, 143, + 143, 143, 143, 143, 142, 145, 142, 140, + 162, 158, 156, 159, 158, 159, 158, 156, + 160, 158, 158, 158, 158, 159, 158, 155, + 177, 173, 172, 173, 174, 174, 173, 172, + 174, 174, 173, 173, 173, 174, 175, 168, + 194, 187, 187, 188, 191, 188, 187, 189, + 189, 189, 188, 187, 189, 190, 190, 183, + 208, 204, 201, 205, 204, 204, 202, 204, + 205, 203, 204, 203, 203, 206, 204, 199, + 223, 219, 217, 219, 220, 218, 219, 219, + 219, 219, 219, 218, 218, 222, 218, 215, + 238, 234, 233, 233, 236, 233, 234, 234, + 235, 234, 233, 234, 234, 236, 234, 229, + 254, 250, 247, 249, 249, 251, 249, 249, + 248, 249, 251, 250, 248, 247, 250, 254, + 230, 233, 236, 234, 234, 234, 233, 235, + 234, 234, 234, 235, 233, 234, 233, 238, + 215, 219, 220, 220, 218, 217, 221, 218, + 220, 217, 220, 219, 219, 218, 218, 223, + 199, 205, 205, 203, 203, 204, 204, 204, + 203, 204, 203, 205, 203, 203, 203, 208, + 184, 189, 191, 187, 188, 188, 190, 189, + 187, 188, 189, 190, 188, 187, 188, 193, + 169, 173, 176, 172, 173, 173, 175, 173, + 172, 173, 174, 175, 172, 172, 173, 178, + 154, 158, 159, 159, 157, 158, 159, 158, + 158, 157, 159, 159, 158, 156, 158, 163, + 138, 144, 144, 143, 142, 143, 143, 144, + 142, 142, 144, 143, 144, 140, 144, 146, + 124, 128, 130, 127, 127, 127, 129, 128, + 127, 128, 128, 128, 127, 128, 126, 133, + 107, 114, 114, 112, 112, 112, 114, 112, + 113, 112, 112, 114, 112, 112, 111, 118, + 92, 98, 99, 98, 96, 97, 98, 98, + 97, 97, 97, 99, 97, 96, 96, 103, + 77, 83, 83, 83, 81, 82, 83, 83, + 81, 82, 82, 83, 82, 82, 81, 86, + 63, 67, 70, 66, 66, 66, 69, 67, + 67, 65, 68, 69, 66, 65, 67, 72, + 46, 54, 52, 53, 50, 51, 54, 51, + 52, 51, 52, 53, 52, 50, 51, 56, + 33, 37, 38, 36, 37, 35, 39, 36, + 35, 38, 36, 38, 36, 35, 36, 42, + 17, 21, 24, 20, 22, 21, 22, 21, + 21, 22, 21, 23, 20, 21, 21, 26, + 1, +}; + +const uint8_t wav_res_bandlimited_nes_triangle_2[] = { + 6, 2, 3, 4, 3, 2, 5, 3, + 2, 5, 2, 3, 4, 4, 1, 6, + 16, 21, 18, 19, 19, 18, 20, 18, + 19, 18, 20, 18, 20, 18, 18, 21, + 32, 36, 34, 33, 36, 34, 34, 35, + 34, 34, 35, 34, 35, 34, 34, 36, + 47, 52, 50, 49, 50, 51, 48, 52, + 49, 50, 50, 50, 49, 52, 47, 53, + 63, 67, 65, 66, 65, 66, 65, 66, + 64, 67, 65, 66, 65, 66, 64, 67, + 80, 82, 81, 80, 83, 79, 82, 81, + 81, 81, 82, 80, 81, 82, 79, 84, + 94, 98, 96, 97, 97, 96, 96, 98, + 96, 96, 98, 95, 98, 97, 94, 100, + 109, 114, 112, 112, 112, 113, 111, 113, + 112, 112, 112, 112, 113, 112, 111, 115, + 124, 131, 126, 128, 128, 127, 128, 129, + 126, 129, 127, 128, 128, 128, 126, 130, + 141, 145, 143, 143, 144, 142, 144, 144, + 142, 144, 143, 144, 142, 145, 141, 146, + 157, 160, 158, 159, 159, 159, 158, 160, + 158, 159, 160, 158, 158, 161, 156, 162, + 172, 175, 175, 174, 175, 174, 174, 175, + 174, 174, 176, 173, 174, 176, 173, 176, + 188, 192, 189, 190, 190, 190, 190, 190, + 190, 189, 192, 188, 191, 190, 189, 192, + 203, 208, 204, 206, 205, 206, 206, 205, + 205, 206, 207, 203, 207, 206, 204, 207, + 220, 222, 221, 220, 222, 221, 221, 222, + 220, 221, 222, 220, 222, 221, 220, 223, + 235, 238, 236, 236, 237, 237, 237, 236, + 237, 237, 236, 237, 236, 238, 235, 239, + 249, 255, 251, 252, 253, 252, 252, 252, + 253, 251, 253, 253, 251, 252, 254, 250, + 238, 236, 237, 237, 236, 237, 237, 236, + 238, 235, 237, 238, 235, 237, 238, 234, + 224, 219, 222, 222, 219, 223, 220, 221, + 222, 221, 220, 222, 221, 221, 222, 219, + 207, 205, 206, 206, 204, 207, 205, 205, + 206, 206, 205, 206, 205, 205, 208, 202, + 193, 188, 191, 190, 189, 191, 190, 189, + 191, 190, 189, 191, 190, 189, 191, 188, + 177, 173, 175, 174, 175, 174, 174, 175, + 174, 175, 174, 175, 174, 173, 177, 172, + 161, 158, 158, 160, 158, 160, 158, 159, + 159, 159, 158, 160, 158, 159, 160, 157, + 145, 142, 144, 143, 143, 144, 143, 143, + 144, 143, 143, 143, 144, 143, 144, 141, + 131, 126, 127, 129, 127, 129, 127, 127, + 128, 128, 128, 128, 127, 127, 130, 125, + 115, 110, 113, 113, 111, 112, 113, 112, + 112, 112, 113, 111, 113, 112, 113, 110, + 99, 95, 97, 97, 96, 97, 97, 96, + 97, 96, 97, 97, 96, 97, 97, 95, + 83, 80, 81, 82, 80, 82, 80, 82, + 80, 82, 81, 81, 81, 80, 83, 79, + 68, 63, 67, 65, 65, 66, 66, 65, + 65, 66, 65, 67, 64, 66, 66, 64, + 52, 48, 51, 50, 49, 51, 50, 49, + 50, 51, 49, 50, 50, 50, 51, 48, + 36, 33, 35, 35, 33, 36, 33, 35, + 35, 33, 35, 35, 34, 33, 37, 31, + 22, 17, 20, 18, 19, 19, 18, 20, + 18, 19, 19, 19, 18, 19, 20, 17, + 5, +}; + +const uint8_t wav_res_bandlimited_nes_triangle_3[] = { + 13, 8, 3, 3, 0, 4, 7, 7, + 8, 7, 3, 1, 2, 3, 9, 13, + 16, 19, 19, 20, 20, 19, 21, 23, + 21, 21, 19, 18, 18, 20, 22, 28, + 32, 33, 35, 36, 35, 35, 37, 36, + 38, 35, 35, 34, 33, 35, 39, 42, + 46, 49, 51, 51, 51, 51, 52, 51, + 52, 51, 51, 49, 49, 50, 54, 58, + 61, 64, 66, 67, 67, 66, 66, 68, + 67, 66, 66, 64, 65, 66, 70, 71, + 78, 79, 81, 82, 83, 81, 83, 82, + 81, 83, 81, 79, 81, 82, 84, 87, + 93, 94, 97, 97, 98, 98, 97, 97, + 98, 97, 96, 95, 97, 96, 100, 103, + 107, 110, 112, 114, 112, 113, 113, 113, + 112, 112, 112, 112, 110, 113, 115, 118, + 122, 125, 128, 129, 128, 129, 128, 127, + 128, 127, 128, 127, 126, 128, 130, 134, + 136, 142, 142, 145, 144, 144, 142, 144, + 143, 142, 143, 142, 143, 143, 145, 149, + 152, 156, 158, 161, 159, 159, 158, 159, + 158, 158, 158, 157, 159, 158, 161, 163, + 168, 172, 173, 175, 176, 174, 174, 173, + 174, 173, 173, 174, 173, 174, 176, 179, + 183, 186, 189, 192, 190, 190, 189, 188, + 189, 189, 188, 189, 190, 188, 192, 194, + 198, 201, 206, 205, 207, 206, 203, 205, + 202, 205, 204, 205, 204, 205, 206, 209, + 214, 217, 219, 223, 222, 220, 220, 219, + 218, 219, 221, 219, 221, 219, 223, 224, + 227, 233, 236, 237, 238, 237, 234, 233, + 234, 235, 235, 235, 237, 236, 237, 238, + 243, 247, 252, 254, 254, 252, 249, 248, + 247, 249, 252, 255, 253, 252, 247, 243, + 239, 236, 237, 235, 237, 234, 236, 232, + 235, 233, 238, 236, 239, 235, 233, 227, + 225, 221, 221, 220, 220, 220, 219, 219, + 218, 220, 220, 223, 221, 221, 216, 214, + 209, 207, 204, 205, 204, 204, 205, 203, + 203, 205, 205, 207, 206, 204, 203, 197, + 195, 190, 190, 189, 189, 189, 188, 189, + 188, 189, 191, 190, 190, 190, 187, 182, + 179, 177, 173, 173, 174, 173, 174, 173, + 174, 173, 174, 176, 175, 174, 171, 167, + 165, 160, 159, 157, 159, 157, 159, 157, + 159, 158, 159, 160, 160, 158, 156, 153, + 148, 145, 144, 142, 142, 143, 143, 142, + 144, 142, 145, 143, 145, 143, 140, 138, + 133, 130, 128, 127, 126, 128, 127, 128, + 128, 128, 127, 130, 128, 128, 125, 123, + 117, 115, 113, 111, 111, 112, 112, 113, + 112, 113, 113, 113, 113, 112, 111, 106, + 103, 100, 97, 95, 96, 97, 97, 97, + 97, 97, 98, 98, 97, 97, 96, 90, + 89, 83, 82, 81, 80, 80, 83, 81, + 83, 82, 81, 83, 82, 81, 80, 77, + 72, 69, 66, 65, 64, 66, 67, 66, + 68, 66, 67, 66, 67, 66, 65, 60, + 58, 54, 50, 50, 49, 50, 51, 52, + 51, 53, 50, 51, 52, 49, 50, 47, + 41, 39, 35, 34, 33, 35, 36, 37, + 36, 37, 35, 36, 35, 35, 34, 31, + 28, 23, 19, 18, 18, 19, 21, 22, + 22, 21, 20, 19, 20, 19, 19, 17, + 12, +}; + +const uint8_t wav_res_bandlimited_nes_triangle_4[] = { + 9, 8, 5, 5, 3, 3, 2, 1, + 2, 1, 3, 3, 5, 6, 7, 9, + 11, 12, 14, 14, 17, 17, 18, 20, + 18, 21, 21, 21, 23, 22, 24, 24, + 26, 27, 28, 28, 31, 32, 32, 34, + 36, 35, 37, 39, 38, 40, 40, 41, + 42, 43, 43, 45, 45, 47, 47, 49, + 50, 51, 53, 53, 54, 56, 56, 57, + 58, 60, 59, 61, 61, 63, 63, 64, + 66, 65, 68, 69, 69, 70, 73, 72, + 74, 75, 75, 78, 77, 78, 80, 80, + 81, 83, 82, 83, 86, 85, 88, 87, + 90, 90, 91, 92, 94, 94, 96, 95, + 98, 98, 99, 99, 102, 100, 103, 104, + 104, 105, 107, 108, 108, 110, 111, 111, + 114, 114, 114, 116, 117, 117, 119, 119, + 120, 122, 121, 123, 125, 124, 126, 128, + 128, 129, 131, 131, 133, 133, 134, 136, + 136, 137, 138, 139, 139, 141, 142, 142, + 144, 144, 146, 147, 147, 150, 149, 152, + 152, 152, 155, 154, 157, 155, 159, 157, + 160, 160, 161, 162, 163, 164, 166, 166, + 167, 169, 170, 170, 172, 172, 174, 174, + 176, 176, 176, 179, 178, 180, 180, 183, + 181, 185, 184, 186, 187, 188, 190, 190, + 191, 192, 194, 193, 195, 196, 196, 198, + 198, 199, 200, 201, 202, 203, 205, 205, + 207, 207, 210, 210, 210, 213, 212, 214, + 214, 215, 217, 216, 217, 219, 219, 221, + 221, 223, 224, 225, 226, 228, 229, 229, + 232, 231, 233, 233, 234, 235, 235, 236, + 237, 237, 238, 239, 241, 241, 244, 245, + 246, 249, 248, 252, 252, 252, 255, 253, + 254, 254, 253, 252, 251, 250, 248, 245, + 246, 243, 242, 241, 238, 239, 237, 237, + 236, 235, 234, 235, 232, 234, 231, 231, + 230, 229, 228, 225, 226, 224, 223, 221, + 220, 220, 218, 218, 216, 217, 214, 215, + 213, 214, 211, 211, 210, 209, 208, 206, + 206, 205, 202, 203, 201, 200, 199, 198, + 197, 197, 196, 194, 194, 194, 191, 192, + 190, 190, 187, 188, 185, 186, 183, 182, + 183, 180, 179, 179, 178, 177, 177, 174, + 175, 173, 173, 172, 170, 169, 170, 167, + 166, 165, 165, 162, 163, 161, 160, 159, + 158, 158, 157, 155, 155, 154, 153, 152, + 152, 149, 149, 148, 146, 147, 144, 143, + 143, 142, 140, 140, 139, 138, 137, 136, + 135, 135, 133, 132, 132, 131, 129, 128, + 127, 126, 126, 123, 123, 123, 120, 121, + 119, 118, 118, 117, 115, 115, 114, 113, + 112, 111, 109, 110, 106, 108, 104, 106, + 102, 103, 102, 100, 100, 99, 98, 97, + 96, 96, 93, 95, 91, 92, 90, 90, + 87, 87, 86, 85, 84, 83, 81, 82, + 80, 79, 78, 79, 76, 76, 74, 75, + 72, 72, 71, 70, 67, 68, 67, 64, + 65, 63, 62, 62, 60, 61, 58, 58, + 58, 56, 56, 54, 53, 52, 52, 49, + 50, 47, 46, 46, 45, 43, 43, 41, + 42, 40, 39, 40, 37, 37, 37, 34, + 34, 34, 30, 31, 30, 27, 26, 27, + 23, 25, 22, 23, 21, 20, 21, 20, + 18, 19, 17, 16, 15, 14, 12, 10, + 10, +}; + +const uint8_t wav_res_bandlimited_nes_triangle_5[] = { + 4, 3, 3, 2, 2, 1, 3, 1, + 1, 2, 1, 3, 2, 3, 2, 5, + 4, 5, 7, 5, 9, 8, 10, 10, + 12, 13, 13, 16, 17, 16, 20, 20, + 21, 22, 24, 25, 27, 26, 30, 29, + 31, 33, 32, 35, 36, 36, 37, 39, + 40, 40, 42, 43, 43, 44, 45, 47, + 47, 48, 49, 49, 52, 51, 52, 54, + 54, 56, 55, 58, 58, 59, 60, 61, + 63, 62, 64, 66, 66, 68, 67, 71, + 70, 71, 74, 73, 76, 75, 78, 79, + 79, 80, 82, 83, 84, 85, 86, 86, + 89, 89, 91, 90, 92, 94, 94, 95, + 95, 98, 98, 99, 99, 102, 101, 103, + 103, 105, 106, 106, 107, 109, 109, 110, + 112, 112, 114, 114, 115, 117, 117, 119, + 119, 121, 122, 122, 125, 124, 127, 126, + 129, 130, 130, 131, 133, 134, 135, 135, + 138, 138, 138, 141, 141, 142, 143, 144, + 145, 147, 146, 149, 149, 149, 152, 151, + 153, 154, 155, 155, 157, 157, 159, 160, + 159, 162, 163, 162, 165, 166, 166, 167, + 168, 170, 171, 171, 173, 174, 175, 175, + 178, 178, 179, 180, 182, 183, 184, 184, + 186, 188, 187, 190, 190, 191, 193, 193, + 195, 195, 196, 198, 198, 199, 200, 202, + 202, 202, 205, 204, 206, 207, 207, 208, + 210, 210, 211, 212, 213, 214, 215, 215, + 218, 217, 220, 219, 222, 222, 223, 224, + 227, 226, 228, 229, 231, 232, 233, 234, + 235, 237, 238, 239, 241, 240, 244, 244, + 244, 246, 247, 248, 249, 249, 250, 252, + 251, 253, 252, 254, 253, 254, 253, 255, + 254, 253, 255, 253, 253, 252, 253, 252, + 251, 250, 250, 248, 249, 246, 246, 245, + 244, 242, 242, 240, 240, 237, 237, 235, + 235, 233, 231, 231, 229, 228, 228, 224, + 226, 222, 223, 221, 220, 219, 218, 216, + 217, 214, 215, 212, 213, 210, 211, 209, + 208, 208, 206, 206, 205, 204, 202, 203, + 201, 200, 199, 199, 197, 197, 194, 196, + 192, 193, 192, 189, 190, 188, 187, 186, + 185, 184, 182, 182, 180, 180, 177, 178, + 176, 175, 173, 173, 172, 170, 170, 168, + 168, 166, 165, 165, 163, 162, 162, 160, + 159, 159, 158, 156, 156, 154, 154, 153, + 152, 151, 150, 148, 149, 147, 146, 145, + 145, 142, 143, 140, 141, 139, 138, 137, + 135, 136, 133, 133, 131, 131, 130, 127, + 128, 126, 125, 124, 122, 123, 120, 120, + 118, 117, 118, 114, 115, 113, 113, 110, + 112, 108, 109, 108, 106, 105, 105, 103, + 104, 101, 100, 101, 99, 97, 98, 95, + 96, 94, 93, 92, 91, 90, 90, 87, + 88, 85, 86, 83, 83, 82, 81, 79, + 78, 78, 76, 75, 74, 72, 73, 70, + 69, 69, 68, 65, 66, 64, 63, 63, + 60, 60, 60, 57, 58, 56, 55, 55, + 53, 52, 52, 51, 49, 50, 47, 48, + 46, 45, 44, 44, 43, 41, 40, 41, + 38, 37, 37, 35, 35, 33, 32, 31, + 30, 29, 27, 26, 25, 24, 23, 21, + 19, 20, 17, 16, 16, 14, 12, 12, + 11, 9, 9, 8, 6, 6, 5, 5, + 3, +}; + +const uint8_t* const waveform_table[] = { + wav_res_bandlimited_triangle_0, + wav_res_bandlimited_triangle_1, + wav_res_bandlimited_triangle_2, + wav_res_bandlimited_triangle_3, + wav_res_bandlimited_triangle_4, + wav_res_bandlimited_triangle_5, + wav_res_bandlimited_triangle_6, + wav_res_bandlimited_triangle_6, + wav_res_bandlimited_nes_triangle_0, + wav_res_bandlimited_nes_triangle_1, + wav_res_bandlimited_nes_triangle_2, + wav_res_bandlimited_nes_triangle_3, + wav_res_bandlimited_nes_triangle_4, + wav_res_bandlimited_nes_triangle_5, + wav_res_bandlimited_triangle_6, + wav_res_bandlimited_triangle_6, +}; + +#endif // WAVETABLES_HPP diff --git a/src/plugin.cpp b/src/plugin.cpp index 5ff10c2..c0d5372 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -24,4 +24,5 @@ void init(rack::Plugin* p) { p->addModel(modelMarbles); p->addModel(modelStages); p->addModel(modelRipples); + p->addModel(modelEdges); } diff --git a/src/plugin.hpp b/src/plugin.hpp index 4608766..16bcc5a 100644 --- a/src/plugin.hpp +++ b/src/plugin.hpp @@ -24,3 +24,4 @@ extern Model* modelFrames; extern Model* modelStages; extern Model* modelMarbles; extern Model* modelRipples; +extern Model *modelEdges;