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 <audio_utils/channels.h>
21 #include <audio_utils/format.h>
22 #include <log/log.h>
23 #include <utils/Timers.h>
24 #include "device_port_source.h"
25 #include "talsa.h"
26 #include "util.h"
27 #include "debug.h"
28
29 namespace android {
30 namespace hardware {
31 namespace audio {
32 namespace V6_0 {
33 namespace implementation {
34
35 namespace {
36
37 struct TinyalsaSource : public DevicePortSource {
TinyalsaSourceandroid::hardware::audio::V6_0::implementation::__anonec57b66a0111::TinyalsaSource38 TinyalsaSource(unsigned pcmCard, unsigned pcmDevice,
39 const AudioConfig &cfg, uint64_t &frames)
40 : mFrames(frames)
41 , mPcm(talsa::pcmOpen(pcmCard, pcmDevice,
42 util::countChannels(cfg.channelMask),
43 cfg.sampleRateHz,
44 cfg.frameCount,
45 false /* isOut */)) {}
46
getCapturePositionandroid::hardware::audio::V6_0::implementation::__anonec57b66a0111::TinyalsaSource47 Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
48 frames = mFrames;
49 time = systemTime(SYSTEM_TIME_MONOTONIC);
50 return Result::OK;
51 }
52
readandroid::hardware::audio::V6_0::implementation::__anonec57b66a0111::TinyalsaSource53 int read(void *data, size_t toReadBytes) override {
54 const int res = ::pcm_read(mPcm.get(), data, toReadBytes);
55 if (res < 0) {
56 return FAILURE(res);
57 } else if (res == 0) {
58 mFrames += ::pcm_bytes_to_frames(mPcm.get(), toReadBytes);
59 return toReadBytes;
60 } else {
61 mFrames += ::pcm_bytes_to_frames(mPcm.get(), res);
62 return res;
63 }
64 }
65
createandroid::hardware::audio::V6_0::implementation::__anonec57b66a0111::TinyalsaSource66 static std::unique_ptr<TinyalsaSource> create(unsigned pcmCard,
67 unsigned pcmDevice,
68 const AudioConfig &cfg,
69 uint64_t &frames) {
70 auto src = std::make_unique<TinyalsaSource>(pcmCard, pcmDevice, cfg, frames);
71 if (src->mPcm) {
72 return src;
73 } else {
74 return FAILURE(nullptr);
75 }
76 }
77
78 private:
79 uint64_t &mFrames;
80 talsa::PcmPtr mPcm;
81 };
82
83 template <class G> struct GeneratedSource : public DevicePortSource {
GeneratedSourceandroid::hardware::audio::V6_0::implementation::__anonec57b66a0111::GeneratedSource84 GeneratedSource(const AudioConfig &cfg, uint64_t &frames, G generator)
85 : mFrames(frames)
86 , mStartNs(systemTime(SYSTEM_TIME_MONOTONIC))
87 , mSampleRateHz(cfg.sampleRateHz)
88 , mNChannels(util::countChannels(cfg.channelMask))
89 , mGenerator(std::move(generator)) {}
90
getCapturePositionandroid::hardware::audio::V6_0::implementation::__anonec57b66a0111::GeneratedSource91 Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
92 const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
93 const uint64_t nowFrames = getNowFrames(nowNs);
94 mFrames += (nowFrames - mPreviousFrames);
95 mPreviousFrames = nowFrames;
96 frames = mFrames;
97 time = nowNs;
98 return Result::OK;
99 }
100
getNowFramesandroid::hardware::audio::V6_0::implementation::__anonec57b66a0111::GeneratedSource101 uint64_t getNowFrames(const nsecs_t nowNs) const {
102 return uint64_t(mSampleRateHz) * ns2ms(nowNs - mStartNs) / 1000;
103 }
104
readandroid::hardware::audio::V6_0::implementation::__anonec57b66a0111::GeneratedSource105 int read(void *data, size_t toReadBytes) override {
106 int16_t *samples = static_cast<int16_t *>(data);
107 const unsigned nChannels = mNChannels;
108 const unsigned requestedFrames = toReadBytes / nChannels / sizeof(*samples);
109
110 unsigned availableFrames;
111 while (true) {
112 const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
113 availableFrames = getNowFrames(nowNs) - mSentFrames;
114 if (availableFrames < requestedFrames / 2) {
115 const unsigned neededMoreFrames = requestedFrames / 2 - availableFrames;
116
117 using namespace std::chrono_literals;
118 std::this_thread::sleep_for(1s * neededMoreFrames / mSampleRateHz);
119 } else {
120 break;
121 }
122 }
123
124 const unsigned nFrames = std::min(requestedFrames, availableFrames);
125 mGenerator(samples, nFrames);
126 const size_t sizeBytes = nFrames * nChannels * sizeof(*samples);
127 if (nChannels > 1) {
128 adjust_channels(samples, 1, samples, nChannels,
129 sizeof(*samples), sizeBytes);
130 }
131
132 mSentFrames += nFrames;
133 return sizeBytes;
134 }
135
136 private:
137 uint64_t &mFrames;
138 const nsecs_t mStartNs;
139 const unsigned mSampleRateHz;
140 const unsigned mNChannels;
141 uint64_t mPreviousFrames = 0;
142 uint64_t mSentFrames = 0;
143 G mGenerator;
144 };
145
convertFloatsToInt16(const std::vector<float> & pcmFloat)146 std::vector<int16_t> convertFloatsToInt16(const std::vector<float> &pcmFloat) {
147 std::vector<int16_t> pcmI16(pcmFloat.size());
148
149 memcpy_by_audio_format(pcmI16.data(), AUDIO_FORMAT_PCM_16_BIT,
150 pcmFloat.data(), AUDIO_FORMAT_PCM_FLOAT,
151 pcmFloat.size());
152
153 return pcmI16;
154 }
155
156 // https://en.wikipedia.org/wiki/Busy_signal
157 struct BusySignalGenerator {
BusySignalGeneratorandroid::hardware::audio::V6_0::implementation::__anonec57b66a0111::BusySignalGenerator158 explicit BusySignalGenerator(const uint32_t sampleRateHz) : mSampleRateHz(sampleRateHz) {
159 // 24/480 = 31/620, mValues must contain 50ms of audio samples
160 const size_t sz = sampleRateHz / 20;
161 std::vector<float> pcm(sz);
162 for (unsigned i = 0; i < sz; ++i) {
163 const double a = double(i) * M_PI * 2 / sampleRateHz;
164 pcm[i] = .5 * (sin(480 * a) + sin(620 * a));
165 }
166 mValues = convertFloatsToInt16(pcm);
167 }
168
operator ()android::hardware::audio::V6_0::implementation::__anonec57b66a0111::BusySignalGenerator169 void operator()(int16_t* s, size_t n) {
170 const unsigned rate = mSampleRateHz;
171 const unsigned rateHalf = rate / 2;
172 const int16_t *const vals = mValues.data();
173 const size_t valsSz = mValues.size();
174 size_t i = mI;
175
176 while (n > 0) {
177 size_t len;
178 if (i < rateHalf) {
179 const size_t valsOff = i % valsSz;
180 len = std::min(n, std::min(rateHalf - i, valsSz - valsOff));
181 memcpy(s, vals + valsOff, len * sizeof(*s));
182 } else {
183 len = std::min(n, rate - i);
184 memset(s, 0, len * sizeof(*s));
185 }
186 s += len;
187 i = (i + len) % rate;
188 n -= len;
189 }
190
191 mI = i;
192 }
193
194 private:
195 const unsigned mSampleRateHz;
196 std::vector<int16_t> mValues;
197 size_t mI = 0;
198 };
199
200 struct RepeatGenerator {
RepeatGeneratorandroid::hardware::audio::V6_0::implementation::__anonec57b66a0111::RepeatGenerator201 explicit RepeatGenerator(const std::vector<float> &pcm)
202 : mValues(convertFloatsToInt16(pcm)) {}
203
operator ()android::hardware::audio::V6_0::implementation::__anonec57b66a0111::RepeatGenerator204 void operator()(int16_t* s, size_t n) {
205 const int16_t *const vals = mValues.data();
206 const size_t valsSz = mValues.size();
207 size_t i = mI;
208
209 while (n > 0) {
210 const size_t len = std::min(n, valsSz - i);
211 memcpy(s, vals + i, len * sizeof(*s));
212 s += len;
213 i = (i + len) % valsSz;
214 n -= len;
215 }
216
217 mI = i;
218 }
219
220 private:
221 const std::vector<int16_t> mValues;
222 size_t mI = 0;
223 };
224
generateSinePattern(uint32_t sampleRateHz,double freq,double amp)225 std::vector<float> generateSinePattern(uint32_t sampleRateHz,
226 double freq,
227 double amp) {
228 std::vector<float> result(3 * sampleRateHz / freq + .5);
229
230 for (size_t i = 0; i < result.size(); ++i) {
231 const double a = double(i) * M_PI * 2 / sampleRateHz;
232 result[i] = amp * sin(a * freq);
233 }
234
235 return result;
236 }
237
238 template <class G> std::unique_ptr<GeneratedSource<G>>
createGeneratedSource(const AudioConfig & cfg,uint64_t & frames,G generator)239 createGeneratedSource(const AudioConfig &cfg, uint64_t &frames, G generator) {
240 return std::make_unique<GeneratedSource<G>>(cfg, frames, std::move(generator));
241 }
242
243 } // namespace
244
245 std::unique_ptr<DevicePortSource>
create(const DeviceAddress & address,const AudioConfig & cfg,const hidl_bitfield<AudioOutputFlag> & flags,uint64_t & frames)246 DevicePortSource::create(const DeviceAddress &address,
247 const AudioConfig &cfg,
248 const hidl_bitfield<AudioOutputFlag> &flags,
249 uint64_t &frames) {
250 (void)flags;
251
252 if (cfg.format != AudioFormat::PCM_16_BIT) {
253 ALOGE("%s:%d Only PCM_16_BIT is supported", __func__, __LINE__);
254 return FAILURE(nullptr);
255 }
256
257 switch (address.device) {
258 case AudioDevice::IN_BUILTIN_MIC:
259 return TinyalsaSource::create(talsa::kPcmCard, talsa::kPcmDevice,
260 cfg, frames);
261
262 case AudioDevice::IN_TELEPHONY_RX:
263 return createGeneratedSource(cfg, frames,
264 BusySignalGenerator(cfg.sampleRateHz));
265
266 case AudioDevice::IN_FM_TUNER:
267 return createGeneratedSource(
268 cfg, frames,
269 RepeatGenerator(generateSinePattern(cfg.sampleRateHz, 440.0, 1.0)));
270
271 default:
272 ALOGE("%s:%d unsupported device: %x", __func__, __LINE__, address.device);
273 return FAILURE(nullptr);
274 }
275 }
276
277 } // namespace implementation
278 } // namespace V6_0
279 } // namespace audio
280 } // namespace hardware
281 } // namespace android
282