diff --git a/Disp_Plus.h b/Disp_Plus.h index cc5bd90..7103fba 100644 --- a/Disp_Plus.h +++ b/Disp_Plus.h @@ -62,7 +62,7 @@ class Disp_Plus : public T memset(tmp, '0', field_size); else memset(tmp, 0x20, field_size); // blank - + if (l > field_size) l = field_size; diff --git a/EngineMkI.cpp b/EngineMkI.cpp index e7d050a..49c8f74 100644 --- a/EngineMkI.cpp +++ b/EngineMkI.cpp @@ -1,25 +1,25 @@ /* - * Copyright (C) 2015-2017 Pascal Gauthier. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * The code is based on ppplay https://github.com/stohrendorf/ppplay and opl3 - * math documentation : - * https://github.com/gtaylormb/opl3_fpga/blob/master/docs/opl3math/opl3math.pdf - * - */ + Copyright (C) 2015-2017 Pascal Gauthier. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + The code is based on ppplay https://github.com/stohrendorf/ppplay and opl3 + math documentation : + https://github.com/gtaylormb/opl3_fpga/blob/master/docs/opl3math/opl3math.pdf + +*/ #include "EngineMkI.h" #define _USE_MATH_DEFINES @@ -30,325 +30,324 @@ #include "exp2.h" #ifdef DEBUG - #include "time.h" - //#define MKIDEBUG +#include "time.h" +//#define MKIDEBUG #endif #ifdef _WIN32 #if _MSC_VER < 1800 - FRAC_NUM log2(FRAC_NUM n) { - //return log(n) / log(2.0); - return LOG_FUNC(n) / LOG_FUNC(2.0); - } - FRAC_NUM round(FRAC_NUM n) { - return n < 0.0 ? ceil(n - 0.5) : floor(n + 0.5); - } +FRAC_NUM log2(FRAC_NUM n) { + //return log(n) / log(2.0); + return LOG_FUNC(n) / LOG_FUNC(2.0); +} +FRAC_NUM round(FRAC_NUM n) { + return n < 0.0 ? ceil(n - 0.5) : floor(n + 0.5); +} #endif - __declspec(align(16)) const int zeros[N] = {0}; +__declspec(align(16)) const int zeros[N] = {0}; #else - const int32_t __attribute__ ((aligned(16))) zeros[_N_] = {0}; +const int32_t __attribute__ ((aligned(16))) zeros[_N_] = {0}; #endif static const uint16_t NEGATIVE_BIT = 0x8000; static const uint16_t ENV_BITDEPTH = 14; static const uint16_t SINLOG_BITDEPTH = 10; -static const uint16_t SINLOG_TABLESIZE = 1< 90 ) { - buffer[0] = 0; - pos = 0; - } + char buffer[4096]; + int pos = 0; + + for (int i = 0; i < SINLOG_TABLESIZE; i++) { + pos += sprintf(buffer + pos, "%d ", sinLogTable[i]); + if ( pos > 90 ) { + buffer[0] = 0; + pos = 0; } - buffer[0] = 0; - pos = 0; - for(int i=0;i 90 ) { - buffer[0] = 0; - pos = 0; - } + } + buffer[0] = 0; + pos = 0; + for (int i = 0; i < SINEXP_TABLESIZE; i++) { + pos += sprintf(buffer + pos, "%d ", sinExpTable[i]); + if ( pos > 90 ) { + buffer[0] = 0; + pos = 0; } + } #endif } inline int32_t mkiSin(int32_t phase, uint16_t env) { - uint16_t expVal = sinLog(phase >> (22 - SINLOG_BITDEPTH)) + (env); - //int16_t expValShow = expVal; - - const bool isSigned = expVal & NEGATIVE_BIT; - expVal &= ~NEGATIVE_BIT; - - const uint16_t SINEXP_FILTER = 0x3FF; - uint16_t result = 4096 + sinExpTable[( expVal & SINEXP_FILTER ) ^ SINEXP_FILTER]; - - //uint16_t resultB4 = result; - result >>= ( expVal >> 10 ); // exp - + uint16_t expVal = sinLog(phase >> (22 - SINLOG_BITDEPTH)) + (env); + //int16_t expValShow = expVal; + + const bool isSigned = expVal & NEGATIVE_BIT; + expVal &= ~NEGATIVE_BIT; + + const uint16_t SINEXP_FILTER = 0x3FF; + uint16_t result = 4096 + sinExpTable[( expVal & SINEXP_FILTER ) ^ SINEXP_FILTER]; + + //uint16_t resultB4 = result; + result >>= ( expVal >> 10 ); // exp + #ifdef MKIDEBUG - if ( ( time(NULL) % 5 ) == 0 ) { - if ( expValShow < 0 ) { - expValShow = (expValShow + 0x7FFF) * -1; - } + if ( ( time(NULL) % 5 ) == 0 ) { + if ( expValShow < 0 ) { + expValShow = (expValShow + 0x7FFF) * -1; } + } #endif - - if( isSigned ) - return (-result - 1) << 13; - else - return result << 13; + + if ( isSigned ) + return (-result - 1) << 13; + else + return result << 13; } void EngineMkI::compute(int32_t *output, const int32_t *input, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; - const int32_t *adder = add ? output : zeros; - - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t y = mkiSin((phase+input[i]), gain); - output[i] = y + adder[i]; - phase += freq; - } - + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; + int32_t gain = gain1; + int32_t phase = phase0; + const int32_t *adder = add ? output : zeros; + + for (int i = 0; i < _N_; i++) { + gain += dgain; + int32_t y = mkiSin((phase + input[i]), gain); + output[i] = y + adder[i]; + phase += freq; + } + } void EngineMkI::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; - const int32_t *adder = add ? output : zeros; - - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t y = mkiSin(phase , gain); - output[i] = y + adder[i]; - phase += freq; - } + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; + int32_t gain = gain1; + int32_t phase = phase0; + const int32_t *adder = add ? output : zeros; + + for (int i = 0; i < _N_; i++) { + gain += dgain; + int32_t y = mkiSin(phase , gain); + output[i] = y + adder[i]; + phase += freq; + } } void EngineMkI::compute_fb(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, int32_t *fb_buf, int fb_shift, bool add) { - int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; - const int32_t *adder = add ? output : zeros; - int32_t y0 = fb_buf[0]; - int32_t y = fb_buf[1]; - - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); - y0 = y; - y = mkiSin((phase+scaled_fb), gain); - output[i] = y + adder[i]; - phase += freq; - } - - fb_buf[0] = y0; - fb_buf[1] = y; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; + int32_t gain = gain1; + int32_t phase = phase0; + const int32_t *adder = add ? output : zeros; + int32_t y0 = fb_buf[0]; + int32_t y = fb_buf[1]; + + for (int i = 0; i < _N_; i++) { + gain += dgain; + int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); + y0 = y; + y = mkiSin((phase + scaled_fb), gain); + output[i] = y + adder[i]; + phase += freq; + } + + fb_buf[0] = y0; + fb_buf[1] = y; } // exclusively used for ALGO 6 with feedback void EngineMkI::compute_fb2(int32_t *output, FmOpParams *parms, int32_t gain01, int32_t gain02, int32_t *fb_buf, int fb_shift) { - int32_t dgain[2]; - int32_t gain[2]; - int32_t phase[2]; - int32_t y0 = fb_buf[0]; - int32_t y = fb_buf[1]; - - phase[0] = parms[0].phase; - phase[1] = parms[1].phase; - - parms[1].gain_out = (ENV_MAX-(parms[1].level_in >> (28-ENV_BITDEPTH))); - - gain[0] = gain01; - gain[1] = parms[1].gain_out == 0 ? (ENV_MAX-1) : parms[1].gain_out; - - dgain[0] = (gain02 - gain01 + (_N_ >> 1)) >> LG_N; - dgain[1] = (parms[1].gain_out - (parms[1].gain_out == 0 ? (ENV_MAX-1) : parms[1].gain_out)); - - for (int i = 0; i < _N_; i++) { - int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); - - // op 0 - gain[0] += dgain[0]; - y0 = y; - y = mkiSin(phase[0]+scaled_fb, gain[0]); - phase[0] += parms[0].freq; - - // op 1 - gain[1] += dgain[1]; - y = mkiSin(phase[1]+y, gain[1]); - phase[1] += parms[1].freq; - - output[i] = y; - } - fb_buf[0] = y0; - fb_buf[1] = y; + int32_t dgain[2]; + int32_t gain[2]; + int32_t phase[2]; + int32_t y0 = fb_buf[0]; + int32_t y = fb_buf[1]; + + phase[0] = parms[0].phase; + phase[1] = parms[1].phase; + + parms[1].gain_out = (ENV_MAX - (parms[1].level_in >> (28 - ENV_BITDEPTH))); + + gain[0] = gain01; + gain[1] = parms[1].gain_out == 0 ? (ENV_MAX - 1) : parms[1].gain_out; + + dgain[0] = (gain02 - gain01 + (_N_ >> 1)) >> LG_N; + dgain[1] = (parms[1].gain_out - (parms[1].gain_out == 0 ? (ENV_MAX - 1) : parms[1].gain_out)); + + for (int i = 0; i < _N_; i++) { + int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); + + // op 0 + gain[0] += dgain[0]; + y0 = y; + y = mkiSin(phase[0] + scaled_fb, gain[0]); + phase[0] += parms[0].freq; + + // op 1 + gain[1] += dgain[1]; + y = mkiSin(phase[1] + y, gain[1]); + phase[1] += parms[1].freq; + + output[i] = y; + } + fb_buf[0] = y0; + fb_buf[1] = y; } // exclusively used for ALGO 4 with feedback void EngineMkI::compute_fb3(int32_t *output, FmOpParams *parms, int32_t gain01, int32_t gain02, int32_t *fb_buf, int fb_shift) { - int32_t dgain[3]; - int32_t gain[3]; - int32_t phase[3]; - int32_t y0 = fb_buf[0]; - int32_t y = fb_buf[1]; - - phase[0] = parms[0].phase; - phase[1] = parms[1].phase; - phase[2] = parms[2].phase; - - parms[1].gain_out = (ENV_MAX-(parms[1].level_in >> (28-ENV_BITDEPTH))); - parms[2].gain_out = (ENV_MAX-(parms[2].level_in >> (28-ENV_BITDEPTH))); - - gain[0] = gain01; - gain[1] = parms[1].gain_out == 0 ? (ENV_MAX-1) : parms[1].gain_out; - gain[2] = parms[2].gain_out == 0 ? (ENV_MAX-1) : parms[2].gain_out; - - dgain[0] = (gain02 - gain01 + (_N_ >> 1)) >> LG_N; - dgain[1] = (parms[1].gain_out - (parms[1].gain_out == 0 ? (ENV_MAX-1) : parms[1].gain_out)); - dgain[2] = (parms[2].gain_out - (parms[2].gain_out == 0 ? (ENV_MAX-1) : parms[2].gain_out)); - - - for (int i = 0; i < _N_; i++) { - int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); - - // op 0 - gain[0] += dgain[0]; - y0 = y; - y = mkiSin(phase[0]+scaled_fb, gain[0]); - phase[0] += parms[0].freq; - - // op 1 - gain[1] += dgain[1]; - y = mkiSin(phase[1]+y, gain[1]); - phase[1] += parms[1].freq; - - // op 2 - gain[2] += dgain[2]; - y = mkiSin(phase[2]+y, gain[2]); - phase[2] += parms[2].freq; - - output[i] = y; - } - fb_buf[0] = y0; - fb_buf[1] = y; + int32_t dgain[3]; + int32_t gain[3]; + int32_t phase[3]; + int32_t y0 = fb_buf[0]; + int32_t y = fb_buf[1]; + + phase[0] = parms[0].phase; + phase[1] = parms[1].phase; + phase[2] = parms[2].phase; + + parms[1].gain_out = (ENV_MAX - (parms[1].level_in >> (28 - ENV_BITDEPTH))); + parms[2].gain_out = (ENV_MAX - (parms[2].level_in >> (28 - ENV_BITDEPTH))); + + gain[0] = gain01; + gain[1] = parms[1].gain_out == 0 ? (ENV_MAX - 1) : parms[1].gain_out; + gain[2] = parms[2].gain_out == 0 ? (ENV_MAX - 1) : parms[2].gain_out; + + dgain[0] = (gain02 - gain01 + (_N_ >> 1)) >> LG_N; + dgain[1] = (parms[1].gain_out - (parms[1].gain_out == 0 ? (ENV_MAX - 1) : parms[1].gain_out)); + dgain[2] = (parms[2].gain_out - (parms[2].gain_out == 0 ? (ENV_MAX - 1) : parms[2].gain_out)); + + + for (int i = 0; i < _N_; i++) { + int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); + + // op 0 + gain[0] += dgain[0]; + y0 = y; + y = mkiSin(phase[0] + scaled_fb, gain[0]); + phase[0] += parms[0].freq; + + // op 1 + gain[1] += dgain[1]; + y = mkiSin(phase[1] + y, gain[1]); + phase[1] += parms[1].freq; + + // op 2 + gain[2] += dgain[2]; + y = mkiSin(phase[2] + y, gain[2]); + phase[2] += parms[2].freq; + + output[i] = y; + } + fb_buf[0] = y0; + fb_buf[1] = y; } void EngineMkI::render(int32_t *output, FmOpParams *params, int algorithm, int32_t *fb_buf, int32_t feedback_shift) { - const int kLevelThresh = ENV_MAX-100; - FmAlgorithm alg = algorithms[algorithm]; - bool has_contents[3] = { true, false, false }; - bool fb_on = feedback_shift < 16; - - switch(algorithm) { - case 3 : case 5 : - if ( fb_on ) - alg.ops[0] = 0xc4; - } - - for (int op = 0; op < 6; op++) { - int flags = alg.ops[op]; - bool add = (flags & OUT_BUS_ADD) != 0; - FmOpParams ¶m = params[op]; - int inbus = (flags >> 4) & 3; - int outbus = flags & 3; - int32_t *outptr = (outbus == 0) ? output : buf_[outbus - 1].get(); - int32_t gain1 = param.gain_out == 0 ? (ENV_MAX-1) : param.gain_out; - int32_t gain2 = ENV_MAX-(param.level_in >> (28-ENV_BITDEPTH)); - param.gain_out = gain2; - - if (gain1 <= kLevelThresh || gain2 <= kLevelThresh) { - - if (!has_contents[outbus]) { - add = false; - } - - if (inbus == 0 || !has_contents[inbus]) { - // PG: this is my 'dirty' implementation of FB for 2 and 3 operators... - if ((flags & 0xc0) == 0xc0 && fb_on) { - switch ( algorithm ) { - // three operator feedback, process exception for ALGO 4 - case 3 : - compute_fb3(outptr, params, gain1, gain2, fb_buf, min((feedback_shift+2), 16)); - params[1].phase += params[1].freq << LG_N; // hack, we already processed op-5 - op-4 - params[2].phase += params[2].freq << LG_N; // yuk yuk - op += 2; // ignore the 2 other operators - break; - // two operator feedback, process exception for ALGO 6 - case 5 : - compute_fb2(outptr, params, gain1, gain2, fb_buf, min((feedback_shift+2), 16)); - params[1].phase += params[1].freq << LG_N; // yuk, hack, we already processed op-5 - op++; // ignore next operator; - break; - default: - // one operator feedback, normal proces - compute_fb(outptr, param.phase, param.freq, gain1, gain2, fb_buf, feedback_shift, add); - break; - } - } else { - compute_pure(outptr, param.phase, param.freq, gain1, gain2, add); - } - } else { - compute(outptr, buf_[inbus - 1].get(), param.phase, param.freq, gain1, gain2, add); - } - - has_contents[outbus] = true; - } else if (!add) { - has_contents[outbus] = false; + const int kLevelThresh = ENV_MAX - 100; + FmAlgorithm alg = algorithms[algorithm]; + bool has_contents[3] = { true, false, false }; + bool fb_on = feedback_shift < 16; + + switch (algorithm) { + case 3 : case 5 : + if ( fb_on ) + alg.ops[0] = 0xc4; + } + + for (int op = 0; op < 6; op++) { + int flags = alg.ops[op]; + bool add = (flags & OUT_BUS_ADD) != 0; + FmOpParams ¶m = params[op]; + int inbus = (flags >> 4) & 3; + int outbus = flags & 3; + int32_t *outptr = (outbus == 0) ? output : buf_[outbus - 1].get(); + int32_t gain1 = param.gain_out == 0 ? (ENV_MAX - 1) : param.gain_out; + int32_t gain2 = ENV_MAX - (param.level_in >> (28 - ENV_BITDEPTH)); + param.gain_out = gain2; + + if (gain1 <= kLevelThresh || gain2 <= kLevelThresh) { + + if (!has_contents[outbus]) { + add = false; + } + + if (inbus == 0 || !has_contents[inbus]) { + // PG: this is my 'dirty' implementation of FB for 2 and 3 operators... + if ((flags & 0xc0) == 0xc0 && fb_on) { + switch ( algorithm ) { + // three operator feedback, process exception for ALGO 4 + case 3 : + compute_fb3(outptr, params, gain1, gain2, fb_buf, min((feedback_shift + 2), 16)); + params[1].phase += params[1].freq << LG_N; // hack, we already processed op-5 - op-4 + params[2].phase += params[2].freq << LG_N; // yuk yuk + op += 2; // ignore the 2 other operators + break; + // two operator feedback, process exception for ALGO 6 + case 5 : + compute_fb2(outptr, params, gain1, gain2, fb_buf, min((feedback_shift + 2), 16)); + params[1].phase += params[1].freq << LG_N; // yuk, hack, we already processed op-5 + op++; // ignore next operator; + break; + default: + // one operator feedback, normal proces + compute_fb(outptr, param.phase, param.freq, gain1, gain2, fb_buf, feedback_shift, add); + break; + } + } else { + compute_pure(outptr, param.phase, param.freq, gain1, gain2, add); } - param.phase += param.freq << LG_N; + } else { + compute(outptr, buf_[inbus - 1].get(), param.phase, param.freq, gain1, gain2, add); + } + + has_contents[outbus] = true; + } else if (!add) { + has_contents[outbus] = false; } + param.phase += param.freq << LG_N; + } } - diff --git a/EngineMkI.h b/EngineMkI.h index 586c732..9caa102 100644 --- a/EngineMkI.h +++ b/EngineMkI.h @@ -1,19 +1,19 @@ /* - * Copyright 2014 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 2014 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. +*/ #ifndef ENGINEMKI_H_INCLUDED #define ENGINEMKI_H_INCLUDED @@ -27,22 +27,22 @@ class EngineMkI : public FmCore { -public: + public: EngineMkI(); - + void render(int32_t *output, FmOpParams *params, int algorithm, int32_t *fb_buf, int32_t feedback_shift); - + void compute(int32_t *output, const int32_t *input, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, - bool add); - - void compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, - bool add); - + bool add); + + void compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, + bool add); + void compute_fb(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, - int32_t *fb_buf, int fb_gain, bool add); - + int32_t *fb_buf, int fb_gain, bool add); + void compute_fb2(int32_t *output, FmOpParams *params, int32_t gain01, int32_t gain02, int32_t *fb_buf, int fb_shift); - + void compute_fb3(int32_t *output, FmOpParams *params, int32_t gain01, int32_t gain02, int32_t *fb_buf, int fb_shift); }; diff --git a/EngineOpl.cpp b/EngineOpl.cpp index 532f4d5..861137e 100644 --- a/EngineOpl.cpp +++ b/EngineOpl.cpp @@ -1,225 +1,213 @@ /* - * Copyright (C) 2014 Pascal Gauthier. - * Copyright (C) 2012 Steffen Ohrendorf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Original Java Code: Copyright (C) 2008 Robson Cozendey - * - * Some code based on forum posts in: http://forums.submarine.org.uk/phpBB/viewforum.php?f=9, - * Copyright (C) 2010-2013 by carbon14 and opl3 - * - */ + Copyright (C) 2014 Pascal Gauthier. + Copyright (C) 2012 Steffen Ohrendorf + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Original Java Code: Copyright (C) 2008 Robson Cozendey + + Some code based on forum posts in: http://forums.submarine.org.uk/phpBB/viewforum.php?f=9, + Copyright (C) 2010-2013 by carbon14 and opl3 + +*/ #include "EngineOpl.h" #ifdef _WIN32 - __declspec(align(16)) const int zeros[N] = {0}; +__declspec(align(16)) const int zeros[N] = {0}; #else - const int32_t __attribute__ ((aligned(16))) zeros[_N_] = {0}; +const int32_t __attribute__ ((aligned(16))) zeros[_N_] = {0}; #endif uint16_t SignBit = 0x8000; uint16_t sinLogTable[256] = { - 2137, 1731, 1543, 1419, 1326, 1252, 1190, 1137, 1091, 1050, 1013, 979, 949, 920, 894, 869, - 846, 825, 804, 785, 767, 749, 732, 717, 701, 687, 672, 659, 646, 633, 621, 609, - 598, 587, 576, 566, 556, 546, 536, 527, 518, 509, 501, 492, 484, 476, 468, 461, - 453, 446, 439, 432, 425, 418, 411, 405, 399, 392, 386, 380, 375, 369, 363, 358, - 352, 347, 341, 336, 331, 326, 321, 316, 311, 307, 302, 297, 293, 289, 284, 280, - 276, 271, 267, 263, 259, 255, 251, 248, 244, 240, 236, 233, 229, 226, 222, 219, - 215, 212, 209, 205, 202, 199, 196, 193, 190, 187, 184, 181, 178, 175, 172, 169, - 167, 164, 161, 159, 156, 153, 151, 148, 146, 143, 141, 138, 136, 134, 131, 129, - 127, 125, 122, 120, 118, 116, 114, 112, 110, 108, 106, 104, 102, 100, 98, 96, - 94, 92, 91, 89, 87, 85, 83, 82, 80, 78, 77, 75, 74, 72, 70, 69, - 67, 66, 64, 63, 62, 60, 59, 57, 56, 55, 53, 52, 51, 49, 48, 47, - 46, 45, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, - 29, 28, 27, 26, 25, 24, 23, 23, 22, 21, 20, 20, 19, 18, 17, 17, - 16, 15, 15, 14, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, - 7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 + 2137, 1731, 1543, 1419, 1326, 1252, 1190, 1137, 1091, 1050, 1013, 979, 949, 920, 894, 869, + 846, 825, 804, 785, 767, 749, 732, 717, 701, 687, 672, 659, 646, 633, 621, 609, + 598, 587, 576, 566, 556, 546, 536, 527, 518, 509, 501, 492, 484, 476, 468, 461, + 453, 446, 439, 432, 425, 418, 411, 405, 399, 392, 386, 380, 375, 369, 363, 358, + 352, 347, 341, 336, 331, 326, 321, 316, 311, 307, 302, 297, 293, 289, 284, 280, + 276, 271, 267, 263, 259, 255, 251, 248, 244, 240, 236, 233, 229, 226, 222, 219, + 215, 212, 209, 205, 202, 199, 196, 193, 190, 187, 184, 181, 178, 175, 172, 169, + 167, 164, 161, 159, 156, 153, 151, 148, 146, 143, 141, 138, 136, 134, 131, 129, + 127, 125, 122, 120, 118, 116, 114, 112, 110, 108, 106, 104, 102, 100, 98, 96, + 94, 92, 91, 89, 87, 85, 83, 82, 80, 78, 77, 75, 74, 72, 70, 69, + 67, 66, 64, 63, 62, 60, 59, 57, 56, 55, 53, 52, 51, 49, 48, 47, + 46, 45, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, + 29, 28, 27, 26, 25, 24, 23, 23, 22, 21, 20, 20, 19, 18, 17, 17, + 16, 15, 15, 14, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, + 7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; uint16_t sinExpTable[256] = { - 0, 3, 6, 8, 11, 14, 17, 20, 22, 25, 28, 31, 34, 37, 40, 42, - 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, - 93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126, 130, 133, 136, 139, - 142, 145, 148, 152, 155, 158, 161, 164, 168, 171, 174, 177, 181, 184, 187, 190, - 194, 197, 200, 204, 207, 210, 214, 217, 220, 224, 227, 231, 234, 237, 241, 244, - 248, 251, 255, 258, 262, 265, 268, 272, 276, 279, 283, 286, 290, 293, 297, 300, - 304, 308, 311, 315, 318, 322, 326, 329, 333, 337, 340, 344, 348, 352, 355, 359, - 363, 367, 370, 374, 378, 382, 385, 389, 393, 397, 401, 405, 409, 412, 416, 420, - 424, 428, 432, 436, 440, 444, 448, 452, 456, 460, 464, 468, 472, 476, 480, 484, - 488, 492, 496, 501, 505, 509, 513, 517, 521, 526, 530, 534, 538, 542, 547, 551, - 555, 560, 564, 568, 572, 577, 581, 585, 590, 594, 599, 603, 607, 612, 616, 621, - 625, 630, 634, 639, 643, 648, 652, 657, 661, 666, 670, 675, 680, 684, 689, 693, - 698, 703, 708, 712, 717, 722, 726, 731, 736, 741, 745, 750, 755, 760, 765, 770, - 774, 779, 784, 789, 794, 799, 804, 809, 814, 819, 824, 829, 834, 839, 844, 849, - 854, 859, 864, 869, 874, 880, 885, 890, 895, 900, 906, 911, 916, 921, 927, 932, - 937, 942, 948, 953, 959, 964, 969, 975, 980, 986, 991, 996, 1002, 1007, 1013, 1018 + 0, 3, 6, 8, 11, 14, 17, 20, 22, 25, 28, 31, 34, 37, 40, 42, + 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, + 93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126, 130, 133, 136, 139, + 142, 145, 148, 152, 155, 158, 161, 164, 168, 171, 174, 177, 181, 184, 187, 190, + 194, 197, 200, 204, 207, 210, 214, 217, 220, 224, 227, 231, 234, 237, 241, 244, + 248, 251, 255, 258, 262, 265, 268, 272, 276, 279, 283, 286, 290, 293, 297, 300, + 304, 308, 311, 315, 318, 322, 326, 329, 333, 337, 340, 344, 348, 352, 355, 359, + 363, 367, 370, 374, 378, 382, 385, 389, 393, 397, 401, 405, 409, 412, 416, 420, + 424, 428, 432, 436, 440, 444, 448, 452, 456, 460, 464, 468, 472, 476, 480, 484, + 488, 492, 496, 501, 505, 509, 513, 517, 521, 526, 530, 534, 538, 542, 547, 551, + 555, 560, 564, 568, 572, 577, 581, 585, 590, 594, 599, 603, 607, 612, 616, 621, + 625, 630, 634, 639, 643, 648, 652, 657, 661, 666, 670, 675, 680, 684, 689, 693, + 698, 703, 708, 712, 717, 722, 726, 731, 736, 741, 745, 750, 755, 760, 765, 770, + 774, 779, 784, 789, 794, 799, 804, 809, 814, 819, 824, 829, 834, 839, 844, 849, + 854, 859, 864, 869, 874, 880, 885, 890, 895, 900, 906, 911, 916, 921, 927, 932, + 937, 942, 948, 953, 959, 964, 969, 975, 980, 986, 991, 996, 1002, 1007, 1013, 1018 }; inline uint16_t sinLog(uint16_t phi) { - const uint8_t index = (phi & 0xff); - - switch( ( phi & 0x0300 ) ) { - case 0x0000: - // rising quarter wave Shape A - return sinLogTable[index]; - case 0x0100: - // falling quarter wave Shape B - return sinLogTable[index ^ 0xFF]; - case 0x0200: - // rising quarter wave -ve Shape C - return sinLogTable[index] | SignBit; - default: - // falling quarter wave -ve Shape D - return sinLogTable[index ^ 0xFF] | SignBit; - } + const uint8_t index = (phi & 0xff); + + switch ( ( phi & 0x0300 ) ) { + case 0x0000: + // rising quarter wave Shape A + return sinLogTable[index]; + case 0x0100: + // falling quarter wave Shape B + return sinLogTable[index ^ 0xFF]; + case 0x0200: + // rising quarter wave -ve Shape C + return sinLogTable[index] | SignBit; + default: + // falling quarter wave -ve Shape D + return sinLogTable[index ^ 0xFF] | SignBit; + } } // 16 env units are ~3dB and halve the output /** - * @brief OPL Sine Wave calculation - * @param[in] phase Wave phase (0..1023) - * @param[in] env Envelope value (0..511) - * @warning @a env will not be checked for correct values. - */ + @brief OPL Sine Wave calculation + @param[in] phase Wave phase (0..1023) + @param[in] env Envelope value (0..511) + @warning @a env will not be checked for correct values. +*/ inline int16_t oplSin( uint16_t phase, uint16_t env ) { - uint16_t expVal = sinLog(phase) + (env << 3); - const bool isSigned = expVal & SignBit; - - expVal &= ~SignBit; - // expVal: 0..2137+511*8 = 0..6225 - // result: 0..1018+1024 - uint32_t result = 0x0400 + sinExpTable[( expVal & 0xff ) ^ 0xFF]; - result <<= 1; - result >>= ( expVal >> 8 ); // exp - - if( isSigned ) { - // -1 for one's complement - return -result - 1; - } else { - return result; - } + uint16_t expVal = sinLog(phase) + (env << 3); + const bool isSigned = expVal & SignBit; + + expVal &= ~SignBit; + // expVal: 0..2137+511*8 = 0..6225 + // result: 0..1018+1024 + uint32_t result = 0x0400 + sinExpTable[( expVal & 0xff ) ^ 0xFF]; + result <<= 1; + result >>= ( expVal >> 8 ); // exp + + if ( isSigned ) { + // -1 for one's complement + return -result - 1; + } else { + return result; + } } void EngineOpl::compute(int32_t *output, const int32_t *input, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; - const int32_t *adder = add ? output : zeros; - - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t y = oplSin((phase+input[i]) >> 14, gain); - output[i] = (y << 14) + adder[i]; - phase += freq; - } + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; + int32_t gain = gain1; + int32_t phase = phase0; + const int32_t *adder = add ? output : zeros; + + for (int i = 0; i < _N_; i++) { + gain += dgain; + int32_t y = oplSin((phase + input[i]) >> 14, gain); + output[i] = (y << 14) + adder[i]; + phase += freq; + } } void EngineOpl::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; - const int32_t *adder = add ? output : zeros; - - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t y = oplSin(phase >> 14, gain); - output[i] = (y << 14) + adder[i]; - phase += freq; - } + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; + int32_t gain = gain1; + int32_t phase = phase0; + const int32_t *adder = add ? output : zeros; + + for (int i = 0; i < _N_; i++) { + gain += dgain; + int32_t y = oplSin(phase >> 14, gain); + output[i] = (y << 14) + adder[i]; + phase += freq; + } } void EngineOpl::compute_fb(int32_t *output, int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, - int32_t *fb_buf, int fb_shift, bool add) { - int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; - const int32_t *adder = add ? output : zeros; - int32_t y0 = fb_buf[0]; - int32_t y = fb_buf[1]; - - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); - y0 = y; - y = oplSin((phase+scaled_fb) >> 14, gain) << 14; - output[i] = y + adder[i]; - phase += freq; - } - - fb_buf[0] = y0; - fb_buf[1] = y; + int32_t gain1, int32_t gain2, + int32_t *fb_buf, int fb_shift, bool add) { + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; + int32_t gain = gain1; + int32_t phase = phase0; + const int32_t *adder = add ? output : zeros; + int32_t y0 = fb_buf[0]; + int32_t y = fb_buf[1]; + + for (int i = 0; i < _N_; i++) { + gain += dgain; + int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); + y0 = y; + y = oplSin((phase + scaled_fb) >> 14, gain) << 14; + output[i] = y + adder[i]; + phase += freq; + } + + fb_buf[0] = y0; + fb_buf[1] = y; } -void EngineOpl::render(int32_t *output, FmOpParams *params, int algorithm,int32_t *fb_buf, int32_t feedback_shift) { - const int kLevelThresh = 507; // really ???? - const FmAlgorithm alg = algorithms[algorithm]; - bool has_contents[3] = { true, false, false }; - for (int op = 0; op < 6; op++) { - int flags = alg.ops[op]; - bool add = (flags & OUT_BUS_ADD) != 0; - FmOpParams ¶m = params[op]; - int inbus = (flags >> 4) & 3; - int outbus = flags & 3; - int32_t *outptr = (outbus == 0) ? output : buf_[outbus - 1].get(); - int32_t gain1 = param.gain_out == 0 ? 511 : param.gain_out; - int32_t gain2 = 512-(param.level_in >> 19); - param.gain_out = gain2; - - if (gain1 <= kLevelThresh || gain2 <= kLevelThresh) { - if (!has_contents[outbus]) { - add = false; - } - if (inbus == 0 || !has_contents[inbus]) { - // todo: more than one op in a feedback loop - if ((flags & 0xc0) == 0xc0 && feedback_shift < 16) { - // cout << op << " fb " << inbus << outbus << add << endl; - compute_fb(outptr, param.phase, param.freq, - gain1, gain2, - fb_buf, feedback_shift, add); - } else { - // cout << op << " pure " << inbus << outbus << add << endl; - compute_pure(outptr, param.phase, param.freq, - gain1, gain2, add); - } - } else { - // cout << op << " normal " << inbus << outbus << " " << param.freq << add << endl; - compute(outptr, buf_[inbus - 1].get(), - param.phase, param.freq, gain1, gain2, add); - } - has_contents[outbus] = true; - } else if (!add) { - has_contents[outbus] = false; +void EngineOpl::render(int32_t *output, FmOpParams *params, int algorithm, int32_t *fb_buf, int32_t feedback_shift) { + const int kLevelThresh = 507; // really ???? + const FmAlgorithm alg = algorithms[algorithm]; + bool has_contents[3] = { true, false, false }; + for (int op = 0; op < 6; op++) { + int flags = alg.ops[op]; + bool add = (flags & OUT_BUS_ADD) != 0; + FmOpParams ¶m = params[op]; + int inbus = (flags >> 4) & 3; + int outbus = flags & 3; + int32_t *outptr = (outbus == 0) ? output : buf_[outbus - 1].get(); + int32_t gain1 = param.gain_out == 0 ? 511 : param.gain_out; + int32_t gain2 = 512 - (param.level_in >> 19); + param.gain_out = gain2; + + if (gain1 <= kLevelThresh || gain2 <= kLevelThresh) { + if (!has_contents[outbus]) { + add = false; + } + if (inbus == 0 || !has_contents[inbus]) { + // todo: more than one op in a feedback loop + if ((flags & 0xc0) == 0xc0 && feedback_shift < 16) { + // cout << op << " fb " << inbus << outbus << add << endl; + compute_fb(outptr, param.phase, param.freq, + gain1, gain2, + fb_buf, feedback_shift, add); + } else { + // cout << op << " pure " << inbus << outbus << add << endl; + compute_pure(outptr, param.phase, param.freq, + gain1, gain2, add); } - param.phase += param.freq << LG_N; + } else { + // cout << op << " normal " << inbus << outbus << " " << param.freq << add << endl; + compute(outptr, buf_[inbus - 1].get(), + param.phase, param.freq, gain1, gain2, add); + } + has_contents[outbus] = true; + } else if (!add) { + has_contents[outbus] = false; } + param.phase += param.freq << LG_N; + } } - - - - - - - - - - - - diff --git a/EngineOpl.h b/EngineOpl.h index 6f71088..0a04edc 100644 --- a/EngineOpl.h +++ b/EngineOpl.h @@ -1,22 +1,22 @@ /** - * - * Copyright (c) 2014 Pascal Gauthier. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ + + Copyright (c) 2014 Pascal Gauthier. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ #ifndef ENGINEOPL_H_INCLUDED #define ENGINEOPL_H_INCLUDED @@ -29,11 +29,11 @@ class EngineOpl : public FmCore { -public: + public: virtual void render(int32_t *output, FmOpParams *params, int algorithm, int32_t *fb_buf, int32_t feedback_shift); void compute(int32_t *output, const int32_t *input, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add); - void compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add); + void compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add); void compute_fb(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, int32_t *fb_buf, int fb_gain, bool add); diff --git a/MicroDexed.ino b/MicroDexed.ino index 038ddb5..c262852 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -1864,9 +1864,6 @@ void set_fx_params(void) modchorus_filter[instance_id]->setLowpass(2, MOD_FILTER_CUTOFF_HZ, 0.54); modchorus_filter[instance_id]->setLowpass(3, MOD_FILTER_CUTOFF_HZ, 1.3); #endif - //chorus_mixer[instance_id]->gain(0, 1.0 - pseudo_log_curve(mapfloat(configuration.fx.chorus_level[instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5))); - //chorus_mixer[instance_id]->gain(1, pseudo_log_curve(mapfloat(configuration.fx.chorus_level[instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5))); - //chorus_mixer[instance_id]->gain(0, 1.0 - mapfloat(configuration.fx.chorus_level[instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5)); chorus_mixer[instance_id]->gain(0, 1.0); chorus_mixer[instance_id]->gain(1, mapfloat(configuration.fx.chorus_level[instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5)); diff --git a/aligned_buf.h b/aligned_buf.h index 5cd1544..b6942ec 100644 --- a/aligned_buf.h +++ b/aligned_buf.h @@ -1,18 +1,18 @@ /* - * Copyright 2013 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 2013 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. +*/ // A convenient wrapper for buffers with alignment constraints @@ -25,12 +25,12 @@ template class AlignedBuf { - public: - T *get() { - return (T *)((((intptr_t)storage_) + alignment - 1) & -alignment); - } - private: - unsigned char storage_[size * sizeof(T) + alignment]; + public: + T *get() { + return (T *)((((intptr_t)storage_) + alignment - 1) & -alignment); + } + private: + unsigned char storage_[size * sizeof(T) + alignment]; }; #endif // __ALIGNED_BUF_H diff --git a/config.h b/config.h index 1422e40..55b4f4e 100644 --- a/config.h +++ b/config.h @@ -114,7 +114,7 @@ #define MOD_FILTER_OUTPUT MOD_BUTTERWORTH_FILTER_OUTPUT // MOD_LINKWITZ_RILEY_FILTER_OUTPUT MOD_BUTTERWORTH_FILTER_OUTPUT MOD_NO_FILTER_OUTPUT #define MOD_FILTER_CUTOFF_HZ 2000 // REVERB parameters -#define REVERB_ANTIALIAS_FRQ 7500 +//#define REVERB_ANTIALIAS_FRQ 7500 //#define PATCHED_FREEVERB 1 #define FREEVERB_FLOAT 1 // ANTIALIAS frequency diff --git a/dexed.cpp b/dexed.cpp index 9049849..3a00e7e 100644 --- a/dexed.cpp +++ b/dexed.cpp @@ -753,7 +753,7 @@ void Dexed::setATController(uint8_t at_range, uint8_t at_assign, uint8_t at_mode void Dexed::setPortamentoMode(uint8_t portamento_mode, uint8_t portamento_glissando, uint8_t portamento_time) { controllers.portamento_cc = portamento_time; - controllers.portamento_enable_cc=portamento_mode>63; + controllers.portamento_enable_cc = portamento_mode > 63; if (portamento_time > 0) controllers.portamento_enable_cc = true; diff --git a/effect_freeverbf.cpp b/effect_freeverbf.cpp index 54086e9..e1d2d8f 100644 --- a/effect_freeverbf.cpp +++ b/effect_freeverbf.cpp @@ -1,28 +1,28 @@ /* Audio Library for Teensy 3.X - * Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com - * - * Development of this audio library was funded by PJRC.COM, LLC by sales of - * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop - * open source software by purchasing Teensy or other PJRC products. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice, development funding notice, and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ + Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com + + Development of this audio library was funded by PJRC.COM, LLC by sales of + Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + open source software by purchasing Teensy or other PJRC products. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice, development funding notice, and this permission + notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ // A Floating point implementation of Freeverb by Jezar at Dreampoint // http://blog.bjornroche.com/2012/06/freeverb-original-public-domain-code-by.html @@ -34,41 +34,41 @@ AudioEffectFreeverbFloat::AudioEffectFreeverbFloat() : AudioStream(1, inputQueueArray) { - for(unsigned int i = 0; i < sizeof(comb1buf)/sizeof(float); i++) comb1buf[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb2buf)/sizeof(float); i++) comb2buf[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb3buf)/sizeof(float); i++) comb3buf[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb4buf)/sizeof(float); i++) comb4buf[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb5buf)/sizeof(float); i++) comb5buf[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb6buf)/sizeof(float); i++) comb6buf[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb7buf)/sizeof(float); i++) comb7buf[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb8buf)/sizeof(float); i++) comb8buf[i] = 0.0; - comb1index = 0; - comb2index = 0; - comb3index = 0; - comb4index = 0; - comb5index = 0; - comb6index = 0; - comb7index = 0; - comb8index = 0; - comb1filter = 0.0; - comb2filter = 0.0; - comb3filter = 0.0; - comb4filter = 0.0; - comb5filter = 0.0; - comb6filter = 0.0; - comb7filter = 0.0; - comb8filter = 0.0; - combdamp1 = 6553.0; - combdamp2 = 26215.0; - combfeeback = 27524.0; - for(unsigned int i = 0; i < sizeof(allpass1buf)/sizeof(float); i++) allpass1buf[i] = 0.0; - for(unsigned int i = 0; i < sizeof(allpass2buf)/sizeof(float); i++) allpass2buf[i] = 0.0; - for(unsigned int i = 0; i < sizeof(allpass3buf)/sizeof(float); i++) allpass3buf[i] = 0.0; - for(unsigned int i = 0; i < sizeof(allpass4buf)/sizeof(float); i++) allpass4buf[i] = 0.0; - allpass1index = 0; - allpass2index = 0; - allpass3index = 0; - allpass4index = 0; + for (unsigned int i = 0; i < sizeof(comb1buf) / sizeof(float); i++) comb1buf[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb2buf) / sizeof(float); i++) comb2buf[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb3buf) / sizeof(float); i++) comb3buf[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb4buf) / sizeof(float); i++) comb4buf[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb5buf) / sizeof(float); i++) comb5buf[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb6buf) / sizeof(float); i++) comb6buf[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb7buf) / sizeof(float); i++) comb7buf[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb8buf) / sizeof(float); i++) comb8buf[i] = 0.0; + comb1index = 0; + comb2index = 0; + comb3index = 0; + comb4index = 0; + comb5index = 0; + comb6index = 0; + comb7index = 0; + comb8index = 0; + comb1filter = 0.0; + comb2filter = 0.0; + comb3filter = 0.0; + comb4filter = 0.0; + comb5filter = 0.0; + comb6filter = 0.0; + comb7filter = 0.0; + comb8filter = 0.0; + combdamp1 = 6553.0; + combdamp2 = 26215.0; + combfeeback = 27524.0; + for (unsigned int i = 0; i < sizeof(allpass1buf) / sizeof(float); i++) allpass1buf[i] = 0.0; + for (unsigned int i = 0; i < sizeof(allpass2buf) / sizeof(float); i++) allpass2buf[i] = 0.0; + for (unsigned int i = 0; i < sizeof(allpass3buf) / sizeof(float); i++) allpass3buf[i] = 0.0; + for (unsigned int i = 0; i < sizeof(allpass4buf) / sizeof(float); i++) allpass4buf[i] = 0.0; + allpass1index = 0; + allpass2index = 0; + allpass3index = 0; + allpass4index = 0; } #if 0 @@ -76,23 +76,23 @@ AudioEffectFreeverbFloat::AudioEffectFreeverbFloat() : AudioStream(1, inputQueue #else // cleaner sat16 by http://www.moseleyinstruments.com/ static int16_t sat16i(int32_t n, int rshift) { - // we should always round towards 0 - // to avoid recirculating round-off noise - // - // a 2s complement positive number is always - // rounded down, so we only need to take - // care of negative numbers - if (n < 0) { - n = n + (~(0xFFFFFFFFUL << rshift)); - } - n = n >> rshift; - if (n > 32767) { - return 32767; - } - if (n < -32768) { - return -32768; - } - return n; + // we should always round towards 0 + // to avoid recirculating round-off noise + // + // a 2s complement positive number is always + // rounded down, so we only need to take + // care of negative numbers + if (n < 0) { + n = n + (~(0xFFFFFFFFUL << rshift)); + } + n = n >> rshift; + if (n > 32767) { + return 32767; + } + if (n < -32768) { + return -32768; + } + return n; } #endif @@ -105,405 +105,406 @@ static int16_t sat16i(int32_t n, int rshift) { // care of negative numbers n = n / (float) (1< 16 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 32 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 48 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 64 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 80 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 96 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 112 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif -} }; + } +}; void AudioEffectFreeverbFloat::update() { #if defined(__ARM_ARCH_7EM__) - const audio_block_t *block; - audio_block_t *outblock; - int i; - float input, bufout, output; - float sum; - - outblock = allocate(); - if (!outblock) { - audio_block_t *tmp = receiveReadOnly(0); - if (tmp) release(tmp); - return; - } - block = receiveReadOnly(0); - if (!block) block = &zeroblock; - - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - // TODO: scale numerical range depending on roomsize & damping - //input = sat16(block->data[i] * 8738, 17); // for numerical headroom - input = (float)block->data[i] / 32768.0f; - sum = 0; - - bufout = comb1buf[comb1index]; - sum += bufout; - comb1filter = bufout * combdamp2 + comb1filter * combdamp1; - comb1buf[comb1index] = input + comb1filter * combfeeback; - if (++comb1index >= sizeof(comb1buf)/sizeof(float)) comb1index = 0; - - bufout = comb2buf[comb2index]; - sum += bufout; - comb2filter = bufout * combdamp2 + comb2filter * combdamp1; - comb2buf[comb2index] = input + comb2filter * combfeeback; - if (++comb2index >= sizeof(comb2buf)/sizeof(float)) comb2index = 0; - - bufout = comb3buf[comb3index]; - sum += bufout; - comb3filter = bufout * combdamp2 + comb3filter * combdamp1; - comb3buf[comb3index] = input + comb3filter * combfeeback; - if (++comb3index >= sizeof(comb3buf)/sizeof(float)) comb3index = 0; - - bufout = comb4buf[comb4index]; - sum += bufout; - comb4filter = bufout * combdamp2 + comb4filter * combdamp1; - comb4buf[comb4index] = input + comb4filter * combfeeback; - if (++comb4index >= sizeof(comb4buf)/sizeof(float)) comb4index = 0; - - bufout = comb5buf[comb5index]; - sum += bufout; - comb5filter = bufout * combdamp2 + comb5filter * combdamp1; - comb5buf[comb5index] = input + comb5filter * combfeeback; - if (++comb5index >= sizeof(comb5buf)/sizeof(float)) comb5index = 0; - - bufout = comb6buf[comb6index]; - sum += bufout; - comb6filter = bufout * combdamp2 + comb6filter * combdamp1; - comb6buf[comb6index] = input + comb6filter * combfeeback; - if (++comb6index >= sizeof(comb6buf)/sizeof(float)) comb6index = 0; - - bufout = comb7buf[comb7index]; - sum += bufout; - comb7filter = bufout * combdamp2 + comb7filter * combdamp1; - comb7buf[comb7index] = input + comb7filter * combfeeback; - if (++comb7index >= sizeof(comb7buf)/sizeof(float)) comb7index = 0; - - bufout = comb8buf[comb8index]; - sum += bufout; - comb8filter = bufout * combdamp2 + comb8filter * combdamp1; - comb8buf[comb8index] = input + comb8filter * combfeeback; - if (++comb8index >= sizeof(comb8buf)/sizeof(float)) comb8index = 0; - - //output = sat16(sum * 31457.0, 17); - //output = sum * 31457.0/131072.0f; - output = sum; - - bufout = allpass1buf[allpass1index]; - allpass1buf[allpass1index] = output + (bufout / 2.0); - output = (bufout - output) /2.0; - if (++allpass1index >= sizeof(allpass1buf)/sizeof(float)) allpass1index = 0; - - bufout = allpass2buf[allpass2index]; - allpass2buf[allpass2index] = output + (bufout / 2.0); - output = (bufout - output) /2.0; - if (++allpass2index >= sizeof(allpass2buf)/sizeof(float)) allpass2index = 0; - - bufout = allpass3buf[allpass3index]; - allpass3buf[allpass3index] = output + (bufout / 2.0); - output = (bufout - output) /2.0; - if (++allpass3index >= sizeof(allpass3buf)/sizeof(float)) allpass3index = 0; - - bufout = allpass4buf[allpass4index]; - allpass4buf[allpass4index] = output + (bufout / 2.0); - output = (bufout - output) /2.0; - if (++allpass4index >= sizeof(allpass4buf)/sizeof(float)) allpass4index = 0; - - //outblock->data[i] = sat16i(output * 30.0, 0); - outblock->data[i] = sat16i(output * 32768.0, 0); - } - transmit(outblock); - release(outblock); - if (block != &zeroblock) release((audio_block_t *)block); + const audio_block_t *block; + audio_block_t *outblock; + int i; + float input, bufout, output; + float sum; + + outblock = allocate(); + if (!outblock) { + audio_block_t *tmp = receiveReadOnly(0); + if (tmp) release(tmp); + return; + } + block = receiveReadOnly(0); + if (!block) block = &zeroblock; + + for (i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { + // TODO: scale numerical range depending on roomsize & damping + //input = sat16(block->data[i] * 8738, 17); // for numerical headroom + input = (float)block->data[i] / 32768.0f; + sum = 0; + + bufout = comb1buf[comb1index]; + sum += bufout; + comb1filter = bufout * combdamp2 + comb1filter * combdamp1; + comb1buf[comb1index] = input + comb1filter * combfeeback; + if (++comb1index >= sizeof(comb1buf) / sizeof(float)) comb1index = 0; + + bufout = comb2buf[comb2index]; + sum += bufout; + comb2filter = bufout * combdamp2 + comb2filter * combdamp1; + comb2buf[comb2index] = input + comb2filter * combfeeback; + if (++comb2index >= sizeof(comb2buf) / sizeof(float)) comb2index = 0; + + bufout = comb3buf[comb3index]; + sum += bufout; + comb3filter = bufout * combdamp2 + comb3filter * combdamp1; + comb3buf[comb3index] = input + comb3filter * combfeeback; + if (++comb3index >= sizeof(comb3buf) / sizeof(float)) comb3index = 0; + + bufout = comb4buf[comb4index]; + sum += bufout; + comb4filter = bufout * combdamp2 + comb4filter * combdamp1; + comb4buf[comb4index] = input + comb4filter * combfeeback; + if (++comb4index >= sizeof(comb4buf) / sizeof(float)) comb4index = 0; + + bufout = comb5buf[comb5index]; + sum += bufout; + comb5filter = bufout * combdamp2 + comb5filter * combdamp1; + comb5buf[comb5index] = input + comb5filter * combfeeback; + if (++comb5index >= sizeof(comb5buf) / sizeof(float)) comb5index = 0; + + bufout = comb6buf[comb6index]; + sum += bufout; + comb6filter = bufout * combdamp2 + comb6filter * combdamp1; + comb6buf[comb6index] = input + comb6filter * combfeeback; + if (++comb6index >= sizeof(comb6buf) / sizeof(float)) comb6index = 0; + + bufout = comb7buf[comb7index]; + sum += bufout; + comb7filter = bufout * combdamp2 + comb7filter * combdamp1; + comb7buf[comb7index] = input + comb7filter * combfeeback; + if (++comb7index >= sizeof(comb7buf) / sizeof(float)) comb7index = 0; + + bufout = comb8buf[comb8index]; + sum += bufout; + comb8filter = bufout * combdamp2 + comb8filter * combdamp1; + comb8buf[comb8index] = input + comb8filter * combfeeback; + if (++comb8index >= sizeof(comb8buf) / sizeof(float)) comb8index = 0; + + //output = sat16(sum * 31457.0, 17); + //output = sum * 31457.0/131072.0f; + output = sum; + + bufout = allpass1buf[allpass1index]; + allpass1buf[allpass1index] = output + (bufout / 2.0); + output = (bufout - output) / 2.0; + if (++allpass1index >= sizeof(allpass1buf) / sizeof(float)) allpass1index = 0; + + bufout = allpass2buf[allpass2index]; + allpass2buf[allpass2index] = output + (bufout / 2.0); + output = (bufout - output) / 2.0; + if (++allpass2index >= sizeof(allpass2buf) / sizeof(float)) allpass2index = 0; + + bufout = allpass3buf[allpass3index]; + allpass3buf[allpass3index] = output + (bufout / 2.0); + output = (bufout - output) / 2.0; + if (++allpass3index >= sizeof(allpass3buf) / sizeof(float)) allpass3index = 0; + + bufout = allpass4buf[allpass4index]; + allpass4buf[allpass4index] = output + (bufout / 2.0); + output = (bufout - output) / 2.0; + if (++allpass4index >= sizeof(allpass4buf) / sizeof(float)) allpass4index = 0; + + //outblock->data[i] = sat16i(output * 30.0, 0); + outblock->data[i] = sat16i(output * 32768.0, 0); + } + transmit(outblock); + release(outblock); + if (block != &zeroblock) release((audio_block_t *)block); #elif defined(KINETISL) - audio_block_t *block; - block = receiveReadOnly(0); - if (block) release(block); + audio_block_t *block; + block = receiveReadOnly(0); + if (block) release(block); #endif } AudioEffectFreeverbStereoFloat::AudioEffectFreeverbStereoFloat() : AudioStream(1, inputQueueArray) { - for(unsigned int i = 0; i < sizeof(comb1bufL)/sizeof(float); i++) comb1bufL[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb2bufL)/sizeof(float); i++) comb2bufL[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb3bufL)/sizeof(float); i++) comb3bufL[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb4bufL)/sizeof(float); i++) comb4bufL[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb5bufL)/sizeof(float); i++) comb5bufL[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb6bufL)/sizeof(float); i++) comb6bufL[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb7bufL)/sizeof(float); i++) comb7bufL[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb8bufL)/sizeof(float); i++) comb8bufL[i] = 0.0; - comb1indexL = 0; - comb2indexL = 0; - comb3indexL = 0; - comb4indexL = 0; - comb5indexL = 0; - comb6indexL = 0; - comb7indexL = 0; - comb8indexL = 0; - comb1filterL = 0.0; - comb2filterL = 0.0; - comb3filterL = 0.0; - comb4filterL = 0.0; - comb5filterL = 0.0; - comb6filterL = 0.0; - comb7filterL = 0.0; - comb8filterL = 0.0; - for(unsigned int i = 0; i < sizeof(comb1bufR)/sizeof(float); i++) comb1bufR[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb2bufR)/sizeof(float); i++) comb2bufR[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb3bufR)/sizeof(float); i++) comb3bufR[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb4bufR)/sizeof(float); i++) comb4bufR[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb5bufR)/sizeof(float); i++) comb5bufR[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb6bufR)/sizeof(float); i++) comb6bufR[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb7bufR)/sizeof(float); i++) comb7bufR[i] = 0.0; - for(unsigned int i = 0; i < sizeof(comb8bufR)/sizeof(float); i++) comb8bufR[i] = 0.0; - comb1indexR = 0; - comb2indexR = 0; - comb3indexR = 0; - comb4indexR = 0; - comb5indexR = 0; - comb6indexR = 0; - comb7indexR = 0; - comb8indexR = 0; - comb1filterR = 0.0; - comb2filterR = 0.0; - comb3filterR = 0.0; - comb4filterR = 0.0; - comb5filterR = 0.0; - comb6filterR = 0.0; - comb7filterR = 0.0; - comb8filterR = 0.0; - combdamp1 = 6553.0; - combdamp2 = 26215.0; - combfeeback = 27524.0; - for(unsigned int i = 0; i < sizeof(allpass1bufL)/sizeof(float); i++) allpass1bufL[i] = 0.0; - for(unsigned int i = 0; i < sizeof(allpass2bufL)/sizeof(float); i++) allpass2bufL[i] = 0.0; - for(unsigned int i = 0; i < sizeof(allpass3bufL)/sizeof(float); i++) allpass3bufL[i] = 0.0; - for(unsigned int i = 0; i < sizeof(allpass4bufL)/sizeof(float); i++) allpass4bufL[i] = 0.0; - allpass1indexL = 0; - allpass2indexL = 0; - allpass3indexL = 0; - allpass4indexL = 0; - for(unsigned int i = 0; i < sizeof(allpass1bufR)/sizeof(float); i++) allpass1bufR[i] = 0.0; - for(unsigned int i = 0; i < sizeof(allpass2bufR)/sizeof(float); i++) allpass2bufR[i] = 0.0; - for(unsigned int i = 0; i < sizeof(allpass3bufR)/sizeof(float); i++) allpass3bufR[i] = 0.0; - for(unsigned int i = 0; i < sizeof(allpass4bufR)/sizeof(float); i++) allpass4bufR[i] = 0.0; - allpass1indexR = 0; - allpass2indexR = 0; - allpass3indexR = 0; - allpass4indexR = 0; + for (unsigned int i = 0; i < sizeof(comb1bufL) / sizeof(float); i++) comb1bufL[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb2bufL) / sizeof(float); i++) comb2bufL[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb3bufL) / sizeof(float); i++) comb3bufL[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb4bufL) / sizeof(float); i++) comb4bufL[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb5bufL) / sizeof(float); i++) comb5bufL[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb6bufL) / sizeof(float); i++) comb6bufL[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb7bufL) / sizeof(float); i++) comb7bufL[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb8bufL) / sizeof(float); i++) comb8bufL[i] = 0.0; + comb1indexL = 0; + comb2indexL = 0; + comb3indexL = 0; + comb4indexL = 0; + comb5indexL = 0; + comb6indexL = 0; + comb7indexL = 0; + comb8indexL = 0; + comb1filterL = 0.0; + comb2filterL = 0.0; + comb3filterL = 0.0; + comb4filterL = 0.0; + comb5filterL = 0.0; + comb6filterL = 0.0; + comb7filterL = 0.0; + comb8filterL = 0.0; + for (unsigned int i = 0; i < sizeof(comb1bufR) / sizeof(float); i++) comb1bufR[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb2bufR) / sizeof(float); i++) comb2bufR[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb3bufR) / sizeof(float); i++) comb3bufR[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb4bufR) / sizeof(float); i++) comb4bufR[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb5bufR) / sizeof(float); i++) comb5bufR[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb6bufR) / sizeof(float); i++) comb6bufR[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb7bufR) / sizeof(float); i++) comb7bufR[i] = 0.0; + for (unsigned int i = 0; i < sizeof(comb8bufR) / sizeof(float); i++) comb8bufR[i] = 0.0; + comb1indexR = 0; + comb2indexR = 0; + comb3indexR = 0; + comb4indexR = 0; + comb5indexR = 0; + comb6indexR = 0; + comb7indexR = 0; + comb8indexR = 0; + comb1filterR = 0.0; + comb2filterR = 0.0; + comb3filterR = 0.0; + comb4filterR = 0.0; + comb5filterR = 0.0; + comb6filterR = 0.0; + comb7filterR = 0.0; + comb8filterR = 0.0; + combdamp1 = 6553.0; + combdamp2 = 26215.0; + combfeeback = 27524.0; + for (unsigned int i = 0; i < sizeof(allpass1bufL) / sizeof(float); i++) allpass1bufL[i] = 0.0; + for (unsigned int i = 0; i < sizeof(allpass2bufL) / sizeof(float); i++) allpass2bufL[i] = 0.0; + for (unsigned int i = 0; i < sizeof(allpass3bufL) / sizeof(float); i++) allpass3bufL[i] = 0.0; + for (unsigned int i = 0; i < sizeof(allpass4bufL) / sizeof(float); i++) allpass4bufL[i] = 0.0; + allpass1indexL = 0; + allpass2indexL = 0; + allpass3indexL = 0; + allpass4indexL = 0; + for (unsigned int i = 0; i < sizeof(allpass1bufR) / sizeof(float); i++) allpass1bufR[i] = 0.0; + for (unsigned int i = 0; i < sizeof(allpass2bufR) / sizeof(float); i++) allpass2bufR[i] = 0.0; + for (unsigned int i = 0; i < sizeof(allpass3bufR) / sizeof(float); i++) allpass3bufR[i] = 0.0; + for (unsigned int i = 0; i < sizeof(allpass4bufR) / sizeof(float); i++) allpass4bufR[i] = 0.0; + allpass1indexR = 0; + allpass2indexR = 0; + allpass3indexR = 0; + allpass4indexR = 0; } void AudioEffectFreeverbStereoFloat::update() { #if defined(__ARM_ARCH_7EM__) - const audio_block_t *block; - audio_block_t *outblockL; - audio_block_t *outblockR; - int i; - float input, bufout, outputL, outputR; - float sum; - - block = receiveReadOnly(0); - outblockL = allocate(); - outblockR = allocate(); - if (!outblockL || !outblockR) { - if (outblockL) release(outblockL); - if (outblockR) release(outblockR); - if (block) release((audio_block_t *)block); - return; - } - if (!block) block = &zeroblock; - - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - // TODO: scale numerical range depending on roomsize & damping - //input = sat16(block->data[i] * 8738.0, 17); // for numerical headroom - input = block->data[i] / 32768.0; - sum = 0; - - bufout = comb1bufL[comb1indexL]; - sum += bufout; - comb1filterL = bufout * combdamp2 + comb1filterL * combdamp1; - comb1bufL[comb1indexL] = input + comb1filterL * combfeeback; - if (++comb1indexL >= sizeof(comb1bufL)/sizeof(float)) comb1indexL = 0; - - bufout = comb2bufL[comb2indexL]; - sum += bufout; - comb2filterL = bufout * combdamp2 + comb2filterL * combdamp1; - comb2bufL[comb2indexL] = input + comb2filterL * combfeeback; - if (++comb2indexL >= sizeof(comb2bufL)/sizeof(float)) comb2indexL = 0; - - bufout = comb3bufL[comb3indexL]; - sum += bufout; - comb3filterL = bufout * combdamp2 + comb3filterL * combdamp1; - comb3bufL[comb3indexL] = input + comb3filterL * combfeeback; - if (++comb3indexL >= sizeof(comb3bufL)/sizeof(float)) comb3indexL = 0; - - bufout = comb4bufL[comb4indexL]; - sum += bufout; - comb4filterL = bufout * combdamp2 + comb4filterL * combdamp1; - comb4bufL[comb4indexL] = input +comb4filterL * combfeeback; - if (++comb4indexL >= sizeof(comb4bufL)/sizeof(float)) comb4indexL = 0; - - bufout = comb5bufL[comb5indexL]; - sum += bufout; - comb5filterL = bufout * combdamp2 + comb5filterL * combdamp1; - comb5bufL[comb5indexL] = input + comb5filterL * combfeeback; - if (++comb5indexL >= sizeof(comb5bufL)/sizeof(float)) comb5indexL = 0; - - bufout = comb6bufL[comb6indexL]; - sum += bufout; - comb6filterL = bufout * combdamp2 + comb6filterL * combdamp1; - comb6bufL[comb6indexL] = input + comb6filterL * combfeeback; - if (++comb6indexL >= sizeof(comb6bufL)/sizeof(float)) comb6indexL = 0; - - bufout = comb7bufL[comb7indexL]; - sum += bufout; - comb7filterL = bufout * combdamp2 + comb7filterL * combdamp1; - comb7bufL[comb7indexL] = input + comb7filterL * combfeeback; - if (++comb7indexL >= sizeof(comb7bufL)/sizeof(float)) comb7indexL = 0; - - bufout = comb8bufL[comb8indexL]; - sum += bufout; - comb8filterL = bufout * combdamp2 + comb8filterL * combdamp1; - comb8bufL[comb8indexL] = input + comb8filterL * combfeeback; - if (++comb8indexL >= sizeof(comb8bufL)/sizeof(float)) comb8indexL = 0; - - //outputL = sat16(sum * 31457, 17); - //outputL = sum * 31457.0/131072.0f; - outputL = sum; - sum = 0.0; - - bufout = comb1bufR[comb1indexR]; - sum += bufout; - comb1filterR = bufout * combdamp2 + comb1filterR * combdamp1; - comb1bufR[comb1indexR] = input + comb1filterR * combfeeback; - if (++comb1indexR >= sizeof(comb1bufR)/sizeof(float)) comb1indexR = 0; - - bufout = comb2bufR[comb2indexR]; - sum += bufout; - comb2filterR = bufout * combdamp2 + comb2filterR * combdamp1; - comb2bufR[comb2indexR] = input + comb2filterR * combfeeback; - if (++comb2indexR >= sizeof(comb2bufR)/sizeof(float)) comb2indexR = 0; - - bufout = comb3bufR[comb3indexR]; - sum += bufout; - comb3filterR = bufout * combdamp2 + comb3filterR * combdamp1; - comb3bufR[comb3indexR] = input + comb3filterR * combfeeback; - if (++comb3indexR >= sizeof(comb3bufR)/sizeof(float)) comb3indexR = 0; - - bufout = comb4bufR[comb4indexR]; - sum += bufout; - comb4filterR = bufout * combdamp2 + comb4filterR * combdamp1; - comb4bufR[comb4indexR] = input + comb4filterR * combfeeback; - if (++comb4indexR >= sizeof(comb4bufR)/sizeof(float)) comb4indexR = 0; - - bufout = comb5bufR[comb5indexR]; - sum += bufout; - comb5filterR = bufout * combdamp2 + comb5filterR * combdamp1; - comb5bufR[comb5indexR] = input + comb5filterR * combfeeback; - if (++comb5indexR >= sizeof(comb5bufR)/sizeof(float)) comb5indexR = 0; - - bufout = comb6bufR[comb6indexR]; - sum += bufout; - comb6filterR = bufout * combdamp2 + comb6filterR * combdamp1; - comb6bufR[comb6indexR] = input + comb6filterR * combfeeback; - if (++comb6indexR >= sizeof(comb6bufR)/sizeof(float)) comb6indexR = 0; - - bufout = comb7bufR[comb7indexR]; - sum += bufout; - comb7filterR = bufout * combdamp2 + comb7filterR * combdamp1; - comb7bufR[comb7indexR] = input + comb7filterR * combfeeback; - if (++comb7indexR >= sizeof(comb7bufR)/sizeof(float)) comb7indexR = 0; - - bufout = comb8bufR[comb8indexR]; - sum += bufout; - comb8filterR = bufout * combdamp2 + comb8filterR * combdamp1; - comb8bufR[comb8indexR] = input + comb8filterR * combfeeback; - if (++comb8indexR >= sizeof(comb8bufR)/sizeof(float)) comb8indexR = 0; - - //outputR = sat16(sum * 31457, 17); - //outputR = sum * 31457.0/131072.0f; - outputR = sum; - - bufout = allpass1bufL[allpass1indexL]; - allpass1bufL[allpass1indexL] = outputL + (bufout / 2.0); - outputL = (bufout - outputL)/2.0; - if (++allpass1indexL >= sizeof(allpass1bufL)/sizeof(float)) allpass1indexL = 0; - - bufout = allpass2bufL[allpass2indexL]; - allpass2bufL[allpass2indexL] = outputL + (bufout / 2.0); - outputL = (bufout - outputL)/2.0; - if (++allpass2indexL >= sizeof(allpass2bufL)/sizeof(float)) allpass2indexL = 0; - - bufout = allpass3bufL[allpass3indexL]; - allpass3bufL[allpass3indexL] = outputL + (bufout / 2.0); - outputL = (bufout - outputL)/2.0; - if (++allpass3indexL >= sizeof(allpass3bufL)/sizeof(float)) allpass3indexL = 0; - - bufout = allpass4bufL[allpass4indexL]; - allpass4bufL[allpass4indexL] = outputL + (bufout / 2.0); - outputL = (bufout - outputL)/2.0; - if (++allpass4indexL >= sizeof(allpass4bufL)/sizeof(float)) allpass4indexL = 0; - - //outblockL->data[i] = sat16i(outputL * 30.0, 0); - outblockL->data[i] = sat16i(outputL * 32768.0, 0); - - bufout = allpass1bufR[allpass1indexR]; - allpass1bufR[allpass1indexR] = outputR + (bufout / 2.0); - //outputR = sat16(bufout - outputR, 1); - outputR = (bufout - outputR)/2.0; - if (++allpass1indexR >= sizeof(allpass1bufR)/sizeof(float)) allpass1indexR = 0; - - bufout = allpass2bufR[allpass2indexR]; - allpass2bufR[allpass2indexR] = outputR + (bufout / 2.0); - outputR = (bufout - outputR)/2.0; - if (++allpass2indexR >= sizeof(allpass2bufR)/sizeof(float)) allpass2indexR = 0; - - bufout = allpass3bufR[allpass3indexR]; - allpass3bufR[allpass3indexR] = outputR + (bufout / 2.0); - outputR = (bufout - outputR)/2.0; - if (++allpass3indexR >= sizeof(allpass3bufR)/sizeof(float)) allpass3indexR = 0; - - bufout = allpass4bufR[allpass4indexR]; - allpass4bufR[allpass4indexR] = outputR + (bufout / 2.0); - outputR = (bufout - outputR)/2.0; - if (++allpass4indexR >= sizeof(allpass4bufR)/sizeof(float)) allpass4indexR = 0; - - //outblockR->data[i] = sat16i(outputR * 30.0, 0); - outblockR->data[i] = sat16i(outputR * 32768.0, 0); - } - transmit(outblockL, 0); - transmit(outblockR, 1); - release(outblockL); - release(outblockR); - if (block != &zeroblock) release((audio_block_t *)block); + const audio_block_t *block; + audio_block_t *outblockL; + audio_block_t *outblockR; + int i; + float input, bufout, outputL, outputR; + float sum; + + block = receiveReadOnly(0); + outblockL = allocate(); + outblockR = allocate(); + if (!outblockL || !outblockR) { + if (outblockL) release(outblockL); + if (outblockR) release(outblockR); + if (block) release((audio_block_t *)block); + return; + } + if (!block) block = &zeroblock; + + for (i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { + // TODO: scale numerical range depending on roomsize & damping + //input = sat16(block->data[i] * 8738.0, 17); // for numerical headroom + input = block->data[i] / 32768.0; + sum = 0; + + bufout = comb1bufL[comb1indexL]; + sum += bufout; + comb1filterL = bufout * combdamp2 + comb1filterL * combdamp1; + comb1bufL[comb1indexL] = input + comb1filterL * combfeeback; + if (++comb1indexL >= sizeof(comb1bufL) / sizeof(float)) comb1indexL = 0; + + bufout = comb2bufL[comb2indexL]; + sum += bufout; + comb2filterL = bufout * combdamp2 + comb2filterL * combdamp1; + comb2bufL[comb2indexL] = input + comb2filterL * combfeeback; + if (++comb2indexL >= sizeof(comb2bufL) / sizeof(float)) comb2indexL = 0; + + bufout = comb3bufL[comb3indexL]; + sum += bufout; + comb3filterL = bufout * combdamp2 + comb3filterL * combdamp1; + comb3bufL[comb3indexL] = input + comb3filterL * combfeeback; + if (++comb3indexL >= sizeof(comb3bufL) / sizeof(float)) comb3indexL = 0; + + bufout = comb4bufL[comb4indexL]; + sum += bufout; + comb4filterL = bufout * combdamp2 + comb4filterL * combdamp1; + comb4bufL[comb4indexL] = input + comb4filterL * combfeeback; + if (++comb4indexL >= sizeof(comb4bufL) / sizeof(float)) comb4indexL = 0; + + bufout = comb5bufL[comb5indexL]; + sum += bufout; + comb5filterL = bufout * combdamp2 + comb5filterL * combdamp1; + comb5bufL[comb5indexL] = input + comb5filterL * combfeeback; + if (++comb5indexL >= sizeof(comb5bufL) / sizeof(float)) comb5indexL = 0; + + bufout = comb6bufL[comb6indexL]; + sum += bufout; + comb6filterL = bufout * combdamp2 + comb6filterL * combdamp1; + comb6bufL[comb6indexL] = input + comb6filterL * combfeeback; + if (++comb6indexL >= sizeof(comb6bufL) / sizeof(float)) comb6indexL = 0; + + bufout = comb7bufL[comb7indexL]; + sum += bufout; + comb7filterL = bufout * combdamp2 + comb7filterL * combdamp1; + comb7bufL[comb7indexL] = input + comb7filterL * combfeeback; + if (++comb7indexL >= sizeof(comb7bufL) / sizeof(float)) comb7indexL = 0; + + bufout = comb8bufL[comb8indexL]; + sum += bufout; + comb8filterL = bufout * combdamp2 + comb8filterL * combdamp1; + comb8bufL[comb8indexL] = input + comb8filterL * combfeeback; + if (++comb8indexL >= sizeof(comb8bufL) / sizeof(float)) comb8indexL = 0; + + //outputL = sat16(sum * 31457, 17); + //outputL = sum * 31457.0/131072.0f; + outputL = sum; + sum = 0.0; + + bufout = comb1bufR[comb1indexR]; + sum += bufout; + comb1filterR = bufout * combdamp2 + comb1filterR * combdamp1; + comb1bufR[comb1indexR] = input + comb1filterR * combfeeback; + if (++comb1indexR >= sizeof(comb1bufR) / sizeof(float)) comb1indexR = 0; + + bufout = comb2bufR[comb2indexR]; + sum += bufout; + comb2filterR = bufout * combdamp2 + comb2filterR * combdamp1; + comb2bufR[comb2indexR] = input + comb2filterR * combfeeback; + if (++comb2indexR >= sizeof(comb2bufR) / sizeof(float)) comb2indexR = 0; + + bufout = comb3bufR[comb3indexR]; + sum += bufout; + comb3filterR = bufout * combdamp2 + comb3filterR * combdamp1; + comb3bufR[comb3indexR] = input + comb3filterR * combfeeback; + if (++comb3indexR >= sizeof(comb3bufR) / sizeof(float)) comb3indexR = 0; + + bufout = comb4bufR[comb4indexR]; + sum += bufout; + comb4filterR = bufout * combdamp2 + comb4filterR * combdamp1; + comb4bufR[comb4indexR] = input + comb4filterR * combfeeback; + if (++comb4indexR >= sizeof(comb4bufR) / sizeof(float)) comb4indexR = 0; + + bufout = comb5bufR[comb5indexR]; + sum += bufout; + comb5filterR = bufout * combdamp2 + comb5filterR * combdamp1; + comb5bufR[comb5indexR] = input + comb5filterR * combfeeback; + if (++comb5indexR >= sizeof(comb5bufR) / sizeof(float)) comb5indexR = 0; + + bufout = comb6bufR[comb6indexR]; + sum += bufout; + comb6filterR = bufout * combdamp2 + comb6filterR * combdamp1; + comb6bufR[comb6indexR] = input + comb6filterR * combfeeback; + if (++comb6indexR >= sizeof(comb6bufR) / sizeof(float)) comb6indexR = 0; + + bufout = comb7bufR[comb7indexR]; + sum += bufout; + comb7filterR = bufout * combdamp2 + comb7filterR * combdamp1; + comb7bufR[comb7indexR] = input + comb7filterR * combfeeback; + if (++comb7indexR >= sizeof(comb7bufR) / sizeof(float)) comb7indexR = 0; + + bufout = comb8bufR[comb8indexR]; + sum += bufout; + comb8filterR = bufout * combdamp2 + comb8filterR * combdamp1; + comb8bufR[comb8indexR] = input + comb8filterR * combfeeback; + if (++comb8indexR >= sizeof(comb8bufR) / sizeof(float)) comb8indexR = 0; + + //outputR = sat16(sum * 31457, 17); + //outputR = sum * 31457.0/131072.0f; + outputR = sum; + + bufout = allpass1bufL[allpass1indexL]; + allpass1bufL[allpass1indexL] = outputL + (bufout / 2.0); + outputL = (bufout - outputL) / 2.0; + if (++allpass1indexL >= sizeof(allpass1bufL) / sizeof(float)) allpass1indexL = 0; + + bufout = allpass2bufL[allpass2indexL]; + allpass2bufL[allpass2indexL] = outputL + (bufout / 2.0); + outputL = (bufout - outputL) / 2.0; + if (++allpass2indexL >= sizeof(allpass2bufL) / sizeof(float)) allpass2indexL = 0; + + bufout = allpass3bufL[allpass3indexL]; + allpass3bufL[allpass3indexL] = outputL + (bufout / 2.0); + outputL = (bufout - outputL) / 2.0; + if (++allpass3indexL >= sizeof(allpass3bufL) / sizeof(float)) allpass3indexL = 0; + + bufout = allpass4bufL[allpass4indexL]; + allpass4bufL[allpass4indexL] = outputL + (bufout / 2.0); + outputL = (bufout - outputL) / 2.0; + if (++allpass4indexL >= sizeof(allpass4bufL) / sizeof(float)) allpass4indexL = 0; + + //outblockL->data[i] = sat16i(outputL * 30.0, 0); + outblockL->data[i] = sat16i(outputL * 32768.0, 0); + + bufout = allpass1bufR[allpass1indexR]; + allpass1bufR[allpass1indexR] = outputR + (bufout / 2.0); + //outputR = sat16(bufout - outputR, 1); + outputR = (bufout - outputR) / 2.0; + if (++allpass1indexR >= sizeof(allpass1bufR) / sizeof(float)) allpass1indexR = 0; + + bufout = allpass2bufR[allpass2indexR]; + allpass2bufR[allpass2indexR] = outputR + (bufout / 2.0); + outputR = (bufout - outputR) / 2.0; + if (++allpass2indexR >= sizeof(allpass2bufR) / sizeof(float)) allpass2indexR = 0; + + bufout = allpass3bufR[allpass3indexR]; + allpass3bufR[allpass3indexR] = outputR + (bufout / 2.0); + outputR = (bufout - outputR) / 2.0; + if (++allpass3indexR >= sizeof(allpass3bufR) / sizeof(float)) allpass3indexR = 0; + + bufout = allpass4bufR[allpass4indexR]; + allpass4bufR[allpass4indexR] = outputR + (bufout / 2.0); + outputR = (bufout - outputR) / 2.0; + if (++allpass4indexR >= sizeof(allpass4bufR) / sizeof(float)) allpass4indexR = 0; + + //outblockR->data[i] = sat16i(outputR * 30.0, 0); + outblockR->data[i] = sat16i(outputR * 32768.0, 0); + } + transmit(outblockL, 0); + transmit(outblockR, 1); + release(outblockL); + release(outblockR); + if (block != &zeroblock) release((audio_block_t *)block); #elif defined(KINETISL) - audio_block_t *block; - block = receiveReadOnly(0); - if (block) release(block); + audio_block_t *block; + block = receiveReadOnly(0); + if (block) release(block); #endif } diff --git a/effect_freeverbf.h b/effect_freeverbf.h index 7fae9ec..abae8ca 100644 --- a/effect_freeverbf.h +++ b/effect_freeverbf.h @@ -1,28 +1,28 @@ /* Audio Library for Teensy 3.X - * Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com - * - * Development of this audio library was funded by PJRC.COM, LLC by sales of - * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop - * open source software by purchasing Teensy or other PJRC products. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice, development funding notice, and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ + Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com + + Development of this audio library was funded by PJRC.COM, LLC by sales of + Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + open source software by purchasing Teensy or other PJRC products. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice, development funding notice, and this permission + notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ #ifndef effect_freeverb_f_h_ #define effect_freeverb_f_h_ @@ -31,159 +31,159 @@ class AudioEffectFreeverbFloat : public AudioStream { -public: - AudioEffectFreeverbFloat(); - virtual void update(); - void roomsize(float n) { - if (n > 1.0f) n = 1.0f; - else if (n < 0.0) n = 0.0f; - //combfeeback = (n * 9175.04f) + 22937.0; - combfeeback = (n * 9175.04f/32768.0f) + 22937.0/32768.0f; - } - void damping(float n) { - if (n > 1.0f) n = 1.0f; - else if (n < 0.0) n = 0.0f; - //float x1 = (n * 13107.2f); - //float x2 = 32768.0 - x1; - float x1 = (n * 13107.2f/ 32768.0f); - float x2 = 1.0 - x1; - __disable_irq(); - combdamp1 = x1; - combdamp2 = x2; - __enable_irq(); - } -private: - audio_block_t *inputQueueArray[1]; - float comb1buf[1116]; - float comb2buf[1188]; - float comb3buf[1277]; - float comb4buf[1356]; - float comb5buf[1422]; - float comb6buf[1491]; - float comb7buf[1557]; - float comb8buf[1617]; - uint16_t comb1index; - uint16_t comb2index; - uint16_t comb3index; - uint16_t comb4index; - uint16_t comb5index; - uint16_t comb6index; - uint16_t comb7index; - uint16_t comb8index; - float comb1filter; - float comb2filter; - float comb3filter; - float comb4filter; - float comb5filter; - float comb6filter; - float comb7filter; - float comb8filter; - float combdamp1; - float combdamp2; - float combfeeback; - float allpass1buf[556]; - float allpass2buf[441]; - float allpass3buf[341]; - float allpass4buf[225]; - uint16_t allpass1index; - uint16_t allpass2index; - uint16_t allpass3index; - uint16_t allpass4index; + public: + AudioEffectFreeverbFloat(); + virtual void update(); + void roomsize(float n) { + if (n > 1.0f) n = 1.0f; + else if (n < 0.0) n = 0.0f; + //combfeeback = (n * 9175.04f) + 22937.0; + combfeeback = (n * 9175.04f / 32768.0f) + 22937.0 / 32768.0f; + } + void damping(float n) { + if (n > 1.0f) n = 1.0f; + else if (n < 0.0) n = 0.0f; + //float x1 = (n * 13107.2f); + //float x2 = 32768.0 - x1; + float x1 = (n * 13107.2f / 32768.0f); + float x2 = 1.0 - x1; + __disable_irq(); + combdamp1 = x1; + combdamp2 = x2; + __enable_irq(); + } + private: + audio_block_t *inputQueueArray[1]; + float comb1buf[1116]; + float comb2buf[1188]; + float comb3buf[1277]; + float comb4buf[1356]; + float comb5buf[1422]; + float comb6buf[1491]; + float comb7buf[1557]; + float comb8buf[1617]; + uint16_t comb1index; + uint16_t comb2index; + uint16_t comb3index; + uint16_t comb4index; + uint16_t comb5index; + uint16_t comb6index; + uint16_t comb7index; + uint16_t comb8index; + float comb1filter; + float comb2filter; + float comb3filter; + float comb4filter; + float comb5filter; + float comb6filter; + float comb7filter; + float comb8filter; + float combdamp1; + float combdamp2; + float combfeeback; + float allpass1buf[556]; + float allpass2buf[441]; + float allpass3buf[341]; + float allpass4buf[225]; + uint16_t allpass1index; + uint16_t allpass2index; + uint16_t allpass3index; + uint16_t allpass4index; }; class AudioEffectFreeverbStereoFloat : public AudioStream { -public: - AudioEffectFreeverbStereoFloat(); - virtual void update(); - void roomsize(float n) { - if (n > 1.0f) n = 1.0f; - else if (n < 0.0) n = 0.0f; - //combfeeback = (n * 9175.04f) + 22937.0; - combfeeback = (n * 9175.04f/32768.0f) + 22937.0/32768.0f; - } - void damping(float n) { - if (n > 1.0f) n = 1.0f; - else if (n < 0.0) n = 0.0f; - //float x1 = (n * 13107.2f); - //float x2 = 32768.0 - x1; - float x1 = (n * 13107.2f/ 32768.0f); - float x2 = 1.0 - x1; - __disable_irq(); - combdamp1 = x1; - combdamp2 = x2; - __enable_irq(); - } -private: - audio_block_t *inputQueueArray[1]; - float comb1bufL[1116]; - float comb2bufL[1188]; - float comb3bufL[1277]; - float comb4bufL[1356]; - float comb5bufL[1422]; - float comb6bufL[1491]; - float comb7bufL[1557]; - float comb8bufL[1617]; - uint16_t comb1indexL; - uint16_t comb2indexL; - uint16_t comb3indexL; - uint16_t comb4indexL; - uint16_t comb5indexL; - uint16_t comb6indexL; - uint16_t comb7indexL; - uint16_t comb8indexL; - float comb1filterL; - float comb2filterL; - float comb3filterL; - float comb4filterL; - float comb5filterL; - float comb6filterL; - float comb7filterL; - float comb8filterL; - float comb1bufR[1139]; - float comb2bufR[1211]; - float comb3bufR[1300]; - float comb4bufR[1379]; - float comb5bufR[1445]; - float comb6bufR[1514]; - float comb7bufR[1580]; - float comb8bufR[1640]; - uint16_t comb1indexR; - uint16_t comb2indexR; - uint16_t comb3indexR; - uint16_t comb4indexR; - uint16_t comb5indexR; - uint16_t comb6indexR; - uint16_t comb7indexR; - uint16_t comb8indexR; - float comb1filterR; - float comb2filterR; - float comb3filterR; - float comb4filterR; - float comb5filterR; - float comb6filterR; - float comb7filterR; - float comb8filterR; - float combdamp1; - float combdamp2; - float combfeeback; - float allpass1bufL[556]; - float allpass2bufL[441]; - float allpass3bufL[341]; - float allpass4bufL[225]; - uint16_t allpass1indexL; - uint16_t allpass2indexL; - uint16_t allpass3indexL; - uint16_t allpass4indexL; - float allpass1bufR[579]; - float allpass2bufR[464]; - float allpass3bufR[364]; - float allpass4bufR[248]; - uint16_t allpass1indexR; - uint16_t allpass2indexR; - uint16_t allpass3indexR; - uint16_t allpass4indexR; + public: + AudioEffectFreeverbStereoFloat(); + virtual void update(); + void roomsize(float n) { + if (n > 1.0f) n = 1.0f; + else if (n < 0.0) n = 0.0f; + //combfeeback = (n * 9175.04f) + 22937.0; + combfeeback = (n * 9175.04f / 32768.0f) + 22937.0 / 32768.0f; + } + void damping(float n) { + if (n > 1.0f) n = 1.0f; + else if (n < 0.0) n = 0.0f; + //float x1 = (n * 13107.2f); + //float x2 = 32768.0 - x1; + float x1 = (n * 13107.2f / 32768.0f); + float x2 = 1.0 - x1; + __disable_irq(); + combdamp1 = x1; + combdamp2 = x2; + __enable_irq(); + } + private: + audio_block_t *inputQueueArray[1]; + float comb1bufL[1116]; + float comb2bufL[1188]; + float comb3bufL[1277]; + float comb4bufL[1356]; + float comb5bufL[1422]; + float comb6bufL[1491]; + float comb7bufL[1557]; + float comb8bufL[1617]; + uint16_t comb1indexL; + uint16_t comb2indexL; + uint16_t comb3indexL; + uint16_t comb4indexL; + uint16_t comb5indexL; + uint16_t comb6indexL; + uint16_t comb7indexL; + uint16_t comb8indexL; + float comb1filterL; + float comb2filterL; + float comb3filterL; + float comb4filterL; + float comb5filterL; + float comb6filterL; + float comb7filterL; + float comb8filterL; + float comb1bufR[1139]; + float comb2bufR[1211]; + float comb3bufR[1300]; + float comb4bufR[1379]; + float comb5bufR[1445]; + float comb6bufR[1514]; + float comb7bufR[1580]; + float comb8bufR[1640]; + uint16_t comb1indexR; + uint16_t comb2indexR; + uint16_t comb3indexR; + uint16_t comb4indexR; + uint16_t comb5indexR; + uint16_t comb6indexR; + uint16_t comb7indexR; + uint16_t comb8indexR; + float comb1filterR; + float comb2filterR; + float comb3filterR; + float comb4filterR; + float comb5filterR; + float comb6filterR; + float comb7filterR; + float comb8filterR; + float combdamp1; + float combdamp2; + float combfeeback; + float allpass1bufL[556]; + float allpass2bufL[441]; + float allpass3bufL[341]; + float allpass4bufL[225]; + uint16_t allpass1indexL; + uint16_t allpass2indexL; + uint16_t allpass3indexL; + uint16_t allpass4indexL; + float allpass1bufR[579]; + float allpass2bufR[464]; + float allpass3bufR[364]; + float allpass4bufR[248]; + uint16_t allpass1indexR; + uint16_t allpass2indexR; + uint16_t allpass3indexR; + uint16_t allpass4indexR; }; diff --git a/effect_modulated_delay.cpp b/effect_modulated_delay.cpp index f0a0610..d43a4dd 100644 --- a/effect_modulated_delay.cpp +++ b/effect_modulated_delay.cpp @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2014, Pete (El Supremo) Copyright (c) 2019-2020, Holger Wirtz diff --git a/effect_modulated_delay.h b/effect_modulated_delay.h index 61bcc2b..02934f2 100644 --- a/effect_modulated_delay.h +++ b/effect_modulated_delay.h @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2014, Pete (El Supremo) Copyright (c) 2019-2020, Holger Wirtz diff --git a/effect_stereo_mono.cpp b/effect_stereo_mono.cpp index 6d4865e..6bd9b83 100644 --- a/effect_stereo_mono.cpp +++ b/effect_stereo_mono.cpp @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2019-2020, Holger Wirtz Permission is hereby granted, free of charge, to any person obtaining a copy @@ -56,7 +56,7 @@ void AudioEffectStereoMono::update(void) bp[1]++; } #else - // devide every channel by 2 + // devide every channel by 2 arm_shift_q15(block[0]->data, -1, block[0]->data, AUDIO_BLOCK_SAMPLES); arm_shift_q15(block[1]->data, -1, block[1]->data, AUDIO_BLOCK_SAMPLES); // add channel 2 to channel 1 diff --git a/effect_stereo_mono.h b/effect_stereo_mono.h index 66282ce..f1774ab 100644 --- a/effect_stereo_mono.h +++ b/effect_stereo_mono.h @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2019-2020, Holger Wirtz Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/env.cc b/env.cc deleted file mode 100644 index 8e497c4..0000000 --- a/env.cc +++ /dev/null @@ -1,188 +0,0 @@ -/* - * 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. - */ - -#include - -#include "synth.h" -#include "env.h" - -//using namespace std; - -uint32_t Env::sr_multiplier = (1<<24); - -const int 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 int 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 FRAC_NUM-checked anyway) -}; -#endif - -void Env::init_sr(FRAC_NUM sampleRate) { - sr_multiplier = (44100.0 / sampleRate) * (1<<24); -} - -void Env::init(const int r[4], const int l[4], int ol, int 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 (rising_) { - const int 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 if (staticcount_) { - ; - } - 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); - } -} - -int Env::scaleoutlevel(int outlevel) { - return outlevel >= 20 ? 28 + outlevel : levellut[outlevel]; -} - -void Env::advance(int newix) { - ix_ = newix; - if (ix_ < 4) { - int newlevel = levels_[ix_]; - int 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 - int qrate = (rates_[ix_] * 41) >> 6; - qrate += rate_scaling_; - qrate = min(qrate, 63); - -#ifdef ACCURATE_ENVELOPE - if (targetlevel_ == level_) { - // approximate number of samples at 44.100 kHz to achieve the time - // empirically gathered using 2 TF1s, could probably use some FRAC_NUM-checking - // and cleanup, but it's pretty close for now. - int staticrate = rates_[ix_]; - staticrate += rate_scaling_; // needs to be checked, as well, but seems correct - staticrate = min(staticrate, 99); - staticcount_ = staticrate < 77 ? statics[staticrate] : 20 * (99 - staticrate); - 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 int r[4], const int l[4], int ol, int 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 ourselve at level 3 - int newlevel = levels_[2]; - int 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_; -} - diff --git a/env.cpp b/env.cpp index 797841f..5306c39 100644 --- a/env.cpp +++ b/env.cpp @@ -1,19 +1,19 @@ /* - * 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. - */ + 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. +*/ #include @@ -22,17 +22,32 @@ //using namespace std; -uint32_t Env::sr_multiplier = (1<<24); +uint32_t Env::sr_multiplier = (1 << 24); const int levellut[] = { - 0, 5, 9, 13, 17, 20, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 42, 43, 45, 46 + 0, 5, 9, 13, 17, 20, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 42, 43, 45, 46 }; -void Env::init_sr(FRAC_NUM sampleRate) { - sr_multiplier = (44100.0 / sampleRate) * (1<<24); +#ifdef ACCURATE_ENVELOPE +const int 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 int r[4], const int l[4], int32_t ol, int rate_scaling) { +void Env::init(const int r[4], const int l[4], int ol, int rate_scaling) { for (int i = 0; i < 4; i++) { rates_[i] = r[i]; levels_[i] = l[i]; @@ -45,8 +60,21 @@ void Env::init(const int r[4], const int l[4], int32_t ol, int rate_scaling) { } 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 (rising_) { + if (staticcount_) { + ; + } + else if (rising_) { const int jumptarget = 1716; if (level_ < (jumptarget << 16)) { level_ = jumptarget << 16; @@ -57,7 +85,8 @@ int32_t Env::getsample() { level_ = targetlevel_; advance(ix_ + 1); } - } else { // !rising + } + else { // !rising level_ -= inc_; if (level_ <= targetlevel_) { level_ = targetlevel_; @@ -71,8 +100,8 @@ int32_t Env::getsample() { void Env::keydown(bool d) { if (down_ != d) { - down_ = d; - advance(d ? 0 : 3); + down_ = d; + advance(d ? 0 : 3); } } @@ -95,22 +124,40 @@ void Env::advance(int newix) { int qrate = (rates_[ix_] * 41) >> 6; qrate += rate_scaling_; qrate = min(qrate, 63); - inc_ = (4 + (qrate & 3)) << (2 + LG_N + (qrate >> 2)); +#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. + int staticrate = rates_[ix_]; + staticrate += rate_scaling_; // needs to be checked, as well, but seems correct + staticrate = min(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_ = ((int64_t)inc_ * (int64_t)sr_multiplier) >> 24; + inc_ = (int)(((int64_t)inc_ * (int64_t)sr_multiplier) >> 24); } } -void Env::update(const int r[4], const int l[4], int32_t ol, int rate_scaling) { +void Env::update(const int r[4], const int l[4], int ol, int rate_scaling) { for (int i = 0; i < 4; i++) { - rates_[i] = r[i]; - levels_[i] = l[i]; + rates_[i] = r[i]; + levels_[i] = l[i]; } outlevel_ = ol; rate_scaling_ = rate_scaling; if ( down_ ) { - // for now we simply reset ourselve at level 3 + // for now we simply reset ourselves at level 3 int newlevel = levels_[2]; int actuallevel = scaleoutlevel(newlevel) >> 1; actuallevel = (actuallevel << 6) - 4256; @@ -121,21 +168,23 @@ void Env::update(const int r[4], const int l[4], int32_t ol, int rate_scaling) { } void Env::getPosition(char *step) { - *step = ix_; + *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_; - inc_ = src.inc_; - down_ = src.down_; + 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_; } - diff --git a/env.h b/env.h index cc5b124..30bbfec 100644 --- a/env.h +++ b/env.h @@ -1,19 +1,19 @@ /* - * 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. - */ + 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. +*/ #ifndef __ENV_H #define __ENV_H @@ -25,58 +25,57 @@ #define ACCURATE_ENVELOPE class Env { - public: - - // The rates and levels arrays are calibrated to match the Dx7 parameters - // (ie, value 0..99). The outlevel parameter is calibrated in microsteps - // (ie units of approx .023 dB), with 99 * 32 = nominal full scale. The - // rate_scaling parameter is in qRate units (ie 0..63). - void init(const int rates[4], const int levels[4], int32_t outlevel, - int rate_scaling); - - void update(const int rates[4], const int levels[4], int32_t outlevel, - int rate_scaling); - // Result is in Q24/doubling log format. Also, result is subsampled - // for every N samples. - // A couple more things need to happen for this to be used as a gain - // value. First, the # of outputs scaling needs to be applied. Also, - // modulation. - // Then, of course, log to linear. - int32_t getsample(); - - void keydown(bool down); - static int scaleoutlevel(int outlevel); - void getPosition(char *step); - - static void init_sr(FRAC_NUM sample_rate); - void transfer(Env &src); - - private: - - // PG: This code is normalized to 44100, need to put a multiplier - // if we are not using 44100. - static uint32_t sr_multiplier; - - int rates_[4]; - int levels_[4]; - int outlevel_; - int rate_scaling_; - // Level is stored so that 2^24 is one doubling, ie 16 more bits than - // the DX7 itself (fraction is stored in level rather than separate - // counter) - int32_t level_; - int targetlevel_; - bool rising_; - int ix_; - int inc_; + public: + + // The rates and levels arrays are calibrated to match the Dx7 parameters + // (ie, value 0..99). The outlevel parameter is calibrated in microsteps + // (ie units of approx .023 dB), with 99 * 32 = nominal full scale. The + // rate_scaling parameter is in qRate units (ie 0..63). + void init(const int rates[4], const int levels[4], int outlevel, + int rate_scaling); + + void update(const int rates[4], const int levels[4], int outlevel, + int rate_scaling); + // Result is in Q24/doubling log format. Also, result is subsampled + // for every N samples. + // A couple more things need to happen for this to be used as a gain + // value. First, the # of outputs scaling needs to be applied. Also, + // modulation. + // Then, of course, log to linear. + int32_t getsample(); + + void keydown(bool down); + static int scaleoutlevel(int outlevel); + void getPosition(char *step); + + static void init_sr(double sample_rate); + void transfer(Env &src); + + private: + + // PG: This code is normalized to 44100, need to put a multiplier + // if we are not using 44100. + static uint32_t sr_multiplier; + + int rates_[4]; + int levels_[4]; + int outlevel_; + int rate_scaling_; + // Level is stored so that 2^24 is one doubling, ie 16 more bits than + // the DX7 itself (fraction is stored in level rather than separate + // counter) + int32_t level_; + int targetlevel_; + bool rising_; + int ix_; + int inc_; #ifdef ACCURATE_ENVELOPE - int staticcount_; + int staticcount_; #endif - bool down_; + bool down_; - void advance(int newix); + void advance(int newix); }; #endif // __ENV_H - diff --git a/exp2.h b/exp2.h index 016ca33..29dc298 100644 --- a/exp2.h +++ b/exp2.h @@ -1,27 +1,27 @@ /* - * 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 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. +*/ class Exp2 { - public: - Exp2(); + public: + Exp2(); - static void init(); + static void init(); - // Q24 in, Q24 out - static int32_t lookup(int32_t x); + // Q24 in, Q24 out + static int32_t lookup(int32_t x); }; #define EXP2_LG_N_SAMPLES 10 @@ -46,11 +46,11 @@ int32_t Exp2::lookup(int32_t x) { #endif class Tanh { - public: - static void init(); + public: + static void init(); - // Q24 in, Q24 out - static int32_t lookup(int32_t x); + // Q24 in, Q24 out + static int32_t lookup(int32_t x); }; #define TANH_LG_N_SAMPLES 10 @@ -66,7 +66,7 @@ int32_t Tanh::lookup(int32_t x) { if (x >= (17 << 23)) { return signum ^ (1 << 24); } - int32_t sx = ((int64_t)-48408812 * (int64_t)x) >> 24; + int32_t sx = ((int64_t) - 48408812 * (int64_t)x) >> 24; return signum ^ ((1 << 24) - 2 * Exp2::lookup(sx)); } else { const int SHIFT = 26 - TANH_LG_N_SAMPLES; diff --git a/fm_core.cpp b/fm_core.cpp index 476cd8d..03331cc 100644 --- a/fm_core.cpp +++ b/fm_core.cpp @@ -1,18 +1,18 @@ /* - * 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 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. +*/ #ifdef VERBOSE #include @@ -71,13 +71,13 @@ int n_out(const FmAlgorithm &alg) { uint8_t FmCore::get_carrier_operators(uint8_t algorithm) { - uint8_t op_out=0; - FmAlgorithm alg=algorithms[algorithm]; + uint8_t op_out = 0; + FmAlgorithm alg = algorithms[algorithm]; - for(uint8_t i=0; i<6;i++) + for (uint8_t i = 0; i < 6; i++) { - if((alg.ops[i]&OUT_BUS_ADD)==OUT_BUS_ADD) - op_out|=1<> 4) & 3; - int outbus = flags & 3; - int32_t *outptr = (outbus == 0) ? output : buf_[outbus - 1].get(); - int32_t gain1 = param.gain_out; - int32_t gain2 = Exp2::lookup(param.level_in - (14 * (1 << 24))); - param.gain_out = gain2; - - if (gain1 >= kLevelThresh || gain2 >= kLevelThresh) { - if (!has_contents[outbus]) { - add = false; - } - if (inbus == 0 || !has_contents[inbus]) { - // todo: more than one op in a feedback loop - if ((flags & 0xc0) == 0xc0 && feedback_shift < 16) { - // cout << op << " fb " << inbus << outbus << add << endl; - FmOpKernel::compute_fb(outptr, param.phase, param.freq, - gain1, gain2, - fb_buf, feedback_shift, add); - } else { - // cout << op << " pure " << inbus << outbus << add << endl; - FmOpKernel::compute_pure(outptr, param.phase, param.freq, - gain1, gain2, add); - } - } else { - // cout << op << " normal " << inbus << outbus << " " << param.freq << add << endl; - FmOpKernel::compute(outptr, buf_[inbus - 1].get(), - param.phase, param.freq, gain1, gain2, add); - } - has_contents[outbus] = true; - } else if (!add) { - has_contents[outbus] = false; + const int kLevelThresh = 1120; + const FmAlgorithm alg = algorithms[algorithm]; + bool has_contents[3] = { true, false, false }; + for (int op = 0; op < 6; op++) { + int flags = alg.ops[op]; + bool add = (flags & OUT_BUS_ADD) != 0; + FmOpParams ¶m = params[op]; + int inbus = (flags >> 4) & 3; + int outbus = flags & 3; + int32_t *outptr = (outbus == 0) ? output : buf_[outbus - 1].get(); + int32_t gain1 = param.gain_out; + int32_t gain2 = Exp2::lookup(param.level_in - (14 * (1 << 24))); + param.gain_out = gain2; + + if (gain1 >= kLevelThresh || gain2 >= kLevelThresh) { + if (!has_contents[outbus]) { + add = false; + } + if (inbus == 0 || !has_contents[inbus]) { + // todo: more than one op in a feedback loop + if ((flags & 0xc0) == 0xc0 && feedback_shift < 16) { + // cout << op << " fb " << inbus << outbus << add << endl; + FmOpKernel::compute_fb(outptr, param.phase, param.freq, + gain1, gain2, + fb_buf, feedback_shift, add); + } else { + // cout << op << " pure " << inbus << outbus << add << endl; + FmOpKernel::compute_pure(outptr, param.phase, param.freq, + gain1, gain2, add); } - param.phase += param.freq << LG_N; + } else { + // cout << op << " normal " << inbus << outbus << " " << param.freq << add << endl; + FmOpKernel::compute(outptr, buf_[inbus - 1].get(), + param.phase, param.freq, gain1, gain2, add); + } + has_contents[outbus] = true; + } else if (!add) { + has_contents[outbus] = false; } + param.phase += param.freq << LG_N; + } } diff --git a/fm_core.h b/fm_core.h index 7c0f2cc..653b634 100644 --- a/fm_core.h +++ b/fm_core.h @@ -1,18 +1,18 @@ /* - * 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 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. +*/ #ifndef __FM_CORE_H #define __FM_CORE_H @@ -25,33 +25,33 @@ class FmOperatorInfo { -public: + public: int in; int out; }; enum FmOperatorFlags { - OUT_BUS_ONE = 1 << 0, - OUT_BUS_TWO = 1 << 1, - OUT_BUS_ADD = 1 << 2, - IN_BUS_ONE = 1 << 4, - IN_BUS_TWO = 1 << 5, - FB_IN = 1 << 6, - FB_OUT = 1 << 7 + OUT_BUS_ONE = 1 << 0, + OUT_BUS_TWO = 1 << 1, + OUT_BUS_ADD = 1 << 2, + IN_BUS_ONE = 1 << 4, + IN_BUS_TWO = 1 << 5, + FB_IN = 1 << 6, + FB_OUT = 1 << 7 }; class FmAlgorithm { -public: + public: int ops[6]; }; class FmCore { -public: + public: virtual ~FmCore() {}; static void dump(); uint8_t get_carrier_operators(uint8_t algorithm); virtual void render(int32_t *output, FmOpParams *params, int algorithm, int32_t *fb_buf, int feedback_gain); -protected: + protected: AlignedBufbuf_[2]; const static FmAlgorithm algorithms[32]; }; diff --git a/fm_op_kernel.cc b/fm_op_kernel.cc deleted file mode 100644 index 1c93ba0..0000000 --- a/fm_op_kernel.cc +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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 - -#ifdef HAVE_NEON -#include -#endif - -#include "synth.h" -#include "sin.h" -#include "fm_op_kernel.h" - -#ifdef HAVE_NEONx -static bool hasNeon() { - return true; - return (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0; -} - -extern "C" -void neon_fm_kernel(const int *in, const int *busin, int *out, int count, - int32_t phase0, int32_t freq, int32_t gain1, int32_t dgain); - -const int32_t __attribute__ ((aligned(16))) zeros[N] = {0}; - -#else -static bool hasNeon() { - return false; -} -#endif - -void FmOpKernel::compute(int32_t *output, const int32_t *input, - int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; - if (hasNeon()) { -#ifdef HAVE_NEON - neon_fm_kernel(input, add ? output : zeros, output, _N_, - phase0, freq, gain, dgain); -#endif - } else { - if (add) { - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t y = Sin::lookup(phase + input[i]); - int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; - output[i] += y1; - phase += freq; - } - } else { - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t y = Sin::lookup(phase + input[i]); - int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; - output[i] = y1; - phase += freq; - } - } - } -} - -void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; - if (hasNeon()) { -#ifdef HAVE_NEON - neon_fm_kernel(zeros, add ? output : zeros, output, _N_, - phase0, freq, gain, dgain); -#endif - } else { - if (add) { - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t y = Sin::lookup(phase); - int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; - output[i] += y1; - phase += freq; - } - } else { - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t y = Sin::lookup(phase); - int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; - output[i] = y1; - phase += freq; - } - } - } -} - -#define noDOUBLE_ACCURACY -#define HIGH_ACCURACY - -void FmOpKernel::compute_fb(int32_t *output, int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, - int32_t *fb_buf, int fb_shift, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; - int32_t y0 = fb_buf[0]; - int32_t y = fb_buf[1]; - if (add) { - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); - y0 = y; - y = Sin::lookup(phase + scaled_fb); - y = ((int64_t)y * (int64_t)gain) >> 24; - output[i] += y; - phase += freq; - } - } else { - for (int i = 0; i < _N_; i++) { - gain += dgain; - int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); - y0 = y; - y = Sin::lookup(phase + scaled_fb); - y = ((int64_t)y * (int64_t)gain) >> 24; - output[i] = y; - phase += freq; - } - } - fb_buf[0] = y0; - fb_buf[1] = y; -} - -//////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// - -// Experimental sine wave generators below -#if 0 -// Results: accuracy 64.3 mean, 170 worst case -// high accuracy: 5.0 mean, 49 worst case -void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; -#ifdef HIGH_ACCURACY - int32_t u = Sin::compute10(phase << 6); - u = ((int64_t)u * gain) >> 30; - int32_t v = Sin::compute10((phase << 6) + (1 << 28)); // quarter cycle - v = ((int64_t)v * gain) >> 30; - int32_t s = Sin::compute10(freq << 6); - int32_t c = Sin::compute10((freq << 6) + (1 << 28)); -#else - int32_t u = Sin::compute(phase); - u = ((int64_t)u * gain) >> 24; - int32_t v = Sin::compute(phase + (1 << 22)); // quarter cycle - v = ((int64_t)v * gain) >> 24; - int32_t s = Sin::compute(freq) << 6; - int32_t c = Sin::compute(freq + (1 << 22)) << 6; -#endif - for (int i = 0; i < _N_; i++) { - output[i] = u; - int32_t t = ((int64_t)v * (int64_t)c - (int64_t)u * (int64_t)s) >> 30; - u = ((int64_t)u * (int64_t)c + (int64_t)v * (int64_t)s) >> 30; - v = t; - } -} -#endif - -#if 0 -// Results: accuracy 392.3 mean, 15190 worst case (near freq = 0.5) -// for freq < 0.25, 275.2 mean, 716 worst -// high accuracy: 57.4 mean, 7559 worst -// freq < 0.25: 17.9 mean, 78 worst -void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; -#ifdef HIGH_ACCURACY - int32_t u = floor(gain * sin(phase * (M_PI / (1 << 23))) + 0.5); - int32_t v = floor(gain * cos((phase - freq * 0.5) * (M_PI / (1 << 23))) + 0.5); - int32_t a = floor((1 << 25) * sin(freq * (M_PI / (1 << 24))) + 0.5); -#else - int32_t u = Sin::compute(phase); - u = ((int64_t)u * gain) >> 24; - int32_t v = Sin::compute(phase + (1 << 22) - (freq >> 1)); - v = ((int64_t)v * gain) >> 24; - int32_t a = Sin::compute(freq >> 1) << 1; -#endif - for (int i = 0; i < _N_; i++) { - output[i] = u; - v -= ((int64_t)a * (int64_t)u) >> 24; - u += ((int64_t)a * (int64_t)v) >> 24; - } -} -#endif - -#if 0 -// Results: accuracy 370.0 mean, 15480 worst case (near freq = 0.5) -// with FRAC_NUM accuracy initialization: mean 1.55, worst 58 (near freq = 0) -// with high accuracy: mean 4.2, worst 292 (near freq = 0.5) -void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; -#ifdef DOUBLE_ACCURACY - int32_t u = floor((1 << 30) * sin(phase * (M_PI / (1 << 23))) + 0.5); - FRAC_NUM a_d = sin(freq * (M_PI / (1 << 24))); - int32_t v = floor((1LL << 31) * a_d * cos((phase - freq * 0.5) * - (M_PI / (1 << 23))) + 0.5); - int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5); -#else -#ifdef HIGH_ACCURACY - int32_t u = Sin::compute10(phase << 6); - int32_t v = Sin::compute10((phase << 6) + (1 << 28) - (freq << 5)); - int32_t a = Sin::compute10(freq << 5); - v = ((int64_t)v * (int64_t)a) >> 29; - int32_t aa = ((int64_t)a * (int64_t)a) >> 29; -#else - int32_t u = Sin::compute(phase) << 6; - int32_t v = Sin::compute(phase + (1 << 22) - (freq >> 1)); - int32_t a = Sin::compute(freq >> 1); - v = ((int64_t)v * (int64_t)a) >> 17; - int32_t aa = ((int64_t)a * (int64_t)a) >> 17; -#endif -#endif - - if (aa < 0) aa = (1 << 31) - 1; - for (int i = 0; i < _N_; i++) { - gain += dgain; - output[i] = ((int64_t)u * (int64_t)gain) >> 30; - v -= ((int64_t)aa * (int64_t)u) >> 29; - u += v; - } -} -#endif - -#if 0 -// Results:: accuracy 112.3 mean, 4262 worst (near freq = 0.5) -// high accuracy 2.9 mean, 143 worst -void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; -#ifdef HIGH_ACCURACY - int32_t u = Sin::compute10(phase << 6); - int32_t lastu = Sin::compute10((phase - freq) << 6); - int32_t a = Sin::compute10((freq << 6) + (1 << 28)) << 1; -#else - int32_t u = Sin::compute(phase) << 6; - int32_t lastu = Sin::compute(phase - freq) << 6; - int32_t a = Sin::compute(freq + (1 << 22)) << 7; -#endif - if (a < 0 && freq < 256) a = (1 << 31) - 1; - if (a > 0 && freq > 0x7fff00) a = -(1 << 31); - for (int i = 0; i < _N_; i++) { - gain += dgain; - output[i] = ((int64_t)u * (int64_t)gain) >> 30; - //output[i] = u; - int32_t newu = (((int64_t)u * (int64_t)a) >> 30) - lastu; - lastu = u; - u = newu; - } -} -#endif - diff --git a/fm_op_kernel.cpp b/fm_op_kernel.cpp index f730d63..df30e4b 100644 --- a/fm_op_kernel.cpp +++ b/fm_op_kernel.cpp @@ -1,18 +1,18 @@ /* - * 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 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 "config.h" #include @@ -35,7 +35,7 @@ static bool hasNeon() { extern "C" void neon_fm_kernel(const int *in, const int *busin, int *out, int count, - int32_t phase0, int32_t freq, int32_t gain1, int32_t dgain); + int32_t phase0, int32_t freq, int32_t gain1, int32_t dgain); const int32_t __attribute__ ((aligned(16))) zeros[_N_] = {0}; @@ -54,7 +54,7 @@ void FmOpKernel::compute(int32_t *output, const int32_t *input, if (hasNeon()) { #ifdef HAVE_NEON neon_fm_kernel(input, add ? output : zeros, output, _N_, - phase0, freq, gain, dgain); + phase0, freq, gain, dgain); #endif } else { if (add) { @@ -85,7 +85,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, if (hasNeon()) { #ifdef HAVE_NEON neon_fm_kernel(zeros, add ? output : zeros, output, _N_, - phase0, freq, gain, dgain); + phase0, freq, gain, dgain); #endif } else { if (add) { @@ -100,7 +100,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, for (int i = 0; i < _N_; i++) { gain += dgain; int32_t y = Sin::lookup(phase); - int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; + int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; output[i] = y1; phase += freq; } @@ -155,30 +155,30 @@ void FmOpKernel::compute_fb(int32_t *output, int32_t phase0, int32_t freq, // high accuracy: 5.0 mean, 49 worst case void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; + int32_t gain = gain1; + int32_t phase = phase0; #ifdef HIGH_ACCURACY - int32_t u = Sin::compute10(phase << 6); - u = ((int64_t)u * gain) >> 30; - int32_t v = Sin::compute10((phase << 6) + (1 << 28)); // quarter cycle - v = ((int64_t)v * gain) >> 30; - int32_t s = Sin::compute10(freq << 6); - int32_t c = Sin::compute10((freq << 6) + (1 << 28)); + int32_t u = Sin::compute10(phase << 6); + u = ((int64_t)u * gain) >> 30; + int32_t v = Sin::compute10((phase << 6) + (1 << 28)); // quarter cycle + v = ((int64_t)v * gain) >> 30; + int32_t s = Sin::compute10(freq << 6); + int32_t c = Sin::compute10((freq << 6) + (1 << 28)); #else - int32_t u = Sin::compute(phase); - u = ((int64_t)u * gain) >> 24; - int32_t v = Sin::compute(phase + (1 << 22)); // quarter cycle - v = ((int64_t)v * gain) >> 24; - int32_t s = Sin::compute(freq) << 6; - int32_t c = Sin::compute(freq + (1 << 22)) << 6; + int32_t u = Sin::compute(phase); + u = ((int64_t)u * gain) >> 24; + int32_t v = Sin::compute(phase + (1 << 22)); // quarter cycle + v = ((int64_t)v * gain) >> 24; + int32_t s = Sin::compute(freq) << 6; + int32_t c = Sin::compute(freq + (1 << 22)) << 6; #endif - for (int i = 0; i < _N_; i++) { - output[i] = u; - int32_t t = ((int64_t)v * (int64_t)c - (int64_t)u * (int64_t)s) >> 30; - u = ((int64_t)u * (int64_t)c + (int64_t)v * (int64_t)s) >> 30; - v = t; - } + for (int i = 0; i < _N_; i++) { + output[i] = u; + int32_t t = ((int64_t)v * (int64_t)c - (int64_t)u * (int64_t)s) >> 30; + u = ((int64_t)u * (int64_t)c + (int64_t)v * (int64_t)s) >> 30; + v = t; + } } #endif @@ -189,25 +189,25 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, // freq < 0.25: 17.9 mean, 78 worst void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; + int32_t gain = gain1; + int32_t phase = phase0; #ifdef HIGH_ACCURACY - int32_t u = floor(gain * sin(phase * (M_PI / (1 << 23))) + 0.5); - int32_t v = floor(gain * cos((phase - freq * 0.5) * (M_PI / (1 << 23))) + 0.5); - int32_t a = floor((1 << 25) * sin(freq * (M_PI / (1 << 24))) + 0.5); + int32_t u = floor(gain * sin(phase * (M_PI / (1 << 23))) + 0.5); + int32_t v = floor(gain * cos((phase - freq * 0.5) * (M_PI / (1 << 23))) + 0.5); + int32_t a = floor((1 << 25) * sin(freq * (M_PI / (1 << 24))) + 0.5); #else - int32_t u = Sin::compute(phase); - u = ((int64_t)u * gain) >> 24; - int32_t v = Sin::compute(phase + (1 << 22) - (freq >> 1)); - v = ((int64_t)v * gain) >> 24; - int32_t a = Sin::compute(freq >> 1) << 1; + int32_t u = Sin::compute(phase); + u = ((int64_t)u * gain) >> 24; + int32_t v = Sin::compute(phase + (1 << 22) - (freq >> 1)); + v = ((int64_t)v * gain) >> 24; + int32_t a = Sin::compute(freq >> 1) << 1; #endif - for (int i = 0; i < _N_; i++) { - output[i] = u; - v -= ((int64_t)a * (int64_t)u) >> 24; - u += ((int64_t)a * (int64_t)v) >> 24; - } + for (int i = 0; i < _N_; i++) { + output[i] = u; + v -= ((int64_t)a * (int64_t)u) >> 24; + u += ((int64_t)a * (int64_t)v) >> 24; + } } #endif @@ -217,38 +217,38 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, // with high accuracy: mean 4.2, worst 292 (near freq = 0.5) void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; + int32_t gain = gain1; + int32_t phase = phase0; #ifdef DOUBLE_ACCURACY - int32_t u = floor((1 << 30) * sin(phase * (M_PI / (1 << 23))) + 0.5); - FRAC_NUM a_d = sin(freq * (M_PI / (1 << 24))); - int32_t v = floor((1LL << 31) * a_d * cos((phase - freq * 0.5) * - (M_PI / (1 << 23))) + 0.5); - int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5); + int32_t u = floor((1 << 30) * sin(phase * (M_PI / (1 << 23))) + 0.5); + FRAC_NUM a_d = sin(freq * (M_PI / (1 << 24))); + int32_t v = floor((1LL << 31) * a_d * cos((phase - freq * 0.5) * + (M_PI / (1 << 23))) + 0.5); + int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5); #else #ifdef HIGH_ACCURACY - int32_t u = Sin::compute10(phase << 6); - int32_t v = Sin::compute10((phase << 6) + (1 << 28) - (freq << 5)); - int32_t a = Sin::compute10(freq << 5); - v = ((int64_t)v * (int64_t)a) >> 29; - int32_t aa = ((int64_t)a * (int64_t)a) >> 29; + int32_t u = Sin::compute10(phase << 6); + int32_t v = Sin::compute10((phase << 6) + (1 << 28) - (freq << 5)); + int32_t a = Sin::compute10(freq << 5); + v = ((int64_t)v * (int64_t)a) >> 29; + int32_t aa = ((int64_t)a * (int64_t)a) >> 29; #else - int32_t u = Sin::compute(phase) << 6; - int32_t v = Sin::compute(phase + (1 << 22) - (freq >> 1)); - int32_t a = Sin::compute(freq >> 1); - v = ((int64_t)v * (int64_t)a) >> 17; - int32_t aa = ((int64_t)a * (int64_t)a) >> 17; + int32_t u = Sin::compute(phase) << 6; + int32_t v = Sin::compute(phase + (1 << 22) - (freq >> 1)); + int32_t a = Sin::compute(freq >> 1); + v = ((int64_t)v * (int64_t)a) >> 17; + int32_t aa = ((int64_t)a * (int64_t)a) >> 17; #endif #endif - - if (aa < 0) aa = (1 << 31) - 1; - for (int i = 0; i < _N_; i++) { - gain += dgain; - output[i] = ((int64_t)u * (int64_t)gain) >> 30; - v -= ((int64_t)aa * (int64_t)u) >> 29; - u += v; - } + + if (aa < 0) aa = (1 << 31) - 1; + for (int i = 0; i < _N_; i++) { + gain += dgain; + output[i] = ((int64_t)u * (int64_t)gain) >> 30; + v -= ((int64_t)aa * (int64_t)u) >> 29; + u += v; + } } #endif @@ -257,28 +257,27 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, // high accuracy 2.9 mean, 143 worst void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; - int32_t gain = gain1; - int32_t phase = phase0; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; + int32_t gain = gain1; + int32_t phase = phase0; #ifdef HIGH_ACCURACY - int32_t u = Sin::compute10(phase << 6); - int32_t lastu = Sin::compute10((phase - freq) << 6); - int32_t a = Sin::compute10((freq << 6) + (1 << 28)) << 1; + int32_t u = Sin::compute10(phase << 6); + int32_t lastu = Sin::compute10((phase - freq) << 6); + int32_t a = Sin::compute10((freq << 6) + (1 << 28)) << 1; #else - int32_t u = Sin::compute(phase) << 6; - int32_t lastu = Sin::compute(phase - freq) << 6; - int32_t a = Sin::compute(freq + (1 << 22)) << 7; + int32_t u = Sin::compute(phase) << 6; + int32_t lastu = Sin::compute(phase - freq) << 6; + int32_t a = Sin::compute(freq + (1 << 22)) << 7; #endif - if (a < 0 && freq < 256) a = (1 << 31) - 1; - if (a > 0 && freq > 0x7fff00) a = -(1 << 31); - for (int i = 0; i < _N_; i++) { - gain += dgain; - output[i] = ((int64_t)u * (int64_t)gain) >> 30; - //output[i] = u; - int32_t newu = (((int64_t)u * (int64_t)a) >> 30) - lastu; - lastu = u; - u = newu; - } + if (a < 0 && freq < 256) a = (1 << 31) - 1; + if (a > 0 && freq > 0x7fff00) a = -(1 << 31); + for (int i = 0; i < _N_; i++) { + gain += dgain; + output[i] = ((int64_t)u * (int64_t)gain) >> 30; + //output[i] = u; + int32_t newu = (((int64_t)u * (int64_t)a) >> 30) - lastu; + lastu = u; + u = newu; + } } #endif - diff --git a/fm_op_kernel.h b/fm_op_kernel.h index a46f1b4..d164bc2 100644 --- a/fm_op_kernel.h +++ b/fm_op_kernel.h @@ -1,47 +1,47 @@ /* - * 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 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. +*/ #ifndef __FM_OP_KERNEL_H #define __FM_OP_KERNEL_H struct FmOpParams { - int32_t level_in; // value to be computed (from level to gain[0]) - int32_t gain_out; // computed value (gain[1] to gain[0]) - int32_t freq; - int32_t phase; + int32_t level_in; // value to be computed (from level to gain[0]) + int32_t gain_out; // computed value (gain[1] to gain[0]) + int32_t freq; + int32_t phase; }; class FmOpKernel { - public: - // gain1 and gain2 represent linear step: gain for sample i is - // gain1 + (1 + i) / 64 * (gain2 - gain1) - - // This is the basic FM operator. No feedback. - static void compute(int32_t *output, const int32_t *input, - int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, bool add); - - // This is a sine generator, no feedback. - static void compute_pure(int32_t *output, int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, bool add); - - // One op with feedback, no add. - static void compute_fb(int32_t *output, int32_t phase0, int32_t freq, - int32_t gain1, int32_t gain2, - int32_t *fb_buf, int fb_gain, bool add); + public: + // gain1 and gain2 represent linear step: gain for sample i is + // gain1 + (1 + i) / 64 * (gain2 - gain1) + + // This is the basic FM operator. No feedback. + static void compute(int32_t *output, const int32_t *input, + int32_t phase0, int32_t freq, + int32_t gain1, int32_t gain2, bool add); + + // This is a sine generator, no feedback. + static void compute_pure(int32_t *output, int32_t phase0, int32_t freq, + int32_t gain1, int32_t gain2, bool add); + + // One op with feedback, no add. + static void compute_fb(int32_t *output, int32_t phase0, int32_t freq, + int32_t gain1, int32_t gain2, + int32_t *fb_buf, int fb_gain, bool add); }; #endif diff --git a/freqlut.cpp b/freqlut.cpp index 9ecdc86..6ef1c7c 100644 --- a/freqlut.cpp +++ b/freqlut.cpp @@ -1,18 +1,18 @@ /* - * 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 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. +*/ // Resolve frequency signal (1.0 in Q24 format = 1 octave) to phase delta. diff --git a/freqlut.h b/freqlut.h index 3fc2e38..83ad3c7 100644 --- a/freqlut.h +++ b/freqlut.h @@ -1,23 +1,23 @@ /* - * 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 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 "synth.h" class Freqlut { - public: - static void init(FRAC_NUM sample_rate); - static int32_t lookup(int32_t logfreq); + public: + static void init(FRAC_NUM sample_rate); + static int32_t lookup(int32_t logfreq); }; diff --git a/lfo.cpp b/lfo.cpp index f6ee069..33f1aa3 100644 --- a/lfo.cpp +++ b/lfo.cpp @@ -1,18 +1,18 @@ /* - * Copyright 2013 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 2013 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. +*/ // Low frequency oscillator, compatible with DX7 @@ -24,74 +24,74 @@ uint32_t Lfo::unit_; void Lfo::init(FRAC_NUM sample_rate) { - // constant is 1 << 32 / 15.5s / 11 - Lfo::unit_ = (int32_t)(_N_ * 25190424 / sample_rate + 0.5); + // constant is 1 << 32 / 15.5s / 11 + Lfo::unit_ = (int32_t)(_N_ * 25190424 / sample_rate + 0.5); } void Lfo::reset(const uint8_t params[6]) { - int rate = params[0]; // 0..99 - int sr = rate == 0 ? 1 : (165 * rate) >> 6; - sr *= sr < 160 ? 11 : (11 + ((sr - 160) >> 4)); - delta_ = unit_ * sr; - int a = 99 - params[1]; // LFO delay - if (a == 99) { - delayinc_ = ~0u; - delayinc2_ = ~0u; - } else { - a = (16 + (a & 15)) << (1 + (a >> 4)); - delayinc_ = unit_ * a; - a &= 0xff80; - a = max(0x80, a); - delayinc2_ = unit_ * a; - } - waveform_ = params[5]; - sync_ = params[4] != 0; + int rate = params[0]; // 0..99 + int sr = rate == 0 ? 1 : (165 * rate) >> 6; + sr *= sr < 160 ? 11 : (11 + ((sr - 160) >> 4)); + delta_ = unit_ * sr; + int a = 99 - params[1]; // LFO delay + if (a == 99) { + delayinc_ = ~0u; + delayinc2_ = ~0u; + } else { + a = (16 + (a & 15)) << (1 + (a >> 4)); + delayinc_ = unit_ * a; + a &= 0xff80; + a = max(0x80, a); + delayinc2_ = unit_ * a; + } + waveform_ = params[5]; + sync_ = params[4] != 0; } int32_t Lfo::getsample() { - phase_ += delta_; - int32_t x; - switch (waveform_) { - case 0: // triangle - x = phase_ >> 7; - x ^= -(phase_ >> 31); - x &= (1 << 24) - 1; - return x; - case 1: // sawtooth down - return (~phase_ ^ (1U << 31)) >> 8; - case 2: // sawtooth up - return (phase_ ^ (1U << 31)) >> 8; - case 3: // square - return ((~phase_) >> 7) & (1 << 24); - case 4: // sine - return (1 << 23) + (Sin::lookup(phase_ >> 8) >> 1); - case 5: // s&h - if (phase_ < delta_) { - randstate_ = (randstate_ * 179 + 17) & 0xff; - } - x = randstate_ ^ 0x80; - return (x + 1) << 16; - } - return 1 << 23; + phase_ += delta_; + int32_t x; + switch (waveform_) { + case 0: // triangle + x = phase_ >> 7; + x ^= -(phase_ >> 31); + x &= (1 << 24) - 1; + return x; + case 1: // sawtooth down + return (~phase_ ^ (1U << 31)) >> 8; + case 2: // sawtooth up + return (phase_ ^ (1U << 31)) >> 8; + case 3: // square + return ((~phase_) >> 7) & (1 << 24); + case 4: // sine + return (1 << 23) + (Sin::lookup(phase_ >> 8) >> 1); + case 5: // s&h + if (phase_ < delta_) { + randstate_ = (randstate_ * 179 + 17) & 0xff; + } + x = randstate_ ^ 0x80; + return (x + 1) << 16; + } + return 1 << 23; } int32_t Lfo::getdelay() { - uint32_t delta = delaystate_ < (1U << 31) ? delayinc_ : delayinc2_; - uint64_t d = ((uint64_t)delaystate_) + delta; - if (d > ~0u) { - return 1 << 24; - } - delaystate_ = d; - if (d < (1U << 31)) { - return 0; - } else { - return (d >> 7) & ((1 << 24) - 1); - } + uint32_t delta = delaystate_ < (1U << 31) ? delayinc_ : delayinc2_; + uint64_t d = ((uint64_t)delaystate_) + delta; + if (d > ~0u) { + return 1 << 24; + } + delaystate_ = d; + if (d < (1U << 31)) { + return 0; + } else { + return (d >> 7) & ((1 << 24) - 1); + } } void Lfo::keydown() { - if (sync_) { - phase_ = (1U << 31) - 1; - } - delaystate_ = 0; + if (sync_) { + phase_ = (1U << 31) - 1; + } + delaystate_ = 0; } diff --git a/lfo.h b/lfo.h index f59bbf6..3a063c1 100644 --- a/lfo.h +++ b/lfo.h @@ -1,43 +1,43 @@ /* - * Copyright 2013 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 2013 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. +*/ // Low frequency oscillator, compatible with DX7 class Lfo { - public: - static void init(FRAC_NUM sample_rate); - void reset(const uint8_t params[6]); + public: + static void init(FRAC_NUM sample_rate); + void reset(const uint8_t params[6]); - // result is 0..1 in Q24 - int32_t getsample(); + // result is 0..1 in Q24 + int32_t getsample(); - // result is 0..1 in Q24 - int32_t getdelay(); + // result is 0..1 in Q24 + int32_t getdelay(); - void keydown(); - private: - static uint32_t unit_; + void keydown(); + private: + static uint32_t unit_; - uint32_t phase_; // Q32 - uint32_t delta_; - uint8_t waveform_; - uint8_t randstate_; - bool sync_; + uint32_t phase_; // Q32 + uint32_t delta_; + uint8_t waveform_; + uint8_t randstate_; + bool sync_; - uint32_t delaystate_; - uint32_t delayinc_; - uint32_t delayinc2_; + uint32_t delaystate_; + uint32_t delayinc_; + uint32_t delayinc2_; }; diff --git a/midinotes.h b/midinotes.h index c62e4a0..1d43573 100644 --- a/midinotes.h +++ b/midinotes.h @@ -1,5 +1,5 @@ /************************************************* - * MIDI note values + MIDI note values *************************************************/ #ifndef _MIDINOTES_H @@ -14,7 +14,7 @@ #define MIDI_DIS1 27 #define MIDI_E1 28 #define MIDI_F1 29 -#define MIDI_FIS1 30 +#define MIDI_FIS1 30 #define MIDI_G1 31 #define MIDI_GIS1 32 #define MIDI_A1 33 @@ -31,7 +31,7 @@ #define MIDI_GIS2 44 #define MIDI_A2 45 #define MIDI_AIS2 46 -#define MIDI_B2 47 +#define MIDI_B2 47 #define MIDI_C3 48 #define MIDI_CIS3 49 #define MIDI_D3 50 diff --git a/module.h b/module.h index e165531..b835a53 100644 --- a/module.h +++ b/module.h @@ -1,18 +1,18 @@ /* - * 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 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. +*/ #ifndef SYNTH_MODULE_H #define SYNTH_MODULE_H @@ -20,12 +20,11 @@ #include class Module { - public: - static const int lg_n = 6; - static const int n = 1 << lg_n; - virtual void process(const int32_t **inbufs, const int32_t *control_in, - const int32_t *control_last, int32_t **outbufs) = 0; + public: + static const int lg_n = 6; + static const int n = 1 << lg_n; + virtual void process(const int32_t **inbufs, const int32_t *control_in, + const int32_t *control_last, int32_t **outbufs) = 0; }; #endif // SYNTH_MODULE_H - diff --git a/my_effect_freeverb.cpp b/my_effect_freeverb.cpp index 01a1842..895157f 100644 --- a/my_effect_freeverb.cpp +++ b/my_effect_freeverb.cpp @@ -1,28 +1,28 @@ /* Audio Library for Teensy 3.X - * Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com - * - * Development of this audio library was funded by PJRC.COM, LLC by sales of - * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop - * open source software by purchasing Teensy or other PJRC products. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice, development funding notice, and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ + Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com + + Development of this audio library was funded by PJRC.COM, LLC by sales of + Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + open source software by purchasing Teensy or other PJRC products. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice, development funding notice, and this permission + notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ // A fixed point implementation of Freeverb by Jezar at Dreampoint // http://blog.bjornroche.com/2012/06/freeverb-original-public-domain-code-by.html @@ -34,449 +34,450 @@ MyAudioEffectFreeverb::MyAudioEffectFreeverb() : AudioStream(1, inputQueueArray) { - memset(comb1buf, 0, sizeof(comb1buf)); - memset(comb2buf, 0, sizeof(comb2buf)); - memset(comb3buf, 0, sizeof(comb3buf)); - memset(comb4buf, 0, sizeof(comb4buf)); - memset(comb5buf, 0, sizeof(comb5buf)); - memset(comb6buf, 0, sizeof(comb6buf)); - memset(comb7buf, 0, sizeof(comb7buf)); - memset(comb8buf, 0, sizeof(comb8buf)); - comb1index = 0; - comb2index = 0; - comb3index = 0; - comb4index = 0; - comb5index = 0; - comb6index = 0; - comb7index = 0; - comb8index = 0; - comb1filter = 0; - comb2filter = 0; - comb3filter = 0; - comb4filter = 0; - comb5filter = 0; - comb6filter = 0; - comb7filter = 0; - comb8filter = 0; - combdamp1 = 6553; - combdamp2 = 26215; - combfeeback = 27524; - memset(allpass1buf, 0, sizeof(allpass1buf)); - memset(allpass2buf, 0, sizeof(allpass2buf)); - memset(allpass3buf, 0, sizeof(allpass3buf)); - memset(allpass4buf, 0, sizeof(allpass4buf)); - allpass1index = 0; - allpass2index = 0; - allpass3index = 0; - allpass4index = 0; + memset(comb1buf, 0, sizeof(comb1buf)); + memset(comb2buf, 0, sizeof(comb2buf)); + memset(comb3buf, 0, sizeof(comb3buf)); + memset(comb4buf, 0, sizeof(comb4buf)); + memset(comb5buf, 0, sizeof(comb5buf)); + memset(comb6buf, 0, sizeof(comb6buf)); + memset(comb7buf, 0, sizeof(comb7buf)); + memset(comb8buf, 0, sizeof(comb8buf)); + comb1index = 0; + comb2index = 0; + comb3index = 0; + comb4index = 0; + comb5index = 0; + comb6index = 0; + comb7index = 0; + comb8index = 0; + comb1filter = 0; + comb2filter = 0; + comb3filter = 0; + comb4filter = 0; + comb5filter = 0; + comb6filter = 0; + comb7filter = 0; + comb8filter = 0; + combdamp1 = 6553; + combdamp2 = 26215; + combfeeback = 27524; + memset(allpass1buf, 0, sizeof(allpass1buf)); + memset(allpass2buf, 0, sizeof(allpass2buf)); + memset(allpass3buf, 0, sizeof(allpass3buf)); + memset(allpass4buf, 0, sizeof(allpass4buf)); + allpass1index = 0; + allpass2index = 0; + allpass3index = 0; + allpass4index = 0; } -// cleaner sat16 by http://www.moseleyinstruments.com/ -static int16_t sat16(int32_t n, int rshift) { - // we should always round towards 0 - // to avoid recirculating round-off noise - // - // a 2s complement positive number is always - // rounded down, so we only need to take - // care of negative numbers - if (n < 0) { - n = n + (~(0xFFFFFFFFUL << rshift)); - } - n = n >> rshift; - if (n > 32767) { - return 32767; - } - if (n < -32768) { - return -32768; - } - return n; -} +// cleaner sat16 by http://www.moseleyinstruments.com/ +static int16_t sat16(int32_t n, int rshift) { + // we should always round towards 0 + // to avoid recirculating round-off noise + // + // a 2s complement positive number is always + // rounded down, so we only need to take + // care of negative numbers + if (n < 0) { + n = n + (~(0xFFFFFFFFUL << rshift)); + } + n = n >> rshift; + if (n > 32767) { + return 32767; + } + if (n < -32768) { + return -32768; + } + return n; +} // TODO: move this to one of the data files, use in output_adat.cpp, output_tdm.cpp, etc static const audio_block_t zeroblock = { -0, 0, 0, { -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #if AUDIO_BLOCK_SAMPLES > 16 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 32 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 48 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 64 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 80 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 96 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif #if AUDIO_BLOCK_SAMPLES > 112 -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif -} }; + } +}; void MyAudioEffectFreeverb::update() { #if defined(__ARM_ARCH_7EM__) - const audio_block_t *block; - audio_block_t *outblock; - int i; - int16_t input, bufout, output; - int32_t sum; - - outblock = allocate(); - if (!outblock) { - audio_block_t *tmp = receiveReadOnly(0); - if (tmp) release(tmp); - return; - } - block = receiveReadOnly(0); - if (!block) block = &zeroblock; - - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - // TODO: scale numerical range depending on roomsize & damping - input = sat16(block->data[i] * 8738, 17); // for numerical headroom - sum = 0; - - bufout = comb1buf[comb1index]; - sum += bufout; - comb1filter = sat16(bufout * combdamp2 + comb1filter * combdamp1, 15); - comb1buf[comb1index] = sat16(input + sat16(comb1filter * combfeeback, 15), 0); - if (++comb1index >= sizeof(comb1buf)/sizeof(int16_t)) comb1index = 0; - - bufout = comb2buf[comb2index]; - sum += bufout; - comb2filter = sat16(bufout * combdamp2 + comb2filter * combdamp1, 15); - comb2buf[comb2index] = sat16(input + sat16(comb2filter * combfeeback, 15), 0); - if (++comb2index >= sizeof(comb2buf)/sizeof(int16_t)) comb2index = 0; - - bufout = comb3buf[comb3index]; - sum += bufout; - comb3filter = sat16(bufout * combdamp2 + comb3filter * combdamp1, 15); - comb3buf[comb3index] = sat16(input + sat16(comb3filter * combfeeback, 15), 0); - if (++comb3index >= sizeof(comb3buf)/sizeof(int16_t)) comb3index = 0; - - bufout = comb4buf[comb4index]; - sum += bufout; - comb4filter = sat16(bufout * combdamp2 + comb4filter * combdamp1, 15); - comb4buf[comb4index] = sat16(input + sat16(comb4filter * combfeeback, 15), 0); - if (++comb4index >= sizeof(comb4buf)/sizeof(int16_t)) comb4index = 0; - - bufout = comb5buf[comb5index]; - sum += bufout; - comb5filter = sat16(bufout * combdamp2 + comb5filter * combdamp1, 15); - comb5buf[comb5index] = sat16(input + sat16(comb5filter * combfeeback, 15), 0); - if (++comb5index >= sizeof(comb5buf)/sizeof(int16_t)) comb5index = 0; - - bufout = comb6buf[comb6index]; - sum += bufout; - comb6filter = sat16(bufout * combdamp2 + comb6filter * combdamp1, 15); - comb6buf[comb6index] = sat16(input + sat16(comb6filter * combfeeback, 15), 0); - if (++comb6index >= sizeof(comb6buf)/sizeof(int16_t)) comb6index = 0; - - bufout = comb7buf[comb7index]; - sum += bufout; - comb7filter = sat16(bufout * combdamp2 + comb7filter * combdamp1, 15); - comb7buf[comb7index] = sat16(input + sat16(comb7filter * combfeeback, 15), 0); - if (++comb7index >= sizeof(comb7buf)/sizeof(int16_t)) comb7index = 0; - - bufout = comb8buf[comb8index]; - sum += bufout; - comb8filter = sat16(bufout * combdamp2 + comb8filter * combdamp1, 15); - comb8buf[comb8index] = sat16(input + sat16(comb8filter * combfeeback, 15), 0); - if (++comb8index >= sizeof(comb8buf)/sizeof(int16_t)) comb8index = 0; - - output = sat16(sum * 31457, 17); - - bufout = allpass1buf[allpass1index]; - allpass1buf[allpass1index] = output + (bufout >> 1); - output = sat16(bufout - output, 1); - if (++allpass1index >= sizeof(allpass1buf)/sizeof(int16_t)) allpass1index = 0; - - bufout = allpass2buf[allpass2index]; - allpass2buf[allpass2index] = output + (bufout >> 1); - output = sat16(bufout - output, 1); - if (++allpass2index >= sizeof(allpass2buf)/sizeof(int16_t)) allpass2index = 0; - - bufout = allpass3buf[allpass3index]; - allpass3buf[allpass3index] = output + (bufout >> 1); - output = sat16(bufout - output, 1); - if (++allpass3index >= sizeof(allpass3buf)/sizeof(int16_t)) allpass3index = 0; - - bufout = allpass4buf[allpass4index]; - allpass4buf[allpass4index] = output + (bufout >> 1); - output = sat16(bufout - output, 1); - if (++allpass4index >= sizeof(allpass4buf)/sizeof(int16_t)) allpass4index = 0; - - outblock->data[i] = sat16(output * 30, 0); - } - transmit(outblock); - release(outblock); - if (block != &zeroblock) release((audio_block_t *)block); + const audio_block_t *block; + audio_block_t *outblock; + int i; + int16_t input, bufout, output; + int32_t sum; + + outblock = allocate(); + if (!outblock) { + audio_block_t *tmp = receiveReadOnly(0); + if (tmp) release(tmp); + return; + } + block = receiveReadOnly(0); + if (!block) block = &zeroblock; + + for (i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { + // TODO: scale numerical range depending on roomsize & damping + input = sat16(block->data[i] * 8738, 17); // for numerical headroom + sum = 0; + + bufout = comb1buf[comb1index]; + sum += bufout; + comb1filter = sat16(bufout * combdamp2 + comb1filter * combdamp1, 15); + comb1buf[comb1index] = sat16(input + sat16(comb1filter * combfeeback, 15), 0); + if (++comb1index >= sizeof(comb1buf) / sizeof(int16_t)) comb1index = 0; + + bufout = comb2buf[comb2index]; + sum += bufout; + comb2filter = sat16(bufout * combdamp2 + comb2filter * combdamp1, 15); + comb2buf[comb2index] = sat16(input + sat16(comb2filter * combfeeback, 15), 0); + if (++comb2index >= sizeof(comb2buf) / sizeof(int16_t)) comb2index = 0; + + bufout = comb3buf[comb3index]; + sum += bufout; + comb3filter = sat16(bufout * combdamp2 + comb3filter * combdamp1, 15); + comb3buf[comb3index] = sat16(input + sat16(comb3filter * combfeeback, 15), 0); + if (++comb3index >= sizeof(comb3buf) / sizeof(int16_t)) comb3index = 0; + + bufout = comb4buf[comb4index]; + sum += bufout; + comb4filter = sat16(bufout * combdamp2 + comb4filter * combdamp1, 15); + comb4buf[comb4index] = sat16(input + sat16(comb4filter * combfeeback, 15), 0); + if (++comb4index >= sizeof(comb4buf) / sizeof(int16_t)) comb4index = 0; + + bufout = comb5buf[comb5index]; + sum += bufout; + comb5filter = sat16(bufout * combdamp2 + comb5filter * combdamp1, 15); + comb5buf[comb5index] = sat16(input + sat16(comb5filter * combfeeback, 15), 0); + if (++comb5index >= sizeof(comb5buf) / sizeof(int16_t)) comb5index = 0; + + bufout = comb6buf[comb6index]; + sum += bufout; + comb6filter = sat16(bufout * combdamp2 + comb6filter * combdamp1, 15); + comb6buf[comb6index] = sat16(input + sat16(comb6filter * combfeeback, 15), 0); + if (++comb6index >= sizeof(comb6buf) / sizeof(int16_t)) comb6index = 0; + + bufout = comb7buf[comb7index]; + sum += bufout; + comb7filter = sat16(bufout * combdamp2 + comb7filter * combdamp1, 15); + comb7buf[comb7index] = sat16(input + sat16(comb7filter * combfeeback, 15), 0); + if (++comb7index >= sizeof(comb7buf) / sizeof(int16_t)) comb7index = 0; + + bufout = comb8buf[comb8index]; + sum += bufout; + comb8filter = sat16(bufout * combdamp2 + comb8filter * combdamp1, 15); + comb8buf[comb8index] = sat16(input + sat16(comb8filter * combfeeback, 15), 0); + if (++comb8index >= sizeof(comb8buf) / sizeof(int16_t)) comb8index = 0; + + output = sat16(sum * 31457, 17); + + bufout = allpass1buf[allpass1index]; + allpass1buf[allpass1index] = output + (bufout >> 1); + output = sat16(bufout - output, 1); + if (++allpass1index >= sizeof(allpass1buf) / sizeof(int16_t)) allpass1index = 0; + + bufout = allpass2buf[allpass2index]; + allpass2buf[allpass2index] = output + (bufout >> 1); + output = sat16(bufout - output, 1); + if (++allpass2index >= sizeof(allpass2buf) / sizeof(int16_t)) allpass2index = 0; + + bufout = allpass3buf[allpass3index]; + allpass3buf[allpass3index] = output + (bufout >> 1); + output = sat16(bufout - output, 1); + if (++allpass3index >= sizeof(allpass3buf) / sizeof(int16_t)) allpass3index = 0; + + bufout = allpass4buf[allpass4index]; + allpass4buf[allpass4index] = output + (bufout >> 1); + output = sat16(bufout - output, 1); + if (++allpass4index >= sizeof(allpass4buf) / sizeof(int16_t)) allpass4index = 0; + + outblock->data[i] = sat16(output * 30, 0); + } + transmit(outblock); + release(outblock); + if (block != &zeroblock) release((audio_block_t *)block); #elif defined(KINETISL) - audio_block_t *block; - block = receiveReadOnly(0); - if (block) release(block); + audio_block_t *block; + block = receiveReadOnly(0); + if (block) release(block); #endif } MyAudioEffectFreeverbStereo::MyAudioEffectFreeverbStereo() : AudioStream(1, inputQueueArray) { - memset(comb1bufL, 0, sizeof(comb1bufL)); - memset(comb2bufL, 0, sizeof(comb2bufL)); - memset(comb3bufL, 0, sizeof(comb3bufL)); - memset(comb4bufL, 0, sizeof(comb4bufL)); - memset(comb5bufL, 0, sizeof(comb5bufL)); - memset(comb6bufL, 0, sizeof(comb6bufL)); - memset(comb7bufL, 0, sizeof(comb7bufL)); - memset(comb8bufL, 0, sizeof(comb8bufL)); - comb1indexL = 0; - comb2indexL = 0; - comb3indexL = 0; - comb4indexL = 0; - comb5indexL = 0; - comb6indexL = 0; - comb7indexL = 0; - comb8indexL = 0; - comb1filterL = 0; - comb2filterL = 0; - comb3filterL = 0; - comb4filterL = 0; - comb5filterL = 0; - comb6filterL = 0; - comb7filterL = 0; - comb8filterL = 0; - memset(comb1bufR, 0, sizeof(comb1bufR)); - memset(comb2bufR, 0, sizeof(comb2bufR)); - memset(comb3bufR, 0, sizeof(comb3bufR)); - memset(comb4bufR, 0, sizeof(comb4bufR)); - memset(comb5bufR, 0, sizeof(comb5bufR)); - memset(comb6bufR, 0, sizeof(comb6bufR)); - memset(comb7bufR, 0, sizeof(comb7bufR)); - memset(comb8bufR, 0, sizeof(comb8bufR)); - comb1indexR = 0; - comb2indexR = 0; - comb3indexR = 0; - comb4indexR = 0; - comb5indexR = 0; - comb6indexR = 0; - comb7indexR = 0; - comb8indexR = 0; - comb1filterR = 0; - comb2filterR = 0; - comb3filterR = 0; - comb4filterR = 0; - comb5filterR = 0; - comb6filterR = 0; - comb7filterR = 0; - comb8filterR = 0; - combdamp1 = 6553; - combdamp2 = 26215; - combfeeback = 27524; - memset(allpass1bufL, 0, sizeof(allpass1bufL)); - memset(allpass2bufL, 0, sizeof(allpass2bufL)); - memset(allpass3bufL, 0, sizeof(allpass3bufL)); - memset(allpass4bufL, 0, sizeof(allpass4bufL)); - allpass1indexL = 0; - allpass2indexL = 0; - allpass3indexL = 0; - allpass4indexL = 0; - memset(allpass1bufR, 0, sizeof(allpass1bufR)); - memset(allpass2bufR, 0, sizeof(allpass2bufR)); - memset(allpass3bufR, 0, sizeof(allpass3bufR)); - memset(allpass4bufR, 0, sizeof(allpass4bufR)); - allpass1indexR = 0; - allpass2indexR = 0; - allpass3indexR = 0; - allpass4indexR = 0; + memset(comb1bufL, 0, sizeof(comb1bufL)); + memset(comb2bufL, 0, sizeof(comb2bufL)); + memset(comb3bufL, 0, sizeof(comb3bufL)); + memset(comb4bufL, 0, sizeof(comb4bufL)); + memset(comb5bufL, 0, sizeof(comb5bufL)); + memset(comb6bufL, 0, sizeof(comb6bufL)); + memset(comb7bufL, 0, sizeof(comb7bufL)); + memset(comb8bufL, 0, sizeof(comb8bufL)); + comb1indexL = 0; + comb2indexL = 0; + comb3indexL = 0; + comb4indexL = 0; + comb5indexL = 0; + comb6indexL = 0; + comb7indexL = 0; + comb8indexL = 0; + comb1filterL = 0; + comb2filterL = 0; + comb3filterL = 0; + comb4filterL = 0; + comb5filterL = 0; + comb6filterL = 0; + comb7filterL = 0; + comb8filterL = 0; + memset(comb1bufR, 0, sizeof(comb1bufR)); + memset(comb2bufR, 0, sizeof(comb2bufR)); + memset(comb3bufR, 0, sizeof(comb3bufR)); + memset(comb4bufR, 0, sizeof(comb4bufR)); + memset(comb5bufR, 0, sizeof(comb5bufR)); + memset(comb6bufR, 0, sizeof(comb6bufR)); + memset(comb7bufR, 0, sizeof(comb7bufR)); + memset(comb8bufR, 0, sizeof(comb8bufR)); + comb1indexR = 0; + comb2indexR = 0; + comb3indexR = 0; + comb4indexR = 0; + comb5indexR = 0; + comb6indexR = 0; + comb7indexR = 0; + comb8indexR = 0; + comb1filterR = 0; + comb2filterR = 0; + comb3filterR = 0; + comb4filterR = 0; + comb5filterR = 0; + comb6filterR = 0; + comb7filterR = 0; + comb8filterR = 0; + combdamp1 = 6553; + combdamp2 = 26215; + combfeeback = 27524; + memset(allpass1bufL, 0, sizeof(allpass1bufL)); + memset(allpass2bufL, 0, sizeof(allpass2bufL)); + memset(allpass3bufL, 0, sizeof(allpass3bufL)); + memset(allpass4bufL, 0, sizeof(allpass4bufL)); + allpass1indexL = 0; + allpass2indexL = 0; + allpass3indexL = 0; + allpass4indexL = 0; + memset(allpass1bufR, 0, sizeof(allpass1bufR)); + memset(allpass2bufR, 0, sizeof(allpass2bufR)); + memset(allpass3bufR, 0, sizeof(allpass3bufR)); + memset(allpass4bufR, 0, sizeof(allpass4bufR)); + allpass1indexR = 0; + allpass2indexR = 0; + allpass3indexR = 0; + allpass4indexR = 0; } void MyAudioEffectFreeverbStereo::update() { #if defined(__ARM_ARCH_7EM__) - const audio_block_t *block; - audio_block_t *outblockL; - audio_block_t *outblockR; - int i; - int16_t input, bufout, outputL, outputR; - int32_t sum; - - block = receiveReadOnly(0); - outblockL = allocate(); - outblockR = allocate(); - if (!outblockL || !outblockR) { - if (outblockL) release(outblockL); - if (outblockR) release(outblockR); - if (block) release((audio_block_t *)block); - return; - } - if (!block) block = &zeroblock; - - for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { - // TODO: scale numerical range depending on roomsize & damping - input = sat16(block->data[i] * 8738, 17); // for numerical headroom - sum = 0; - - bufout = comb1bufL[comb1indexL]; - sum += bufout; - comb1filterL = sat16(bufout * combdamp2 + comb1filterL * combdamp1, 15); - comb1bufL[comb1indexL] = sat16(input + sat16(comb1filterL * combfeeback, 15), 0); - if (++comb1indexL >= sizeof(comb1bufL)/sizeof(int16_t)) comb1indexL = 0; - - bufout = comb2bufL[comb2indexL]; - sum += bufout; - comb2filterL = sat16(bufout * combdamp2 + comb2filterL * combdamp1, 15); - comb2bufL[comb2indexL] = sat16(input + sat16(comb2filterL * combfeeback, 15), 0); - if (++comb2indexL >= sizeof(comb2bufL)/sizeof(int16_t)) comb2indexL = 0; - - bufout = comb3bufL[comb3indexL]; - sum += bufout; - comb3filterL = sat16(bufout * combdamp2 + comb3filterL * combdamp1, 15); - comb3bufL[comb3indexL] = sat16(input + sat16(comb3filterL * combfeeback, 15), 0); - if (++comb3indexL >= sizeof(comb3bufL)/sizeof(int16_t)) comb3indexL = 0; - - bufout = comb4bufL[comb4indexL]; - sum += bufout; - comb4filterL = sat16(bufout * combdamp2 + comb4filterL * combdamp1, 15); - comb4bufL[comb4indexL] = sat16(input + sat16(comb4filterL * combfeeback, 15), 0); - if (++comb4indexL >= sizeof(comb4bufL)/sizeof(int16_t)) comb4indexL = 0; - - bufout = comb5bufL[comb5indexL]; - sum += bufout; - comb5filterL = sat16(bufout * combdamp2 + comb5filterL * combdamp1, 15); - comb5bufL[comb5indexL] = sat16(input + sat16(comb5filterL * combfeeback, 15), 0); - if (++comb5indexL >= sizeof(comb5bufL)/sizeof(int16_t)) comb5indexL = 0; - - bufout = comb6bufL[comb6indexL]; - sum += bufout; - comb6filterL = sat16(bufout * combdamp2 + comb6filterL * combdamp1, 15); - comb6bufL[comb6indexL] = sat16(input + sat16(comb6filterL * combfeeback, 15), 0); - if (++comb6indexL >= sizeof(comb6bufL)/sizeof(int16_t)) comb6indexL = 0; - - bufout = comb7bufL[comb7indexL]; - sum += bufout; - comb7filterL = sat16(bufout * combdamp2 + comb7filterL * combdamp1, 15); - comb7bufL[comb7indexL] = sat16(input + sat16(comb7filterL * combfeeback, 15), 0); - if (++comb7indexL >= sizeof(comb7bufL)/sizeof(int16_t)) comb7indexL = 0; - - bufout = comb8bufL[comb8indexL]; - sum += bufout; - comb8filterL = sat16(bufout * combdamp2 + comb8filterL * combdamp1, 15); - comb8bufL[comb8indexL] = sat16(input + sat16(comb8filterL * combfeeback, 15), 0); - if (++comb8indexL >= sizeof(comb8bufL)/sizeof(int16_t)) comb8indexL = 0; - - outputL = sat16(sum * 31457, 17); - sum = 0; - - bufout = comb1bufR[comb1indexR]; - sum += bufout; - comb1filterR = sat16(bufout * combdamp2 + comb1filterR * combdamp1, 15); - comb1bufR[comb1indexR] = sat16(input + sat16(comb1filterR * combfeeback, 15), 0); - if (++comb1indexR >= sizeof(comb1bufR)/sizeof(int16_t)) comb1indexR = 0; - - bufout = comb2bufR[comb2indexR]; - sum += bufout; - comb2filterR = sat16(bufout * combdamp2 + comb2filterR * combdamp1, 15); - comb2bufR[comb2indexR] = sat16(input + sat16(comb2filterR * combfeeback, 15), 0); - if (++comb2indexR >= sizeof(comb2bufR)/sizeof(int16_t)) comb2indexR = 0; - - bufout = comb3bufR[comb3indexR]; - sum += bufout; - comb3filterR = sat16(bufout * combdamp2 + comb3filterR * combdamp1, 15); - comb3bufR[comb3indexR] = sat16(input + sat16(comb3filterR * combfeeback, 15), 0); - if (++comb3indexR >= sizeof(comb3bufR)/sizeof(int16_t)) comb3indexR = 0; - - bufout = comb4bufR[comb4indexR]; - sum += bufout; - comb4filterR = sat16(bufout * combdamp2 + comb4filterR * combdamp1, 15); - comb4bufR[comb4indexR] = sat16(input + sat16(comb4filterR * combfeeback, 15), 0); - if (++comb4indexR >= sizeof(comb4bufR)/sizeof(int16_t)) comb4indexR = 0; - - bufout = comb5bufR[comb5indexR]; - sum += bufout; - comb5filterR = sat16(bufout * combdamp2 + comb5filterR * combdamp1, 15); - comb5bufR[comb5indexR] = sat16(input + sat16(comb5filterR * combfeeback, 15), 0); - if (++comb5indexR >= sizeof(comb5bufR)/sizeof(int16_t)) comb5indexR = 0; - - bufout = comb6bufR[comb6indexR]; - sum += bufout; - comb6filterR = sat16(bufout * combdamp2 + comb6filterR * combdamp1, 15); - comb6bufR[comb6indexR] = sat16(input + sat16(comb6filterR * combfeeback, 15), 0); - if (++comb6indexR >= sizeof(comb6bufR)/sizeof(int16_t)) comb6indexR = 0; - - bufout = comb7bufR[comb7indexR]; - sum += bufout; - comb7filterR = sat16(bufout * combdamp2 + comb7filterR * combdamp1, 15); - comb7bufR[comb7indexR] = sat16(input + sat16(comb7filterR * combfeeback, 15), 0); - if (++comb7indexR >= sizeof(comb7bufR)/sizeof(int16_t)) comb7indexR = 0; - - bufout = comb8bufR[comb8indexR]; - sum += bufout; - comb8filterR = sat16(bufout * combdamp2 + comb8filterR * combdamp1, 15); - comb8bufR[comb8indexR] = sat16(input + sat16(comb8filterR * combfeeback, 15), 0); - if (++comb8indexR >= sizeof(comb8bufR)/sizeof(int16_t)) comb8indexR = 0; - - outputR = sat16(sum * 31457, 17); - - bufout = allpass1bufL[allpass1indexL]; - allpass1bufL[allpass1indexL] = outputL + (bufout >> 1); - outputL = sat16(bufout - outputL, 1); - if (++allpass1indexL >= sizeof(allpass1bufL)/sizeof(int16_t)) allpass1indexL = 0; - - bufout = allpass2bufL[allpass2indexL]; - allpass2bufL[allpass2indexL] = outputL + (bufout >> 1); - outputL = sat16(bufout - outputL, 1); - if (++allpass2indexL >= sizeof(allpass2bufL)/sizeof(int16_t)) allpass2indexL = 0; - - bufout = allpass3bufL[allpass3indexL]; - allpass3bufL[allpass3indexL] = outputL + (bufout >> 1); - outputL = sat16(bufout - outputL, 1); - if (++allpass3indexL >= sizeof(allpass3bufL)/sizeof(int16_t)) allpass3indexL = 0; - - bufout = allpass4bufL[allpass4indexL]; - allpass4bufL[allpass4indexL] = outputL + (bufout >> 1); - outputL = sat16(bufout - outputL, 1); - if (++allpass4indexL >= sizeof(allpass4bufL)/sizeof(int16_t)) allpass4indexL = 0; - - outblockL->data[i] = sat16(outputL * 30, 0); - - bufout = allpass1bufR[allpass1indexR]; - allpass1bufR[allpass1indexR] = outputR + (bufout >> 1); - outputR = sat16(bufout - outputR, 1); - if (++allpass1indexR >= sizeof(allpass1bufR)/sizeof(int16_t)) allpass1indexR = 0; - - bufout = allpass2bufR[allpass2indexR]; - allpass2bufR[allpass2indexR] = outputR + (bufout >> 1); - outputR = sat16(bufout - outputR, 1); - if (++allpass2indexR >= sizeof(allpass2bufR)/sizeof(int16_t)) allpass2indexR = 0; - - bufout = allpass3bufR[allpass3indexR]; - allpass3bufR[allpass3indexR] = outputR + (bufout >> 1); - outputR = sat16(bufout - outputR, 1); - if (++allpass3indexR >= sizeof(allpass3bufR)/sizeof(int16_t)) allpass3indexR = 0; - - bufout = allpass4bufR[allpass4indexR]; - allpass4bufR[allpass4indexR] = outputR + (bufout >> 1); - outputR = sat16(bufout - outputR, 1); - if (++allpass4indexR >= sizeof(allpass4bufR)/sizeof(int16_t)) allpass4indexR = 0; - - outblockR->data[i] = sat16(outputL * 30, 0); - } - transmit(outblockL, 0); - transmit(outblockR, 1); - release(outblockL); - release(outblockR); - if (block != &zeroblock) release((audio_block_t *)block); + const audio_block_t *block; + audio_block_t *outblockL; + audio_block_t *outblockR; + int i; + int16_t input, bufout, outputL, outputR; + int32_t sum; + + block = receiveReadOnly(0); + outblockL = allocate(); + outblockR = allocate(); + if (!outblockL || !outblockR) { + if (outblockL) release(outblockL); + if (outblockR) release(outblockR); + if (block) release((audio_block_t *)block); + return; + } + if (!block) block = &zeroblock; + + for (i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { + // TODO: scale numerical range depending on roomsize & damping + input = sat16(block->data[i] * 8738, 17); // for numerical headroom + sum = 0; + + bufout = comb1bufL[comb1indexL]; + sum += bufout; + comb1filterL = sat16(bufout * combdamp2 + comb1filterL * combdamp1, 15); + comb1bufL[comb1indexL] = sat16(input + sat16(comb1filterL * combfeeback, 15), 0); + if (++comb1indexL >= sizeof(comb1bufL) / sizeof(int16_t)) comb1indexL = 0; + + bufout = comb2bufL[comb2indexL]; + sum += bufout; + comb2filterL = sat16(bufout * combdamp2 + comb2filterL * combdamp1, 15); + comb2bufL[comb2indexL] = sat16(input + sat16(comb2filterL * combfeeback, 15), 0); + if (++comb2indexL >= sizeof(comb2bufL) / sizeof(int16_t)) comb2indexL = 0; + + bufout = comb3bufL[comb3indexL]; + sum += bufout; + comb3filterL = sat16(bufout * combdamp2 + comb3filterL * combdamp1, 15); + comb3bufL[comb3indexL] = sat16(input + sat16(comb3filterL * combfeeback, 15), 0); + if (++comb3indexL >= sizeof(comb3bufL) / sizeof(int16_t)) comb3indexL = 0; + + bufout = comb4bufL[comb4indexL]; + sum += bufout; + comb4filterL = sat16(bufout * combdamp2 + comb4filterL * combdamp1, 15); + comb4bufL[comb4indexL] = sat16(input + sat16(comb4filterL * combfeeback, 15), 0); + if (++comb4indexL >= sizeof(comb4bufL) / sizeof(int16_t)) comb4indexL = 0; + + bufout = comb5bufL[comb5indexL]; + sum += bufout; + comb5filterL = sat16(bufout * combdamp2 + comb5filterL * combdamp1, 15); + comb5bufL[comb5indexL] = sat16(input + sat16(comb5filterL * combfeeback, 15), 0); + if (++comb5indexL >= sizeof(comb5bufL) / sizeof(int16_t)) comb5indexL = 0; + + bufout = comb6bufL[comb6indexL]; + sum += bufout; + comb6filterL = sat16(bufout * combdamp2 + comb6filterL * combdamp1, 15); + comb6bufL[comb6indexL] = sat16(input + sat16(comb6filterL * combfeeback, 15), 0); + if (++comb6indexL >= sizeof(comb6bufL) / sizeof(int16_t)) comb6indexL = 0; + + bufout = comb7bufL[comb7indexL]; + sum += bufout; + comb7filterL = sat16(bufout * combdamp2 + comb7filterL * combdamp1, 15); + comb7bufL[comb7indexL] = sat16(input + sat16(comb7filterL * combfeeback, 15), 0); + if (++comb7indexL >= sizeof(comb7bufL) / sizeof(int16_t)) comb7indexL = 0; + + bufout = comb8bufL[comb8indexL]; + sum += bufout; + comb8filterL = sat16(bufout * combdamp2 + comb8filterL * combdamp1, 15); + comb8bufL[comb8indexL] = sat16(input + sat16(comb8filterL * combfeeback, 15), 0); + if (++comb8indexL >= sizeof(comb8bufL) / sizeof(int16_t)) comb8indexL = 0; + + outputL = sat16(sum * 31457, 17); + sum = 0; + + bufout = comb1bufR[comb1indexR]; + sum += bufout; + comb1filterR = sat16(bufout * combdamp2 + comb1filterR * combdamp1, 15); + comb1bufR[comb1indexR] = sat16(input + sat16(comb1filterR * combfeeback, 15), 0); + if (++comb1indexR >= sizeof(comb1bufR) / sizeof(int16_t)) comb1indexR = 0; + + bufout = comb2bufR[comb2indexR]; + sum += bufout; + comb2filterR = sat16(bufout * combdamp2 + comb2filterR * combdamp1, 15); + comb2bufR[comb2indexR] = sat16(input + sat16(comb2filterR * combfeeback, 15), 0); + if (++comb2indexR >= sizeof(comb2bufR) / sizeof(int16_t)) comb2indexR = 0; + + bufout = comb3bufR[comb3indexR]; + sum += bufout; + comb3filterR = sat16(bufout * combdamp2 + comb3filterR * combdamp1, 15); + comb3bufR[comb3indexR] = sat16(input + sat16(comb3filterR * combfeeback, 15), 0); + if (++comb3indexR >= sizeof(comb3bufR) / sizeof(int16_t)) comb3indexR = 0; + + bufout = comb4bufR[comb4indexR]; + sum += bufout; + comb4filterR = sat16(bufout * combdamp2 + comb4filterR * combdamp1, 15); + comb4bufR[comb4indexR] = sat16(input + sat16(comb4filterR * combfeeback, 15), 0); + if (++comb4indexR >= sizeof(comb4bufR) / sizeof(int16_t)) comb4indexR = 0; + + bufout = comb5bufR[comb5indexR]; + sum += bufout; + comb5filterR = sat16(bufout * combdamp2 + comb5filterR * combdamp1, 15); + comb5bufR[comb5indexR] = sat16(input + sat16(comb5filterR * combfeeback, 15), 0); + if (++comb5indexR >= sizeof(comb5bufR) / sizeof(int16_t)) comb5indexR = 0; + + bufout = comb6bufR[comb6indexR]; + sum += bufout; + comb6filterR = sat16(bufout * combdamp2 + comb6filterR * combdamp1, 15); + comb6bufR[comb6indexR] = sat16(input + sat16(comb6filterR * combfeeback, 15), 0); + if (++comb6indexR >= sizeof(comb6bufR) / sizeof(int16_t)) comb6indexR = 0; + + bufout = comb7bufR[comb7indexR]; + sum += bufout; + comb7filterR = sat16(bufout * combdamp2 + comb7filterR * combdamp1, 15); + comb7bufR[comb7indexR] = sat16(input + sat16(comb7filterR * combfeeback, 15), 0); + if (++comb7indexR >= sizeof(comb7bufR) / sizeof(int16_t)) comb7indexR = 0; + + bufout = comb8bufR[comb8indexR]; + sum += bufout; + comb8filterR = sat16(bufout * combdamp2 + comb8filterR * combdamp1, 15); + comb8bufR[comb8indexR] = sat16(input + sat16(comb8filterR * combfeeback, 15), 0); + if (++comb8indexR >= sizeof(comb8bufR) / sizeof(int16_t)) comb8indexR = 0; + + outputR = sat16(sum * 31457, 17); + + bufout = allpass1bufL[allpass1indexL]; + allpass1bufL[allpass1indexL] = outputL + (bufout >> 1); + outputL = sat16(bufout - outputL, 1); + if (++allpass1indexL >= sizeof(allpass1bufL) / sizeof(int16_t)) allpass1indexL = 0; + + bufout = allpass2bufL[allpass2indexL]; + allpass2bufL[allpass2indexL] = outputL + (bufout >> 1); + outputL = sat16(bufout - outputL, 1); + if (++allpass2indexL >= sizeof(allpass2bufL) / sizeof(int16_t)) allpass2indexL = 0; + + bufout = allpass3bufL[allpass3indexL]; + allpass3bufL[allpass3indexL] = outputL + (bufout >> 1); + outputL = sat16(bufout - outputL, 1); + if (++allpass3indexL >= sizeof(allpass3bufL) / sizeof(int16_t)) allpass3indexL = 0; + + bufout = allpass4bufL[allpass4indexL]; + allpass4bufL[allpass4indexL] = outputL + (bufout >> 1); + outputL = sat16(bufout - outputL, 1); + if (++allpass4indexL >= sizeof(allpass4bufL) / sizeof(int16_t)) allpass4indexL = 0; + + outblockL->data[i] = sat16(outputL * 30, 0); + + bufout = allpass1bufR[allpass1indexR]; + allpass1bufR[allpass1indexR] = outputR + (bufout >> 1); + outputR = sat16(bufout - outputR, 1); + if (++allpass1indexR >= sizeof(allpass1bufR) / sizeof(int16_t)) allpass1indexR = 0; + + bufout = allpass2bufR[allpass2indexR]; + allpass2bufR[allpass2indexR] = outputR + (bufout >> 1); + outputR = sat16(bufout - outputR, 1); + if (++allpass2indexR >= sizeof(allpass2bufR) / sizeof(int16_t)) allpass2indexR = 0; + + bufout = allpass3bufR[allpass3indexR]; + allpass3bufR[allpass3indexR] = outputR + (bufout >> 1); + outputR = sat16(bufout - outputR, 1); + if (++allpass3indexR >= sizeof(allpass3bufR) / sizeof(int16_t)) allpass3indexR = 0; + + bufout = allpass4bufR[allpass4indexR]; + allpass4bufR[allpass4indexR] = outputR + (bufout >> 1); + outputR = sat16(bufout - outputR, 1); + if (++allpass4indexR >= sizeof(allpass4bufR) / sizeof(int16_t)) allpass4indexR = 0; + + outblockR->data[i] = sat16(outputL * 30, 0); + } + transmit(outblockL, 0); + transmit(outblockR, 1); + release(outblockL); + release(outblockR); + if (block != &zeroblock) release((audio_block_t *)block); #elif defined(KINETISL) - audio_block_t *block; - block = receiveReadOnly(0); - if (block) release(block); + audio_block_t *block; + block = receiveReadOnly(0); + if (block) release(block); #endif } diff --git a/my_effect_freeverb.h b/my_effect_freeverb.h index e3c612a..0d6dbdf 100644 --- a/my_effect_freeverb.h +++ b/my_effect_freeverb.h @@ -1,28 +1,28 @@ /* Audio Library for Teensy 3.X - * Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com - * - * Development of this audio library was funded by PJRC.COM, LLC by sales of - * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop - * open source software by purchasing Teensy or other PJRC products. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice, development funding notice, and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ + Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com + + Development of this audio library was funded by PJRC.COM, LLC by sales of + Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + open source software by purchasing Teensy or other PJRC products. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice, development funding notice, and this permission + notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ #ifndef my_effect_freeverb_h_ #define my_effect_freeverb_h_ @@ -31,153 +31,153 @@ class MyAudioEffectFreeverb : public AudioStream { -public: - MyAudioEffectFreeverb(); - virtual void update(); - void roomsize(float n) { - if (n > 1.0f) n = 1.0f; - else if (n < 0.0) n = 0.0f; - combfeeback = (int)(n * 9175.04f) + 22937; - } - void damping(float n) { - if (n > 1.0f) n = 1.0f; - else if (n < 0.0) n = 0.0f; - int x1 = (int)(n * 13107.2f); - int x2 = 32768 - x1; - __disable_irq(); - combdamp1 = x1; - combdamp2 = x2; - __enable_irq(); - } -private: - audio_block_t *inputQueueArray[1]; - int16_t comb1buf[1116]; - int16_t comb2buf[1188]; - int16_t comb3buf[1277]; - int16_t comb4buf[1356]; - int16_t comb5buf[1422]; - int16_t comb6buf[1491]; - int16_t comb7buf[1557]; - int16_t comb8buf[1617]; - uint16_t comb1index; - uint16_t comb2index; - uint16_t comb3index; - uint16_t comb4index; - uint16_t comb5index; - uint16_t comb6index; - uint16_t comb7index; - uint16_t comb8index; - int16_t comb1filter; - int16_t comb2filter; - int16_t comb3filter; - int16_t comb4filter; - int16_t comb5filter; - int16_t comb6filter; - int16_t comb7filter; - int16_t comb8filter; - int16_t combdamp1; - int16_t combdamp2; - int16_t combfeeback; - int16_t allpass1buf[556]; - int16_t allpass2buf[441]; - int16_t allpass3buf[341]; - int16_t allpass4buf[225]; - uint16_t allpass1index; - uint16_t allpass2index; - uint16_t allpass3index; - uint16_t allpass4index; + public: + MyAudioEffectFreeverb(); + virtual void update(); + void roomsize(float n) { + if (n > 1.0f) n = 1.0f; + else if (n < 0.0) n = 0.0f; + combfeeback = (int)(n * 9175.04f) + 22937; + } + void damping(float n) { + if (n > 1.0f) n = 1.0f; + else if (n < 0.0) n = 0.0f; + int x1 = (int)(n * 13107.2f); + int x2 = 32768 - x1; + __disable_irq(); + combdamp1 = x1; + combdamp2 = x2; + __enable_irq(); + } + private: + audio_block_t *inputQueueArray[1]; + int16_t comb1buf[1116]; + int16_t comb2buf[1188]; + int16_t comb3buf[1277]; + int16_t comb4buf[1356]; + int16_t comb5buf[1422]; + int16_t comb6buf[1491]; + int16_t comb7buf[1557]; + int16_t comb8buf[1617]; + uint16_t comb1index; + uint16_t comb2index; + uint16_t comb3index; + uint16_t comb4index; + uint16_t comb5index; + uint16_t comb6index; + uint16_t comb7index; + uint16_t comb8index; + int16_t comb1filter; + int16_t comb2filter; + int16_t comb3filter; + int16_t comb4filter; + int16_t comb5filter; + int16_t comb6filter; + int16_t comb7filter; + int16_t comb8filter; + int16_t combdamp1; + int16_t combdamp2; + int16_t combfeeback; + int16_t allpass1buf[556]; + int16_t allpass2buf[441]; + int16_t allpass3buf[341]; + int16_t allpass4buf[225]; + uint16_t allpass1index; + uint16_t allpass2index; + uint16_t allpass3index; + uint16_t allpass4index; }; class MyAudioEffectFreeverbStereo : public AudioStream { -public: - MyAudioEffectFreeverbStereo(); - virtual void update(); - void roomsize(float n) { - if (n > 1.0f) n = 1.0f; - else if (n < 0.0) n = 0.0f; - combfeeback = (int)(n * 9175.04f) + 22937; - } - void damping(float n) { - if (n > 1.0f) n = 1.0f; - else if (n < 0.0) n = 0.0f; - int x1 = (int)(n * 13107.2f); - int x2 = 32768 - x1; - __disable_irq(); - combdamp1 = x1; - combdamp2 = x2; - __enable_irq(); - } -private: - audio_block_t *inputQueueArray[1]; - int16_t comb1bufL[1116]; - int16_t comb2bufL[1188]; - int16_t comb3bufL[1277]; - int16_t comb4bufL[1356]; - int16_t comb5bufL[1422]; - int16_t comb6bufL[1491]; - int16_t comb7bufL[1557]; - int16_t comb8bufL[1617]; - uint16_t comb1indexL; - uint16_t comb2indexL; - uint16_t comb3indexL; - uint16_t comb4indexL; - uint16_t comb5indexL; - uint16_t comb6indexL; - uint16_t comb7indexL; - uint16_t comb8indexL; - int16_t comb1filterL; - int16_t comb2filterL; - int16_t comb3filterL; - int16_t comb4filterL; - int16_t comb5filterL; - int16_t comb6filterL; - int16_t comb7filterL; - int16_t comb8filterL; - int16_t comb1bufR[1139]; - int16_t comb2bufR[1211]; - int16_t comb3bufR[1300]; - int16_t comb4bufR[1379]; - int16_t comb5bufR[1445]; - int16_t comb6bufR[1514]; - int16_t comb7bufR[1580]; - int16_t comb8bufR[1640]; - uint16_t comb1indexR; - uint16_t comb2indexR; - uint16_t comb3indexR; - uint16_t comb4indexR; - uint16_t comb5indexR; - uint16_t comb6indexR; - uint16_t comb7indexR; - uint16_t comb8indexR; - int16_t comb1filterR; - int16_t comb2filterR; - int16_t comb3filterR; - int16_t comb4filterR; - int16_t comb5filterR; - int16_t comb6filterR; - int16_t comb7filterR; - int16_t comb8filterR; - int16_t combdamp1; - int16_t combdamp2; - int16_t combfeeback; - int16_t allpass1bufL[556]; - int16_t allpass2bufL[441]; - int16_t allpass3bufL[341]; - int16_t allpass4bufL[225]; - uint16_t allpass1indexL; - uint16_t allpass2indexL; - uint16_t allpass3indexL; - uint16_t allpass4indexL; - int16_t allpass1bufR[579]; - int16_t allpass2bufR[464]; - int16_t allpass3bufR[364]; - int16_t allpass4bufR[248]; - uint16_t allpass1indexR; - uint16_t allpass2indexR; - uint16_t allpass3indexR; - uint16_t allpass4indexR; + public: + MyAudioEffectFreeverbStereo(); + virtual void update(); + void roomsize(float n) { + if (n > 1.0f) n = 1.0f; + else if (n < 0.0) n = 0.0f; + combfeeback = (int)(n * 9175.04f) + 22937; + } + void damping(float n) { + if (n > 1.0f) n = 1.0f; + else if (n < 0.0) n = 0.0f; + int x1 = (int)(n * 13107.2f); + int x2 = 32768 - x1; + __disable_irq(); + combdamp1 = x1; + combdamp2 = x2; + __enable_irq(); + } + private: + audio_block_t *inputQueueArray[1]; + int16_t comb1bufL[1116]; + int16_t comb2bufL[1188]; + int16_t comb3bufL[1277]; + int16_t comb4bufL[1356]; + int16_t comb5bufL[1422]; + int16_t comb6bufL[1491]; + int16_t comb7bufL[1557]; + int16_t comb8bufL[1617]; + uint16_t comb1indexL; + uint16_t comb2indexL; + uint16_t comb3indexL; + uint16_t comb4indexL; + uint16_t comb5indexL; + uint16_t comb6indexL; + uint16_t comb7indexL; + uint16_t comb8indexL; + int16_t comb1filterL; + int16_t comb2filterL; + int16_t comb3filterL; + int16_t comb4filterL; + int16_t comb5filterL; + int16_t comb6filterL; + int16_t comb7filterL; + int16_t comb8filterL; + int16_t comb1bufR[1139]; + int16_t comb2bufR[1211]; + int16_t comb3bufR[1300]; + int16_t comb4bufR[1379]; + int16_t comb5bufR[1445]; + int16_t comb6bufR[1514]; + int16_t comb7bufR[1580]; + int16_t comb8bufR[1640]; + uint16_t comb1indexR; + uint16_t comb2indexR; + uint16_t comb3indexR; + uint16_t comb4indexR; + uint16_t comb5indexR; + uint16_t comb6indexR; + uint16_t comb7indexR; + uint16_t comb8indexR; + int16_t comb1filterR; + int16_t comb2filterR; + int16_t comb3filterR; + int16_t comb4filterR; + int16_t comb5filterR; + int16_t comb6filterR; + int16_t comb7filterR; + int16_t comb8filterR; + int16_t combdamp1; + int16_t combdamp2; + int16_t combfeeback; + int16_t allpass1bufL[556]; + int16_t allpass2bufL[441]; + int16_t allpass3bufL[341]; + int16_t allpass4bufL[225]; + uint16_t allpass1indexL; + uint16_t allpass2indexL; + uint16_t allpass3indexL; + uint16_t allpass4indexL; + int16_t allpass1bufR[579]; + int16_t allpass2bufR[464]; + int16_t allpass3bufR[364]; + int16_t allpass4bufR[248]; + uint16_t allpass1indexR; + uint16_t allpass2indexR; + uint16_t allpass3indexR; + uint16_t allpass4indexR; }; diff --git a/name.c b/name.c index f2073ec..5c96b91 100644 --- a/name.c +++ b/name.c @@ -5,7 +5,7 @@ // Do not change this part. This exact format is required by USB. struct usb_string_descriptor_struct usb_string_product_name = { - 2 + MIDI_NAME_LEN * 2, - 3, - MIDI_NAME + 2 + MIDI_NAME_LEN * 2, + 3, + MIDI_NAME }; diff --git a/pitchenv.cpp b/pitchenv.cpp index 9ff29ca..d7f53bd 100644 --- a/pitchenv.cpp +++ b/pitchenv.cpp @@ -1,18 +1,18 @@ /* - * 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 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 "synth.h" #include "pitchenv.h" @@ -91,5 +91,3 @@ void PitchEnv::advance(int newix) { void PitchEnv::getPosition(char *step) { *step = ix_; } - - diff --git a/pitchenv.h b/pitchenv.h index 6386fc5..50b5134 100644 --- a/pitchenv.h +++ b/pitchenv.h @@ -1,18 +1,18 @@ /* - * Copyright 2013 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 2013 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. +*/ #ifndef __PITCHENV_H #define __PITCHENV_H @@ -20,34 +20,33 @@ // Computation of the DX7 pitch envelope class PitchEnv { - public: - static void init(FRAC_NUM sample_rate); - - // The rates and levels arrays are calibrated to match the Dx7 parameters - // (ie, value 0..99). - void set(const int rates[4], const int levels[4]); - - // Result is in Q24/octave - int32_t getsample(); - void keydown(bool down); - void getPosition(char *step); - private: - static int unit_; - int rates_[4]; - int levels_[4]; - int32_t level_; - int targetlevel_; - bool rising_; - int ix_; - int inc_; - - bool down_; - - void advance(int newix); + public: + static void init(FRAC_NUM sample_rate); + + // The rates and levels arrays are calibrated to match the Dx7 parameters + // (ie, value 0..99). + void set(const int rates[4], const int levels[4]); + + // Result is in Q24/octave + int32_t getsample(); + void keydown(bool down); + void getPosition(char *step); + private: + static int unit_; + int rates_[4]; + int levels_[4]; + int32_t level_; + int targetlevel_; + bool rising_; + int ix_; + int inc_; + + bool down_; + + void advance(int newix); }; extern const uint8_t pitchenv_rate[]; extern const int8_t pitchenv_tab[]; - #endif // __PITCHENV_H - +#endif // __PITCHENV_H diff --git a/sin.h b/sin.h index d84a7d3..85eccd1 100644 --- a/sin.h +++ b/sin.h @@ -1,29 +1,29 @@ /* - * 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 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. +*/ class Sin { - public: - Sin(); + public: + Sin(); - static void init(); - static int32_t lookup(int32_t phase); - static int32_t compute(int32_t phase); + static void init(); + static int32_t lookup(int32_t phase); + static int32_t compute(int32_t phase); - // A more accurate sine, both input and output Q30 - static int32_t compute10(int32_t phase); + // A more accurate sine, both input and output Q30 + static int32_t compute10(int32_t phase); }; #define SIN_LG_N_SAMPLES 10 diff --git a/source_microdexed.h b/source_microdexed.h index f220754..e46e867 100644 --- a/source_microdexed.h +++ b/source_microdexed.h @@ -14,7 +14,7 @@ class AudioSourceMicroDexed : public AudioStream, public Dexed { void update(void) { - if (in_update==true) + if (in_update == true) { xrun++; return; diff --git a/synth.h b/synth.h index b37b9d3..f74f98a 100644 --- a/synth.h +++ b/synth.h @@ -65,12 +65,12 @@ inline static T max(const T& a, const T& b) { #define FRAC_NUM float #define SIN_FUNC sinf -// #define SIN_FUNC arm_sin_f32 // very fast but not as accurate +// #define SIN_FUNC arm_sin_f32 // very fast but not as accurate #define COS_FUNC cosf -// #define COS_FUNC arm_cos_f32 // very fast but not as accurate +// #define COS_FUNC arm_cos_f32 // very fast but not as accurate #define LOG_FUNC logf #define EXP_FUNC expf #define SQRT_FUNC sqrtf -// #define ARM_SQRT_FUNC arm_sqrt_f32 // fast but not as accurate +// #define ARM_SQRT_FUNC arm_sqrt_f32 // fast but not as accurate #endif // __SYNTH_H diff --git a/teensy_board_detection.h b/teensy_board_detection.h index cf233c0..bf59d63 100644 --- a/teensy_board_detection.h +++ b/teensy_board_detection.h @@ -37,12 +37,12 @@ #endif #endif -// Teensy-3.6 +// Teensy-3.6 #if defined(__MK66FX1M0__) # define TEENSY3_6 #endif -// Teensy-3.5 +// Teensy-3.5 #if defined (__MK64FX512__) #define TEENSY3_5 #endif