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