• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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