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