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