1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * DCA ADPCM engine 3cabdff1aSopenharmony_ci * Copyright (C) 2017 Daniil Cherednik 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include "dcaadpcm.h" 24cabdff1aSopenharmony_ci#include "dcaenc.h" 25cabdff1aSopenharmony_ci#include "dca_core.h" 26cabdff1aSopenharmony_ci#include "mathops.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_citypedef int32_t premultiplied_coeffs[10]; 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci//assume we have DCA_ADPCM_COEFFS values before x 31cabdff1aSopenharmony_cistatic inline int64_t calc_corr(const int32_t *x, int len, int j, int k) 32cabdff1aSopenharmony_ci{ 33cabdff1aSopenharmony_ci int n; 34cabdff1aSopenharmony_ci int64_t s = 0; 35cabdff1aSopenharmony_ci for (n = 0; n < len; n++) 36cabdff1aSopenharmony_ci s += MUL64(x[n-j], x[n-k]); 37cabdff1aSopenharmony_ci return s; 38cabdff1aSopenharmony_ci} 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_cistatic inline int64_t apply_filter(const int16_t a[DCA_ADPCM_COEFFS], const int64_t corr[15], const int32_t aa[10]) 41cabdff1aSopenharmony_ci{ 42cabdff1aSopenharmony_ci int64_t err = 0; 43cabdff1aSopenharmony_ci int64_t tmp = 0; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci err = corr[0]; 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ci tmp += MUL64(a[0], corr[1]); 48cabdff1aSopenharmony_ci tmp += MUL64(a[1], corr[2]); 49cabdff1aSopenharmony_ci tmp += MUL64(a[2], corr[3]); 50cabdff1aSopenharmony_ci tmp += MUL64(a[3], corr[4]); 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci tmp = norm__(tmp, 13); 53cabdff1aSopenharmony_ci tmp += tmp; 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci err -= tmp; 56cabdff1aSopenharmony_ci tmp = 0; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci tmp += MUL64(corr[5], aa[0]); 59cabdff1aSopenharmony_ci tmp += MUL64(corr[6], aa[1]); 60cabdff1aSopenharmony_ci tmp += MUL64(corr[7], aa[2]); 61cabdff1aSopenharmony_ci tmp += MUL64(corr[8], aa[3]); 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci tmp += MUL64(corr[9], aa[4]); 64cabdff1aSopenharmony_ci tmp += MUL64(corr[10], aa[5]); 65cabdff1aSopenharmony_ci tmp += MUL64(corr[11], aa[6]); 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci tmp += MUL64(corr[12], aa[7]); 68cabdff1aSopenharmony_ci tmp += MUL64(corr[13], aa[8]); 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci tmp += MUL64(corr[14], aa[9]); 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci tmp = norm__(tmp, 26); 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci err += tmp; 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_ci return llabs(err); 77cabdff1aSopenharmony_ci} 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_cistatic int64_t find_best_filter(const DCAADPCMEncContext *s, const int32_t *in, int len) 80cabdff1aSopenharmony_ci{ 81cabdff1aSopenharmony_ci const premultiplied_coeffs *precalc_data = s->private_data; 82cabdff1aSopenharmony_ci int i, j, k = 0; 83cabdff1aSopenharmony_ci int vq = -1; 84cabdff1aSopenharmony_ci int64_t err; 85cabdff1aSopenharmony_ci int64_t min_err = 1ll << 62; 86cabdff1aSopenharmony_ci int64_t corr[15]; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci for (i = 0; i <= DCA_ADPCM_COEFFS; i++) 89cabdff1aSopenharmony_ci for (j = i; j <= DCA_ADPCM_COEFFS; j++) 90cabdff1aSopenharmony_ci corr[k++] = calc_corr(in+4, len, i, j); 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_ci for (i = 0; i < DCA_ADPCM_VQCODEBOOK_SZ; i++) { 93cabdff1aSopenharmony_ci err = apply_filter(ff_dca_adpcm_vb[i], corr, *precalc_data); 94cabdff1aSopenharmony_ci if (err < min_err) { 95cabdff1aSopenharmony_ci min_err = err; 96cabdff1aSopenharmony_ci vq = i; 97cabdff1aSopenharmony_ci } 98cabdff1aSopenharmony_ci precalc_data++; 99cabdff1aSopenharmony_ci } 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci return vq; 102cabdff1aSopenharmony_ci} 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_cistatic inline int64_t calc_prediction_gain(int pred_vq, const int32_t *in, int32_t *out, int len) 105cabdff1aSopenharmony_ci{ 106cabdff1aSopenharmony_ci int i; 107cabdff1aSopenharmony_ci int32_t error; 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci int64_t signal_energy = 0; 110cabdff1aSopenharmony_ci int64_t error_energy = 0; 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ci for (i = 0; i < len; i++) { 113cabdff1aSopenharmony_ci error = in[DCA_ADPCM_COEFFS + i] - ff_dcaadpcm_predict(pred_vq, in + i); 114cabdff1aSopenharmony_ci out[i] = error; 115cabdff1aSopenharmony_ci signal_energy += MUL64(in[DCA_ADPCM_COEFFS + i], in[DCA_ADPCM_COEFFS + i]); 116cabdff1aSopenharmony_ci error_energy += MUL64(error, error); 117cabdff1aSopenharmony_ci } 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ci if (!error_energy) 120cabdff1aSopenharmony_ci return -1; 121cabdff1aSopenharmony_ci 122cabdff1aSopenharmony_ci return signal_energy / error_energy; 123cabdff1aSopenharmony_ci} 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ciint ff_dcaadpcm_subband_analysis(const DCAADPCMEncContext *s, const int32_t *in, int len, int *diff) 126cabdff1aSopenharmony_ci{ 127cabdff1aSopenharmony_ci int pred_vq, i; 128cabdff1aSopenharmony_ci int32_t input_buffer[16 + DCA_ADPCM_COEFFS]; 129cabdff1aSopenharmony_ci int32_t input_buffer2[16 + DCA_ADPCM_COEFFS]; 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci int32_t max = 0; 132cabdff1aSopenharmony_ci int shift_bits; 133cabdff1aSopenharmony_ci uint64_t pg = 0; 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_ci for (i = 0; i < len + DCA_ADPCM_COEFFS; i++) 136cabdff1aSopenharmony_ci max |= FFABS(in[i]); 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci // normalize input to simplify apply_filter 139cabdff1aSopenharmony_ci shift_bits = av_log2(max) - 11; 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci for (i = 0; i < len + DCA_ADPCM_COEFFS; i++) { 142cabdff1aSopenharmony_ci input_buffer[i] = norm__(in[i], 7); 143cabdff1aSopenharmony_ci input_buffer2[i] = norm__(in[i], shift_bits); 144cabdff1aSopenharmony_ci } 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci pred_vq = find_best_filter(s, input_buffer2, len); 147cabdff1aSopenharmony_ci 148cabdff1aSopenharmony_ci if (pred_vq < 0) 149cabdff1aSopenharmony_ci return -1; 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci pg = calc_prediction_gain(pred_vq, input_buffer, diff, len); 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci // Greater than 10db (10*log(10)) prediction gain to use ADPCM. 154cabdff1aSopenharmony_ci // TODO: Tune it. 155cabdff1aSopenharmony_ci if (pg < 10) 156cabdff1aSopenharmony_ci return -1; 157cabdff1aSopenharmony_ci 158cabdff1aSopenharmony_ci for (i = 0; i < len; i++) 159cabdff1aSopenharmony_ci diff[i] <<= 7; 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci return pred_vq; 162cabdff1aSopenharmony_ci} 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_cistatic void precalc(premultiplied_coeffs *data) 165cabdff1aSopenharmony_ci{ 166cabdff1aSopenharmony_ci int i, j, k; 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci for (i = 0; i < DCA_ADPCM_VQCODEBOOK_SZ; i++) { 169cabdff1aSopenharmony_ci int id = 0; 170cabdff1aSopenharmony_ci int32_t t = 0; 171cabdff1aSopenharmony_ci for (j = 0; j < DCA_ADPCM_COEFFS; j++) { 172cabdff1aSopenharmony_ci for (k = j; k < DCA_ADPCM_COEFFS; k++) { 173cabdff1aSopenharmony_ci t = (int32_t)ff_dca_adpcm_vb[i][j] * (int32_t)ff_dca_adpcm_vb[i][k]; 174cabdff1aSopenharmony_ci if (j != k) 175cabdff1aSopenharmony_ci t *= 2; 176cabdff1aSopenharmony_ci (*data)[id++] = t; 177cabdff1aSopenharmony_ci } 178cabdff1aSopenharmony_ci } 179cabdff1aSopenharmony_ci data++; 180cabdff1aSopenharmony_ci } 181cabdff1aSopenharmony_ci} 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_ciint ff_dcaadpcm_do_real(int pred_vq_index, 184cabdff1aSopenharmony_ci softfloat quant, int32_t scale_factor, int32_t step_size, 185cabdff1aSopenharmony_ci const int32_t *prev_hist, const int32_t *in, int32_t *next_hist, int32_t *out, 186cabdff1aSopenharmony_ci int len, int32_t peak) 187cabdff1aSopenharmony_ci{ 188cabdff1aSopenharmony_ci int i; 189cabdff1aSopenharmony_ci int64_t delta; 190cabdff1aSopenharmony_ci int32_t dequant_delta; 191cabdff1aSopenharmony_ci int32_t work_bufer[16 + DCA_ADPCM_COEFFS]; 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ci memcpy(work_bufer, prev_hist, sizeof(int32_t) * DCA_ADPCM_COEFFS); 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci for (i = 0; i < len; i++) { 196cabdff1aSopenharmony_ci work_bufer[DCA_ADPCM_COEFFS + i] = ff_dcaadpcm_predict(pred_vq_index, &work_bufer[i]); 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_ci delta = (int64_t)in[i] - ((int64_t)work_bufer[DCA_ADPCM_COEFFS + i] << 7); 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci out[i] = quantize_value(av_clip64(delta, -peak, peak), quant); 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci ff_dca_core_dequantize(&dequant_delta, &out[i], step_size, scale_factor, 0, 1); 203cabdff1aSopenharmony_ci 204cabdff1aSopenharmony_ci work_bufer[DCA_ADPCM_COEFFS+i] += dequant_delta; 205cabdff1aSopenharmony_ci } 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci memcpy(next_hist, &work_bufer[len], sizeof(int32_t) * DCA_ADPCM_COEFFS); 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci return 0; 210cabdff1aSopenharmony_ci} 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ciav_cold int ff_dcaadpcm_init(DCAADPCMEncContext *s) 213cabdff1aSopenharmony_ci{ 214cabdff1aSopenharmony_ci if (!s) 215cabdff1aSopenharmony_ci return -1; 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci s->private_data = av_malloc(sizeof(premultiplied_coeffs) * DCA_ADPCM_VQCODEBOOK_SZ); 218cabdff1aSopenharmony_ci if (!s->private_data) 219cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci precalc(s->private_data); 222cabdff1aSopenharmony_ci return 0; 223cabdff1aSopenharmony_ci} 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ciav_cold void ff_dcaadpcm_free(DCAADPCMEncContext *s) 226cabdff1aSopenharmony_ci{ 227cabdff1aSopenharmony_ci if (!s) 228cabdff1aSopenharmony_ci return; 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci av_freep(&s->private_data); 231cabdff1aSopenharmony_ci} 232