PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/mythtv/libs/libmyth/audio/audiooutpututil.cpp

https://github.com/royboy626/mythtv
C++ | 769 lines | 658 code | 60 blank | 51 comment | 71 complexity | 5616452be77a1355e1a68e8d33be4796 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
  1. #include <math.h>
  2. #include <sys/types.h>
  3. #include <inttypes.h>
  4. #include "bswap.h"
  5. #include "mythconfig.h"
  6. #include "mythlogging.h"
  7. #include "audiooutpututil.h"
  8. extern "C" {
  9. #include "libavcodec/avcodec.h"
  10. #include "libswresample/swresample.h"
  11. #include "pink.h"
  12. }
  13. #define LOC QString("AOUtil: ")
  14. #if ARCH_X86
  15. static int has_sse2 = -1;
  16. // Check cpuid for SSE2 support on x86 / x86_64
  17. static inline bool sse_check()
  18. {
  19. if (has_sse2 != -1)
  20. return (bool)has_sse2;
  21. __asm__(
  22. // -fPIC - we may not clobber ebx/rbx
  23. #if ARCH_X86_64
  24. "push %%rbx \n\t"
  25. #else
  26. "push %%ebx \n\t"
  27. #endif
  28. "mov $1, %%eax \n\t"
  29. "cpuid \n\t"
  30. "and $0x4000000, %%edx \n\t"
  31. "shr $26, %%edx \n\t"
  32. #if ARCH_X86_64
  33. "pop %%rbx \n\t"
  34. #else
  35. "pop %%ebx \n\t"
  36. #endif
  37. :"=d"(has_sse2)
  38. ::"%eax","%ecx"
  39. );
  40. return (bool)has_sse2;
  41. }
  42. #endif //ARCH_x86
  43. #if !HAVE_LRINTF
  44. static av_always_inline av_const long int lrintf(float x)
  45. {
  46. return (int)(rint(x));
  47. }
  48. #endif /* HAVE_LRINTF */
  49. static inline float clipcheck(float f) {
  50. if (f > 1.0f) f = 1.0f;
  51. else if (f < -1.0f) f = -1.0f;
  52. return f;
  53. }
  54. /*
  55. All toFloat variants require 16 byte aligned input and output buffers on x86
  56. The SSE code processes 16 bytes at a time and leaves any remainder for the C
  57. - there is no remainder in practice */
  58. static int toFloat8(float *out, uchar *in, int len)
  59. {
  60. int i = 0;
  61. float f = 1.0f / ((1<<7) - 1);
  62. #if ARCH_X86
  63. if (sse_check() && len >= 16)
  64. {
  65. int loops = len >> 4;
  66. i = loops << 4;
  67. int a = 0x80808080;
  68. __asm__ volatile (
  69. "movd %3, %%xmm0 \n\t"
  70. "movd %4, %%xmm7 \n\t"
  71. "punpckldq %%xmm0, %%xmm0 \n\t"
  72. "punpckldq %%xmm7, %%xmm7 \n\t"
  73. "punpckldq %%xmm0, %%xmm0 \n\t"
  74. "punpckldq %%xmm7, %%xmm7 \n\t"
  75. "1: \n\t"
  76. "movdqa (%1), %%xmm1 \n\t"
  77. "xorpd %%xmm2, %%xmm2 \n\t"
  78. "xorpd %%xmm3, %%xmm3 \n\t"
  79. "psubb %%xmm0, %%xmm1 \n\t"
  80. "xorpd %%xmm4, %%xmm4 \n\t"
  81. "punpcklbw %%xmm1, %%xmm2 \n\t"
  82. "xorpd %%xmm5, %%xmm5 \n\t"
  83. "punpckhbw %%xmm1, %%xmm3 \n\t"
  84. "punpcklwd %%xmm2, %%xmm4 \n\t"
  85. "xorpd %%xmm6, %%xmm6 \n\t"
  86. "punpckhwd %%xmm2, %%xmm5 \n\t"
  87. "psrad $24, %%xmm4 \n\t"
  88. "punpcklwd %%xmm3, %%xmm6 \n\t"
  89. "psrad $24, %%xmm5 \n\t"
  90. "punpckhwd %%xmm3, %%xmm1 \n\t"
  91. "psrad $24, %%xmm6 \n\t"
  92. "cvtdq2ps %%xmm4, %%xmm4 \n\t"
  93. "psrad $24, %%xmm1 \n\t"
  94. "cvtdq2ps %%xmm5, %%xmm5 \n\t"
  95. "mulps %%xmm7, %%xmm4 \n\t"
  96. "cvtdq2ps %%xmm6, %%xmm6 \n\t"
  97. "mulps %%xmm7, %%xmm5 \n\t"
  98. "movaps %%xmm4, (%0) \n\t"
  99. "cvtdq2ps %%xmm1, %%xmm1 \n\t"
  100. "mulps %%xmm7, %%xmm6 \n\t"
  101. "movaps %%xmm5, 16(%0) \n\t"
  102. "mulps %%xmm7, %%xmm1 \n\t"
  103. "movaps %%xmm6, 32(%0) \n\t"
  104. "add $16, %1 \n\t"
  105. "movaps %%xmm1, 48(%0) \n\t"
  106. "add $64, %0 \n\t"
  107. "sub $1, %%ecx \n\t"
  108. "jnz 1b \n\t"
  109. :"+r"(out),"+r"(in)
  110. :"c"(loops), "r"(a), "r"(f)
  111. );
  112. }
  113. #endif //ARCH_x86
  114. for (; i < len; i++)
  115. *out++ = (*in++ - 0x80) * f;
  116. return len << 2;
  117. }
  118. /*
  119. The SSE code processes 16 bytes at a time and leaves any remainder for the C
  120. - there is no remainder in practice */
  121. static int fromFloat8(uchar *out, float *in, int len)
  122. {
  123. int i = 0;
  124. float f = (1<<7) - 1;
  125. #if ARCH_X86
  126. if (sse_check() && len >= 16 && ((unsigned long)out & 0xf) == 0)
  127. {
  128. int loops = len >> 4;
  129. i = loops << 4;
  130. int a = 0x80808080;
  131. __asm__ volatile (
  132. "movd %3, %%xmm0 \n\t"
  133. "movd %4, %%xmm7 \n\t"
  134. "punpckldq %%xmm0, %%xmm0 \n\t"
  135. "punpckldq %%xmm7, %%xmm7 \n\t"
  136. "punpckldq %%xmm0, %%xmm0 \n\t"
  137. "punpckldq %%xmm7, %%xmm7 \n\t"
  138. "1: \n\t"
  139. "movups (%1), %%xmm1 \n\t"
  140. "movups 16(%1), %%xmm2 \n\t"
  141. "mulps %%xmm7, %%xmm1 \n\t"
  142. "movups 32(%1), %%xmm3 \n\t"
  143. "mulps %%xmm7, %%xmm2 \n\t"
  144. "cvtps2dq %%xmm1, %%xmm1 \n\t"
  145. "movups 48(%1), %%xmm4 \n\t"
  146. "mulps %%xmm7, %%xmm3 \n\t"
  147. "cvtps2dq %%xmm2, %%xmm2 \n\t"
  148. "mulps %%xmm7, %%xmm4 \n\t"
  149. "cvtps2dq %%xmm3, %%xmm3 \n\t"
  150. "packssdw %%xmm2, %%xmm1 \n\t"
  151. "cvtps2dq %%xmm4, %%xmm4 \n\t"
  152. "packssdw %%xmm4, %%xmm3 \n\t"
  153. "add $64, %1 \n\t"
  154. "packsswb %%xmm3, %%xmm1 \n\t"
  155. "paddb %%xmm0, %%xmm1 \n\t"
  156. "movdqu %%xmm1, (%0) \n\t"
  157. "add $16, %0 \n\t"
  158. "sub $1, %%ecx \n\t"
  159. "jnz 1b \n\t"
  160. :"+r"(out),"+r"(in)
  161. :"c"(loops), "r"(a), "r"(f)
  162. );
  163. }
  164. #endif //ARCH_x86
  165. for (;i < len; i++)
  166. *out++ = lrintf(clipcheck(*in++) * f) + 0x80;
  167. return len;
  168. }
  169. static int toFloat16(float *out, short *in, int len)
  170. {
  171. int i = 0;
  172. float f = 1.0f / ((1<<15) - 1);
  173. #if ARCH_X86
  174. if (sse_check() && len >= 16)
  175. {
  176. int loops = len >> 4;
  177. i = loops << 4;
  178. __asm__ volatile (
  179. "movd %3, %%xmm7 \n\t"
  180. "punpckldq %%xmm7, %%xmm7 \n\t"
  181. "punpckldq %%xmm7, %%xmm7 \n\t"
  182. "1: \n\t"
  183. "xorpd %%xmm2, %%xmm2 \n\t"
  184. "movdqa (%1), %%xmm1 \n\t"
  185. "xorpd %%xmm3, %%xmm3 \n\t"
  186. "punpcklwd %%xmm1, %%xmm2 \n\t"
  187. "movdqa 16(%1), %%xmm4 \n\t"
  188. "punpckhwd %%xmm1, %%xmm3 \n\t"
  189. "psrad $16, %%xmm2 \n\t"
  190. "punpcklwd %%xmm4, %%xmm5 \n\t"
  191. "psrad $16, %%xmm3 \n\t"
  192. "cvtdq2ps %%xmm2, %%xmm2 \n\t"
  193. "punpckhwd %%xmm4, %%xmm6 \n\t"
  194. "psrad $16, %%xmm5 \n\t"
  195. "mulps %%xmm7, %%xmm2 \n\t"
  196. "cvtdq2ps %%xmm3, %%xmm3 \n\t"
  197. "psrad $16, %%xmm6 \n\t"
  198. "mulps %%xmm7, %%xmm3 \n\t"
  199. "cvtdq2ps %%xmm5, %%xmm5 \n\t"
  200. "movaps %%xmm2, (%0) \n\t"
  201. "cvtdq2ps %%xmm6, %%xmm6 \n\t"
  202. "mulps %%xmm7, %%xmm5 \n\t"
  203. "movaps %%xmm3, 16(%0) \n\t"
  204. "mulps %%xmm7, %%xmm6 \n\t"
  205. "movaps %%xmm5, 32(%0) \n\t"
  206. "add $32, %1 \n\t"
  207. "movaps %%xmm6, 48(%0) \n\t"
  208. "add $64, %0 \n\t"
  209. "sub $1, %%ecx \n\t"
  210. "jnz 1b \n\t"
  211. :"+r"(out),"+r"(in)
  212. :"c"(loops), "r"(f)
  213. );
  214. }
  215. #endif //ARCH_x86
  216. for (; i < len; i++)
  217. *out++ = *in++ * f;
  218. return len << 2;
  219. }
  220. static int fromFloat16(short *out, float *in, int len)
  221. {
  222. int i = 0;
  223. float f = (1<<15) - 1;
  224. #if ARCH_X86
  225. if (sse_check() && len >= 16 && ((unsigned long)out & 0xf) == 0)
  226. {
  227. int loops = len >> 4;
  228. i = loops << 4;
  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. "movups (%1), %%xmm1 \n\t"
  235. "movups 16(%1), %%xmm2 \n\t"
  236. "mulps %%xmm7, %%xmm1 \n\t"
  237. "movups 32(%1), %%xmm3 \n\t"
  238. "mulps %%xmm7, %%xmm2 \n\t"
  239. "cvtps2dq %%xmm1, %%xmm1 \n\t"
  240. "movups 48(%1), %%xmm4 \n\t"
  241. "mulps %%xmm7, %%xmm3 \n\t"
  242. "cvtps2dq %%xmm2, %%xmm2 \n\t"
  243. "mulps %%xmm7, %%xmm4 \n\t"
  244. "cvtps2dq %%xmm3, %%xmm3 \n\t"
  245. "cvtps2dq %%xmm4, %%xmm4 \n\t"
  246. "packssdw %%xmm2, %%xmm1 \n\t"
  247. "packssdw %%xmm4, %%xmm3 \n\t"
  248. "add $64, %1 \n\t"
  249. "movdqu %%xmm1, (%0) \n\t"
  250. "movdqu %%xmm3, 16(%0) \n\t"
  251. "add $32, %0 \n\t"
  252. "sub $1, %%ecx \n\t"
  253. "jnz 1b \n\t"
  254. :"+r"(out),"+r"(in)
  255. :"c"(loops), "r"(f)
  256. );
  257. }
  258. #endif //ARCH_x86
  259. for (;i < len;i++)
  260. *out++ = lrintf(clipcheck(*in++) * f);
  261. return len << 1;
  262. }
  263. static int toFloat32(AudioFormat format, float *out, int *in, int len)
  264. {
  265. int i = 0;
  266. int bits = AudioOutputSettings::FormatToBits(format);
  267. float f = 1.0f / ((uint)(1<<(bits-1)) - 128);
  268. int shift = 32 - bits;
  269. if (format == FORMAT_S24LSB)
  270. shift = 0;
  271. #if ARCH_X86
  272. if (sse_check() && len >= 16)
  273. {
  274. int loops = len >> 4;
  275. i = loops << 4;
  276. __asm__ volatile (
  277. "movd %3, %%xmm7 \n\t"
  278. "punpckldq %%xmm7, %%xmm7 \n\t"
  279. "movd %4, %%xmm6 \n\t"
  280. "punpckldq %%xmm7, %%xmm7 \n\t"
  281. "1: \n\t"
  282. "movdqa (%1), %%xmm1 \n\t"
  283. "movdqa 16(%1), %%xmm2 \n\t"
  284. "psrad %%xmm6, %%xmm1 \n\t"
  285. "movdqa 32(%1), %%xmm3 \n\t"
  286. "cvtdq2ps %%xmm1, %%xmm1 \n\t"
  287. "psrad %%xmm6, %%xmm2 \n\t"
  288. "movdqa 48(%1), %%xmm4 \n\t"
  289. "cvtdq2ps %%xmm2, %%xmm2 \n\t"
  290. "psrad %%xmm6, %%xmm3 \n\t"
  291. "mulps %%xmm7, %%xmm1 \n\t"
  292. "psrad %%xmm6, %%xmm4 \n\t"
  293. "cvtdq2ps %%xmm3, %%xmm3 \n\t"
  294. "movaps %%xmm1, (%0) \n\t"
  295. "mulps %%xmm7, %%xmm2 \n\t"
  296. "cvtdq2ps %%xmm4, %%xmm4 \n\t"
  297. "movaps %%xmm2, 16(%0) \n\t"
  298. "mulps %%xmm7, %%xmm3 \n\t"
  299. "mulps %%xmm7, %%xmm4 \n\t"
  300. "movaps %%xmm3, 32(%0) \n\t"
  301. "add $64, %1 \n\t"
  302. "movaps %%xmm4, 48(%0) \n\t"
  303. "add $64, %0 \n\t"
  304. "sub $1, %%ecx \n\t"
  305. "jnz 1b \n\t"
  306. :"+r"(out),"+r"(in)
  307. :"c"(loops), "r"(f), "r"(shift)
  308. );
  309. }
  310. #endif //ARCH_x86
  311. for (; i < len; i++)
  312. *out++ = (*in++ >> shift) * f;
  313. return len << 2;
  314. }
  315. static int fromFloat32(AudioFormat format, int *out, float *in, int len)
  316. {
  317. int i = 0;
  318. int bits = AudioOutputSettings::FormatToBits(format);
  319. float f = (uint)(1<<(bits-1)) - 128;
  320. int shift = 32 - bits;
  321. if (format == FORMAT_S24LSB)
  322. shift = 0;
  323. #if ARCH_X86
  324. if (sse_check() && len >= 16 && ((unsigned long)out & 0xf) == 0)
  325. {
  326. float o = 1, mo = -1;
  327. int loops = len >> 4;
  328. i = loops << 4;
  329. __asm__ volatile (
  330. "movd %3, %%xmm7 \n\t"
  331. "movss %4, %%xmm5 \n\t"
  332. "punpckldq %%xmm7, %%xmm7 \n\t"
  333. "movss %5, %%xmm6 \n\t"
  334. "punpckldq %%xmm5, %%xmm5 \n\t"
  335. "punpckldq %%xmm6, %%xmm6 \n\t"
  336. "movd %6, %%xmm0 \n\t"
  337. "punpckldq %%xmm7, %%xmm7 \n\t"
  338. "punpckldq %%xmm5, %%xmm5 \n\t"
  339. "punpckldq %%xmm6, %%xmm6 \n\t"
  340. "1: \n\t"
  341. "movups (%1), %%xmm1 \n\t"
  342. "movups 16(%1), %%xmm2 \n\t"
  343. "minps %%xmm5, %%xmm1 \n\t"
  344. "movups 32(%1), %%xmm3 \n\t"
  345. "maxps %%xmm6, %%xmm1 \n\t"
  346. "movups 48(%1), %%xmm4 \n\t"
  347. "mulps %%xmm7, %%xmm1 \n\t"
  348. "minps %%xmm5, %%xmm2 \n\t"
  349. "cvtps2dq %%xmm1, %%xmm1 \n\t"
  350. "maxps %%xmm6, %%xmm2 \n\t"
  351. "pslld %%xmm0, %%xmm1 \n\t"
  352. "minps %%xmm5, %%xmm3 \n\t"
  353. "mulps %%xmm7, %%xmm2 \n\t"
  354. "movdqu %%xmm1, (%0) \n\t"
  355. "cvtps2dq %%xmm2, %%xmm2 \n\t"
  356. "maxps %%xmm6, %%xmm3 \n\t"
  357. "minps %%xmm5, %%xmm4 \n\t"
  358. "pslld %%xmm0, %%xmm2 \n\t"
  359. "mulps %%xmm7, %%xmm3 \n\t"
  360. "maxps %%xmm6, %%xmm4 \n\t"
  361. "movdqu %%xmm2, 16(%0) \n\t"
  362. "cvtps2dq %%xmm3, %%xmm3 \n\t"
  363. "mulps %%xmm7, %%xmm4 \n\t"
  364. "pslld %%xmm0, %%xmm3 \n\t"
  365. "cvtps2dq %%xmm4, %%xmm4 \n\t"
  366. "movdqu %%xmm3, 32(%0) \n\t"
  367. "pslld %%xmm0, %%xmm4 \n\t"
  368. "add $64, %1 \n\t"
  369. "movdqu %%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), "m"(o), "m"(mo), "r"(shift)
  375. );
  376. }
  377. #endif //ARCH_x86
  378. for (;i < len;i++)
  379. *out++ = lrintf(clipcheck(*in++) * f) << shift;
  380. return len << 2;
  381. }
  382. static int fromFloatFLT(float *out, float *in, int len)
  383. {
  384. int i = 0;
  385. #if ARCH_X86
  386. if (sse_check() && len >= 16 && ((unsigned long)in & 0xf) == 0)
  387. {
  388. int loops = len >> 4;
  389. float o = 1, mo = -1;
  390. i = loops << 4;
  391. __asm__ volatile (
  392. "movss %3, %%xmm6 \n\t"
  393. "movss %4, %%xmm7 \n\t"
  394. "punpckldq %%xmm6, %%xmm6 \n\t"
  395. "punpckldq %%xmm7, %%xmm7 \n\t"
  396. "punpckldq %%xmm6, %%xmm6 \n\t"
  397. "punpckldq %%xmm7, %%xmm7 \n\t"
  398. "1: \n\t"
  399. "movups (%1), %%xmm1 \n\t"
  400. "movups 16(%1), %%xmm2 \n\t"
  401. "minps %%xmm6, %%xmm1 \n\t"
  402. "movups 32(%1), %%xmm3 \n\t"
  403. "maxps %%xmm7, %%xmm1 \n\t"
  404. "minps %%xmm6, %%xmm2 \n\t"
  405. "movups 48(%1), %%xmm4 \n\t"
  406. "maxps %%xmm7, %%xmm2 \n\t"
  407. "movups %%xmm1, (%0) \n\t"
  408. "minps %%xmm6, %%xmm3 \n\t"
  409. "movups %%xmm2, 16(%0) \n\t"
  410. "maxps %%xmm7, %%xmm3 \n\t"
  411. "minps %%xmm6, %%xmm4 \n\t"
  412. "movups %%xmm3, 32(%0) \n\t"
  413. "maxps %%xmm7, %%xmm4 \n\t"
  414. "add $64, %1 \n\t"
  415. "movups %%xmm4, 48(%0) \n\t"
  416. "add $64, %0 \n\t"
  417. "sub $1, %%ecx \n\t"
  418. "jnz 1b \n\t"
  419. :"+r"(out), "+r"(in)
  420. :"c"(loops), "m"(o), "m"(mo)
  421. );
  422. }
  423. #endif //ARCH_x86
  424. for (;i < len;i++)
  425. *out++ = clipcheck(*in++);
  426. return len << 2;
  427. }
  428. /**
  429. * Returns true if platform has an FPU.
  430. * for the time being, this test is limited to testing if SSE2 is supported
  431. */
  432. bool AudioOutputUtil::has_hardware_fpu()
  433. {
  434. #if ARCH_X86
  435. return sse_check();
  436. #else
  437. return false;
  438. #endif
  439. }
  440. /**
  441. * Convert integer samples to floats
  442. *
  443. * Consumes 'bytes' bytes from in and returns the numer of bytes written to out
  444. */
  445. int AudioOutputUtil::toFloat(AudioFormat format, void *out, void *in,
  446. int bytes)
  447. {
  448. if (bytes <= 0)
  449. return 0;
  450. switch (format)
  451. {
  452. case FORMAT_U8:
  453. return toFloat8((float *)out, (uchar *)in, bytes);
  454. case FORMAT_S16:
  455. return toFloat16((float *)out, (short *)in, bytes >> 1);
  456. case FORMAT_S24:
  457. case FORMAT_S24LSB:
  458. case FORMAT_S32:
  459. return toFloat32(format, (float *)out, (int *)in, bytes >> 2);
  460. case FORMAT_FLT:
  461. memcpy(out, in, bytes);
  462. return bytes;
  463. case FORMAT_NONE:
  464. default:
  465. return 0;
  466. }
  467. }
  468. /**
  469. * Convert float samples to integers
  470. *
  471. * Consumes 'bytes' bytes from in and returns the numer of bytes written to out
  472. */
  473. int AudioOutputUtil::fromFloat(AudioFormat format, void *out, void *in,
  474. int bytes)
  475. {
  476. if (bytes <= 0)
  477. return 0;
  478. switch (format)
  479. {
  480. case FORMAT_U8:
  481. return fromFloat8((uchar *)out, (float *)in, bytes >> 2);
  482. case FORMAT_S16:
  483. return fromFloat16((short *)out, (float *)in, bytes >> 2);
  484. case FORMAT_S24:
  485. case FORMAT_S24LSB:
  486. case FORMAT_S32:
  487. return fromFloat32(format, (int *)out, (float *)in, bytes >> 2);
  488. case FORMAT_FLT:
  489. return fromFloatFLT((float *)out, (float *)in, bytes >> 2);
  490. case FORMAT_NONE:
  491. default:
  492. return 0;
  493. }
  494. }
  495. /**
  496. * Convert a mono stream to stereo by copying and interleaving samples
  497. */
  498. void AudioOutputUtil::MonoToStereo(void *dst, void *src, int samples)
  499. {
  500. float *d = (float *)dst;
  501. float *s = (float *)src;
  502. for (int i = 0; i < samples; i++)
  503. {
  504. *d++ = *s;
  505. *d++ = *s++;
  506. }
  507. }
  508. /**
  509. * Adjust the volume of samples
  510. *
  511. * Makes a crude attempt to normalise the relative volumes of
  512. * PCM from mythmusic, PCM from video and upmixed AC-3
  513. */
  514. void AudioOutputUtil::AdjustVolume(void *buf, int len, int volume,
  515. bool music, bool upmix)
  516. {
  517. float g = volume / 100.0f;
  518. float *fptr = (float *)buf;
  519. int samples = len >> 2;
  520. int i = 0;
  521. // Should be exponential - this'll do
  522. g *= g;
  523. // Try to ~ match stereo volume when upmixing
  524. if (upmix)
  525. g *= 1.5f;
  526. // Music is relatively loud
  527. if (music)
  528. g *= 0.4f;
  529. if (g == 1.0f)
  530. return;
  531. #if ARCH_X86
  532. if (sse_check() && samples >= 16)
  533. {
  534. int loops = samples >> 4;
  535. i = loops << 4;
  536. __asm__ volatile (
  537. "movss %2, %%xmm0 \n\t"
  538. "punpckldq %%xmm0, %%xmm0 \n\t"
  539. "punpckldq %%xmm0, %%xmm0 \n\t"
  540. "1: \n\t"
  541. "movups (%0), %%xmm1 \n\t"
  542. "movups 16(%0), %%xmm2 \n\t"
  543. "mulps %%xmm0, %%xmm1 \n\t"
  544. "movups 32(%0), %%xmm3 \n\t"
  545. "mulps %%xmm0, %%xmm2 \n\t"
  546. "movups 48(%0), %%xmm4 \n\t"
  547. "mulps %%xmm0, %%xmm3 \n\t"
  548. "movups %%xmm1, (%0) \n\t"
  549. "mulps %%xmm0, %%xmm4 \n\t"
  550. "movups %%xmm2, 16(%0) \n\t"
  551. "movups %%xmm3, 32(%0) \n\t"
  552. "movups %%xmm4, 48(%0) \n\t"
  553. "add $64, %0 \n\t"
  554. "sub $1, %%ecx \n\t"
  555. "jnz 1b \n\t"
  556. :"+r"(fptr)
  557. :"c"(loops),"m"(g)
  558. );
  559. }
  560. #endif //ARCH_X86
  561. for (; i < samples; i++)
  562. *fptr++ *= g;
  563. }
  564. template <class AudioDataType>
  565. void _MuteChannel(AudioDataType *buffer, int channels, int ch, int frames)
  566. {
  567. AudioDataType *s1 = buffer + ch;
  568. AudioDataType *s2 = buffer - ch + 1;
  569. for (int i = 0; i < frames; i++)
  570. {
  571. *s1 = *s2;
  572. s1 += channels;
  573. s2 += channels;
  574. }
  575. }
  576. /**
  577. * Mute individual channels through mono->stereo duplication
  578. *
  579. * Mute given channel (left or right) by copying right or left
  580. * channel over.
  581. */
  582. void AudioOutputUtil::MuteChannel(int obits, int channels, int ch,
  583. void *buffer, int bytes)
  584. {
  585. int frames = bytes / ((obits >> 3) * channels);
  586. if (obits == 8)
  587. _MuteChannel((uchar *)buffer, channels, ch, frames);
  588. else if (obits == 16)
  589. _MuteChannel((short *)buffer, channels, ch, frames);
  590. else
  591. _MuteChannel((int *)buffer, channels, ch, frames);
  592. }
  593. #if HAVE_BIGENDIAN
  594. #define LE_SHORT(v) bswap_16(v)
  595. #define LE_INT(v) bswap_32(v)
  596. #else
  597. #define LE_SHORT(v) (v)
  598. #define LE_INT(v) (v)
  599. #endif
  600. char *AudioOutputUtil::GeneratePinkFrames(char *frames, int channels,
  601. int channel, int count, int bits)
  602. {
  603. pink_noise_t pink;
  604. initialize_pink_noise(&pink, bits);
  605. double res;
  606. int32_t ires;
  607. int16_t *samp16 = (int16_t*) frames;
  608. int32_t *samp32 = (int32_t*) frames;
  609. while (count-- > 0)
  610. {
  611. for(int chn = 0 ; chn < channels; chn++)
  612. {
  613. if (chn==channel)
  614. {
  615. res = generate_pink_noise_sample(&pink) * 0x03fffffff; /* Don't use MAX volume */
  616. ires = res;
  617. if (bits == 16)
  618. *samp16++ = LE_SHORT(ires >> 16);
  619. else
  620. *samp32++ = LE_INT(ires);
  621. }
  622. else
  623. {
  624. if (bits == 16)
  625. *samp16++ = 0;
  626. else
  627. *samp32++ = 0;
  628. }
  629. }
  630. }
  631. return frames;
  632. }
  633. /**
  634. * DecodeAudio
  635. * Decode an audio packet, and compact it if data is planar
  636. * Return negative error code if an error occurred during decoding
  637. * or the number of bytes consumed from the input AVPacket
  638. * data_size contains the size of decoded data copied into buffer
  639. */
  640. int AudioOutputUtil::DecodeAudio(AVCodecContext *ctx,
  641. uint8_t *buffer, int &data_size,
  642. AVPacket *pkt)
  643. {
  644. AVFrame frame;
  645. int got_frame = 0;
  646. int ret, ret2;
  647. char error[AV_ERROR_MAX_STRING_SIZE];
  648. data_size = 0;
  649. avcodec_get_frame_defaults(&frame);
  650. ret = avcodec_decode_audio4(ctx, &frame, &got_frame, pkt);
  651. if (ret < 0 || !got_frame)
  652. {
  653. LOG(VB_AUDIO, LOG_ERR, LOC +
  654. QString("audio decode error: %1 (%2)")
  655. .arg(av_make_error_string(error, sizeof(error), ret))
  656. .arg(got_frame));
  657. return ret;
  658. }
  659. AVSampleFormat format = (AVSampleFormat)frame.format;
  660. if (!av_sample_fmt_is_planar(format))
  661. {
  662. // data is already compacted... simply copy it
  663. data_size = av_samples_get_buffer_size(NULL, ctx->channels,
  664. frame.nb_samples,
  665. format, 1);
  666. memcpy(buffer, frame.extended_data[0], data_size);
  667. return ret;
  668. }
  669. // Need to find a valid channels layout, as not all codecs provide one
  670. int64_t channel_layout =
  671. frame.channel_layout && frame.channels == av_get_channel_layout_nb_channels(frame.channel_layout) ?
  672. frame.channel_layout : av_get_default_channel_layout(frame.channels);
  673. SwrContext *swr = swr_alloc_set_opts(NULL,
  674. channel_layout,
  675. av_get_packed_sample_fmt(format),
  676. frame.sample_rate,
  677. channel_layout,
  678. format,
  679. frame.sample_rate,
  680. 0, NULL);
  681. if (!swr)
  682. {
  683. LOG(VB_AUDIO, LOG_ERR, LOC + "error allocating resampler context");
  684. return AVERROR(ENOMEM);
  685. }
  686. /* initialize the resampling context */
  687. ret2 = swr_init(swr);
  688. if (ret2 < 0)
  689. {
  690. LOG(VB_AUDIO, LOG_ERR, LOC +
  691. QString("error initializing resampler context (%1)")
  692. .arg(av_make_error_string(error, sizeof(error), ret2)));
  693. swr_free(&swr);
  694. return ret2;
  695. }
  696. uint8_t *out[] = {buffer};
  697. ret2 = swr_convert(swr, out, frame.nb_samples,
  698. (const uint8_t **)frame.extended_data, frame.nb_samples);
  699. swr_free(&swr);
  700. if (ret2 < 0)
  701. {
  702. LOG(VB_AUDIO, LOG_ERR, LOC +
  703. QString("error converting audio from planar format (%1)")
  704. .arg(av_make_error_string(error, sizeof(error), ret2)));
  705. return ret2;
  706. }
  707. data_size = ret2 * frame.channels * av_get_bytes_per_sample(format);
  708. return ret;
  709. }