| /* |
| * Copyright 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.hyphonate.megaaudio.common; |
| |
| import android.media.AudioDeviceCallback; |
| import android.media.AudioDeviceInfo; |
| import android.media.AudioFormat; |
| |
| public abstract class StreamBase { |
| // |
| // Error Codes |
| // These values must be kept in sync with the equivalent symbols in |
| // megaaudio/common/Streambase.h |
| // |
| public static final int OK = 0; |
| public static final int ERROR_UNKNOWN = -1; |
| public static final int ERROR_UNSUPPORTED = -2; |
| public static final int ERROR_INVALID_STATE = -3; |
| |
| // |
| // Stream attributes |
| // |
| protected int mChannelCount; |
| protected int mSampleRate; |
| |
| // Routing |
| protected AudioDeviceInfo mRouteDevice; |
| |
| // the thread on which the underlying Android AudioTrack/AudioRecord will run |
| protected Thread mStreamThread = null; |
| |
| // |
| // Attributes |
| // |
| public int getChannelCount() { return mChannelCount; } |
| public int getSampleRate() { return mSampleRate; } |
| |
| public abstract int getNumBufferFrames(); |
| |
| // Routing |
| public void setRouteDevice(AudioDeviceInfo routeDevice) { |
| mRouteDevice = routeDevice; |
| } |
| |
| public static final int ROUTED_DEVICE_ID_INVALID = -1; |
| public abstract int getRoutedDeviceId(); |
| |
| // |
| // Sample Format Utils |
| // |
| /** |
| * @param encoding An Android ENCODING_ constant for audio data. |
| * @return The size in BYTES of samples encoded as specified. |
| */ |
| public static int sampleSizeInBytes(int encoding) { |
| switch (encoding) { |
| case AudioFormat.ENCODING_PCM_16BIT: |
| return 2; |
| |
| case AudioFormat.ENCODING_PCM_FLOAT: |
| return 4; |
| |
| default: |
| return 0; |
| } |
| } |
| |
| /** |
| * @param numChannels The number of channels in a FRAME of audio data. |
| * @return The size in BYTES of a FRAME of audio data encoded as specified. |
| */ |
| public static int calcFrameSizeInBytes(int numChannels) { |
| return sampleSizeInBytes(AudioFormat.ENCODING_PCM_FLOAT) * numChannels; |
| } |
| |
| // |
| // State |
| // |
| |
| /** |
| * @param channelCount The number of channels of audio data to be streamed. |
| * @param sampleRate The stream sample rate |
| * @param numFrames The number of frames of audio data in the stream's buffer. |
| * @return ERROR_NONE if successful, otherwise an error code |
| */ |
| public abstract int setupStream(int channelCount, int sampleRate, int numFrames); |
| |
| public abstract int teardownStream(); |
| |
| /** |
| * Starts playback on an open stream player. (@see open() method above). |
| * @return ERROR_NONE if successful, otherwise an error code |
| */ |
| public abstract int startStream(); |
| |
| /** |
| * Stops playback. |
| * May not stop the stream immediately. i.e. does not stop until the next audio callback |
| * from the underlying system. |
| * @return ERROR_NONE if successful, otherwise an error code |
| */ |
| public abstract int stopStream(); |
| |
| // |
| // Thread stuff |
| // |
| /** |
| * Joins the record thread to ensure that the stream is stopped. |
| */ |
| protected void waitForStreamThreadToExit() { |
| try { |
| if (mStreamThread != null) { |
| mStreamThread.join(); |
| mStreamThread = null; |
| } |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| // |
| // Utility |
| // |
| /** |
| * @param chanCount The number of channels for which to generate an index mask. |
| * @return A channel index mask corresponding to the supplied channel count. |
| * |
| * @note The generated index mask has active channels from 0 to chanCount - 1 |
| */ |
| public static int channelCountToIndexMask(int chanCount) { |
| return (1 << chanCount) - 1; |
| } |
| } |