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#ifndef SINE_GENERATOR_H
18#define SINE_GENERATOR_H
19
20#include <math.h>
21
22class SineGenerator
23{
24public:
25    SineGenerator() {}
26    virtual ~SineGenerator() = default;
27
28    void setup(double frequency, double frameRate) {
29        mFrameRate = frameRate;
30        mPhaseIncrement = frequency * M_PI * 2 / frameRate;
31    }
32
33    void setSweep(double frequencyLow, double frequencyHigh, double seconds) {
34        mPhaseIncrementLow = frequencyLow * M_PI * 2 / mFrameRate;
35        mPhaseIncrementHigh = frequencyHigh * M_PI * 2 / mFrameRate;
36
37        double numFrames = seconds * mFrameRate;
38        mUpScaler = pow((frequencyHigh / frequencyLow), (1.0 / numFrames));
39        mDownScaler = 1.0 / mUpScaler;
40        mGoingUp = true;
41        mSweeping = true;
42    }
43
44    void render(int16_t *buffer, int32_t channelStride, int32_t numFrames) {
45        int sampleIndex = 0;
46        for (int i = 0; i < numFrames; i++) {
47            buffer[sampleIndex] = (int16_t) (32767 * sin(mPhase) * mAmplitude);
48            sampleIndex += channelStride;
49            advancePhase();
50        }
51    }
52    void render(float *buffer, int32_t channelStride, int32_t numFrames) {
53        int sampleIndex = 0;
54        for (int i = 0; i < numFrames; i++) {
55            buffer[sampleIndex] = sin(mPhase) * mAmplitude;
56            sampleIndex += channelStride;
57            advancePhase();
58        }
59    }
60
61private:
62    void advancePhase() {
63        mPhase += mPhaseIncrement;
64        if (mPhase > M_PI * 2) {
65            mPhase -= M_PI * 2;
66        }
67        if (mSweeping) {
68            if (mGoingUp) {
69                mPhaseIncrement *= mUpScaler;
70                if (mPhaseIncrement > mPhaseIncrementHigh) {
71                    mGoingUp = false;
72                }
73            } else {
74                mPhaseIncrement *= mDownScaler;
75                if (mPhaseIncrement < mPhaseIncrementLow) {
76                    mGoingUp = true;
77                }
78            }
79        }
80    }
81
82    double mAmplitude = 0.05;  // unitless scaler
83    double mPhase = 0.0;
84    double mPhaseIncrement = 440 * M_PI * 2 / 48000;
85    double mFrameRate = 48000;
86    double mPhaseIncrementLow;
87    double mPhaseIncrementHigh;
88    double mUpScaler = 1.0;
89    double mDownScaler = 1.0;
90    bool   mGoingUp = false;
91    bool   mSweeping = false;
92};
93
94#endif /* SINE_GENERATOR_H */
95
96