diff --git a/MicroDexed.ino b/MicroDexed.ino index afdf8b2..97268fa 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -4,6 +4,7 @@ #include "dexed.h" #define RATE 128 +#define SAMPLERATE 44100 #define TEENSY 1 #define TEST_MIDI 1 #define TEST_NOTE1 59 @@ -18,11 +19,13 @@ // GUItool: begin automatically generated code AudioPlayQueue queue1; //xy=266,484 -AudioEffectReverb reverb1; //xy=486,545 +//AudioEffectReverb reverb1; //xy=486,545 AudioOutputI2S i2s1; //xy=739,486 -AudioConnection patchCord1(queue1, reverb1); -AudioConnection patchCord2(reverb1, 0, i2s1, 0); -AudioConnection patchCord3(reverb1, 0, i2s1, 1); +//AudioConnection patchCord1(queue1, reverb1); +//AudioConnection patchCord2(reverb1, 0, i2s1, 0); +//AudioConnection patchCord3(reverb1, 0, i2s1, 1); +AudioConnection patchCord2(queue1, 0, i2s1, 0); +AudioConnection patchCord3(queue1, 0, i2s1, 1); AudioControlSGTL5000 sgtl5000_1; //xy=384,610 // GUItool: end automatically generated code @@ -40,7 +43,7 @@ AudioControlSGTL5000 sgtl5000_1; //xy=384,610 MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI); -Dexed* dexed = new Dexed(RATE); +Dexed* dexed = new Dexed(SAMPLERATE); void setup() { @@ -57,7 +60,7 @@ void setup() AudioMemory(16); sgtl5000_1.enable(); - sgtl5000_1.volume(0.6); + sgtl5000_1.volume(0.3); // Initialize processor and memory measurements //AudioProcessorUsageMaxReset(); @@ -82,7 +85,7 @@ void setup() dexed->ProcessMidiMessage(0x90, TEST_NOTE2, 60); #endif - reverb1.reverbTime(5.0); + //reverb1.reverbTime(5.0); Serial.println("Go"); } @@ -110,17 +113,15 @@ void loop() // process midi->audio if (MIDI.read()) { - Serial.print("Type: "); + /* Serial.print("Type: "); Serial.print(MIDI.getType(), DEC); Serial.print(" Data1: "); Serial.print(MIDI.getData1(), DEC); Serial.print(" Data2: "); - Serial.println(MIDI.getData2(), DEC); + Serial.println(MIDI.getData2(), DEC); */ dexed->ProcessMidiMessage(MIDI.getType(), MIDI.getData1(), MIDI.getData2()); } - else - - dexed->GetSamples(RATE, audio_buffer); + dexed->GetSamples(RATE, audio_buffer); /* uint8_t i = 0; for (i = 0; i < 128; i++) diff --git a/dexed.cpp b/dexed.cpp index 2273630..433cc2a 100644 --- a/dexed.cpp +++ b/dexed.cpp @@ -31,7 +31,7 @@ #include #include -Dexed::Dexed(uint8_t rate) +Dexed::Dexed(int rate) { 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); for (uint8_t j = 0; j < _N_; ++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; - /* float f = static_cast(clip_val >> 1) / static_cast(0x8000); - if (f > 1) f = 1; - if (f < -1) f = -1; - sumbuf[j] += f;*/ + float f = static_cast(clip_val >> 1) / static_cast(0x8000); + if (f > 1) f = 1; + if (f < -1) f = -1; sumbuf[j] += clip_val; audiobuf.get()[j] = 0; } diff --git a/dexed.h b/dexed.h index 0b587c7..9499cba 100644 --- a/dexed.h +++ b/dexed.h @@ -55,7 +55,7 @@ enum DexedEngineResolution { class Dexed { public: - Dexed(uint8_t rate); + Dexed(int rate); ~Dexed(); void activate(void); void deactivate(void); @@ -96,7 +96,6 @@ class Dexed uint32_t extra_buf_size_; private: - uint16_t _rate; uint8_t _k_rate_counter; uint8_t _param_change_counter; diff --git a/dx7note.cpp b/dx7note.cpp index 0050aad..97c039e 100644 --- a/dx7note.cpp +++ b/dx7note.cpp @@ -1,19 +1,19 @@ /* - * Copyright 2016-2017 Pascal Gauthier. - * Copyright 2012 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ + Copyright 2016-2017 Pascal Gauthier. + Copyright 2012 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ #include #include @@ -26,307 +26,306 @@ 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; - return base + step * midinote; + const int32_t base = 50857777; // (1 << 24) * (log(440) / log(2) - 69/12) + const int32_t step = (1 << 24) / 12; + return base + step * midinote; } const int32_t coarsemul[] = { - -16777216, 0, 16777216, 26591258, 33554432, 38955489, 43368474, 47099600, - 50331648, 53182516, 55732705, 58039632, 60145690, 62083076, 63876816, - 65546747, 67108864, 68576247, 69959732, 71268397, 72509921, 73690858, - 74816848, 75892776, 76922906, 77910978, 78860292, 79773775, 80654032, - 81503396, 82323963, 83117622 + -16777216, 0, 16777216, 26591258, 33554432, 38955489, 43368474, 47099600, + 50331648, 53182516, 55732705, 58039632, 60145690, 62083076, 63876816, + 65546747, 67108864, 68576247, 69959732, 71268397, 72509921, 73690858, + 74816848, 75892776, 76922906, 77910978, 78860292, 79773775, 80654032, + 81503396, 82323963, 83117622 }; int32_t osc_freq(int midinote, int mode, int coarse, int fine, int detune) { - // TODO: pitch randomization - int32_t logfreq; - if (mode == 0) { - logfreq = midinote_to_logfreq(midinote); - - // 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; - logfreq += detuneRatio * logfreq * (detune - 7); - - logfreq += coarsemul[coarse & 31]; - if (fine) { - // (1 << 24) / log(2) - 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; + // TODO: pitch randomization + int32_t logfreq; + if (mode == 0) { + logfreq = midinote_to_logfreq(midinote); + // 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; + logfreq += detuneRatio * logfreq * (detune - 7); + + logfreq += coarsemul[coarse & 31]; + if (fine) { + // (1 << 24) / log(2) + logfreq += (int32_t)floor(24204406.323123 * log(1 + 0.01 * fine) + 0.5); } - 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] = { - 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, - 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, - 252, 253, 254 + 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, + 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, + 252, 253, 254 }; // See "velocity" section of notes. Returns velocity delta in microsteps. int ScaleVelocity(int velocity, int sensitivity) { - int clamped_vel = max(0, min(127, velocity)); - int vel_value = velocity_data[clamped_vel >> 1] - 239; - int scaled_vel = ((sensitivity * vel_value + 7) >> 3) << 4; - return scaled_vel; + int clamped_vel = max(0, min(127, velocity)); + int vel_value = velocity_data[clamped_vel >> 1] - 239; + int scaled_vel = ((sensitivity * vel_value + 7) >> 3) << 4; + return scaled_vel; } int ScaleRate(int midinote, int sensitivity) { - int x = min(31, max(0, midinote / 3 - 7)); - int qratedelta = (sensitivity * x) >> 3; + int x = min(31, max(0, midinote / 3 - 7)); + int qratedelta = (sensitivity * x) >> 3; #ifdef SUPER_PRECISE - int rem = x & 7; - if (sensitivity == 3 && rem == 3) { - qratedelta -= 1; - } else if (sensitivity == 7 && rem > 0 && rem < 4) { - qratedelta += 1; - } + int rem = x & 7; + if (sensitivity == 3 && rem == 3) { + qratedelta -= 1; + } else if (sensitivity == 7 && rem > 0 && rem < 4) { + qratedelta += 1; + } #endif - return qratedelta; + return qratedelta; } 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, - 80, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 250 + 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 }; int ScaleCurve(int group, int depth, int curve) { - int scale; - if (curve == 0 || curve == 3) { - // linear - scale = (group * depth * 329) >> 12; - } else { - // exponential - int n_scale_data = sizeof(exp_scale_data); - int raw_exp = exp_scale_data[min(group, n_scale_data - 1)]; - scale = (raw_exp * depth * 329) >> 15; - } - if (curve < 2) { - scale = -scale; - } - return scale; + int scale; + if (curve == 0 || curve == 3) { + // linear + scale = (group * depth * 329) >> 12; + } else { + // exponential + int n_scale_data = sizeof(exp_scale_data); + int raw_exp = exp_scale_data[min(group, n_scale_data - 1)]; + scale = (raw_exp * depth * 329) >> 15; + } + if (curve < 2) { + scale = -scale; + } + return scale; } int ScaleLevel(int midinote, int break_pt, int left_depth, int right_depth, int left_curve, int right_curve) { - int offset = midinote - break_pt - 17; - if (offset >= 0) { - return ScaleCurve((offset+1) / 3, right_depth, right_curve); - } else { - return ScaleCurve(-(offset-1) / 3, left_depth, left_curve); - } + int offset = midinote - break_pt - 17; + if (offset >= 0) { + return ScaleCurve((offset + 1) / 3, right_depth, right_curve); + } else { + return ScaleCurve(-(offset - 1) / 3, left_depth, left_curve); + } } 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 static const uint32_t ampmodsenstab[] = { - 0, 4342338, 7171437, 16777216 + 0, 4342338, 7171437, 16777216 }; Dx7Note::Dx7Note() { - for(int op=0;op<6;op++) { - params_[op].phase = 0; - params_[op].gain_out = 0; - } + for (int op = 0; op < 6; op++) { + params_[op].phase = 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[173], int midinote, int velocity) { - int rates[4]; - int levels[4]; - for (int op = 0; op < 6; op++) { - 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]; - } + int rates[4]; + int levels[4]; + for (int op = 0; op < 6; op++) { + int off = op * 21; for (int i = 0; i < 4; i++) { - rates[i] = patch[126 + i]; - levels[i] = patch[130 + i]; + rates[i] = patch[off + i]; + levels[i] = patch[off + 4 + 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; + 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++) { + 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) { - // ==== PITCH ==== - uint32_t pmd = pitchmoddepth_ * lfo_delay; // Q32 - int32_t senslfo = pitchmodsens_ * (lfo_val - (1 << 23)); - int32_t pmod_1 = (((int64_t) pmd) * (int64_t) senslfo) >> 39; - pmod_1 = abs(pmod_1); - int32_t pmod_2 = (int32_t)(((int64_t)ctrls->pitch_mod * (int64_t)senslfo) >> 14); - pmod_2 = abs(pmod_2); - int32_t pitch_mod = max(pmod_1, pmod_2); - pitch_mod = pitchenv_.getsample() + (pitch_mod * (senslfo < 0 ? -1 : 1)); - - // ---- PITCH BEND ---- - int pitchbend = ctrls->values_[kControllerPitch]; - int32_t pb = (pitchbend - 0x2000); - if (pb != 0) { - if (ctrls->values_[kControllerPitchStep] == 0) { - pb = ((float) (pb << 11)) * ((float) ctrls->values_[kControllerPitchRange]) / 12.0; - } else { - int stp = 12 / ctrls->values_[kControllerPitchStep]; - pb = pb * stp / 8191; - pb = (pb * (8191 / stp)) << 11; - } + // ==== PITCH ==== + uint32_t pmd = pitchmoddepth_ * lfo_delay; // Q32 + int32_t senslfo = pitchmodsens_ * (lfo_val - (1 << 23)); + int32_t pmod_1 = (((int64_t) pmd) * (int64_t) senslfo) >> 39; + pmod_1 = abs(pmod_1); + int32_t pmod_2 = (int32_t)(((int64_t)ctrls->pitch_mod * (int64_t)senslfo) >> 14); + pmod_2 = abs(pmod_2); + int32_t pitch_mod = max(pmod_1, pmod_2); + pitch_mod = pitchenv_.getsample() + (pitch_mod * (senslfo < 0 ? -1 : 1)); + + // ---- PITCH BEND ---- + int pitchbend = ctrls->values_[kControllerPitch]; + int32_t pb = (pitchbend - 0x2000); + if (pb != 0) { + if (ctrls->values_[kControllerPitchStep] == 0) { + pb = ((float) (pb << 11)) * ((float) ctrls->values_[kControllerPitchRange]) / 12.0; + } else { + int stp = 12 / ctrls->values_[kControllerPitchStep]; + pb = pb * stp / 8191; + pb = (pb * (8191 / stp)) << 11; } - int32_t pitch_base = pb + ctrls->masterTune; - pitch_mod += pitch_base; - - // ==== AMP MOD ==== - lfo_val = (1<<24) - lfo_val; - uint32_t amod_1 = (uint32_t)(((int64_t) ampmoddepth_ * (int64_t) lfo_delay) >> 8); // Q24 :D - amod_1 = (uint32_t)(((int64_t) amod_1 * (int64_t) lfo_val) >> 24); - 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; - amd_mod = max((1<<24) - amod_3, amd_mod); - - // ==== OP RENDER ==== - for (int op = 0; op < 6; op++) { - // if ( ctrls->opSwitch[op] == '0' ) { - if (!(ctrls->opSwitch & (1<> 24); - - // TODO: mehhh.. this needs some real tuning. - uint32_t pt = exp(((float)sensamp)/262144 * 0.07 + 12.2); - uint32_t ldiff = (uint32_t)(((uint64_t)level) * (((uint64_t)pt<<4)) >> 28); - level -= ldiff; - } - params_[op].level_in = level; - } + } + int32_t pitch_base = pb + ctrls->masterTune; + pitch_mod += pitch_base; + + // ==== AMP MOD ==== + lfo_val = (1 << 24) - lfo_val; + uint32_t amod_1 = (uint32_t)(((int64_t) ampmoddepth_ * (int64_t) lfo_delay) >> 8); // Q24 :D + amod_1 = (uint32_t)(((int64_t) amod_1 * (int64_t) lfo_val) >> 24); + 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; + amd_mod = max((1 << 24) - amod_3, amd_mod); + + // ==== OP RENDER ==== + for (int op = 0; op < 6; op++) { + // if ( ctrls->opSwitch[op] == '0' ) { + if (!(ctrls->opSwitch & (1 << op))) { + env_[op].getsample(); // advance the envelop even if it is not playing + params_[op].level_in = 0; + } else { + //int32_t gain = pow(2, 10 + level * (1.0 / (1 << 24))); + + if ( opMode[op] ) + params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_base); + else + params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_mod); + + int32_t level = env_[op].getsample(); + 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); + uint32_t ldiff = (uint32_t)(((uint64_t)level) * (((uint64_t)pt << 4)) >> 28); + level -= ldiff; + } + 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() { - for (int op = 0; op < 6; op++) { - env_[op].keydown(false); - } - pitchenv_.keydown(false); + for (int op = 0; op < 6; op++) { + env_[op].keydown(false); + } + pitchenv_.keydown(false); } 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]; - int coarse = patch[off + 18]; - int fine = patch[off + 19]; - int detune = patch[off + 20]; - basepitch_[op] = osc_freq(midinote, mode, coarse, fine, detune); - ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3]; - opMode[op] = mode; - - 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); + int rates[4]; + int levels[4]; + for (int op = 0; op < 6; op++) { + int off = op * 21; + int mode = patch[off + 17]; + int coarse = patch[off + 18]; + int fine = patch[off + 19]; + int detune = patch[off + 20]; + basepitch_[op] = osc_freq(midinote, mode, coarse, fine, detune); + ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3]; + opMode[op] = mode; + + for (int i = 0; i < 4; i++) { + rates[i] = patch[off + i]; + levels[i] = patch[off + 4 + i]; } - 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; + 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 ? FEEDBACK_BITDEPTH - feedback : 16; + pitchmoddepth_ = (patch[139] * 165) >> 6; + pitchmodsens_ = pitchmodsenstab[patch[143] & 7]; + ampmoddepth_ = (patch[140] * 165) >> 6; } void Dx7Note::peekVoiceStatus(VoiceStatus &status) { - for(int i=0;i<6;i++) { - status.amp[i] = Exp2::lookup(params_[i].level_in - (14 * (1 << 24))); - env_[i].getPosition(&status.ampStep[i]); - } - pitchenv_.getPosition(&status.pitchStep); + for (int i = 0; i < 6; i++) { + status.amp[i] = Exp2::lookup(params_[i].level_in - (14 * (1 << 24))); + env_[i].getPosition(&status.ampStep[i]); + } + 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) { - for (int i=0;i<6;i++) { - env_[i].transfer(src.env_[i]); - params_[i].gain_out = src.params_[i].gain_out; - params_[i].phase = src.params_[i].phase; - } + for (int i = 0; i < 6; i++) { + env_[i].transfer(src.env_[i]); + params_[i].gain_out = src.params_[i].gain_out; + params_[i].phase = src.params_[i].phase; + } } void Dx7Note::transferSignal(Dx7Note &src) { - for (int i=0;i<6;i++) { - params_[i].gain_out = src.params_[i].gain_out; - params_[i].phase = src.params_[i].phase; - } + for (int i = 0; i < 6; i++) { + params_[i].gain_out = src.params_[i].gain_out; + params_[i].phase = src.params_[i].phase; + } } void Dx7Note::oscSync() { - for (int i=0;i<6;i++) { - params_[i].gain_out = 0; - params_[i].phase = 0; - } + for (int i = 0; i < 6; i++) { + params_[i].gain_out = 0; + params_[i].phase = 0; + } } diff --git a/synth.h b/synth.h index 838162d..ad60d1e 100644 --- a/synth.h +++ b/synth.h @@ -18,6 +18,7 @@ #define __SYNTH_H #include +#define SUPER_PRECISE // This IS not be present on MSVC. // See http://stackoverflow.com/questions/126279/c99-stdint-h-header-and-ms-visual-studio