You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

488 lines
17KB

  1. /* Audio Library for Teensy 3.X
  2. * Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com
  3. *
  4. * Development of this audio library was funded by PJRC.COM, LLC by sales of
  5. * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
  6. * open source software by purchasing Teensy or other PJRC products.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice, development funding notice, and this permission
  16. * notice shall be included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. // A fixed point implementation of Freeverb by Jezar at Dreampoint
  27. // http://blog.bjornroche.com/2012/06/freeverb-original-public-domain-code-by.html
  28. // https://music.columbia.edu/pipermail/music-dsp/2001-October/045433.html
  29. #include <Arduino.h>
  30. #include "effect_freeverb.h"
  31. #include "utility/dspinst.h"
  32. AudioEffectFreeverb::AudioEffectFreeverb() : AudioStream(1, inputQueueArray)
  33. {
  34. memset(comb1buf, 0, sizeof(comb1buf));
  35. memset(comb2buf, 0, sizeof(comb2buf));
  36. memset(comb3buf, 0, sizeof(comb3buf));
  37. memset(comb4buf, 0, sizeof(comb4buf));
  38. memset(comb5buf, 0, sizeof(comb5buf));
  39. memset(comb6buf, 0, sizeof(comb6buf));
  40. memset(comb7buf, 0, sizeof(comb7buf));
  41. memset(comb8buf, 0, sizeof(comb8buf));
  42. comb1index = 0;
  43. comb2index = 0;
  44. comb3index = 0;
  45. comb4index = 0;
  46. comb5index = 0;
  47. comb6index = 0;
  48. comb7index = 0;
  49. comb8index = 0;
  50. comb1filter = 0;
  51. comb2filter = 0;
  52. comb3filter = 0;
  53. comb4filter = 0;
  54. comb5filter = 0;
  55. comb6filter = 0;
  56. comb7filter = 0;
  57. comb8filter = 0;
  58. combdamp1 = 6553;
  59. combdamp2 = 26215;
  60. combfeeback = 27524;
  61. memset(allpass1buf, 0, sizeof(allpass1buf));
  62. memset(allpass2buf, 0, sizeof(allpass2buf));
  63. memset(allpass3buf, 0, sizeof(allpass3buf));
  64. memset(allpass4buf, 0, sizeof(allpass4buf));
  65. allpass1index = 0;
  66. allpass2index = 0;
  67. allpass3index = 0;
  68. allpass4index = 0;
  69. }
  70. // cleaner sat16 by http://www.moseleyinstruments.com/
  71. __attribute__((unused))
  72. static int16_t sat16(int32_t n, int rshift) {
  73. // we should always round towards 0
  74. // to avoid recirculating round-off noise
  75. //
  76. // a 2s complement positive number is always
  77. // rounded down, so we only need to take
  78. // care of negative numbers
  79. if (n < 0) {
  80. n = n + (~(0xFFFFFFFFUL << rshift));
  81. }
  82. n = n >> rshift;
  83. if (n > 32767) {
  84. return 32767;
  85. }
  86. if (n < -32768) {
  87. return -32768;
  88. }
  89. return n;
  90. }
  91. // TODO: move this to one of the data files, use in output_adat.cpp, output_tdm.cpp, etc
  92. static const audio_block_t zeroblock = {
  93. 0, 0, 0, {
  94. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  95. #if AUDIO_BLOCK_SAMPLES > 16
  96. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  97. #endif
  98. #if AUDIO_BLOCK_SAMPLES > 32
  99. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  100. #endif
  101. #if AUDIO_BLOCK_SAMPLES > 48
  102. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  103. #endif
  104. #if AUDIO_BLOCK_SAMPLES > 64
  105. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  106. #endif
  107. #if AUDIO_BLOCK_SAMPLES > 80
  108. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  109. #endif
  110. #if AUDIO_BLOCK_SAMPLES > 96
  111. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  112. #endif
  113. #if AUDIO_BLOCK_SAMPLES > 112
  114. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  115. #endif
  116. } };
  117. void AudioEffectFreeverb::update()
  118. {
  119. #if defined(__ARM_ARCH_7EM__)
  120. const audio_block_t *block;
  121. audio_block_t *outblock;
  122. int i;
  123. int16_t input, bufout, output;
  124. int32_t sum;
  125. outblock = allocate();
  126. if (!outblock) {
  127. audio_block_t *tmp = receiveReadOnly(0);
  128. if (tmp) release(tmp);
  129. return;
  130. }
  131. block = receiveReadOnly(0);
  132. if (!block) block = &zeroblock;
  133. for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
  134. // TODO: scale numerical range depending on roomsize & damping
  135. input = sat16(block->data[i] * 8738, 17); // for numerical headroom
  136. sum = 0;
  137. bufout = comb1buf[comb1index];
  138. sum += bufout;
  139. comb1filter = sat16(bufout * combdamp2 + comb1filter * combdamp1, 15);
  140. comb1buf[comb1index] = sat16(input + sat16(comb1filter * combfeeback, 15), 0);
  141. if (++comb1index >= sizeof(comb1buf)/sizeof(int16_t)) comb1index = 0;
  142. bufout = comb2buf[comb2index];
  143. sum += bufout;
  144. comb2filter = sat16(bufout * combdamp2 + comb2filter * combdamp1, 15);
  145. comb2buf[comb2index] = sat16(input + sat16(comb2filter * combfeeback, 15), 0);
  146. if (++comb2index >= sizeof(comb2buf)/sizeof(int16_t)) comb2index = 0;
  147. bufout = comb3buf[comb3index];
  148. sum += bufout;
  149. comb3filter = sat16(bufout * combdamp2 + comb3filter * combdamp1, 15);
  150. comb3buf[comb3index] = sat16(input + sat16(comb3filter * combfeeback, 15), 0);
  151. if (++comb3index >= sizeof(comb3buf)/sizeof(int16_t)) comb3index = 0;
  152. bufout = comb4buf[comb4index];
  153. sum += bufout;
  154. comb4filter = sat16(bufout * combdamp2 + comb4filter * combdamp1, 15);
  155. comb4buf[comb4index] = sat16(input + sat16(comb4filter * combfeeback, 15), 0);
  156. if (++comb4index >= sizeof(comb4buf)/sizeof(int16_t)) comb4index = 0;
  157. bufout = comb5buf[comb5index];
  158. sum += bufout;
  159. comb5filter = sat16(bufout * combdamp2 + comb5filter * combdamp1, 15);
  160. comb5buf[comb5index] = sat16(input + sat16(comb5filter * combfeeback, 15), 0);
  161. if (++comb5index >= sizeof(comb5buf)/sizeof(int16_t)) comb5index = 0;
  162. bufout = comb6buf[comb6index];
  163. sum += bufout;
  164. comb6filter = sat16(bufout * combdamp2 + comb6filter * combdamp1, 15);
  165. comb6buf[comb6index] = sat16(input + sat16(comb6filter * combfeeback, 15), 0);
  166. if (++comb6index >= sizeof(comb6buf)/sizeof(int16_t)) comb6index = 0;
  167. bufout = comb7buf[comb7index];
  168. sum += bufout;
  169. comb7filter = sat16(bufout * combdamp2 + comb7filter * combdamp1, 15);
  170. comb7buf[comb7index] = sat16(input + sat16(comb7filter * combfeeback, 15), 0);
  171. if (++comb7index >= sizeof(comb7buf)/sizeof(int16_t)) comb7index = 0;
  172. bufout = comb8buf[comb8index];
  173. sum += bufout;
  174. comb8filter = sat16(bufout * combdamp2 + comb8filter * combdamp1, 15);
  175. comb8buf[comb8index] = sat16(input + sat16(comb8filter * combfeeback, 15), 0);
  176. if (++comb8index >= sizeof(comb8buf)/sizeof(int16_t)) comb8index = 0;
  177. output = sat16(sum * 31457, 17);
  178. bufout = allpass1buf[allpass1index];
  179. allpass1buf[allpass1index] = output + (bufout >> 1);
  180. output = sat16(bufout - output, 1);
  181. if (++allpass1index >= sizeof(allpass1buf)/sizeof(int16_t)) allpass1index = 0;
  182. bufout = allpass2buf[allpass2index];
  183. allpass2buf[allpass2index] = output + (bufout >> 1);
  184. output = sat16(bufout - output, 1);
  185. if (++allpass2index >= sizeof(allpass2buf)/sizeof(int16_t)) allpass2index = 0;
  186. bufout = allpass3buf[allpass3index];
  187. allpass3buf[allpass3index] = output + (bufout >> 1);
  188. output = sat16(bufout - output, 1);
  189. if (++allpass3index >= sizeof(allpass3buf)/sizeof(int16_t)) allpass3index = 0;
  190. bufout = allpass4buf[allpass4index];
  191. allpass4buf[allpass4index] = output + (bufout >> 1);
  192. output = sat16(bufout - output, 1);
  193. if (++allpass4index >= sizeof(allpass4buf)/sizeof(int16_t)) allpass4index = 0;
  194. outblock->data[i] = sat16(output * 30, 0);
  195. }
  196. transmit(outblock);
  197. release(outblock);
  198. if (block != &zeroblock) release((audio_block_t *)block);
  199. #elif defined(KINETISL)
  200. audio_block_t *block;
  201. block = receiveReadOnly(0);
  202. if (block) release(block);
  203. #endif
  204. }
  205. AudioEffectFreeverbStereo::AudioEffectFreeverbStereo() : AudioStream(1, inputQueueArray)
  206. {
  207. memset(comb1bufL, 0, sizeof(comb1bufL));
  208. memset(comb2bufL, 0, sizeof(comb2bufL));
  209. memset(comb3bufL, 0, sizeof(comb3bufL));
  210. memset(comb4bufL, 0, sizeof(comb4bufL));
  211. memset(comb5bufL, 0, sizeof(comb5bufL));
  212. memset(comb6bufL, 0, sizeof(comb6bufL));
  213. memset(comb7bufL, 0, sizeof(comb7bufL));
  214. memset(comb8bufL, 0, sizeof(comb8bufL));
  215. comb1indexL = 0;
  216. comb2indexL = 0;
  217. comb3indexL = 0;
  218. comb4indexL = 0;
  219. comb5indexL = 0;
  220. comb6indexL = 0;
  221. comb7indexL = 0;
  222. comb8indexL = 0;
  223. comb1filterL = 0;
  224. comb2filterL = 0;
  225. comb3filterL = 0;
  226. comb4filterL = 0;
  227. comb5filterL = 0;
  228. comb6filterL = 0;
  229. comb7filterL = 0;
  230. comb8filterL = 0;
  231. memset(comb1bufR, 0, sizeof(comb1bufR));
  232. memset(comb2bufR, 0, sizeof(comb2bufR));
  233. memset(comb3bufR, 0, sizeof(comb3bufR));
  234. memset(comb4bufR, 0, sizeof(comb4bufR));
  235. memset(comb5bufR, 0, sizeof(comb5bufR));
  236. memset(comb6bufR, 0, sizeof(comb6bufR));
  237. memset(comb7bufR, 0, sizeof(comb7bufR));
  238. memset(comb8bufR, 0, sizeof(comb8bufR));
  239. comb1indexR = 0;
  240. comb2indexR = 0;
  241. comb3indexR = 0;
  242. comb4indexR = 0;
  243. comb5indexR = 0;
  244. comb6indexR = 0;
  245. comb7indexR = 0;
  246. comb8indexR = 0;
  247. comb1filterR = 0;
  248. comb2filterR = 0;
  249. comb3filterR = 0;
  250. comb4filterR = 0;
  251. comb5filterR = 0;
  252. comb6filterR = 0;
  253. comb7filterR = 0;
  254. comb8filterR = 0;
  255. combdamp1 = 6553;
  256. combdamp2 = 26215;
  257. combfeeback = 27524;
  258. memset(allpass1bufL, 0, sizeof(allpass1bufL));
  259. memset(allpass2bufL, 0, sizeof(allpass2bufL));
  260. memset(allpass3bufL, 0, sizeof(allpass3bufL));
  261. memset(allpass4bufL, 0, sizeof(allpass4bufL));
  262. allpass1indexL = 0;
  263. allpass2indexL = 0;
  264. allpass3indexL = 0;
  265. allpass4indexL = 0;
  266. memset(allpass1bufR, 0, sizeof(allpass1bufR));
  267. memset(allpass2bufR, 0, sizeof(allpass2bufR));
  268. memset(allpass3bufR, 0, sizeof(allpass3bufR));
  269. memset(allpass4bufR, 0, sizeof(allpass4bufR));
  270. allpass1indexR = 0;
  271. allpass2indexR = 0;
  272. allpass3indexR = 0;
  273. allpass4indexR = 0;
  274. }
  275. void AudioEffectFreeverbStereo::update()
  276. {
  277. #if defined(__ARM_ARCH_7EM__)
  278. const audio_block_t *block;
  279. audio_block_t *outblockL;
  280. audio_block_t *outblockR;
  281. int i;
  282. int16_t input, bufout, outputL, outputR;
  283. int32_t sum;
  284. block = receiveReadOnly(0);
  285. outblockL = allocate();
  286. outblockR = allocate();
  287. if (!outblockL || !outblockR) {
  288. if (outblockL) release(outblockL);
  289. if (outblockR) release(outblockR);
  290. if (block) release((audio_block_t *)block);
  291. return;
  292. }
  293. if (!block) block = &zeroblock;
  294. for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
  295. // TODO: scale numerical range depending on roomsize & damping
  296. input = sat16(block->data[i] * 8738, 17); // for numerical headroom
  297. sum = 0;
  298. bufout = comb1bufL[comb1indexL];
  299. sum += bufout;
  300. comb1filterL = sat16(bufout * combdamp2 + comb1filterL * combdamp1, 15);
  301. comb1bufL[comb1indexL] = sat16(input + sat16(comb1filterL * combfeeback, 15), 0);
  302. if (++comb1indexL >= sizeof(comb1bufL)/sizeof(int16_t)) comb1indexL = 0;
  303. bufout = comb2bufL[comb2indexL];
  304. sum += bufout;
  305. comb2filterL = sat16(bufout * combdamp2 + comb2filterL * combdamp1, 15);
  306. comb2bufL[comb2indexL] = sat16(input + sat16(comb2filterL * combfeeback, 15), 0);
  307. if (++comb2indexL >= sizeof(comb2bufL)/sizeof(int16_t)) comb2indexL = 0;
  308. bufout = comb3bufL[comb3indexL];
  309. sum += bufout;
  310. comb3filterL = sat16(bufout * combdamp2 + comb3filterL * combdamp1, 15);
  311. comb3bufL[comb3indexL] = sat16(input + sat16(comb3filterL * combfeeback, 15), 0);
  312. if (++comb3indexL >= sizeof(comb3bufL)/sizeof(int16_t)) comb3indexL = 0;
  313. bufout = comb4bufL[comb4indexL];
  314. sum += bufout;
  315. comb4filterL = sat16(bufout * combdamp2 + comb4filterL * combdamp1, 15);
  316. comb4bufL[comb4indexL] = sat16(input + sat16(comb4filterL * combfeeback, 15), 0);
  317. if (++comb4indexL >= sizeof(comb4bufL)/sizeof(int16_t)) comb4indexL = 0;
  318. bufout = comb5bufL[comb5indexL];
  319. sum += bufout;
  320. comb5filterL = sat16(bufout * combdamp2 + comb5filterL * combdamp1, 15);
  321. comb5bufL[comb5indexL] = sat16(input + sat16(comb5filterL * combfeeback, 15), 0);
  322. if (++comb5indexL >= sizeof(comb5bufL)/sizeof(int16_t)) comb5indexL = 0;
  323. bufout = comb6bufL[comb6indexL];
  324. sum += bufout;
  325. comb6filterL = sat16(bufout * combdamp2 + comb6filterL * combdamp1, 15);
  326. comb6bufL[comb6indexL] = sat16(input + sat16(comb6filterL * combfeeback, 15), 0);
  327. if (++comb6indexL >= sizeof(comb6bufL)/sizeof(int16_t)) comb6indexL = 0;
  328. bufout = comb7bufL[comb7indexL];
  329. sum += bufout;
  330. comb7filterL = sat16(bufout * combdamp2 + comb7filterL * combdamp1, 15);
  331. comb7bufL[comb7indexL] = sat16(input + sat16(comb7filterL * combfeeback, 15), 0);
  332. if (++comb7indexL >= sizeof(comb7bufL)/sizeof(int16_t)) comb7indexL = 0;
  333. bufout = comb8bufL[comb8indexL];
  334. sum += bufout;
  335. comb8filterL = sat16(bufout * combdamp2 + comb8filterL * combdamp1, 15);
  336. comb8bufL[comb8indexL] = sat16(input + sat16(comb8filterL * combfeeback, 15), 0);
  337. if (++comb8indexL >= sizeof(comb8bufL)/sizeof(int16_t)) comb8indexL = 0;
  338. outputL = sat16(sum * 31457, 17);
  339. sum = 0;
  340. bufout = comb1bufR[comb1indexR];
  341. sum += bufout;
  342. comb1filterR = sat16(bufout * combdamp2 + comb1filterR * combdamp1, 15);
  343. comb1bufR[comb1indexR] = sat16(input + sat16(comb1filterR * combfeeback, 15), 0);
  344. if (++comb1indexR >= sizeof(comb1bufR)/sizeof(int16_t)) comb1indexR = 0;
  345. bufout = comb2bufR[comb2indexR];
  346. sum += bufout;
  347. comb2filterR = sat16(bufout * combdamp2 + comb2filterR * combdamp1, 15);
  348. comb2bufR[comb2indexR] = sat16(input + sat16(comb2filterR * combfeeback, 15), 0);
  349. if (++comb2indexR >= sizeof(comb2bufR)/sizeof(int16_t)) comb2indexR = 0;
  350. bufout = comb3bufR[comb3indexR];
  351. sum += bufout;
  352. comb3filterR = sat16(bufout * combdamp2 + comb3filterR * combdamp1, 15);
  353. comb3bufR[comb3indexR] = sat16(input + sat16(comb3filterR * combfeeback, 15), 0);
  354. if (++comb3indexR >= sizeof(comb3bufR)/sizeof(int16_t)) comb3indexR = 0;
  355. bufout = comb4bufR[comb4indexR];
  356. sum += bufout;
  357. comb4filterR = sat16(bufout * combdamp2 + comb4filterR * combdamp1, 15);
  358. comb4bufR[comb4indexR] = sat16(input + sat16(comb4filterR * combfeeback, 15), 0);
  359. if (++comb4indexR >= sizeof(comb4bufR)/sizeof(int16_t)) comb4indexR = 0;
  360. bufout = comb5bufR[comb5indexR];
  361. sum += bufout;
  362. comb5filterR = sat16(bufout * combdamp2 + comb5filterR * combdamp1, 15);
  363. comb5bufR[comb5indexR] = sat16(input + sat16(comb5filterR * combfeeback, 15), 0);
  364. if (++comb5indexR >= sizeof(comb5bufR)/sizeof(int16_t)) comb5indexR = 0;
  365. bufout = comb6bufR[comb6indexR];
  366. sum += bufout;
  367. comb6filterR = sat16(bufout * combdamp2 + comb6filterR * combdamp1, 15);
  368. comb6bufR[comb6indexR] = sat16(input + sat16(comb6filterR * combfeeback, 15), 0);
  369. if (++comb6indexR >= sizeof(comb6bufR)/sizeof(int16_t)) comb6indexR = 0;
  370. bufout = comb7bufR[comb7indexR];
  371. sum += bufout;
  372. comb7filterR = sat16(bufout * combdamp2 + comb7filterR * combdamp1, 15);
  373. comb7bufR[comb7indexR] = sat16(input + sat16(comb7filterR * combfeeback, 15), 0);
  374. if (++comb7indexR >= sizeof(comb7bufR)/sizeof(int16_t)) comb7indexR = 0;
  375. bufout = comb8bufR[comb8indexR];
  376. sum += bufout;
  377. comb8filterR = sat16(bufout * combdamp2 + comb8filterR * combdamp1, 15);
  378. comb8bufR[comb8indexR] = sat16(input + sat16(comb8filterR * combfeeback, 15), 0);
  379. if (++comb8indexR >= sizeof(comb8bufR)/sizeof(int16_t)) comb8indexR = 0;
  380. outputR = sat16(sum * 31457, 17);
  381. bufout = allpass1bufL[allpass1indexL];
  382. allpass1bufL[allpass1indexL] = outputL + (bufout >> 1);
  383. outputL = sat16(bufout - outputL, 1);
  384. if (++allpass1indexL >= sizeof(allpass1bufL)/sizeof(int16_t)) allpass1indexL = 0;
  385. bufout = allpass2bufL[allpass2indexL];
  386. allpass2bufL[allpass2indexL] = outputL + (bufout >> 1);
  387. outputL = sat16(bufout - outputL, 1);
  388. if (++allpass2indexL >= sizeof(allpass2bufL)/sizeof(int16_t)) allpass2indexL = 0;
  389. bufout = allpass3bufL[allpass3indexL];
  390. allpass3bufL[allpass3indexL] = outputL + (bufout >> 1);
  391. outputL = sat16(bufout - outputL, 1);
  392. if (++allpass3indexL >= sizeof(allpass3bufL)/sizeof(int16_t)) allpass3indexL = 0;
  393. bufout = allpass4bufL[allpass4indexL];
  394. allpass4bufL[allpass4indexL] = outputL + (bufout >> 1);
  395. outputL = sat16(bufout - outputL, 1);
  396. if (++allpass4indexL >= sizeof(allpass4bufL)/sizeof(int16_t)) allpass4indexL = 0;
  397. outblockL->data[i] = sat16(outputL * 30, 0);
  398. bufout = allpass1bufR[allpass1indexR];
  399. allpass1bufR[allpass1indexR] = outputR + (bufout >> 1);
  400. outputR = sat16(bufout - outputR, 1);
  401. if (++allpass1indexR >= sizeof(allpass1bufR)/sizeof(int16_t)) allpass1indexR = 0;
  402. bufout = allpass2bufR[allpass2indexR];
  403. allpass2bufR[allpass2indexR] = outputR + (bufout >> 1);
  404. outputR = sat16(bufout - outputR, 1);
  405. if (++allpass2indexR >= sizeof(allpass2bufR)/sizeof(int16_t)) allpass2indexR = 0;
  406. bufout = allpass3bufR[allpass3indexR];
  407. allpass3bufR[allpass3indexR] = outputR + (bufout >> 1);
  408. outputR = sat16(bufout - outputR, 1);
  409. if (++allpass3indexR >= sizeof(allpass3bufR)/sizeof(int16_t)) allpass3indexR = 0;
  410. bufout = allpass4bufR[allpass4indexR];
  411. allpass4bufR[allpass4indexR] = outputR + (bufout >> 1);
  412. outputR = sat16(bufout - outputR, 1);
  413. if (++allpass4indexR >= sizeof(allpass4bufR)/sizeof(int16_t)) allpass4indexR = 0;
  414. outblockR->data[i] = sat16(outputL * 30, 0);
  415. }
  416. transmit(outblockL, 0);
  417. transmit(outblockR, 1);
  418. release(outblockL);
  419. release(outblockR);
  420. if (block != &zeroblock) release((audio_block_t *)block);
  421. #elif defined(KINETISL)
  422. audio_block_t *block;
  423. block = receiveReadOnly(0);
  424. if (block) release(block);
  425. #endif
  426. }