1 /*
2  * Copyright 2023 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 #pragma once
18 
19 #include <array>
20 #include <cstdint>
21 #include <memory>
22 #include <vector>
23 
24 #include "common/message_loop_thread.h"
25 
26 namespace bluetooth::audio::asrc {
27 
28 class SourceAudioHalAsrc {
29  public:
30   // The Asynchronous Sample Rate Conversion (ASRC) is set up from the PCM
31   // stream characteristics and the length, expressed in us, of the buffers.
32   //
33   // A transmission `burst` is proposed, to fulfill the audio pipeline
34   // buffering. After an initial delay of `burst_delay_ms`, a burst of
35   // `num_burst_buffers` is generated. By experience, it looks like some
36   // controllers discard and acknowledge the first packets without following
37   // transmission intervals. This behavior leads to dumping initial buffers. The
38   // `burst_delay_ms` helps to ensure that the synchronization with the
39   // transmission intervals is done.
40 
41   SourceAudioHalAsrc(bluetooth::common::MessageLoopThread* thread, int channels,
42                      int sample_rate, int bit_depth, int interval_us,
43                      int num_burst_buffers = 2, int burst_delay_ms = 500);
44 
45   ~SourceAudioHalAsrc();
46 
47   // Takes an input buffer, and returns a list of resamples buffers locked to
48   // the cadence of the transmission. The input and output buffers have a fixed
49   // size, deducted from the PCM characteristics, given to the constructor.
50   //
51   // The data of `in` mest be aligned to `int16_t` or `int32_t` for respectively
52   // bit depth less or equal to 16, or greater.
53   //
54 
55   std::vector<const std::vector<uint8_t>*> Run(const std::vector<uint8_t>& in);
56 
57  private:
58   const int sample_rate_;
59   const int bit_depth_;
60   const int interval_us_;
61 
62   unsigned burst_delay_us_;
63   std::vector<const std::vector<uint8_t>*> burst_buffers_;
64 
65   unsigned stream_us_;
66   double drift_z0_, drift_us_;
67   unsigned out_counter_;
68 
69   size_t buffers_size_;
70 
71   struct {
72     std::array<std::vector<uint8_t>, 3> pool;
73     int initial_buffering;
74     int index, offset;
75   } buffers_;
76 
77   class ClockRecovery;
78   std::unique_ptr<ClockRecovery> clock_recovery_;
79 
80   class Resampler;
81   std::unique_ptr<std::vector<Resampler>> resamplers_;
82   struct {
83     unsigned seconds;
84     int samples;
85   } resampler_pos_;
86 
87   template <typename T>
88   void Resample(double, const std::vector<uint8_t>&,
89                 std::vector<const std::vector<uint8_t>*>*, uint32_t*);
90 
91   friend class SourceAudioHalAsrcTest;
92 };
93 
94 }  // namespace bluetooth::audio::asrc
95