aboutsummaryrefslogtreecommitdiff
path: root/system/embdrv/encoder_for_aptx/src/DitherGenerator.h
blob: baa5605491f8c88c8c4385df92a59521830d6152 (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
/**
 * Copyright (C) 2022 The Android Open Source Project
 *
 * 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.
 */
/*------------------------------------------------------------------------------
 *
 *  These functions allow clients to update an internal codeword history
 *  attribute from previously-generated quantised codes, and to generate a new
 *  pseudo-random dither value per subband from this internal attribute.
 *
 *----------------------------------------------------------------------------*/

#ifndef DITHERGENERATOR_H
#define DITHERGENERATOR_H

#include "AptxParameters.h"

/* This function updates an internal bit-pool (private
 * variable in DitherGenerator) based on bits obtained from
 * previously encoded or received aptX codewords. */
XBT_INLINE_ int32_t xbtEncupdateCodewordHistory(const int32_t quantisedCodes[4],
                                                int32_t m_codewordHistory) {
  int32_t newBits;
  int32_t updatedCodewordHistory;

  const int32_t llMask = 0x3L;
  const int32_t lhMask = 0x2L;
  const int32_t hlMask = 0x1L;
  const uint32_t lhShift = 1;
  const uint32_t hlShift = 3;
  /* Shift value to left-justify a 24-bit value in a 32-bit signed variable*/
  const uint32_t leftJustifyShift = 8;
  const uint32_t numNewBits = 4;

  /* Make a 4-bit vector from particular bits from 3 quantised codes */
  newBits = (quantisedCodes[LL] & llMask) +
            ((quantisedCodes[LH] & lhMask) << lhShift) +
            ((quantisedCodes[HL] & hlMask) << hlShift);

  /* Add the 4 new bits to the codeword history. Note that this is a 24-bit
   * value LEFT-JUSTIFIED in a 32-bit signed variable. Maintaining the history
   * as signed is useful in the dither generation process below. */
  updatedCodewordHistory =
      (m_codewordHistory << numNewBits) + (newBits << leftJustifyShift);

  return updatedCodewordHistory;
}

/* Function to generate a dither value for each subband based
 * on the current contents of the codewordHistory bit-pool. */
XBT_INLINE_ int32_t xbtEncgenerateDither(int32_t m_codewordHistory,
                                         int32_t* m_ditherOutputs) {
  int32_t history24b;
  int32_t upperAcc;
  int32_t lowerAcc;
  int32_t accSum;
  int64_t tmp_acc;
  int32_t ditherSample;
  int32_t m_dithSyncRandBit;

  /* Fixed value to multiply codeword history variable by */
  const uint32_t dithConstMultiplier = 0x4f1bbbL;
  /* Shift value to left-justify a 24-bit value in a 32-bit signed variable*/
  const uint32_t leftJustifyShift = 8;

  /* AND mask to retain only the lower 24 bits of a variable */
  const int32_t keepLower24bitsMask = 0xffffffL;

  /* Convert the codeword history to a 24-bit signed value. This can be done
   * cheaply with a 8-position right-shift since it is maintained as 24-bits
   * value left-justified in a signed 32-bit variable. */
  history24b = m_codewordHistory >> (leftJustifyShift - 1);

  /* Multiply the history by a fixed constant. The constant has already been
   * shifted right by 1 position to compensate for the left-shift introduced
   * on the product by the fractional multiplier. */
  tmp_acc = ((int64_t)history24b * (int64_t)dithConstMultiplier);

  /* Get the upper and lower 24-bit values from the accumulator, and form
   * their sum. */
  upperAcc = ((int32_t)(tmp_acc >> 24)) & 0x00FFFFFFL;
  lowerAcc = ((int32_t)tmp_acc) & 0x00FFFFFFL;
  accSum = upperAcc + lowerAcc;

  /* The dither sample is the 2 msbs of lowerAcc and the 22 lsbs of accSum */
  ditherSample = ((lowerAcc >> 22) + (accSum << 2)) & keepLower24bitsMask;

  /* The sign bit of 24-bit accSum is saved as a random bit to
   * assist in the aptX sync insertion process. */
  m_dithSyncRandBit = (accSum >> 23) & 0x1;

  /* Successive dither outputs for the 4 subbands are versions of ditherSample
   * offset by a further 5-position left shift for each subband. Also apply a
   * constant left-shift of 8 to turn the values into signed 24-bit values
   * left-justified in the 32-bit ditherOutput variable. */
  m_ditherOutputs[HH] = ditherSample << leftJustifyShift;
  m_ditherOutputs[HL] = ditherSample << (5 + leftJustifyShift);
  m_ditherOutputs[LH] = ditherSample << (10 + leftJustifyShift);
  m_ditherOutputs[LL] = ditherSample << (15 + leftJustifyShift);

  return m_dithSyncRandBit;
};

#endif  // DITHERGENERATOR_H