MythTV  master
audioconvert.cpp
Go to the documentation of this file.
1 
2 /*
3  * Class AudioConvert
4  * Created by Jean-Yves Avenard on 10/06/13.
5  *
6  * Copyright (C) Bubblestuff Pty Ltd 2013
7  * Copyright (C) foobum@gmail.com 2010
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 #include <cinttypes>
25 #include <cmath>
26 #include <sys/types.h>
27 
28 #include "mythconfig.h"
29 #include "mythlogging.h"
30 #include "mythaverror.h"
31 #include "audioconvert.h"
32 
33 extern "C" {
34 #include "libavcodec/avcodec.h"
35 #include "libswresample/swresample.h"
36 }
37 
38 #define LOC QString("AudioConvert: ")
39 
40 #define ISALIGN(x) (((unsigned long)(x) & 0xf) == 0)
41 
42 #if ARCH_X86
43 static int has_sse2 = -1;
44 
45 // Check cpuid for SSE2 support on x86 / x86_64
46 static inline bool sse_check()
47 {
48  if (has_sse2 != -1)
49  return (bool)has_sse2;
50  __asm__(
51  // -fPIC - we may not clobber ebx/rbx
52 #if ARCH_X86_64
53  "push %%rbx \n\t"
54 #else
55  "push %%ebx \n\t"
56 #endif
57  "mov $1, %%eax \n\t"
58  "cpuid \n\t"
59  "and $0x4000000, %%edx \n\t"
60  "shr $26, %%edx \n\t"
61 #if ARCH_X86_64
62  "pop %%rbx \n\t"
63 #else
64  "pop %%ebx \n\t"
65 #endif
66  :"=d"(has_sse2)
67  ::"%eax","%ecx"
68  );
69  return (bool)has_sse2;
70 }
71 #endif //ARCH_x86
72 
73 #if !HAVE_LRINTF
74 static av_always_inline av_const long int lrintf(float x)
75 {
76  return (int)(rint(x));
77 }
78 #endif /* HAVE_LRINTF */
79 
80 static inline float clipcheck(float f)
81 {
82  if (f > 1.0F) f = 1.0F;
83  else if (f < -1.0F) f = -1.0F;
84  return f;
85 }
86 
87 /*
88  The SSE code processes 16 bytes at a time and leaves any remainder for the C
89  */
90 
91 static int toFloat8(float* out, const uchar* in, int len)
92 {
93  int i = 0;
94  float f = 1.0F / ((1<<7));
95 
96 #if ARCH_X86
97  if (sse_check() && len >= 16)
98  {
99  int loops = len >> 4;
100  i = loops << 4;
101  int a = 0x80808080;
102 
103  __asm__ volatile (
104  "movd %3, %%xmm0 \n\t"
105  "movd %4, %%xmm7 \n\t"
106  "punpckldq %%xmm0, %%xmm0 \n\t"
107  "punpckldq %%xmm7, %%xmm7 \n\t"
108  "punpckldq %%xmm0, %%xmm0 \n\t"
109  "punpckldq %%xmm7, %%xmm7 \n\t"
110  "1: \n\t"
111  "movdqu (%1), %%xmm1 \n\t"
112  "xorpd %%xmm2, %%xmm2 \n\t"
113  "xorpd %%xmm3, %%xmm3 \n\t"
114  "psubb %%xmm0, %%xmm1 \n\t"
115  "xorpd %%xmm4, %%xmm4 \n\t"
116  "punpcklbw %%xmm1, %%xmm2 \n\t"
117  "xorpd %%xmm5, %%xmm5 \n\t"
118  "punpckhbw %%xmm1, %%xmm3 \n\t"
119  "punpcklwd %%xmm2, %%xmm4 \n\t"
120  "xorpd %%xmm6, %%xmm6 \n\t"
121  "punpckhwd %%xmm2, %%xmm5 \n\t"
122  "psrad $24, %%xmm4 \n\t"
123  "punpcklwd %%xmm3, %%xmm6 \n\t"
124  "psrad $24, %%xmm5 \n\t"
125  "punpckhwd %%xmm3, %%xmm1 \n\t"
126  "psrad $24, %%xmm6 \n\t"
127  "cvtdq2ps %%xmm4, %%xmm4 \n\t"
128  "psrad $24, %%xmm1 \n\t"
129  "cvtdq2ps %%xmm5, %%xmm5 \n\t"
130  "mulps %%xmm7, %%xmm4 \n\t"
131  "cvtdq2ps %%xmm6, %%xmm6 \n\t"
132  "mulps %%xmm7, %%xmm5 \n\t"
133  "movups %%xmm4, (%0) \n\t"
134  "cvtdq2ps %%xmm1, %%xmm1 \n\t"
135  "mulps %%xmm7, %%xmm6 \n\t"
136  "movups %%xmm5, 16(%0) \n\t"
137  "mulps %%xmm7, %%xmm1 \n\t"
138  "movups %%xmm6, 32(%0) \n\t"
139  "add $16, %1 \n\t"
140  "movups %%xmm1, 48(%0) \n\t"
141  "add $64, %0 \n\t"
142  "sub $1, %%ecx \n\t"
143  "jnz 1b \n\t"
144  :"+r"(out),"+r"(in)
145  :"c"(loops), "r"(a), "r"(f)
146  :"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7"
147  );
148  }
149 #endif //ARCH_x86
150  for (; i < len; i++)
151  *out++ = (*in++ - 0x80) * f;
152  return len << 2;
153 }
154 
155 /*
156  The SSE code processes 16 bytes at a time and leaves any remainder for the C
157  - there is no remainder in practice */
158 
159 static inline uchar clip_uchar(int a)
160 {
161  if (a&(~0xFF))
162  return (-a)>>31;
163  return a;
164 }
165 
166 static int fromFloat8(uchar* out, const float* in, int len)
167 {
168  int i = 0;
169  float f = (1<<7);
170 
171 #if ARCH_X86
172  if (sse_check() && len >= 16)
173  {
174  int loops = len >> 4;
175  i = loops << 4;
176  int a = 0x80808080;
177 
178  __asm__ volatile (
179  "movd %3, %%xmm0 \n\t"
180  "movd %4, %%xmm7 \n\t"
181  "punpckldq %%xmm0, %%xmm0 \n\t"
182  "punpckldq %%xmm7, %%xmm7 \n\t"
183  "punpckldq %%xmm0, %%xmm0 \n\t"
184  "punpckldq %%xmm7, %%xmm7 \n\t"
185  "1: \n\t"
186  "movups (%1), %%xmm1 \n\t"
187  "movups 16(%1), %%xmm2 \n\t"
188  "mulps %%xmm7, %%xmm1 \n\t"
189  "movups 32(%1), %%xmm3 \n\t"
190  "mulps %%xmm7, %%xmm2 \n\t"
191  "cvtps2dq %%xmm1, %%xmm1 \n\t"
192  "movups 48(%1), %%xmm4 \n\t"
193  "mulps %%xmm7, %%xmm3 \n\t"
194  "cvtps2dq %%xmm2, %%xmm2 \n\t"
195  "mulps %%xmm7, %%xmm4 \n\t"
196  "cvtps2dq %%xmm3, %%xmm3 \n\t"
197  "packssdw %%xmm2, %%xmm1 \n\t"
198  "cvtps2dq %%xmm4, %%xmm4 \n\t"
199  "packssdw %%xmm4, %%xmm3 \n\t"
200  "add $64, %1 \n\t"
201  "packsswb %%xmm3, %%xmm1 \n\t"
202  "paddb %%xmm0, %%xmm1 \n\t"
203  "movdqu %%xmm1, (%0) \n\t"
204  "add $16, %0 \n\t"
205  "sub $1, %%ecx \n\t"
206  "jnz 1b \n\t"
207  :"+r"(out),"+r"(in)
208  :"c"(loops), "r"(a), "r"(f)
209  :"xmm0","xmm1","xmm2","xmm3","xmm4","xmm7"
210  );
211  }
212 #endif //ARCH_x86
213  for (;i < len; i++)
214  *out++ = clip_uchar(lrintf(*in++ * f) + 0x80);
215  return len;
216 }
217 
218 static int toFloat16(float* out, const short* in, int len)
219 {
220  int i = 0;
221  float f = 1.0F / ((1<<15));
222 
223 #if ARCH_X86
224  if (sse_check() && len >= 16)
225  {
226  int loops = len >> 4;
227  i = loops << 4;
228 
229  __asm__ volatile (
230  "movd %3, %%xmm7 \n\t"
231  "punpckldq %%xmm7, %%xmm7 \n\t"
232  "punpckldq %%xmm7, %%xmm7 \n\t"
233  "1: \n\t"
234  "xorpd %%xmm2, %%xmm2 \n\t"
235  "movdqu (%1), %%xmm1 \n\t"
236  "xorpd %%xmm3, %%xmm3 \n\t"
237  "punpcklwd %%xmm1, %%xmm2 \n\t"
238  "movdqu 16(%1), %%xmm4 \n\t"
239  "punpckhwd %%xmm1, %%xmm3 \n\t"
240  "psrad $16, %%xmm2 \n\t"
241  "punpcklwd %%xmm4, %%xmm5 \n\t"
242  "psrad $16, %%xmm3 \n\t"
243  "cvtdq2ps %%xmm2, %%xmm2 \n\t"
244  "punpckhwd %%xmm4, %%xmm6 \n\t"
245  "psrad $16, %%xmm5 \n\t"
246  "mulps %%xmm7, %%xmm2 \n\t"
247  "cvtdq2ps %%xmm3, %%xmm3 \n\t"
248  "psrad $16, %%xmm6 \n\t"
249  "mulps %%xmm7, %%xmm3 \n\t"
250  "cvtdq2ps %%xmm5, %%xmm5 \n\t"
251  "movups %%xmm2, (%0) \n\t"
252  "cvtdq2ps %%xmm6, %%xmm6 \n\t"
253  "mulps %%xmm7, %%xmm5 \n\t"
254  "movups %%xmm3, 16(%0) \n\t"
255  "mulps %%xmm7, %%xmm6 \n\t"
256  "movups %%xmm5, 32(%0) \n\t"
257  "add $32, %1 \n\t"
258  "movups %%xmm6, 48(%0) \n\t"
259  "add $64, %0 \n\t"
260  "sub $1, %%ecx \n\t"
261  "jnz 1b \n\t"
262  :"+r"(out),"+r"(in)
263  :"c"(loops), "r"(f)
264  :"xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7"
265  );
266  }
267 #endif //ARCH_x86
268  for (; i < len; i++)
269  *out++ = *in++ * f;
270  return len << 2;
271 }
272 
273 static inline short clip_short(int a)
274 {
275  if ((a+0x8000) & ~0xFFFF)
276  return (a>>31) ^ 0x7FFF;
277  return a;
278 }
279 
280 static int fromFloat16(short* out, const float* in, int len)
281 {
282  int i = 0;
283  float f = (1<<15);
284 
285 #if ARCH_X86
286  if (sse_check() && len >= 16)
287  {
288  int loops = len >> 4;
289  i = loops << 4;
290 
291  __asm__ volatile (
292  "movd %3, %%xmm7 \n\t"
293  "punpckldq %%xmm7, %%xmm7 \n\t"
294  "punpckldq %%xmm7, %%xmm7 \n\t"
295  "1: \n\t"
296  "movups (%1), %%xmm1 \n\t"
297  "movups 16(%1), %%xmm2 \n\t"
298  "mulps %%xmm7, %%xmm1 \n\t"
299  "movups 32(%1), %%xmm3 \n\t"
300  "mulps %%xmm7, %%xmm2 \n\t"
301  "cvtps2dq %%xmm1, %%xmm1 \n\t"
302  "movups 48(%1), %%xmm4 \n\t"
303  "mulps %%xmm7, %%xmm3 \n\t"
304  "cvtps2dq %%xmm2, %%xmm2 \n\t"
305  "mulps %%xmm7, %%xmm4 \n\t"
306  "cvtps2dq %%xmm3, %%xmm3 \n\t"
307  "cvtps2dq %%xmm4, %%xmm4 \n\t"
308  "packssdw %%xmm2, %%xmm1 \n\t"
309  "packssdw %%xmm4, %%xmm3 \n\t"
310  "add $64, %1 \n\t"
311  "movdqu %%xmm1, (%0) \n\t"
312  "movdqu %%xmm3, 16(%0) \n\t"
313  "add $32, %0 \n\t"
314  "sub $1, %%ecx \n\t"
315  "jnz 1b \n\t"
316  :"+r"(out),"+r"(in)
317  :"c"(loops), "r"(f)
318  :"xmm1","xmm2","xmm3","xmm4","xmm7"
319  );
320  }
321 #endif //ARCH_x86
322  for (;i < len;i++)
323  *out++ = clip_short(lrintf(*in++ * f));
324  return len << 1;
325 }
326 
327 static int toFloat32(AudioFormat format, float* out, const int* in, int len)
328 {
329  int i = 0;
330  int bits = AudioOutputSettings::FormatToBits(format);
331  float f = 1.0F / ((uint)(1<<(bits-1)));
332  int shift = 32 - bits;
333 
334  if (format == FORMAT_S24LSB)
335  shift = 0;
336 
337 #if ARCH_X86
338  if (sse_check() && len >= 16)
339  {
340  int loops = len >> 4;
341  i = loops << 4;
342 
343  __asm__ volatile (
344  "movd %3, %%xmm7 \n\t"
345  "punpckldq %%xmm7, %%xmm7 \n\t"
346  "movd %4, %%xmm6 \n\t"
347  "punpckldq %%xmm7, %%xmm7 \n\t"
348  "1: \n\t"
349  "movdqu (%1), %%xmm1 \n\t"
350  "movdqu 16(%1), %%xmm2 \n\t"
351  "psrad %%xmm6, %%xmm1 \n\t"
352  "movdqu 32(%1), %%xmm3 \n\t"
353  "cvtdq2ps %%xmm1, %%xmm1 \n\t"
354  "psrad %%xmm6, %%xmm2 \n\t"
355  "movdqu 48(%1), %%xmm4 \n\t"
356  "cvtdq2ps %%xmm2, %%xmm2 \n\t"
357  "psrad %%xmm6, %%xmm3 \n\t"
358  "mulps %%xmm7, %%xmm1 \n\t"
359  "psrad %%xmm6, %%xmm4 \n\t"
360  "cvtdq2ps %%xmm3, %%xmm3 \n\t"
361  "movups %%xmm1, (%0) \n\t"
362  "mulps %%xmm7, %%xmm2 \n\t"
363  "cvtdq2ps %%xmm4, %%xmm4 \n\t"
364  "movups %%xmm2, 16(%0) \n\t"
365  "mulps %%xmm7, %%xmm3 \n\t"
366  "mulps %%xmm7, %%xmm4 \n\t"
367  "movups %%xmm3, 32(%0) \n\t"
368  "add $64, %1 \n\t"
369  "movups %%xmm4, 48(%0) \n\t"
370  "add $64, %0 \n\t"
371  "sub $1, %%ecx \n\t"
372  "jnz 1b \n\t"
373  :"+r"(out),"+r"(in)
374  :"c"(loops), "r"(f), "r"(shift)
375  :"xmm1","xmm2","xmm3","xmm4","xmm6","xmm7"
376  );
377  }
378 #endif //ARCH_x86
379  for (; i < len; i++)
380  *out++ = (*in++ >> shift) * f;
381  return len << 2;
382 }
383 
384 static int fromFloat32(AudioFormat format, int* out, const float* in, int len)
385 {
386  int i = 0;
387  int bits = AudioOutputSettings::FormatToBits(format);
388  float f = (uint)(1<<(bits-1));
389  int shift = 32 - bits;
390 
391  if (format == FORMAT_S24LSB)
392  shift = 0;
393 
394 #if ARCH_X86
395  if (sse_check() && len >= 16)
396  {
397  float o = 0.99999995;
398  float mo = -1;
399  int loops = len >> 4;
400  i = loops << 4;
401 
402  __asm__ volatile (
403  "movd %3, %%xmm7 \n\t"
404  "movss %4, %%xmm5 \n\t"
405  "punpckldq %%xmm7, %%xmm7 \n\t"
406  "movss %5, %%xmm6 \n\t"
407  "punpckldq %%xmm5, %%xmm5 \n\t"
408  "punpckldq %%xmm6, %%xmm6 \n\t"
409  "movd %6, %%xmm0 \n\t"
410  "punpckldq %%xmm7, %%xmm7 \n\t"
411  "punpckldq %%xmm5, %%xmm5 \n\t"
412  "punpckldq %%xmm6, %%xmm6 \n\t"
413  "1: \n\t"
414  "movups (%1), %%xmm1 \n\t"
415  "movups 16(%1), %%xmm2 \n\t"
416  "minps %%xmm5, %%xmm1 \n\t"
417  "movups 32(%1), %%xmm3 \n\t"
418  "maxps %%xmm6, %%xmm1 \n\t"
419  "movups 48(%1), %%xmm4 \n\t"
420  "mulps %%xmm7, %%xmm1 \n\t"
421  "minps %%xmm5, %%xmm2 \n\t"
422  "cvtps2dq %%xmm1, %%xmm1 \n\t"
423  "maxps %%xmm6, %%xmm2 \n\t"
424  "pslld %%xmm0, %%xmm1 \n\t"
425  "minps %%xmm5, %%xmm3 \n\t"
426  "mulps %%xmm7, %%xmm2 \n\t"
427  "movdqu %%xmm1, (%0) \n\t"
428  "cvtps2dq %%xmm2, %%xmm2 \n\t"
429  "maxps %%xmm6, %%xmm3 \n\t"
430  "minps %%xmm5, %%xmm4 \n\t"
431  "pslld %%xmm0, %%xmm2 \n\t"
432  "mulps %%xmm7, %%xmm3 \n\t"
433  "maxps %%xmm6, %%xmm4 \n\t"
434  "movdqu %%xmm2, 16(%0) \n\t"
435  "cvtps2dq %%xmm3, %%xmm3 \n\t"
436  "mulps %%xmm7, %%xmm4 \n\t"
437  "pslld %%xmm0, %%xmm3 \n\t"
438  "cvtps2dq %%xmm4, %%xmm4 \n\t"
439  "movdqu %%xmm3, 32(%0) \n\t"
440  "pslld %%xmm0, %%xmm4 \n\t"
441  "add $64, %1 \n\t"
442  "movdqu %%xmm4, 48(%0) \n\t"
443  "add $64, %0 \n\t"
444  "sub $1, %%ecx \n\t"
445  "jnz 1b \n\t"
446  :"+r"(out), "+r"(in)
447  :"c"(loops), "r"(f), "m"(o), "m"(mo), "r"(shift)
448  :"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7"
449  );
450  }
451 #endif //ARCH_x86
452  uint range = 1<<(bits-1);
453  for (; i < len; i++)
454  {
455  float valf = *in++;
456 
457  if (valf >= 1.0F)
458  {
459  *out++ = (range - 128) << shift;
460  continue;
461  }
462  if (valf <= -1.0F)
463  {
464  *out++ = (-range) << shift;
465  continue;
466  }
467  *out++ = lrintf(valf * f) << shift;
468  }
469  return len << 2;
470 }
471 
472 static int fromFloatFLT(float* out, const float* in, int len)
473 {
474  int i = 0;
475 
476 #if ARCH_X86
477  if (sse_check() && len >= 16)
478  {
479  int loops = len >> 4;
480  float o = 1;
481  float mo = -1;
482  i = loops << 4;
483 
484  __asm__ volatile (
485  "movss %3, %%xmm6 \n\t"
486  "movss %4, %%xmm7 \n\t"
487  "punpckldq %%xmm6, %%xmm6 \n\t"
488  "punpckldq %%xmm7, %%xmm7 \n\t"
489  "punpckldq %%xmm6, %%xmm6 \n\t"
490  "punpckldq %%xmm7, %%xmm7 \n\t"
491  "1: \n\t"
492  "movups (%1), %%xmm1 \n\t"
493  "movups 16(%1), %%xmm2 \n\t"
494  "minps %%xmm6, %%xmm1 \n\t"
495  "movups 32(%1), %%xmm3 \n\t"
496  "maxps %%xmm7, %%xmm1 \n\t"
497  "minps %%xmm6, %%xmm2 \n\t"
498  "movups 48(%1), %%xmm4 \n\t"
499  "maxps %%xmm7, %%xmm2 \n\t"
500  "movups %%xmm1, (%0) \n\t"
501  "minps %%xmm6, %%xmm3 \n\t"
502  "movups %%xmm2, 16(%0) \n\t"
503  "maxps %%xmm7, %%xmm3 \n\t"
504  "minps %%xmm6, %%xmm4 \n\t"
505  "movups %%xmm3, 32(%0) \n\t"
506  "maxps %%xmm7, %%xmm4 \n\t"
507  "add $64, %1 \n\t"
508  "movups %%xmm4, 48(%0) \n\t"
509  "add $64, %0 \n\t"
510  "sub $1, %%ecx \n\t"
511  "jnz 1b \n\t"
512  :"+r"(out), "+r"(in)
513  :"c"(loops), "m"(o), "m"(mo)
514  :"xmm1","xmm2","xmm3","xmm4","xmm6","xmm7"
515  );
516  }
517 #endif //ARCH_x86
518  for (;i < len;i++)
519  *out++ = clipcheck(*in++);
520  return len << 2;
521 }
522 
528 int AudioConvert::toFloat(AudioFormat format, void* out, const void* in,
529  int bytes)
530 {
531  if (bytes <= 0)
532  return 0;
533 
534  switch (format)
535  {
536  case FORMAT_U8:
537  return toFloat8((float*)out, (uchar*)in, bytes);
538  case FORMAT_S16:
539  return toFloat16((float*)out, (short*)in, bytes >> 1);
540  case FORMAT_S24:
541  case FORMAT_S24LSB:
542  case FORMAT_S32:
543  return toFloat32(format, (float*)out, (int*)in, bytes >> 2);
544  case FORMAT_FLT:
545  memcpy(out, in, bytes);
546  return bytes;
547  case FORMAT_NONE:
548  default:
549  return 0;
550  }
551 }
552 
558 int AudioConvert::fromFloat(AudioFormat format, void* out, const void* in,
559  int bytes)
560 {
561  if (bytes <= 0)
562  return 0;
563 
564  switch (format)
565  {
566  case FORMAT_U8:
567  return fromFloat8((uchar*)out, (float*)in, bytes >> 2);
568  case FORMAT_S16:
569  return fromFloat16((short*)out, (float*)in, bytes >> 2);
570  case FORMAT_S24:
571  case FORMAT_S24LSB:
572  case FORMAT_S32:
573  return fromFloat32(format, (int*)out, (float*)in, bytes >> 2);
574  case FORMAT_FLT:
575  return fromFloatFLT((float*)out, (float*)in, bytes >> 2);
576  case FORMAT_NONE:
577  default:
578  return 0;
579  }
580 }
581 
583 
585 {
586 public:
587  AudioConvertInternal(AVSampleFormat in, AVSampleFormat out) :
588  m_in(in), m_out(out)
589  {
590  m_swr = swr_alloc_set_opts(nullptr,
591  av_get_default_channel_layout(1),
592  m_out,
593  48000,
594  av_get_default_channel_layout(1),
595  m_in,
596  48000,
597  0, nullptr);
598  if (!m_swr)
599  {
600  LOG(VB_AUDIO, LOG_ERR, LOC + "error allocating resampler context");
601  return;
602  }
603  /* initialize the resampling context */
604  int ret = swr_init(m_swr);
605  if (ret < 0)
606  {
607  std::string error;
608  LOG(VB_AUDIO, LOG_ERR, LOC +
609  QString("error initializing resampler context (%1)")
611  swr_free(&m_swr);
612  return;
613  }
614  }
615  int Process(void* out, const void* in, int bytes) const
616  {
617  if (!m_swr)
618  return -1;
619 
620  std::array<uint8_t*,1> outp {(uint8_t*)out};
621  std::array<const uint8_t*,1> inp {(const uint8_t*)in};
622  int samples = bytes / av_get_bytes_per_sample(m_in);
623  int ret = swr_convert(m_swr,
624  outp.data(), samples,
625  inp.data(), samples);
626  if (ret < 0)
627  return ret;
628  return ret * av_get_bytes_per_sample(m_out);
629  }
631  {
632  if (m_swr)
633  {
634  swr_free(&m_swr);
635  }
636  }
637 
638  SwrContext* m_swr {nullptr};
639  AVSampleFormat m_in, m_out;
640 };
641 
642 
644 {
645  delete m_ctx;
646  m_ctx = nullptr;
647 }
648 
655 int AudioConvert::Process(void* out, const void* in, int bytes, bool noclip)
656 {
657  if (bytes <= 0)
658  return 0;
659  if (m_out == FORMAT_NONE || m_in == FORMAT_NONE)
660  return 0;
661 
662  if (noclip && m_in == m_out)
663  {
664  memcpy(out, in, bytes);
665  return bytes;
666  }
667 
668  /* use conversion routines to perform clipping on samples */
669  if (m_in == FORMAT_FLT)
670  return fromFloat(m_out, out, in, bytes);
671  if (m_out == FORMAT_FLT)
672  return toFloat(m_in, out, in, bytes);
673 
674  if (m_in == m_out)
675  {
676  memcpy(out, in, bytes);
677  return bytes;
678  }
679 
680  if (m_in == FORMAT_S24 || m_in == FORMAT_S24LSB ||
682  {
683  // FFmpeg can't handle those, so use float conversion intermediary
685  {
686  // this can be done in place
687  int s = toFloat(m_in, out, in, bytes);
688  return fromFloat(m_out, out, out, s);
689  }
690  // this leave S24 -> U8/S16.
691  // TODO: native handling of those ; use internal temp buffer in the mean time
692 
693  alignas(16) std::array<uint8_t,65536> buffer {0};
694  int left = bytes;
695 
696  while (left > 0)
697  {
698  int s = 0;
699 
700  if (left >= 65536)
701  {
702  s = toFloat(m_in, buffer.data(), in, buffer.size());
703  in = (void*)((long)in + s);
704  out = (void*)((long)out + fromFloat(m_out, out, buffer.data(), s));
705  left -= buffer.size();
706  continue;
707  }
708  s = toFloat(m_in, buffer.data(), in, left);
709  in = (void*)((long)in + s);
710  out = (void*)((long)out + fromFloat(m_out, out, buffer.data(), s));
711  left = 0;
712  }
714  }
715 
716  // use FFmpeg conversion routine for S32<->S16, S32<->U8 and S16<->U8
717  if (!m_ctx)
718  {
721  }
722 
723  return m_ctx->Process(out, in, bytes);
724 }
725 
729 void AudioConvert::MonoToStereo(void* dst, const void* src, int samples)
730 {
731  auto* d = (float*)dst;
732  auto* s = (float*)src;
733  for (int i = 0; i < samples; i++)
734  {
735  *d++ = *s;
736  *d++ = *s++;
737  }
738 }
739 
740 template <class AudioDataType>
741 void tDeinterleaveSample(AudioDataType* out, const AudioDataType* in, int channels, int frames)
742 {
743  std::array<AudioDataType*,8> outp {};
744 
745  for (int i = 0; i < channels; i++)
746  {
747  outp[i] = out + (i * frames);
748  }
749 
750  for (int i = 0; i < frames; i++)
751  {
752  for (int j = 0; j < channels; j++)
753  {
754  *(outp[j]++) = *(in++);
755  }
756  }
757 }
758 
764  uint8_t* output, const uint8_t* input,
765  int data_size)
766 {
767  if (channels == 1)
768  {
769  // If channel count is 1, planar and non-planar formats are the same
770  memcpy(output, input, data_size);
771  return;
772  }
773 
774  int bits = AudioOutputSettings::FormatToBits(format);
775  if (bits == 8)
776  {
777  tDeinterleaveSample((char*)output, (const char*)input, channels, data_size/sizeof(char)/channels);
778  }
779  else if (bits == 16)
780  {
781  tDeinterleaveSample((short*)output, (const short*)input, channels, data_size/sizeof(short)/channels);
782  }
783  else
784  {
785  tDeinterleaveSample((int*)output, (const int*)input, channels, data_size/sizeof(int)/channels);
786  }
787 }
788 
789 template <class AudioDataType>
790 void tInterleaveSample(AudioDataType* out, const AudioDataType* in, int channels, int frames,
791  const AudioDataType* const* inp = nullptr)
792 {
793  std::array<const AudioDataType*,8> my_inp {};
794 
795  if (channels == 1)
796  {
797  //special case for mono
798  memcpy(out, inp ? inp[0] : in, sizeof(AudioDataType) * frames);
799  return;
800  }
801 
802  if (!inp)
803  {
804  // We're given an array of int, calculate pointers to each row
805  for (int i = 0; i < channels; i++)
806  {
807  my_inp[i] = in + (i * frames);
808  }
809  }
810  else
811  {
812  for (int i = 0; i < channels; i++)
813  {
814  my_inp[i] = inp[i];
815  }
816  }
817 
818  for (int i = 0; i < frames; i++)
819  {
820  for (int j = 0; j < channels; j++)
821  {
822  *(out++) = *(my_inp[j]++);
823  }
824  }
825 }
826 
833  uint8_t* output, const uint8_t* const* input,
834  int data_size)
835 {
836  int bits = AudioOutputSettings::FormatToBits(format);
837  if (bits == 8)
838  {
839  tInterleaveSample((char*)output, (const char*)nullptr, channels, data_size/sizeof(char)/channels,
840  (const char* const*)input);
841  }
842  else if (bits == 16)
843  {
844  tInterleaveSample((short*)output, (const short*)nullptr, channels, data_size/sizeof(short)/channels,
845  (const short* const*)input);
846  }
847  else
848  {
849  tInterleaveSample((int*)output, (const int*)nullptr, channels, data_size/sizeof(int)/channels,
850  (const int* const*)input);
851  }
852 }
853 
859  uint8_t* output, const uint8_t* input,
860  int data_size)
861 {
862  int bits = AudioOutputSettings::FormatToBits(format);
863  if (bits == 8)
864  {
865  tInterleaveSample((char*)output, (const char*)input, channels, data_size/sizeof(char)/channels);
866  }
867  else if (bits == 16)
868  {
869  tInterleaveSample((short*)output, (const short*)input, channels, data_size/sizeof(short)/channels);
870  }
871  else
872  {
873  tInterleaveSample((int*)output, (const int*)input, channels, data_size/sizeof(int)/channels);
874  }
875 }
876 
878  uint8_t* output, const uint8_t* input,
879  int data_size)
880 {
881  DeinterleaveSamples(m_in, channels, output, input, data_size);
882 }
883 
885  uint8_t* output, const uint8_t* const* input,
886  int data_size)
887 {
888  InterleaveSamples(m_in, channels, output, input, data_size);
889 }
890 
892  uint8_t* output, const uint8_t* input,
893  int data_size)
894 {
895  InterleaveSamples(m_in, channels, output, input, data_size);
896 }
FORMAT_U8
@ FORMAT_U8
Definition: audiooutputsettings.h:27
FORMAT_NONE
@ FORMAT_NONE
Definition: audiooutputsettings.h:26
AudioConvert::toFloat
static int toFloat(AudioFormat format, void *out, const void *in, int bytes)
Convert integer samples to floats.
Definition: audioconvert.cpp:528
error
static void error(const char *str,...)
Definition: vbi.cpp:42
FORMAT_S16
@ FORMAT_S16
Definition: audiooutputsettings.h:28
AudioConvertInternal::Process
int Process(void *out, const void *in, int bytes) const
Definition: audioconvert.cpp:615
AudioOutputSettings::FormatToAVSampleFormat
static AVSampleFormat FormatToAVSampleFormat(AudioFormat format)
Return AudioFormat closest equivalent to AVSampleFormat Note that FORMAT_S24LSB and FORMAT_S24 have n...
Definition: audiooutputsettings.cpp:222
AudioOutputSettings::FormatToBits
static int FormatToBits(AudioFormat format)
Definition: audiooutputsettings.cpp:149
LOC
#define LOC
Definition: audioconvert.cpp:38
AudioConvertInternal::m_swr
SwrContext * m_swr
Definition: audioconvert.cpp:638
arg
arg(title).arg(filename).arg(doDelete))
toFloat16
static int toFloat16(float *out, const short *in, int len)
Definition: audioconvert.cpp:218
AudioConvert::fromFloat
static int fromFloat(AudioFormat format, void *out, const void *in, int bytes)
Convert float samples to integers.
Definition: audioconvert.cpp:558
AudioConvert::m_in
AudioFormat m_in
Definition: audioconvert.h:82
AudioOutputSettings::SampleSize
static int SampleSize(AudioFormat format)
Definition: audiooutputsettings.cpp:179
AudioConvertInternal::m_out
AVSampleFormat m_out
Definition: audioconvert.cpp:639
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
AudioConvertInternal::~AudioConvertInternal
~AudioConvertInternal()
Definition: audioconvert.cpp:630
fromFloat16
static int fromFloat16(short *out, const float *in, int len)
Definition: audioconvert.cpp:280
clipcheck
static float clipcheck(float f)
Definition: audioconvert.cpp:80
clip_uchar
static uchar clip_uchar(int a)
Definition: audioconvert.cpp:159
tInterleaveSample
void tInterleaveSample(AudioDataType *out, const AudioDataType *in, int channels, int frames, const AudioDataType *const *inp=nullptr)
Definition: audioconvert.cpp:790
clip_short
static short clip_short(int a)
Definition: audioconvert.cpp:273
AudioConvert::~AudioConvert
virtual ~AudioConvert()
Definition: audioconvert.cpp:643
toFloat8
static int toFloat8(float *out, const uchar *in, int len)
Definition: audioconvert.cpp:91
mythlogging.h
AudioConvertInternal
Definition: audioconvert.cpp:585
FORMAT_S24
@ FORMAT_S24
Definition: audiooutputsettings.h:30
fromFloatFLT
static int fromFloatFLT(float *out, const float *in, int len)
Definition: audioconvert.cpp:472
AudioConvert::m_out
AudioFormat m_out
Definition: audioconvert.h:82
AudioConvertInternal::m_in
AVSampleFormat m_in
Definition: audioconvert.cpp:639
FORMAT_FLT
@ FORMAT_FLT
Definition: audiooutputsettings.h:32
AudioConvert::m_ctx
AudioConvertInternal * m_ctx
Definition: audioconvert.h:81
FORMAT_S32
@ FORMAT_S32
Definition: audiooutputsettings.h:31
f
QTextStream t & f
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:603
lrintf
static av_always_inline av_const long int lrintf(float x)
Definition: audioconvert.cpp:74
AudioConvert::DeinterleaveSamples
void DeinterleaveSamples(int channels, uint8_t *output, const uint8_t *input, int data_size)
Definition: audioconvert.cpp:877
uint
unsigned int uint
Definition: compat.h:140
AudioConvert::MonoToStereo
static void MonoToStereo(void *dst, const void *src, int samples)
Convert a mono stream to stereo by copying and interleaving samples.
Definition: audioconvert.cpp:729
musicbrainzngs.compat.bytes
bytes
Definition: compat.py:49
fromFloat32
static int fromFloat32(AudioFormat format, int *out, const float *in, int len)
Definition: audioconvert.cpp:384
AudioConvertInternal::AudioConvertInternal
AudioConvertInternal(AVSampleFormat in, AVSampleFormat out)
Definition: audioconvert.cpp:587
AudioConvert::Process
int Process(void *out, const void *in, int bytes, bool noclip=false)
Process Parameters: out : destination buffer where converted samples will be copied in : source buffe...
Definition: audioconvert.cpp:655
tDeinterleaveSample
void tDeinterleaveSample(AudioDataType *out, const AudioDataType *in, int channels, int frames)
Definition: audioconvert.cpp:741
AudioConvert::InterleaveSamples
void InterleaveSamples(int channels, uint8_t *output, const uint8_t *const *input, int data_size)
Definition: audioconvert.cpp:884
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
AudioFormat
AudioFormat
Definition: audiooutputsettings.h:25
fromFloat8
static int fromFloat8(uchar *out, const float *in, int len)
Definition: audioconvert.cpp:166
output
#define output
Definition: synaesthesia.cpp:220
samples
static const std::array< const uint64_t, 4 > samples
Definition: element.cpp:46
mythaverror.h
av_make_error_stdstring
char * av_make_error_stdstring(std::string &errbuf, int errnum)
Definition: mythaverror.cpp:41
FORMAT_S24LSB
@ FORMAT_S24LSB
Definition: audiooutputsettings.h:29
toFloat32
static int toFloat32(AudioFormat format, float *out, const int *in, int len)
Definition: audioconvert.cpp:327
audioconvert.h