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      */
52     void setSampleRate(int sampleRate);
53 
54     /**
55      * Set the frequency of the output signal.
56      * @param freq  Signal frequency in Hz.
57      */
setFreq(float freq)58     void setFreq(float freq) {
59         mFreq = freq;
60     }
61 
62     /**
63      * Resets the playback position to the 1st sample.
64      */
reset()65     void reset()  override {
66         mSrcPhase = 0.0f;
67     }
68 
69     virtual int getNumChannels() override;
70 
71     virtual int getEncoding() override;
72 
73     /**
74      * Fills the specified buffer with values generated from the wave table which will playback
75      * at the specified frequency.
76      *
77      * @param buffer The buffer to be filled.
78      * @param numFrames The number of frames of audio to provide.
79      * @param numChans The number of channels (in the buffer) required by the player.
80      * @return  The number of samples generated. Since we are generating a continuous periodic
81      * signal, this will always be <code>numFrames</code>.
82      */
83     virtual int pull(float* buffer, int numFrames, int numChans) override;
84 
85     /*
86      * Standard wavetable generators
87      */
88     static void genSinWave(float* buffer, int length);
89     static void genTriangleWave(float* buffer, int size, float maxValue, float minValue,
90                                            float dutyCycle);
91     static void genPulseWave(float* buffer, int size,float maxValue, float minValue,
92                                             float dutyCycle);
93 
94 protected:
95     static const int DEFAULT_WAVETABLE_LENGTH = 2049;
96 
97     /**
98      * Calculates the "Nominal" frequency of the wave table.
99      */
100     void calcFN();
101 
102     /** The samples defining one cycle of the waveform to play */
103     //TODO - make this a shared_ptr
104     float*  mWaveTable;
105 
106     /** The number of samples in the wave table. Note that the wave table is presumed to contain
107      * an "extra" sample (a copy of the 1st sample) in order to simplify the interpolation
108      * calculation. Thus, this value will be 1 less than the length of mWaveTable.
109      */
110     int mNumWaveTableSamples;
111 
112     /** The phase (offset within the wave table) of the next output sample.
113      *  Note that this may (will) be a fractional value. Range 0.0 -> mNumWaveTableSamples.
114      */
115     float mSrcPhase;
116 
117     /** The sample rate at which playback occurs */
118     float mSampleRate = 48000;  // This seems likely, but can be changed
119 
120     /** The frequency of the generated audio signal */
121     float mFreq = 1000;         // Some reasonable default frequency
122 
123     /** The "Nominal" frequency of the wavetable. i.e., the frequency that would be generated if
124      * each sample in the wave table was sent in turn to the output at the specified sample rate.
125      */
126     float mFN;
127 
128     /** 1 / mFN. Calculated when mFN is set to avoid a division on each call to fill() */
129     float mFNInverse;
130 };
131 
132 #endif // MEGA_PLAYER_WAVETABLESOURCE_H
133