FIRST WORKING VERSION!
pull/4/head
Holger Wirtz 7 years ago
parent 4660200948
commit fd755727b5
  1. 25
      MicroDexed.ino
  2. 11
      dexed.cpp
  3. 3
      dexed.h
  4. 495
      dx7note.cpp
  5. 1
      synth.h

@ -4,6 +4,7 @@
#include "dexed.h" #include "dexed.h"
#define RATE 128 #define RATE 128
#define SAMPLERATE 44100
#define TEENSY 1 #define TEENSY 1
#define TEST_MIDI 1 #define TEST_MIDI 1
#define TEST_NOTE1 59 #define TEST_NOTE1 59
@ -18,11 +19,13 @@
// GUItool: begin automatically generated code // GUItool: begin automatically generated code
AudioPlayQueue queue1; //xy=266,484 AudioPlayQueue queue1; //xy=266,484
AudioEffectReverb reverb1; //xy=486,545 //AudioEffectReverb reverb1; //xy=486,545
AudioOutputI2S i2s1; //xy=739,486 AudioOutputI2S i2s1; //xy=739,486
AudioConnection patchCord1(queue1, reverb1); //AudioConnection patchCord1(queue1, reverb1);
AudioConnection patchCord2(reverb1, 0, i2s1, 0); //AudioConnection patchCord2(reverb1, 0, i2s1, 0);
AudioConnection patchCord3(reverb1, 0, i2s1, 1); //AudioConnection patchCord3(reverb1, 0, i2s1, 1);
AudioConnection patchCord2(queue1, 0, i2s1, 0);
AudioConnection patchCord3(queue1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=384,610 AudioControlSGTL5000 sgtl5000_1; //xy=384,610
// GUItool: end automatically generated code // GUItool: end automatically generated code
@ -40,7 +43,7 @@ AudioControlSGTL5000 sgtl5000_1; //xy=384,610
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI); MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
Dexed* dexed = new Dexed(RATE); Dexed* dexed = new Dexed(SAMPLERATE);
void setup() void setup()
{ {
@ -57,7 +60,7 @@ void setup()
AudioMemory(16); AudioMemory(16);
sgtl5000_1.enable(); sgtl5000_1.enable();
sgtl5000_1.volume(0.6); sgtl5000_1.volume(0.3);
// Initialize processor and memory measurements // Initialize processor and memory measurements
//AudioProcessorUsageMaxReset(); //AudioProcessorUsageMaxReset();
@ -82,7 +85,7 @@ void setup()
dexed->ProcessMidiMessage(0x90, TEST_NOTE2, 60); dexed->ProcessMidiMessage(0x90, TEST_NOTE2, 60);
#endif #endif
reverb1.reverbTime(5.0); //reverb1.reverbTime(5.0);
Serial.println("Go"); Serial.println("Go");
} }
@ -110,17 +113,15 @@ void loop()
// process midi->audio // process midi->audio
if (MIDI.read()) if (MIDI.read())
{ {
Serial.print("Type: "); /* Serial.print("Type: ");
Serial.print(MIDI.getType(), DEC); Serial.print(MIDI.getType(), DEC);
Serial.print(" Data1: "); Serial.print(" Data1: ");
Serial.print(MIDI.getData1(), DEC); Serial.print(MIDI.getData1(), DEC);
Serial.print(" Data2: "); Serial.print(" Data2: ");
Serial.println(MIDI.getData2(), DEC); Serial.println(MIDI.getData2(), DEC); */
dexed->ProcessMidiMessage(MIDI.getType(), MIDI.getData1(), MIDI.getData2()); dexed->ProcessMidiMessage(MIDI.getType(), MIDI.getData1(), MIDI.getData2());
} }
else dexed->GetSamples(RATE, audio_buffer);
dexed->GetSamples(RATE, audio_buffer);
/* uint8_t i = 0; /* uint8_t i = 0;
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)

@ -31,7 +31,7 @@
#include <unistd.h> #include <unistd.h>
#include <limits.h> #include <limits.h>
Dexed::Dexed(uint8_t rate) Dexed::Dexed(int rate)
{ {
uint8_t i; uint8_t i;
@ -177,12 +177,11 @@ void Dexed::GetSamples(uint16_t n_samples, int16_t* buffer)
voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers); voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers);
for (uint8_t j = 0; j < _N_; ++j) { for (uint8_t j = 0; j < _N_; ++j) {
int32_t val = audiobuf.get()[j]; int32_t val = audiobuf.get()[j];
//val = val >> 4; val = val >> 4;
int32_t clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9; int32_t clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9;
/* float f = static_cast<float>(clip_val >> 1) / static_cast<float>(0x8000); float f = static_cast<float>(clip_val >> 1) / static_cast<float>(0x8000);
if (f > 1) f = 1; if (f > 1) f = 1;
if (f < -1) f = -1; if (f < -1) f = -1;
sumbuf[j] += f;*/
sumbuf[j] += clip_val; sumbuf[j] += clip_val;
audiobuf.get()[j] = 0; audiobuf.get()[j] = 0;
} }

