FIRST WORKING VERSION!
pull/4/head
Holger Wirtz 7 years ago
parent 4660200948
commit fd755727b5
  1. 23
      MicroDexed.ino
  2. 7
      dexed.cpp
  3. 3
      dexed.h
  4. 67
      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,16 +113,14 @@ 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;

@ -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,8 +26,8 @@
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;
} }
@ -44,9 +44,8 @@ int32_t osc_freq(int midinote, int mode, int coarse, int fine, int detune) {
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];
@ -122,9 +121,9 @@ 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);
} }
} }
@ -138,7 +137,7 @@ static const uint32_t ampmodsenstab[] = {
}; };
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;
} }
@ -215,20 +214,20 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Co
pitch_mod += pitch_base; pitch_mod += pitch_base;
// ==== AMP MOD ==== // ==== AMP MOD ====
lfo_val = (1<<24) - lfo_val; lfo_val = (1 << 24) - lfo_val;
uint32_t amod_1 = (uint32_t)(((int64_t) ampmoddepth_ * (int64_t) lfo_delay) >> 8); // Q24 :D 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); 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 amod_2 = (uint32_t)(((int64_t) ctrls->amp_mod * (int64_t) lfo_val) >> 7); // Q?? :|
uint32_t amd_mod = max(amod_1, amod_2); uint32_t amd_mod = max(amod_1, amod_2);
// ==== EG AMP MOD ==== // ==== EG AMP MOD ====
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); amd_mod = max((1 << 24) - amod_3, amd_mod);
// ==== OP RENDER ==== // ==== OP RENDER ====
for (int op = 0; op < 6; op++) { for (int op = 0; op < 6; op++) {
// if ( ctrls->opSwitch[op] == '0' ) { // if ( ctrls->opSwitch[op] == '0' ) {
if (!(ctrls->opSwitch & (1<<op))) { if (!(ctrls->opSwitch & (1 << op))) {
env_[op].getsample(); // advance the envelop even if it is not playing env_[op].getsample(); // advance the envelop even if it is not playing
params_[op].level_in = 0; params_[op].level_in = 0;
} else { } else {
@ -244,8 +243,8 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Co
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);
// TODO: mehhh.. this needs some real tuning. // TODO: mehhh.. this needs some real tuning.
uint32_t pt = exp(((float)sensamp)/262144 * 0.07 + 12.2); uint32_t pt = exp(((float)sensamp) / 262144 * 0.07 + 12.2);
uint32_t ldiff = (uint32_t)(((uint64_t)level) * (((uint64_t)pt<<4)) >> 28); uint32_t ldiff = (uint32_t)(((uint64_t)level) * (((uint64_t)pt << 4)) >> 28);
level -= ldiff; level -= ldiff;
} }
params_[op].level_in = level; params_[op].level_in = level;
@ -299,7 +298,7 @@ void Dx7Note::update(const uint8_t patch[156], int midinote, int velocity) {
} }
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]);
} }
@ -307,10 +306,10 @@ void Dx7Note::peekVoiceStatus(VoiceStatus &status) {
} }
/** /**
* 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;
@ -318,14 +317,14 @@ void Dx7Note::transferState(Dx7Note &src) {
} }
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