From a86828d58e636cddbb878e105432abb85f2594de Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Wed, 11 Sep 2019 13:04:29 +0200 Subject: [PATCH] Small fixes. Boundary checks for setting parameters added. --- MicroMDAEPiano.ino | 11 +- UI.hpp | 84 +++++++- synth_waveform_extended.cpp | 403 ------------------------------------ synth_waveform_extended.h | 221 -------------------- 4 files changed, 86 insertions(+), 633 deletions(-) delete mode 100644 synth_waveform_extended.cpp delete mode 100644 synth_waveform_extended.h diff --git a/MicroMDAEPiano.ino b/MicroMDAEPiano.ino index 644ef11..7b9ccef 100644 --- a/MicroMDAEPiano.ino +++ b/MicroMDAEPiano.ino @@ -37,7 +37,6 @@ #include "UI.hpp" #include "midi_devices.hpp" #include "config.h" -#include "synth_waveform_extended.h" //************************************************************************************************* //* GLOBAL VARIABLES @@ -57,7 +56,7 @@ AudioAmplifier volume_l; AudioAmplifier inverter; AudioEffectModulatedDelay modchorus_r; AudioEffectModulatedDelay modchorus_l; -AudioSynthWaveformExtended modulator; +AudioSynthWaveform modulator; AudioConnection patchCord0(queue_r, peak_r); AudioConnection patchCord1(queue_l, peak_l); AudioConnection patchCord2(queue_r, freeverb_r); @@ -558,7 +557,7 @@ void config_from_eeprom(void) { EEPROM_readAnything(EEPROM_CONFIGURATIONS + sizeof(config_t) * (sound - 1), configuration); #ifdef SHOW_DEBUG - Serial.print(F(" - OK")); + Serial.println(F(" - OK")); #endif } else @@ -667,6 +666,7 @@ void show_cpu_and_mem_usage(void) void show_sound(void) { + Serial.println(F("======SHOW=SOUND=CONFIGURATION======")); Serial.print(F("Master Volume: ")); Serial.println(master_volume, DEC); Serial.print(F("Sound: ")); @@ -721,6 +721,10 @@ void show_sound(void) Serial.println(configuration.chorus_delay, DEC); Serial.print(F("Chorus Intensity: ")); Serial.println(configuration.chorus_intensity, DEC); + Serial.print(F("Chorus Feedback: ")); + Serial.println(configuration.chorus_feedback, DEC); + Serial.print(F("Chorus Waveform: ")); + Serial.println(configuration.chorus_waveform, DEC); Serial.print(F("Chorus Level: ")); Serial.println(configuration.chorus_level, DEC); Serial.print(F("Bass L/R Level: ")); @@ -741,5 +745,6 @@ void show_sound(void) Serial.println(configuration.max_poly, DEC); Serial.print(F("Panorama: ")); Serial.println(configuration.pan, DEC); + Serial.println(F("======END=SOUND=CONFIGURATION=======")); } #endif diff --git a/UI.hpp b/UI.hpp index 4bf5a59..15db4be 100644 --- a/UI.hpp +++ b/UI.hpp @@ -49,7 +49,6 @@ #include #include "Encoder4.h" #include "config.h" -#include "synth_waveform_extended.h" LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, LCD_CHARS, LCD_LINES); Encoder4 enc[NUM_ENCODER] = {Encoder4(ENC_L_PIN_A, ENC_L_PIN_B), Encoder4(ENC_R_PIN_A, ENC_R_PIN_B)}; @@ -124,7 +123,7 @@ extern void eeprom_config_write(uint8_t value); extern AudioControlSGTL5000 sgtl5000_1; extern AudioEffectFreeverb freeverb_r; extern AudioEffectFreeverb freeverb_l; -extern AudioSynthWaveformExtended modulator; +extern AudioSynthWaveform modulator; extern AudioEffectModulatedDelay modchorus_r; extern AudioEffectModulatedDelay modchorus_l; extern AudioMixer4 mixer_r; @@ -1886,6 +1885,8 @@ void save_sound(void) void set_decay(uint8_t value) { + if (value > ENC_DECAY_MAX) + value = ENC_DECAY_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set DECAY ")); Serial.println(value); @@ -1897,6 +1898,8 @@ void set_decay(uint8_t value) void set_release(uint8_t value) { + if (value > ENC_RELEASE_MAX) + value = ENC_RELEASE_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set RELEASE ")); Serial.println(value); @@ -1908,6 +1911,8 @@ void set_release(uint8_t value) void set_hardness(uint8_t value) { + if (value > ENC_HARDNESS_MAX) + value = ENC_HARDNESS_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set HARDNESS ")); Serial.println(value); @@ -1919,6 +1924,8 @@ void set_hardness(uint8_t value) void set_treble(uint8_t value) { + if (value > ENC_TREBLE_MAX) + value = ENC_TREBLE_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set TREBLE ")); Serial.println(value); @@ -1930,6 +1937,8 @@ void set_treble(uint8_t value) void set_stereo(int8_t value) { + if (value > ENC_STEREO_MAX) + value = ENC_STEREO_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set STEREO ")); Serial.println(value); @@ -1941,6 +1950,10 @@ void set_stereo(int8_t value) void set_transpose(int8_t value) { + if (value < ENC_TRANSPOSE_MIN) + value = ENC_TRANSPOSE_MIN; + if (value > ENC_TRANSPOSE_MAX) + value = ENC_TRANSPOSE_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set TRANSPOSE ")); Serial.println(value); @@ -1951,6 +1964,10 @@ void set_transpose(int8_t value) void set_tune(int8_t value) { + if (value < ENC_TUNE_MIN) + value = ENC_TUNE_MIN; + if (value > ENC_TUNE_MAX) + value = ENC_TUNE_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set TUNE ")); Serial.println(value); @@ -1962,6 +1979,8 @@ void set_tune(int8_t value) void set_detune(uint8_t value) { + if (value > ENC_DETUNE_MAX) + value = ENC_DETUNE_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set DETUNE ")); Serial.println(value); @@ -1973,6 +1992,8 @@ void set_detune(uint8_t value) void set_velocity_sense(uint8_t value) { + if (value > ENC_VELOCITY_SENSE_MAX) + value = ENC_VELOCITY_SENSE_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set VELOCITY_SENSE ")); Serial.println(value); @@ -1984,6 +2005,8 @@ void set_velocity_sense(uint8_t value) void set_pan_trem_frequency(uint8_t value) { + if (value > ENC_PAN_TREM_FREQUENCY_MAX) + value = ENC_PAN_TREM_FREQUENCY_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set PAN_TREM_FREQENCY ")); Serial.println(value); @@ -1995,6 +2018,8 @@ void set_pan_trem_frequency(uint8_t value) void set_pan_trem_level(uint8_t value) { + if (value > ENC_PAN_TREM_LEVEL_MAX) + value = ENC_PAN_TREM_LEVEL_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set PAN_TREM_LEVEL ")); Serial.println(value); @@ -2006,6 +2031,8 @@ void set_pan_trem_level(uint8_t value) void set_overdrive(uint8_t value) { + if (value > ENC_OVERDRIVE_MAX) + value = ENC_OVERDRIVE_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set OVERDRIVE ")); Serial.println(value); @@ -2017,6 +2044,8 @@ void set_overdrive(uint8_t value) void set_comp_gain(uint8_t value) { + if (value > ENC_COMP_GAIN_MAX) + value = ENC_COMP_GAIN_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set COMP_GAIN ")); Serial.println(value); @@ -2028,6 +2057,8 @@ void set_comp_gain(uint8_t value) void set_comp_response(uint8_t value) { + if (value > ENC_COMP_RESPONSE_MAX) + value = ENC_COMP_RESPONSE_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set COMP_RESPONSE ")); Serial.println(value); @@ -2039,6 +2070,8 @@ void set_comp_response(uint8_t value) void set_comp_limit(uint8_t value) { + if (value > ENC_COMP_LIMIT_MAX) + value = ENC_COMP_LIMIT_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set COMP_LIMIT ")); Serial.println(value); @@ -2050,6 +2083,8 @@ void set_comp_limit(uint8_t value) void set_comp_threshold(uint8_t value) { + if (value > ENC_COMP_THRESHOLD_MAX) + value = ENC_COMP_THRESHOLD_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set COMP_THRESHOLD ")); Serial.println(value); @@ -2061,6 +2096,8 @@ void set_comp_threshold(uint8_t value) void set_comp_attack(uint8_t value) { + if (value > ENC_COMP_ATTACK_MAX) + value = ENC_COMP_ATTACK_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set COMP_ATTACK ")); Serial.println(value); @@ -2072,6 +2109,8 @@ void set_comp_attack(uint8_t value) void set_comp_decay(uint8_t value) { + if (value > ENC_COMP_DECAY_MAX) + value = ENC_COMP_DECAY_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set COMP_DECAY ")); Serial.println(value); @@ -2083,6 +2122,8 @@ void set_comp_decay(uint8_t value) void set_reverb_roomsize(uint8_t value) { + if (value > ENC_REVERB_ROOMSIZE_MAX) + value = ENC_REVERB_ROOMSIZE_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set REVERB_ROOMSIZE ")); Serial.println(value); @@ -2095,6 +2136,8 @@ void set_reverb_roomsize(uint8_t value) void set_reverb_damping(uint8_t value) { + if (value > ENC_REVERB_DAMPING_MAX) + value = ENC_REVERB_DAMPING_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set REVERB_DAMPING ")); Serial.println(value); @@ -2107,6 +2150,8 @@ void set_reverb_damping(uint8_t value) void set_reverb_level(uint8_t value) { + if (value > ENC_REVERB_LEVEL_MAX) + value = ENC_REVERB_LEVEL_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set REVERB_LEVEL ")); Serial.println(value); @@ -2119,6 +2164,8 @@ void set_reverb_level(uint8_t value) void set_chorus_frequency(uint8_t value) { + if (value > ENC_CHORUS_FREQUENCY_MAX) + value = ENC_CHORUS_FREQUENCY_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set CHORUS_FREQUENCY ")); Serial.println(value); @@ -2129,6 +2176,8 @@ void set_chorus_frequency(uint8_t value) void set_chorus_delay(uint8_t value) { + if (value > ENC_CHORUS_DELAY_MAX) + value = ENC_CHORUS_DELAY_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set CHORUS_DELAY ")); Serial.println(value); @@ -2139,6 +2188,8 @@ void set_chorus_delay(uint8_t value) void set_chorus_intensity(uint8_t value) { + if (value > ENC_CHORUS_INTENSITY_MAX) + value = ENC_CHORUS_INTENSITY_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set CHORUS_INTENSITY ")); Serial.println(value); @@ -2149,6 +2200,8 @@ void set_chorus_intensity(uint8_t value) void set_chorus_feedback(uint8_t value) { + if (value > ENC_CHORUS_FEEDBACK_MAX) + value = ENC_CHORUS_FEEDBACK_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set CHORUS_FEEDBACK ")); Serial.println(value); @@ -2162,25 +2215,28 @@ void set_chorus_waveform(uint8_t value) { #ifdef SHOW_DEBUG Serial.print(F("Set CHORUS_WAVEFORM ")); - Serial.println(value); #endif switch (value) { case 1: - modulator.waveform(WAVEFORM_TRIANGLE); + modulator.begin(WAVEFORM_TRIANGLE); break; case 2: - modulator.waveform(WAVEFORM_SINE); + modulator.begin(WAVEFORM_SINE); break; default: - modulator.waveform(WAVEFORM_TRIANGLE); + modulator.begin(WAVEFORM_TRIANGLE); + value = 1; break; } configuration.chorus_waveform = value; + Serial.println(value); } void set_chorus_level(uint8_t value) { + if (value > ENC_CHORUS_LEVEL_MAX) + value = ENC_CHORUS_LEVEL_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set CHORUS_LEVEL ")); Serial.println(value); @@ -2195,6 +2251,8 @@ void set_chorus_level(uint8_t value) void set_bass_lr_level(uint8_t value) { + if (value > ENC_BASS_MONO_LEVEL_MAX) + value = ENC_BASS_MONO_LEVEL_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set BASS_LR_LEVEL ")); Serial.println(value); @@ -2207,6 +2265,8 @@ void set_bass_lr_level(uint8_t value) void set_bass_mono_level(uint8_t value) { + if (value > ENC_BASS_LR_LEVEL_MAX) + value = ENC_BASS_LR_LEVEL_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set BASS_MONO_LEVEL ")); Serial.println(value); @@ -2219,6 +2279,8 @@ void set_bass_mono_level(uint8_t value) void set_eq_bass(uint8_t value) { + if (value > ENC_EQ_TREBLE_MAX) + value = ENC_EQ_TREBLE_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set EQ_BASS ")); Serial.println(value); @@ -2231,6 +2293,8 @@ void set_eq_bass(uint8_t value) void set_eq_treble(uint8_t value) { + if (value > ENC_EQ_BASS_MAX ) + value = ENC_EQ_BASS_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set EQ_TREBLE ")); Serial.println(value); @@ -2243,6 +2307,8 @@ void set_eq_treble(uint8_t value) void set_loudness(uint8_t value) { + if (value > ENC_LOUDNESS_MAX) + value = ENC_LOUDNESS_MAX; #ifdef SHOW_DEBUG Serial.print(F("Set LOUDNESS ")); Serial.println(value); @@ -2255,6 +2321,8 @@ void set_loudness(uint8_t value) void set_midi_channel(uint8_t value) { + if (value > 16) + value = 16; #ifdef SHOW_DEBUG Serial.print(F("Set MIDI_CHANNEL ")); Serial.println(value); @@ -2264,6 +2332,8 @@ void set_midi_channel(uint8_t value) void set_midi_soft_thru(uint8_t value) { + if (value > 1) + value = 1; #ifdef SHOW_DEBUG Serial.print(F("Set MIDI_SOFT_THRU ")); Serial.println(value); @@ -2273,6 +2343,8 @@ void set_midi_soft_thru(uint8_t value) void set_max_poly(uint8_t value) { + if (value > ENC_MAX_POLY_DEFAULT) + value = ENC_MAX_POLY_DEFAULT; #ifdef SHOW_DEBUG Serial.print(F("Set MAX_POLY ")); Serial.println(value); diff --git a/synth_waveform_extended.cpp b/synth_waveform_extended.cpp deleted file mode 100644 index 3f985ff..0000000 --- a/synth_waveform_extended.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* Audio Library for Teensy 3.X - * Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com - * - * Development of this audio library was funded by PJRC.COM, LLC by sales of - * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop - * open source software by purchasing Teensy or other PJRC products. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice, development funding notice, and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include "synth_waveform_extended.h" -#include "arm_math.h" -#include "utility/dspinst.h" - - -// uncomment for more accurate but more computationally expensive frequency modulation -//#define IMPROVE_EXPONENTIAL_ACCURACY - - -void AudioSynthWaveformExtended::update(void) -{ - audio_block_t *block; - int16_t *bp, *end; - int32_t val1, val2; - int16_t magnitude15; - uint32_t i, ph, index, index2, scale; - const uint32_t inc = phase_increment; - - ph = phase_accumulator + phase_offset; - if (magnitude == 0) { - phase_accumulator += inc * AUDIO_BLOCK_SAMPLES; - return; - } - block = allocate(); - if (!block) { - phase_accumulator += inc * AUDIO_BLOCK_SAMPLES; - return; - } - bp = block->data; - - switch(tone_type) { - case WAVEFORM_SINE: - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - index = ph >> 24; - val1 = AudioWaveformSine[index]; - val2 = AudioWaveformSine[index+1]; - scale = (ph >> 8) & 0xFFFF; - val2 *= scale; - val1 *= 0x10000 - scale; - *bp++ = multiply_32x32_rshift32(val1 + val2, magnitude); - ph += inc; - } - break; - - case WAVEFORM_ARBITRARY: - if (!arbdata) { - release(block); - phase_accumulator += inc * AUDIO_BLOCK_SAMPLES; - return; - } - // len = 256 - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - index = ph >> 24; - index2 = index + 1; - if (index2 >= 256) index2 = 0; - val1 = *(arbdata + index); - val2 = *(arbdata + index2); - scale = (ph >> 8) & 0xFFFF; - val2 *= scale; - val1 *= 0x10000 - scale; - *bp++ = multiply_32x32_rshift32(val1 + val2, magnitude); - ph += inc; - } - break; - - case WAVEFORM_SQUARE: - magnitude15 = signed_saturate_rshift(magnitude, 16, 1); - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - if (ph & 0x80000000) { - *bp++ = -magnitude15; - } else { - *bp++ = magnitude15; - } - ph += inc; - } - break; - - case WAVEFORM_SAWTOOTH: - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - *bp++ = signed_multiply_32x16t(magnitude, ph); - ph += inc; - } - break; - - case WAVEFORM_SAWTOOTH_REVERSE: - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - *bp++ = signed_multiply_32x16t(0xFFFFFFFFu - magnitude, ph); - ph += inc; - } - break; - - case WAVEFORM_TRIANGLE: - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - uint32_t phtop = ph >> 30; - if (phtop == 1 || phtop == 2) { - *bp++ = ((0xFFFF - (ph >> 15)) * magnitude) >> 16; - } else { - *bp++ = (((int32_t)ph >> 15) * magnitude) >> 16; - } - ph += inc; - } - break; - - case WAVEFORM_TRIANGLE_VARIABLE: - do { - uint32_t rise = 0xFFFFFFFF / (pulse_width >> 16); - uint32_t fall = 0xFFFFFFFF / (0xFFFF - (pulse_width >> 16)); - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - if (ph < pulse_width/2) { - uint32_t n = (ph >> 16) * rise; - *bp++ = ((n >> 16) * magnitude) >> 16; - } else if (ph < 0xFFFFFFFF - pulse_width/2) { - uint32_t n = 0x7FFFFFFF - (((ph - pulse_width/2) >> 16) * fall); - *bp++ = (((int32_t)n >> 16) * magnitude) >> 16; - } else { - uint32_t n = ((ph + pulse_width/2) >> 16) * rise + 0x80000000; - *bp++ = (((int32_t)n >> 16) * magnitude) >> 16; - } - ph += inc; - } - } while (0); - break; - - case WAVEFORM_PULSE: - magnitude15 = signed_saturate_rshift(magnitude, 16, 1); - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - if (ph < pulse_width) { - *bp++ = magnitude15; - } else { - *bp++ = -magnitude15; - } - ph += inc; - } - break; - - case WAVEFORM_SAMPLE_HOLD: - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - *bp++ = sample; - uint32_t newph = ph + inc; - if (newph < ph) { - sample = random(magnitude) - (magnitude >> 1); - } - ph = newph; - } - break; - } - phase_accumulator = ph - phase_offset; - - if (tone_offset) { - bp = block->data; - end = bp + AUDIO_BLOCK_SAMPLES; - do { - val1 = *bp; - *bp++ = signed_saturate_rshift(val1 + tone_offset, 16, 0); - } while (bp < end); - } - transmit(block, 0); - release(block); -} - -//-------------------------------------------------------------------------------- - -void AudioSynthWaveformExtendedModulated::update(void) -{ - audio_block_t *block, *moddata, *shapedata; - int16_t *bp, *end; - int32_t val1, val2; - int16_t magnitude15; - uint32_t i, ph, index, index2, scale, priorphase; - const uint32_t inc = phase_increment; - - moddata = receiveReadOnly(0); - shapedata = receiveReadOnly(1); - - // Pre-compute the phase angle for every output sample of this update - ph = phase_accumulator; - priorphase = phasedata[AUDIO_BLOCK_SAMPLES-1]; - if (moddata && modulation_type == 0) { - // Frequency Modulation - bp = moddata->data; - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - int32_t n = (*bp++) * modulation_factor; // n is # of octaves to mod - int32_t ipart = n >> 27; // 4 integer bits - n &= 0x7FFFFFF; // 27 fractional bits - #ifdef IMPROVE_EXPONENTIAL_ACCURACY - // exp2 polynomial suggested by Stefan Stenzel on "music-dsp" - // mail list, Wed, 3 Sep 2014 10:08:55 +0200 - int32_t x = n << 3; - n = multiply_accumulate_32x32_rshift32_rounded(536870912, x, 1494202713); - int32_t sq = multiply_32x32_rshift32_rounded(x, x); - n = multiply_accumulate_32x32_rshift32_rounded(n, sq, 1934101615); - n = n + (multiply_32x32_rshift32_rounded(sq, - multiply_32x32_rshift32_rounded(x, 1358044250)) << 1); - n = n << 1; - #else - // exp2 algorithm by Laurent de Soras - // https://www.musicdsp.org/en/latest/Other/106-fast-exp2-approximation.html - n = (n + 134217728) << 3; - n = multiply_32x32_rshift32_rounded(n, n); - n = multiply_32x32_rshift32_rounded(n, 715827883) << 3; - n = n + 715827882; - #endif - uint32_t scale = n >> (14 - ipart); - uint64_t phstep = (uint64_t)inc * scale; - uint32_t phstep_msw = phstep >> 32; - if (phstep_msw < 0x7FFE) { - ph += phstep >> 16; - } else { - ph += 0x7FFE0000; - } - phasedata[i] = ph; - } - release(moddata); - } else if (moddata) { - // Phase Modulation - bp = moddata->data; - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - // more than +/- 180 deg shift by 32 bit overflow of "n" - uint32_t n = (uint16_t)(*bp++) * modulation_factor; - phasedata[i] = ph + n; - ph += inc; - } - release(moddata); - } else { - // No Modulation Input - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - phasedata[i] = ph; - ph += inc; - } - } - phase_accumulator = ph; - - // If the amplitude is zero, no output, but phase still increments properly - if (magnitude == 0) { - if (shapedata) release(shapedata); - return; - } - block = allocate(); - if (!block) { - if (shapedata) release(shapedata); - return; - } - bp = block->data; - - // Now generate the output samples using the pre-computed phase angles - switch(tone_type) { - case WAVEFORM_SINE: - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - ph = phasedata[i]; - index = ph >> 24; - val1 = AudioWaveformSine[index]; - val2 = AudioWaveformSine[index+1]; - scale = (ph >> 8) & 0xFFFF; - val2 *= scale; - val1 *= 0x10000 - scale; - *bp++ = multiply_32x32_rshift32(val1 + val2, magnitude); - } - break; - - case WAVEFORM_ARBITRARY: - if (!arbdata) { - release(block); - if (shapedata) release(shapedata); - return; - } - // len = 256 - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - ph = phasedata[i]; - index = ph >> 24; - index2 = index + 1; - if (index2 >= 256) index2 = 0; - val1 = *(arbdata + index); - val2 = *(arbdata + index2); - scale = (ph >> 8) & 0xFFFF; - val2 *= scale; - val1 *= 0x10000 - scale; - *bp++ = multiply_32x32_rshift32(val1 + val2, magnitude); - } - break; - - case WAVEFORM_PULSE: - if (shapedata) { - magnitude15 = signed_saturate_rshift(magnitude, 16, 1); - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - uint32_t width = ((shapedata->data[i] + 0x8000) & 0xFFFF) << 16; - if (phasedata[i] < width) { - *bp++ = magnitude15; - } else { - *bp++ = -magnitude15; - } - } - break; - } // else fall through to orginary square without shape modulation - - case WAVEFORM_SQUARE: - magnitude15 = signed_saturate_rshift(magnitude, 16, 1); - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - if (phasedata[i] & 0x80000000) { - *bp++ = -magnitude15; - } else { - *bp++ = magnitude15; - } - } - break; - - case WAVEFORM_SAWTOOTH: - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - *bp++ = signed_multiply_32x16t(magnitude, phasedata[i]); - } - break; - - case WAVEFORM_SAWTOOTH_REVERSE: - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - *bp++ = signed_multiply_32x16t(0xFFFFFFFFu - magnitude, phasedata[i]); - } - break; - - case WAVEFORM_TRIANGLE_VARIABLE: - if (shapedata) { - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - uint32_t width = (shapedata->data[i] + 0x8000) & 0xFFFF; - uint32_t rise = 0xFFFFFFFF / width; - uint32_t fall = 0xFFFFFFFF / (0xFFFF - width); - uint32_t halfwidth = width << 15; - uint32_t n; - ph = phasedata[i]; - if (ph < halfwidth) { - n = (ph >> 16) * rise; - *bp++ = ((n >> 16) * magnitude) >> 16; - } else if (ph < 0xFFFFFFFF - halfwidth) { - n = 0x7FFFFFFF - (((ph - halfwidth) >> 16) * fall); - *bp++ = (((int32_t)n >> 16) * magnitude) >> 16; - } else { - n = ((ph + halfwidth) >> 16) * rise + 0x80000000; - *bp++ = (((int32_t)n >> 16) * magnitude) >> 16; - } - ph += inc; - } - break; - } // else fall through to orginary triangle without shape modulation - - case WAVEFORM_TRIANGLE: - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - ph = phasedata[i]; - uint32_t phtop = ph >> 30; - if (phtop == 1 || phtop == 2) { - *bp++ = ((0xFFFF - (ph >> 15)) * magnitude) >> 16; - } else { - *bp++ = (((int32_t)ph >> 15) * magnitude) >> 16; - } - } - break; - case WAVEFORM_SAMPLE_HOLD: - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - ph = phasedata[i]; - if (ph < priorphase) { // does not work for phase modulation - sample = random(magnitude) - (magnitude >> 1); - } - priorphase = ph; - *bp++ = sample; - } - break; - } - - if (tone_offset) { - bp = block->data; - end = bp + AUDIO_BLOCK_SAMPLES; - do { - val1 = *bp; - *bp++ = signed_saturate_rshift(val1 + tone_offset, 16, 0); - } while (bp < end); - } - if (shapedata) release(shapedata); - transmit(block, 0); - release(block); -} diff --git a/synth_waveform_extended.h b/synth_waveform_extended.h deleted file mode 100644 index 843ddf4..0000000 --- a/synth_waveform_extended.h +++ /dev/null @@ -1,221 +0,0 @@ -/* Audio Library for Teensy 3.X - Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com - - Development of this audio library was funded by PJRC.COM, LLC by sales of - Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop - open source software by purchasing Teensy or other PJRC products. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice, development funding notice, and this permission - notice shall be included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* - Extension for setting the waveform while running by H. Wirtz -*/ - -#ifndef synth_waveform_extended_h_ -#define synth_waveform_extended_h_ - -#include -#include "AudioStream.h" -#include "arm_math.h" - -// waveforms.c -extern "C" { - extern const int16_t AudioWaveformSine[257]; -} - - -#define WAVEFORM_SINE 0 -#define WAVEFORM_SAWTOOTH 1 -#define WAVEFORM_SQUARE 2 -#define WAVEFORM_TRIANGLE 3 -#define WAVEFORM_ARBITRARY 4 -#define WAVEFORM_PULSE 5 -#define WAVEFORM_SAWTOOTH_REVERSE 6 -#define WAVEFORM_SAMPLE_HOLD 7 -#define WAVEFORM_TRIANGLE_VARIABLE 8 - -class AudioSynthWaveformExtended : public AudioStream -{ - public: - AudioSynthWaveformExtended(void) : AudioStream(0, NULL), - phase_accumulator(0), phase_increment(0), phase_offset(0), - magnitude(0), pulse_width(0x40000000), - arbdata(NULL), sample(0), tone_type(WAVEFORM_SINE), - tone_offset(0) { - } - - void frequency(float freq) { - if (freq < 0.0) { - freq = 0.0; - } else if (freq > AUDIO_SAMPLE_RATE_EXACT / 2) { - freq = AUDIO_SAMPLE_RATE_EXACT / 2; - } - phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT); - if (phase_increment > 0x7FFE0000u) phase_increment = 0x7FFE0000; - } - void phase(float angle) { - if (angle < 0.0) { - angle = 0.0; - } else if (angle > 360.0) { - angle = angle - 360.0; - if (angle >= 360.0) return; - } - phase_offset = angle * (4294967296.0 / 360.0); - } - void amplitude(float n) { // 0 to 1.0 - if (n < 0) { - n = 0; - } else if (n > 1.0) { - n = 1.0; - } - magnitude = n * 65536.0; - } - void offset(float n) { - if (n < -1.0) { - n = -1.0; - } else if (n > 1.0) { - n = 1.0; - } - tone_offset = n * 32767.0; - } - void pulseWidth(float n) { // 0.0 to 1.0 - if (n < 0) { - n = 0; - } else if (n > 1.0) { - n = 1.0; - } - pulse_width = n * 4294967296.0; - } - void waveform(short t_type) { - phase_offset = 0; - tone_type = t_type; - } - void begin(short t_type) { - phase_offset = 0; - tone_type = t_type; - } - void begin(float t_amp, float t_freq, short t_type) { - amplitude(t_amp); - frequency(t_freq); - phase_offset = 0; - tone_type = t_type; - } - void arbitraryWaveform(const int16_t *data, float maxFreq) { - arbdata = data; - } - virtual void update(void); - - private: - uint32_t phase_accumulator; - uint32_t phase_increment; - uint32_t phase_offset; - int32_t magnitude; - uint32_t pulse_width; - const int16_t *arbdata; - int16_t sample; // for WAVEFORM_SAMPLE_HOLD - short tone_type; - int16_t tone_offset; -}; - - -class AudioSynthWaveformExtendedModulated : public AudioStream -{ - public: - AudioSynthWaveformExtendedModulated(void) : AudioStream(2, inputQueueArray), - phase_accumulator(0), phase_increment(0), modulation_factor(32768), - magnitude(0), arbdata(NULL), sample(0), tone_offset(0), - tone_type(WAVEFORM_SINE), modulation_type(0) { - } - - void frequency(float freq) { - if (freq < 0.0) { - freq = 0.0; - } else if (freq > AUDIO_SAMPLE_RATE_EXACT / 2) { - freq = AUDIO_SAMPLE_RATE_EXACT / 2; - } - phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT); - if (phase_increment > 0x7FFE0000u) phase_increment = 0x7FFE0000; - } - void amplitude(float n) { // 0 to 1.0 - if (n < 0) { - n = 0; - } else if (n > 1.0) { - n = 1.0; - } - magnitude = n * 65536.0; - } - void offset(float n) { - if (n < -1.0) { - n = -1.0; - } else if (n > 1.0) { - n = 1.0; - } - tone_offset = n * 32767.0; - } - void waveform(short t_type) { - tone_type = t_type; - } - void begin(short t_type) { - tone_type = t_type; - } - void begin(float t_amp, float t_freq, short t_type) { - amplitude(t_amp); - frequency(t_freq); - tone_type = t_type; - } - void arbitraryWaveform(const int16_t *data, float maxFreq) { - arbdata = data; - } - void frequencyModulation(float octaves) { - if (octaves > 12.0) { - octaves = 12.0; - } else if (octaves < 0.1) { - octaves = 0.1; - } - modulation_factor = octaves * 4096.0; - modulation_type = 0; - } - void phaseModulation(float degrees) { - if (degrees > 9000.0) { - degrees = 9000.0; - } else if (degrees < 30.0) { - degrees = 30.0; - } - modulation_factor = degrees * (65536.0 / 180.0); - modulation_type = 1; - } - virtual void update(void); - - private: - audio_block_t *inputQueueArray[2]; - uint32_t phase_accumulator; - uint32_t phase_increment; - uint32_t modulation_factor; - int32_t magnitude; - const int16_t *arbdata; - uint32_t phasedata[AUDIO_BLOCK_SAMPLES]; - int16_t sample; // for WAVEFORM_SAMPLE_HOLD - int16_t tone_offset; - uint8_t tone_type; - uint8_t modulation_type; -}; - - -#endif