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