1 /*
2  * Copyright (C) 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 
17 #ifndef _PLAYER_SAMPLESOURCE_
18 #define _PLAYER_SAMPLESOURCE_
19 
20 #include <cstdint>
21 
22 #include "DataSource.h"
23 
24 #include "SampleBuffer.h"
25 
26 namespace iolib {
27 
28 /**
29  * Defines an interface for audio data provided to a player object.
30  * Concrete examples include OneShotSampleBuffer. One could imagine a LoopingSampleBuffer.
31  * Supports stereo position via mPan member.
32  */
33 class SampleSource: public DataSource {
34 public:
35     // Pan position of the audio in a stereo mix
36     // [left:-1.0f] <- [center: 0.0f] -> -[right: 1.0f]
37     static constexpr float PAN_HARDLEFT = -1.0f;
38     static constexpr float PAN_HARDRIGHT = 1.0f;
39     static constexpr float PAN_CENTER = 0.0f;
40 
SampleSource(SampleBuffer * sampleBuffer,float pan)41     SampleSource(SampleBuffer *sampleBuffer, float pan)
42      : mSampleBuffer(sampleBuffer), mCurFrameIndex(0), mIsPlaying(false), mGain(1.0f) {
43         setPan(pan);
44     }
~SampleSource()45     virtual ~SampleSource() {}
46 
setPlayMode()47     void setPlayMode() { mCurFrameIndex = 0; mIsPlaying = true; }
setStopMode()48     void setStopMode() { mIsPlaying = false; mCurFrameIndex = 0; }
49 
isPlaying()50     bool isPlaying() { return mIsPlaying; }
51 
setPan(float pan)52     void setPan(float pan) {
53         if (pan < PAN_HARDLEFT) {
54             mPan = PAN_HARDLEFT;
55         } else if (pan > PAN_HARDRIGHT) {
56             mPan = PAN_HARDRIGHT;
57         } else {
58             mPan = pan;
59         }
60         calcGainFactors();
61     }
62 
getPan()63     float getPan() {
64         return mPan;
65     }
66 
setGain(float gain)67     void setGain(float gain) {
68         mGain = gain;
69         calcGainFactors();
70     }
71 
getGain()72     float getGain() {
73         return mGain;
74     }
75 
76 protected:
77     SampleBuffer    *mSampleBuffer;
78 
79     int32_t mCurFrameIndex;
80 
81     bool mIsPlaying;
82 
83     // Logical pan value
84     float mPan;
85 
86     // precomputed channel gains for pan
87     float mLeftGain;
88     float mRightGain;
89 
90     // Overall gain
91     float mGain;
92 
93 private:
calcGainFactors()94     void calcGainFactors() {
95         // useful panning information: http://www.cs.cmu.edu/~music/icm-online/readings/panlaws/
96         float rightPan = (mPan * 0.5) + 0.5;
97         mRightGain = rightPan * mGain;
98         mLeftGain = (1.0 - rightPan) * mGain;    }
99 };
100 
101 } // namespace wavlib
102 
103 #endif //_PLAYER_SAMPLESOURCE_
104