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