164b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk/* 264b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * Copyright (C) 2016 The Android Open Source Project 364b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * 464b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * Licensed under the Apache License, Version 2.0 (the "License"); 564b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * you may not use this file except in compliance with the License. 664b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * You may obtain a copy of the License at 764b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * 864b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * http://www.apache.org/licenses/LICENSE-2.0 964b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * 1064b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * Unless required by applicable law or agreed to in writing, software 1164b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * distributed under the License is distributed on an "AS IS" BASIS, 1264b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1364b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * See the License for the specific language governing permissions and 1464b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk * limitations under the License. 1564b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk */ 1664b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 1764b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk#ifndef SINE_GENERATOR_H 1864b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk#define SINE_GENERATOR_H 1964b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 2064b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk#include <math.h> 2164b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 2264b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burkclass SineGenerator 2364b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk{ 2464b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burkpublic: 2564b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk SineGenerator() {} 2664b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk virtual ~SineGenerator() = default; 2764b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 2864b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk void setup(double frequency, double frameRate) { 2964b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mFrameRate = frameRate; 3064b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mPhaseIncrement = frequency * M_PI * 2 / frameRate; 3164b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 3264b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 3364b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk void setSweep(double frequencyLow, double frequencyHigh, double seconds) { 3464b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mPhaseIncrementLow = frequencyLow * M_PI * 2 / mFrameRate; 3564b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mPhaseIncrementHigh = frequencyHigh * M_PI * 2 / mFrameRate; 3664b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 3764b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk double numFrames = seconds * mFrameRate; 3864b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mUpScaler = pow((frequencyHigh / frequencyLow), (1.0 / numFrames)); 3964b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mDownScaler = 1.0 / mUpScaler; 4064b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mGoingUp = true; 4164b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mSweeping = true; 4264b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 4364b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 4464b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk void render(int16_t *buffer, int32_t channelStride, int32_t numFrames) { 4564b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk int sampleIndex = 0; 4664b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk for (int i = 0; i < numFrames; i++) { 4764b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk buffer[sampleIndex] = (int16_t) (32767 * sin(mPhase) * mAmplitude); 4864b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk sampleIndex += channelStride; 4964b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk advancePhase(); 5064b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 5164b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 5264b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk void render(float *buffer, int32_t channelStride, int32_t numFrames) { 5364b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk int sampleIndex = 0; 5464b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk for (int i = 0; i < numFrames; i++) { 5564b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk buffer[sampleIndex] = sin(mPhase) * mAmplitude; 5664b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk sampleIndex += channelStride; 5764b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk advancePhase(); 5864b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 5964b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 6064b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 6164b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burkprivate: 6264b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk void advancePhase() { 6364b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mPhase += mPhaseIncrement; 6464b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk if (mPhase > M_PI * 2) { 6564b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mPhase -= M_PI * 2; 6664b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 6764b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk if (mSweeping) { 6864b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk if (mGoingUp) { 6964b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mPhaseIncrement *= mUpScaler; 7064b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk if (mPhaseIncrement > mPhaseIncrementHigh) { 7164b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mGoingUp = false; 7264b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 7364b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } else { 7464b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mPhaseIncrement *= mDownScaler; 7564b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk if (mPhaseIncrement < mPhaseIncrementLow) { 7664b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk mGoingUp = true; 7764b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 7864b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 7964b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 8064b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk } 8164b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 82e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk double mAmplitude = 0.05; // unitless scaler 8364b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk double mPhase = 0.0; 8464b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk double mPhaseIncrement = 440 * M_PI * 2 / 48000; 8564b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk double mFrameRate = 48000; 8664b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk double mPhaseIncrementLow; 8764b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk double mPhaseIncrementHigh; 8864b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk double mUpScaler = 1.0; 8964b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk double mDownScaler = 1.0; 9064b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk bool mGoingUp = false; 9164b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk bool mSweeping = false; 9264b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk}; 9364b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 9464b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk#endif /* SINE_GENERATOR_H */ 9564b8787dbf65a13f36a9ae4f7c31eed3c5bc5bc3Phil Burk 96