| Line | Branch | Exec | Source | 
|---|---|---|---|
| 1 | /* | ||
| 2 | * Audio Processing Technology codec for Bluetooth (aptX) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2017 Aurelien Jacobs <aurel@gnuage.org> | ||
| 5 | * | ||
| 6 | * This file is part of FFmpeg. | ||
| 7 | * | ||
| 8 | * FFmpeg is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU Lesser General Public | ||
| 10 | * License as published by the Free Software Foundation; either | ||
| 11 | * version 2.1 of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | * Lesser General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU Lesser General Public | ||
| 19 | * License along with FFmpeg; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef AVCODEC_APTX_H | ||
| 24 | #define AVCODEC_APTX_H | ||
| 25 | |||
| 26 | #include "libavutil/intreadwrite.h" | ||
| 27 | #include "avcodec.h" | ||
| 28 | #include "mathops.h" | ||
| 29 | |||
| 30 | |||
| 31 | enum channels { | ||
| 32 | LEFT, | ||
| 33 | RIGHT, | ||
| 34 | NB_CHANNELS | ||
| 35 | }; | ||
| 36 | |||
| 37 | enum subbands { | ||
| 38 | LF, // Low Frequency (0-5.5 kHz) | ||
| 39 | MLF, // Medium-Low Frequency (5.5-11kHz) | ||
| 40 | MHF, // Medium-High Frequency (11-16.5kHz) | ||
| 41 | HF, // High Frequency (16.5-22kHz) | ||
| 42 | NB_SUBBANDS | ||
| 43 | }; | ||
| 44 | |||
| 45 | #define NB_FILTERS 2 | ||
| 46 | #define FILTER_TAPS 16 | ||
| 47 | |||
| 48 | typedef struct { | ||
| 49 | int pos; | ||
| 50 | int32_t buffer[2*FILTER_TAPS]; | ||
| 51 | } FilterSignal; | ||
| 52 | |||
| 53 | typedef struct { | ||
| 54 | FilterSignal outer_filter_signal[NB_FILTERS]; | ||
| 55 | FilterSignal inner_filter_signal[NB_FILTERS][NB_FILTERS]; | ||
| 56 | } QMFAnalysis; | ||
| 57 | |||
| 58 | typedef struct { | ||
| 59 | int32_t quantized_sample; | ||
| 60 | int32_t quantized_sample_parity_change; | ||
| 61 | int32_t error; | ||
| 62 | } Quantize; | ||
| 63 | |||
| 64 | typedef struct { | ||
| 65 | int32_t quantization_factor; | ||
| 66 | int32_t factor_select; | ||
| 67 | int32_t reconstructed_difference; | ||
| 68 | } InvertQuantize; | ||
| 69 | |||
| 70 | typedef struct { | ||
| 71 | int32_t prev_sign[2]; | ||
| 72 | int32_t s_weight[2]; | ||
| 73 | int32_t d_weight[24]; | ||
| 74 | int32_t pos; | ||
| 75 | int32_t reconstructed_differences[48]; | ||
| 76 | int32_t previous_reconstructed_sample; | ||
| 77 | int32_t predicted_difference; | ||
| 78 | int32_t predicted_sample; | ||
| 79 | } Prediction; | ||
| 80 | |||
| 81 | typedef struct { | ||
| 82 | int32_t codeword_history; | ||
| 83 | int32_t dither_parity; | ||
| 84 | int32_t dither[NB_SUBBANDS]; | ||
| 85 | |||
| 86 | QMFAnalysis qmf; | ||
| 87 | Quantize quantize[NB_SUBBANDS]; | ||
| 88 | InvertQuantize invert_quantize[NB_SUBBANDS]; | ||
| 89 | Prediction prediction[NB_SUBBANDS]; | ||
| 90 | } Channel; | ||
| 91 | |||
| 92 | typedef struct { | ||
| 93 | int hd; | ||
| 94 | int block_size; | ||
| 95 | int32_t sync_idx; | ||
| 96 | Channel channels[NB_CHANNELS]; | ||
| 97 | } AptXContext; | ||
| 98 | |||
| 99 | typedef const struct { | ||
| 100 | const int32_t *quantize_intervals; | ||
| 101 | const int32_t *invert_quantize_dither_factors; | ||
| 102 | const int32_t *quantize_dither_factors; | ||
| 103 | const int16_t *quantize_factor_select_offset; | ||
| 104 | int tables_size; | ||
| 105 | int32_t factor_max; | ||
| 106 | int32_t prediction_order; | ||
| 107 | } ConstTables; | ||
| 108 | |||
| 109 | extern ConstTables ff_aptx_quant_tables[2][NB_SUBBANDS]; | ||
| 110 | |||
| 111 | /* Rounded right shift with optional clipping */ | ||
| 112 | #define RSHIFT_SIZE(size) \ | ||
| 113 | av_always_inline \ | ||
| 114 | static int##size##_t rshift##size(int##size##_t value, int shift) \ | ||
| 115 | { \ | ||
| 116 | int##size##_t rounding = (int##size##_t)1 << (shift - 1); \ | ||
| 117 | int##size##_t mask = ((int##size##_t)1 << (shift + 1)) - 1; \ | ||
| 118 | return ((value + rounding) >> shift) - ((value & mask) == rounding); \ | ||
| 119 | } \ | ||
| 120 | av_always_inline \ | ||
| 121 | static int##size##_t rshift##size##_clip24(int##size##_t value, int shift) \ | ||
| 122 | { \ | ||
| 123 | return av_clip_intp2(rshift##size(value, shift), 23); \ | ||
| 124 | } | ||
| 125 | 36961712 | RSHIFT_SIZE(32) | |
| 126 | 37506752 | RSHIFT_SIZE(64) | |
| 127 | |||
| 128 | /* | ||
| 129 | * Convolution filter coefficients for the outer QMF of the QMF tree. | ||
| 130 | * The 2 sets are a mirror of each other. | ||
| 131 | */ | ||
| 132 | static const int32_t aptx_qmf_outer_coeffs[NB_FILTERS][FILTER_TAPS] = { | ||
| 133 | { | ||
| 134 | 730, -413, -9611, 43626, -121026, 269973, -585547, 2801966, | ||
| 135 | 697128, -160481, 27611, 8478, -10043, 3511, 688, -897, | ||
| 136 | }, | ||
| 137 | { | ||
| 138 | -897, 688, 3511, -10043, 8478, 27611, -160481, 697128, | ||
| 139 | 2801966, -585547, 269973, -121026, 43626, -9611, -413, 730, | ||
| 140 | }, | ||
| 141 | }; | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Convolution filter coefficients for the inner QMF of the QMF tree. | ||
| 145 | * The 2 sets are a mirror of each other. | ||
| 146 | */ | ||
| 147 | static const int32_t aptx_qmf_inner_coeffs[NB_FILTERS][FILTER_TAPS] = { | ||
| 148 | { | ||
| 149 | 1033, -584, -13592, 61697, -171156, 381799, -828088, 3962579, | ||
| 150 | 985888, -226954, 39048, 11990, -14203, 4966, 973, -1268, | ||
| 151 | }, | ||
| 152 | { | ||
| 153 | -1268, 973, 4966, -14203, 11990, 39048, -226954, 985888, | ||
| 154 | 3962579, -828088, 381799, -171156, 61697, -13592, -584, 1033, | ||
| 155 | }, | ||
| 156 | }; | ||
| 157 | |||
| 158 | /* | ||
| 159 | * Push one sample into a circular signal buffer. | ||
| 160 | */ | ||
| 161 | av_always_inline | ||
| 162 | 3458112 | static void aptx_qmf_filter_signal_push(FilterSignal *signal, int32_t sample) | |
| 163 | { | ||
| 164 | 3458112 | signal->buffer[signal->pos ] = sample; | |
| 165 | 3458112 | signal->buffer[signal->pos+FILTER_TAPS] = sample; | |
| 166 | 3458112 | signal->pos = (signal->pos + 1) & (FILTER_TAPS - 1); | |
| 167 | 3458112 | } | |
| 168 | |||
| 169 | /* | ||
| 170 | * Compute the convolution of the signal with the coefficients, and reduce | ||
| 171 | * to 24 bits by applying the specified right shifting. | ||
| 172 | */ | ||
| 173 | av_always_inline | ||
| 174 | 3458112 | static int32_t aptx_qmf_convolution(FilterSignal *signal, | |
| 175 | const int32_t coeffs[FILTER_TAPS], | ||
| 176 | int shift) | ||
| 177 | { | ||
| 178 | 3458112 | int32_t *sig = &signal->buffer[signal->pos]; | |
| 179 | 3458112 | int64_t e = 0; | |
| 180 | int i; | ||
| 181 | |||
| 182 | 
        2/2✓ Branch 0 taken 55329792 times. 
          ✓ Branch 1 taken 3458112 times. 
         | 
      58787904 | for (i = 0; i < FILTER_TAPS; i++) | 
| 183 | 55329792 | e += MUL64(sig[i], coeffs[i]); | |
| 184 | |||
| 185 | 3458112 | return rshift64_clip24(e, shift); | |
| 186 | } | ||
| 187 | |||
| 188 | 1283480 | static inline int32_t aptx_quantized_parity(Channel *channel) | |
| 189 | { | ||
| 190 | 1283480 | int32_t parity = channel->dither_parity; | |
| 191 | int subband; | ||
| 192 | |||
| 193 | 
        2/2✓ Branch 0 taken 5133920 times. 
          ✓ Branch 1 taken 1283480 times. 
         | 
      6417400 | for (subband = 0; subband < NB_SUBBANDS; subband++) | 
| 194 | 5133920 | parity ^= channel->quantize[subband].quantized_sample; | |
| 195 | |||
| 196 | 1283480 | return parity & 1; | |
| 197 | } | ||
| 198 | |||
| 199 | /* For each sample, ensure that the parity of all subbands of all channels | ||
| 200 | * is 0 except once every 8 samples where the parity is forced to 1. */ | ||
| 201 | 216132 | static inline int aptx_check_parity(Channel channels[NB_CHANNELS], int32_t *idx) | |
| 202 | { | ||
| 203 | 216132 | int32_t parity = aptx_quantized_parity(&channels[LEFT]) | |
| 204 | 216132 | ^ aptx_quantized_parity(&channels[RIGHT]); | |
| 205 | |||
| 206 | 216132 | int eighth = *idx == 7; | |
| 207 | 216132 | *idx = (*idx + 1) & 7; | |
| 208 | |||
| 209 | 216132 | return parity ^ eighth; | |
| 210 | } | ||
| 211 | |||
| 212 | void ff_aptx_invert_quantize_and_prediction(Channel *channel, int hd); | ||
| 213 | void ff_aptx_generate_dither(Channel *channel); | ||
| 214 | |||
| 215 | int ff_aptx_init(AVCodecContext *avctx); | ||
| 216 | |||
| 217 | #endif /* AVCODEC_APTX_H */ | ||
| 218 |