Added portamento patch.

dev
Holger Wirtz 3 years ago
parent 6a3ad57f1f
commit 9b2b99e189
  1. 22
      src/dexed.cpp
  2. 2
      src/dexed.h
  3. 55
      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]);
}
lastKeyDown = -1;
max_notes=16;
currentNote = 0;
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.masterTune=0;
controllers.opSwitch=0x3f; // enable all operators
//controllers.opSwitch=0x00;
controllers.portamento_enable_cc = false;
controllers.portamento_cc = 0;
bufsize_=256;
@ -447,7 +449,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, voices[i].velocity);
voices[i].dx7_note->update(data, voices[i].midi_note, voices[i].velocity, voices[i].porta);
}
lfo.reset(data+137);
refreshVoice = false;
@ -687,6 +689,9 @@ bool Dexed::ProcessMidiMessage(const uint8_t *buf, uint32_t buf_size) {
controllers.foot_cc = value;
controllers.refresh();
break;
case 5:
controllers.portamento_cc = value;
break;
case 64:
TRACE("MIDI sustain event: %d %d",ctrl,value);
sustain = value > 63;
@ -699,6 +704,9 @@ bool Dexed::ProcessMidiMessage(const uint8_t *buf, uint32_t buf_size) {
}
}
break;
case 65:
controllers.portamento_enable_cc = value >= 64;
break;
case 120:
TRACE("MIDI all-sound-off: %d %d",ctrl,value);
panic();
@ -770,6 +778,13 @@ TRACE("pitch=%d, velo=%d\n",pitch,velo);
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 keydown_counter=0;
@ -778,9 +793,10 @@ TRACE("pitch=%d, velo=%d\n",pitch,velo);
currentNote = (note + 1) % max_notes;
voices[note].midi_note = pitch;
voices[note].velocity = velo;
voices[note].porta = porta;
voices[note].sustained = sustain;
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] )
voices[note].dx7_note->oscSync();
break;

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

@ -19,6 +19,7 @@
#include <stdlib.h>
#include "synth.h"
#include "freqlut.h"
#include "porta.h"
#include "exp2.h"
#include "controllers.h"
#include "dx7note.h"
@ -31,6 +32,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,
@ -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 levels[4];
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;
basepitch_[op] = freq;
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++) {
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;
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) {
@ -233,10 +246,18 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Co
} else {
//int32_t gain = pow(2, 10 + level * (1.0 / (1 << 24)));
int32_t basepitch = basepitch_[op];
if ( opMode[op] )
params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_base);
else
params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_mod);
params_[op].freq = Freqlut::lookup(basepitch + pitch_base);
else {
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();
if (ampmodsens_[op] != 0) {
@ -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;
}
}
// ==== 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_);
}
@ -260,7 +300,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++) {
@ -273,6 +313,9 @@ void Dx7Note::update(const uint8_t patch[156], int midinote, int velocity) {
ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3];
opMode[op] = mode;
if (porta >= 0)
porta_curpitch_[op] = basepitch_[op];
for (int i = 0; i < 4; i++) {
rates[i] = patch[off + 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;
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) {

@ -37,7 +37,7 @@ struct VoiceStatus {
class Dx7Note {
public:
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
// worth it...
@ -52,7 +52,7 @@ public:
// 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);
@ -72,6 +72,10 @@ private:
int algorithm_;
int pitchmoddepth_;
int pitchmodsens_;
int porta_rateindex_;
int porta_gliss_;
int32_t porta_curpitch_[6];
};
#endif // SYNTH_DX7NOTE_H_

Loading…
Cancel
Save