summaryrefslogtreecommitdiff
path: root/system/embdrv/lc3_dec/Decoder/DecoderFrame.hpp
blob: 4ce1c86b66974a1ea535171237f165be078164de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 * DecoderFrame.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 __DECODER_FRAME_HPP_
#define __DECODER_FRAME_HPP_

#include <cstdint>

#include "ArithmeticDec.hpp"
#include "Datapoints.hpp"
#include "Lc3Config.hpp"
#include "LongTermPostfilter.hpp"
#include "MdctDec.hpp"
#include "PacketLossConcealment.hpp"
#include "ResidualSpectrum.hpp"
#include "SideInformation.hpp"
#include "SpectralNoiseShaping.hpp"

namespace Lc3Dec {

class DecoderFrame {
 public:
  DecoderFrame(ResidualSpectrum& residualSpectrum_,
               SpectralNoiseShaping& spectralNoiseShaping_,
               PacketLossConcealment& packetLossConcealment_, MdctDec& mdctDec_,
               const Lc3Config& lc3Config_, uint16_t nbytes_);
  virtual ~DecoderFrame();

  void registerDatapoints(DatapointContainer* datapoints_);

  template <typename T>
  void run(const uint8_t* bytes, uint8_t BFI,
           uint16_t bits_per_audio_sample_dec, T* x_out, uint8_t& BEC_detect) {
    if (!lc3Config.isValid()) {
      return;
    }

    // main decoder implementation: 3.4.1 until 3.4.9 (d09r06)
    runFloat(bytes, BFI, BEC_detect);

    // 3.4.10 Output signal scaling and rounding   (d09r06)
    const uint32_t outputScale = 1UL << (-15 + bits_per_audio_sample_dec - 1);
    for (uint16_t k = 0; k < lc3Config.NF; k++) {
      double x_hat_clip_local;
      if (longTermPostfilter.x_hat_ltpf[k] > 32767) {
        x_hat_clip_local = 32767;
      } else if (longTermPostfilter.x_hat_ltpf[k] < -32768) {
        x_hat_clip_local = -32768;
      } else {
        x_hat_clip_local = longTermPostfilter.x_hat_ltpf[k];
      }

      // datapoint buffer for x_hat_clip only prepared when datapoints are
      // available
      if (nullptr != x_hat_clip) {
        x_hat_clip[k] = x_hat_clip_local;
      }

      // Round 𝑥 to nearest integer, e.g., ⌊−4.5⌉ = −5, ⌊−3.2⌉ = −3, ⌊3.2⌉ = 3,
      // ⌊4.5⌉ = 5,
      if (x_hat_clip_local > 0) {
        x_out[k] = outputScale * x_hat_clip_local + 0.5;
      } else {
        x_out[k] = outputScale * x_hat_clip_local - 0.5;
      }
    }

    if (nullptr != datapoints) {
      datapoints->log("x_out", &x_out[0], sizeof(T) * lc3Config.NF);
      datapoints->log("BER_detect", &BEC_detect, sizeof(BEC_detect));
    }
  }

  void linkPreviousFrame(DecoderFrame* previousFrame);

  // per instance constant parameter
  const uint16_t nbytes;
  const uint16_t nbits;
  const Lc3Config& lc3Config;
  const uint8_t tns_lpc_weighting;

 private:
  void runFloat(const uint8_t* bytes, uint8_t BFI, uint8_t& BEC_detect);

  void noiseFilling();
  void applyGlobalGain();
  void temporalNoiseShaping();

  SideInformation sideInformation;
  ArithmeticDec arithmeticDec;
  ResidualSpectrum& residualSpectrum;
  SpectralNoiseShaping& spectralNoiseShaping;
  PacketLossConcealment& packetLossConcealment;
  MdctDec& mdctDec;
  LongTermPostfilter longTermPostfilter;

  DatapointContainer* datapoints;

  // states & outputs
  int16_t frameN;

  int16_t lastnz;
  int16_t P_BW;
  uint8_t lsbMode;
  int16_t gg_ind;
  int16_t num_tns_filters;
  int16_t rc_order[2];
  uint8_t pitch_present;
  int16_t pitch_index;
  int16_t ltpf_active;
  int16_t F_NF;
  int16_t ind_LF;
  int16_t ind_HF;
  int16_t Gind;
  int16_t LS_indA;
  int16_t LS_indB;
  int32_t idxA;
  int16_t idxB;
  uint16_t nf_seed;
  uint16_t zeroFrame;
  int16_t gg_off;
  double* X_hat_q_nf;
  double* X_hat_f;
  double* X_s_tns;
  double* X_hat_ss;
  double* x_hat_clip;
};

}  // namespace Lc3Dec

#endif  // __DECODER_FRAME_HPP_