1 /* 2 * Copyright 2018 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 SOUNDBOARD_SYNTH_H 18 #define SOUNDBOARD_SYNTH_H 19 20 #include <array> 21 #include <TappableAudioSource.h> 22 23 #include <SynthSound.h> 24 #include <Mixer.h> 25 #include <MonoToStereo.h> 26 27 constexpr float kOscBaseFrequency = 196.00; // Start at G3 28 constexpr float kOscFrequencyMultiplier = 1.05946309436; 29 constexpr float kOscBaseAmplitude = 0.20; 30 constexpr float kOscAmplitudeMultiplier = 0.96; 31 32 class Synth : public IRenderableAudio, public ITappable { 33 public: create(const int32_t sampleRate,const int32_t channelCount,const int32_t numSignals)34 static ::std::shared_ptr<Synth> create(const int32_t sampleRate, const int32_t channelCount, const int32_t numSignals) { 35 return ::std::make_shared<Synth>(sampleRate, channelCount, numSignals); 36 } 37 Synth(const int32_t sampleRate,const int32_t channelCount,const int32_t numSignals)38 Synth(const int32_t sampleRate, const int32_t channelCount, const int32_t numSignals) { 39 float curFrequency = kOscBaseFrequency; 40 float curAmplitude = kOscBaseAmplitude; 41 for (int i = 0; i < numSignals; ++i) { 42 mOscs[i].setSampleRate(sampleRate); 43 mOscs[i].setFrequency(curFrequency); 44 curFrequency *= kOscFrequencyMultiplier; 45 mOscs[i].setAmplitude(curAmplitude); 46 curAmplitude *= kOscAmplitudeMultiplier; 47 mMixer.addTrack(&mOscs[i]); 48 } 49 50 if (channelCount == oboe::ChannelCount::Stereo) { 51 mOutputStage = &mConverter; 52 } else { 53 mOutputStage = &mMixer; 54 } 55 } 56 noteOff(int32_t noteIndex)57 void noteOff(int32_t noteIndex) { 58 mOscs[noteIndex].noteOff(); 59 } 60 noteOn(int32_t noteIndex)61 void noteOn(int32_t noteIndex) { 62 mOscs[noteIndex].noteOn(); 63 } 64 tap(bool isOn)65 void tap(bool isOn) override { 66 for (int i = 0; i < mNumSignals; i++) { 67 if (isOn) { 68 mOscs[i].noteOn(); 69 } else { 70 mOscs[i].noteOff(); 71 } 72 } 73 }; 74 75 // From IRenderableAudio renderAudio(float * audioData,int32_t numFrames)76 void renderAudio(float *audioData, int32_t numFrames) override { 77 mOutputStage->renderAudio(audioData, numFrames); 78 }; 79 ~Synth()80 virtual ~Synth() { 81 } 82 private: 83 // Rendering objects 84 int32_t mNumSignals; 85 std::array<SynthSound, kMaxTracks> mOscs; 86 Mixer mMixer; 87 MonoToStereo mConverter = MonoToStereo(&mMixer); 88 IRenderableAudio *mOutputStage; // This will point to either the mixer or converter, so it needs to be raw 89 }; 90 91 92 #endif //SOUNDBOARD_SYNTH_H 93