1 /*****************************************************************************
2 * arm_neon.c: NEON assembly optimized audio conversions
3 *****************************************************************************
4 * Copyright (C) 2009 RĂ©mi Denis-Courmont
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
25 #include <vlc_common.h>
26 #include <vlc_plugin.h>
28 #include <vlc_filter.h>
31 static int Open (vlc_object_t *);
34 set_description (N_("ARM NEON audio format conversions") )
35 set_capability ("audio filter2", 20)
36 set_callbacks (Open, NULL)
37 add_requirement (NEON)
40 static block_t *Do_F32_S32 (filter_t *, block_t *);
41 static block_t *Do_S32_S16 (filter_t *, block_t *);
43 static int Open (vlc_object_t *obj)
45 filter_t *filter = (filter_t *)obj;
47 if (!AOUT_FMTS_SIMILAR (&filter->fmt_in.audio, &filter->fmt_out.audio))
50 switch (filter->fmt_in.audio.i_format)
53 switch (filter->fmt_out.audio.i_format)
56 filter->pf_audio_filter = Do_F32_S32;
64 switch (filter->fmt_out.audio.i_format)
67 filter->pf_audio_filter = Do_S32_S16;
80 * Single-precision floating point to signed fixed point conversion.
82 static block_t *Do_F32_S32 (filter_t *filter, block_t *inbuf)
84 unsigned nb_samples = inbuf->i_nb_samples
85 * aout_FormatNbChannels (&filter->fmt_in.audio);
86 int32_t *outp = (int32_t *)inbuf->p_buffer;
87 int32_t *endp = outp + nb_samples;
92 "vldr.32 s0, [%[outp]]\n"
93 "vcvt.s32.f32 d0, d0, #28\n"
94 "vstr.32 s0, [%[outp]]\n"
103 "vld1.f32 {d0}, [%[outp]]\n"
104 "vcvt.s32.f32 d0, d0, #28\n"
105 "vst1.s32 {d0}, [%[outp]]!\n"
112 "vld1.f32 {q0}, [%[outp]]\n"
113 "vcvt.s32.f32 q0, q0, #28\n"
114 "vst1.s32 {q0}, [%[outp]]!\n"
121 "vld1.f32 {q0-q1}, [%[outp]]\n"
122 "vcvt.s32.f32 q0, q0, #28\n"
123 "vcvt.s32.f32 q1, q1, #28\n"
124 "vst1.s32 {q0-q1}, [%[outp]]!\n"
127 : "q0", "q1", "memory");
133 * Signed 32-bits fixed point to signed 16-bits integer
135 static block_t *Do_S32_S16 (filter_t *filter, block_t *inbuf)
137 unsigned nb_samples = inbuf->i_nb_samples
138 * aout_FormatNbChannels (&filter->fmt_in.audio);
139 int32_t *inp = (int32_t *)inbuf->p_buffer;
140 const int32_t *endp = inp + nb_samples;
141 int16_t *outp = (int16_t *)inp;
143 while (nb_samples & 3)
145 const int16_t roundup = 1 << 12;
147 "qadd r0, %[inv], %[roundup]\n"
148 "ssat %[outv], #16, r0, asr #13\n"
149 : [outv] "=r" (*outp)
150 : [inv] "r" (*inp), [roundup] "r" (roundup)
159 "vld1.s32 {q0}, [%[inp]]!\n"
160 "vrshrn.i32 d0, q0, #13\n"
161 "vst1.s16 {d0}, [%[outp]]!\n"
162 : [outp] "+r" (outp), [inp] "+r" (inp)
168 "vld1.s32 {q0-q1}, [%[inp]]!\n"
169 "vrshrn.i32 d0, q0, #13\n"
170 "vrshrn.i32 d1, q1, #13\n"
171 "vst1.s16 {q0}, [%[outp]]!\n"
172 : [outp] "+r" (outp), [inp] "+r" (inp)
174 : "q0", "q1", "memory");
178 "vld1.s32 {q0-q1}, [%[inp]]!\n"
179 "vld1.s32 {q2-q3}, [%[inp]]!\n"
180 "vrshrn.s32 d0, q0, #13\n"
181 "vrshrn.s32 d1, q1, #13\n"
182 "vrshrn.s32 d2, q2, #13\n"
183 "vrshrn.s32 d3, q3, #13\n"
184 "vst1.s16 {q0-q1}, [%[outp]]!\n"
185 : [outp] "+r" (outp), [inp] "+r" (inp)
187 : "q0", "q1", "q2", "q3", "memory");
189 inbuf->i_buffer /= 2;