]> git.sesse.net Git - vlc/blob - modules/arm_neon/audio_format.c
Use var_InheritString for --decklink-video-connection.
[vlc] / modules / arm_neon / audio_format.c
1 /*****************************************************************************
2  * audio_format.c: NEON assembly optimized audio conversions
3  *****************************************************************************
4  * Copyright (C) 2009 RĂ©mi Denis-Courmont
5  *
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.
10  *
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.
15  *
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  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <vlc_common.h>
26 #include <vlc_plugin.h>
27 #include <vlc_aout.h>
28 #include <vlc_filter.h>
29
30 #include <assert.h>
31
32 static int Open (vlc_object_t *);
33
34 vlc_module_begin ()
35     set_description (N_("ARM NEON audio format conversions") )
36     set_capability ("audio filter", 20)
37     set_callbacks (Open, NULL)
38 vlc_module_end ()
39
40 static block_t *Do_F32_S32 (filter_t *, block_t *);
41 static block_t *Do_S32_S16 (filter_t *, block_t *);
42
43 static int Open (vlc_object_t *obj)
44 {
45     filter_t *filter = (filter_t *)obj;
46
47     if (!AOUT_FMTS_SIMILAR (&filter->fmt_in.audio, &filter->fmt_out.audio))
48         return VLC_EGENERIC;
49
50     switch (filter->fmt_in.audio.i_format)
51     {
52         case VLC_CODEC_FL32:
53             switch (filter->fmt_out.audio.i_format)
54             {
55                 case VLC_CODEC_FI32:
56                     filter->pf_audio_filter = Do_F32_S32;
57                     break;
58                 default:
59                     return VLC_EGENERIC;
60             }
61             break;
62
63         case VLC_CODEC_FI32:
64             switch (filter->fmt_out.audio.i_format)
65             {
66                 case VLC_CODEC_S16N:
67                     filter->pf_audio_filter = Do_S32_S16;
68                     break;
69                 default:
70                     return VLC_EGENERIC;
71             }
72             break;
73         default:
74             return VLC_EGENERIC;
75     }
76     return VLC_SUCCESS;
77 }
78
79 /**
80  * Single-precision floating point to signed fixed point conversion.
81  */
82 static block_t *Do_F32_S32 (filter_t *filter, block_t *inbuf)
83 {
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;
88
89     if (nb_samples & 1)
90     {
91         asm volatile (
92             "vldr.32 s0, [%[outp]]\n"
93             "vcvt.s32.f32 d0, d0, #28\n"
94             "vstr.32 s0, [%[outp]]\n"
95             :
96             : [outp] "r" (outp)
97             : "d0", "memory");
98         outp++;
99     }
100
101     if (nb_samples & 2)
102         asm volatile (
103             "vld1.f32 {d0}, [%[outp]]\n"
104             "vcvt.s32.f32 d0, d0, #28\n"
105             "vst1.s32 {d0}, [%[outp]]!\n"
106             : [outp] "+r" (outp)
107             :
108             : "d0", "memory");
109
110     if (nb_samples & 4)
111         asm volatile (
112             "vld1.f32 {q0}, [%[outp]]\n"
113             "vcvt.s32.f32 q0, q0, #28\n"
114             "vst1.s32 {q0}, [%[outp]]!\n"
115             : [outp] "+r" (outp)
116             :
117             : "q0", "memory");
118
119     while (outp != endp)
120         asm volatile (
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"
125             : [outp] "+r" (outp)
126             :
127             : "q0", "q1", "memory");
128
129     return inbuf;
130 }
131
132 void s32_s16_neon_unaligned (int16_t *out, const int32_t *in, unsigned nb);
133 void s32_s16_neon (int16_t *out, const int32_t *in, unsigned nb);
134
135 /**
136  * Signed 32-bits fixed point to signed 16-bits integer
137  */
138 static block_t *Do_S32_S16 (filter_t *filter, block_t *inbuf)
139 {
140     const int32_t *in = (int32_t *)inbuf->p_buffer;
141     int16_t *out = (int16_t *)in;
142     unsigned nb;
143
144     nb = ((-(uintptr_t)in) & 12) >> 2;
145     out += nb; /* fix up misalignment */
146     inbuf->p_buffer += 2 * nb;
147
148     s32_s16_neon_unaligned (out, in, nb);
149     in += nb;
150     out += nb;
151
152     nb = inbuf->i_nb_samples
153          * aout_FormatNbChannels (&filter->fmt_in.audio) - nb;
154     assert (!(((uintptr_t)in) & 15));
155     assert (!(((uintptr_t)out) & 15));
156
157     s32_s16_neon (out, in, nb);
158     inbuf->i_buffer /= 2;
159     return inbuf;
160 }