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 mNumSignals = numSignals; 40 mOscs = std::make_unique<SynthSound[]>(numSignals); 41 float curFrequency = kOscBaseFrequency; 42 float curAmplitude = kOscBaseAmplitude; 43 for (int i = 0; i < numSignals; ++i) { 44 mOscs[i].setSampleRate(sampleRate); 45 mOscs[i].setFrequency(curFrequency); 46 curFrequency *= kOscFrequencyMultiplier; 47 mOscs[i].setAmplitude(curAmplitude); 48 curAmplitude *= kOscAmplitudeMultiplier; 49 mMixer.addTrack(&mOscs[i]); 50 } 51 52 if (channelCount == oboe::ChannelCount::Stereo) { 53 mOutputStage = &mConverter; 54 } else { 55 mOutputStage = &mMixer; 56 } 57 } 58 noteOff(int32_t noteIndex)59 void noteOff(int32_t noteIndex) { 60 mOscs[noteIndex].noteOff(); 61 } 62 noteOn(int32_t noteIndex)63 void noteOn(int32_t noteIndex) { 64 mOscs[noteIndex].noteOn(); 65 } 66 tap(bool isOn)67 void tap(bool isOn) override { 68 for (int i = 0; i < mNumSignals; i++) { 69 if (isOn) { 70 mOscs[i].noteOn(); 71 } else { 72 mOscs[i].noteOff(); 73 } 74 } 75 }; 76 77 // From IRenderableAudio renderAudio(float * audioData,int32_t numFrames)78 void renderAudio(float *audioData, int32_t numFrames) override { 79 mOutputStage->renderAudio(audioData, numFrames); 80 }; 81 ~Synth()82 virtual ~Synth() { 83 } 84 private: 85 // Rendering objects 86 int32_t mNumSignals; 87 std::unique_ptr<SynthSound[]> mOscs; 88 Mixer mMixer; 89 MonoToStereo mConverter = MonoToStereo(&mMixer); 90 IRenderableAudio *mOutputStage; // This will point to either the mixer or converter, so it needs to be raw 91 }; 92 93 94 #endif //SOUNDBOARD_SYNTH_H 95