1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SYNTHMARK_SYNTHTOOLS_H 18 #define SYNTHMARK_SYNTHTOOLS_H 19 20 #include <cmath> 21 #include <cstdint> 22 23 namespace marksynth { 24 typedef float synth_float_t; 25 26 // The number of frames that are synthesized at one time. 27 constexpr int kSynthmarkFramesPerRender = 8; 28 29 constexpr int kSynthmarkSampleRate = 48000; 30 constexpr int kSynthmarkMaxVoices = 1024; 31 32 /** 33 * A fractional amplitude corresponding to exactly -96 dB. 34 * amplitude = pow(10.0, db/20.0) 35 */ 36 constexpr double kAmplitudeDb96 = 1.0 / 63095.73444801943; 37 38 /** A fraction that is approximately -90.3 dB. Defined as 1 bit of an S16. */ 39 constexpr double kAmplitudeDb90 = 1.0 / (1 << 15); 40 41 class SynthTools 42 { 43 public: 44 fillBuffer(synth_float_t * output,int32_t numSamples,synth_float_t value)45 static void fillBuffer(synth_float_t *output, 46 int32_t numSamples, 47 synth_float_t value) { 48 for (int i = 0; i < numSamples; i++) { 49 *output++ = value; 50 } 51 } 52 scaleBuffer(const synth_float_t * input,synth_float_t * output,int32_t numSamples,synth_float_t multiplier)53 static void scaleBuffer(const synth_float_t *input, 54 synth_float_t *output, 55 int32_t numSamples, 56 synth_float_t multiplier) { 57 for (int i = 0; i < numSamples; i++) { 58 *output++ = *input++ * multiplier; 59 } 60 } 61 scaleOffsetBuffer(const synth_float_t * input,synth_float_t * output,int32_t numSamples,synth_float_t multiplier,synth_float_t offset)62 static void scaleOffsetBuffer(const synth_float_t *input, 63 synth_float_t *output, 64 int32_t numSamples, 65 synth_float_t multiplier, 66 synth_float_t offset) { 67 for (int i = 0; i < numSamples; i++) { 68 *output++ = (*input++ * multiplier) + offset; 69 } 70 } 71 mixBuffers(const synth_float_t * input1,synth_float_t gain1,const synth_float_t * input2,synth_float_t gain2,synth_float_t * output,int32_t numSamples)72 static void mixBuffers(const synth_float_t *input1, 73 synth_float_t gain1, 74 const synth_float_t *input2, 75 synth_float_t gain2, 76 synth_float_t *output, 77 int32_t numSamples) { 78 for (int i = 0; i < numSamples; i++) { 79 *output++ = (*input1++ * gain1) + (*input2++ * gain2); 80 } 81 } 82 multiplyBuffers(const synth_float_t * input1,const synth_float_t * input2,synth_float_t * output,int32_t numSamples)83 static void multiplyBuffers(const synth_float_t *input1, 84 const synth_float_t *input2, 85 synth_float_t *output, 86 int32_t numSamples) { 87 for (int i = 0; i < numSamples; i++) { 88 *output++ = *input1++ * *input2; 89 } 90 } 91 convertTimeToExponentialScaler(synth_float_t duration,synth_float_t sampleRate)92 static double convertTimeToExponentialScaler(synth_float_t duration, synth_float_t sampleRate) { 93 // Calculate scaler so that scaler^frames = target/source 94 synth_float_t numFrames = duration * sampleRate; 95 return pow(kAmplitudeDb90, (1.0 / numFrames)); 96 } 97 98 /** 99 * Calculate sine using a Taylor expansion. 100 * Code is based on SineOscillator from JSyn. 101 * 102 * @param phase between -PI and +PI 103 */ fastSine(synth_float_t phase)104 static synth_float_t fastSine(synth_float_t phase) { 105 // Factorial coefficients. 106 const synth_float_t IF3 = 1.0 / (2 * 3); 107 const synth_float_t IF5 = IF3 / (4 * 5); 108 const synth_float_t IF7 = IF5 / (6 * 7); 109 const synth_float_t IF9 = IF7 / (8 * 9); 110 const synth_float_t IF11 = IF9 / (10 * 11); 111 112 /* Wrap phase back into region where results are more accurate. */ 113 synth_float_t x = (phase > M_PI_2) ? M_PI - phase 114 : ((phase < -M_PI_2) ? -(M_PI + phase) : phase); 115 116 synth_float_t x2 = (x * x); 117 /* Taylor expansion out to x**11/11! factored into multiply-adds */ 118 return x * (x2 * (x2 * (x2 * (x2 * ((x2 * (-IF11)) + IF9) - IF7) + IF5) - IF3) + 1); 119 } 120 121 /** 122 * Calculate cosine using a Taylor expansion. 123 * 124 * @param phase between -PI and +PI 125 */ fastCosine(synth_float_t phase)126 static synth_float_t fastCosine(synth_float_t phase) { 127 // Factorial coefficients. 128 const synth_float_t IF2 = 1.0 / (2); 129 const synth_float_t IF4 = IF2 / (3 * 4); 130 const synth_float_t IF6 = IF4 / (5 * 6); 131 const synth_float_t IF8 = IF6 / (7 * 8); 132 const synth_float_t IF10 = IF8 / (9 * 10); 133 134 /* Wrap phase back into region where results are more accurate. */ 135 synth_float_t x = phase; 136 if (x < 0.0) { 137 x = 0.0 - phase; 138 } 139 int negate = 1; 140 if (x > M_PI_2) { 141 x = M_PI_2 - x; 142 negate = -1; 143 } 144 145 synth_float_t x2 = (x * x); 146 /* Taylor expansion out to x**11/11! factored into multiply-adds */ 147 synth_float_t cosine = 148 1 + (x2 * (x2 * (x2 * (x2 * ((x2 * (-IF10)) + IF8) - IF6) + IF4) - IF2)); 149 return cosine * negate; 150 } 151 152 153 /** 154 * Calculate random 32 bit number using linear-congruential method. 155 */ nextRandomInteger()156 static uint32_t nextRandomInteger() { 157 static uint64_t seed = 99887766; 158 // Use values for 64-bit sequence from MMIX by Donald Knuth. 159 seed = (seed * 6364136223846793005L) + 1442695040888963407L; 160 return (uint32_t) (seed >> 32); // The higher bits have a longer sequence. 161 } 162 163 /** 164 * @return a random double between 0.0 and 1.0 165 */ nextRandomDouble()166 static double nextRandomDouble() { 167 const double scaler = 1.0 / (((uint64_t)1) << 32); 168 return nextRandomInteger() * scaler; 169 } 170 171 }; 172 }; 173 #endif // SYNTHMARK_SYNTHTOOLS_H 174