| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| // Generate a sinusoidal signal with optional onset and offset ramps. |
| |
| #include <stdlib.h> |
| #include <math.h> |
| |
| static inline short clipAndRound(float val) { |
| if (val > 32767.0) |
| return 32767; |
| if (val < -32768.0) |
| return -32768; |
| if (val >= 0.0) |
| return static_cast<short>(0.5 + val); |
| return static_cast<short>(val - 0.5); |
| } |
| |
| /* Return a sinusoid of frequency freq Hz and amplitude ampl in output |
| of length numOutput. If ramp > 0.0, taper the ends of the signal |
| with a half-raised-cosine function. It is up to the caller to |
| delete[] output. If this call fails due to unreasonable arguments, |
| numOutput will be zero, and output will be NULL. Note that the |
| duration of the up/down ramps will be within the specified |
| duration. Note that if amplitude is specified outside of the |
| numerical range of int16, the signal will be clipped at +- 32767. */ |
| void generateSinusoid(float freq, float duration, float sampleRate, |
| float amplitude, float ramp, |
| int* numOutput, short** output) { |
| // Sanity check |
| if ((duration < (2.0 * ramp)) || ((freq * 2.0) > sampleRate) || (ramp < 0.0)) { |
| *output = NULL; |
| *numOutput = 0; |
| return; |
| } |
| int numSamples = int(0.5 + (sampleRate * duration)); |
| double arg = M_PI * 2.0 * freq / sampleRate; |
| short* wave = new short[numSamples]; |
| int numRamp = int(0.5 + (sampleRate * ramp)); |
| for (int i = 0; i < numSamples; ++i) { |
| float val = amplitude * sin(arg * i); |
| if (numRamp > 0) { |
| if (i < numRamp) { |
| float gain = (0.5 - (0.5 * cos((0.5 + i) * M_PI / numRamp))); |
| val *= gain; |
| } else { |
| if (i > (numSamples - numRamp - 1)) { |
| float gain = (0.5 - (0.5 * cos((0.5 + (numSamples - i - 1)) |
| * M_PI / numRamp))); |
| val *= gain; |
| } |
| } |
| } |
| wave[i] = clipAndRound(val); |
| } |
| *numOutput = numSamples; |
| *output = wave; |
| } |