31 #include "libavcodec/avcodec.h"
32 #include "libswresample/swresample.h"
41 #define LOC QString("AudioConvert: ")
43 #ifdef Q_PROCESSOR_X86
45 static inline bool sse2_check()
47 #ifdef Q_PROCESSOR_X86_64
50 static int has_sse2 = -1;
52 return (
bool)has_sse2;
55 #ifdef Q_PROCESSOR_X86_64
62 "and $0x4000000, %%edx \n\t"
64 #ifdef Q_PROCESSOR_X86_64
72 return (
bool)has_sse2;
74 #endif //Q_PROCESSOR_X86
78 return std::clamp(f, -1.0F, 1.0F);
85 static int toFloat8(
float* out,
const uint8_t* in,
int len)
88 float f = 1.0F / ((1<<7));
90 #ifdef Q_PROCESSOR_X86
91 if (sse2_check() && len >= 16)
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"
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"
134 "movups %%xmm1, 48(%0) \n\t"
139 :
"c"(loops),
"r"(a),
"r"(f)
140 :
"xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm5",
"xmm6",
"xmm7"
143 #endif //Q_PROCESSOR_X86
145 *out++ = (*in++ - 0x80) * f;
160 static int fromFloat8(uint8_t* out,
const float* in,
int len)
165 #ifdef Q_PROCESSOR_X86
166 if (sse2_check() && len >= 16)
168 int loops = len >> 4;
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"
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"
195 "packsswb %%xmm3, %%xmm1 \n\t"
196 "paddb %%xmm0, %%xmm1 \n\t"
197 "movdqu %%xmm1, (%0) \n\t"
202 :
"c"(loops),
"r"(a),
"r"(f)
203 :
"xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm7"
206 #endif //Q_PROCESSOR_X86
208 *out++ =
clip_uint8(lrintf(*in++ * f) + 0x80);
212 static int toFloat16(
float* out,
const short* in,
int len)
215 float f = 1.0F / ((1<<15));
217 #ifdef Q_PROCESSOR_X86
218 if (sse2_check() && len >= 16)
220 int loops = len >> 4;
224 "movd %3, %%xmm7 \n\t"
225 "punpckldq %%xmm7, %%xmm7 \n\t"
226 "punpckldq %%xmm7, %%xmm7 \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"
252 "movups %%xmm6, 48(%0) \n\t"
258 :
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm5",
"xmm6",
"xmm7"
261 #endif //Q_PROCESSOR_X86
269 if ((a+0x8000) & ~0xFFFF)
270 return (a>>31) ^ 0x7FFF;
279 #ifdef Q_PROCESSOR_X86
280 if (sse2_check() && len >= 16)
282 int loops = len >> 4;
286 "movd %3, %%xmm7 \n\t"
287 "punpckldq %%xmm7, %%xmm7 \n\t"
288 "punpckldq %%xmm7, %%xmm7 \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"
305 "movdqu %%xmm1, (%0) \n\t"
306 "movdqu %%xmm3, 16(%0) \n\t"
312 :
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm7"
315 #endif //Q_PROCESSOR_X86
325 float f = 1.0F / ((
uint)(1<<(bits-1)));
326 int shift = 32 - bits;
331 #ifdef Q_PROCESSOR_X86
332 if (sse2_check() && len >= 16)
334 int loops = len >> 4;
338 "movd %3, %%xmm7 \n\t"
339 "punpckldq %%xmm7, %%xmm7 \n\t"
340 "movd %4, %%xmm6 \n\t"
341 "punpckldq %%xmm7, %%xmm7 \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"
363 "movups %%xmm4, 48(%0) \n\t"
368 :
"c"(loops),
"r"(f),
"r"(shift)
369 :
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm6",
"xmm7"
372 #endif //Q_PROCESSOR_X86
374 *out++ = (*in++ >> shift) * f;
382 float f = (
uint)(1<<(bits-1));
383 int shift = 32 - bits;
388 #ifdef Q_PROCESSOR_X86
389 if (sse2_check() && len >= 16)
391 float o = 0.99999995;
393 int loops = len >> 4;
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"
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"
436 "movdqu %%xmm4, 48(%0) \n\t"
441 :
"c"(loops),
"r"(f),
"m"(o),
"m"(mo),
"r"(shift)
442 :
"xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm5",
"xmm6",
"xmm7"
445 #endif //Q_PROCESSOR_X86
446 uint range = 1<<(bits-1);
453 *out++ = (range - 128) << shift;
458 *out++ = (-range) << shift;
461 *out++ = lrintf(valf * f) << shift;
470 #ifdef Q_PROCESSOR_X86
471 if (sse2_check() && len >= 16)
473 int loops = len >> 4;
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"
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"
502 "movups %%xmm4, 48(%0) \n\t"
507 :
"c"(loops),
"m"(o),
"m"(mo)
508 :
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm6",
"xmm7"
511 #endif //Q_PROCESSOR_X86
539 memcpy(out, in,
bytes);
584 AVChannelLayout channel_layout;
585 av_channel_layout_default(&channel_layout, 1);
586 int ret = swr_alloc_set_opts2(&
m_swr,
594 if (!
m_swr || ret < 0)
597 LOG(VB_AUDIO, LOG_ERR,
LOC +
598 QString(
"error allocating resampler context (%1)")
603 ret = swr_init(
m_swr);
607 LOG(VB_AUDIO, LOG_ERR,
LOC +
608 QString(
"error initializing resampler context (%1)")
619 std::array<uint8_t*,1> outp {(uint8_t*)out};
620 std::array<const uint8_t*,1> inp {(
const uint8_t*)in};
622 int ret = swr_convert(
m_swr,
627 return ret * av_get_bytes_per_sample(
m_out);
663 memcpy(out, in,
bytes);
675 memcpy(out, in,
bytes);
692 alignas(16) std::array<uint8_t,65536> buffer {0};
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();
708 in =
static_cast<const uint8_t *
>(in) + s;
709 out =
static_cast<uint8_t *
>(out) +
fromFloat(
m_out, out, buffer.data(), s);
730 auto*
d = (
float*)dst;
731 auto* s = (
float*)src;
732 for (
int i = 0; i <
samples; i++)
739 template <
class AudioDataType>
742 std::array<AudioDataType*,8> outp {};
744 for (
int i = 0; i < channels; i++)
746 outp[i] = out + (i * frames);
749 for (
int i = 0; i < frames; i++)
751 for (
int j = 0; j < channels; j++)
753 *(outp[j]++) = *(in++);
763 uint8_t*
output,
const uint8_t* input,
769 memcpy(
output, input, data_size);
788 template <
class AudioDataType>
790 const AudioDataType*
const* inp =
nullptr)
792 std::array<const AudioDataType*,8> my_inp {};
797 memcpy(out, inp ? inp[0] : in,
sizeof(AudioDataType) * frames);
804 for (
int i = 0; i < channels; i++)
806 my_inp[i] = in + (i * frames);
811 for (
int i = 0; i < channels; i++)
817 for (
int i = 0; i < frames; i++)
819 for (
int j = 0; j < channels; j++)
821 *(out++) = *(my_inp[j]++);
832 uint8_t*
output,
const uint8_t*
const* input,
839 (
const char*
const*)input);
844 (
const short*
const*)input);
849 (
const int*
const*)input);
858 uint8_t*
output,
const uint8_t* input,
877 uint8_t*
output,
const uint8_t* input,
884 uint8_t*
output,
const uint8_t*
const* input,
891 uint8_t*
output,
const uint8_t* input,