31#include "libavcodec/avcodec.h"
32#include "libswresample/swresample.h"
41#define LOC QString("AudioConvert: ")
45static 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;
85static int toFloat8(
float* out,
const uint8_t* in,
int len)
88 float f = 1.0F / ((1<<7));
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"
145 *out++ = (*in++ - 0x80) * f;
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"
208 *out++ =
clip_uint8(lrintf(*in++ * f) + 0x80);
212static 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"
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"
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"
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"
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"
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++)
739template <
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);
788template <
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,
void tDeinterleaveSample(AudioDataType *out, const AudioDataType *in, int channels, int frames)
static int fromFloatFLT(float *out, const float *in, int len)
static uint8_t clip_uint8(long a)
static float clipcheck(float f)
static int toFloat8(float *out, const uint8_t *in, int len)
static int fromFloat16(short *out, const float *in, int len)
static int fromFloat32(AudioFormat format, int *out, const float *in, int len)
static int toFloat16(float *out, const short *in, int len)
static int toFloat32(AudioFormat format, float *out, const int *in, int len)
void tInterleaveSample(AudioDataType *out, const AudioDataType *in, int channels, int frames, const AudioDataType *const *inp=nullptr)
static short clip_short(long a)
static int fromFloat8(uint8_t *out, const float *in, int len)
int Process(void *out, const void *in, int bytes) const
AudioConvertInternal(AVSampleFormat in, AVSampleFormat out)
static int toFloat(AudioFormat format, void *out, const void *in, int bytes)
Convert integer samples to floats.
AudioConvertInternal * m_ctx
void DeinterleaveSamples(int channels, uint8_t *output, const uint8_t *input, int data_size)
static void MonoToStereo(void *dst, const void *src, int samples)
Convert a mono stream to stereo by copying and interleaving samples.
static int fromFloat(AudioFormat format, void *out, const void *in, int bytes)
Convert float samples to integers.
void InterleaveSamples(int channels, uint8_t *output, const uint8_t *const *input, int data_size)
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 int SampleSize(AudioFormat format)
static AVSampleFormat FormatToAVSampleFormat(AudioFormat format)
Return AudioFormat closest equivalent to AVSampleFormat Note that FORMAT_S24LSB and FORMAT_S24 have n...
static int FormatToBits(AudioFormat format)
static const std::array< const uint64_t, 4 > samples
static const iso6937table * d
char * av_make_error_stdstring(std::string &errbuf, int errnum)
A C++ equivalent to av_make_error_string.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static eu8 clamp(eu8 value, eu8 low, eu8 high)