diff --git a/src/yaw-shepard/synth.cpp b/src/yaw-shepard/synth.cpp index 097ed5a..cbb5f5e 100644 --- a/src/yaw-shepard/synth.cpp +++ b/src/yaw-shepard/synth.cpp @@ -12,7 +12,7 @@ static constexpr double getAmplitude( double hz ) { if( hz < 20.0 ) return 0.0; if( hz < 440.0 ) return hz / 440.0; - if( hz < 16000.0 ) return (16000.0 - hz) / 15560.0; + if( hz < 10000.0 ) return (10000.0 - hz) / 9560.0; return 0.0; } @@ -42,14 +42,14 @@ void Synth::process(float* output, const uint32_t frames) //Don't bother rendering anything over the Nyquist rate. if( hz > hzNyq ) break; - output[i] += getAmplitude(hz) * sin(2.0 * M_PI * phase); + output[i] += getAmplitude(hz) * (phase > 0.5); // * sin(2.0 * M_PI * phase); //Remember phase, move to higher overtone. phases[(voice + idxFund) & VOICE_MASK] = phase; hz *= ratio; } - output[i] *= volume; + output[i] *= volume / static_cast(NUM_VOICES); } //Make timbre cyclical. @@ -81,7 +81,7 @@ void Synth::process(float* output, const uint32_t frames) void Synth::setSampleRate(double oldRate, double newRate){ sampleInterval = 1.0 / newRate; hzNyq = newRate / 2; - ratioSlewRate *= newRate / oldRate; + ratioSlewRate = pow(ratioSlewRate, oldRate / newRate); hzShift = pow(hzShift, newRate / oldRate); } @@ -92,11 +92,13 @@ void Synth::setFrequencyShift(double in){ hzShift = exp2(2.0 * (in - 0.5) * sampleInterval); } +static constexpr double minRatio = 1.0; +static constexpr double maxRatio = 3.0; //Slew to given ratio. //0 : next voice is one fifth above previous voice. //1 : next voice is one octave above previous voice. void Synth::setTargetRatio(double in){ - targetRatio = 1.5 + in * 0.5; + targetRatio = minRatio + in * (maxRatio - minRatio); } void Synth::setVolume(double in){ diff --git a/src/yaw-shepard/synth.h b/src/yaw-shepard/synth.h index f4a15c5..15da8c3 100644 --- a/src/yaw-shepard/synth.h +++ b/src/yaw-shepard/synth.h @@ -7,8 +7,8 @@ struct Voice double phase; }; -constexpr int NUM_VOICES = 256; -constexpr uchar VOICE_MASK = 0xFF; +constexpr unsigned int NUM_VOICES = 64; +constexpr unsigned int VOICE_MASK = NUM_VOICES - 1; class Synth { @@ -25,7 +25,7 @@ private: //Phase of each voice, considered as a period function on the unit interval. std::array phases = {0}; //Index of lowest voice in phase array. - uchar idxFund = 0; + unsigned int idxFund = 0; float volume = 0.0f; double hzFund = 32.7; double hzShift = 1.0;