Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 448440ff authored by Henri Chataing's avatar Henri Chataing Committed by Automerger Merge Worker
Browse files

Merge changes I5302146e,Ib9b96c8c into main am: cbda9520 am: d912ad26

parents da50740f d912ad26
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -14,9 +14,6 @@ cc_library_static {
        "asrc/asrc_resampler.cc",
        "asrc/asrc_tables.cc",
    ],
    include_dirs: [
        "packages/modules/Bluetooth/system/gd",
    ],
    shared_libs: [
        "libchrome",
    ],
@@ -44,7 +41,6 @@ cc_library_host_shared {
    stl: "libc++_static",
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/gd",
    ],
    generated_headers: [
        "BluetoothGeneratedDumpsysDataSchema_h",
+10 −12
Original line number Diff line number Diff line
@@ -19,15 +19,15 @@
#include <base/logging.h>
#include <base/strings/stringprintf.h>

#include <algorithm>
#include <cmath>
#include <utility>

#include "asrc_tables.h"
#include "hal/nocp_iso_clocker.h"

namespace bluetooth::audio::asrc {

class SourceAudioHalAsrc::ClockRecovery : ::bluetooth::hal::NocpIsoHandler {
class SourceAudioHalAsrc::ClockRecovery : public ClockHandler {
  const int interval_;

  std::mutex mutex_;
@@ -113,8 +113,7 @@ class SourceAudioHalAsrc::ClockRecovery : ::bluetooth::hal::NocpIsoHandler {
    }

    int dt_current = int(timestamp_us - link.local_time);
    if (std::abs(dt_current) < std::abs(link.decim_dt[1]))
      link.decim_dt[1] = dt_current;
    link.decim_dt[1] = std::min(link.decim_dt[1], dt_current);

    if (link.local_time - link.decim_t0 < 1000 * 1000) return;

@@ -237,11 +236,9 @@ class SourceAudioHalAsrc::ClockRecovery : ::bluetooth::hal::NocpIsoHandler {
        state_{
            .link = {{.state = LinkState::RESET}, {.state = LinkState::RESET}},
            .active_link_id = -1},
        reference_timing_{0, 0, 0} {
    ::bluetooth::hal::NocpIsoClocker::Register(this);
  }
        reference_timing_{0, 0, 0} {}

  ~ClockRecovery() override { ::bluetooth::hal::NocpIsoClocker::Unregister(); }
  ~ClockRecovery() override {}

  __attribute__((no_sanitize("integer"))) uint32_t Convert(
      uint32_t stream_time) {
@@ -466,16 +463,16 @@ inline int32_t SourceAudioHalAsrc::Resampler::Filter(const int32_t* in,

#endif

SourceAudioHalAsrc::SourceAudioHalAsrc(int channels, int sample_rate,
                                       int bit_depth, int interval_us,
                                       int num_burst_buffers,
                                       int burst_delay_ms)
SourceAudioHalAsrc::SourceAudioHalAsrc(
    std::shared_ptr<ClockSource> clock_source, int channels, int sample_rate,
    int bit_depth, int interval_us, int num_burst_buffers, int burst_delay_ms)
    : sample_rate_(sample_rate),
      bit_depth_(bit_depth),
      interval_us_(interval_us),
      stream_us_(0),
      drift_us_(0),
      out_counter_(0),
      clock_source_(std::move(clock_source)),
      resampler_pos_{0, 0} {
  buffers_size_ = 0;

@@ -509,6 +506,7 @@ SourceAudioHalAsrc::SourceAudioHalAsrc(int channels, int sample_rate,
  // when the PCM bit_depth is higher than 16 bits.

  clock_recovery_ = std::make_unique<ClockRecovery>(interval_us_);
  clock_source_->Bind(clock_recovery_.get());
  resamplers_ = std::make_unique<std::vector<Resampler>>(channels, bit_depth_);

  // Deduct from the PCM stream characteristics, the size of the pool buffers
+17 −3
Original line number Diff line number Diff line
@@ -23,6 +23,19 @@

namespace bluetooth::audio::asrc {

class ClockHandler {
 public:
  virtual ~ClockHandler() = default;
  virtual void OnEvent(uint32_t timestamp, int link_id,
                       int num_of_completed_packets) = 0;
};

class ClockSource {
 public:
  virtual ~ClockSource() = default;
  virtual void Bind(ClockHandler*) = 0;
};

class SourceAudioHalAsrc {
 public:
  // The Asynchronous Sample Rate Conversion (ASRC) is set up from the PCM
@@ -36,9 +49,9 @@ class SourceAudioHalAsrc {
  // `burst_delay_ms` helps to ensure that the synchronization with the
  // transmission intervals is done.

  SourceAudioHalAsrc(int channels, int sample_rate, int bit_depth,
                     int interval_us, int num_burst_buffers = 2,
                     int burst_delay_ms = 500);
  SourceAudioHalAsrc(std::shared_ptr<ClockSource> clock_source, int channels,
                     int sample_rate, int bit_depth, int interval_us,
                     int num_burst_buffers = 2, int burst_delay_ms = 500);

  ~SourceAudioHalAsrc();

@@ -74,6 +87,7 @@ class SourceAudioHalAsrc {

  class ClockRecovery;
  std::unique_ptr<ClockRecovery> clock_recovery_;
  std::shared_ptr<ClockSource> clock_source_;

  class Resampler;
  std::unique_ptr<std::vector<Resampler>> resamplers_;
+6 −6
Original line number Diff line number Diff line
@@ -19,17 +19,17 @@
#include <cstdio>
#include <iostream>

namespace bluetooth::hal {
void NocpIsoClocker::Register(NocpIsoHandler*) {}
void NocpIsoClocker::Unregister() {}
}  // namespace bluetooth::hal

namespace bluetooth::audio::asrc {

class MockClockSource : public ClockSource {
  void Bind(ClockHandler*) override {}
};

class SourceAudioHalAsrcTest : public SourceAudioHalAsrc {
 public:
  SourceAudioHalAsrcTest(int channels, int bitdepth)
      : SourceAudioHalAsrc(channels, 48000, bitdepth, 10000) {}
      : SourceAudioHalAsrc(std::make_unique<MockClockSource>(), channels, 48000,
                           bitdepth, 10000) {}

  template <typename T>
  void Resample(double ratio, const T* in, size_t in_length, size_t* in_count,
+84 −1
Original line number Diff line number Diff line
@@ -32,12 +32,14 @@
#include <mutex>
#include <vector>

#include "audio/asrc/asrc_resampler.h"
#include "bta/include/bta_gatt_api.h"
#include "bta/include/bta_gatt_queue.h"
#include "bta/include/bta_hearing_aid_api.h"
#include "btm_iso_api.h"
#include "device/include/controller.h"
#include "embdrv/g722/g722_enc_dec.h"
#include "hal/link_clocker.h"
#include "hardware/bt_gatt_types.h"
#include "include/check.h"
#include "internal_include/bt_trace.h"
@@ -275,6 +277,13 @@ class HearingAidImpl : public HearingAid {
  const int DROP_FREQUENCY_THRESHOLD =
      bluetooth::common::init_flags::get_asha_packet_drop_frequency_threshold();

  // Resampler context for audio stream.
  // Clock recovery uses L2CAP Flow Control Credit Ind acknowledgments
  // from either the left or right connection, whichever is first
  // connected.
  std::shared_ptr<bluetooth::hal::L2capCreditIndEvents> asrc_clock_source;
  std::unique_ptr<bluetooth::audio::asrc::SourceAudioHalAsrc> asrc;

 public:
  ~HearingAidImpl() override = default;

@@ -354,6 +363,51 @@ class HearingAidImpl : public HearingAid {
    }
  }

  // Reset and configure the ASHA resampling context using the input device
  // devices as reference for the BT clock estimation.
  void ConfigureAsrc() {
    if (!IS_FLAG_ENABLED(asha_asrc)) {
      log::info("Asha resampling disabled: feature flag off");
      return;
    }

    // Create a new ASRC context if required.
    if (asrc == nullptr) {
      asrc_clock_source =
          std::make_shared<bluetooth::hal::L2capCreditIndEvents>();
      asrc = std::make_unique<bluetooth::audio::asrc::SourceAudioHalAsrc>(
          asrc_clock_source, /*channels*/ 2,
          /*sample_rate*/ codec_in_use == CODEC_G722_24KHZ ? 24000 : 16000,
          /*bit_depth*/ 16,
          /*interval_us*/ default_data_interval_ms * 1000,
          /*num_burst_buffers*/ 0,
          /*burst_delay*/ 0);
    }

    for (auto& device : hearingDevices.devices) {
      if (!device.accepting_audio) {
        continue;
      }

      uint16_t lcid = GAP_ConnGetL2CAPCid(device.gap_handle);
      uint16_t rcid = 0;
      L2CA_GetRemoteCid(lcid, &rcid);

      auto conn = btm_acl_for_bda(device.address, BT_TRANSPORT_LE);
      log::info("Updating ASRC context for handle=0x{:x}, cid=0x{:x}",
                conn->Handle(), rcid);

      asrc_clock_source->Update(device.isLeft(), conn->Handle(), rcid);
    }
  }

  // Reset the ASHA resampling context.
  void ResetAsrc() {
    log::info("Resetting the Asha resampling context");
    asrc_clock_source = nullptr;
    asrc = nullptr;
  }

  uint16_t UpdateBleConnParams(const RawAddress& address) {
    /* List of parameters that depends on the chosen Connection Interval */
    uint16_t min_ce_len = MIN_CE_LEN_20MS_CI;
@@ -1171,6 +1225,10 @@ class HearingAidImpl : public HearingAid {
    } else {
      log::info("audio_running={}", audio_running);
    }

    // Close the ASRC context.
    ResetAsrc();

    audio_running = false;
    stop_audio_ticks();

@@ -1213,6 +1271,9 @@ class HearingAidImpl : public HearingAid {
      return;
    }

    // Open the ASRC context.
    ConfigureAsrc();

    // TODO: shall we also reset the encoder ?
    encoder_state_release();
    encoder_state_init();
@@ -1352,6 +1413,16 @@ class HearingAidImpl : public HearingAid {
    return diff_credit < (init_credit / 2 - 1);
  }

  void OnAudioDataReadyResample(const std::vector<uint8_t>& data) {
    if (asrc == nullptr) {
      return OnAudioDataReady(data);
    }

    for (auto const resampled_data : asrc->Run(data)) {
      OnAudioDataReady(*resampled_data);
    }
  }

  void OnAudioDataReady(const std::vector<uint8_t>& data) {
    /* For now we assume data comes in as 16bit per sample 16kHz PCM stereo */
    bool need_drop = false;
@@ -1414,6 +1485,18 @@ class HearingAidImpl : public HearingAid {
      l2cap_flush_threshold = 1;
    }

    // Skipping packets completely messes up the resampler context.
    // The condition for skipping packets seems to be easily triggered,
    // causing dropouts that could have been avoided.
    //
    // When the resampler is enabled, the flush threshold is set
    // to the number of credits specified for the ASHA l2cap streaming
    // channel. This will ensure it is only triggered in case of
    // critical failure.
    if (IS_FLAG_ENABLED(asha_asrc)) {
      l2cap_flush_threshold = 8;
    }

    // TODO: monural, binarual check

    // divide encoded data into packets, add header, send.
@@ -2069,7 +2152,7 @@ void encryption_callback(const RawAddress* address, tBT_TRANSPORT, void*,
class HearingAidAudioReceiverImpl : public HearingAidAudioReceiver {
 public:
  void OnAudioDataReady(const std::vector<uint8_t>& data) override {
    if (instance) instance->OnAudioDataReady(data);
    if (instance) instance->OnAudioDataReadyResample(data);
  }
  void OnAudioSuspend(const std::function<void()>& stop_audio_ticks) override {
    if (instance) instance->OnAudioSuspend(stop_audio_ticks);
Loading