@ -55,7 +55,7 @@ enum DexedEngineResolution {
class Dexed class Dexed
{ {
public: public:
Dexed(uint8_t rate); Dexed(int rate);
~Dexed(); ~Dexed();
void activate(void); void activate(void);
void deactivate(void); void deactivate(void);
@ -96,7 +96,6 @@ class Dexed
uint32_t extra_buf_size_; uint32_t extra_buf_size_;
private: private:
uint16_t _rate;
uint8_t _k_rate_counter; uint8_t _k_rate_counter;
uint8_t _param_change_counter; uint8_t _param_change_counter;

@ -1,19 +1,19 @@
/* /*
* Copyright 2016-2017 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");
* you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
* You may obtain a copy of the License at You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ */
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
@ -26,307 +26,306 @@
const int FEEDBACK_BITDEPTH = 8; 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 int32_t base = 50857777; // (1 << 24) * (log(440) / log(2) - 69/12)
const int step = (1 << 24) / 12; const int32_t step = (1 << 24) / 12;
return base + step * midinote; return base + step * midinote;
} }
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,
65546747, 67108864, 68576247, 69959732, 71268397, 72509921, 73690858, 65546747, 67108864, 68576247, 69959732, 71268397, 72509921, 73690858,
74816848, 75892776, 76922906, 77910978, 78860292, 79773775, 80654032, 74816848, 75892776, 76922906, 77910978, 78860292, 79773775, 80654032,
81503396, 82323963, 83117622 81503396, 82323963, 83117622
}; };
int32_t osc_freq(int midinote, int mode, int coarse, int fine, int detune) { int32_t osc_freq(int midinote, int mode, int coarse, int fine, int detune) {
// TODO: pitch randomization // TODO: pitch randomization
int32_t logfreq; int32_t logfreq;
if (mode == 0) { if (mode == 0) {
logfreq = midinote_to_logfreq(midinote); logfreq = midinote_to_logfreq(midinote);
// could use more precision, closer enough for now. those numbers comes from my DX7
// could use more precision, closer enough for now. those numbers comes from my DX7 double detuneRatio = 0.0209 * exp(-0.396 * (((float)logfreq) / (1 << 24))) / 7;
double detuneRatio = 0.0209 * exp(-0.396 * (((float)logfreq)/(1<<24))) / 7; logfreq += detuneRatio * logfreq * (detune - 7);
logfreq += detuneRatio * logfreq * (detune - 7);
logfreq += coarsemul[coarse & 31];
logfreq += coarsemul[coarse & 31]; if (fine) {
if (fine) { // (1 << 24) / log(2)
// (1 << 24) / log(2) logfreq += (int32_t)floor(24204406.323123 * log(1 + 0.01 * fine) + 0.5);
logfreq += (int32_t)floor(24204406.323123 * log(1 + 0.01 * fine) + 0.5);
}
// // This was measured at 7.213Hz per count at 9600Hz, but the exact
// // value is somewhat dependent on midinote. Close enough for now.
// //logfreq += 12606 * (detune -7);
} else {
// ((1 << 24) * log(10) / log(2) * .01) << 3
logfreq = (4458616 * ((coarse & 3) * 100 + fine)) >> 3;
logfreq += detune > 7 ? 13457 * (detune - 7) : 0;
} }
return logfreq;
// // This was measured at 7.213Hz per count at 9600Hz, but the exact
// // value is somewhat dependent on midinote. Close enough for now.
// //logfreq += 12606 * (detune -7);
} else {
// ((1 << 24) * log(10) / log(2) * .01) << 3
logfreq = (4458616 * ((coarse & 3) * 100 + fine)) >> 3;
logfreq += detune > 7 ? 13457 * (detune - 7) : 0;
}
return logfreq;
} }
const uint8_t velocity_data[64] = { const uint8_t velocity_data[64] = {
0, 70, 86, 97, 106, 114, 121, 126, 132, 138, 142, 148, 152, 156, 160, 163, 0, 70, 86, 97, 106, 114, 121, 126, 132, 138, 142, 148, 152, 156, 160, 163,
166, 170, 173, 174, 178, 181, 184, 186, 189, 190, 194, 196, 198, 200, 202, 166, 170, 173, 174, 178, 181, 184, 186, 189, 190, 194, 196, 198, 200, 202,
205, 206, 209, 211, 214, 216, 218, 220, 222, 224, 225, 227, 229, 230, 232, 205, 206, 209, 211, 214, 216, 218, 220, 222, 224, 225, 227, 229, 230, 232,
233, 235, 237, 238, 240, 241, 242, 243, 244, 246, 246, 248, 249, 250, 251, 233, 235, 237, 238, 240, 241, 242, 243, 244, 246, 246, 248, 249, 250, 251,
252, 253, 254 252, 253, 254
}; };
// See "velocity" section of notes. Returns velocity delta in microsteps. // See "velocity" section of notes. Returns velocity delta in microsteps.
int ScaleVelocity(int velocity, int sensitivity) { int ScaleVelocity(int velocity, int sensitivity) {
int clamped_vel = max(0, min(127, velocity)); int clamped_vel = max(0, min(127, velocity));
int vel_value = velocity_data[clamped_vel >> 1] - 239; int vel_value = velocity_data[clamped_vel >> 1] - 239;
int scaled_vel = ((sensitivity * vel_value + 7) >> 3) << 4; int scaled_vel = ((sensitivity * vel_value + 7) >> 3) << 4;
return scaled_vel; return scaled_vel;
} }
int ScaleRate(int midinote, int sensitivity) { int ScaleRate(int midinote, int sensitivity) {
int x = min(31, max(0, midinote / 3 - 7)); int x = min(31, max(0, midinote / 3 - 7));
int qratedelta = (sensitivity * x) >> 3; int qratedelta = (sensitivity * x) >> 3;
#ifdef SUPER_PRECISE #ifdef SUPER_PRECISE
int rem = x & 7; int rem = x & 7;
if (sensitivity == 3 && rem == 3) { if (sensitivity == 3 && rem == 3) {
qratedelta -= 1; qratedelta -= 1;
} else if (sensitivity == 7 && rem > 0 && rem < 4) { } else if (sensitivity == 7 && rem > 0 && rem < 4) {
qratedelta += 1; qratedelta += 1;
} }
#endif #endif
return qratedelta; return qratedelta;
} }
const uint8_t exp_scale_data[] = { const uint8_t exp_scale_data[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 14, 16, 19, 23, 27, 33, 39, 47, 56, 66, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 14, 16, 19, 23, 27, 33, 39, 47, 56, 66,
80, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 250 80, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 250
}; };
int ScaleCurve(int group, int depth, int curve) { int ScaleCurve(int group, int depth, int curve) {
int scale; int scale;
if (curve == 0 || curve == 3) { if (curve == 0 || curve == 3) {
// linear // linear
scale = (group * depth * 329) >> 12; scale = (group * depth * 329) >> 12;
} else { } else {
// exponential // exponential
int n_scale_data = sizeof(exp_scale_data); int n_scale_data = sizeof(exp_scale_data);
int raw_exp = exp_scale_data[min(group, n_scale_data - 1)]; int raw_exp = exp_scale_data[min(group, n_scale_data - 1)];
scale = (raw_exp * depth * 329) >> 15; scale = (raw_exp * depth * 329) >> 15;
} }
if (curve < 2) { if (curve < 2) {
scale = -scale; scale = -scale;
} }
return scale; return scale;
} }
int ScaleLevel(int midinote, int break_pt, int left_depth, int right_depth, int ScaleLevel(int midinote, int break_pt, int left_depth, int right_depth,
int left_curve, int right_curve) { int left_curve, int right_curve) {
int offset = midinote - break_pt - 17; int offset = midinote - break_pt - 17;
if (offset >= 0) { if (offset >= 0) {
return ScaleCurve((offset+1) / 3, right_depth, right_curve); return ScaleCurve((offset + 1) / 3, right_depth, right_curve);
} else { } else {
return ScaleCurve(-(offset-1) / 3, left_depth, left_curve); return ScaleCurve(-(offset - 1) / 3, left_depth, left_curve);
} }
} }
static const uint8_t pitchmodsenstab[] = { static const uint8_t pitchmodsenstab[] = {
0, 10, 20, 33, 55, 92, 153, 255 0, 10, 20, 33, 55, 92, 153, 255
}; };
// 0, 66, 109, 255 // 0, 66, 109, 255
static const uint32_t ampmodsenstab[] = { static const uint32_t ampmodsenstab[] = {
0, 4342338, 7171437, 16777216 0, 4342338, 7171437, 16777216
}; };
Dx7Note::Dx7Note() { Dx7Note::Dx7Note() {
for(int op=0;op<6;op++) { for (int op = 0; op < 6; op++) {
params_[op].phase = 0; params_[op].phase = 0;
params_[op].gain_out = 0; params_[op].gain_out = 0;
} }
} }
//void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity) { //void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity) {
void Dx7Note::init(const uint8_t patch[173], int midinote, int velocity) { void Dx7Note::init(const uint8_t patch[173], 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++) {
int off = op * 21; int off = op * 21;
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].init(rates, levels, outlevel, rate_scaling);
int mode = patch[off + 17];
int coarse = patch[off + 18];
int fine = patch[off + 19];
int detune = patch[off + 20];
int32_t freq = osc_freq(midinote, mode, coarse, fine, detune);
opMode[op] = mode;
basepitch_[op] = freq;
ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3];
}
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
rates[i] = patch[126 + i]; rates[i] = patch[off + i];
levels[i] = patch[130 + i]; levels[i] = patch[off + 4 + i];
} }
pitchenv_.set(rates, levels); int outlevel = patch[off + 16];
algorithm_ = patch[134]; outlevel = Env::scaleoutlevel(outlevel);
int feedback = patch[135]; int level_scaling = ScaleLevel(midinote, patch[off + 8], patch[off + 9],
fb_shift_ = feedback != 0 ? FEEDBACK_BITDEPTH - feedback : 16; patch[off + 10], patch[off + 11], patch[off + 12]);
pitchmoddepth_ = (patch[139] * 165) >> 6; outlevel += level_scaling;
pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; outlevel = min(127, outlevel);
ampmoddepth_ = (patch[140] * 165) >> 6; outlevel = outlevel << 5;
outlevel += ScaleVelocity(velocity, patch[off + 15]);
outlevel = max(0, outlevel);
int rate_scaling = ScaleRate(midinote, patch[off + 13]);
env_[op].init(rates, levels, outlevel, rate_scaling);
int mode = patch[off + 17];
int coarse = patch[off + 18];
int fine = patch[off + 19];
int detune = patch[off + 20];
int32_t freq = osc_freq(midinote, mode, coarse, fine, detune);
opMode[op] = mode;
basepitch_[op] = freq;
ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3];
}
for (int i = 0; i < 4; i++) {
rates[i] = patch[126 + i];
levels[i] = patch[130 + i];
}
pitchenv_.set(rates, levels);
algorithm_ = patch[134];
int feedback = patch[135];
fb_shift_ = feedback != 0 ? FEEDBACK_BITDEPTH - feedback : 16;
pitchmoddepth_ = (patch[139] * 165) >> 6;
pitchmodsens_ = pitchmodsenstab[patch[143] & 7];
ampmoddepth_ = (patch[140] * 165) >> 6;
} }
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) {
// ==== PITCH ==== // ==== PITCH ====
uint32_t pmd = pitchmoddepth_ * lfo_delay; // Q32 uint32_t pmd = pitchmoddepth_ * lfo_delay; // Q32
int32_t senslfo = pitchmodsens_ * (lfo_val - (1 << 23)); int32_t senslfo = pitchmodsens_ * (lfo_val - (1 << 23));
int32_t pmod_1 = (((int64_t) pmd) * (int64_t) senslfo) >> 39; int32_t pmod_1 = (((int64_t) pmd) * (int64_t) senslfo) >> 39;
pmod_1 = abs(pmod_1); pmod_1 = abs(pmod_1);
int32_t pmod_2 = (int32_t)(((int64_t)ctrls->pitch_mod * (int64_t)senslfo) >> 14); int32_t pmod_2 = (int32_t)(((int64_t)ctrls->pitch_mod * (int64_t)senslfo) >> 14);
pmod_2 = abs(pmod_2); pmod_2 = abs(pmod_2);
int32_t pitch_mod = max(pmod_1, pmod_2); int32_t pitch_mod = max(pmod_1, pmod_2);
pitch_mod = pitchenv_.getsample() + (pitch_mod * (senslfo < 0 ? -1 : 1)); pitch_mod = pitchenv_.getsample() + (pitch_mod * (senslfo < 0 ? -1 : 1));
// ---- PITCH BEND ---- // ---- PITCH BEND ----
int pitchbend = ctrls->values_[kControllerPitch]; int pitchbend = ctrls->values_[kControllerPitch];
int32_t pb = (pitchbend - 0x2000); int32_t pb = (pitchbend - 0x2000);
if (pb != 0) { if (pb != 0) {
if (ctrls->values_[kControllerPitchStep] == 0) { if (ctrls->values_[kControllerPitchStep] == 0) {
pb = ((float) (pb << 11)) * ((float) ctrls->values_[kControllerPitchRange]) / 12.0; pb = ((float) (pb << 11)) * ((float) ctrls->values_[kControllerPitchRange]) / 12.0;
} else { } else {
int stp = 12 / ctrls->values_[kControllerPitchStep]; int stp = 12 / ctrls->values_[kControllerPitchStep];
pb = pb * stp / 8191; pb = pb * stp / 8191;
pb = (pb * (8191 / stp)) << 11; pb = (pb * (8191 / stp)) << 11;
}
} }
int32_t pitch_base = pb + ctrls->masterTune; }
pitch_mod += pitch_base; int32_t pitch_base = pb + ctrls->masterTune;
pitch_mod += pitch_base;
// ==== AMP MOD ====
lfo_val = (1<<24) - lfo_val; // ==== AMP MOD ====
uint32_t amod_1 = (uint32_t)(((int64_t) ampmoddepth_ * (int64_t) lfo_delay) >> 8); // Q24 :D lfo_val = (1 << 24) - lfo_val;
amod_1 = (uint32_t)(((int64_t) amod_1 * (int64_t) lfo_val) >> 24); uint32_t amod_1 = (uint32_t)(((int64_t) ampmoddepth_ * (int64_t) lfo_delay) >> 8); // Q24 :D
uint32_t amod_2 = (uint32_t)(((int64_t) ctrls->amp_mod * (int64_t) lfo_val) >> 7); // Q?? :| amod_1 = (uint32_t)(((int64_t) amod_1 * (int64_t) lfo_val) >> 24);
uint32_t amd_mod = max(amod_1, amod_2); uint32_t amod_2 = (uint32_t)(((int64_t) ctrls->amp_mod * (int64_t) lfo_val) >> 7); // Q?? :|
uint32_t amd_mod = max(amod_1, amod_2);
// ==== EG AMP MOD ====
uint32_t amod_3 = (ctrls->eg_mod+1) << 17; // ==== EG AMP MOD ====
amd_mod = max((1<<24) - amod_3, amd_mod); uint32_t amod_3 = (ctrls->eg_mod + 1) << 17;
amd_mod = max((1 << 24) - amod_3, amd_mod);
// ==== OP RENDER ====
for (int op = 0; op < 6; op++) { // ==== OP RENDER ====
// if ( ctrls->opSwitch[op] == '0' ) { for (int op = 0; op < 6; op++) {
if (!(ctrls->opSwitch & (1<<op))) { // if ( ctrls->opSwitch[op] == '0' ) {
env_[op].getsample(); // advance the envelop even if it is not playing if (!(ctrls->opSwitch & (1 << op))) {
params_[op].level_in = 0; env_[op].getsample(); // advance the envelop even if it is not playing
} else { params_[op].level_in = 0;
//int32_t gain = pow(2, 10 + level * (1.0 / (1 << 24))); } else {
//int32_t gain = pow(2, 10 + level * (1.0 / (1 << 24)));
if ( opMode[op] )
params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_base); if ( opMode[op] )
else params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_base);
params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_mod); else
params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_mod);
int32_t level = env_[op].getsample();
if (ampmodsens_[op] != 0) { int32_t level = env_[op].getsample();
uint32_t sensamp = (uint32_t)(((uint64_t) amd_mod) * ((uint64_t) ampmodsens_[op]) >> 24); if (ampmodsens_[op] != 0) {
uint32_t sensamp = (uint32_t)(((uint64_t) amd_mod) * ((uint64_t) ampmodsens_[op]) >> 24);
// TODO: mehhh.. this needs some real tuning.
uint32_t pt = exp(((float)sensamp)/262144 * 0.07 + 12.2); // TODO: mehhh.. this needs some real tuning.
uint32_t ldiff = (uint32_t)(((uint64_t)level) * (((uint64_t)pt<<4)) >> 28); uint32_t pt = exp(((float)sensamp) / 262144 * 0.07 + 12.2);
level -= ldiff; uint32_t ldiff = (uint32_t)(((uint64_t)level) * (((uint64_t)pt << 4)) >> 28);
} level -= ldiff;
params_[op].level_in = level; }
} params_[op].level_in = level;
} }
ctrls->core->render(buf, params_, algorithm_, fb_buf_, fb_shift_); }
ctrls->core->render(buf, params_, algorithm_, fb_buf_, fb_shift_);
} }
void Dx7Note::keyup() { void Dx7Note::keyup() {
for (int op = 0; op < 6; op++) { for (int op = 0; op < 6; op++) {
env_[op].keydown(false); env_[op].keydown(false);
} }
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 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++) {
int off = op * 21; int off = op * 21;
int mode = patch[off + 17]; int mode = patch[off + 17];
int coarse = patch[off + 18]; int coarse = patch[off + 18];
int fine = patch[off + 19]; int fine = patch[off + 19];
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];
opMode[op] = mode; opMode[op] = mode;
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];
}
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 outlevel = patch[off + 16];
int feedback = patch[135]; outlevel = Env::scaleoutlevel(outlevel);
fb_shift_ = feedback != 0 ? FEEDBACK_BITDEPTH - feedback : 16; int level_scaling = ScaleLevel(midinote, patch[off + 8], patch[off + 9],
pitchmoddepth_ = (patch[139] * 165) >> 6; patch[off + 10], patch[off + 11], patch[off + 12]);
pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; outlevel += level_scaling;
ampmoddepth_ = (patch[140] * 165) >> 6; 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 ? FEEDBACK_BITDEPTH - feedback : 16;
pitchmoddepth_ = (patch[139] * 165) >> 6;
pitchmodsens_ = pitchmodsenstab[patch[143] & 7];
ampmoddepth_ = (patch[140] * 165) >> 6;
} }
void Dx7Note::peekVoiceStatus(VoiceStatus &status) { void Dx7Note::peekVoiceStatus(VoiceStatus &status) {
for(int i=0;i<6;i++) { for (int i = 0; i < 6; i++) {
status.amp[i] = Exp2::lookup(params_[i].level_in - (14 * (1 << 24))); status.amp[i] = Exp2::lookup(params_[i].level_in - (14 * (1 << 24)));
env_[i].getPosition(&status.ampStep[i]); env_[i].getPosition(&status.ampStep[i]);
} }
pitchenv_.getPosition(&status.pitchStep); pitchenv_.getPosition(&status.pitchStep);
} }
/** /**
* Used in monophonic mode to transfert voice state from different notes Used in monophonic mode to transfert voice state from different notes
*/ */
void Dx7Note::transferState(Dx7Note &src) { void Dx7Note::transferState(Dx7Note &src) {
for (int i=0;i<6;i++) { for (int i = 0; i < 6; i++) {
env_[i].transfer(src.env_[i]); env_[i].transfer(src.env_[i]);
params_[i].gain_out = src.params_[i].gain_out; params_[i].gain_out = src.params_[i].gain_out;
params_[i].phase = src.params_[i].phase; params_[i].phase = src.params_[i].phase;
} }
} }
void Dx7Note::transferSignal(Dx7Note &src) { void Dx7Note::transferSignal(Dx7Note &src) {
for (int i=0;i<6;i++) { for (int i = 0; i < 6; i++) {
params_[i].gain_out = src.params_[i].gain_out; params_[i].gain_out = src.params_[i].gain_out;
params_[i].phase = src.params_[i].phase; params_[i].phase = src.params_[i].phase;
} }
} }
void Dx7Note::oscSync() { void Dx7Note::oscSync() {
for (int i=0;i<6;i++) { for (int i = 0; i < 6; i++) {
params_[i].gain_out = 0; params_[i].gain_out = 0;
params_[i].phase = 0; params_[i].phase = 0;
} }
} }

@ -18,6 +18,7 @@
#define __SYNTH_H #define __SYNTH_H
#include <Arduino.h> #include <Arduino.h>
#define SUPER_PRECISE
// This IS not be present on MSVC. // This IS not be present on MSVC.
// See http://stackoverflow.com/questions/126279/c99-stdint-h-header-and-ms-visual-studio // See http://stackoverflow.com/questions/126279/c99-stdint-h-header-and-ms-visual-studio

Loading…
Cancel
Save