xref: /aosp_15_r20/external/oboe/samples/SoundBoard/src/main/cpp/Synth.h (revision 05767d913155b055644481607e6fa1e35e2fe72c)
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