BsAudioUtility.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsAudioUtility.h"
  4. namespace BansheeEngine
  5. {
  6. void convertToMono8(UINT8* input, UINT8* output, UINT32 numSamples, UINT32 numChannels)
  7. {
  8. for (UINT32 i = 0; i < numSamples; i++)
  9. {
  10. UINT16 sum = 0;
  11. for (UINT32 j = 0; j < numChannels; j++)
  12. {
  13. sum += *input;
  14. ++input;
  15. }
  16. *output = sum / numChannels;
  17. ++output;
  18. }
  19. }
  20. void convertToMono16(INT16* input, INT16* output, UINT32 numSamples, UINT32 numChannels)
  21. {
  22. for (UINT32 i = 0; i < numSamples; i++)
  23. {
  24. INT32 sum = 0;
  25. for (UINT32 j = 0; j < numChannels; j++)
  26. {
  27. sum += *input;
  28. ++input;
  29. }
  30. *output = sum / numChannels;
  31. ++output;
  32. }
  33. }
  34. INT32 convert24To32Bits(const UINT8* input)
  35. {
  36. bool isNegative = (input[2] & 0x80) != 0;
  37. if (isNegative) // Sign extend if negative
  38. return (0xFF << 24) | (input[2] << 16) | (input[1] << 8) | input[0];
  39. else
  40. return (input[2] << 16) | (input[1] << 8) | input[0];
  41. }
  42. void convert32To24Bits(INT32 input, UINT8* output)
  43. {
  44. UINT32 valToEncode = *(UINT32*)&input;
  45. output[0] = valToEncode & 0x000000FF;
  46. output[1] = (valToEncode >> 8) & 0x000000FF;
  47. output[2] = (valToEncode >> 16) & 0x000000FF;
  48. }
  49. void convertToMono24(UINT8* input, UINT8* output, UINT32 numSamples, UINT32 numChannels)
  50. {
  51. for (UINT32 i = 0; i < numSamples; i++)
  52. {
  53. INT32 sum = 0;
  54. for (UINT32 j = 0; j < numChannels; j++)
  55. {
  56. sum += convert24To32Bits(input);
  57. input += 3;
  58. }
  59. INT32 avg = sum / numChannels;
  60. convert32To24Bits(avg, output);
  61. output += 3;
  62. }
  63. }
  64. void convertToMono32(INT32* input, INT32* output, UINT32 numSamples, UINT32 numChannels)
  65. {
  66. for (UINT32 i = 0; i < numSamples; i++)
  67. {
  68. INT64 sum = 0;
  69. for (UINT32 j = 0; j < numChannels; j++)
  70. {
  71. sum += *input;
  72. ++input;
  73. }
  74. *output = (INT32)(sum / numChannels);
  75. ++output;
  76. }
  77. }
  78. void convert8To32Bits(UINT8* input, INT32* output, UINT32 numSamples)
  79. {
  80. for (UINT32 i = 0; i < numSamples; i++)
  81. {
  82. INT8 val = (INT8)(input[i] - 128);
  83. output[i] = val << 24;
  84. }
  85. }
  86. void convert16To32Bits(INT16* input, INT32* output, UINT32 numSamples)
  87. {
  88. for (UINT32 i = 0; i < numSamples; i++)
  89. output[i] = input[i] << 16;
  90. }
  91. void convert24To32Bits(UINT8* input, INT32* output, UINT32 numSamples)
  92. {
  93. for (UINT32 i = 0; i < numSamples; i++)
  94. {
  95. output[i] = convert24To32Bits(input);
  96. input += 3;
  97. }
  98. }
  99. void convert32To8Bits(INT32* input, UINT8* output, UINT32 numSamples)
  100. {
  101. for (UINT32 i = 0; i < numSamples; i++)
  102. {
  103. INT8 val = (INT8)(input[i] >> 24);
  104. output[i] = (UINT8)(val + 128);
  105. }
  106. }
  107. void convert32To16Bits(INT32* input, INT16* output, UINT32 numSamples)
  108. {
  109. for (UINT32 i = 0; i < numSamples; i++)
  110. output[i] = (INT16)(input[i] >> 16);
  111. }
  112. void convert32To24Bits(INT32* input, UINT8* output, UINT32 numSamples)
  113. {
  114. for (UINT32 i = 0; i < numSamples; i++)
  115. {
  116. convert32To24Bits(input[i], output);
  117. output += 3;
  118. }
  119. }
  120. void AudioUtility::convertToMono(UINT8* input, UINT8* output, UINT32 bitDepth, UINT32 numSamples, UINT32 numChannels)
  121. {
  122. switch (bitDepth)
  123. {
  124. case 8:
  125. convertToMono8(input, output, numSamples, numChannels);
  126. break;
  127. case 16:
  128. convertToMono16((INT16*)input, (INT16*)output, numSamples, numChannels);
  129. break;
  130. case 24:
  131. convertToMono24(input, output, numSamples, numChannels);
  132. break;
  133. case 32:
  134. convertToMono32((INT32*)input, (INT32*)output, numSamples, numChannels);
  135. break;
  136. default:
  137. assert(false);
  138. break;
  139. }
  140. }
  141. void AudioUtility::convertBitDepth(UINT8* input, UINT32 inBitDepth, UINT8* output, UINT32 outBitDepth, UINT32 numSamples)
  142. {
  143. INT32* srcBuffer = nullptr;
  144. bool needTempBuffer = inBitDepth != 32;
  145. if (needTempBuffer)
  146. srcBuffer = (INT32*)bs_stack_alloc(numSamples * sizeof(INT32));
  147. else
  148. srcBuffer = (INT32*)input;
  149. // Note: I convert to a temporary 32-bit buffer and then use that to convert to actual requested bit depth.
  150. // It would be more efficient to convert directly from source to requested depth without a temporary buffer,
  151. // at the cost of additional complexity. If this method ever becomes a performance issue consider that.
  152. switch (inBitDepth)
  153. {
  154. case 8:
  155. convert8To32Bits(input, srcBuffer, numSamples);
  156. break;
  157. case 16:
  158. convert16To32Bits((INT16*)input, srcBuffer, numSamples);
  159. break;
  160. case 24:
  161. convert8To32Bits(input, srcBuffer, numSamples);
  162. break;
  163. case 32:
  164. // Do nothing
  165. break;
  166. default:
  167. assert(false);
  168. break;
  169. }
  170. switch (outBitDepth)
  171. {
  172. case 8:
  173. convert32To8Bits(srcBuffer, output, numSamples);
  174. break;
  175. case 16:
  176. convert32To16Bits(srcBuffer, (INT16*)output, numSamples);
  177. break;
  178. case 24:
  179. convert32To24Bits(srcBuffer, output, numSamples);
  180. break;
  181. case 32:
  182. memcpy(output, srcBuffer, numSamples * sizeof(INT32));
  183. break;
  184. default:
  185. assert(false);
  186. break;
  187. }
  188. if (needTempBuffer)
  189. {
  190. bs_stack_free(srcBuffer);
  191. srcBuffer = nullptr;
  192. }
  193. }
  194. }