audio-repack.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include "audio-repack.h"
  2. #include <emmintrin.h>
  3. int check_buffer(struct audio_repack *repack,
  4. uint32_t frame_count)
  5. {
  6. const uint32_t new_size = frame_count * repack->base_dst_size
  7. + repack->extra_dst_size;
  8. if (repack->packet_size < new_size) {
  9. repack->packet_buffer = brealloc(
  10. repack->packet_buffer, new_size);
  11. if (!repack->packet_buffer)
  12. return -1;
  13. repack->packet_size = new_size;
  14. }
  15. return 0;
  16. }
  17. /*
  18. * Swap channel 3 & 4, 5 & 7, 6 & 8 and squash arrays
  19. * 2.1:
  20. *
  21. * | FL | FR | LFE | emp | emp | emp |emp |emp |
  22. * | | |
  23. * | FL | FR | LFE |
  24. * 4.0 (quad):
  25. *
  26. * | FL | FR | BR | BL | emp | emp |emp |emp |
  27. * | | x |
  28. * | FL | FR | BL | BC |
  29. *
  30. * 4.1:
  31. *
  32. * | FL | FR |LFE | FC | BC | emp |emp |emp |
  33. * | | x | |
  34. * | FL | FR | FC |LFE | BC |
  35. *
  36. * 5.1:
  37. *
  38. * | FL | FR |LFE | FC |(emp|emp)|(BL|BR)|
  39. * | | x x
  40. * | FL | FR | FC |LFE | BL | BR |
  41. *
  42. * 7.1:
  43. *
  44. * | FL | FR |LFE | FC |( SL | SR )|(BL |BR )|
  45. * | | x X
  46. * | FL | FR | FC |LFE |( BL | BR )|(SL |SR )|
  47. */
  48. int repack_squash_swap(struct audio_repack *repack,
  49. const uint8_t *bsrc, uint32_t frame_count)
  50. {
  51. if (check_buffer(repack, frame_count) < 0)
  52. return -1;
  53. int squash = repack->extra_dst_size;
  54. const __m128i *src = (__m128i *)bsrc;
  55. const __m128i *esrc = src + frame_count;
  56. uint16_t *dst = (uint16_t *)repack->packet_buffer;
  57. /* 2.1 audio does not require re-ordering but still needs squashing
  58. * in order to avoid sampling issues.
  59. */
  60. if (squash == 5) {
  61. while (src != esrc) {
  62. __m128i target = _mm_load_si128(src++);
  63. _mm_storeu_si128((__m128i *)dst, target);
  64. dst += 8 - squash;
  65. }
  66. } else {
  67. while (src != esrc) {
  68. __m128i target = _mm_load_si128(src++);
  69. __m128i buf = _mm_shufflelo_epi16(target, _MM_SHUFFLE(2, 3, 1, 0));
  70. __m128i buf2 = _mm_shufflehi_epi16(buf, _MM_SHUFFLE(1, 0, 3, 2));
  71. _mm_storeu_si128((__m128i *)dst, buf2);
  72. dst += 8 - squash;
  73. }
  74. }
  75. return 0;
  76. }
  77. int audio_repack_init(struct audio_repack *repack,
  78. audio_repack_mode_t repack_mode, uint8_t sample_bit)
  79. {
  80. memset(repack, 0, sizeof(*repack));
  81. if (sample_bit != 16)
  82. return -1;
  83. switch (repack_mode) {
  84. case repack_mode_8to3ch_swap23:
  85. repack->base_src_size = 8 * (16 / 8);
  86. repack->base_dst_size = 3 * (16 / 8);
  87. repack->extra_dst_size = 5;
  88. repack->repack_func = &repack_squash_swap;
  89. break;
  90. case repack_mode_8to4ch_swap23:
  91. repack->base_src_size = 8 * (16 / 8);
  92. repack->base_dst_size = 4 * (16 / 8);
  93. repack->extra_dst_size = 4;
  94. repack->repack_func = &repack_squash_swap;
  95. break;
  96. case repack_mode_8to5ch_swap23:
  97. repack->base_src_size = 8 * (16 / 8);
  98. repack->base_dst_size = 5 * (16 / 8);
  99. repack->extra_dst_size = 3;
  100. repack->repack_func = &repack_squash_swap;
  101. break;
  102. case repack_mode_8to6ch_swap23:
  103. repack->base_src_size = 8 * (16 / 8);
  104. repack->base_dst_size = 6 * (16 / 8);
  105. repack->extra_dst_size = 2;
  106. repack->repack_func = &repack_squash_swap;
  107. break;
  108. case repack_mode_8ch_swap23_swap46_swap57:
  109. repack->base_src_size = 8 * (16 / 8);
  110. repack->base_dst_size = 8 * (16 / 8);
  111. repack->extra_dst_size = 0;
  112. repack->repack_func = &repack_squash_swap;
  113. break;
  114. default: return -1;
  115. }
  116. return 0;
  117. }
  118. void audio_repack_free(struct audio_repack *repack)
  119. {
  120. if (repack->packet_buffer)
  121. bfree(repack->packet_buffer);
  122. memset(repack, 0, sizeof(*repack));
  123. }