| /* |
| * 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.duplex; |
| |
| import android.media.AudioDeviceInfo; |
| import android.util.Log; |
| |
| import org.hyphonate.megaaudio.common.BuilderBase; |
| import org.hyphonate.megaaudio.common.StreamBase; |
| import org.hyphonate.megaaudio.player.AudioSource; |
| import org.hyphonate.megaaudio.player.AudioSourceProvider; |
| import org.hyphonate.megaaudio.player.Player; |
| import org.hyphonate.megaaudio.player.PlayerBuilder; |
| import org.hyphonate.megaaudio.recorder.AudioSink; |
| import org.hyphonate.megaaudio.recorder.AudioSinkProvider; |
| import org.hyphonate.megaaudio.recorder.Recorder; |
| import org.hyphonate.megaaudio.recorder.RecorderBuilder; |
| |
| public class DuplexAudioManager { |
| private static final String TAG = DuplexAudioManager.class.getSimpleName(); |
| |
| // Player |
| //TODO - explain these constants |
| private int mNumPlayerChannels = 2; |
| private int mPlayerSampleRate = 48000; |
| private int mNumPlayerBufferFrames; |
| |
| private Player mPlayer; |
| private AudioSourceProvider mSourceProvider; |
| private AudioDeviceInfo mPlayerSelectedDevice; |
| |
| // Recorder |
| private int mNumRecorderChannels = 2; |
| private int mRecorderSampleRate = 48000; |
| private int mNumRecorderBufferFrames; |
| |
| private Recorder mRecorder; |
| private AudioSinkProvider mSinkProvider; |
| private AudioDeviceInfo mRecorderSelectedDevice; |
| private int mInputPreset = Recorder.INPUT_PRESET_NONE; |
| |
| public DuplexAudioManager(AudioSourceProvider sourceProvider, AudioSinkProvider sinkProvider) { |
| mSourceProvider = sourceProvider; |
| mSinkProvider = sinkProvider; |
| } |
| |
| public void setInputPreset(int preset) { mInputPreset = preset; } |
| |
| public int setupStreams(int playerType, int recorderType) { |
| // Recorder |
| if ((recorderType & BuilderBase.TYPE_MASK) != BuilderBase.TYPE_NONE) { |
| try { |
| mRecorder = new RecorderBuilder() |
| .setRecorderType(recorderType) |
| .setAudioSinkProvider(mSinkProvider) |
| .build(); |
| if (mInputPreset != Recorder.INPUT_PRESET_NONE) { |
| mRecorder.setInputPreset(mInputPreset); |
| } |
| mRecorder.setRouteDevice(mRecorderSelectedDevice); |
| int errorCode = mRecorder.setupStream( |
| mNumRecorderChannels, mRecorderSampleRate, mNumRecorderBufferFrames); |
| if (errorCode != StreamBase.OK) { |
| Log.e(TAG, "Recorder setupStream() failed"); |
| return errorCode; |
| } |
| mNumRecorderBufferFrames = mRecorder.getNumBufferFrames(); |
| } catch (RecorderBuilder.BadStateException ex) { |
| Log.e(TAG, "Recorder - BadStateException" + ex); |
| return StreamBase.ERROR_UNSUPPORTED; |
| } |
| } |
| |
| // Player |
| if ((playerType & BuilderBase.TYPE_MASK) != BuilderBase.TYPE_NONE) { |
| try { |
| mNumPlayerBufferFrames = |
| Player.calcMinBufferFrames(mNumPlayerChannels, mPlayerSampleRate); |
| mPlayer = new PlayerBuilder() |
| .setPlayerType(playerType) |
| .setSourceProvider(mSourceProvider) |
| .build(); |
| mPlayer.setRouteDevice(mPlayerSelectedDevice); |
| int errorCode = mPlayer.setupStream( |
| mNumPlayerChannels, mPlayerSampleRate, mNumPlayerBufferFrames); |
| if (errorCode != StreamBase.OK) { |
| Log.e(TAG, "Player - setupStream() failed"); |
| return errorCode; |
| } |
| } catch (PlayerBuilder.BadStateException ex) { |
| Log.e(TAG, "Player - BadStateException" + ex); |
| return StreamBase.ERROR_UNSUPPORTED; |
| } |
| } |
| |
| return StreamBase.OK; |
| } |
| |
| public int start() { |
| int result = StreamBase.OK; |
| if (mRecorder != null && (result = mRecorder.startStream()) != StreamBase.OK) { |
| return result; |
| } |
| |
| if (mPlayer != null && (result = mPlayer.startStream()) != StreamBase.OK) { |
| return result; |
| } |
| |
| return result; |
| } |
| |
| public int stop() { |
| int playerResult = StreamBase.OK; |
| if (mPlayer != null) { |
| int result1 = mPlayer.stopStream(); |
| int result2 = mPlayer.teardownStream(); |
| playerResult = result1 != StreamBase.OK ? result1 : result2; |
| } |
| |
| int recorderResult = StreamBase.OK; |
| if (mRecorder != null) { |
| int result1 = mRecorder.stopStream(); |
| int result2 = mRecorder.teardownStream(); |
| recorderResult = result1 != StreamBase.OK ? result1 : result2; |
| } |
| |
| return playerResult != StreamBase.OK ? playerResult: recorderResult; |
| } |
| |
| public int getNumPlayerBufferFrames() { |
| return mPlayer != null ? mPlayer.getNumBufferFrames() : 0; |
| } |
| |
| public int getNumRecorderBufferFrames() { |
| return mRecorder != null ? mRecorder.getNumBufferFrames() : 0; |
| } |
| } |