mix_arm.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. * Generic routines for mixing audio samples
  3. * (C) notaz, 2007,2008
  4. *
  5. * This work is licensed under the terms of MAME license.
  6. * See COPYING file in the top-level directory.
  7. */
  8. .text
  9. .align 4
  10. @ this assumes src is word aligned
  11. .global mix_16h_to_32 @ int *dest, short *src, int count
  12. mix_16h_to_32:
  13. stmfd sp!, {r4-r6,lr}
  14. /*
  15. tst r1, #2
  16. beq m16_32_mo_unalw
  17. ldrsh r4, [r1], #2
  18. ldr r3, [r0]
  19. sub r2, r2, #1
  20. add r3, r3, r4, asr #1
  21. str r3, [r0], #4
  22. */
  23. m16_32_mo_unalw:
  24. subs r2, r2, #4
  25. bmi m16_32_end
  26. m16_32_loop:
  27. ldmia r0, {r3-r6}
  28. ldmia r1!,{r12,lr}
  29. subs r2, r2, #4
  30. add r4, r4, r12,asr #17 @ we use half volume
  31. mov r12,r12,lsl #16
  32. add r3, r3, r12,asr #17
  33. add r6, r6, lr, asr #17
  34. mov lr, lr, lsl #16
  35. add r5, r5, lr, asr #17
  36. stmia r0!,{r3-r6}
  37. bpl m16_32_loop
  38. m16_32_end:
  39. tst r2, #2
  40. beq m16_32_no_unal2
  41. ldr r5, [r1], #4
  42. ldmia r0, {r3,r4}
  43. mov r12,r5, lsl #16
  44. add r3, r3, r12,asr #17
  45. add r4, r4, r5, asr #17
  46. stmia r0!,{r3,r4}
  47. m16_32_no_unal2:
  48. tst r2, #1
  49. ldmeqfd sp!, {r4-r6,pc}
  50. ldrsh r4, [r1], #2
  51. ldr r3, [r0]
  52. add r3, r3, r4, asr #1
  53. str r3, [r0], #4
  54. ldmfd sp!, {r4-r6,lr}
  55. bx lr
  56. .global mix_16h_to_32_s1 @ int *dest, short *src, int count
  57. mix_16h_to_32_s1:
  58. stmfd sp!, {r4-r6,lr}
  59. subs r2, r2, #4
  60. bmi m16_32_s1_end
  61. m16_32_s1_loop:
  62. ldmia r0, {r3-r6}
  63. ldr r12,[r1], #8
  64. ldr lr, [r1], #8
  65. subs r2, r2, #4
  66. add r4, r4, r12,asr #17
  67. mov r12,r12,lsl #16
  68. add r3, r3, r12,asr #17 @ we use half volume
  69. add r6, r6, lr, asr #17
  70. mov lr, lr, lsl #16
  71. add r5, r5, lr, asr #17
  72. stmia r0!,{r3-r6}
  73. bpl m16_32_s1_loop
  74. m16_32_s1_end:
  75. tst r2, #2
  76. beq m16_32_s1_no_unal2
  77. ldr r5, [r1], #8
  78. ldmia r0, {r3,r4}
  79. mov r12,r5, lsl #16
  80. add r3, r3, r12,asr #17
  81. add r4, r4, r5, asr #17
  82. stmia r0!,{r3,r4}
  83. m16_32_s1_no_unal2:
  84. tst r2, #1
  85. ldmeqfd sp!, {r4-r6,pc}
  86. ldrsh r4, [r1], #2
  87. ldr r3, [r0]
  88. add r3, r3, r4, asr #1
  89. str r3, [r0], #4
  90. ldmfd sp!, {r4-r6,lr}
  91. bx lr
  92. .global mix_16h_to_32_s2 @ int *dest, short *src, int count
  93. mix_16h_to_32_s2:
  94. stmfd sp!, {r4-r6,lr}
  95. subs r2, r2, #4
  96. bmi m16_32_s2_end
  97. m16_32_s2_loop:
  98. ldmia r0, {r3-r6}
  99. ldr r12,[r1], #16
  100. ldr lr, [r1], #16
  101. subs r2, r2, #4
  102. add r4, r4, r12,asr #17
  103. mov r12,r12,lsl #16
  104. add r3, r3, r12,asr #17 @ we use half volume
  105. add r6, r6, lr, asr #17
  106. mov lr, lr, lsl #16
  107. add r5, r5, lr, asr #17
  108. stmia r0!,{r3-r6}
  109. bpl m16_32_s2_loop
  110. m16_32_s2_end:
  111. tst r2, #2
  112. beq m16_32_s2_no_unal2
  113. ldr r5, [r1], #16
  114. ldmia r0, {r3,r4}
  115. mov r12,r5, lsl #16
  116. add r3, r3, r12,asr #17
  117. add r4, r4, r5, asr #17
  118. stmia r0!,{r3,r4}
  119. m16_32_s2_no_unal2:
  120. tst r2, #1
  121. ldmeqfd sp!, {r4-r6,pc}
  122. ldrsh r4, [r1], #2
  123. ldr r3, [r0]
  124. add r3, r3, r4, asr #1
  125. str r3, [r0], #4
  126. ldmfd sp!, {r4-r6,lr}
  127. bx lr
  128. @ limit
  129. @ reg=int_sample, r12=1, r8=tmp, kills flags
  130. .macro Limit reg
  131. @ sub \reg, \reg, \reg, asr #2 @ reduce audio lvl to avoid clipping
  132. add r8, r12, \reg, asr #15
  133. bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1
  134. movne \reg, #0x8000
  135. subpl \reg, \reg, #1
  136. .endm
  137. @ limit and shift up by 16
  138. @ reg=int_sample, r12=1, r8=tmp, kills flags
  139. .macro Limitsh reg
  140. @ sub \reg, \reg, \reg, asr #2 @ reduce audio lvl to avoid clipping
  141. add r8, r12,\reg, asr #15
  142. bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1
  143. moveq \reg, \reg, lsl #16
  144. movne \reg, #0x80000000
  145. subpl \reg, \reg, #0x00010000
  146. .endm
  147. @ filter out DC offset
  148. @ in=int_sample (max 20 bit), y=filter memory, r8=tmp
  149. .macro DCfilt in y
  150. rsb r8, \y, \in, lsl #12 @ fixpoint 20.12
  151. add \y, \y, r8, asr #12 @ alpha = 1-1/4094
  152. sub \in, \in, \y, asr #12
  153. .endm
  154. @ lowpass filter
  155. @ in=int_sample (max 20 bit), y=filter memory, r12=alpha(Q8), r8=tmp
  156. .macro LPfilt in y
  157. @ asr r8, \y, #8
  158. @ rsb r8, r8, \in, lsl #4 @ fixpoint 20.12
  159. sub r8, \in, \y, asr #12 @ fixpoint 20.12
  160. mla \y, r8, r12, \y
  161. asr \in, \y, #12
  162. .endm
  163. @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio with left channel only
  164. @ warning: this function assumes dest is word aligned
  165. .global mix_32_to_16l_stereo @ short *dest, int *src, int count
  166. mix_32_to_16l_stereo:
  167. stmfd sp!, {r4-r8,r10-r11,lr}
  168. mov r2, r2, lsl #1
  169. subs r2, r2, #4
  170. bmi m32_16l_st_end
  171. ldr r12, =filter
  172. ldr r8, [r12], #4
  173. ldmia r12, {r3,r10-r11,lr}
  174. str r8, [sp, #-4]!
  175. m32_16l_st_loop:
  176. ldmia r0, {r8,r12}
  177. ldmia r1!, {r4-r7}
  178. mov r8, r8, lsl #16
  179. mov r12,r12,lsl #16
  180. add r4, r4, r8, asr #16
  181. add r5, r5, r8, asr #16
  182. add r6, r6, r12,asr #16
  183. add r7, r7, r12,asr #16
  184. ldr r12,[sp]
  185. LPfilt r4, r3
  186. LPfilt r5, lr
  187. LPfilt r6, r3
  188. LPfilt r7, lr
  189. DCfilt r4, r10
  190. DCfilt r5, r11
  191. DCfilt r6, r10
  192. DCfilt r7, r11
  193. mov r12,#1
  194. Limitsh r4
  195. Limitsh r5
  196. Limitsh r6
  197. Limitsh r7
  198. subs r2, r2, #4
  199. orr r4, r5, r4, lsr #16
  200. orr r5, r7, r6, lsr #16
  201. stmia r0!, {r4,r5}
  202. bpl m32_16l_st_loop
  203. m32_16l_st_end:
  204. @ check for remaining bytes to convert
  205. tst r2, #2
  206. beq m32_16l_st_no_unal2
  207. ldrsh r6, [r0]
  208. ldmia r1!,{r4,r5}
  209. add r4, r4, r6
  210. add r5, r5, r6
  211. ldr r12,[sp]
  212. LPfilt r4, r3
  213. LPfilt r5, lr
  214. DCfilt r4, r10
  215. DCfilt r5, r11
  216. mov r12,#1
  217. Limitsh r4
  218. Limitsh r5
  219. orr r4, r5, r4, lsr #16
  220. str r4, [r0], #4
  221. m32_16l_st_no_unal2:
  222. ldr r12, =filter
  223. add r12,r12, #4
  224. stmia r12, {r3,r10-r11,lr}
  225. add sp, sp, #4
  226. ldmfd sp!, {r4-r8,r10-r11,lr}
  227. bx lr
  228. @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio (for mono sound)
  229. .global mix_32_to_16_mono @ short *dest, int *src, int count
  230. mix_32_to_16_mono:
  231. stmfd sp!, {r4-r8,r10-r11,lr}
  232. ldr r12, =filter
  233. ldr r8, [r12], #4
  234. ldmia r12, {r10-r11}
  235. str r8, [sp, #-4]!
  236. @ check if dest is word aligned
  237. tst r0, #2
  238. beq m32_16_mo_no_unalw
  239. ldrsh r5, [r0]
  240. ldr r4, [r1], #4
  241. sub r2, r2, #1
  242. add r4, r4, r5
  243. ldr r12,[sp]
  244. LPfilt r4, r11
  245. DCfilt r4, r10
  246. mov r12,#1
  247. Limit r4
  248. strh r4, [r0], #2
  249. m32_16_mo_no_unalw:
  250. subs r2, r2, #4
  251. bmi m32_16_mo_end
  252. m32_16_mo_loop:
  253. ldmia r0, {r8,r12}
  254. ldmia r1!, {r4-r7}
  255. add r5, r5, r8, asr #16
  256. mov r8, r8, lsl #16
  257. add r4, r4, r8, asr #16
  258. add r7, r7, r12,asr #16
  259. mov r12,r12,lsl #16
  260. add r6, r6, r12,asr #16
  261. ldr r12,[sp]
  262. LPfilt r4, r11
  263. LPfilt r5, r11
  264. LPfilt r6, r11
  265. LPfilt r7, r11
  266. DCfilt r4, r10
  267. DCfilt r5, r10
  268. DCfilt r6, r10
  269. DCfilt r7, r10
  270. mov r12,#1
  271. Limitsh r4
  272. Limitsh r5
  273. Limitsh r6
  274. Limitsh r7
  275. subs r2, r2, #4
  276. orr r4, r5, r4, lsr #16
  277. orr r5, r7, r6, lsr #16
  278. stmia r0!, {r4,r5}
  279. bpl m32_16_mo_loop
  280. m32_16_mo_end:
  281. @ check for remaining bytes to convert
  282. tst r2, #2
  283. beq m32_16_mo_no_unal2
  284. ldr r6, [r0]
  285. ldmia r1!,{r4,r5}
  286. add r5, r5, r6, asr #16
  287. mov r6, r6, lsl #16
  288. add r4, r4, r6, asr #16
  289. ldr r12,[sp]
  290. LPfilt r4, r11
  291. LPfilt r5, r11
  292. DCfilt r4, r10
  293. DCfilt r5, r10
  294. mov r12,#1
  295. Limitsh r4
  296. Limitsh r5
  297. orr r4, r5, r4, lsr #16
  298. str r4, [r0], #4
  299. m32_16_mo_no_unal2:
  300. tst r2, #1
  301. beq m32_16_mo_no_unal
  302. ldrsh r5, [r0]
  303. ldr r4, [r1], #4
  304. add r4, r4, r5
  305. ldr r12,[sp]
  306. LPfilt r4, r11
  307. DCfilt r4, r10
  308. mov r12,#1
  309. Limit r4
  310. strh r4, [r0], #2
  311. m32_16_mo_no_unal:
  312. ldr r12, =filter
  313. add r12,r12, #4
  314. stmia r12, {r10-r11}
  315. add sp, sp, #4
  316. ldmfd sp!, {r4-r8,r10-r11,lr}
  317. bx lr
  318. #ifdef __GP2X__
  319. .data
  320. .align 4
  321. .global mix_32_to_16l_level
  322. mix_32_to_16l_level:
  323. .word 0
  324. .text
  325. .align 4
  326. @ same as mix_32_to_16l_stereo, but with additional shift
  327. .global mix_32_to_16l_stereo_lvl @ short *dest, int *src, int count
  328. mix_32_to_16l_stereo_lvl:
  329. stmfd sp!, {r4-r11,lr}
  330. ldr r9, =mix_32_to_16l_level
  331. mov lr, #1
  332. ldr r9, [r9]
  333. ldr r12, =filter
  334. ldr r8, [r12], #4
  335. ldmia r12, {r3,r10-r11,lr}
  336. str r8, [sp, #-4]!
  337. mov r2, r2, lsl #1
  338. subs r2, r2, #4
  339. bmi m32_16l_st_l_end
  340. m32_16l_st_l_loop:
  341. ldmia r0, {r8,r12}
  342. ldmia r1!, {r4-r7}
  343. mov r8, r8, lsl #16
  344. mov r12,r12,lsl #16
  345. add r4, r4, r8, asr #16
  346. add r5, r5, r8, asr #16
  347. add r6, r6, r12,asr #16
  348. add r7, r7, r12,asr #16
  349. mov r4, r4, asr r9
  350. mov r5, r5, asr r9
  351. mov r6, r6, asr r9
  352. mov r7, r7, asr r9
  353. ldr r12,[sp]
  354. LPfilt r4, r3
  355. LPfilt r5, lr
  356. LPfilt r6, r3
  357. LPfilt r7, lr
  358. DCfilt r4, r10
  359. DCfilt r5, r11
  360. DCfilt r6, r10
  361. DCfilt r7, r11
  362. mov r12,#1
  363. Limitsh r4
  364. Limitsh r5
  365. Limitsh r6
  366. Limitsh r7
  367. subs r2, r2, #4
  368. orr r4, r5, r4, lsr #16
  369. orr r5, r7, r6, lsr #16
  370. stmia r0!, {r4,r5}
  371. bpl m32_16l_st_l_loop
  372. m32_16l_st_l_end:
  373. @ check for remaining bytes to convert
  374. tst r2, #2
  375. beq m32_16l_st_l_no_unal2
  376. ldrsh r6, [r0]
  377. ldmia r1!,{r4,r5}
  378. add r4, r4, r6
  379. add r5, r5, r6
  380. mov r4, r4, asr r9
  381. mov r5, r5, asr r9
  382. ldr r12,[sp]
  383. LPfilt r4, r3
  384. LPfilt r5, lr
  385. DCfilt r4, r10
  386. DCfilt r5, r11
  387. mov r12,#1
  388. Limitsh r4
  389. Limitsh r5
  390. orr r4, r5, r4, lsr #16
  391. str r4, [r0], #4
  392. m32_16l_st_l_no_unal2:
  393. ldr r12, =filter
  394. add r12,r12, #4
  395. stmia r12, {r3,r10-r11,lr}
  396. add sp, sp, #4
  397. ldmfd sp!, {r4-r11,lr}
  398. bx lr
  399. #endif /* __GP2X__ */
  400. .global mix_reset @ int alpha_q16
  401. mix_reset:
  402. ldr r2, =filter
  403. rsb r0, r0, #0x10000
  404. @ asr r0, r0, #8
  405. asr r0, r0, #4
  406. str r0, [r2], #4
  407. mov r1, #0
  408. str r1, [r2], #4
  409. str r1, [r2], #4
  410. str r1, [r2], #4
  411. str r1, [r2], #4
  412. bx lr
  413. .data
  414. filter:
  415. .ds 4 @ alpha_q8
  416. .ds 8 @ filter history for left channel
  417. .ds 8 @ filter history for right channel
  418. @ vim:filetype=armasm