1 /*
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 package org.hyphonate.megaaudio.player;
17 
18 import android.media.AudioFormat;
19 import android.media.AudioTimestamp;
20 import android.media.AudioTrack;
21 
22 import org.hyphonate.megaaudio.common.StreamBase;
23 
24 import java.util.ArrayList;
25 
26 /**
27  * An abstract class defining the common operations and attributes for all
28  * player (concrete) sub-classes.
29  */
30 public abstract class Player extends StreamBase {
31     @SuppressWarnings("unused")
32     private static final String TAG = Player.class.getSimpleName();
33     @SuppressWarnings("unused")
34     private static final boolean LOG = false;
35 
36     private ArrayList<BufferCallback> mCallbacks = new ArrayList<BufferCallback>();
37 
Player(AudioSourceProvider sourceProvider)38     public Player(AudioSourceProvider sourceProvider) {
39         mSourceProvider = sourceProvider;
40     }
41 
42     /*
43      * Audio Source
44      */
45     /**
46      * The AudioSource object providing audio data to play.
47      */
48     protected AudioSource mAudioSource;
49 
50     protected AudioSourceProvider mSourceProvider;
51 
52     /** <code>true</code> if currently playing audio data */
53     protected boolean mPlaying;
54 
55     /**
56      * @return The AudioSource object providing audio for this Player.
57      */
getAudioSource()58     public AudioSource getAudioSource() {
59         return mAudioSource;
60     }
61 
62     //
63     // Status
64     //
isPlaying()65     public boolean isPlaying() {
66         return mPlaying;
67     }
68 
69     /*
70      * Channel utils
71      */
72     // TODO Consider moving these to a "Utility" library.
73     /**
74      * @param channelCount  The number of channels for which to generate an output position mask.
75      * @return An output channel-position mask corresponding to the supplied number of channels.
76      */
channelCountToChannelMask(int channelCount)77     public static int channelCountToChannelMask(int channelCount) {
78         switch (channelCount) {
79             case 1:
80                 return AudioFormat.CHANNEL_OUT_MONO;
81 
82             case 2:
83                 return AudioFormat.CHANNEL_OUT_STEREO;
84 
85             case 3:
86                 return AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
87 
88             case 4:
89                 return AudioFormat.CHANNEL_OUT_QUAD;
90 
91             case 5: // 5.0
92                 return AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
93 
94             case 6: // 5.1
95                 return AudioFormat.CHANNEL_OUT_5POINT1;
96 
97             case 7: // 6.1
98                 return AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER;
99 
100             case 8:
101                 return AudioFormat.CHANNEL_OUT_7POINT1;
102 
103             default:
104                 return AudioTrack.ERROR_BAD_VALUE;
105         }
106     }
107 
108     //
109     // TimeStamp
110     //
111     /**
112      * Gets a timestamp from the audio stream
113      * @param timestamp
114      * @return
115      */
getTimestamp(AudioTimestamp timestamp)116     public abstract boolean getTimestamp(AudioTimestamp timestamp);
117 
118     //
119     // BufferCallback Stuff
120     //
121     /**
122      * Defines an interface for buffer callback objects
123      */
124     public interface BufferCallback {
125         /**
126          * Called when player executes a pull() on the associated AudioSource
127          */
onPull()128         void onPull();
129     }
130 
131     /**
132      * Adds a callback object
133      * @param callback
134      */
addBufferCallback(BufferCallback callback)135     public void addBufferCallback(BufferCallback callback) {
136         mCallbacks.add(callback);
137     }
138 
139     /**
140      * Removes a previously added callback object
141      * @param callback
142      */
removeBufferCallback(BufferCallback callback)143     public void removeBufferCallback(BufferCallback callback) {
144         mCallbacks.remove(callback);
145     }
146 
147     /**
148      * Iterates through callback objects and calls their onPull() method.
149      */
onPull()150     public void onPull() {
151         for (BufferCallback callback : mCallbacks) {
152             callback.onPull();
153         }
154     }
155 }
156