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 #include <android/log.h>
18 
19 //static const char * const TAG = "WaveTableOscillator";
20 
21 #include "WaveTableOscillator.h"
22 #include "SystemParams.h"
23 
24 namespace ndkaudio {
25 
WaveTableOscillator(int numChannels,float * waveTable,int waveTableSize)26 WaveTableOscillator::WaveTableOscillator(int numChannels, float* waveTable,
27                                          int waveTableSize)
28  : PeriodicAudioSource(numChannels),
29    waveTable_(waveTable),
30    waveTableSize_(waveTableSize),
31    fN_(0.0f),
32    srcPhase_(0.0f),
33    prevFillTime_(0)
34 {
35     setWaveTable(waveTable, waveTableSize);
36 }
37 
setWaveTable(float * waveTable,int waveTableSize)38 void WaveTableOscillator::setWaveTable(float* waveTable, int waveTableSize) {
39     waveTable_ = waveTable;
40     waveTableSize_ = waveTableSize - 1;
41 
42     // The frequency that would be played if we took every sample from the table and
43     // played it at the system sample-rate. The "Nominal" frequency
44     fN_ = SystemParams::getSampleRate() / (float) waveTableSize_;
45 }
46 
getData(long time,float * outBuff,int numFrames,int)47 int WaveTableOscillator::getData(long time, float* outBuff, int numFrames,
48                                  int /*outChans*/) {
49     prevFillTime_ = time;
50 
51     // Frequency - main
52     float currentFreq = targetFreq_;
53 
54     float phaseIncr = currentFreq / fN_;
55 
56 //	__android_log_print(ANDROID_LOG_INFO, TAG, "getData() freq:%f, fN_:%f, phs:%f incr:%f", currentFreq, fN_, srcPhase_, phaseIncr);
57 
58     if (numChannels_ == 1) {
59         // calculate wave values
60         for (int dstIndex = 0; dstIndex < numFrames; ++dstIndex) {
61             // 'mod' back into the waveTable
62             if (srcPhase_ >= (float) waveTableSize_) {
63                 srcPhase_ -= (float) waveTableSize_;
64             }
65 
66             // linear-interpolate
67             int srcIndex = (int) srcPhase_;
68             float delta0 = srcPhase_ - srcIndex;
69             float delta1 = 1.0f - delta0;
70             outBuff[dstIndex] = ((waveTable_[srcIndex] * delta1)
71                     + (waveTable_[srcIndex + 1] * delta0)) / 2.0f;
72 
73             srcPhase_ += phaseIncr;
74         }
75     } else if (numChannels_ == 2) {
76         // calculate wave values
77         int dstIndex = 0;
78         for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
79             // 'mod' back into the waveTable
80             if (srcPhase_ >= (float) waveTableSize_) {
81                 srcPhase_ -= (float) waveTableSize_;
82             }
83 
84             // linear-interpolate
85             int srcIndex = (int) srcPhase_;
86             float delta0 = srcPhase_ - srcIndex;
87             float delta1 = 1.0f - delta0;
88             float out = ((waveTable_[srcIndex] * delta1)
89                     + (waveTable_[srcIndex + 1] * delta0)) / 2.0f;
90 
91             outBuff[dstIndex++] = out;
92             outBuff[dstIndex++] = out;
93 
94             srcPhase_ += phaseIncr;
95         }
96     }
97 
98 //	__android_log_print(ANDROID_LOG_INFO, TAG, "    %d samples", numSamples);
99     return numFrames;
100 }
101 
102 } // namespace ndkaudio
103