1*05767d91SRobert Wu /* 2*05767d91SRobert Wu * Copyright 2018 The Android Open Source Project 3*05767d91SRobert Wu * 4*05767d91SRobert Wu * Licensed under the Apache License, Version 2.0 (the "License"); 5*05767d91SRobert Wu * you may not use this file except in compliance with the License. 6*05767d91SRobert Wu * You may obtain a copy of the License at 7*05767d91SRobert Wu * 8*05767d91SRobert Wu * http://www.apache.org/licenses/LICENSE-2.0 9*05767d91SRobert Wu * 10*05767d91SRobert Wu * Unless required by applicable law or agreed to in writing, software 11*05767d91SRobert Wu * distributed under the License is distributed on an "AS IS" BASIS, 12*05767d91SRobert Wu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*05767d91SRobert Wu * See the License for the specific language governing permissions and 14*05767d91SRobert Wu * limitations under the License. 15*05767d91SRobert Wu */ 16*05767d91SRobert Wu #ifndef SHARED_SYNTH_SOUND_H 17*05767d91SRobert Wu #define SHARED_SYNTH_SOUND_H 18*05767d91SRobert Wu #include <cstdint> 19*05767d91SRobert Wu #include <atomic> 20*05767d91SRobert Wu #include <math.h> 21*05767d91SRobert Wu #include <memory> 22*05767d91SRobert Wu #include "IRenderableAudio.h" 23*05767d91SRobert Wu constexpr float kDefaultFrequency = 440.0; 24*05767d91SRobert Wu constexpr int32_t kDefaultSampleRate = 48000; 25*05767d91SRobert Wu constexpr float kPi = M_PI; 26*05767d91SRobert Wu constexpr float kTwoPi = kPi * 2; 27*05767d91SRobert Wu constexpr int32_t kNumSineWaves = 5; 28*05767d91SRobert Wu constexpr float kSustainMultiplier = 0.99999; 29*05767d91SRobert Wu constexpr float kReleaseMultiplier = 0.999; 30*05767d91SRobert Wu // Stop playing music below this cutoff 31*05767d91SRobert Wu constexpr float kMasterAmplitudeCutOff = 0.01; 32*05767d91SRobert Wu 33*05767d91SRobert Wu class SynthSound : public IRenderableAudio { 34*05767d91SRobert Wu 35*05767d91SRobert Wu public: SynthSound()36*05767d91SRobert Wu SynthSound() { 37*05767d91SRobert Wu 38*05767d91SRobert Wu } 39*05767d91SRobert Wu ~SynthSound()40*05767d91SRobert Wu ~SynthSound() { 41*05767d91SRobert Wu 42*05767d91SRobert Wu }; 43*05767d91SRobert Wu noteOn()44*05767d91SRobert Wu void noteOn() { 45*05767d91SRobert Wu mTrigger = true; // start a note envelope 46*05767d91SRobert Wu mAmplitudeScaler = kSustainMultiplier; 47*05767d91SRobert Wu } 48*05767d91SRobert Wu noteOff()49*05767d91SRobert Wu void noteOff() { 50*05767d91SRobert Wu mAmplitudeScaler = kReleaseMultiplier; 51*05767d91SRobert Wu } 52*05767d91SRobert Wu setSampleRate(int32_t sampleRate)53*05767d91SRobert Wu void setSampleRate(int32_t sampleRate) { 54*05767d91SRobert Wu mSampleRate = sampleRate; 55*05767d91SRobert Wu updatePhaseIncrement(); 56*05767d91SRobert Wu }; setFrequency(float frequency)57*05767d91SRobert Wu void setFrequency(float frequency) { 58*05767d91SRobert Wu mFrequency = frequency; 59*05767d91SRobert Wu updatePhaseIncrement(); 60*05767d91SRobert Wu }; 61*05767d91SRobert Wu // Amplitudes from https://epubs.siam.org/doi/pdf/10.1137/S00361445003822 setAmplitude(float amplitude)62*05767d91SRobert Wu inline void setAmplitude(float amplitude) { 63*05767d91SRobert Wu mAmplitudes[0] = amplitude * .2f; 64*05767d91SRobert Wu mAmplitudes[1] = amplitude; 65*05767d91SRobert Wu mAmplitudes[2] = amplitude * .1f; 66*05767d91SRobert Wu mAmplitudes[3] = amplitude * .02f; 67*05767d91SRobert Wu mAmplitudes[4] = amplitude * .15f; 68*05767d91SRobert Wu }; 69*05767d91SRobert Wu // From IRenderableAudio renderAudio(float * audioData,int32_t numFrames)70*05767d91SRobert Wu void renderAudio(float *audioData, int32_t numFrames) override { 71*05767d91SRobert Wu for (int i = 0; i < numFrames; ++i) { 72*05767d91SRobert Wu if (mTrigger.exchange(false)) { 73*05767d91SRobert Wu mMasterAmplitude = 1.0; 74*05767d91SRobert Wu mPhase = 0.0f; 75*05767d91SRobert Wu } else { 76*05767d91SRobert Wu mMasterAmplitude *= mAmplitudeScaler; 77*05767d91SRobert Wu } 78*05767d91SRobert Wu 79*05767d91SRobert Wu audioData[i] = 0; 80*05767d91SRobert Wu if (mMasterAmplitude < kMasterAmplitudeCutOff) { 81*05767d91SRobert Wu continue; 82*05767d91SRobert Wu } 83*05767d91SRobert Wu for (int j = 0; j < kNumSineWaves; ++j) { 84*05767d91SRobert Wu audioData[i] += sinf(mPhase * (j + 1)) * mAmplitudes[j] * mMasterAmplitude; 85*05767d91SRobert Wu } 86*05767d91SRobert Wu mPhase += mPhaseIncrement; 87*05767d91SRobert Wu if (mPhase > kTwoPi) { 88*05767d91SRobert Wu mPhase -= kTwoPi; 89*05767d91SRobert Wu } 90*05767d91SRobert Wu } 91*05767d91SRobert Wu }; 92*05767d91SRobert Wu 93*05767d91SRobert Wu private: 94*05767d91SRobert Wu std::atomic<bool> mTrigger { false }; 95*05767d91SRobert Wu float mMasterAmplitude = 0.0f; 96*05767d91SRobert Wu std::atomic<float> mAmplitudeScaler { 0.0f }; 97*05767d91SRobert Wu std::array<std::atomic<float>, kNumSineWaves> mAmplitudes; 98*05767d91SRobert Wu float mPhase = 0.0f; 99*05767d91SRobert Wu std::atomic<float> mPhaseIncrement { 0 }; 100*05767d91SRobert Wu std::atomic<float> mFrequency { kDefaultFrequency }; 101*05767d91SRobert Wu std::atomic<int32_t> mSampleRate { kDefaultSampleRate }; updatePhaseIncrement()102*05767d91SRobert Wu void updatePhaseIncrement(){ 103*05767d91SRobert Wu // Note how there is a division here. If this file is changed so that updatePhaseIncrement 104*05767d91SRobert Wu // is called more frequently, please cache 1/mSampleRate. This allows this operation to not 105*05767d91SRobert Wu // need divisions. 106*05767d91SRobert Wu mPhaseIncrement = kTwoPi * mFrequency / static_cast<float>(mSampleRate); 107*05767d91SRobert Wu }; 108*05767d91SRobert Wu }; 109*05767d91SRobert Wu #endif //SHARED_SYNTH_SOUND_H 110