• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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 package org.hyphonate.megaaudio.player.sources;
17 
18 /**
19  * An AudioSourceProvider for multi-channel sine waves with control over which
20  * channels have audio data and which channels have silence.
21  */
22 public class SparseChannelAudioSource extends WaveTableSource {
23     /**
24      * The number of SAMPLES in the Sin Wave table.
25      * This is plenty of samples for a clear sine wave.
26      * the + 1 is to avoid special handling of the interpolation on the last sample.
27      */
28     static final int WAVETABLE_LENGTH = 2049;
29 
30     int mChannelsMask;
31 
SparseChannelAudioSource(int mask)32     public SparseChannelAudioSource(int mask) {
33         super();
34         float[] waveTbl = new float[WAVETABLE_LENGTH];
35         WaveTableSource.genSinWave(waveTbl);
36 
37         setWaveTable(waveTbl);
38 
39         mChannelsMask = mask;
40     }
41 
channelNumToMask(int chanNum)42     private int channelNumToMask(int chanNum) {
43         if (chanNum <= 0) {
44             return 0;
45         }
46         return 1 << (chanNum - 1);
47     }
48 
49     @Override
pull(float[] buffer, int numFrames, int numChans)50     public int pull(float[] buffer, int numFrames, int numChans) {
51         final float phaseIncr = mFreq * mFNInverse;
52         int outIndex = 0;
53         for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
54             // 'mod' back into the waveTable
55             while (mSrcPhase >= (float) mNumWaveTblSamples) {
56                 mSrcPhase -= (float) mNumWaveTblSamples;
57             }
58 
59             // linear-interpolate
60             int srcIndex = (int) mSrcPhase;
61             float delta0 = mSrcPhase - (float) srcIndex;
62             float delta1 = 1.0f - delta0;
63             float value = ((mWaveTbl[srcIndex] * delta0) + (mWaveTbl[srcIndex + 1] * delta1));
64 
65             // Put the same value in all channels.
66             // This is inefficient and should be pulled out of this loop
67             for (int chanIndex = 0; chanIndex < numChans; chanIndex++) {
68                 if ((mChannelsMask & (1 << chanIndex)) != 0) {
69                     buffer[outIndex++] = value;
70                 } else {
71                     buffer[outIndex++] = 0.0f;
72                 }
73             }
74 
75             mSrcPhase += phaseIncr;
76         }
77 
78         return numFrames;
79     }
80 
81 }
82