Added portamento patch.

dev
Holger Wirtz 3 years ago
parent 6a3ad57f1f
commit 9b2b99e189
  1. 24
      src/dexed.cpp
  2. 2
      src/dexed.h
  3. 61
      src/msfa/dx7note.cc
  4. 8
      src/msfa/dx7note.h

@ -85,6 +85,7 @@ Dexed::Dexed(double rate) : lvtk::Synth<DexedVoice, Dexed>(p_n_ports, p_midi_in)
TRACE("%d->%f",i,data_float[i]); TRACE("%d->%f",i,data_float[i]);
} }
lastKeyDown = -1;
max_notes=16; max_notes=16;
currentNote = 0; currentNote = 0;
controllers.values_[kControllerPitch] = 0x2000; controllers.values_[kControllerPitch] = 0x2000;
@ -96,7 +97,8 @@ Dexed::Dexed(double rate) : lvtk::Synth<DexedVoice, Dexed>(p_n_ports, p_midi_in)
controllers.aftertouch_cc = 0; controllers.aftertouch_cc = 0;
controllers.masterTune=0; controllers.masterTune=0;
controllers.opSwitch=0x3f; // enable all operators controllers.opSwitch=0x3f; // enable all operators
//controllers.opSwitch=0x00; controllers.portamento_enable_cc = false;
controllers.portamento_cc = 0;
bufsize_=256; bufsize_=256;
@ -447,7 +449,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, voices[i].velocity); voices[i].dx7_note->update(data, voices[i].midi_note, voices[i].velocity, voices[i].porta);
} }
lfo.reset(data+137); lfo.reset(data+137);
refreshVoice = false; refreshVoice = false;
@ -687,6 +689,9 @@ bool Dexed::ProcessMidiMessage(const uint8_t *buf, uint32_t buf_size) {
controllers.foot_cc = value; controllers.foot_cc = value;
controllers.refresh(); controllers.refresh();
break; break;
case 5:
controllers.portamento_cc = value;
break;
case 64: case 64:
TRACE("MIDI sustain event: %d %d",ctrl,value); TRACE("MIDI sustain event: %d %d",ctrl,value);
sustain = value > 63; sustain = value > 63;
@ -699,6 +704,9 @@ bool Dexed::ProcessMidiMessage(const uint8_t *buf, uint32_t buf_size) {
} }
} }
break; break;
case 65:
controllers.portamento_enable_cc = value >= 64;
break;
case 120: case 120:
TRACE("MIDI all-sound-off: %d %d",ctrl,value); TRACE("MIDI all-sound-off: %d %d",ctrl,value);
panic(); panic();
@ -769,7 +777,14 @@ TRACE("pitch=%d, velo=%d\n",pitch,velo);
} }
pitch += data[144] - 24; pitch += data[144] - 24;
int previousKeyDown = lastKeyDown;
lastKeyDown = pitch;
int porta = -1;
if ( controllers.portamento_enable_cc && previousKeyDown >= 0 )
porta = controllers.portamento_cc;
uint8_t note = currentNote; uint8_t note = currentNote;
uint8_t keydown_counter=0; uint8_t keydown_counter=0;
@ -778,9 +793,10 @@ TRACE("pitch=%d, velo=%d\n",pitch,velo);
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].velocity = velo;
voices[note].porta = porta;
voices[note].sustained = sustain; voices[note].sustained = sustain;
voices[note].keydown = true; voices[note].keydown = true;
voices[note].dx7_note->init(data, pitch, velo); voices[note].dx7_note->init(data, pitch, velo, previousKeyDown, porta);
if ( data[136] ) if ( data[136] )
voices[note].dx7_note->oscSync(); voices[note].dx7_note->oscSync();
break; break;

