From 89c13cfef3690362456252262b568ecad1756510 Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Mon, 25 Nov 2019 13:23:49 +0100 Subject: [PATCH] Fixes and additions for portamento. Added modulator input for mono2stereo. Changed memory usage for AUDIO_MEM. --- config.h | 11 ++++--- dexed.cpp | 5 ++-- dexed.h | 1 + dx7note.cpp | 29 ++++++++++++++++-- dx7note.h | 4 ++- mono2stereo.cpp => effect_mono2stereo.cpp | 36 +++++++++++++++-------- mono2stereo.h => effect_mono2stereo.h | 7 ++--- 7 files changed, 67 insertions(+), 26 deletions(-) rename mono2stereo.cpp => effect_mono2stereo.cpp (70%) rename mono2stereo.h => effect_mono2stereo.h (93%) diff --git a/config.h b/config.h index b2d3133..ea9f4c9 100644 --- a/config.h +++ b/config.h @@ -91,17 +91,17 @@ //************************************************************************************************* #ifndef TEENSY_AUDIO_BOARD #if AUDIO_BLOCK_SAMPLES == 64 -#define AUDIO_MEM 450 +#define AUDIO_MEM 256 #else -#define AUDIO_MEM 225 +#define AUDIO_MEM 128 #endif #define REDUCE_LOUDNESS 1 #else // IF TEENSY_AUDIO_BOARD #define SGTL5000_LINEOUT_LEVEL 29 #if AUDIO_BLOCK_SAMPLES == 64 -#define AUDIO_MEM 900 +#define AUDIO_MEM 512 #else -#define AUDIO_MEM 450 +#define AUDIO_MEM 256 #endif #define DELAY_MAX_TIME 600 #define REDUCE_LOUDNESS 1 @@ -475,9 +475,12 @@ typedef struct { dexed_t dexed[NUM_DEXED]; } config_t; +#if !defined(_MAPFLOAT) +#define _MAPFLOAT inline float mapfloat(float val, float in_min, float in_max, float out_min, float out_max) { return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } +#endif #endif // CONFIG_H_INCLUDED diff --git a/dexed.cpp b/dexed.cpp index 29b84d1..23abc5d 100644 --- a/dexed.cpp +++ b/dexed.cpp @@ -119,7 +119,7 @@ void Dexed::getSamples(uint16_t n_samples, int16_t* buffer) for (i = 0; i < max_notes; i++) { if ( voices[i].live ) - voices[i].dx7_note->update(data, voices[i].midi_note, voices[i].velocity); + voices[i].dx7_note->update(data, voices[i].midi_note, voices[i].velocity, voices[i].porta); } lfo.reset(data + 137); @@ -212,7 +212,8 @@ void Dexed::keydown(int16_t pitch, uint8_t velo) { voices[note].velocity = velo; voices[note].sustained = sustain; voices[note].keydown = true; - voices[note].dx7_note->init(data, pitch, velo, previousKeyDown, porta); + int srcnote = (previousKeyDown >= 0) ? previousKeyDown : pitch; + voices[note].dx7_note->init(data, pitch, velo, srcnote, porta); if ( data[136] ) voices[note].dx7_note->oscSync(); break; diff --git a/dexed.h b/dexed.h index a598f7a..a4abd44 100644 --- a/dexed.h +++ b/dexed.h @@ -48,6 +48,7 @@ extern float vol_left; struct ProcessorVoice { int16_t midi_note; uint8_t velocity; + int16_t porta; bool keydown; bool sustained; bool live; diff --git a/dx7note.cpp b/dx7note.cpp index 00edd9e..9020f4f 100644 --- a/dx7note.cpp +++ b/dx7note.cpp @@ -23,6 +23,7 @@ #include "exp2.h" #include "controllers.h" #include "dx7note.h" +#include "dexed.h" const int FEEDBACK_BITDEPTH = 8; @@ -33,6 +34,13 @@ int32_t midinote_to_logfreq(int midinote) { return base + step * midinote; } +int32_t logfreq_round2semi(int freq) { + const int base = 50857777; // (1 << 24) * (log(440) / log(2) - 69/12) + const int step = (1 << 24) / 12; + const int rem = (freq - base) % step; + return freq - rem; +} + const int32_t coarsemul[] = { -16777216, 0, 16777216, 26591258, 33554432, 38955489, 43368474, 47099600, 50331648, 53182516, 55732705, 58039632, 60145690, 62083076, 63876816, @@ -176,6 +184,7 @@ void Dx7Note::init(const uint8_t patch[173], int midinote, int velocity, int src int32_t freq = osc_freq(midinote, mode, coarse, fine, detune); opMode[op] = mode; basepitch_[op] = freq; + porta_curpitch_[op] = freq; ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3]; if (porta >= 0) @@ -193,6 +202,7 @@ void Dx7Note::init(const uint8_t patch[173], int midinote, int velocity, int src pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; ampmoddepth_ = (patch[140] * 165) >> 6; porta_rateindex_ = (porta < 128) ? porta : 127; + porta_gliss_ = patch[68]; } void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Controllers *ctrls) { @@ -246,8 +256,11 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Co if ( opMode[op] ) params_[op].freq = Freqlut::lookup(basepitch + pitch_base); else { - if ( porta_rateindex_ >= 0 ) + if ( porta_rateindex_ >= 0 ) { basepitch = porta_curpitch_[op]; + if ( porta_gliss_ ) + basepitch = logfreq_round2semi(basepitch); + } params_[op].freq = Freqlut::lookup(basepitch + pitch_mod); } @@ -293,7 +306,7 @@ void Dx7Note::keyup() { pitchenv_.keydown(false); } -void Dx7Note::update(const uint8_t patch[156], int midinote, int velocity) { +void Dx7Note::update(const uint8_t patch[156], int midinote, int velocity, int porta) { int rates[4]; int levels[4]; for (int op = 0; op < 6; op++) { @@ -302,7 +315,9 @@ void Dx7Note::update(const uint8_t patch[156], int midinote, int velocity) { int coarse = patch[off + 18]; int fine = patch[off + 19]; int detune = patch[off + 20]; - basepitch_[op] = osc_freq(midinote, mode, coarse, fine, detune); + int32_t freq = osc_freq(midinote, mode, coarse, fine, detune); + basepitch_[op] = freq; + porta_curpitch_[op] = freq; ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3]; opMode[op] = mode; @@ -328,6 +343,8 @@ void Dx7Note::update(const uint8_t patch[156], int midinote, int velocity) { pitchmoddepth_ = (patch[139] * 165) >> 6; pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; ampmoddepth_ = (patch[140] * 165) >> 6; + porta_rateindex_ = (porta < 128) ? porta : 127; + porta_gliss_ = patch[68]; } void Dx7Note::peekVoiceStatus(VoiceStatus &status) { @@ -356,6 +373,12 @@ void Dx7Note::transferSignal(Dx7Note &src) { } } +void Dx7Note::transferPortamento(Dx7Note &src) { + for (int i = 0; i < 6; i++) { + porta_curpitch_[i] = src.porta_curpitch_[i]; + } +} + void Dx7Note::oscSync() { for (int i = 0; i < 6; i++) { params_[i].gain_out = 0; diff --git a/dx7note.h b/dx7note.h index 508b418..fcd5487 100644 --- a/dx7note.h +++ b/dx7note.h @@ -53,10 +53,11 @@ class Dx7Note { // keyup, that won't work. // PG:add the update - void update(const uint8_t patch[156], int midinote, int velocity); + void update(const uint8_t patch[156], int midinote, int velocity, int porta); void peekVoiceStatus(VoiceStatus &status); void transferState(Dx7Note& src); void transferSignal(Dx7Note &src); + void transferPortamento(Dx7Note &src); void oscSync(); private: @@ -75,6 +76,7 @@ class Dx7Note { int pitchmodsens_; int porta_rateindex_; + int porta_gliss_; int32_t porta_curpitch_[6]; }; diff --git a/mono2stereo.cpp b/effect_mono2stereo.cpp similarity index 70% rename from mono2stereo.cpp rename to effect_mono2stereo.cpp index 435f7a2..f63492b 100644 --- a/mono2stereo.cpp +++ b/effect_mono2stereo.cpp @@ -22,47 +22,59 @@ #include #include -#include "mono2stereo.h" +#include "effect_mono2stereo.h" /*************************************************************************/ // A u d i o E f f e c t M o n o 2 S t e r e o // Written by Holger Wirtz -// 20191122 - inital version +// 20191122 - initial version -void Mono2Stereo::pan(float pan) +#if !defined(_MAPFLOAT) +#define _MAPFLOAT +inline float mapfloat(float val, float in_min, float in_max, float out_min, float out_max) { - constrain(pan, 0.0, 1.0); - _pan = pan; + return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } +#endif void Mono2Stereo::update(void) { audio_block_t *in; + audio_block_t *mod; audio_block_t *out[2]; in = receiveReadOnly(0); + mod = receiveReadOnly(1); + out[0] = allocate(); out[1] = allocate(); - if (in && out[0] && out[1]) + if (in && mod && out[0] && out[1]) { int16_t *ip = in->data; + int16_t *modp = mod->data; int16_t *op[2] = { out[0]->data, out[1]->data }; - float f_l = _pseudo_log * sinf(_pan * PI / 2); // _Pan [L0.0 ... M0.5 ... 1.0R] - float f_r = _pseudo_log * cosf(_pan * PI / 2); for (uint16_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { - *op[0] = int16_t(f_l * (*ip)); - *op[1] = int16_t(f_r * (*ip++)); - op[0]++; - op[1]++; + mapfloat(*modp, -1.0, 1.0, 0.0, 1.0); + float f_l = _pseudo_log * sinf(*modp * PI / 2); // _Pan [L0.0 ... M0.5 ... 1.0R] + float f_r = _pseudo_log * cosf(*modp * PI / 2); + *op[0]++ = int16_t(f_l * (*ip)); + *op[1]++ = int16_t(f_r * (*ip++)); + //op[0]++; + //op[1]++; + mod++; } if (in) { release(in); } + if (mod) + { + release(mod); + } for (uint8_t i = 0; i < 2; i++) { if (out[i]) diff --git a/mono2stereo.h b/effect_mono2stereo.h similarity index 93% rename from mono2stereo.h rename to effect_mono2stereo.h index 68de6f0..fc8af98 100644 --- a/mono2stereo.h +++ b/effect_mono2stereo.h @@ -20,8 +20,8 @@ THE SOFTWARE. */ -#ifndef mono2stereo_h_ -#define mono2stereo_h_ +#ifndef effect_mono2stereo_h_ +#define effect_mono2stereo_h_ #include "Arduino.h" #include "AudioStream.h" @@ -35,13 +35,12 @@ class Mono2Stereo : public AudioStream { public: Mono2Stereo(void): - AudioStream(1, inputQueueArray) + AudioStream(2, inputQueueArray) { _pan = 0.5; } virtual void update(void); - virtual void pan(float pan); private: audio_block_t *inputQueueArray[4];