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