blob: 5c1a6817dda1f90f3f778294cc0c20b3799fe1a3 [file] [log] [blame]
Paul McLean073ad282020-01-13 10:32:50 -07001/*
2 * Copyright 2019 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#include <android/log.h>
18
Paul McLean0c8b6832020-03-02 10:36:40 -070019// parselib includes
Paul McLean06a59262020-05-13 11:10:56 -060020#include <stream/MemInputStream.h>
21#include <wav/WavStreamReader.h>
Paul McLean073ad282020-01-13 10:32:50 -070022
Paul McLean8266d262020-03-16 10:24:32 -060023// local includes
24#include "OneShotSampleSource.h"
Paul McLean073ad282020-01-13 10:32:50 -070025#include "SimpleMultiPlayer.h"
26
27static const char* TAG = "SimpleMultiPlayer";
28
Paul McLean8266d262020-03-16 10:24:32 -060029using namespace oboe;
Paul McLean0c8b6832020-03-02 10:36:40 -070030using namespace parselib;
31
32namespace iolib {
Paul McLean073ad282020-01-13 10:32:50 -070033
34constexpr int32_t kBufferSizeInBursts = 2; // Use 2 bursts as the buffer size (double buffer)
35
36SimpleMultiPlayer::SimpleMultiPlayer()
37 : mChannelCount(0), mSampleRate(0), mOutputReset(false)
38{}
39
40DataCallbackResult SimpleMultiPlayer::onAudioReady(AudioStream *oboeStream, void *audioData,
41 int32_t numFrames) {
42
43 StreamState streamState = oboeStream->getState();
44 if (streamState != StreamState::Open && streamState != StreamState::Started) {
45 __android_log_print(ANDROID_LOG_ERROR, TAG, " streamState:%d", streamState);
46 }
47 if (streamState == StreamState::Disconnected) {
48 __android_log_print(ANDROID_LOG_ERROR, TAG, " streamState::Disconnected");
49 }
50
Paul McLean519322a2020-04-16 09:04:31 -060051 memset(audioData, 0, numFrames * mChannelCount * sizeof(float));
Paul McLean073ad282020-01-13 10:32:50 -070052
Paul McLeane35a1762020-04-09 13:59:42 -060053 // OneShotSampleSource* sources = mSampleSources.get();
Paul McLean073ad282020-01-13 10:32:50 -070054 for(int32_t index = 0; index < mNumSampleBuffers; index++) {
Paul McLeane35a1762020-04-09 13:59:42 -060055 if (mSampleSources[index]->isPlaying()) {
Paul McLean519322a2020-04-16 09:04:31 -060056 mSampleSources[index]->mixAudio((float*)audioData, mChannelCount, numFrames);
Paul McLean073ad282020-01-13 10:32:50 -070057 }
58 }
59
60 return DataCallbackResult::Continue;
61}
62
63void SimpleMultiPlayer::onErrorAfterClose(AudioStream *oboeStream, Result error) {
Paul McLean80198012020-01-21 13:29:48 -070064 __android_log_print(ANDROID_LOG_INFO, TAG, "==== onErrorAfterClose() error:%d", error);
Paul McLean073ad282020-01-13 10:32:50 -070065
66 resetAll();
67 openStream();
68 mOutputReset = true;
69}
70
71void SimpleMultiPlayer::onErrorBeforeClose(AudioStream *, Result error) {
Paul McLean80198012020-01-21 13:29:48 -070072 __android_log_print(ANDROID_LOG_INFO, TAG, "==== onErrorBeforeClose() error:%d", error);
Paul McLean073ad282020-01-13 10:32:50 -070073}
74
75bool SimpleMultiPlayer::openStream() {
76 __android_log_print(ANDROID_LOG_INFO, TAG, "openStream()");
77
78 // Create an audio stream
79 AudioStreamBuilder builder;
80 builder.setChannelCount(mChannelCount);
81 builder.setSampleRate(mSampleRate);
82 builder.setCallback(this);
83 builder.setPerformanceMode(PerformanceMode::LowLatency);
84 builder.setSharingMode(SharingMode::Exclusive);
85 builder.setSampleRateConversionQuality(SampleRateConversionQuality::Medium);
86
Paul McLeane35a1762020-04-09 13:59:42 -060087 Result result = builder.openManagedStream(mAudioStream);
Paul McLean073ad282020-01-13 10:32:50 -070088 if (result != Result::OK){
Don Turner2ff4d4c2020-04-08 16:16:02 +010089 __android_log_print(
90 ANDROID_LOG_ERROR,
91 TAG,
92 "openStream failed. Error: %s", convertToText(result));
Paul McLean073ad282020-01-13 10:32:50 -070093 return false;
94 }
95
96 // Reduce stream latency by setting the buffer size to a multiple of the burst size
Don Turner2ff4d4c2020-04-08 16:16:02 +010097 // Note: this will fail with ErrorUnimplemented if we are using a callback with OpenSL ES
98 // See oboe::AudioStreamBuffered::setBufferSizeInFrames
99 result = mAudioStream->setBufferSizeInFrames(
Paul McLean073ad282020-01-13 10:32:50 -0700100 mAudioStream->getFramesPerBurst() * kBufferSizeInBursts);
Don Turner2ff4d4c2020-04-08 16:16:02 +0100101 if (result != Result::OK) {
102 __android_log_print(
103 ANDROID_LOG_WARN,
104 TAG,
105 "setBufferSizeInFrames failed. Error: %s", convertToText(result));
Paul McLean073ad282020-01-13 10:32:50 -0700106 }
107
Don Turner2ff4d4c2020-04-08 16:16:02 +0100108 result = mAudioStream->requestStart();
Paul McLean073ad282020-01-13 10:32:50 -0700109 if (result != Result::OK){
Don Turner2ff4d4c2020-04-08 16:16:02 +0100110 __android_log_print(
111 ANDROID_LOG_ERROR,
112 TAG,
113 "requestStart failed. Error: %s", convertToText(result));
Paul McLean073ad282020-01-13 10:32:50 -0700114 return false;
115 }
116
117 return true;
118}
119
Paul McLeane35a1762020-04-09 13:59:42 -0600120void SimpleMultiPlayer::setupAudioStream(int32_t channelCount, int32_t sampleRate) {
121 __android_log_print(ANDROID_LOG_INFO, TAG, "setupAudioStream()");
Paul McLean073ad282020-01-13 10:32:50 -0700122 mChannelCount = channelCount;
123 mSampleRate = sampleRate;
Paul McLeane35a1762020-04-09 13:59:42 -0600124 mSampleRate = sampleRate;
Paul McLean8266d262020-03-16 10:24:32 -0600125
Paul McLean073ad282020-01-13 10:32:50 -0700126 openStream();
127}
128
129void SimpleMultiPlayer::teardownAudioStream() {
Paul McLeane35a1762020-04-09 13:59:42 -0600130 __android_log_print(ANDROID_LOG_INFO, TAG, "teardownAudioStream()");
Paul McLean073ad282020-01-13 10:32:50 -0700131 // tear down the player
132 if (mAudioStream != nullptr) {
133 mAudioStream->stop();
Paul McLean073ad282020-01-13 10:32:50 -0700134 }
Paul McLeane35a1762020-04-09 13:59:42 -0600135}
Paul McLean073ad282020-01-13 10:32:50 -0700136
Paul McLeanb2cf2322020-04-20 13:36:51 -0600137void SimpleMultiPlayer::addSampleSource(SampleSource* source, SampleBuffer* buffer) {
Paul McLean519322a2020-04-16 09:04:31 -0600138 mSampleBuffers.push_back(buffer);
139 mSampleSources.push_back(source);
140 mNumSampleBuffers++;
Paul McLean073ad282020-01-13 10:32:50 -0700141}
142
143void SimpleMultiPlayer::unloadSampleData() {
Paul McLeane35a1762020-04-09 13:59:42 -0600144 __android_log_print(ANDROID_LOG_INFO, TAG, "unloadSampleData()");
Paul McLean1ca821b2020-04-28 09:35:15 -0600145 resetAll();
146
Paul McLean073ad282020-01-13 10:32:50 -0700147 for (int32_t bufferIndex = 0; bufferIndex < mNumSampleBuffers; bufferIndex++) {
Paul McLeane35a1762020-04-09 13:59:42 -0600148 delete mSampleBuffers[bufferIndex];
149 delete mSampleSources[bufferIndex];
Paul McLean073ad282020-01-13 10:32:50 -0700150 }
Paul McLean0c8b6832020-03-02 10:36:40 -0700151
Paul McLeaned4f54a2020-04-13 08:59:44 -0600152 mSampleBuffers.clear();
Paul McLeane35a1762020-04-09 13:59:42 -0600153 mSampleSources.clear();
154
Paul McLean073ad282020-01-13 10:32:50 -0700155 mNumSampleBuffers = 0;
156}
157
158void SimpleMultiPlayer::triggerDown(int32_t index) {
159 if (index < mNumSampleBuffers) {
Paul McLeane35a1762020-04-09 13:59:42 -0600160 mSampleSources[index]->setPlayMode();
Paul McLean073ad282020-01-13 10:32:50 -0700161 }
162}
163
164void SimpleMultiPlayer::triggerUp(int32_t index) {
165 if (index < mNumSampleBuffers) {
Paul McLeane35a1762020-04-09 13:59:42 -0600166 mSampleSources[index]->setStopMode();
Paul McLean073ad282020-01-13 10:32:50 -0700167 }
168}
169
170void SimpleMultiPlayer::resetAll() {
171 for (int32_t bufferIndex = 0; bufferIndex < mNumSampleBuffers; bufferIndex++) {
Paul McLeane35a1762020-04-09 13:59:42 -0600172 mSampleSources[bufferIndex]->setStopMode();
Paul McLean073ad282020-01-13 10:32:50 -0700173 }
174}
Paul McLean0c8b6832020-03-02 10:36:40 -0700175
Paul McLeanb2cf2322020-04-20 13:36:51 -0600176void SimpleMultiPlayer::setPan(int index, float pan) {
177 mSampleSources[index]->setPan(pan);
178}
179
180float SimpleMultiPlayer::getPan(int index) {
181 return mSampleSources[index]->getPan();
182}
183
184void SimpleMultiPlayer::setGain(int index, float gain) {
185 mSampleSources[index]->setGain(gain);
186}
187
188float SimpleMultiPlayer::getGain(int index) {
189 return mSampleSources[index]->getGain();
190}
191
Paul McLean0c8b6832020-03-02 10:36:40 -0700192}