@ -39,6 +39,7 @@
struct ProcessorVoice { struct ProcessorVoice {
uint8_t midi_note; uint8_t midi_note;
uint8_t velocity; uint8_t velocity;
int porta;
bool keydown; bool keydown;
bool sustained; bool sustained;
bool live; bool live;
@ -121,6 +122,7 @@ class Dexed : public lvtk::Synth<DexedVoice, Dexed>
uint32_t bufsize_; uint32_t bufsize_;
float extra_buf_[N]; float extra_buf_[N];
uint32_t extra_buf_size_; uint32_t extra_buf_size_;
int lastKeyDown;
private: private:
double _rate; double _rate;

@ -19,6 +19,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "synth.h" #include "synth.h"
#include "freqlut.h" #include "freqlut.h"
#include "porta.h"
#include "exp2.h" #include "exp2.h"
#include "controllers.h" #include "controllers.h"
#include "dx7note.h" #include "dx7note.h"
@ -31,6 +32,13 @@ int32_t midinote_to_logfreq(int midinote) {
return base + step * 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[] = { const int32_t coarsemul[] = {
-16777216, 0, 16777216, 26591258, 33554432, 38955489, 43368474, 47099600, -16777216, 0, 16777216, 26591258, 33554432, 38955489, 43368474, 47099600,
50331648, 53182516, 55732705, 58039632, 60145690, 62083076, 63876816, 50331648, 53182516, 55732705, 58039632, 60145690, 62083076, 63876816,
@ -144,7 +152,7 @@ Dx7Note::Dx7Note() {
} }
} }
void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity) { void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity, int srcnote, int porta) {
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,6 +181,9 @@ void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity) {
opMode[op] = mode; opMode[op] = mode;
basepitch_[op] = freq; basepitch_[op] = freq;
ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3]; ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3];
if (porta >= 0)
porta_curpitch_[op] = osc_freq(srcnote, mode, coarse, fine, detune);
} }
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
rates[i] = patch[126 + i]; rates[i] = patch[126 + i];
@ -185,6 +196,8 @@ void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity) {
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;
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) { void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Controllers *ctrls) {
@ -232,12 +245,20 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Co
params_[op].level_in = 0; params_[op].level_in = 0;
} else { } else {
//int32_t gain = pow(2, 10 + level * (1.0 / (1 << 24))); //int32_t gain = pow(2, 10 + level * (1.0 / (1 << 24)));
int32_t basepitch = basepitch_[op];
if ( opMode[op] ) if ( opMode[op] )
params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_base); params_[op].freq = Freqlut::lookup(basepitch + pitch_base);
else else {
params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_mod); if ( porta_rateindex_ >= 0 ) {
basepitch = porta_curpitch_[op];
if ( porta_gliss_ )
basepitch = logfreq_round2semi(basepitch);
}
params_[op].freq = Freqlut::lookup(basepitch + pitch_mod);
}
int32_t level = env_[op].getsample(); int32_t level = env_[op].getsample();
if (ampmodsens_[op] != 0) { if (ampmodsens_[op] != 0) {
uint32_t sensamp = (uint32_t)(((uint64_t) amd_mod) * ((uint64_t) ampmodsens_[op]) >> 24); uint32_t sensamp = (uint32_t)(((uint64_t) amd_mod) * ((uint64_t) ampmodsens_[op]) >> 24);
@ -250,6 +271,25 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Co
params_[op].level_in = level; params_[op].level_in = level;
} }
} }
// ==== PORTAMENTO ====
int porta = porta_rateindex_;
if ( porta >= 0 ) {
int32_t rate = Porta::rates[porta];
for (int op = 0; op < 6; op++) {
int32_t cur = porta_curpitch_[op];
int32_t dst = basepitch_[op];
bool going_up = cur < dst;
int32_t newpitch = cur + (going_up ? +rate : -rate);
if ( going_up ? (cur > dst) : (cur < dst) )
newpitch = dst;
porta_curpitch_[op] = newpitch;
}
}
ctrls->core->render(buf, params_, algorithm_, fb_buf_, fb_shift_); ctrls->core->render(buf, params_, algorithm_, fb_buf_, fb_shift_);
} }
@ -260,7 +300,7 @@ void Dx7Note::keyup() {
pitchenv_.keydown(false); 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 rates[4];
int levels[4]; int levels[4];
for (int op = 0; op < 6; op++) { for (int op = 0; op < 6; op++) {
@ -272,7 +312,10 @@ void Dx7Note::update(const uint8_t patch[156], int midinote, int velocity) {
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];
opMode[op] = mode; opMode[op] = mode;
if (porta >= 0)
porta_curpitch_[op] = basepitch_[op];
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
rates[i] = patch[off + i]; rates[i] = patch[off + i];
levels[i] = patch[off + 4 + i]; levels[i] = patch[off + 4 + i];
@ -295,6 +338,8 @@ void Dx7Note::update(const uint8_t patch[156], int midinote, int velocity) {
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;
porta_rateindex_ = (porta < 128) ? porta : 127;
porta_gliss_ = patch[68];
} }
void Dx7Note::peekVoiceStatus(VoiceStatus &status) { void Dx7Note::peekVoiceStatus(VoiceStatus &status) {

@ -37,7 +37,7 @@ struct VoiceStatus {
class Dx7Note { class Dx7Note {
public: public:
Dx7Note(); Dx7Note();
void init(const uint8_t patch[156], int midinote, int velocity); void init(const uint8_t patch[156], int midinote, int velocity, int srcnote, int porta);
// 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 +52,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 velocity); void update(const uint8_t patch[156], int midinote, int velocity, int porta);
void peekVoiceStatus(VoiceStatus &status); void peekVoiceStatus(VoiceStatus &status);
void transferState(Dx7Note& src); void transferState(Dx7Note& src);
void transferSignal(Dx7Note &src); void transferSignal(Dx7Note &src);
@ -72,6 +72,10 @@ private:
int algorithm_; int algorithm_;
int pitchmoddepth_; int pitchmoddepth_;
int pitchmodsens_; int pitchmodsens_;
int porta_rateindex_;
int porta_gliss_;
int32_t porta_curpitch_[6];
}; };
#endif // SYNTH_DX7NOTE_H_ #endif // SYNTH_DX7NOTE_H_

Loading…
Cancel
Save