1*b7c941bbSAndroid Build Coastguard Worker /* 2*b7c941bbSAndroid Build Coastguard Worker * Copyright 2020 The Android Open Source Project 3*b7c941bbSAndroid Build Coastguard Worker * 4*b7c941bbSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*b7c941bbSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*b7c941bbSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*b7c941bbSAndroid Build Coastguard Worker * 8*b7c941bbSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*b7c941bbSAndroid Build Coastguard Worker * 10*b7c941bbSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*b7c941bbSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*b7c941bbSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*b7c941bbSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*b7c941bbSAndroid Build Coastguard Worker * limitations under the License. 15*b7c941bbSAndroid Build Coastguard Worker */ 16*b7c941bbSAndroid Build Coastguard Worker 17*b7c941bbSAndroid Build Coastguard Worker #ifndef MEGA_PLAYER_WAVETABLESOURCE_H 18*b7c941bbSAndroid Build Coastguard Worker #define MEGA_PLAYER_WAVETABLESOURCE_H 19*b7c941bbSAndroid Build Coastguard Worker 20*b7c941bbSAndroid Build Coastguard Worker #include <memory> 21*b7c941bbSAndroid Build Coastguard Worker 22*b7c941bbSAndroid Build Coastguard Worker #include "AudioSource.h" 23*b7c941bbSAndroid Build Coastguard Worker 24*b7c941bbSAndroid Build Coastguard Worker class WaveTableSource: public AudioSource { 25*b7c941bbSAndroid Build Coastguard Worker public: 26*b7c941bbSAndroid Build Coastguard Worker /** 27*b7c941bbSAndroid Build Coastguard Worker * Constructor. Sets up to play samples from the provided wave table. 28*b7c941bbSAndroid Build Coastguard Worker * @param waveTbl Contains the samples defining a single cycle of the desired waveform. 29*b7c941bbSAndroid Build Coastguard Worker */ 30*b7c941bbSAndroid Build Coastguard Worker WaveTableSource(); 31*b7c941bbSAndroid Build Coastguard Worker 32*b7c941bbSAndroid Build Coastguard Worker /** 33*b7c941bbSAndroid Build Coastguard Worker * Sets up to play samples from the provided wave table. 34*b7c941bbSAndroid Build Coastguard Worker * @param waveTbl Contains the samples defining a single cycle of the desired waveform. 35*b7c941bbSAndroid Build Coastguard Worker * This wave table contains a redundant sample in the last slot (== first slot) 36*b7c941bbSAndroid Build Coastguard Worker * to make the interpolation calculation simpler, so the logical length of 37*b7c941bbSAndroid Build Coastguard Worker * the wave table is one less than the length of the array. 38*b7c941bbSAndroid Build Coastguard Worker * NOTE: WaveTableSource DOES NOT take ownership of the wave table. The user of WaveTableSource 39*b7c941bbSAndroid Build Coastguard Worker * is responsible for managing the lifetime of othe wave table. 40*b7c941bbSAndroid Build Coastguard Worker */ setWaveTable(float * waveTable,int length)41*b7c941bbSAndroid Build Coastguard Worker void setWaveTable(float* waveTable, int length) { 42*b7c941bbSAndroid Build Coastguard Worker mWaveTable = waveTable; 43*b7c941bbSAndroid Build Coastguard Worker mNumWaveTableSamples = length - 1; 44*b7c941bbSAndroid Build Coastguard Worker 45*b7c941bbSAndroid Build Coastguard Worker calcFN(); 46*b7c941bbSAndroid Build Coastguard Worker } 47*b7c941bbSAndroid Build Coastguard Worker 48*b7c941bbSAndroid Build Coastguard Worker /** 49*b7c941bbSAndroid Build Coastguard Worker * Sets the playback sample rate for which samples will be generated. 50*b7c941bbSAndroid Build Coastguard Worker * @param sampleRate 51*b7c941bbSAndroid Build Coastguard Worker */ 52*b7c941bbSAndroid Build Coastguard Worker void setSampleRate(int sampleRate); 53*b7c941bbSAndroid Build Coastguard Worker 54*b7c941bbSAndroid Build Coastguard Worker /** 55*b7c941bbSAndroid Build Coastguard Worker * Set the frequency of the output signal. 56*b7c941bbSAndroid Build Coastguard Worker * @param freq Signal frequency in Hz. 57*b7c941bbSAndroid Build Coastguard Worker */ setFreq(float freq)58*b7c941bbSAndroid Build Coastguard Worker void setFreq(float freq) { 59*b7c941bbSAndroid Build Coastguard Worker mFreq = freq; 60*b7c941bbSAndroid Build Coastguard Worker } 61*b7c941bbSAndroid Build Coastguard Worker 62*b7c941bbSAndroid Build Coastguard Worker /** 63*b7c941bbSAndroid Build Coastguard Worker * Resets the playback position to the 1st sample. 64*b7c941bbSAndroid Build Coastguard Worker */ reset()65*b7c941bbSAndroid Build Coastguard Worker void reset() override { 66*b7c941bbSAndroid Build Coastguard Worker mSrcPhase = 0.0f; 67*b7c941bbSAndroid Build Coastguard Worker } 68*b7c941bbSAndroid Build Coastguard Worker 69*b7c941bbSAndroid Build Coastguard Worker virtual int getNumChannels() override; 70*b7c941bbSAndroid Build Coastguard Worker 71*b7c941bbSAndroid Build Coastguard Worker virtual int getEncoding() override; 72*b7c941bbSAndroid Build Coastguard Worker 73*b7c941bbSAndroid Build Coastguard Worker /** 74*b7c941bbSAndroid Build Coastguard Worker * Fills the specified buffer with values generated from the wave table which will playback 75*b7c941bbSAndroid Build Coastguard Worker * at the specified frequency. 76*b7c941bbSAndroid Build Coastguard Worker * 77*b7c941bbSAndroid Build Coastguard Worker * @param buffer The buffer to be filled. 78*b7c941bbSAndroid Build Coastguard Worker * @param numFrames The number of frames of audio to provide. 79*b7c941bbSAndroid Build Coastguard Worker * @param numChans The number of channels (in the buffer) required by the player. 80*b7c941bbSAndroid Build Coastguard Worker * @return The number of samples generated. Since we are generating a continuous periodic 81*b7c941bbSAndroid Build Coastguard Worker * signal, this will always be <code>numFrames</code>. 82*b7c941bbSAndroid Build Coastguard Worker */ 83*b7c941bbSAndroid Build Coastguard Worker virtual int pull(float* buffer, int numFrames, int numChans) override; 84*b7c941bbSAndroid Build Coastguard Worker 85*b7c941bbSAndroid Build Coastguard Worker /* 86*b7c941bbSAndroid Build Coastguard Worker * Standard wavetable generators 87*b7c941bbSAndroid Build Coastguard Worker */ 88*b7c941bbSAndroid Build Coastguard Worker static void genSinWave(float* buffer, int length); 89*b7c941bbSAndroid Build Coastguard Worker static void genTriangleWave(float* buffer, int size, float maxValue, float minValue, 90*b7c941bbSAndroid Build Coastguard Worker float dutyCycle); 91*b7c941bbSAndroid Build Coastguard Worker static void genPulseWave(float* buffer, int size,float maxValue, float minValue, 92*b7c941bbSAndroid Build Coastguard Worker float dutyCycle); 93*b7c941bbSAndroid Build Coastguard Worker 94*b7c941bbSAndroid Build Coastguard Worker protected: 95*b7c941bbSAndroid Build Coastguard Worker static const int DEFAULT_WAVETABLE_LENGTH = 2049; 96*b7c941bbSAndroid Build Coastguard Worker 97*b7c941bbSAndroid Build Coastguard Worker /** 98*b7c941bbSAndroid Build Coastguard Worker * Calculates the "Nominal" frequency of the wave table. 99*b7c941bbSAndroid Build Coastguard Worker */ 100*b7c941bbSAndroid Build Coastguard Worker void calcFN(); 101*b7c941bbSAndroid Build Coastguard Worker 102*b7c941bbSAndroid Build Coastguard Worker /** The samples defining one cycle of the waveform to play */ 103*b7c941bbSAndroid Build Coastguard Worker //TODO - make this a shared_ptr 104*b7c941bbSAndroid Build Coastguard Worker float* mWaveTable; 105*b7c941bbSAndroid Build Coastguard Worker 106*b7c941bbSAndroid Build Coastguard Worker /** The number of samples in the wave table. Note that the wave table is presumed to contain 107*b7c941bbSAndroid Build Coastguard Worker * an "extra" sample (a copy of the 1st sample) in order to simplify the interpolation 108*b7c941bbSAndroid Build Coastguard Worker * calculation. Thus, this value will be 1 less than the length of mWaveTable. 109*b7c941bbSAndroid Build Coastguard Worker */ 110*b7c941bbSAndroid Build Coastguard Worker int mNumWaveTableSamples; 111*b7c941bbSAndroid Build Coastguard Worker 112*b7c941bbSAndroid Build Coastguard Worker /** The phase (offset within the wave table) of the next output sample. 113*b7c941bbSAndroid Build Coastguard Worker * Note that this may (will) be a fractional value. Range 0.0 -> mNumWaveTableSamples. 114*b7c941bbSAndroid Build Coastguard Worker */ 115*b7c941bbSAndroid Build Coastguard Worker float mSrcPhase; 116*b7c941bbSAndroid Build Coastguard Worker 117*b7c941bbSAndroid Build Coastguard Worker /** The sample rate at which playback occurs */ 118*b7c941bbSAndroid Build Coastguard Worker float mSampleRate = 48000; // This seems likely, but can be changed 119*b7c941bbSAndroid Build Coastguard Worker 120*b7c941bbSAndroid Build Coastguard Worker /** The frequency of the generated audio signal */ 121*b7c941bbSAndroid Build Coastguard Worker float mFreq = 1000; // Some reasonable default frequency 122*b7c941bbSAndroid Build Coastguard Worker 123*b7c941bbSAndroid Build Coastguard Worker /** The "Nominal" frequency of the wavetable. i.e., the frequency that would be generated if 124*b7c941bbSAndroid Build Coastguard Worker * each sample in the wave table was sent in turn to the output at the specified sample rate. 125*b7c941bbSAndroid Build Coastguard Worker */ 126*b7c941bbSAndroid Build Coastguard Worker float mFN; 127*b7c941bbSAndroid Build Coastguard Worker 128*b7c941bbSAndroid Build Coastguard Worker /** 1 / mFN. Calculated when mFN is set to avoid a division on each call to fill() */ 129*b7c941bbSAndroid Build Coastguard Worker float mFNInverse; 130*b7c941bbSAndroid Build Coastguard Worker }; 131*b7c941bbSAndroid Build Coastguard Worker 132*b7c941bbSAndroid Build Coastguard Worker #endif // MEGA_PLAYER_WAVETABLESOURCE_H 133