1 /*****************************************************************************
2 * audio_format.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>
33 static int Open (vlc_object_t
*);
36 set_description (N_("ARM NEON audio format conversions") )
37 set_capability ("audio filter", 20)
38 set_callbacks (Open
, NULL
)
41 //static block_t *Do_F32_S32 (filter_t *, block_t *);
42 static block_t
*Do_S32_S16 (filter_t
*, block_t
*);
44 static int Open (vlc_object_t
*obj
)
46 filter_t
*filter
= (filter_t
*)obj
;
48 if (!(vlc_CPU() & CPU_CAPABILITY_NEON
))
50 if (!AOUT_FMTS_SIMILAR (&filter
->fmt_in
.audio
, &filter
->fmt_out
.audio
))
53 switch (filter
->fmt_in
.audio
.i_format
)
57 switch (filter
->fmt_out
.audio
.i_format
)
60 filter
->pf_audio_filter
= Do_F32_S32
;
68 switch (filter
->fmt_out
.audio
.i_format
)
71 filter
->pf_audio_filter
= Do_S32_S16
;
85 * Single-precision floating point to signed fixed point conversion.
87 static block_t
*Do_F32_S32 (filter_t
*filter
, block_t
*inbuf
)
89 unsigned nb_samples
= inbuf
->i_nb_samples
90 * aout_FormatNbChannels (&filter
->fmt_in
.audio
);
91 int32_t *outp
= (int32_t *)inbuf
->p_buffer
;
92 int32_t *endp
= outp
+ nb_samples
;
97 "vldr.32 s0, [%[outp]]\n"
98 "vcvt.s32.f32 d0, d0, #28\n"
99 "vstr.32 s0, [%[outp]]\n"
108 "vld1.f32 {d0}, [%[outp]]\n"
109 "vcvt.s32.f32 d0, d0, #28\n"
110 "vst1.s32 {d0}, [%[outp]]!\n"
117 "vld1.f32 {q0}, [%[outp]]\n"
118 "vcvt.s32.f32 q0, q0, #28\n"
119 "vst1.s32 {q0}, [%[outp]]!\n"
126 "vld1.f32 {q0-q1}, [%[outp]]\n"
127 "vcvt.s32.f32 q0, q0, #28\n"
128 "vcvt.s32.f32 q1, q1, #28\n"
129 "vst1.s32 {q0-q1}, [%[outp]]!\n"
132 : "q0", "q1", "memory");
138 void s32_s16_neon_unaligned (int16_t *out
, const int32_t *in
, unsigned nb
);
139 void s32_s16_neon (int16_t *out
, const int32_t *in
, unsigned nb
);
142 * Signed 32-bits fixed point to signed 16-bits integer
144 static block_t
*Do_S32_S16 (filter_t
*filter
, block_t
*inbuf
)
146 const int32_t *in
= (int32_t *)inbuf
->p_buffer
;
147 int16_t *out
= (int16_t *)in
;
150 nb
= ((-(uintptr_t)in
) & 12) >> 2;
151 out
+= nb
; /* fix up misalignment */
152 inbuf
->p_buffer
+= 2 * nb
;
154 s32_s16_neon_unaligned (out
, in
, nb
);
158 nb
= inbuf
->i_nb_samples
159 * aout_FormatNbChannels (&filter
->fmt_in
.audio
) - nb
;
160 assert (!(((uintptr_t)in
) & 15));
161 assert (!(((uintptr_t)out
) & 15));
163 s32_s16_neon (out
, in
, nb
);
164 inbuf
->i_buffer
/= 2;