voice tuning correct
This commit is contained in:
parent
5c1c79464e
commit
e73914e4ae
@ -30,7 +30,10 @@ Synth::Synth() {
|
|||||||
|
|
||||||
void Synth::buildTables(double sampleRate) {
|
void Synth::buildTables(double sampleRate) {
|
||||||
for (uint8_t i = 0; i < 104; i++) {
|
for (uint8_t i = 0; i < 104; i++) {
|
||||||
pitchTable[i] = 440.0f * powf(2, (i - 45) / 12.0f) / sampleRate;
|
// slightly flat middle C from ROM divider table
|
||||||
|
// actually adjusted a little so that the notes are bang on
|
||||||
|
// on the real synth the tuning knob is tweaked a little off to pull it in
|
||||||
|
pitchTable[i] = 260.15f * powf(2, (i - 36) / 12.0f) / sampleRate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,25 +42,22 @@ void Synth::run() {
|
|||||||
// callled once every 4.3ms block of samples
|
// callled once every 4.3ms block of samples
|
||||||
|
|
||||||
for (uint8_t i = 0; i < NUM_VOICES; i++) {
|
for (uint8_t i = 0; i < NUM_VOICES; i++) {
|
||||||
ic29.voices[i].env.run();
|
ic29.voices[i].update();
|
||||||
ic29.voices[i].calcPitch();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Synth::voiceOn(uint8_t voice, uint8_t note) {
|
void Synth::voiceOn(uint8_t voice, uint8_t note) {
|
||||||
// enable synth voice, start it all running
|
// enable synth voice, start it all running
|
||||||
voice &= 0x7f;
|
voice &= 0x7f;
|
||||||
ic29.voices[voice].env.on();
|
ic29.voices[voice].on(note);
|
||||||
|
|
||||||
// FIXME determine if we need to reset the counter
|
|
||||||
ic29.voices[voice].note = note;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Synth::voiceOff(uint8_t voice) {
|
void Synth::voiceOff(uint8_t voice) {
|
||||||
// enable synth voice, start it all running
|
// enable synth voice, start it all running
|
||||||
voice &= 0x7f;
|
voice &= 0x7f;
|
||||||
ic29.voices[voice].env.off();
|
ic29.voices[voice].off();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Synth::basePitch() {
|
void Synth::basePitch() {
|
||||||
uint16_t pitch = 0x1818;
|
uint16_t pitch = 0x1818;
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ Voice::Voice() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Voice::calcPitch() {
|
void Voice::calcPitch() {
|
||||||
uint16_t target = (note - 24) << 8;
|
uint16_t target = note << 8;
|
||||||
|
|
||||||
if (ic29.portaCoeff != 0) {
|
if (ic29.portaCoeff != 0) {
|
||||||
// porta up
|
// porta up
|
||||||
@ -121,6 +121,14 @@ void Voice::calcPitch() {
|
|||||||
pitch = target;
|
pitch = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pitch += 0x1818; //ic29.masterPitch;
|
||||||
|
|
||||||
|
if (pitch < 0x3000) pitch = 0x3000; // lowest note
|
||||||
|
if (pitch > 0x9700) pitch = 0x6700; // highest note
|
||||||
|
|
||||||
|
pitch -= 0x3000;
|
||||||
|
//pitch &= 0xff00;
|
||||||
|
|
||||||
double o1 = ic29.pitchTable[pitch >> 8];
|
double o1 = ic29.pitchTable[pitch >> 8];
|
||||||
double o2 = ic29.pitchTable[(pitch >> 8) + 1];
|
double o2 = ic29.pitchTable[(pitch >> 8) + 1];
|
||||||
double frac = (pitch & 0xff) / 255.0;
|
double frac = (pitch & 0xff) / 255.0;
|
||||||
@ -128,6 +136,27 @@ void Voice::calcPitch() {
|
|||||||
omega = ((o2 - o1) * frac) + o1;
|
omega = ((o2 - o1) * frac) + o1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Voice::update() {
|
||||||
|
// calculate the once-per-block values
|
||||||
|
env.run();
|
||||||
|
calcPitch();
|
||||||
|
// do filter values
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::on(uint8_t key) {
|
||||||
|
voiceState = V_ON;
|
||||||
|
note = key;
|
||||||
|
env.on();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::off() {
|
||||||
|
// I need to rethink this bit FIXME
|
||||||
|
voiceState = V_OFF;
|
||||||
|
if (!ic29.sustained) {
|
||||||
|
env.off();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Voice::run(float *buffer, uint32_t samples) {
|
void Voice::run(float *buffer, uint32_t samples) {
|
||||||
float gain = env.level / 16384.0;
|
float gain = env.level / 16384.0;
|
||||||
gain *= 0.125;
|
gain *= 0.125;
|
||||||
|
@ -31,6 +31,11 @@ class Envelope {
|
|||||||
void off() {
|
void off() {
|
||||||
phase = ENV_RLS;
|
phase = ENV_RLS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool inRelease() {
|
||||||
|
return phase == ENV_RLS;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t level;
|
uint16_t level;
|
||||||
|
|
||||||
// private:
|
// private:
|
||||||
@ -45,18 +50,21 @@ class Envelope {
|
|||||||
class Voice {
|
class Voice {
|
||||||
public:
|
public:
|
||||||
Voice();
|
Voice();
|
||||||
void run();
|
|
||||||
uint8_t note = 0x3c; // middle C
|
uint8_t note = 0x3c; // middle C
|
||||||
|
void run(float *buffer, uint32_t samples);
|
||||||
|
void update();
|
||||||
|
void on(uint8_t note);
|
||||||
|
void off();
|
||||||
|
|
||||||
// private:
|
private:
|
||||||
Envelope env; // calculated envelope value
|
Envelope env; // calculated envelope value
|
||||||
uint16_t pitch = 0x1818; // calculated pitch value with porta and master pitch etc
|
uint16_t pitch = 0x1818; // calculated pitch value with porta and master pitch etc
|
||||||
float phase=0, omega=0;
|
float phase = 0, omega = 0;
|
||||||
enum { V_DONE,
|
enum { V_DONE,
|
||||||
V_OFF,
|
V_OFF,
|
||||||
V_ON } voiceState;
|
V_ON } voiceState;
|
||||||
|
|
||||||
void calcPitch();
|
void calcPitch();
|
||||||
void run(float *buffer, uint32_t samples);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Synth {
|
class Synth {
|
||||||
@ -77,11 +85,11 @@ class Synth {
|
|||||||
uint16_t masterPitch; // sum of bend and LFO, plus any other pitch-setting value
|
uint16_t masterPitch; // sum of bend and LFO, plus any other pitch-setting value
|
||||||
// protected:
|
// protected:
|
||||||
uint16_t envAtk, envDcy, envStn, envRls;
|
uint16_t envAtk, envDcy, envStn, envRls;
|
||||||
int16_t portaCoeff;
|
int8_t portaCoeff;
|
||||||
|
bool sustained;
|
||||||
double pitchTable[104];
|
double pitchTable[104];
|
||||||
|
|
||||||
|
// private:
|
||||||
//private:
|
|
||||||
int16_t lfoPitch;
|
int16_t lfoPitch;
|
||||||
int16_t bendPitch;
|
int16_t bendPitch;
|
||||||
Voice voices[NUM_VOICES];
|
Voice voices[NUM_VOICES];
|
||||||
|
Loading…
Reference in New Issue
Block a user