summaryrefslogtreecommitdiff
path: root/apps/codecs/libatrac/atrac3_arm.S
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libatrac/atrac3_arm.S')
-rwxr-xr-xapps/codecs/libatrac/atrac3_arm.S137
1 files changed, 137 insertions, 0 deletions
diff --git a/apps/codecs/libatrac/atrac3_arm.S b/apps/codecs/libatrac/atrac3_arm.S
new file mode 100755
index 0000000000..be8b2a0e0e
--- /dev/null
+++ b/apps/codecs/libatrac/atrac3_arm.S
@@ -0,0 +1,137 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id:
9 *
10 * Copyright (C) 2009 by Andree Buschmann
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22 .section .text, "ax", %progbits
23
24/****************************************************************************
25 * void atrac3_iqmf_matrixing(int32_t *dest,
26 * int32_t *inlo,
27 * int32_t *inhi,
28 * unsigned int count);
29 *
30 * Matrixing step within iqmf of atrac3 synthesis. Reference implementation:
31 *
32 * for(i=0; i<counter; i+=2){
33 * dest[2*i+0] = inlo[i ] + inhi[i ];
34 * dest[2*i+1] = inlo[i ] - inhi[i ];
35 * dest[2*i+2] = inlo[i+1] + inhi[i+1];
36 * dest[2*i+3] = inlo[i+1] - inhi[i+1];
37 * }
38 * Note: r12 is a scratch register and can be used without restorage.
39 ****************************************************************************/
40 .align 2
41 .global atrac3_iqmf_matrixing
42 .type atrac3_iqmf_matrixing, %function
43
44atrac3_iqmf_matrixing:
45 /* r0 = dest */
46 /* r1 = inlo */
47 /* r2 = inhi */
48 /* r3 = counter */
49 stmfd sp!, {r4-r9, lr} /* save non-scratch registers */
50
51.iqmf_matrixing_loop:
52 ldmia r1!, { r4, r6, r8, r12} /* load inlo[0...3] */
53 ldmia r2!, { r5, r7, r9, lr } /* load inhi[0...3] */
54 add r4, r4, r5 /* r4 = inlo[0] + inhi[0] */
55 sub r5, r4, r5, asl #1 /* r5 = inlo[0] - inhi[0] */
56 add r6, r6, r7 /* r6 = inlo[1] + inhi[1] */
57 sub r7, r6, r7, asl #1 /* r7 = inlo[1] - inhi[1] */
58 add r8, r8, r9 /* r8 = inlo[2] + inhi[2] */
59 sub r9, r8, r9, asl #1 /* r9 = inlo[2] - inhi[2] */
60 add r12, r12, lr /* r12 = inlo[3] + inhi[3] */
61 sub lr , r12, lr, asl #1 /* lr = inlo[3] - inhi[3] */
62 stmia r0!, {r4-r9, r12, lr} /* store results to dest */
63 subs r3, r3, #4 /* counter -= 4 */
64 bgt .iqmf_matrixing_loop
65
66 ldmfd sp!, {r4-r9, pc} /* restore registers */
67
68.atrac3_iqmf_matrixing_end:
69 .size atrac3_iqmf_matrixing,.atrac3_iqmf_matrixing_end-atrac3_iqmf_matrixing
70
71
72/****************************************************************************
73 * atrac3_iqmf_dewindowing(int32_t *out,
74 * int32_t *in,
75 * int32_t *win,
76 * unsigned int nIn);
77 *
78 * Dewindowing step within iqmf of atrac3 synthesis. Reference implementation:
79 *
80 * for (j = nIn; j != 0; j--) {
81 * s1 = fixmul32(in[0], win[0]);
82 * s2 = fixmul32(in[1], win[1]);
83 * for (i = 2; i < 48; i += 2) {
84 * s1 += fixmul32(in[i ], win[i ]);
85 * s2 += fixmul32(in[i+1], win[i+1]);
86 * }
87 * out[0] = s2 << 1;
88 * out[1] = s1 << 1;
89 * in += 2;
90 * out += 2;
91 * }
92 * Note: r12 is a scratch register and can be used without restorage.
93 ****************************************************************************/
94 .align 2
95 .global atrac3_iqmf_dewindowing
96 .type atrac3_iqmf_dewindowing, %function
97
98atrac3_iqmf_dewindowing:
99 /* r0 = dest */
100 /* r1 = input samples */
101 /* r2 = window coefficients */
102 /* r3 = counter */
103 stmfd sp!, {r4-r10, lr} /* save non-scratch registers */
104
105.iqmf_dewindow_outer_loop: /* outer loop 0...counter-1 */
106
107 ldmia r2!, {r5, r6} /* load win[0..1] */
108 ldmia r1!, {r7, r8} /* load in[0..1] */
109 smull lr , r10, r5, r7 /* s1 = win[0] * in[0] */
110 smull r12, r9 , r6, r8 /* s2 = win[1] * in[1] */
111
112 mov r4, #46 /* r4 = 46 */
113.iqmf_dewindow_inner_loop: /* inner loop i=2...48 */
114 ldmia r2!, {r5, r6} /* load win[i...i+1] */
115 ldmia r1!, {r7, r8} /* load in[i...i+1] */
116 smlal lr , r10, r5, r7 /* s1 = win[i ] * in[i ] */
117 smlal r12, r9 , r6, r8 /* s2 = win[i+1] * in[i+1] */
118
119 subs r4, r4, #2 /* inner loop -= 2*/
120 bgt .iqmf_dewindow_inner_loop
121
122 mov lr , lr , lsr #31
123 orr r10, lr , r10, lsl #1 /* s1 = low>>31 || hi<<1 */
124 mov r12, r12, lsr #31
125 orr r9 , r12, r9 , lsl #1 /* s2 = low>>31 || hi<<1 */
126
127 stmia r0!, {r9, r10} /* store result out[0]=s2, out[1]=s1 */
128 sub r1, r1, #184 /* roll back 64 entries = 184 bytes */
129 sub r2, r2, #192 /* roll back 48 entries = 192 bytes = win[0] */
130
131 subs r3, r3, #1 /* outer loop -= 1 */
132 bgt .iqmf_dewindow_outer_loop
133
134 ldmfd sp!, {r4-r10, pc} /* restore registers */
135
136.atrac3_iqmf_dewindowing_end:
137 .size atrac3_iqmf_dewindowing,.atrac3_iqmf_dewindowing_end-atrac3_iqmf_dewindowing