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