/* Copyright 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. */ //using namespace std; #include #include "synth.h" #include "env.h" uint32_t Env::sr_multiplier = (1 << 24); const int32_t levellut[] = { 0, 5, 9, 13, 17, 20, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 42, 43, 45, 46 }; #ifdef ACCURATE_ENVELOPE const int32_t statics[] = { 1764000, 1764000, 1411200, 1411200, 1190700, 1014300, 992250, 882000, 705600, 705600, 584325, 507150, 502740, 441000, 418950, 352800, 308700, 286650, 253575, 220500, 220500, 176400, 145530, 145530, 125685, 110250, 110250, 88200, 88200, 74970, 61740, 61740, 55125, 48510, 44100, 37485, 31311, 30870, 27562, 27562, 22050, 18522, 17640, 15435, 14112, 13230, 11025, 9261, 9261, 7717, 6615, 6615, 5512, 5512, 4410, 3969, 3969, 3439, 2866, 2690, 2249, 1984, 1896, 1808, 1411, 1367, 1234, 1146, 926, 837, 837, 705, 573, 573, 529, 441, 441 // and so on, I stopped measuring after R=76 (needs to be double-checked anyway) }; #endif void Env::init_sr(double sampleRate) { sr_multiplier = (44100.0 / sampleRate) * (1 << 24); } void Env::init(const int32_t r[4], const int32_t l[4], int32_t ol, int32_t rate_scaling) { for (int i = 0; i < 4; i++) { rates_[i] = r[i]; levels_[i] = l[i]; } outlevel_ = ol; rate_scaling_ = rate_scaling; level_ = 0; down_ = true; advance(0); } int32_t Env::getsample() { #ifdef ACCURATE_ENVELOPE if (staticcount_) { staticcount_ -= _N_; if (staticcount_ <= 0) { staticcount_ = 0; advance(ix_ + 1); } } #endif if (ix_ < 3 || ((ix_ < 4) && !down_)) { if (staticcount_) { ; } else if (rising_) { const int32_t jumptarget = 1716; if (level_ < (jumptarget << 16)) { level_ = jumptarget << 16; } level_ += (((17 << 24) - level_) >> 24) * inc_; // TODO: should probably be more accurate when inc is large if (level_ >= targetlevel_) { level_ = targetlevel_; advance(ix_ + 1); } } else { // !rising level_ -= inc_; if (level_ <= targetlevel_) { level_ = targetlevel_; advance(ix_ + 1); } } } // TODO: this would be a good place to set level to 0 when under threshold return level_; } void Env::keydown(bool d) { if (down_ != d) { down_ = d; advance(d ? 0 : 3); } } int32_t Env::scaleoutlevel(int32_t outlevel) { return outlevel >= 20 ? 28 + outlevel : levellut[outlevel]; } void Env::advance(int newix) { ix_ = newix; if (ix_ < 4) { int32_t newlevel = levels_[ix_]; int32_t actuallevel = scaleoutlevel(newlevel) >> 1; actuallevel = (actuallevel << 6) + outlevel_ - 4256; actuallevel = actuallevel < 16 ? 16 : actuallevel; // level here is same as Java impl targetlevel_ = actuallevel << 16; rising_ = (targetlevel_ > level_); // rate int32_t qrate = (rates_[ix_] * 41) >> 6; qrate += rate_scaling_; qrate = std::min(int(qrate), 63); #ifdef ACCURATE_ENVELOPE if (targetlevel_ == level_ || (ix_ == 0 && newlevel == 0)) { // approximate number of samples at 44.100 kHz to achieve the time // empirically gathered using 2 TF1s, could probably use some double-checking // and cleanup, but it's pretty close for now. int32_t staticrate = rates_[ix_]; staticrate += rate_scaling_; // needs to be checked, as well, but seems correct staticrate = std::min(int(staticrate), 99); staticcount_ = staticrate < 77 ? statics[staticrate] : 20 * (99 - staticrate); if (staticrate < 77 && (ix_ == 0 && newlevel == 0)) { staticcount_ /= 20; // attack is scaled faster } staticcount_ = (int)(((int64_t)staticcount_ * (int64_t)sr_multiplier) >> 24); } else { staticcount_ = 0; } #endif inc_ = (4 + (qrate & 3)) << (2 + LG_N + (qrate >> 2)); // meh, this should be fixed elsewhere inc_ = (int)(((int64_t)inc_ * (int64_t)sr_multiplier) >> 24); } } void Env::update(const int32_t r[4], const int32_t l[4], int32_t ol, int32_t rate_scaling) { for (int i = 0; i < 4; i++) { rates_[i] = r[i]; levels_[i] = l[i]; } outlevel_ = ol; rate_scaling_ = rate_scaling; if ( down_ ) { // for now we simply reset ourselves at level 3 int32_t newlevel = levels_[2]; int32_t actuallevel = scaleoutlevel(newlevel) >> 1; actuallevel = (actuallevel << 6) - 4256; actuallevel = actuallevel < 16 ? 16 : actuallevel; targetlevel_ = actuallevel << 16; advance(2); } } void Env::getPosition(char *step) { *step = ix_; } void Env::transfer(Env &src) { for (int i = 0; i < 4; i++) { rates_[i] = src.rates_[i]; levels_[i] = src.levels_[i]; } outlevel_ = src.outlevel_; rate_scaling_ = src.rate_scaling_; level_ = src.level_; targetlevel_ = src.targetlevel_; rising_ = src.rising_; ix_ = src.ix_; down_ = src.down_; #ifdef ACCURATE_ENVELOPE staticcount_ = src.staticcount_; #endif inc_ = src.inc_; }