1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 // Generate a sinusoidal signal with optional onset and offset ramps. 18 19 #include <stdlib.h> 20 #include <math.h> 21 22 static inline short clipAndRound(float val) { 23 if (val > 32767.0) 24 return 32767; 25 if (val < -32768.0) 26 return -32768; 27 if (val >= 0.0) 28 return static_cast<short>(0.5 + val); 29 return static_cast<short>(val - 0.5); 30 } 31 32 /* Return a sinusoid of frequency freq Hz and amplitude ampl in output 33 of length numOutput. If ramp > 0.0, taper the ends of the signal 34 with a half-raised-cosine function. It is up to the caller to 35 delete[] output. If this call fails due to unreasonable arguments, 36 numOutput will be zero, and output will be NULL. Note that the 37 duration of the up/down ramps will be within the specified 38 duration. Note that if amplitude is specified outside of the 39 numerical range of int16, the signal will be clipped at +- 32767. */ 40 void generateSinusoid(float freq, float duration, float sampleRate, 41 float amplitude, float ramp, 42 int* numOutput, short** output) { 43 // Sanity check 44 if ((duration < (2.0 * ramp)) || ((freq * 2.0) > sampleRate) || (ramp < 0.0)) { 45 *output = NULL; 46 *numOutput = 0; 47 return; 48 } 49 int numSamples = int(0.5 + (sampleRate * duration)); 50 double arg = M_PI * 2.0 * freq / sampleRate; 51 short* wave = new short[numSamples]; 52 int numRamp = int(0.5 + (sampleRate * ramp)); 53 for (int i = 0; i < numSamples; ++i) { 54 float val = amplitude * sin(arg * i); 55 if (numRamp > 0) { 56 if (i < numRamp) { 57 float gain = (0.5 - (0.5 * cos((0.5 + i) * M_PI / numRamp))); 58 val *= gain; 59 } else { 60 if (i > (numSamples - numRamp - 1)) { 61 float gain = (0.5 - (0.5 * cos((0.5 + (numSamples - i - 1)) 62 * M_PI / numRamp))); 63 val *= gain; 64 } 65 } 66 } 67 wave[i] = clipAndRound(val); 68 } 69 *numOutput = numSamples; 70 *output = wave; 71 } 72