Added several patches from the original Dexed.

pull/1/head
root 7 years ago
parent bf24d15002
commit ca476751eb
  1. 8
      src/EngineMkI.cpp
  2. 2
      src/EngineOpl.cpp
  3. 12
      src/dexed.cpp
  4. 2
      src/dexed.h
  5. 36
      src/msfa/controllers.h
  6. 33
      src/msfa/dx7note.cc
  7. 5
      src/msfa/dx7note.h
  8. 40
      src/msfa/env.cc
  9. 4
      src/msfa/env.h

@ -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 * 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 * it under the terms of the GNU General Public License as published by
@ -41,7 +41,7 @@
double round(double n) { double round(double n) {
return n < 0.0 ? ceil(n - 0.5) : floor(n + 0.5); 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 #else
const int32_t __attribute__ ((aligned(16))) zeros[N] = {0}; const int32_t __attribute__ ((aligned(16))) zeros[N] = {0};
#endif #endif
@ -330,14 +330,14 @@ void EngineMkI::render(int32_t *output, FmOpParams *params, int algorithm, int32
switch ( algorithm ) { switch ( algorithm ) {
// three operator feedback, process exception for ALGO 4 // three operator feedback, process exception for ALGO 4
case 3 : 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[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 params[2].phase += params[2].freq << LG_N; // yuk yuk
op += 2; // ignore the 2 other operators op += 2; // ignore the 2 other operators
break; break;
// two operator feedback, process exception for ALGO 6 // two operator feedback, process exception for ALGO 6
case 5 : 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 params[1].phase += params[1].freq << LG_N; // yuk, hack, we already processed op-5
op++; // ignore next operator; op++; // ignore next operator;
break; break;

@ -26,7 +26,7 @@
#include "EngineOpl.h" #include "EngineOpl.h"
#ifdef _WIN32 #ifdef _WIN32
__declspec(align(16)) int zeros[N] = {0}; __declspec(align(16)) const int zeros[N] = {0};
#else #else
const int32_t __attribute__ ((aligned(16))) zeros[N] = {0}; const int32_t __attribute__ ((aligned(16))) zeros[N] = {0};
#endif #endif

@ -360,7 +360,10 @@ void Dexed::set_params(void)
onParam(172,*p(p_number_of_voices)); onParam(172,*p(p_number_of_voices));
if(_param_change_counter>PARAM_CHANGE_LEVEL) if(_param_change_counter>PARAM_CHANGE_LEVEL)
{
panic(); panic();
controllers.refresh();
}
//TRACE("Bye"); //TRACE("Bye");
} }
@ -427,7 +430,7 @@ void Dexed::GetSamples(uint32_t n_samples, float* buffer)
if(refreshVoice) { if(refreshVoice) {
for(i=0;i < max_notes;i++) { for(i=0;i < max_notes;i++) {
if ( voices[i].live ) 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); lfo.reset(data+137);
refreshVoice = false; refreshVoice = false;
@ -632,9 +635,10 @@ TRACE("pitch=%d, velo=%d\n",pitch,velo);
if (!voices[note].keydown) { if (!voices[note].keydown) {
currentNote = (note + 1) % max_notes; currentNote = (note + 1) % max_notes;
voices[note].midi_note = pitch; voices[note].midi_note = pitch;
voices[note].velocity = velo;
voices[note].sustained = sustain; voices[note].sustained = sustain;
voices[note].keydown = true; 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] ) if ( data[136] )
voices[note].dx7_note->oscSync(); voices[note].dx7_note->oscSync();
break; break;
@ -802,21 +806,19 @@ void Dexed::setEngineType(uint8_t tp) {
case DEXED_ENGINE_MARKI: case DEXED_ENGINE_MARKI:
TRACE("DEXED_ENGINE_MARKI:%d",DEXED_ENGINE_MARKI); TRACE("DEXED_ENGINE_MARKI:%d",DEXED_ENGINE_MARKI);
controllers.core = engineMkI; controllers.core = engineMkI;
feedback_bitdepth = 11;
break; break;
case DEXED_ENGINE_OPL: case DEXED_ENGINE_OPL:
TRACE("DEXED_ENGINE_OPL:%d",DEXED_ENGINE_OPL); TRACE("DEXED_ENGINE_OPL:%d",DEXED_ENGINE_OPL);
controllers.core = engineOpl; controllers.core = engineOpl;
feedback_bitdepth = 11;
break; break;
default: default:
TRACE("DEXED_ENGINE_MODERN:%d",DEXED_ENGINE_MODERN); TRACE("DEXED_ENGINE_MODERN:%d",DEXED_ENGINE_MODERN);
controllers.core = engineMsfa; controllers.core = engineMsfa;
feedback_bitdepth = 8;
break; break;
} }
engineType = tp; engineType = tp;
panic(); panic();
controllers.refresh();
} }
bool Dexed::isMonoMode(void) { bool Dexed::isMonoMode(void) {

@ -38,6 +38,7 @@
struct ProcessorVoice { struct ProcessorVoice {
uint8_t midi_note; uint8_t midi_note;
uint8_t velocity;
bool keydown; bool keydown;
bool sustained; bool sustained;
bool live; bool live;
@ -106,7 +107,6 @@ class Dexed : public lvtk::Synth<DexedVoice, Dexed>
bool monoMode; bool monoMode;
bool refreshVoice; bool refreshVoice;
uint8_t engineType; uint8_t engineType;
uint8_t feedback_bitdepth;
PluginFx fx; PluginFx fx;
Lfo lfo; Lfo lfo;
FmCore* engineMsfa; FmCore* engineMsfa;

@ -35,33 +35,44 @@ class FmCore;
struct FmMod { struct FmMod {
uint8_t range; uint8_t range;
uint8_t target; bool pitch;
bool amp;
bool eg;
FmMod() { FmMod() {
range = 0; range = 0;
target= 0; pitch = false;
amp = false;
eg = false;
} }
public:
void setRange(uint8_t r) { void setRange(uint8_t r) {
//range = r < 0 && r > 127 ? 0 : r; range = r < 0 && r > 127 ? 0 : r;
range = r < 0 && r > 100 ? 0 : r;
} }
void setTarget(uint8_t assign) { 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 { class Controllers {
void applyMod(int cc, FmMod &mod) { void applyMod(int cc, FmMod &mod) {
uint8_t total = (int)(cc * mod.range * 0.01); float range = 0.01 * mod.range;
if(mod.target&1) // AMP uint8_t total = cc * range;
if(mod.amp)
amp_mod = max(amp_mod, total); amp_mod = max(amp_mod, total);
else if(mod.target&2) // PITCH
if(mod.pitch)
pitch_mod = max(pitch_mod, total); 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: public:
@ -99,9 +110,8 @@ public:
applyMod(foot_cc, foot); applyMod(foot_cc, foot);
applyMod(aftertouch_cc, at); 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; eg_mod = 127;
*/
TRACE("amp_mod %d pitch_mod %d", amp_mod, pitch_mod); TRACE("amp_mod %d pitch_mod %d", amp_mod, pitch_mod);
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2016 Pascal Gauthier. * Copyright 2016-2017 Pascal Gauthier.
* Copyright 2012 Google Inc. * Copyright 2012 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -23,6 +23,8 @@
#include "controllers.h" #include "controllers.h"
#include "dx7note.h" #include "dx7note.h"
const int FEEDBACK_BITDEPTH = 8;
int32_t midinote_to_logfreq(int midinote) { int32_t midinote_to_logfreq(int midinote) {
const int base = 50857777; // (1 << 24) * (log(440) / log(2) - 69/12) const int base = 50857777; // (1 << 24) * (log(440) / log(2) - 69/12)
const int step = (1 << 24) / 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[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 rates[4];
int levels[4]; int levels[4];
for (int op = 0; op < 6; op++) { 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); pitchenv_.set(rates, levels);
algorithm_ = patch[134]; algorithm_ = patch[134];
int feedback = patch[135]; 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; pitchmoddepth_ = (patch[139] * 165) >> 6;
pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; pitchmodsens_ = pitchmodsenstab[patch[143] & 7];
ampmoddepth_ = (patch[140] * 165) >> 6; 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); uint32_t amd_mod = max(amod_1, amod_2);
// ==== EG AMP MOD ==== // ==== 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); amd_mod = max((1<<24) - amod_3, amd_mod);
// ==== OP RENDER ==== // ==== OP RENDER ====
@ -247,7 +248,9 @@ void Dx7Note::keyup() {
pitchenv_.keydown(false); 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++) { for (int op = 0; op < 6; op++) {
int off = op * 21; int off = op * 21;
int mode = patch[off + 17]; 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]; int detune = patch[off + 20];
basepitch_[op] = osc_freq(midinote, mode, coarse, fine, detune); basepitch_[op] = osc_freq(midinote, mode, coarse, fine, detune);
ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3]; 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]; algorithm_ = patch[134];
int feedback = patch[135]; int feedback = patch[135];
fb_shift_ = feedback != 0 ? 11 - feedback : 16; fb_shift_ = feedback != 0 ? FEEDBACK_BITDEPTH - feedback : 16;
pitchmoddepth_ = (patch[139] * 165) >> 6; pitchmoddepth_ = (patch[139] * 165) >> 6;
pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; pitchmodsens_ = pitchmodsenstab[patch[143] & 7];
ampmoddepth_ = (patch[140] * 165) >> 6; ampmoddepth_ = (patch[140] * 165) >> 6;

@ -1,4 +1,5 @@
/* /*
* Copyright 2016-2017 Pascal Gauthier.
* Copyright 2012 Google Inc. * Copyright 2012 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -37,7 +38,7 @@ class Dx7Note {
public: public:
Dx7Note(); Dx7Note();
//void init(const uint8_t patch[156], int midinote, int velocity, int fb_depth); //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 // Note: this _adds_ to the buffer. Interesting question whether it's
// worth it... // worth it...
@ -52,7 +53,7 @@ public:
// keyup, that won't work. // keyup, that won't work.
// PG:add the update // 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 peekVoiceStatus(VoiceStatus &status);
void transferState(Dx7Note& src); void transferState(Dx7Note& src);
void transferSignal(Dx7Note &src); void transferSignal(Dx7Note &src);

@ -1,4 +1,5 @@
/* /*
* Copyright 2017 Pascal Gauthier.
* Copyright 2012 Google Inc. * Copyright 2012 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -23,6 +24,10 @@
uint32_t Env::sr_multiplier = (1<<24); 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) { void Env::init_sr(double sampleRate) {
sr_multiplier = (44100.0 / sampleRate) * (1<<24); sr_multiplier = (44100.0 / sampleRate) * (1<<24);
} }
@ -66,24 +71,11 @@ int32_t Env::getsample() {
void Env::keydown(bool d) { void Env::keydown(bool d) {
if (down_ != d) { if (down_ != d) {
down_ = d; down_ = d;
advance(d ? 0 : 3); 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;
} }
// 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) { int Env::scaleoutlevel(int outlevel) {
return outlevel >= 20 ? 28 + outlevel : levellut[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) { void Env::getPosition(char *step) {
*step = ix_; *step = ix_;
} }

@ -31,6 +31,9 @@ class Env {
void init(const int rates[4], const int levels[4], int outlevel, void init(const int rates[4], const int levels[4], int outlevel,
int rate_scaling); 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 // Result is in Q24/doubling log format. Also, result is subsampled
// for every N samples. // for every N samples.
// A couple more things need to happen for this to be used as a gain // A couple more things need to happen for this to be used as a gain
@ -40,7 +43,6 @@ class Env {
int32_t getsample(); int32_t getsample();
void keydown(bool down); void keydown(bool down);
void setparam(int param, int value);
static int scaleoutlevel(int outlevel); static int scaleoutlevel(int outlevel);
void getPosition(char *step); void getPosition(char *step);

Loading…
Cancel
Save