blob: 30c38a4ecd66b1d545578f9bc13a5975859ea90e [file] [log] [blame]
Paul McLean4dd3a512020-12-07 17:21:52 +00001/*
2 * Copyright 2020 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#include <math.h>
17
18#include "WaveTableSource.h"
19
20/**
21 * Constructor. Sets up to play samples from the provided wave table.
22 * @param waveTbl Contains the samples defining a single cycle of the desired waveform.
23 */
24WaveTableSource::WaveTableSource() {
25 reset();
26}
27
28/**
29 * Calculates the "Nominal" frequency of the wave table.
30 */
31void WaveTableSource::calcFN() {
32 mFN = mSampleRate / (float)mNumWaveTableSamples;
33 mFNInverse = 1.0f / mFN;
34}
35
36int WaveTableSource::getNumChannels() {
37 return NUMCHANNELS_UNSPECIFIED;
38}
39
40int WaveTableSource::getEncoding() {
41 return ENCODING_FLOAT;
42}
43
44/**
45 * Fills the specified buffer with values generated from the wave table which will playback
46 * at the specified frequency.
47 *
48 * @param buffer The buffer to be filled.
49 * @param numFrames The number of frames of audio to provide.
50 * @param numChans The number of channels (in the buffer) required by the player.
51 * @return The number of samples generated. Since we are generating a continuous periodic
52 * signal, this will always be <code>numFrames</code>.
53 */
54int WaveTableSource::pull(float* buffer, int numFrames, int numChans) {
55 float phaseIncr = mFreq * mFNInverse;
56 int outIndex = 0;
57 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
58 // 'mod' back into the waveTable
59 while (mSrcPhase >= (float)mNumWaveTableSamples) {
60 mSrcPhase -= (float)mNumWaveTableSamples;
61 }
62
63 // linear-interpolate
64 int srcIndex = (int)mSrcPhase;
65 float delta = mSrcPhase - (float)srcIndex;
66 float s0 = mWaveTable[srcIndex];
67 float s1 = mWaveTable[srcIndex + 1];
68 float value = s0 + ((s1 - s0) * delta);
69
70 // Put the same value in all channels.
71 for (int chanIndex = 0; chanIndex < numChans; chanIndex++) {
72 buffer[outIndex++] = value;
73 }
74
75 mSrcPhase += phaseIncr;
76 }
77
78 return numFrames;
79}
80
81/*
82 * Standard wavetable generators
83 */
84void WaveTableSource::genSinWave(float* buffer, int length) {
85 float incr = ((float)M_PI * 2.0f) / (float)(length - 1);
86 for(int index = 0; index < length; index++) {
87 buffer[index] = sinf(index * incr);
88 }
89}