• 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 #include <aaudio/AAudio.h>
23 #include <base/logging.h>
24 #include <utils/StrongPointer.h>
25 
26 #include <algorithm>
27 
28 #include "bt_target.h"
29 #include "osi/include/log.h"
30 
31 using namespace android;
32 
33 typedef struct {
34   AAudioStream* stream;
35   int bitsPerSample;
36   int channelCount;
37   float* buffer;
38   size_t bufferLength;
39   float gain;
40 } BtifAvrcpAudioTrack;
41 
42 #if (DUMP_PCM_DATA == TRUE)
43 FILE* outputPcmSampleFile;
44 char outputFilename[50] = "/data/misc/bluedroid/output_sample.pcm";
45 #endif
46 
47 // Maximum track gain that can be set.
48 constexpr float kMaxTrackGain = 1.0f;
49 // Minimum track gain that can be set.
50 constexpr float kMinTrackGain = 0.0f;
51 
BtifAvrcpAudioTrackCreate(int trackFreq,int bitsPerSample,int channelCount)52 void* BtifAvrcpAudioTrackCreate(int trackFreq, int bitsPerSample,
53                                 int channelCount) {
54   LOG_VERBOSE("%s Track.cpp: btCreateTrack freq %d bps %d channel %d ",
55               __func__, trackFreq, bitsPerSample, channelCount);
56 
57   AAudioStreamBuilder* builder;
58   AAudioStream* stream;
59   aaudio_result_t result = AAudio_createStreamBuilder(&builder);
60   AAudioStreamBuilder_setSampleRate(builder, trackFreq);
61   AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
62   AAudioStreamBuilder_setChannelCount(builder, channelCount);
63   AAudioStreamBuilder_setSessionId(builder, AAUDIO_SESSION_ID_ALLOCATE);
64   AAudioStreamBuilder_setPerformanceMode(builder,
65                                          AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
66   result = AAudioStreamBuilder_openStream(builder, &stream);
67   CHECK(result == AAUDIO_OK);
68   AAudioStreamBuilder_delete(builder);
69 
70   BtifAvrcpAudioTrack* trackHolder = new BtifAvrcpAudioTrack;
71   CHECK(trackHolder != NULL);
72   trackHolder->stream = stream;
73   trackHolder->bitsPerSample = bitsPerSample;
74   trackHolder->channelCount = channelCount;
75   trackHolder->bufferLength =
76       trackHolder->channelCount * AAudioStream_getBufferSizeInFrames(stream);
77   trackHolder->gain = kMaxTrackGain;
78   trackHolder->buffer = new float[trackHolder->bufferLength]();
79 
80 #if (DUMP_PCM_DATA == TRUE)
81   outputPcmSampleFile = fopen(outputFilename, "ab");
82 #endif
83   return (void*)trackHolder;
84 }
85 
BtifAvrcpAudioTrackStart(void * handle)86 void BtifAvrcpAudioTrackStart(void* handle) {
87   if (handle == NULL) {
88     LOG_ERROR("%s: handle is null!", __func__);
89     return;
90   }
91   BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
92   CHECK(trackHolder != NULL);
93   CHECK(trackHolder->stream != NULL);
94   LOG_VERBOSE("%s Track.cpp: btStartTrack", __func__);
95   AAudioStream_requestStart(trackHolder->stream);
96 }
97 
BtifAvrcpAudioTrackStop(void * handle)98 void BtifAvrcpAudioTrackStop(void* handle) {
99   if (handle == NULL) {
100     LOG_INFO("%s handle is null.", __func__);
101     return;
102   }
103   BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
104   if (trackHolder != NULL && trackHolder->stream != NULL) {
105     LOG_VERBOSE("%s Track.cpp: btStartTrack", __func__);
106     AAudioStream_requestStop(trackHolder->stream);
107   }
108 }
109 
BtifAvrcpAudioTrackDelete(void * handle)110 void BtifAvrcpAudioTrackDelete(void* handle) {
111   if (handle == NULL) {
112     LOG_INFO("%s handle is null.", __func__);
113     return;
114   }
115   BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
116   if (trackHolder != NULL && trackHolder->stream != NULL) {
117     LOG_VERBOSE("%s Track.cpp: btStartTrack", __func__);
118     AAudioStream_close(trackHolder->stream);
119     delete trackHolder->buffer;
120     delete trackHolder;
121   }
122 
123 #if (DUMP_PCM_DATA == TRUE)
124   if (outputPcmSampleFile) {
125     fclose(outputPcmSampleFile);
126   }
127   outputPcmSampleFile = NULL;
128 #endif
129 }
130 
BtifAvrcpAudioTrackPause(void * handle)131 void BtifAvrcpAudioTrackPause(void* handle) {
132   if (handle == NULL) {
133     LOG_INFO("%s handle is null.", __func__);
134     return;
135   }
136   BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
137   if (trackHolder != NULL && trackHolder->stream != NULL) {
138     LOG_VERBOSE("%s Track.cpp: btPauseTrack", __func__);
139     AAudioStream_requestPause(trackHolder->stream);
140     AAudioStream_requestFlush(trackHolder->stream);
141   }
142 }
143 
BtifAvrcpSetAudioTrackGain(void * handle,float gain)144 void BtifAvrcpSetAudioTrackGain(void* handle, float gain) {
145   if (handle == NULL) {
146     LOG_INFO("%s handle is null.", __func__);
147     return;
148   }
149   BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
150   if (trackHolder != NULL) {
151     const float clampedGain = std::clamp(gain, kMinTrackGain, kMaxTrackGain);
152     if (clampedGain != gain) {
153       LOG_WARN("Out of bounds gain set. Clamping the gain from :%f to %f", gain,
154                clampedGain);
155     }
156     trackHolder->gain = clampedGain;
157     LOG_INFO("Avrcp audio track gain is set to %f", trackHolder->gain);
158   }
159 }
160 
161 constexpr float kScaleQ15ToFloat = 1.0f / 32768.0f;
162 constexpr float kScaleQ23ToFloat = 1.0f / 8388608.0f;
163 constexpr float kScaleQ31ToFloat = 1.0f / 2147483648.0f;
164 
sampleSizeFor(BtifAvrcpAudioTrack * trackHolder)165 static size_t sampleSizeFor(BtifAvrcpAudioTrack* trackHolder) {
166   return trackHolder->bitsPerSample / 8;
167 }
168 
transcodeQ15ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)169 static size_t transcodeQ15ToFloat(uint8_t* buffer, size_t length,
170                                   BtifAvrcpAudioTrack* trackHolder) {
171   size_t sampleSize = sampleSizeFor(trackHolder);
172   size_t i = 0;
173   const float scaledGain = trackHolder->gain * kScaleQ15ToFloat;
174   for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
175     trackHolder->buffer[i] = ((int16_t*)buffer)[i] * scaledGain;
176   }
177   return i * sampleSize;
178 }
179 
transcodeQ23ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)180 static size_t transcodeQ23ToFloat(uint8_t* buffer, size_t length,
181                                   BtifAvrcpAudioTrack* trackHolder) {
182   size_t sampleSize = sampleSizeFor(trackHolder);
183   size_t i = 0;
184   const float scaledGain = trackHolder->gain * kScaleQ23ToFloat;
185   for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
186     size_t offset = i * sampleSize;
187     int32_t sample = *((int32_t*)(buffer + offset - 1)) & 0x00FFFFFF;
188     trackHolder->buffer[i] = sample * scaledGain;
189   }
190   return i * sampleSize;
191 }
192 
transcodeQ31ToFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)193 static size_t transcodeQ31ToFloat(uint8_t* buffer, size_t length,
194                                   BtifAvrcpAudioTrack* trackHolder) {
195   size_t sampleSize = sampleSizeFor(trackHolder);
196   size_t i = 0;
197   const float scaledGain = trackHolder->gain * kScaleQ31ToFloat;
198   for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) {
199     trackHolder->buffer[i] = ((int32_t*)buffer)[i] * scaledGain;
200   }
201   return i * sampleSize;
202 }
203 
transcodeToPcmFloat(uint8_t * buffer,size_t length,BtifAvrcpAudioTrack * trackHolder)204 static size_t transcodeToPcmFloat(uint8_t* buffer, size_t length,
205                                   BtifAvrcpAudioTrack* trackHolder) {
206   switch (trackHolder->bitsPerSample) {
207     case 16:
208       return transcodeQ15ToFloat(buffer, length, trackHolder);
209     case 24:
210       return transcodeQ23ToFloat(buffer, length, trackHolder);
211     case 32:
212       return transcodeQ31ToFloat(buffer, length, trackHolder);
213   }
214   return -1;
215 }
216 
217 constexpr int64_t kTimeoutNanos = 100 * 1000 * 1000;  // 100 ms
218 
BtifAvrcpAudioTrackWriteData(void * handle,void * audioBuffer,int bufferLength)219 int BtifAvrcpAudioTrackWriteData(void* handle, void* audioBuffer,
220                                  int bufferLength) {
221   BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
222   CHECK(trackHolder != NULL);
223   CHECK(trackHolder->stream != NULL);
224   aaudio_result_t retval = -1;
225 #if (DUMP_PCM_DATA == TRUE)
226   if (outputPcmSampleFile) {
227     fwrite((audioBuffer), 1, (size_t)bufferLength, outputPcmSampleFile);
228   }
229 #endif
230 
231   size_t sampleSize = sampleSizeFor(trackHolder);
232   int transcodedCount = 0;
233   do {
234     transcodedCount +=
235         transcodeToPcmFloat(((uint8_t*)audioBuffer) + transcodedCount,
236                             bufferLength - transcodedCount, trackHolder);
237 
238     retval = AAudioStream_write(
239         trackHolder->stream, trackHolder->buffer,
240         transcodedCount / (sampleSize * trackHolder->channelCount),
241         kTimeoutNanos);
242     LOG_VERBOSE("%s Track.cpp: btWriteData len = %d ret = %d", __func__,
243                 bufferLength, retval);
244   } while (transcodedCount < bufferLength);
245 
246   return transcodedCount;
247 }
248