blob: 05d4a68d3cb9d2142b129df27dbce0f3c8fb9674 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <android/log.h>
static const char * TAG = "WaveTableOscillator";
#include "WaveTableOscillator.h"
#include "SystemParams.h"
namespace ndkaudio {
WaveTableOscillator::WaveTableOscillator(int numChannels, float* waveTable,
int waveTableSize)
: PeriodicAudioSource(numChannels),
waveTable_(waveTable),
waveTableSize_(waveTableSize),
fN_(0.0f),
srcPhase_(0.0f),
prevFillTime_(0)
{
setWaveTable(waveTable, waveTableSize);
}
void WaveTableOscillator::setWaveTable(float* waveTable, int waveTableSize) {
waveTable_ = waveTable;
waveTableSize_ = waveTableSize - 1;
// The frequency that would be played if we took every sample from the table and
// played it at the system sample-rate. The "Nominal" frequency
fN_ = SystemParams::getSampleRate() / (float) waveTableSize_;
}
int WaveTableOscillator::getData(long time, float* outBuff, int numFrames,
int /*outChans*/) {
prevFillTime_ = time;
// Frequency - main
float currentFreq = targetFreq_;
float phaseIncr = currentFreq / fN_;
// __android_log_print(ANDROID_LOG_INFO, TAG, "getData() freq:%f, fN_:%f, phs:%f incr:%f", currentFreq, fN_, srcPhase_, phaseIncr);
if (numChannels_ == 1) {
// calculate wave values
for (int dstIndex = 0; dstIndex < numFrames; ++dstIndex) {
// 'mod' back into the waveTable
if (srcPhase_ >= (float) waveTableSize_) {
srcPhase_ -= (float) waveTableSize_;
}
// linear-interpolate
int srcIndex = (int) srcPhase_;
float delta0 = srcPhase_ - srcIndex;
float delta1 = 1.0f - delta0;
outBuff[dstIndex] = ((waveTable_[srcIndex] * delta1)
+ (waveTable_[srcIndex + 1] * delta0)) / 2.0f;
srcPhase_ += phaseIncr;
}
} else if (numChannels_ == 2) {
// calculate wave values
int dstIndex = 0;
for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
// 'mod' back into the waveTable
if (srcPhase_ >= (float) waveTableSize_) {
srcPhase_ -= (float) waveTableSize_;
}
// linear-interpolate
int srcIndex = (int) srcPhase_;
float delta0 = srcPhase_ - srcIndex;
float delta1 = 1.0f - delta0;
float out = ((waveTable_[srcIndex] * delta1)
+ (waveTable_[srcIndex + 1] * delta0)) / 2.0f;
outBuff[dstIndex++] = out;
outBuff[dstIndex++] = out;
srcPhase_ += phaseIncr;
}
}
// __android_log_print(ANDROID_LOG_INFO, TAG, " %d samples", numSamples);
return numFrames;
}
} // namespace ndkaudio