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 private ArrayList<BufferCallback> mCallbacks = new ArrayList<BufferCallback>(); 32 Player(AudioSourceProvider sourceProvider)33 public Player(AudioSourceProvider sourceProvider) { 34 mSourceProvider = sourceProvider; 35 } 36 37 /* 38 * Audio Source 39 */ 40 protected AudioSourceProvider mSourceProvider; 41 42 // 43 // Attributes 44 // 45 // This needs to be static because it is called before creating the Recorder subclass calcMinBufferFrames(int channelCount, int sampleRate)46 public static int calcMinBufferFrames(int channelCount, int sampleRate) { 47 int channelMask = Player.channelCountToChannelMask(channelCount); 48 int bufferSizeInBytes = 49 AudioTrack.getMinBufferSize (sampleRate, 50 channelMask, 51 AudioFormat.ENCODING_PCM_FLOAT); 52 return bufferSizeInBytes / sampleSizeInBytes(AudioFormat.ENCODING_PCM_FLOAT); 53 } 54 55 /** 56 * @return The AudioSouce object associated with this player 57 */ getAudioSource()58 public abstract AudioSource getAudioSource(); 59 60 // 61 // Status 62 // isPlaying()63 public abstract boolean isPlaying(); 64 65 /* 66 * Channel utils 67 */ 68 // TODO Consider moving these to a "Utility" library. 69 /** 70 * @param channelCount The number of channels for which to generate an output position mask. 71 * @return An output channel-position mask corresponding to the supplied number of channels. 72 */ channelCountToChannelMask(int channelCount)73 public static int channelCountToChannelMask(int channelCount) { 74 switch (channelCount) { 75 case 1: 76 return AudioFormat.CHANNEL_OUT_MONO; 77 78 case 2: 79 return AudioFormat.CHANNEL_OUT_STEREO; 80 81 case 3: 82 return AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_FRONT_CENTER; 83 84 case 4: 85 return AudioFormat.CHANNEL_OUT_QUAD; 86 87 case 5: // 5.0 88 return AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER; 89 90 case 6: // 5.1 91 return AudioFormat.CHANNEL_OUT_5POINT1; 92 93 case 7: // 6.1 94 return AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER; 95 96 case 8: 97 return AudioFormat.CHANNEL_OUT_7POINT1; 98 99 default: 100 return AudioTrack.ERROR_BAD_VALUE; 101 } 102 } 103 104 // 105 // TimeStamp 106 // 107 /** 108 * Gets a timestamp from the audio stream 109 * @param timestamp 110 * @return 111 */ getTimestamp(AudioTimestamp timestamp)112 public abstract boolean getTimestamp(AudioTimestamp timestamp); 113 114 // 115 // BufferCallback Stuff 116 // 117 118 /** 119 * Defines an interface for buffer callback objects 120 */ 121 public interface BufferCallback { 122 /** 123 * Called when player executes a pull() on the associated AudioSource 124 */ onPull()125 void onPull(); 126 } 127 128 /** 129 * Adds a callback object 130 * @param callback 131 */ addBufferCallback(BufferCallback callback)132 public void addBufferCallback(BufferCallback callback) { 133 mCallbacks.add(callback); 134 } 135 136 /** 137 * Removes a previously added callback object 138 * @param callback 139 */ removeBufferCallback(BufferCallback callback)140 public void removeBufferCallback(BufferCallback callback) { 141 mCallbacks.remove(callback); 142 } 143 144 /** 145 * Iterates through callback objects and calls their onPull() method. 146 */ onPull()147 public void onPull() { 148 for (BufferCallback callback : mCallbacks) { 149 callback.onPull(); 150 } 151 } 152 } 153