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_SIMPLE_VOICE_H 18 #define SYNTHMARK_SIMPLE_VOICE_H 19 20 #include <cstdint> 21 #include <math.h> 22 #include "SynthTools.h" 23 #include "VoiceBase.h" 24 #include "SawtoothOscillator.h" 25 #include "SawtoothOscillatorDPW.h" 26 #include "SquareOscillatorDPW.h" 27 #include "SineOscillator.h" 28 #include "EnvelopeADSR.h" 29 #include "PitchToFrequency.h" 30 #include "BiquadFilter.h" 31 32 namespace marksynth { 33 /** 34 * Classic subtractive synthesizer voice with 35 * 2 LFOs, 2 audio oscillators, filter and envelopes. 36 */ 37 class SimpleVoice : public VoiceBase 38 { 39 public: SimpleVoice()40 SimpleVoice() 41 : VoiceBase() 42 , mLfo1() 43 , mOsc1() 44 , mOsc2() 45 , mPitchToFrequency() 46 , mFilter() 47 , mFilterEnvelope() 48 , mAmplitudeEnvelope() 49 // The following values are arbitrary but typical values. 50 , mDetune(1.0001f) // slight phasing 51 , mVibratoDepth(0.03f) 52 , mVibratoRate(6.0f) 53 , mFilterEnvDepth(3000.0f) 54 , mFilterCutoff(400.0f) 55 { 56 mFilter.setQ(2.0); 57 // Randomize attack times to smooth out CPU load for envelope state transitions. 58 mFilterEnvelope.setAttackTime(0.05 + (0.2 * SynthTools::nextRandomDouble())); 59 mFilterEnvelope.setDecayTime(7.0 + (1.0 * SynthTools::nextRandomDouble())); 60 mAmplitudeEnvelope.setAttackTime(0.02 + (0.05 * SynthTools::nextRandomDouble())); 61 mAmplitudeEnvelope.setDecayTime(1.0 + (0.2 * SynthTools::nextRandomDouble())); 62 } 63 64 virtual ~SimpleVoice() = default; 65 setPitch(synth_float_t pitch)66 void setPitch(synth_float_t pitch) { 67 mPitch = pitch; 68 } 69 noteOn(synth_float_t pitch,synth_float_t velocity)70 void noteOn(synth_float_t pitch, synth_float_t velocity) { 71 (void) velocity; // TODO use velocity? 72 mPitch = pitch; 73 mFilterEnvelope.setGate(true); 74 mAmplitudeEnvelope.setGate(true); 75 } 76 noteOff()77 void noteOff() { 78 mFilterEnvelope.setGate(false); 79 mAmplitudeEnvelope.setGate(false); 80 } 81 generate(int32_t numFrames)82 void generate(int32_t numFrames) { 83 assert(numFrames <= kSynthmarkFramesPerRender); 84 85 // LFO #1 - vibrato 86 mLfo1.generate(mVibratoRate, numFrames); 87 synth_float_t *pitches = mBuffer1; 88 SynthTools::scaleOffsetBuffer(mLfo1.output, pitches, numFrames, mVibratoDepth, mPitch); 89 synth_float_t *frequencies = mBuffer2; 90 mPitchToFrequency.generate(pitches, frequencies, numFrames); 91 92 // OSC #1 - sawtooth 93 mOsc1.generate(frequencies, numFrames); 94 95 // OSC #2 - detuned square wave oscillator 96 SynthTools::scaleBuffer(frequencies, frequencies, numFrames, mDetune); 97 mOsc2.generate(frequencies, numFrames); 98 99 // Mix the two oscillators 100 synth_float_t *mixed = frequencies; 101 SynthTools::mixBuffers(mOsc1.output, 0.6, mOsc2.output, 0.4, mixed, numFrames); 102 103 // Filter envelope 104 mFilterEnvelope.generate(numFrames); 105 synth_float_t *cutoffFrequencies = pitches; // reuse unneeded buffer 106 SynthTools::scaleOffsetBuffer(mFilterEnvelope.output, cutoffFrequencies, numFrames, 107 mFilterEnvDepth, mFilterCutoff); 108 109 // Biquad resonant low-pass filter 110 mFilter.generate(mixed, cutoffFrequencies, numFrames); 111 112 // Amplitude ADSR 113 mAmplitudeEnvelope.generate(numFrames); 114 SynthTools::multiplyBuffers(mFilter.output, mAmplitudeEnvelope.output, output, numFrames); 115 } 116 117 private: 118 SineOscillator mLfo1; 119 SawtoothOscillatorDPW mOsc1; 120 SquareOscillatorDPW mOsc2; 121 PitchToFrequency mPitchToFrequency; 122 BiquadFilter mFilter; 123 EnvelopeADSR mFilterEnvelope; 124 EnvelopeADSR mAmplitudeEnvelope; 125 126 synth_float_t mDetune; // frequency scaler 127 synth_float_t mVibratoDepth; // in semitones 128 synth_float_t mVibratoRate; // in Hertz 129 synth_float_t mFilterEnvDepth; // in Hertz 130 synth_float_t mFilterCutoff; // in Hertz 131 132 // Buffers for storing signals that are being passed between units. 133 synth_float_t mBuffer1[kSynthmarkFramesPerRender]; 134 synth_float_t mBuffer2[kSynthmarkFramesPerRender]; 135 }; 136 }; 137 #endif // SYNTHMARK_SIMPLE_VOICE_H 138