1 /*
2 * Copyright 2015 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 // #define LOG_NDEBUG 0
18 #define LOG_TAG "bt_btif_avrcp_audio_track"
19
20 #include "btif_avrcp_audio_track.h"
21
22 #ifndef __INTRODUCED_IN
23 #define __INTRODUCED_IN(x)
24 #endif
25
26 #include <aaudio/AAudio.h>
27 #include <bluetooth/log.h>
28
29 #include <algorithm>
30 #include <cstddef>
31 #include <cstdint>
32 #include <thread>
33
34 using namespace bluetooth;
35
36 typedef struct {
37 AAudioStream* stream;
38 int bitsPerSample;
39 int channelCount;
40 float* buffer;
41 size_t bufferLength;
42 float gain;
43 } BtifAvrcpAudioTrack;
44
45 // Maximum track gain that can be set.
46 constexpr float kMaxTrackGain = 1.0f;
47 // Minimum track gain that can be set.
48 constexpr float kMinTrackGain = 0.0f;
49
50 struct AudioEngine {
51 int trackFreq = 0;
52 int channelCount = 0;
53 std::thread* thread = nullptr;
54 void* trackHandle = nullptr;
55 } s_AudioEngine;
56
57 static void ErrorCallback(AAudioStream* stream, void* userdata, aaudio_result_t error);
58
BtifAvrcpAudioErrorHandle()59 static void BtifAvrcpAudioErrorHandle() {
60 AAudioStreamBuilder* builder;
61 AAudioStream* stream;
62
63 aaudio_result_t result = AAudio_createStreamBuilder(&builder);
64 AAudioStreamBuilder_setSampleRate(builder, s_AudioEngine.trackFreq);
65 AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
66 AAudioStreamBuilder_setChannelCount(builder, s_AudioEngine.channelCount);
67 AAudioStreamBuilder_setSessionId(builder, AAUDIO_SESSION_ID_ALLOCATE);
68 AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
69 AAudioStreamBuilder_setErrorCallback(builder, ErrorCallback, nullptr);
70 result = AAudioStreamBuilder_openStream(builder, &stream);
71 log::assert_that(result == AAUDIO_OK, "assert failed: result == AAUDIO_OK");
72 AAudioStreamBuilder_delete(builder);
73
74 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(s_AudioEngine.trackHandle);
75
76 trackHolder->stream = stream;
77
78 if (trackHolder != nullptr && trackHolder->stream != NULL) {
79 log::debug("AAudio Error handle: restart A2dp Sink AudioTrack");
80 AAudioStream_requestStart(trackHolder->stream);
81 }
82 s_AudioEngine.thread = nullptr;
83 }
84
ErrorCallback(AAudioStream *,void *,aaudio_result_t error)85 static void ErrorCallback(AAudioStream* /* stream */, void* /* userdata */, aaudio_result_t error) {
86 if (error == AAUDIO_ERROR_DISCONNECTED) {
87 if (s_AudioEngine.thread == nullptr) {
88 s_AudioEngine.thread = new std::thread(BtifAvrcpAudioErrorHandle);
89 }
90 }
91 }
92
BtifAvrcpAudioTrackCreate(int trackFreq,int bitsPerSample,int channelCount)93 void* BtifAvrcpAudioTrackCreate(int trackFreq, int bitsPerSample, int channelCount) {
94 log::info("Track.cpp: btCreateTrack freq {} bps {} channel {}", trackFreq, bitsPerSample,
95 channelCount);
96
97 AAudioStreamBuilder* builder;
98 AAudioStream* stream;
99 aaudio_result_t result = AAudio_createStreamBuilder(&builder);
100 AAudioStreamBuilder_setSampleRate(builder, trackFreq);
101 AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
102 AAudioStreamBuilder_setChannelCount(builder, channelCount);
103 AAudioStreamBuilder_setSessionId(builder, AAUDIO_SESSION_ID_ALLOCATE);
104 AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
105 AAudioStreamBuilder_setErrorCallback(builder, ErrorCallback, nullptr);
106 result = AAudioStreamBuilder_openStream(builder, &stream);
107 log::assert_that(result == AAUDIO_OK, "assert failed: result == AAUDIO_OK");
108 AAudioStreamBuilder_delete(builder);
109
110 BtifAvrcpAudioTrack* trackHolder = new BtifAvrcpAudioTrack;
111 log::assert_that(trackHolder != NULL, "assert failed: trackHolder != NULL");
112 trackHolder->stream = stream;
113 trackHolder->bitsPerSample = bitsPerSample;
114 trackHolder->channelCount = channelCount;
115 trackHolder->bufferLength =
116 trackHolder->channelCount * AAudioStream_getBufferSizeInFrames(stream);
117 trackHolder->gain = kMaxTrackGain;
118 trackHolder->buffer = new float[trackHolder->bufferLength]();
119
120 s_AudioEngine.trackFreq = trackFreq;
121 s_AudioEngine.channelCount = channelCount;
122 s_AudioEngine.trackHandle = (void*)trackHolder;
123
124 return (void*)trackHolder;
125 }
126
BtifAvrcpAudioTrackStart(void * handle)127 void BtifAvrcpAudioTrackStart(void* handle) {
128 if (handle == NULL) {
129 log::error("handle is null!");
130 return;
131 }
132 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
133 log::assert_that(trackHolder != NULL, "assert failed: trackHolder != NULL");
134 log::assert_that(trackHolder->stream != NULL, "assert failed: trackHolder->stream != NULL");
135 log::verbose("Track.cpp: btStartTrack");
136 AAudioStream_requestStart(trackHolder->stream);
137 }
138
BtifAvrcpAudioTrackStop(void * handle)139 void BtifAvrcpAudioTrackStop(void* handle) {
140 if (handle == NULL) {
141 log::info("handle is null.");
142 return;
143 }
144 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
145 if (trackHolder != NULL && trackHolder->stream != NULL) {
146 log::verbose("Track.cpp: btStopTrack");
147 AAudioStream_requestStop(trackHolder->stream);
148 }
149 }
150
BtifAvrcpAudioTrackDelete(void * handle)151 void BtifAvrcpAudioTrackDelete(void* handle) {
152 if (handle == NULL) {
153 log::info("handle is null.");
154 return;
155 }
156 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
157 if (trackHolder != NULL && trackHolder->stream != NULL) {
158 log::verbose("Track.cpp: btStartTrack");
159 AAudioStream_close(trackHolder->stream);
160 delete trackHolder->buffer;
161 delete trackHolder;
162 }
163 }
164
BtifAvrcpAudioTrackPause(void * handle)165 void BtifAvrcpAudioTrackPause(void* handle) {
166 if (handle == NULL) {
167 log::info("handle is null.");
168 return;
169 }
170 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
171 if (trackHolder != NULL && trackHolder->stream != NULL) {
172 log::verbose("Track.cpp: btPauseTrack");
173 AAudioStream_requestPause(trackHolder->stream);
174 AAudioStream_requestFlush(trackHolder->stream);
175 }
176 }
177
BtifAvrcpSetAudioTrackGain(void * handle,float gain)178 void BtifAvrcpSetAudioTrackGain(void* handle, float gain) {
179 if (handle == NULL) {
180 log::info("handle is null.");
181 return;
182 }
183 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
184 if (trackHolder != NULL) {
185 const float clampedGain = std::clamp(gain, kMinTrackGain, kMaxTrackGain);
186 if (clampedGain != gain) {
187 log::warn("Out of bounds gain set. Clamping the gain from :{:f} to {:f}", gain, clampedGain);
188 }
189 trackHolder->gain = clampedGain;
190 log::info("Avrcp audio track gain is set to {:f}", trackHolder->gain);
191 }
192 }
193
194 constexpr float kScaleQ15ToFloat = 1.0f / 32768.0f;
195 constexpr float kScaleQ23ToFloat = 1.0f / 8388608.0f;
196 constexpr float kScaleQ31ToFloat = 1.0f / 2147483648.0f;
197
sampleSizeFor(BtifAvrcpAudioTrack * trackHolder)198 static size_t sampleSizeFor(BtifAvrcpAudioTrack* trackHolder) {
199 return trackHolder->bitsPerSample / 8;
200 }
201
transcodeQ15ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)202 static size_t transcodeQ15ToFloat(uint8_t* buffer, size_t length,
203 BtifAvrcpAudioTrack* trackHolder) {
204 size_t sampleSize = sampleSizeFor(trackHolder);
205 size_t i = 0;
206 const float scaledGain = trackHolder->gain * kScaleQ15ToFloat;
207 for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
208 trackHolder->buffer[i] = ((int16_t*)buffer)[i] * scaledGain;
209 }
210 return i * sampleSize;
211 }
212
transcodeQ23ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)213 static size_t transcodeQ23ToFloat(uint8_t* buffer, size_t length,
214 BtifAvrcpAudioTrack* trackHolder) {
215 size_t sampleSize = sampleSizeFor(trackHolder);
216 size_t i = 0;
217 const float scaledGain = trackHolder->gain * kScaleQ23ToFloat;
218 for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
219 size_t offset = i * sampleSize;
220 int32_t sample = *((int32_t*)(buffer + offset - 1)) & 0x00FFFFFF;
221 trackHolder->buffer[i] = sample * scaledGain;
222 }
223 return i * sampleSize;
224 }
225
transcodeQ31ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)226 static size_t transcodeQ31ToFloat(uint8_t* buffer, size_t length,
227 BtifAvrcpAudioTrack* trackHolder) {
228 size_t sampleSize = sampleSizeFor(trackHolder);
229 size_t i = 0;
230 const float scaledGain = trackHolder->gain * kScaleQ31ToFloat;
231 for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
232 trackHolder->buffer[i] = ((int32_t*)buffer)[i] * scaledGain;
233 }
234 return i * sampleSize;
235 }
236
transcodeToPcmFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)237 static size_t transcodeToPcmFloat(uint8_t* buffer, size_t length,
238 BtifAvrcpAudioTrack* trackHolder) {
239 switch (trackHolder->bitsPerSample) {
240 case 16:
241 return transcodeQ15ToFloat(buffer, length, trackHolder);
242 case 24:
243 return transcodeQ23ToFloat(buffer, length, trackHolder);
244 case 32:
245 return transcodeQ31ToFloat(buffer, length, trackHolder);
246 }
247 return -1;
248 }
249
250 constexpr int64_t kTimeoutNanos = 100 * 1000 * 1000; // 100 ms
251
BtifAvrcpAudioTrackWriteData(void * handle,void * audioBuffer,int bufferLength)252 int BtifAvrcpAudioTrackWriteData(void* handle, void* audioBuffer, int bufferLength) {
253 BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
254 log::assert_that(trackHolder != NULL, "assert failed: trackHolder != NULL");
255 log::assert_that(trackHolder->stream != NULL, "assert failed: trackHolder->stream != NULL");
256 aaudio_result_t retval = -1;
257
258 size_t sampleSize = sampleSizeFor(trackHolder);
259 int transcodedCount = 0;
260 do {
261 transcodedCount += transcodeToPcmFloat(((uint8_t*)audioBuffer) + transcodedCount,
262 bufferLength - transcodedCount, trackHolder);
263
264 retval = AAudioStream_write(trackHolder->stream, trackHolder->buffer,
265 transcodedCount / (sampleSize * trackHolder->channelCount),
266 kTimeoutNanos);
267 log::verbose("Track.cpp: btWriteData len = {} ret = {}", bufferLength, retval);
268 } while (transcodedCount < bufferLength);
269
270 return transcodedCount;
271 }
272