You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
5.9KB

  1. /*
  2. * DCA ADPCM engine
  3. * Copyright (C) 2017 Daniil Cherednik
  4. *
  5. * This file is part of FFmpeg.
  6. *
  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.
  11. *
  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.
  16. *
  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
  20. */
  21. #include "dcaadpcm.h"
  22. #include "dcaenc.h"
  23. #include "dca_core.h"
  24. #include "mathops.h"
  25. typedef int32_t premultiplied_coeffs[10];
  26. //assume we have DCA_ADPCM_COEFFS values before x
  27. static inline int64_t calc_corr(const int32_t *x, int len, int j, int k)
  28. {
  29. int n;
  30. int64_t s = 0;
  31. for (n = 0; n < len; n++)
  32. s += MUL64(x[n-j], x[n-k]);
  33. return s;
  34. }
  35. static inline int64_t apply_filter(const int16_t a[DCA_ADPCM_COEFFS], const int64_t corr[15], const int32_t aa[10])
  36. {
  37. int64_t err = 0;
  38. int64_t tmp = 0;
  39. err = corr[0];
  40. tmp += MUL64(a[0], corr[1]);
  41. tmp += MUL64(a[1], corr[2]);
  42. tmp += MUL64(a[2], corr[3]);
  43. tmp += MUL64(a[3], corr[4]);
  44. tmp = norm__(tmp, 13);
  45. tmp += tmp;
  46. err -= tmp;
  47. tmp = 0;
  48. tmp += MUL64(corr[5], aa[0]);
  49. tmp += MUL64(corr[6], aa[1]);
  50. tmp += MUL64(corr[7], aa[2]);
  51. tmp += MUL64(corr[8], aa[3]);
  52. tmp += MUL64(corr[9], aa[4]);
  53. tmp += MUL64(corr[10], aa[5]);
  54. tmp += MUL64(corr[11], aa[6]);
  55. tmp += MUL64(corr[12], aa[7]);
  56. tmp += MUL64(corr[13], aa[8]);
  57. tmp += MUL64(corr[14], aa[9]);
  58. tmp = norm__(tmp, 26);
  59. err += tmp;
  60. return llabs(err);
  61. }
  62. static int64_t find_best_filter(const DCAADPCMEncContext *s, const int32_t *in, int len)
  63. {
  64. const premultiplied_coeffs *precalc_data = s->private_data;
  65. int i, j, k = 0;
  66. int vq = -1;
  67. int64_t err;
  68. int64_t min_err = 1ll << 62;
  69. int64_t corr[15];
  70. for (i = 0; i <= DCA_ADPCM_COEFFS; i++)
  71. for (j = i; j <= DCA_ADPCM_COEFFS; j++)
  72. corr[k++] = calc_corr(in+4, len, i, j);
  73. for (i = 0; i < DCA_ADPCM_VQCODEBOOK_SZ; i++) {
  74. err = apply_filter(ff_dca_adpcm_vb[i], corr, *precalc_data);
  75. if (err < min_err) {
  76. min_err = err;
  77. vq = i;
  78. }
  79. precalc_data++;
  80. }
  81. return vq;
  82. }
  83. static inline int64_t calc_prediction_gain(int pred_vq, const int32_t *in, int32_t *out, int len)
  84. {
  85. int i;
  86. int32_t error;
  87. int64_t signal_energy = 0;
  88. int64_t error_energy = 0;
  89. for (i = 0; i < len; i++) {
  90. error = in[DCA_ADPCM_COEFFS + i] - ff_dcaadpcm_predict(pred_vq, in + i);
  91. out[i] = error;
  92. signal_energy += MUL64(in[DCA_ADPCM_COEFFS + i], in[DCA_ADPCM_COEFFS + i]);
  93. error_energy += MUL64(error, error);
  94. }
  95. if (!error_energy)
  96. return -1;
  97. return signal_energy / error_energy;
  98. }
  99. int ff_dcaadpcm_subband_analysis(const DCAADPCMEncContext *s, const int32_t *in, int len, int *diff)
  100. {
  101. int pred_vq, i;
  102. int32_t input_buffer[16 + DCA_ADPCM_COEFFS];
  103. int32_t input_buffer2[16 + DCA_ADPCM_COEFFS];
  104. int32_t max = 0;
  105. int shift_bits;
  106. uint64_t pg = 0;
  107. for (i = 0; i < len + DCA_ADPCM_COEFFS; i++)
  108. max |= FFABS(in[i]);
  109. // normalize input to simplify apply_filter
  110. shift_bits = av_log2(max) - 11;
  111. for (i = 0; i < len + DCA_ADPCM_COEFFS; i++) {
  112. input_buffer[i] = norm__(in[i], 7);
  113. input_buffer2[i] = norm__(in[i], shift_bits);
  114. }
  115. pred_vq = find_best_filter(s, input_buffer2, len);
  116. if (pred_vq < 0)
  117. return -1;
  118. pg = calc_prediction_gain(pred_vq, input_buffer, diff, len);
  119. // Greater than 10db (10*log(10)) prediction gain to use ADPCM.
  120. // TODO: Tune it.
  121. if (pg < 10)
  122. return -1;
  123. for (i = 0; i < len; i++)
  124. diff[i] <<= 7;
  125. return pred_vq;
  126. }
  127. static void precalc(premultiplied_coeffs *data)
  128. {
  129. int i, j, k;
  130. for (i = 0; i < DCA_ADPCM_VQCODEBOOK_SZ; i++) {
  131. int id = 0;
  132. int32_t t = 0;
  133. for (j = 0; j < DCA_ADPCM_COEFFS; j++) {
  134. for (k = j; k < DCA_ADPCM_COEFFS; k++) {
  135. t = (int32_t)ff_dca_adpcm_vb[i][j] * (int32_t)ff_dca_adpcm_vb[i][k];
  136. if (j != k)
  137. t *= 2;
  138. (*data)[id++] = t;
  139. }
  140. }
  141. data++;
  142. }
  143. }
  144. int ff_dcaadpcm_do_real(int pred_vq_index,
  145. softfloat quant, int32_t scale_factor, int32_t step_size,
  146. const int32_t *prev_hist, const int32_t *in, int32_t *next_hist, int32_t *out,
  147. int len, int32_t peak)
  148. {
  149. int i;
  150. int64_t delta;
  151. int32_t dequant_delta;
  152. int32_t work_bufer[16 + DCA_ADPCM_COEFFS];
  153. memcpy(work_bufer, prev_hist, sizeof(int32_t) * DCA_ADPCM_COEFFS);
  154. for (i = 0; i < len; i++) {
  155. work_bufer[DCA_ADPCM_COEFFS + i] = ff_dcaadpcm_predict(pred_vq_index, &work_bufer[i]);
  156. delta = (int64_t)in[i] - ((int64_t)work_bufer[DCA_ADPCM_COEFFS + i] << 7);
  157. out[i] = quantize_value(av_clip64(delta, -peak, peak), quant);
  158. ff_dca_core_dequantize(&dequant_delta, &out[i], step_size, scale_factor, 0, 1);
  159. work_bufer[DCA_ADPCM_COEFFS+i] += dequant_delta;
  160. }
  161. memcpy(next_hist, &work_bufer[len], sizeof(int32_t) * DCA_ADPCM_COEFFS);
  162. return 0;
  163. }
  164. av_cold int ff_dcaadpcm_init(DCAADPCMEncContext *s)
  165. {
  166. if (!s)
  167. return -1;
  168. s->private_data = av_malloc(sizeof(premultiplied_coeffs) * DCA_ADPCM_VQCODEBOOK_SZ);
  169. if (!s->private_data)
  170. return AVERROR(ENOMEM);
  171. precalc(s->private_data);
  172. return 0;
  173. }
  174. av_cold void ff_dcaadpcm_free(DCAADPCMEncContext *s)
  175. {
  176. if (!s)
  177. return;
  178. av_freep(&s->private_data);
  179. }