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

Commit 111ff202 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

Delete previous LC3 encoder implementation

fuzzer is crashing in encoder code, and we don't have anyone to maintain
it.

Bug: 150670922
Test: compilation
Change-Id: Ieec50da8b6c1883af51ea448e412e8f733bd609a
parent c090ca4c
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@
#include "device/include/controller.h"
#include "devices.h"
#include "embdrv/lc3/Api/Lc3Decoder.hpp"
#include "embdrv/lc3/Api/Lc3Encoder.hpp"
#include "embdrv/lc3_enc/include/lc3.h"
#include "gatt/bta_gattc_int.h"
#include "le_audio_types.h"
+0 −2
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

#include <memory>

#include "embdrv/lc3/Api/Lc3Encoder.hpp"

namespace bluetooth {
namespace audio {
class HalVersionManager {
+0 −13
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ cc_library_static {
        "Common/*.cpp",
        "Common/fft/*.c",
        "Common/Tables/*.cpp",
        "Encoder/*.cpp",
        "Decoder/*.cpp",
        "TestSupport/DatapointsAndroid.cpp",
    ],
@@ -57,18 +56,6 @@ cc_library_static {
    ],
}

cc_fuzz {
  name: "liblc3codec_encoder_fuzzer",

  srcs: [
    "fuzzer/liblc3codec_encoder_fuzzer.cpp",
  ],

  static_libs: [
    "liblc3codec",
  ],
}

cc_fuzz {
  name: "liblc3codec_decoder_fuzzer",

+0 −198
Original line number Diff line number Diff line
/*
 * Lc3Encoder.hpp
 *
 * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
 * www.ehima.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef API_LC3ENCODER_HPP_
#define API_LC3ENCODER_HPP_

#include <cstdint>
#include <vector>

#include "Lc3Config.hpp"

/*
 * Forward declaration of the "internal" class EncoderTop, so
 * that the private vector of single channel encoders can be declared in
 * Lc3Encoder.
 */
namespace Lc3Enc {
class EncoderTop;
}

/*
 * The LC3 encoder interface is specified in
 * LC3 specification Sections 2.2 "Encoder interfaces" (dr09r07).
 *
 * Lc3Encoder is designed such that all specified features are provided
 * with the (current) exception of not providing other input bit depth
 * than 16 bit/sample. At the time of writing, the main purpose of the
 * implementation was to handle 16bit audio data provided within android
 * smartphones. Providing the specified 24bit and 32 bit audio data input,
 * would make the API more complex. However, the main argument to not support
 * these sample rates right now, is that internal operations and memory
 * consumption would have to be increased measurable otherwise.
 *
 * Instantiating Lc3Encoder implies providing a Lc3Config instance. A copy of
 * this instance is available as public const member so that all essential
 * session parameters can be obtained throughout the lifetime of the Lc3Encoder
 * instance.
 *
 * There is no possibility of changing Lc3Config within Lc3Encoder. When session
 * parameters have to be changed, the calling application has to create a new
 * instance of Lc3Encoder.
 *
 * Lc3 supports operation with variable encoded bitrate. It is possible to
 * change the bitrate from frame to frame, where for preciseness the parameter
 * is not given as bit rate directly but in terms of the byte_count per frame.
 * This parameter has to be in the range of 20 to 400 (see LC3 specification
 * Section 3.2.5 "Bit budget and bitrate")
 *
 */

class Lc3Encoder {
 public:
  /*
   * Convenience constructor of Lc3Encoder with one simple parameter only.
   * Note that this constructor instantiated Lc3Config implicitly with
   *  Lc3Config(Fs, Lc3Config::FrameDuration::d10ms, 1) that means that this
   * constructor provides processing of one channel (mono) with 10ms frame
   * duration.
   *
   * Parameters:
   *  Fs : Sampling frequency in Hz -> see Lc3Config.hpp for supported values
   */
  Lc3Encoder(uint16_t Fs);

  /*
   * General constructor of Lc3Encoder.
   *
   * Parameters:
   *  lc3Config_ : instance of Lc3Config. See documentation of Lc3Config for
   * more details. Note: providing an invalid instance of Lc3Config will result
   *                     in skipping any processing later.
   *               The provided instance of Lc3Config will be copied to the
   *               public field "lc3Config" (see below).
   *
   *  bits_per_audio_sample_enc_ : The bits per audio sample for the input PCM
   * signal. See LC3 specification Section 2.2 "Encoder interfaces" and
   * Section 3.2.3 "Bits per sample" for the general LC3 requirement to support
   * 16, 24 and 32 bit. Note: This parameter may differ from the decoder output
   * PCM setting "bits_per_audio_sample_dec".
   *
   *                                However, the current implementation allows
   * 16 bit only and will return an error INVALID_BITS_PER_AUDIO_SAMPLE for
   * run() when configured with any other value. (see reasoning for this
   * constraint in the general class descripton above)
   *
   * datapoints : pointer to an instance of a class allowing to collect internal
   * data. Note: this feature is used and prepared for testing of the codec
   *                    implementation only. See general "Readme.txt"
   */
  Lc3Encoder(Lc3Config lc3Config_, uint8_t bits_per_audio_sample_enc_ = 16,
             void* datapoints = nullptr);

  // no default constructor supported
  Lc3Encoder() = delete;

  // Destructor
  virtual ~Lc3Encoder();

  /*
   * Configuration provided during instantiation accessible as public const
   * fields. Note: Lc3Config provides a getter to check whether the
   * configuration is valid.
   */
  const Lc3Config lc3Config;
  const uint8_t bits_per_audio_sample_enc;

  // encoding errors (see return values of "run" methods)
  static const uint8_t ERROR_FREE = 0x00;
  static const uint8_t INVALID_CONFIGURATION = 0x01;
  static const uint8_t INVALID_BYTE_COUNT = 0x02;
  static const uint8_t INVALID_BITS_PER_AUDIO_SAMPLE = 0x03;
  static const uint8_t ENCODER_ALLOCATION_ERROR = 0x04;

  /*
   * Encoding of one input frame for one channel.
   *
   * Note that this method can be used for multi-channel configurations as well,
   * particularly when the provided multi-channel "run" (see below) is not
   * providing the kind of byte stream concatenation desired by a specific
   * application.
   *
   * Parameters:
   *  x          : pointer to input signal array with 16bit/sample.
   *               The length of the signal to be provided depends on the given
   *               session configuration and can be obtained via
   *               lc3Config.NF
   *
   *  byte_count : determines the compression strength (-> bitrate) to be used
   *               for this specific frame. Supported values are 20 bytes to 400
   * bytes, where values well below 40 bytes typically give rather poor audio
   * quality. Note: in case of having an application targeting a given bitrate,
   * the helper method "lc3Config.getByteCountFromBitrate(.)" can be used to
   * compute the proper setting for this byte_count parameter.
   *
   *  bytes      : pointer to byte array (memory) provided by the application,
   * where the encoded byte stream will be placed. The size of this memory is
   * given by the byte_count parameter.
   *
   *  channelNr  : index of channel to be processed (default=0), where channelNr
   * < lc3Config.Nc
   *
   * Return value: error code as listed above.
   */
  uint8_t run(const int16_t* x, uint16_t byte_count, uint8_t* bytes,
              uint8_t channelNr = 0);

  /*
   * Encoding of one multi-channel frame.
   *
   * Note that this call always processes all channels configured in the given
   * session.
   *
   * Parameters:
   *  x          : pointer to input signal array with 16bit/sample.
   *               The length of the signal to be provided depends on the given
   *               session configuration and can be obtained via
   *               lc3Config.NF * lc3Config.Nc
   *
   *  byte_count_per_channel : determines the compression strength (-> bitrate)
   * to be used for each channel individually of this specific frame. Thus,
   * byte_count_per_channel is an array of byte_count values with length
   * lc3Conig.Nc Supported values per channel are 20 bytes to 400 bytes. See
   * also the documentation for the single channel "run" above.
   *
   *  bytes      : pointer to byte array (memory) provided by the application,
   * where the encoded byte stream will be placed. The size of this memory is
   * given by the byte_count_per_channel parameter, specifically by the sum of
   * all channel-wise byte_count values (byte_count_per_channel[0] + ... +
   * byte_count_per_channel[lc3Config.Nc]) This implies that the encoded bytes
   * from the individual channels are concatenated directly (without any
   * stuffing bytes or meta information).
   *
   * Return value: error code as listed above.
   */
  uint8_t run(const int16_t* x, const uint16_t* byte_count_per_channel,
              uint8_t* bytes);

 private:
  std::vector<Lc3Enc::EncoderTop*> encoderList;
};

#endif /* API_LC3ENCODER_HPP_ */
+0 −120
Original line number Diff line number Diff line
/*
 * AttackDetector.cpp
 *
 * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
 * www.ehima.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "AttackDetector.hpp"

#include <cmath>

namespace Lc3Enc {

AttackDetector::AttackDetector(const Lc3Config& lc3Config_)
    : lc3Config(lc3Config_),
      M_F((lc3Config.N_ms == Lc3Config::FrameDuration::d10ms)
              ? 160
              : 120),  // 16*N_ms
      F_att(0),
      E_att_last(0),
      A_att_last(0),
      P_att_last(-1) {
  // make sure these states are initially zero as demanded by the specification
  x_att_last[0] = 0;
  x_att_last[1] = 0;
}

AttackDetector::~AttackDetector() {}

void AttackDetector::run(const int16_t* const x_s, uint16_t nbytes) {
  // 3.3.6.1 Overview (d09r06_FhG)
  // -> attack detection active only for higher bitrates and fs>=32000;
  // otherwise defaults are set
  F_att = 0;
  if (lc3Config.Fs < 32000) {
    return;
  }
  bool isActive =
      ((lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) &&
       (lc3Config.Fs == 32000) && (nbytes > 80)) ||
      ((lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) &&
       (lc3Config.Fs >= 44100) && (nbytes >= 100)) ||
      ((lc3Config.N_ms == Lc3Config::FrameDuration::d7p5ms) &&
       (lc3Config.Fs == 32000) && (nbytes >= 61) && (nbytes < 150)) ||
      ((lc3Config.N_ms == Lc3Config::FrameDuration::d7p5ms) &&
       (lc3Config.Fs >= 44100) && (nbytes >= 75) && (nbytes < 150));
  if (!isActive) {
    // Note: in bitrate switching situations we have to set proper states
    E_att_last = 0;
    A_att_last = 0;
    P_att_last = -1;
    return;
  }

  // 3.3.6.2 Downsampling and filtering of input signal (d09r02_F2F)
  // Note: the following section might be converted to int32 instead
  //       of double computation (maybe something for optimization)
  double x_att_extended[M_F + 2];
  x_att_extended[0] = x_att_last[0];
  x_att_extended[1] = x_att_last[1];
  double* x_att = &x_att_extended[2];
  for (uint8_t n = 0; n < M_F; n++)  // downsampling
  {
    x_att[n] = 0;
    for (uint8_t m = 0; m < lc3Config.NF / M_F; m++) {
      x_att[n] += x_s[lc3Config.NF / M_F * n + m];
    }
  }
  x_att_last[0] = x_att[M_F - 2];
  x_att_last[1] = x_att[M_F - 1];
  double* x_hp = x_att_extended;     // just for improve readability
  for (uint8_t n = 0; n < M_F; n++)  // highpass-filtering (in-place!)
  {
    x_hp[n] = 0.375 * x_att[n] - 0.5 * x_att[n - 1] + 0.125 * x_att[n - 2];
  }

  // 3.3.6.3 Energy calculation & 3.3.6.4 Attack detection (d09r06_FhG)
  int8_t P_att = -1;
  const uint8_t N_blocks =
      (lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? 4 : 3;  // N_ms/2.5
  for (uint8_t n = 0; n < N_blocks; n++) {
    double E_att = 0;
    for (uint8_t l = 40 * n; l <= (40 * n + 39); l++) {
      E_att += x_hp[l] * x_hp[l];
    }
    double A_att =
        (0.25 * A_att_last > E_att_last) ? 0.25 * A_att_last : E_att_last;
    if (E_att > 8.5 * A_att) {
      // attack detected
      P_att = n;
    }
    E_att_last = E_att;
    A_att_last = A_att;
  }
  const uint8_t T_att = (lc3Config.N_ms == Lc3Config::FrameDuration::d10ms)
                            ? 2
                            : 1;  // floor(N_blocks/2)
  F_att = (P_att >= 0) || (P_att_last >= T_att);
  P_att_last = P_att;  // prepare next frame
}

void AttackDetector::registerDatapoints(DatapointContainer* datapoints) {
  if (nullptr != datapoints) {
    datapoints->addDatapoint("F_att", &F_att, sizeof(F_att));
  }
}

}  // namespace Lc3Enc
Loading