From ca476751eb8f0bfeb53ae946f184058901f6bc9c Mon Sep 17 00:00:00 2001 From: root Date: Wed, 29 Mar 2017 14:53:53 +0200 Subject: [PATCH] Added several patches from the original Dexed. --- src/EngineMkI.cpp | 8 ++++---- src/EngineOpl.cpp | 2 +- src/dexed.cpp | 12 +++++++----- src/dexed.h | 2 +- src/msfa/controllers.h | 36 +++++++++++++++++++++++------------- src/msfa/dx7note.cc | 33 ++++++++++++++++++++++++++------- src/msfa/dx7note.h | 5 +++-- src/msfa/env.cc | 40 +++++++++++++++++++++++++--------------- src/msfa/env.h | 4 +++- 9 files changed, 93 insertions(+), 49 deletions(-) diff --git a/src/EngineMkI.cpp b/src/EngineMkI.cpp index 8d9d233..df66a47 100644 --- a/src/EngineMkI.cpp +++ b/src/EngineMkI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2016 Pascal Gauthier. + * Copyright (C) 2015-2017 Pascal Gauthier. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,7 +41,7 @@ double round(double n) { return n < 0.0 ? ceil(n - 0.5) : floor(n + 0.5); } - __declspec(align(16)) int zeros[N] = {0}; + __declspec(align(16)) const int zeros[N] = {0}; #else const int32_t __attribute__ ((aligned(16))) zeros[N] = {0}; #endif @@ -330,14 +330,14 @@ void EngineMkI::render(int32_t *output, FmOpParams *params, int algorithm, int32 switch ( algorithm ) { // three operator feedback, process exception for ALGO 4 case 3 : - compute_fb3(outptr, params, gain1, gain2, fb_buf, feedback_shift); + compute_fb3(outptr, params, gain1, gain2, fb_buf, min((feedback_shift+2),16)); params[1].phase += params[1].freq << LG_N; // hack, we already processed op-5 - op-4 params[2].phase += params[2].freq << LG_N; // yuk yuk op += 2; // ignore the 2 other operators break; // two operator feedback, process exception for ALGO 6 case 5 : - compute_fb2(outptr, params, gain1, gain2, fb_buf, feedback_shift); + compute_fb2(outptr, params, gain1, gain2, fb_buf, min((feedback_shift+2),16)); params[1].phase += params[1].freq << LG_N; // yuk, hack, we already processed op-5 op++; // ignore next operator; break; diff --git a/src/EngineOpl.cpp b/src/EngineOpl.cpp index 803d1e7..073881e 100644 --- a/src/EngineOpl.cpp +++ b/src/EngineOpl.cpp @@ -26,7 +26,7 @@ #include "EngineOpl.h" #ifdef _WIN32 - __declspec(align(16)) int zeros[N] = {0}; + __declspec(align(16)) const int zeros[N] = {0}; #else const int32_t __attribute__ ((aligned(16))) zeros[N] = {0}; #endif diff --git a/src/dexed.cpp b/src/dexed.cpp index 0f7e49f..6fb6de9 100644 --- a/src/dexed.cpp +++ b/src/dexed.cpp @@ -360,7 +360,10 @@ void Dexed::set_params(void) onParam(172,*p(p_number_of_voices)); if(_param_change_counter>PARAM_CHANGE_LEVEL) + { panic(); + controllers.refresh(); + } //TRACE("Bye"); } @@ -427,7 +430,7 @@ void Dexed::GetSamples(uint32_t n_samples, float* buffer) if(refreshVoice) { for(i=0;i < max_notes;i++) { if ( voices[i].live ) - voices[i].dx7_note->update(data, voices[i].midi_note, feedback_bitdepth); + voices[i].dx7_note->update(data, voices[i].midi_note, voices[i].velocity); } lfo.reset(data+137); refreshVoice = false; @@ -632,9 +635,10 @@ TRACE("pitch=%d, velo=%d\n",pitch,velo); if (!voices[note].keydown) { currentNote = (note + 1) % max_notes; voices[note].midi_note = pitch; + voices[note].velocity = velo; voices[note].sustained = sustain; voices[note].keydown = true; - voices[note].dx7_note->init(data, pitch, velo, feedback_bitdepth); + voices[note].dx7_note->init(data, pitch, velo); if ( data[136] ) voices[note].dx7_note->oscSync(); break; @@ -802,21 +806,19 @@ void Dexed::setEngineType(uint8_t tp) { case DEXED_ENGINE_MARKI: TRACE("DEXED_ENGINE_MARKI:%d",DEXED_ENGINE_MARKI); controllers.core = engineMkI; - feedback_bitdepth = 11; break; case DEXED_ENGINE_OPL: TRACE("DEXED_ENGINE_OPL:%d",DEXED_ENGINE_OPL); controllers.core = engineOpl; - feedback_bitdepth = 11; break; default: TRACE("DEXED_ENGINE_MODERN:%d",DEXED_ENGINE_MODERN); controllers.core = engineMsfa; - feedback_bitdepth = 8; break; } engineType = tp; panic(); + controllers.refresh(); } bool Dexed::isMonoMode(void) { diff --git a/src/dexed.h b/src/dexed.h index 441a2a8..ebafd84 100644 --- a/src/dexed.h +++ b/src/dexed.h @@ -38,6 +38,7 @@ struct ProcessorVoice { uint8_t midi_note; + uint8_t velocity; bool keydown; bool sustained; bool live; @@ -106,7 +107,6 @@ class Dexed : public lvtk::Synth bool monoMode; bool refreshVoice; uint8_t engineType; - uint8_t feedback_bitdepth; PluginFx fx; Lfo lfo; FmCore* engineMsfa; diff --git a/src/msfa/controllers.h b/src/msfa/controllers.h index d765835..9a399ee 100755 --- a/src/msfa/controllers.h +++ b/src/msfa/controllers.h @@ -35,33 +35,44 @@ class FmCore; struct FmMod { uint8_t range; - uint8_t target; + bool pitch; + bool amp; + bool eg; FmMod() { range = 0; - target= 0; + pitch = false; + amp = false; + eg = false; } -public: void setRange(uint8_t r) { - //range = r < 0 && r > 127 ? 0 : r; - range = r < 0 && r > 100 ? 0 : r; + range = r < 0 && r > 127 ? 0 : r; } void setTarget(uint8_t assign) { - target=assign < 0 && assign > 7 ? 0 : assign; + assign=assign < 0 && assign > 7 ? 0 : assign; + if(assign&1) // AMP + pitch=true; + if(assign&2) // PITCH + amp=true; + if(assign&4) // EG + eg=true; } }; class Controllers { void applyMod(int cc, FmMod &mod) { - uint8_t total = (int)(cc * mod.range * 0.01); - if(mod.target&1) // AMP + float range = 0.01 * mod.range; + uint8_t total = cc * range; + if(mod.amp) amp_mod = max(amp_mod, total); - else if(mod.target&2) // PITCH + + if(mod.pitch) pitch_mod = max(pitch_mod, total); - else if(mod.target&4) // EG - eg_mod = max(eg_mod, total); + + if(mod.eg) + eg_mod = max(eg_mod, total); } public: @@ -99,9 +110,8 @@ public: applyMod(foot_cc, foot); applyMod(aftertouch_cc, at); -/* if ( ! ((wheel.eg || foot.eg) || (breath.eg || at.eg)) ) + if ( ! ((wheel.eg || foot.eg) || (breath.eg || at.eg)) ) eg_mod = 127; - */ TRACE("amp_mod %d pitch_mod %d", amp_mod, pitch_mod); } diff --git a/src/msfa/dx7note.cc b/src/msfa/dx7note.cc index b97f83f..99db121 100644 --- a/src/msfa/dx7note.cc +++ b/src/msfa/dx7note.cc @@ -1,5 +1,5 @@ /* - * Copyright 2016 Pascal Gauthier. + * Copyright 2016-2017 Pascal Gauthier. * Copyright 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,6 +23,8 @@ #include "controllers.h" #include "dx7note.h" +const int FEEDBACK_BITDEPTH = 8; + int32_t midinote_to_logfreq(int midinote) { const int base = 50857777; // (1 << 24) * (log(440) / log(2) - 69/12) const int step = (1 << 24) / 12; @@ -137,7 +139,7 @@ Dx7Note::Dx7Note() { } //void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity, int fb_depth) { -void Dx7Note::init(const uint8_t patch[167], int midinote, int velocity, int fb_depth) { +void Dx7Note::init(const uint8_t patch[167], int midinote, int velocity) { int rates[4]; int levels[4]; for (int op = 0; op < 6; op++) { @@ -173,7 +175,7 @@ void Dx7Note::init(const uint8_t patch[167], int midinote, int velocity, int fb_ pitchenv_.set(rates, levels); algorithm_ = patch[134]; int feedback = patch[135]; - fb_shift_ = feedback != 0 ? fb_depth - feedback : 16; + fb_shift_ = feedback != 0 ? FEEDBACK_BITDEPTH - feedback : 16; pitchmoddepth_ = (patch[139] * 165) >> 6; pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; ampmoddepth_ = (patch[140] * 165) >> 6; @@ -211,8 +213,7 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Co uint32_t amd_mod = max(amod_1, amod_2); // ==== EG AMP MOD ==== - //uint32_t amod_3 = (ctrls->eg_mod+1) << 17; - uint32_t amod_3 = ((ctrls->eg_mod)+1) << 17; + uint32_t amod_3 = (ctrls->eg_mod+1) << 17; amd_mod = max((1<<24) - amod_3, amd_mod); // ==== OP RENDER ==== @@ -247,7 +248,9 @@ void Dx7Note::keyup() { pitchenv_.keydown(false); } -void Dx7Note::update(const uint8_t patch[156], int midinote, int fb_depth) { +void Dx7Note::update(const uint8_t patch[156], int midinote, int velocity) { + int rates[4]; + int levels[4]; for (int op = 0; op < 6; op++) { int off = op * 21; int mode = patch[off + 17]; @@ -256,10 +259,26 @@ void Dx7Note::update(const uint8_t patch[156], int midinote, int fb_depth) { int detune = patch[off + 20]; basepitch_[op] = osc_freq(midinote, mode, coarse, fine, detune); ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3]; + + for (int i = 0; i < 4; i++) { + rates[i] = patch[off + i]; + levels[i] = patch[off + 4 + i]; + } + int outlevel = patch[off + 16]; + outlevel = Env::scaleoutlevel(outlevel); + int level_scaling = ScaleLevel(midinote, patch[off + 8], patch[off + 9], + patch[off + 10], patch[off + 11], patch[off + 12]); + outlevel += level_scaling; + outlevel = min(127, outlevel); + outlevel = outlevel << 5; + outlevel += ScaleVelocity(velocity, patch[off + 15]); + outlevel = max(0, outlevel); + int rate_scaling = ScaleRate(midinote, patch[off + 13]); + env_[op].update(rates, levels, outlevel, rate_scaling); } algorithm_ = patch[134]; int feedback = patch[135]; - fb_shift_ = feedback != 0 ? 11 - feedback : 16; + fb_shift_ = feedback != 0 ? FEEDBACK_BITDEPTH - feedback : 16; pitchmoddepth_ = (patch[139] * 165) >> 6; pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; ampmoddepth_ = (patch[140] * 165) >> 6; diff --git a/src/msfa/dx7note.h b/src/msfa/dx7note.h index 6b6a108..3636797 100644 --- a/src/msfa/dx7note.h +++ b/src/msfa/dx7note.h @@ -1,4 +1,5 @@ /* + * Copyright 2016-2017 Pascal Gauthier. * Copyright 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,7 +38,7 @@ class Dx7Note { public: Dx7Note(); //void init(const uint8_t patch[156], int midinote, int velocity, int fb_depth); - void init(const uint8_t patch[160], int midinote, int velocity, int fb_depth); + void init(const uint8_t patch[160], int midinote, int velocity); // Note: this _adds_ to the buffer. Interesting question whether it's // worth it... @@ -52,7 +53,7 @@ public: // keyup, that won't work. // PG:add the update - void update(const uint8_t patch[156], int midinote, int fb_depth); + void update(const uint8_t patch[156], int midinote, int velocity); void peekVoiceStatus(VoiceStatus &status); void transferState(Dx7Note& src); void transferSignal(Dx7Note &src); diff --git a/src/msfa/env.cc b/src/msfa/env.cc index 9249d94..b6b98de 100644 --- a/src/msfa/env.cc +++ b/src/msfa/env.cc @@ -1,4 +1,5 @@ /* + * Copyright 2017 Pascal Gauthier. * Copyright 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,6 +24,10 @@ uint32_t Env::sr_multiplier = (1<<24); +const int levellut[] = { + 0, 5, 9, 13, 17, 20, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 42, 43, 45, 46 +}; + void Env::init_sr(double sampleRate) { sr_multiplier = (44100.0 / sampleRate) * (1<<24); } @@ -66,24 +71,11 @@ int32_t Env::getsample() { void Env::keydown(bool d) { if (down_ != d) { - down_ = d; - advance(d ? 0 : 3); - } -} - -void Env::setparam(int param, int value) { - if (param < 4) { - rates_[param] = value; - } else if (param < 8) { - levels_[param - 4] = value; + down_ = d; + advance(d ? 0 : 3); } - // Unknown parameter, ignore for now } -const int levellut[] = { - 0, 5, 9, 13, 17, 20, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 42, 43, 45, 46 -}; - int Env::scaleoutlevel(int outlevel) { return outlevel >= 20 ? 28 + outlevel : levellut[outlevel]; } @@ -110,6 +102,24 @@ void Env::advance(int newix) { } } +void Env::update(const int r[4], const int l[4], int32_t ol, int rate_scaling) { + for (int i = 0; i < 4; i++) { + rates_[i] = r[i]; + levels_[i] = l[i]; + } + outlevel_ = ol; + rate_scaling_ = rate_scaling; + if ( down_ ) { + // for now we simply reset ourselve at level 3 + int newlevel = levels_[2]; + int actuallevel = scaleoutlevel(newlevel) >> 1; + actuallevel = (actuallevel << 6) - 4256; + actuallevel = actuallevel < 16 ? 16 : actuallevel; + targetlevel_ = actuallevel << 16; + advance(2); + } +} + void Env::getPosition(char *step) { *step = ix_; } diff --git a/src/msfa/env.h b/src/msfa/env.h index 047eb95..cb5daa6 100755 --- a/src/msfa/env.h +++ b/src/msfa/env.h @@ -31,6 +31,9 @@ class Env { void init(const int rates[4], const int levels[4], int outlevel, int rate_scaling); + void update(const int rates[4], const int levels[4], int outlevel, + int rate_scaling); + // Result is in Q24/doubling log format. Also, result is subsampled // for every N samples. // A couple more things need to happen for this to be used as a gain @@ -40,7 +43,6 @@ class Env { int32_t getsample(); void keydown(bool down); - void setparam(int param, int value); static int scaleoutlevel(int outlevel); void getPosition(char *step);