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 optionnal 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 |