blob: c2c4d4875e5e43843a24cf82568fb58c9f3d1de8 [file] [log] [blame]
/*
* Copyright 2017 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 "SineGenerator.h"
constexpr int kDefaultFrameRate = 48000;
constexpr float kDefaultAmplitude = 0.01;
constexpr float kDefaultFrequency = 440.0;
constexpr double kTwoPi = M_PI * 2;
SineGenerator::SineGenerator() {
setup(kDefaultFrequency, kDefaultFrameRate, kDefaultAmplitude);
}
void SineGenerator::setup(double frequency, int32_t frameRate) {
mFrameRate = frameRate;
mPhaseIncrement = getPhaseIncremement(frequency);
}
void SineGenerator::setup(double frequency, int32_t frameRate, float amplitude) {
setup(frequency, frameRate);
mAmplitude = amplitude;
}
void SineGenerator::setSweep(double frequencyLow, double frequencyHigh, double seconds) {
mPhaseIncrementLow = getPhaseIncremement(frequencyLow);
mPhaseIncrementHigh = getPhaseIncremement(frequencyHigh);
double numFrames = seconds * mFrameRate;
mUpScaler = pow((frequencyHigh / frequencyLow), (1.0 / numFrames));
mDownScaler = 1.0 / mUpScaler;
mGoingUp = true;
mSweeping = true;
}
void SineGenerator::render(int16_t *buffer, int32_t channelStride, int32_t numFrames) {
int sampleIndex = 0;
for (int i = 0; i < numFrames; i++) {
buffer[sampleIndex] = (int16_t) (INT16_MAX * sinf(mPhase) * mAmplitude);
sampleIndex += channelStride;
advancePhase();
}
}
void SineGenerator::render(float *buffer, int32_t channelStride, int32_t numFrames) {
for (int i = 0, sampleIndex = 0; i < numFrames; i++) {
buffer[sampleIndex] = (float) (sinf(mPhase) * mAmplitude);
sampleIndex += channelStride;
advancePhase();
}
}
void SineGenerator::advancePhase() {
mPhase += mPhaseIncrement;
while (mPhase >= kTwoPi) {
mPhase -= kTwoPi;
}
if (mSweeping) {
if (mGoingUp) {
mPhaseIncrement *= mUpScaler;
if (mPhaseIncrement > mPhaseIncrementHigh) {
mGoingUp = false;
}
} else {
mPhaseIncrement *= mDownScaler;
if (mPhaseIncrement < mPhaseIncrementLow) {
mGoingUp = true;
}
}
}
}
double SineGenerator::getPhaseIncremement(double frequency) {
return frequency * kTwoPi / mFrameRate;
}