channels.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. /*
  2. * Copyright (C) 2014 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <string.h>
  17. #include <audio_utils/channels.h>
  18. #include "private/private.h"
  19. /*
  20. * Clamps a 24-bit value from a 32-bit sample
  21. */
  22. static inline int32_t clamp24(int32_t sample)
  23. {
  24. if ((sample>>23) ^ (sample>>31)) {
  25. sample = 0x007FFFFF ^ (sample>>31);
  26. }
  27. return sample;
  28. }
  29. /*
  30. * Converts a uint8x3_t into an int32_t
  31. */
  32. static inline int32_t uint8x3_to_int32(uint8x3_t val) {
  33. #if HAVE_BIG_ENDIAN
  34. int32_t temp = (val.c[0] << 24 | val.c[1] << 16 | val.c[2] << 8) >> 8;
  35. #else
  36. int32_t temp = (val.c[2] << 24 | val.c[1] << 16 | val.c[0] << 8) >> 8;
  37. #endif
  38. return clamp24(temp);
  39. }
  40. /*
  41. * Converts an int32_t to a uint8x3_t
  42. */
  43. static inline uint8x3_t int32_to_uint8x3(int32_t in) {
  44. uint8x3_t out;
  45. #if HAVE_BIG_ENDIAN
  46. out.c[2] = in;
  47. out.c[1] = in >> 8;
  48. out.c[0] = in >> 16;
  49. #else
  50. out.c[0] = in;
  51. out.c[1] = in >> 8;
  52. out.c[2] = in >> 16;
  53. #endif
  54. return out;
  55. }
  56. /* This is written as a C macro because it operates on generic types,
  57. * which in a C++ file could be alternatively achieved by a "template"
  58. * or an "auto" declaration.
  59. * TODO: convert this from a C file to a C++ file.
  60. */
  61. /* Channel expands (adds zeroes to audio frame end) from an input buffer to an output buffer.
  62. * See expand_channels() function below for parameter definitions.
  63. *
  64. * Move from back to front so that the conversion can be done in-place
  65. * i.e. in_buff == out_buff
  66. * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
  67. *
  68. * Macro has a return statement.
  69. */
  70. #define EXPAND_CHANNELS(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes, zero) \
  71. { \
  72. size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
  73. size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
  74. typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \
  75. size_t src_index; \
  76. typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \
  77. size_t num_zero_chans = (out_buff_chans) - (in_buff_chans); \
  78. for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
  79. size_t dst_offset; \
  80. for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) { \
  81. *dst_ptr-- = zero; \
  82. } \
  83. for (; dst_offset < (out_buff_chans); dst_offset++) { \
  84. *dst_ptr-- = *src_ptr--; \
  85. } \
  86. } \
  87. /* return number of *bytes* generated */ \
  88. return num_out_samples * sizeof(*(out_buff)); \
  89. }
  90. /* Channel expands from an input buffer to an output buffer.
  91. * See expand_selected_channels() function below for parameter definitions.
  92. * Selected channels are replaced in the output buffer, with any extra channels
  93. * per frame left alone.
  94. *
  95. * Move from back to front so that the conversion can be done in-place
  96. * i.e. in_buff == out_buff
  97. * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
  98. *
  99. * Macro has a return statement.
  100. */
  101. #define EXPAND_SELECTED_CHANNELS( \
  102. in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes) \
  103. { \
  104. size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
  105. size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
  106. typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \
  107. size_t src_index; \
  108. typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \
  109. size_t num_extra_chans = (out_buff_chans) - (in_buff_chans); \
  110. for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
  111. dst_ptr -= num_extra_chans; \
  112. for (size_t dst_offset = num_extra_chans; dst_offset < (out_buff_chans); dst_offset++) { \
  113. *dst_ptr-- = *src_ptr--; \
  114. } \
  115. } \
  116. /* return number of *bytes* generated */ \
  117. return num_out_samples * sizeof(*(out_buff)); \
  118. }
  119. /* Expand number of channels from an input buffer to an output buffer.
  120. * See expand_channels_non_destructive() function below for parameter definitions.
  121. *
  122. * Input channels are copied to the output buffer, with extra output
  123. * channels interleaved from back of input buffer.
  124. *
  125. * So for in_chans = 2, out_chans = 4: [1|2|1|2...|3|4|3|4] => [1|2|3|4|1|2|3|4...]
  126. *
  127. * NOTE: in_buff must be same size as out_buff and num_in_bytes must
  128. * be a multiple of in_buff_channels * in_buff_sample_size.
  129. *
  130. * Uses a temporary buffer so that the conversion can be done in-place
  131. * i.e. in_buff == out_buff
  132. *
  133. * Macro has a return statement.
  134. */
  135. #define EXPAND_CHANNELS_NON_DESTRUCTIVE(in_buff, in_buff_chans, \
  136. out_buff, out_buff_chans, num_in_bytes) \
  137. { \
  138. size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
  139. size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
  140. typeof(out_buff) dst_ptr = (out_buff); \
  141. typeof(in_buff) src_ptr = (in_buff); \
  142. typeof(*out_buff) temp_buff[num_in_samples]; \
  143. typeof(out_buff) temp_ptr = temp_buff; \
  144. /* if in-place, copy input channels to a temp buffer */ \
  145. if ((in_buff) == (out_buff)) { \
  146. memcpy(temp_buff, src_ptr, (num_in_bytes)); \
  147. src_ptr += num_in_samples; \
  148. } else { \
  149. temp_ptr = (typeof(out_buff)) src_ptr; \
  150. src_ptr += num_in_samples; \
  151. } \
  152. /* interleave channels from end of source buffer with those from front */ \
  153. size_t src_index; \
  154. for (src_index = 0; src_index < num_out_samples; src_index += (out_buff_chans)) { \
  155. size_t dst_offset; \
  156. for (dst_offset = 0; dst_offset < (in_buff_chans); dst_offset++) { \
  157. *dst_ptr++ = *temp_ptr++; \
  158. } \
  159. for (;dst_offset < (out_buff_chans); dst_offset++) { \
  160. *dst_ptr++ = *src_ptr++; \
  161. } \
  162. } \
  163. /* return number of *bytes* generated */ \
  164. return num_out_samples * sizeof(*(out_buff)); \
  165. }
  166. /* Channel expands from a MONO input buffer to a MULTICHANNEL output buffer by duplicating the
  167. * single input channel to the first 2 output channels and 0-filling the remaining.
  168. * See expand_channels() function below for parameter definitions.
  169. *
  170. * in_buff_chans MUST be 1 and out_buff_chans MUST be >= 2
  171. *
  172. * Move from back to front so that the conversion can be done in-place
  173. * i.e. in_buff == out_buff
  174. * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
  175. *
  176. * Macro has a return statement.
  177. */
  178. #define EXPAND_MONO_TO_MULTI(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes, zero) \
  179. { \
  180. size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
  181. size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
  182. typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \
  183. size_t src_index; \
  184. typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \
  185. size_t num_zero_chans = (out_buff_chans) - (in_buff_chans) - 1; \
  186. for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
  187. size_t dst_offset; \
  188. for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) { \
  189. *dst_ptr-- = zero; \
  190. } \
  191. for (; dst_offset < (out_buff_chans); dst_offset++) { \
  192. *dst_ptr-- = *src_ptr; \
  193. } \
  194. src_ptr--; \
  195. } \
  196. /* return number of *bytes* generated */ \
  197. return num_out_samples * sizeof(*(out_buff)); \
  198. }
  199. /* Channel contracts (removes from audio frame end) from an input buffer to an output buffer.
  200. * See contract_channels() function below for parameter definitions.
  201. *
  202. * Move from front to back so that the conversion can be done in-place
  203. * i.e. in_buff == out_buff
  204. * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
  205. *
  206. * Macro has a return statement.
  207. */
  208. #define CONTRACT_CHANNELS(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes) \
  209. { \
  210. size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
  211. size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
  212. size_t num_skip_samples = (in_buff_chans) - (out_buff_chans); \
  213. typeof(out_buff) dst_ptr = out_buff; \
  214. typeof(in_buff) src_ptr = in_buff; \
  215. size_t src_index; \
  216. for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
  217. size_t dst_offset; \
  218. for (dst_offset = 0; dst_offset < (out_buff_chans); dst_offset++) { \
  219. *dst_ptr++ = *src_ptr++; \
  220. } \
  221. src_ptr += num_skip_samples; \
  222. } \
  223. /* return number of *bytes* generated */ \
  224. return num_out_samples * sizeof(*(out_buff)); \
  225. }
  226. /* Contract number of channels from an input buffer to an output buffer,
  227. * storing removed channels at end of buffer.
  228. *
  229. * See contract_channels_non_destructive() function below for parameter definitions.
  230. *
  231. * So for in_chans = 4, out_chans = 2: [1|2|3|4|1|2|3|4...] => [1|2|1|2...|3|4|3|4]
  232. *
  233. * NOTE: in_buff must be same size as out_buff and num_in_bytes must
  234. * be a multiple of in_buff_channels * in_buff_sample_size.
  235. *
  236. * Uses a temporary buffer so that the conversion can be done in-place
  237. * i.e. in_buff == out_buff
  238. *
  239. * Macro has a return statement.
  240. */
  241. #define CONTRACT_CHANNELS_NON_DESTRUCTIVE(in_buff, in_buff_chans, out_buff, \
  242. out_buff_chans, num_in_bytes) \
  243. { \
  244. size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
  245. size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
  246. typeof(out_buff) dst_ptr = (out_buff); \
  247. typeof(in_buff) src_ptr = (in_buff); \
  248. size_t num_temp_samples = num_in_samples - num_out_samples; \
  249. typeof(*out_buff) temp_buff[num_temp_samples]; \
  250. typeof(out_buff) temp_ptr; \
  251. /* if in-place, copy input channels to a temp buffer instead of out buffer */ \
  252. if ((in_buff) == (out_buff)) { \
  253. temp_ptr = temp_buff; \
  254. } else { \
  255. temp_ptr = dst_ptr + num_out_samples; \
  256. } \
  257. size_t src_index; \
  258. for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
  259. size_t dst_offset; \
  260. for (dst_offset = 0; dst_offset < (out_buff_chans); dst_offset++) { \
  261. *dst_ptr++ = *src_ptr++; \
  262. } \
  263. for (;dst_offset < (in_buff_chans); dst_offset++) { \
  264. *temp_ptr++ = *src_ptr++; \
  265. } \
  266. } \
  267. /* if in-place, interleave channels from the temp buffer */ \
  268. if ((in_buff) == (out_buff)) { \
  269. temp_ptr = temp_buff; \
  270. memcpy(dst_ptr, temp_ptr, num_temp_samples * sizeof(*(in_buff))); \
  271. } \
  272. /* return number of *bytes* generated */ \
  273. return num_out_samples * sizeof(*(out_buff)); \
  274. }
  275. /* Channel contracts from a MULTICHANNEL input buffer to a MONO output buffer by mixing the
  276. * first two input channels into the single output channel (and skipping the rest).
  277. * See contract_channels() function below for parameter definitions.
  278. *
  279. * in_buff_chans MUST be >= 2 and out_buff_chans MUST be 1
  280. *
  281. * Move from front to back so that the conversion can be done in-place
  282. * i.e. in_buff == out_buff
  283. * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
  284. * NOTE: Overload of the summed channels is avoided by averaging the two input channels.
  285. * NOTE: Can not be used for uint8x3_t samples, see CONTRACT_TO_MONO_24() below.
  286. *
  287. * Macro has a return statement.
  288. */
  289. #define CONTRACT_TO_MONO(in_buff, out_buff, num_in_bytes) \
  290. { \
  291. size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
  292. size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
  293. size_t num_skip_samples = in_buff_chans - 2; \
  294. typeof(out_buff) dst_ptr = out_buff; \
  295. typeof(in_buff) src_ptr = in_buff; \
  296. int32_t temp0, temp1; \
  297. size_t src_index; \
  298. for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \
  299. temp0 = *src_ptr++; \
  300. temp1 = *src_ptr++; \
  301. /* *dst_ptr++ = temp >> 1; */ \
  302. /* This bit of magic adds and normalizes without overflow (or so claims hunga@) */ \
  303. /* Bitwise half adder trick, see http://en.wikipedia.org/wiki/Adder_(electronics) */ \
  304. /* Hacker's delight, p. 19 http://www.hackersdelight.org/basics2.pdf */ \
  305. *dst_ptr++ = (temp0 & temp1) + ((temp0 ^ temp1) >> 1); \
  306. src_ptr += num_skip_samples; \
  307. } \
  308. /* return number of *bytes* generated */ \
  309. return num_out_samples * sizeof(*(out_buff)); \
  310. }
  311. /* Channel contracts from a MULTICHANNEL uint8x3_t input buffer to a MONO uint8x3_t output buffer
  312. * by mixing the first two input channels into the single output channel (and skipping the rest).
  313. * See contract_channels() function below for parameter definitions.
  314. *
  315. * Move from front to back so that the conversion can be done in-place
  316. * i.e. in_buff == out_buff
  317. * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
  318. * NOTE: Overload of the summed channels is avoided by averaging the two input channels.
  319. * NOTE: Can not be used for normal, scalar samples, see CONTRACT_TO_MONO() above.
  320. *
  321. * Macro has a return statement.
  322. */
  323. #define CONTRACT_TO_MONO_24(in_buff, out_buff, num_in_bytes) \
  324. { \
  325. size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
  326. size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
  327. size_t num_skip_samples = in_buff_chans - 2; \
  328. typeof(out_buff) dst_ptr = out_buff; \
  329. typeof(in_buff) src_ptr = in_buff; \
  330. int32_t temp; \
  331. size_t src_index; \
  332. for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \
  333. temp = uint8x3_to_int32(*src_ptr++); \
  334. temp += uint8x3_to_int32(*src_ptr++); \
  335. *dst_ptr = int32_to_uint8x3(temp >> 1); \
  336. src_ptr += num_skip_samples; \
  337. } \
  338. /* return number of *bytes* generated */ \
  339. return num_out_samples * sizeof(*(out_buff)); \
  340. }
  341. /*
  342. * Convert a buffer of N-channel, interleaved samples to M-channel
  343. * (where N > M).
  344. * in_buff points to the buffer of samples
  345. * in_buff_channels Specifies the number of channels in the input buffer.
  346. * out_buff points to the buffer to receive converted samples.
  347. * out_buff_channels Specifies the number of channels in the output buffer.
  348. * sample_size_in_bytes Specifies the number of bytes per sample.
  349. * num_in_bytes size of input buffer in BYTES
  350. * returns
  351. * the number of BYTES of output data.
  352. * NOTE
  353. * channels > M are thrown away.
  354. * The out and sums buffers must either be completely separate (non-overlapping), or
  355. * they must both start at the same address. Partially overlapping buffers are not supported.
  356. */
  357. static size_t contract_channels(const void* in_buff, size_t in_buff_chans,
  358. void* out_buff, size_t out_buff_chans,
  359. unsigned sample_size_in_bytes, size_t num_in_bytes)
  360. {
  361. switch (sample_size_in_bytes) {
  362. case 1:
  363. if (out_buff_chans == 1) {
  364. /* Special case Multi to Mono */
  365. CONTRACT_TO_MONO((const uint8_t*)in_buff, (uint8_t*)out_buff, num_in_bytes);
  366. // returns in macro
  367. } else {
  368. CONTRACT_CHANNELS((const uint8_t*)in_buff, in_buff_chans,
  369. (uint8_t*)out_buff, out_buff_chans,
  370. num_in_bytes);
  371. // returns in macro
  372. }
  373. case 2:
  374. if (out_buff_chans == 1) {
  375. /* Special case Multi to Mono */
  376. CONTRACT_TO_MONO((const int16_t*)in_buff, (int16_t*)out_buff, num_in_bytes);
  377. // returns in macro
  378. } else {
  379. CONTRACT_CHANNELS((const int16_t*)in_buff, in_buff_chans,
  380. (int16_t*)out_buff, out_buff_chans,
  381. num_in_bytes);
  382. // returns in macro
  383. }
  384. case 3:
  385. if (out_buff_chans == 1) {
  386. /* Special case Multi to Mono */
  387. CONTRACT_TO_MONO_24((const uint8x3_t*)in_buff,
  388. (uint8x3_t*)out_buff, num_in_bytes);
  389. // returns in macro
  390. } else {
  391. CONTRACT_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans,
  392. (uint8x3_t*)out_buff, out_buff_chans,
  393. num_in_bytes);
  394. // returns in macro
  395. }
  396. case 4:
  397. if (out_buff_chans == 1) {
  398. /* Special case Multi to Mono */
  399. CONTRACT_TO_MONO((const int32_t*)in_buff, (int32_t*)out_buff, num_in_bytes);
  400. // returns in macro
  401. } else {
  402. CONTRACT_CHANNELS((const int32_t*)in_buff, in_buff_chans,
  403. (int32_t*)out_buff, out_buff_chans,
  404. num_in_bytes);
  405. // returns in macro
  406. }
  407. default:
  408. return 0;
  409. }
  410. }
  411. /*
  412. * Convert a buffer of N-channel, interleaved samples to M-channel
  413. * (where N > M).
  414. * in_buff points to the buffer of samples
  415. * in_buff_channels specifies the number of channels in the input buffer.
  416. * out_buff points to the buffer to receive converted samples.
  417. * out_buff_channels specifies the number of channels in the output buffer.
  418. * sample_size_in_bytes specifies the number of bytes per sample.
  419. * num_in_bytes size of input buffer in BYTES
  420. * returns
  421. * the number of BYTES of output data.
  422. * NOTE
  423. * channels > M are stored at the end of the output buffer.
  424. * The output and input buffers must be the same length.
  425. * The output and input buffers must either be completely separate (non-overlapping), or
  426. * they must both start at the same address. Partially overlapping buffers are not supported.
  427. */
  428. static size_t contract_channels_non_destructive(const void* in_buff, size_t in_buff_chans,
  429. void* out_buff, size_t out_buff_chans,
  430. unsigned sample_size_in_bytes, size_t num_in_bytes)
  431. {
  432. switch (sample_size_in_bytes) {
  433. case 1:
  434. CONTRACT_CHANNELS_NON_DESTRUCTIVE((const uint8_t*)in_buff, in_buff_chans,
  435. (uint8_t*)out_buff, out_buff_chans,
  436. num_in_bytes);
  437. // returns in macro
  438. case 2:
  439. CONTRACT_CHANNELS_NON_DESTRUCTIVE((const int16_t*)in_buff, in_buff_chans,
  440. (int16_t*)out_buff, out_buff_chans,
  441. num_in_bytes);
  442. // returns in macro
  443. case 3:
  444. CONTRACT_CHANNELS_NON_DESTRUCTIVE((const uint8x3_t*)in_buff, in_buff_chans,
  445. (uint8x3_t*)out_buff, out_buff_chans,
  446. num_in_bytes);
  447. // returns in macro
  448. case 4:
  449. CONTRACT_CHANNELS_NON_DESTRUCTIVE((const int32_t*)in_buff, in_buff_chans,
  450. (int32_t*)out_buff, out_buff_chans,
  451. num_in_bytes);
  452. // returns in macro
  453. default:
  454. return 0;
  455. }
  456. }
  457. /*
  458. * Convert a buffer of N-channel, interleaved samples to M-channel
  459. * (where N < M).
  460. * in_buff points to the buffer of samples
  461. * in_buff_channels Specifies the number of channels in the input buffer.
  462. * out_buff points to the buffer to receive converted samples.
  463. * out_buff_channels Specifies the number of channels in the output buffer.
  464. * sample_size_in_bytes Specifies the number of bytes per sample.
  465. * num_in_bytes size of input buffer in BYTES
  466. * returns
  467. * the number of BYTES of output data.
  468. * NOTE
  469. * channels > N are filled with silence.
  470. * The out and sums buffers must either be completely separate (non-overlapping), or
  471. * they must both start at the same address. Partially overlapping buffers are not supported.
  472. */
  473. static size_t expand_channels(const void* in_buff, size_t in_buff_chans,
  474. void* out_buff, size_t out_buff_chans,
  475. unsigned sample_size_in_bytes, size_t num_in_bytes)
  476. {
  477. static const uint8x3_t packed24_zero; /* zero 24 bit sample */
  478. switch (sample_size_in_bytes) {
  479. case 1:
  480. if (in_buff_chans == 1) {
  481. /* special case of mono source to multi-channel */
  482. EXPAND_MONO_TO_MULTI((const uint8_t*)in_buff, in_buff_chans,
  483. (uint8_t*)out_buff, out_buff_chans,
  484. num_in_bytes, 0);
  485. // returns in macro
  486. } else {
  487. EXPAND_CHANNELS((const uint8_t*)in_buff, in_buff_chans,
  488. (uint8_t*)out_buff, out_buff_chans,
  489. num_in_bytes, 0);
  490. // returns in macro
  491. }
  492. case 2:
  493. if (in_buff_chans == 1) {
  494. /* special case of mono source to multi-channel */
  495. EXPAND_MONO_TO_MULTI((const int16_t*)in_buff, in_buff_chans,
  496. (int16_t*)out_buff, out_buff_chans,
  497. num_in_bytes, 0);
  498. // returns in macro
  499. } else {
  500. EXPAND_CHANNELS((const int16_t*)in_buff, in_buff_chans,
  501. (int16_t*)out_buff, out_buff_chans,
  502. num_in_bytes, 0);
  503. // returns in macro
  504. }
  505. case 3:
  506. if (in_buff_chans == 1) {
  507. /* special case of mono source to multi-channel */
  508. EXPAND_MONO_TO_MULTI((const uint8x3_t*)in_buff, in_buff_chans,
  509. (uint8x3_t*)out_buff, out_buff_chans,
  510. num_in_bytes, packed24_zero);
  511. // returns in macro
  512. } else {
  513. EXPAND_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans,
  514. (uint8x3_t*)out_buff, out_buff_chans,
  515. num_in_bytes, packed24_zero);
  516. // returns in macro
  517. }
  518. case 4:
  519. if (in_buff_chans == 1) {
  520. /* special case of mono source to multi-channel */
  521. EXPAND_MONO_TO_MULTI((const int32_t*)in_buff, in_buff_chans,
  522. (int32_t*)out_buff, out_buff_chans,
  523. num_in_bytes, 0);
  524. // returns in macro
  525. } else {
  526. EXPAND_CHANNELS((const int32_t*)in_buff, in_buff_chans,
  527. (int32_t*)out_buff, out_buff_chans,
  528. num_in_bytes, 0);
  529. // returns in macro
  530. }
  531. default:
  532. return 0;
  533. }
  534. }
  535. /*
  536. * Convert a buffer of N-channel, interleaved samples to M-channel
  537. * (where N < M).
  538. * in_buff points to the buffer of samples
  539. * in_buff_channels Specifies the number of channels in the input buffer.
  540. * out_buff points to the buffer to receive converted samples.
  541. * out_buff_channels Specifies the number of channels in the output buffer.
  542. * sample_size_in_bytes Specifies the number of bytes per sample.
  543. * num_in_bytes size of input buffer in BYTES
  544. * returns
  545. * the number of BYTES of output data.
  546. * NOTE
  547. * channels > N are left alone in out_buff.
  548. * The out and in buffers must either be completely separate (non-overlapping), or
  549. * they must both start at the same address. Partially overlapping buffers are not supported.
  550. */
  551. static size_t expand_selected_channels(const void* in_buff, size_t in_buff_chans,
  552. void* out_buff, size_t out_buff_chans,
  553. unsigned sample_size_in_bytes, size_t num_in_bytes)
  554. {
  555. switch (sample_size_in_bytes) {
  556. case 1:
  557. EXPAND_SELECTED_CHANNELS((const uint8_t*)in_buff, in_buff_chans,
  558. (uint8_t*)out_buff, out_buff_chans,
  559. num_in_bytes);
  560. // returns in macro
  561. case 2:
  562. EXPAND_SELECTED_CHANNELS((const int16_t*)in_buff, in_buff_chans,
  563. (int16_t*)out_buff, out_buff_chans,
  564. num_in_bytes);
  565. // returns in macro
  566. case 3:
  567. EXPAND_SELECTED_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans,
  568. (uint8x3_t*)out_buff, out_buff_chans,
  569. num_in_bytes);
  570. // returns in macro
  571. case 4:
  572. EXPAND_SELECTED_CHANNELS((const int32_t*)in_buff, in_buff_chans,
  573. (int32_t*)out_buff, out_buff_chans,
  574. num_in_bytes);
  575. // returns in macro
  576. default:
  577. return 0;
  578. }
  579. }
  580. /*
  581. * Convert a buffer of N-channel, interleaved samples to M-channel
  582. * (where N < M).
  583. * in_buff points to the buffer of samples
  584. * in_buff_channels Specifies the number of channels in the input buffer.
  585. * out_buff points to the buffer to receive converted samples.
  586. * out_buff_channels Specifies the number of channels in the output buffer.
  587. * sample_size_in_bytes Specifies the number of bytes per sample.
  588. * num_in_bytes size of input buffer in BYTES
  589. * returns
  590. * the number of BYTES of output data.
  591. * NOTE
  592. * channels > N are interleaved with data from the end of the input buffer.
  593. * The output and input buffers must be the same length.
  594. * The output and input buffers must either be completely separate (non-overlapping), or
  595. * they must both start at the same address. Partially overlapping buffers are not supported.
  596. */
  597. static size_t expand_channels_non_destructive(const void* in_buff, size_t in_buff_chans,
  598. void* out_buff, size_t out_buff_chans,
  599. unsigned sample_size_in_bytes, size_t num_in_bytes)
  600. {
  601. switch (sample_size_in_bytes) {
  602. case 1:
  603. EXPAND_CHANNELS_NON_DESTRUCTIVE((const uint8_t*)in_buff, in_buff_chans,
  604. (uint8_t*)out_buff, out_buff_chans,
  605. num_in_bytes);
  606. // returns in macro
  607. case 2:
  608. EXPAND_CHANNELS_NON_DESTRUCTIVE((const int16_t*)in_buff, in_buff_chans,
  609. (int16_t*)out_buff, out_buff_chans,
  610. num_in_bytes);
  611. // returns in macro
  612. case 3:
  613. EXPAND_CHANNELS_NON_DESTRUCTIVE((const uint8x3_t*)in_buff, in_buff_chans,
  614. (uint8x3_t*)out_buff, out_buff_chans,
  615. num_in_bytes);
  616. // returns in macro
  617. case 4:
  618. EXPAND_CHANNELS_NON_DESTRUCTIVE((const int32_t*)in_buff, in_buff_chans,
  619. (int32_t*)out_buff, out_buff_chans,
  620. num_in_bytes);
  621. // returns in macro
  622. default:
  623. return 0;
  624. }
  625. }
  626. size_t adjust_channels(const void* in_buff, size_t in_buff_chans,
  627. void* out_buff, size_t out_buff_chans,
  628. unsigned sample_size_in_bytes, size_t num_in_bytes)
  629. {
  630. if (out_buff_chans > in_buff_chans) {
  631. return expand_channels(in_buff, in_buff_chans, out_buff, out_buff_chans,
  632. sample_size_in_bytes, num_in_bytes);
  633. } else if (out_buff_chans < in_buff_chans) {
  634. return contract_channels(in_buff, in_buff_chans, out_buff, out_buff_chans,
  635. sample_size_in_bytes, num_in_bytes);
  636. } else if (in_buff != out_buff) {
  637. memcpy(out_buff, in_buff, num_in_bytes);
  638. }
  639. return num_in_bytes;
  640. }
  641. size_t adjust_selected_channels(const void* in_buff, size_t in_buff_chans,
  642. void* out_buff, size_t out_buff_chans,
  643. unsigned sample_size_in_bytes, size_t num_in_bytes)
  644. {
  645. if (out_buff_chans > in_buff_chans) {
  646. return expand_selected_channels(in_buff, in_buff_chans, out_buff, out_buff_chans,
  647. sample_size_in_bytes, num_in_bytes);
  648. } else if (out_buff_chans < in_buff_chans) {
  649. return contract_channels(in_buff, in_buff_chans, out_buff, out_buff_chans,
  650. sample_size_in_bytes, num_in_bytes);
  651. } else if (in_buff != out_buff) {
  652. memcpy(out_buff, in_buff, num_in_bytes);
  653. }
  654. return num_in_bytes;
  655. }
  656. size_t adjust_channels_non_destructive(const void* in_buff, size_t in_buff_chans,
  657. void* out_buff, size_t out_buff_chans,
  658. unsigned sample_size_in_bytes, size_t num_in_bytes)
  659. {
  660. if (out_buff_chans > in_buff_chans) {
  661. return expand_channels_non_destructive(in_buff, in_buff_chans, out_buff, out_buff_chans,
  662. sample_size_in_bytes, num_in_bytes);
  663. } else if (out_buff_chans < in_buff_chans) {
  664. return contract_channels_non_destructive(in_buff, in_buff_chans, out_buff, out_buff_chans,
  665. sample_size_in_bytes, num_in_bytes);
  666. } else if (in_buff != out_buff) {
  667. memcpy(out_buff, in_buff, num_in_bytes);
  668. }
  669. return num_in_bytes;
  670. }