• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 class SineGenerator
23 {
24 public:
SineGenerator()25     SineGenerator() {}
26     virtual ~SineGenerator() = default;
27 
setup(double frequency,double frameRate)28     void setup(double frequency, double frameRate) {
29         mFrameRate = frameRate;
30         mPhaseIncrement = frequency * M_PI * 2 / frameRate;
31     }
32 
setSweep(double frequencyLow,double frequencyHigh,double seconds)33     void setSweep(double frequencyLow, double frequencyHigh, double seconds) {
34         mSweeping = seconds > 0.0;
35         if (mSweeping) {
36             mPhaseIncrementLow = frequencyLow * M_PI * 2 / mFrameRate;
37             mPhaseIncrementHigh = frequencyHigh * M_PI * 2 / mFrameRate;
38             double numFrames = seconds * mFrameRate;
39             mUpScaler = pow((frequencyHigh / frequencyLow), (1.0 / numFrames));
40             mDownScaler = 1.0 / mUpScaler;
41         }
42     }
43 
next()44     float next() {
45         float value = sinf(mPhase) * mAmplitude;
46         advancePhase();
47         return value;
48     }
49 
render(int16_t * buffer,int32_t channelStride,int32_t numFrames)50     void render(int16_t *buffer, int32_t channelStride, int32_t numFrames) {
51         int sampleIndex = 0;
52         for (int i = 0; i < numFrames; i++) {
53             buffer[sampleIndex] = (int16_t) (INT16_MAX * next());
54             sampleIndex += channelStride;
55         }
56     }
57 
render(float * buffer,int32_t channelStride,int32_t numFrames)58     void render(float *buffer, int32_t channelStride, int32_t numFrames) {
59         int sampleIndex = 0;
60         for (int i = 0; i < numFrames; i++) {
61             buffer[sampleIndex] = next();
62             sampleIndex += channelStride;
63         }
64     }
65 
render(int32_t * buffer,int32_t channelStride,int32_t numFrames)66     void render(int32_t *buffer, int32_t channelStride, int32_t numFrames) {
67         int sampleIndex = 0;
68         for (int i = 0; i < numFrames; i++) {
69             buffer[sampleIndex] = (int32_t) (INT32_MAX * next());
70             sampleIndex += channelStride;
71         }
72     }
73 
render24(uint8_t * buffer,int32_t channelStride,int32_t numFrames)74     void render24(uint8_t *buffer, int32_t channelStride, int32_t numFrames) {
75         int sampleIndex = 0;
76         constexpr int32_t INT24_MAX = (1 << 23) - 1;
77         constexpr int bytesPerSample = getBytesPerSample(AAUDIO_FORMAT_PCM_I24_PACKED);
78         const bool isLittleEndian = isNativeLittleEndian();
79         for (int i = 0; i < numFrames; i++) {
80             int32_t sample = (int32_t) (INT24_MAX * next());
81             uint32_t usample = (uint32_t) sample;
82             if (isLittleEndian) {
83                 buffer[sampleIndex] = usample; // little end first
84                 buffer[sampleIndex + 1] = usample >> 8;
85                 buffer[sampleIndex + 2] = usample >> 16;
86             } else {
87                 buffer[sampleIndex] = usample >> 16; // big end first
88                 buffer[sampleIndex + 1] = usample >> 8;
89                 buffer[sampleIndex + 2] = usample;
90             }
91             sampleIndex += channelStride * bytesPerSample;
92         }
93     }
94 
setAmplitude(double amplitude)95     void setAmplitude(double amplitude) {
96         mAmplitude = amplitude;
97     }
98 
getAmplitude()99     double getAmplitude() const {
100         return mAmplitude;
101     }
102 
103 private:
advancePhase()104     void advancePhase() {
105         mPhase += mPhaseIncrement;
106         if (mPhase > M_PI * 2) {
107             mPhase -= M_PI * 2;
108         }
109         if (mSweeping) {
110             if (mGoingUp) {
111                 mPhaseIncrement *= mUpScaler;
112                 if (mPhaseIncrement > mPhaseIncrementHigh) {
113                     mGoingUp = false;
114                 }
115             } else {
116                 mPhaseIncrement *= mDownScaler;
117                 if (mPhaseIncrement < mPhaseIncrementLow) {
118                     mGoingUp = true;
119                 }
120             }
121         }
122     }
123 
124     double mAmplitude = 0.05;  // unitless scaler
125     double mPhase = 0.0;
126     double mPhaseIncrement = 440 * M_PI * 2 / 48000;
127     double mFrameRate = 48000;
128     double mPhaseIncrementLow;
129     double mPhaseIncrementHigh;
130     double mUpScaler = 1.0;
131     double mDownScaler = 1.0;
132     bool   mGoingUp = false;
133     bool   mSweeping = false;
134 };
135 
136 #endif /* SINE_GENERATOR_H */
137