pdispatch: add missing commands to command table
[pulseaudio-mirror.git] / src / pulsecore / svolume_arm.c
blob5bd1448f33ae9df0030325822fc1cc473e79f09e
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk>
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <pulse/timeval.h>
28 #include <pulsecore/random.h>
29 #include <pulsecore/macro.h>
30 #include <pulsecore/g711.h>
31 #include <pulsecore/core-util.h>
33 #include "cpu-arm.h"
35 #include "sample-util.h"
36 #include "endianmacros.h"
38 #if defined (__arm__)
40 #define MOD_INC() \
41 " subs r0, r6, %2 \n\t" \
42 " addcs r0, %1 \n\t" \
43 " movcs r6, r0 \n\t"
45 static void
46 pa_volume_s16ne_arm (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
48 int32_t *ve;
50 channels = PA_MAX (4U, channels);
51 ve = volumes + channels;
53 __asm__ __volatile__ (
54 " mov r6, %1 \n\t"
55 " mov %3, %3, LSR #1 \n\t" /* length /= sizeof (int16_t) */
56 " tst %3, #1 \n\t" /* check for odd samples */
57 " beq 2f \n\t"
59 "1: \n\t"
60 " ldr r0, [r6], #4 \n\t" /* odd samples volumes */
61 " ldrh r2, [%0] \n\t"
63 " smulwb r0, r0, r2 \n\t"
64 " ssat r0, #16, r0 \n\t"
66 " strh r0, [%0], #2 \n\t"
68 MOD_INC()
70 "2: \n\t"
71 " mov %3, %3, LSR #1 \n\t"
72 " tst %3, #1 \n\t" /* check for odd samples */
73 " beq 4f \n\t"
75 "3: \n\t"
76 " ldrd r2, [r6], #8 \n\t" /* 2 samples at a time */
77 " ldr r0, [%0] \n\t"
79 " smulwt r2, r2, r0 \n\t"
80 " smulwb r3, r3, r0 \n\t"
82 " ssat r2, #16, r2 \n\t"
83 " ssat r3, #16, r3 \n\t"
85 " pkhbt r0, r3, r2, LSL #16 \n\t"
86 " str r0, [%0], #4 \n\t"
88 MOD_INC()
90 "4: \n\t"
91 " movs %3, %3, LSR #1 \n\t"
92 " beq 6f \n\t"
94 "5: \n\t"
95 " ldrd r2, [r6], #8 \n\t" /* 4 samples at a time */
96 " ldrd r4, [r6], #8 \n\t"
97 " ldrd r0, [%0] \n\t"
99 " smulwt r2, r2, r0 \n\t"
100 " smulwb r3, r3, r0 \n\t"
101 " smulwt r4, r4, r1 \n\t"
102 " smulwb r5, r5, r1 \n\t"
104 " ssat r2, #16, r2 \n\t"
105 " ssat r3, #16, r3 \n\t"
106 " ssat r4, #16, r4 \n\t"
107 " ssat r5, #16, r5 \n\t"
109 " pkhbt r0, r3, r2, LSL #16 \n\t"
110 " pkhbt r1, r5, r4, LSL #16 \n\t"
111 " strd r0, [%0], #8 \n\t"
113 MOD_INC()
115 " subs %3, %3, #1 \n\t"
116 " bne 5b \n\t"
117 "6: \n\t"
119 : "+r" (samples), "+r" (volumes), "+r" (ve), "+r" (length)
121 : "r6", "r5", "r4", "r3", "r2", "r1", "r0", "cc"
125 #undef RUN_TEST
127 #ifdef RUN_TEST
128 #define CHANNELS 2
129 #define SAMPLES 1023
130 #define TIMES 1000
131 #define PADDING 16
133 static void run_test (void) {
134 int16_t samples[SAMPLES];
135 int16_t samples_ref[SAMPLES];
136 int16_t samples_orig[SAMPLES];
137 int32_t volumes[CHANNELS + PADDING];
138 int i, j, padding;
139 pa_do_volume_func_t func;
140 pa_usec_t start, stop;
142 func = pa_get_volume_func (PA_SAMPLE_S16NE);
144 printf ("checking ARM %zd\n", sizeof (samples));
146 pa_random (samples, sizeof (samples));
147 memcpy (samples_ref, samples, sizeof (samples));
148 memcpy (samples_orig, samples, sizeof (samples));
150 for (i = 0; i < CHANNELS; i++)
151 volumes[i] = rand() >> 1;
152 for (padding = 0; padding < PADDING; padding++, i++)
153 volumes[i] = volumes[padding];
155 func (samples_ref, volumes, CHANNELS, sizeof (samples));
156 pa_volume_s16ne_arm (samples, volumes, CHANNELS, sizeof (samples));
157 for (i = 0; i < SAMPLES; i++) {
158 if (samples[i] != samples_ref[i]) {
159 printf ("%d: %04x != %04x (%04x * %04x)\n", i, samples[i], samples_ref[i],
160 samples_orig[i], volumes[i % CHANNELS]);
164 start = pa_rtclock_now();
165 for (j = 0; j < TIMES; j++) {
166 memcpy (samples, samples_orig, sizeof (samples));
167 pa_volume_s16ne_arm (samples, volumes, CHANNELS, sizeof (samples));
169 stop = pa_rtclock_now();
170 pa_log_info("ARM: %llu usec.", (long long unsigned int) (stop - start));
172 start = pa_rtclock_now();
173 for (j = 0; j < TIMES; j++) {
174 memcpy (samples_ref, samples_orig, sizeof (samples));
175 func (samples_ref, volumes, CHANNELS, sizeof (samples));
177 stop = pa_rtclock_now();
178 pa_log_info("ref: %llu usec.", (long long unsigned int) (stop - start));
180 #endif
182 #endif /* defined (__arm__) */
185 void pa_volume_func_init_arm (pa_cpu_arm_flag_t flags) {
186 #if defined (__arm__)
187 pa_log_info("Initialising ARM optimized functions.");
189 #ifdef RUN_TEST
190 run_test ();
191 #endif
193 pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_arm);
194 #endif /* defined (__arm__) */