1 /*
2 * Copyright (C) 2020 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 <cmath>
18 #include <chrono>
19 #include <thread>
20 #include <unistd.h>
21 #include <audio_utils/channels.h>
22 #include <audio_utils/format.h>
23 #include <log/log.h>
24 #include <utils/ThreadDefs.h>
25 #include <utils/Timers.h>
26 #include "device_port_source.h"
27 #include "talsa.h"
28 #include "ring_buffer.h"
29 #include "audio_ops.h"
30 #include "util.h"
31 #include "debug.h"
32
33 namespace android {
34 namespace hardware {
35 namespace audio {
36 namespace V6_0 {
37 namespace implementation {
38
39 namespace {
40
41 constexpr int kMaxJitterUs = 3000; // Enforced by CTS, should be <= 6ms
42
43 struct TinyalsaSource : public DevicePortSource {
TinyalsaSourceandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource44 TinyalsaSource(unsigned pcmCard, unsigned pcmDevice,
45 const AudioConfig &cfg, uint64_t &frames)
46 : mStartNs(systemTime(SYSTEM_TIME_MONOTONIC))
47 , mSampleRateHz(cfg.sampleRateHz)
48 , mFrameSize(util::countChannels(cfg.channelMask) * sizeof(int16_t))
49 , mReadSizeFrames(cfg.frameCount)
50 , mFrames(frames)
51 , mRingBuffer(mFrameSize * cfg.frameCount * 3)
52 , mMixer(pcmCard)
53 , mPcm(talsa::pcmOpen(pcmCard, pcmDevice,
54 util::countChannels(cfg.channelMask),
55 cfg.sampleRateHz,
56 cfg.frameCount,
57 false /* isOut */)) {
58 mProduceThread = std::thread(&TinyalsaSource::producerThread, this);
59 }
60
~TinyalsaSourceandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource61 ~TinyalsaSource() {
62 mProduceThreadRunning = false;
63 mProduceThread.join();
64 }
65
getCapturePositionandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource66 Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
67 const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
68 const uint64_t nowFrames = getCaptureFrames(nowNs);
69 mFrames += (nowFrames - mPreviousFrames);
70 mPreviousFrames = nowFrames;
71
72 frames = mFrames;
73 time = nowNs;
74 return Result::OK;
75 }
76
getCaptureFramesandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource77 uint64_t getCaptureFrames(const nsecs_t nowNs) const {
78 return uint64_t(mSampleRateHz) * ns2us(nowNs - mStartNs) / 1000000;
79 }
80
getAvailableFramesandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource81 uint64_t getAvailableFrames(const nsecs_t nowNs) const {
82 return getCaptureFrames(nowNs) - mSentFrames;
83 }
84
getAvailableFramesNowandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource85 uint64_t getAvailableFramesNow() const {
86 return getAvailableFrames(systemTime(SYSTEM_TIME_MONOTONIC));
87 }
88
getWaitFramesNowandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource89 size_t getWaitFramesNow(const size_t requestedFrames) const {
90 const size_t availableFrames = getAvailableFramesNow();
91 return (requestedFrames > availableFrames)
92 ? (requestedFrames - availableFrames) : 0;
93 }
94
readandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource95 size_t read(float volume, size_t bytesToRead, IWriter &writer) override {
96 const size_t waitFrames = getWaitFramesNow(bytesToRead / mFrameSize);
97 const auto blockUntil =
98 std::chrono::high_resolution_clock::now() +
99 + std::chrono::microseconds(waitFrames * 1000000 / mSampleRateHz);
100
101 while (bytesToRead > 0) {
102 if (mRingBuffer.waitForConsumeAvailable(blockUntil
103 + std::chrono::microseconds(kMaxJitterUs))) {
104 if (mRingBuffer.availableToConsume() >= bytesToRead) {
105 // Since the ring buffer has all bytes we need, make sure we
106 // are not too early here: tinyalsa is jittery, we don't
107 // want to go faster than SYSTEM_TIME_MONOTONIC
108 std::this_thread::sleep_until(blockUntil);
109 }
110
111 auto chunk = mRingBuffer.getConsumeChunk();
112 const size_t writeBufSzBytes = std::min(chunk.size, bytesToRead);
113
114 aops::multiplyByVolume(volume,
115 static_cast<int16_t *>(chunk.data),
116 writeBufSzBytes / sizeof(int16_t));
117
118 writer(chunk.data, writeBufSzBytes);
119 LOG_ALWAYS_FATAL_IF(mRingBuffer.consume(chunk, writeBufSzBytes) < writeBufSzBytes);
120
121 bytesToRead -= writeBufSzBytes;
122 mSentFrames += writeBufSzBytes / mFrameSize;
123 } else {
124 ALOGW("TinyalsaSource::%s:%d pcm_read was late delivering "
125 "frames, inserting %zu us of silence",
126 __func__, __LINE__,
127 size_t(1000000 * bytesToRead / mFrameSize / mSampleRateHz));
128
129 static const uint8_t zeroes[256] = {0};
130
131 while (bytesToRead > 0) {
132 const size_t nZeroFrames =
133 std::min(bytesToRead, sizeof(zeroes)) / mFrameSize;
134 const size_t nZeroBytes = nZeroFrames * mFrameSize;
135
136 writer(zeroes, nZeroBytes);
137 mSentFrames += nZeroFrames;
138 bytesToRead -= nZeroBytes;
139 }
140 break;
141 }
142 }
143
144 return mFramesLost.exchange(0);
145 }
146
producerThreadandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource147 void producerThread() {
148 util::setThreadPriority(PRIORITY_URGENT_AUDIO);
149 std::vector<uint8_t> readBuf(mReadSizeFrames * mFrameSize);
150
151 while (mProduceThreadRunning) {
152 const size_t bytesLost = mRingBuffer.makeRoomForProduce(readBuf.size());
153 mFramesLost += bytesLost / mFrameSize;
154
155 auto produceChunk = mRingBuffer.getProduceChunk();
156 if (produceChunk.size < readBuf.size()) {
157 const size_t sz = doRead(readBuf.data(), readBuf.size());
158 if (sz > 0) {
159 LOG_ALWAYS_FATAL_IF(mRingBuffer.produce(readBuf.data(), sz) < sz);
160 }
161 } else {
162 const size_t sz = doRead(produceChunk.data, readBuf.size());
163 if (sz > 0) {
164 LOG_ALWAYS_FATAL_IF(mRingBuffer.produce(readBuf.size()) < sz);
165 }
166 }
167 }
168 }
169
doReadandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource170 size_t doRead(void *dst, size_t sz) {
171 const int res = ::pcm_read(mPcm.get(), dst, sz);
172 if (res < 0) {
173 ALOGW("TinyalsaSource::%s:%d pcm_read failed with res=%d",
174 __func__, __LINE__, res);
175 return 0;
176 }
177
178 return sz;
179 }
180
createandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::TinyalsaSource181 static std::unique_ptr<TinyalsaSource> create(unsigned pcmCard,
182 unsigned pcmDevice,
183 const AudioConfig &cfg,
184 size_t writerBufferSizeHint,
185 uint64_t &frames) {
186 (void)writerBufferSizeHint;
187
188 auto src = std::make_unique<TinyalsaSource>(pcmCard, pcmDevice,
189 cfg, frames);
190 if (src->mMixer && src->mPcm) {
191 return src;
192 } else {
193 return FAILURE(nullptr);
194 }
195 }
196
197 private:
198 const nsecs_t mStartNs;
199 const unsigned mSampleRateHz;
200 const unsigned mFrameSize;
201 const unsigned mReadSizeFrames;
202 uint64_t &mFrames;
203 uint64_t mPreviousFrames = 0;
204 uint64_t mSentFrames = 0;
205 std::atomic<uint32_t> mFramesLost = 0;
206 RingBuffer mRingBuffer;
207 talsa::Mixer mMixer;
208 talsa::PcmPtr mPcm;
209 std::thread mProduceThread;
210 std::atomic<bool> mProduceThreadRunning = true;
211 };
212
213 template <class G> struct GeneratedSource : public DevicePortSource {
GeneratedSourceandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::GeneratedSource214 GeneratedSource(const AudioConfig &cfg,
215 size_t writerBufferSizeHint,
216 uint64_t &frames,
217 G generator)
218 : mWriteBuffer(writerBufferSizeHint / sizeof(int16_t))
219 , mFrames(frames)
220 , mStartNs(systemTime(SYSTEM_TIME_MONOTONIC))
221 , mSampleRateHz(cfg.sampleRateHz)
222 , mNChannels(util::countChannels(cfg.channelMask))
223 , mGenerator(std::move(generator)) {}
224
getCapturePositionandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::GeneratedSource225 Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
226 const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
227 const uint64_t nowFrames = getCaptureFrames(nowNs);
228 mFrames += (nowFrames - mPreviousFrames);
229 mPreviousFrames = nowFrames;
230 frames = mFrames;
231 time = nowNs;
232 return Result::OK;
233 }
234
getCaptureFramesandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::GeneratedSource235 uint64_t getCaptureFrames(const nsecs_t nowNs) const {
236 return uint64_t(mSampleRateHz) * ns2us(nowNs - mStartNs) / 1000000;
237 }
238
getAvailableFramesandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::GeneratedSource239 uint64_t getAvailableFrames(const nsecs_t nowNs) const {
240 return getCaptureFrames(nowNs) - mSentFrames;
241 }
242
readandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::GeneratedSource243 size_t read(float volume, size_t bytesToRead, IWriter &writer) override {
244 mWriteBuffer.resize(bytesToRead / sizeof(int16_t));
245
246 int16_t *samples = mWriteBuffer.data();
247 const unsigned nChannels = mNChannels;
248 const unsigned requestedFrames = bytesToRead / nChannels / sizeof(*samples);
249
250 unsigned availableFrames;
251 while (true) {
252 const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
253 availableFrames = getAvailableFrames(nowNs);
254 if (availableFrames < requestedFrames / 2) {
255 const unsigned neededMoreFrames = requestedFrames / 2 - availableFrames;
256
257 using namespace std::chrono_literals;
258 std::this_thread::sleep_for(1s * neededMoreFrames / mSampleRateHz);
259 } else {
260 break;
261 }
262 }
263
264 const unsigned nFrames = std::min(requestedFrames, availableFrames);
265 mGenerator(samples, nFrames);
266 const size_t sizeBytes = nFrames * nChannels * sizeof(*samples);
267 if (nChannels > 1) {
268 adjust_channels(samples, 1, samples, nChannels,
269 sizeof(*samples), sizeBytes);
270 }
271 mSentFrames += nFrames;
272
273 aops::multiplyByVolume(volume,
274 mWriteBuffer.data(),
275 sizeBytes / sizeof(int16_t));
276
277 writer(mWriteBuffer.data(), sizeBytes);
278 return 0;
279 }
280
281 private:
282 std::vector<int16_t> mWriteBuffer;
283 uint64_t &mFrames;
284 const nsecs_t mStartNs;
285 const unsigned mSampleRateHz;
286 const unsigned mNChannels;
287 uint64_t mPreviousFrames = 0;
288 uint64_t mSentFrames = 0;
289 G mGenerator;
290 };
291
convertFloatsToInt16(const std::vector<float> & pcmFloat)292 std::vector<int16_t> convertFloatsToInt16(const std::vector<float> &pcmFloat) {
293 std::vector<int16_t> pcmI16(pcmFloat.size());
294
295 memcpy_by_audio_format(pcmI16.data(), AUDIO_FORMAT_PCM_16_BIT,
296 pcmFloat.data(), AUDIO_FORMAT_PCM_FLOAT,
297 pcmFloat.size());
298
299 return pcmI16;
300 }
301
302 // https://en.wikipedia.org/wiki/Busy_signal
303 struct BusySignalGenerator {
BusySignalGeneratorandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::BusySignalGenerator304 explicit BusySignalGenerator(const uint32_t sampleRateHz) : mSampleRateHz(sampleRateHz) {
305 // 24/480 = 31/620, mValues must contain 50ms of audio samples
306 const size_t sz = sampleRateHz / 20;
307 std::vector<float> pcm(sz);
308 for (unsigned i = 0; i < sz; ++i) {
309 const double a = double(i) * M_PI * 2 / sampleRateHz;
310 pcm[i] = .5 * (sin(480 * a) + sin(620 * a));
311 }
312 mValues = convertFloatsToInt16(pcm);
313 }
314
operator ()android::hardware::audio::V6_0::implementation::__anond1989e5f0111::BusySignalGenerator315 void operator()(int16_t* s, size_t n) {
316 const unsigned rate = mSampleRateHz;
317 const unsigned rateHalf = rate / 2;
318 const int16_t *const vals = mValues.data();
319 const size_t valsSz = mValues.size();
320 size_t i = mI;
321
322 while (n > 0) {
323 size_t len;
324 if (i < rateHalf) {
325 const size_t valsOff = i % valsSz;
326 len = std::min(n, std::min(rateHalf - i, valsSz - valsOff));
327 memcpy(s, vals + valsOff, len * sizeof(*s));
328 } else {
329 len = std::min(n, rate - i);
330 memset(s, 0, len * sizeof(*s));
331 }
332 s += len;
333 i = (i + len) % rate;
334 n -= len;
335 }
336
337 mI = i;
338 }
339
340 private:
341 const unsigned mSampleRateHz;
342 std::vector<int16_t> mValues;
343 size_t mI = 0;
344 };
345
346 struct RepeatGenerator {
RepeatGeneratorandroid::hardware::audio::V6_0::implementation::__anond1989e5f0111::RepeatGenerator347 explicit RepeatGenerator(const std::vector<float> &pcm)
348 : mValues(convertFloatsToInt16(pcm)) {}
349
operator ()android::hardware::audio::V6_0::implementation::__anond1989e5f0111::RepeatGenerator350 void operator()(int16_t* s, size_t n) {
351 const int16_t *const vals = mValues.data();
352 const size_t valsSz = mValues.size();
353 size_t i = mI;
354
355 while (n > 0) {
356 const size_t len = std::min(n, valsSz - i);
357 memcpy(s, vals + i, len * sizeof(*s));
358 s += len;
359 i = (i + len) % valsSz;
360 n -= len;
361 }
362
363 mI = i;
364 }
365
366 private:
367 const std::vector<int16_t> mValues;
368 size_t mI = 0;
369 };
370
generateSinePattern(uint32_t sampleRateHz,double freq,double amp)371 std::vector<float> generateSinePattern(uint32_t sampleRateHz,
372 double freq,
373 double amp) {
374 std::vector<float> result(3 * sampleRateHz / freq + .5);
375
376 for (size_t i = 0; i < result.size(); ++i) {
377 const double a = double(i) * M_PI * 2 / sampleRateHz;
378 result[i] = amp * sin(a * freq);
379 }
380
381 return result;
382 }
383
384 template <class G> std::unique_ptr<GeneratedSource<G>>
createGeneratedSource(const AudioConfig & cfg,size_t writerBufferSizeHint,uint64_t & frames,G generator)385 createGeneratedSource(const AudioConfig &cfg,
386 size_t writerBufferSizeHint,
387 uint64_t &frames,
388 G generator) {
389 return std::make_unique<GeneratedSource<G>>(cfg,
390 writerBufferSizeHint,
391 frames,
392 std::move(generator));
393 }
394
395 } // namespace
396
397 std::unique_ptr<DevicePortSource>
create(size_t writerBufferSizeHint,const DeviceAddress & address,const AudioConfig & cfg,const hidl_bitfield<AudioOutputFlag> & flags,uint64_t & frames)398 DevicePortSource::create(size_t writerBufferSizeHint,
399 const DeviceAddress &address,
400 const AudioConfig &cfg,
401 const hidl_bitfield<AudioOutputFlag> &flags,
402 uint64_t &frames) {
403 (void)flags;
404
405 if (cfg.format != AudioFormat::PCM_16_BIT) {
406 ALOGE("%s:%d Only PCM_16_BIT is supported", __func__, __LINE__);
407 return FAILURE(nullptr);
408 }
409
410 switch (address.device) {
411 case AudioDevice::IN_BUILTIN_MIC:
412 return TinyalsaSource::create(talsa::kPcmCard, talsa::kPcmDevice,
413 cfg, writerBufferSizeHint, frames);
414
415 case AudioDevice::IN_TELEPHONY_RX:
416 return createGeneratedSource(cfg, writerBufferSizeHint, frames,
417 BusySignalGenerator(cfg.sampleRateHz));
418
419 case AudioDevice::IN_FM_TUNER:
420 return createGeneratedSource(
421 cfg, writerBufferSizeHint, frames,
422 RepeatGenerator(generateSinePattern(cfg.sampleRateHz, 440.0, 1.0)));
423
424 default:
425 ALOGE("%s:%d unsupported device: %x", __func__, __LINE__, address.device);
426 return FAILURE(nullptr);
427 }
428 }
429
430 } // namespace implementation
431 } // namespace V6_0
432 } // namespace audio
433 } // namespace hardware
434 } // namespace android
435