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
* 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;

@ -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

@ -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) {

@ -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<DexedVoice, Dexed>
bool monoMode;
bool refreshVoice;
uint8_t engineType;
uint8_t feedback_bitdepth;
PluginFx fx;
Lfo lfo;
FmCore* engineMsfa;

@ -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);
}

@ -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;

@ -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);

@ -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_;
}

@ -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);

Loading…
Cancel
Save