3 * Copyright (C) 2017 Daniil Cherednik
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "libavutil/mem.h"
29 typedef int32_t premultiplied_coeffs
[10];
31 //assume we have DCA_ADPCM_COEFFS values before x
32 static inline int64_t calc_corr(const int32_t *x
, int len
, int j
, int k
)
36 for (n
= 0; n
< len
; n
++)
37 s
+= MUL64(x
[n
-j
], x
[n
-k
]);
41 static inline int64_t apply_filter(const int16_t a
[DCA_ADPCM_COEFFS
], const int64_t corr
[15], const int32_t aa
[10])
48 tmp
+= MUL64(a
[0], corr
[1]);
49 tmp
+= MUL64(a
[1], corr
[2]);
50 tmp
+= MUL64(a
[2], corr
[3]);
51 tmp
+= MUL64(a
[3], corr
[4]);
53 tmp
= norm__(tmp
, 13);
59 tmp
+= MUL64(corr
[5], aa
[0]);
60 tmp
+= MUL64(corr
[6], aa
[1]);
61 tmp
+= MUL64(corr
[7], aa
[2]);
62 tmp
+= MUL64(corr
[8], aa
[3]);
64 tmp
+= MUL64(corr
[9], aa
[4]);
65 tmp
+= MUL64(corr
[10], aa
[5]);
66 tmp
+= MUL64(corr
[11], aa
[6]);
68 tmp
+= MUL64(corr
[12], aa
[7]);
69 tmp
+= MUL64(corr
[13], aa
[8]);
71 tmp
+= MUL64(corr
[14], aa
[9]);
73 tmp
= norm__(tmp
, 26);
80 static int64_t find_best_filter(const DCAADPCMEncContext
*s
, const int32_t *in
, int len
)
82 const premultiplied_coeffs
*precalc_data
= s
->private_data
;
86 int64_t min_err
= 1ll << 62;
89 for (i
= 0; i
<= DCA_ADPCM_COEFFS
; i
++)
90 for (j
= i
; j
<= DCA_ADPCM_COEFFS
; j
++)
91 corr
[k
++] = calc_corr(in
+4, len
, i
, j
);
93 for (i
= 0; i
< DCA_ADPCM_VQCODEBOOK_SZ
; i
++) {
94 err
= apply_filter(ff_dca_adpcm_vb
[i
], corr
, *precalc_data
);
105 static inline int64_t calc_prediction_gain(int pred_vq
, const int32_t *in
, int32_t *out
, int len
)
110 int64_t signal_energy
= 0;
111 int64_t error_energy
= 0;
113 for (i
= 0; i
< len
; i
++) {
114 error
= in
[DCA_ADPCM_COEFFS
+ i
] - ff_dcaadpcm_predict(pred_vq
, in
+ i
);
116 signal_energy
+= MUL64(in
[DCA_ADPCM_COEFFS
+ i
], in
[DCA_ADPCM_COEFFS
+ i
]);
117 error_energy
+= MUL64(error
, error
);
123 return signal_energy
/ error_energy
;
126 int ff_dcaadpcm_subband_analysis(const DCAADPCMEncContext
*s
, const int32_t *in
, int len
, int *diff
)
129 int32_t input_buffer
[16 + DCA_ADPCM_COEFFS
];
130 int32_t input_buffer2
[16 + DCA_ADPCM_COEFFS
];
136 for (i
= 0; i
< len
+ DCA_ADPCM_COEFFS
; i
++)
139 // normalize input to simplify apply_filter
140 shift_bits
= av_log2(max
) - 11;
142 for (i
= 0; i
< len
+ DCA_ADPCM_COEFFS
; i
++) {
143 input_buffer
[i
] = norm__(in
[i
], 7);
144 input_buffer2
[i
] = norm__(in
[i
], shift_bits
);
147 pred_vq
= find_best_filter(s
, input_buffer2
, len
);
152 pg
= calc_prediction_gain(pred_vq
, input_buffer
, diff
, len
);
154 // Greater than 10db (10*log(10)) prediction gain to use ADPCM.
159 for (i
= 0; i
< len
; i
++)
165 static void precalc(premultiplied_coeffs
*data
)
169 for (i
= 0; i
< DCA_ADPCM_VQCODEBOOK_SZ
; i
++) {
172 for (j
= 0; j
< DCA_ADPCM_COEFFS
; j
++) {
173 for (k
= j
; k
< DCA_ADPCM_COEFFS
; k
++) {
174 t
= (int32_t)ff_dca_adpcm_vb
[i
][j
] * (int32_t)ff_dca_adpcm_vb
[i
][k
];
184 int ff_dcaadpcm_do_real(int pred_vq_index
,
185 softfloat quant
, int32_t scale_factor
, int32_t step_size
,
186 const int32_t *prev_hist
, const int32_t *in
, int32_t *next_hist
, int32_t *out
,
187 int len
, int32_t peak
)
191 int32_t dequant_delta
;
192 int32_t work_bufer
[16 + DCA_ADPCM_COEFFS
];
194 memcpy(work_bufer
, prev_hist
, sizeof(int32_t) * DCA_ADPCM_COEFFS
);
196 for (i
= 0; i
< len
; i
++) {
197 work_bufer
[DCA_ADPCM_COEFFS
+ i
] = ff_dcaadpcm_predict(pred_vq_index
, &work_bufer
[i
]);
199 delta
= (int64_t)in
[i
] - ((int64_t)work_bufer
[DCA_ADPCM_COEFFS
+ i
] << 7);
201 out
[i
] = quantize_value(av_clip64(delta
, -peak
, peak
), quant
);
203 ff_dca_core_dequantize(&dequant_delta
, &out
[i
], step_size
, scale_factor
, 0, 1);
205 work_bufer
[DCA_ADPCM_COEFFS
+i
] += dequant_delta
;
208 memcpy(next_hist
, &work_bufer
[len
], sizeof(int32_t) * DCA_ADPCM_COEFFS
);
213 av_cold
int ff_dcaadpcm_init(DCAADPCMEncContext
*s
)
218 s
->private_data
= av_malloc(sizeof(premultiplied_coeffs
) * DCA_ADPCM_VQCODEBOOK_SZ
);
219 if (!s
->private_data
)
220 return AVERROR(ENOMEM
);
222 precalc(s
->private_data
);
226 av_cold
void ff_dcaadpcm_free(DCAADPCMEncContext
*s
)
231 av_freep(&s
->private_data
);