[vlc-commits] volume_neon: ARM NEON software amplification
Rémi Denis-Courmont
git at videolan.org
Sat Aug 4 23:11:36 CEST 2012
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Aug 5 00:02:35 2012 +0300| [b089c842dfe083a26024c060d239f32693d30c2f] | committer: Rémi Denis-Courmont
volume_neon: ARM NEON software amplification
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b089c842dfe083a26024c060d239f32693d30c2f
---
modules/arm_neon/Modules.am | 6 +++
modules/arm_neon/amplify.S | 81 +++++++++++++++++++++++++++++++++++++++++
modules/arm_neon/volume.c | 85 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 172 insertions(+)
diff --git a/modules/arm_neon/Modules.am b/modules/arm_neon/Modules.am
index 9dfd4ab..b60011b 100644
--- a/modules/arm_neon/Modules.am
+++ b/modules/arm_neon/Modules.am
@@ -18,6 +18,11 @@ libchroma_yuv_neon_plugin_la_CFLAGS = $(AM_CFLAGS)
libchroma_yuv_neon_plugin_la_LIBADD = $(AM_LIBADD)
libchroma_yuv_neon_plugin_la_DEPENDENCIES =
+libvolume_neon_plugin_la_SOURCES = volume.c amplify.S
+libvolume_neon_plugin_la_CFLAGS = $(AM_CFLAGS)
+libvolume_neon_plugin_la_LIBADD = $(AM_LIBADD)
+libvolume_neon_plugin_la_DEPENDENCIES =
+
libyuv_rgb_neon_plugin_la_SOURCES = \
i420_rgb.S \
nv21_rgb.S \
@@ -30,5 +35,6 @@ libyuv_rgb_neon_plugin_la_DEPENDENCIES =
libvlc_LTLIBRARIES += \
libaudio_format_neon_plugin.la \
libchroma_yuv_neon_plugin.la \
+ libvolume_neon_plugin.la \
libyuv_rgb_neon_plugin.la \
$(NULL)
diff --git a/modules/arm_neon/amplify.S b/modules/arm_neon/amplify.S
new file mode 100644
index 0000000..5938118
--- /dev/null
+++ b/modules/arm_neon/amplify.S
@@ -0,0 +1,81 @@
+ @*****************************************************************************
+ @ amplify.S : ARM NEON software amplification
+ @*****************************************************************************
+ @ Copyright (C) 2012 Rémi Denis-Courmont
+ @
+ @ This program is free software; you can redistribute it and/or modify
+ @ it under the terms of the GNU Lesser General Public License as published by
+ @ the Free Software Foundation; either version 2.1 of the License, or
+ @ (at your option) any later version.
+ @
+ @ This program is distributed in the hope that it will be useful,
+ @ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ @ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ @ GNU Lesser General Public License for more details.
+ @
+ @ You should have received a copy of the GNU Lesser General Public License
+ @ along with this program; if not, write to the Free Software Foundation,
+ @ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ @****************************************************************************/
+
+ .syntax unified
+ .arm
+ .fpu neon
+ .text
+
+#define DST r0
+#define SRC r1
+#define SIZE r2
+ .align 2
+ .global amplify_float_arm_neon
+ .type amplify_float_arm_neon, %function
+amplify_float_arm_neon:
+ cmp SIZE, #0
+ bxeq lr
+#ifdef __ARM_PCS
+ vmov s0, r3 @ softfp
+#endif
+ pld [SRC, #64]
+ vld1.f32 {d16-d17}, [SRC,:128]!
+ subs SIZE, SIZE, #16
+ vmul.f32 d16, d16, d0[0]
+ vmul.f32 d17, d17, d0[0]
+ blo 5f
+ pld [SRC, #64]
+ vld1.f32 {d18-d19}, [SRC,:128]!
+ subs SIZE, SIZE, #16
+ vmul.f32 d18, d18, d0[0]
+ vmul.f32 d19, d19, d0[0]
+ blo 2f
+1: @ main loop starts
+ pld [SRC, #64]
+ vld1.f32 {d20-d21}, [SRC,:128]!
+ subs SIZE, SIZE, #16
+ vmul.f32 d20, d20, d0[0]
+ vmul.f32 d21, d21, d0[0]
+ vst1.f32 {d16-d17}, [DST,:128]!
+ blo 3f
+ pld [SRC, #64]
+ vld1.f32 {d16-d17}, [SRC,:128]!
+ subs SIZE, SIZE, #16
+ vmul.f32 d16, d16, d0[0]
+ vmul.f32 d17, d17, d0[0]
+ vst1.f32 {d18-d19}, [DST,:128]!
+ blo 4f
+ pld [SRC, #64]
+ vld1.f32 {d18-d19}, [SRC,:128]!
+ subs SIZE, SIZE, #16
+ vmul.f32 d18, d18, d0[0]
+ vmul.f32 d19, d19, d0[0]
+ vst1.f32 {d20-d21}, [DST,:128]!
+ bhi 1b
+ @ main loop ends
+2: vst1.f32 {d16-d17}, [DST,:128]!
+ vst1.f32 {d18-d19}, [DST,:128]!
+ bx lr
+3: vst1.f32 {d18-d19}, [DST,:128]!
+ vst1.f32 {d20-d21}, [DST,:128]!
+ bx lr
+4: vst1.f32 {d20-d21}, [DST,:128]!
+5: vst1.f32 {d16-d17}, [DST,:128]!
+ bx lr
diff --git a/modules/arm_neon/volume.c b/modules/arm_neon/volume.c
new file mode 100644
index 0000000..9a214cd
--- /dev/null
+++ b/modules/arm_neon/volume.c
@@ -0,0 +1,85 @@
+/*****************************************************************************
+ * volume.c : ARM NEON audio volume
+ *****************************************************************************
+ * Copyright (C) 2012 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_cpu.h>
+#include <vlc_aout.h>
+#include <vlc_aout_volume.h>
+
+static int Probe(vlc_object_t *);
+
+vlc_module_begin()
+ set_category(CAT_AUDIO)
+ set_subcategory(SUBCAT_AUDIO_MISC)
+ set_description(N_("ARM NEON audio volume"))
+ set_capability("audio volume", 10)
+ set_callbacks(Probe, NULL)
+vlc_module_end()
+
+static void AmplifyFloat(audio_volume_t *, block_t *, float);
+
+static int Probe(vlc_object_t *obj)
+{
+ audio_volume_t *volume = (audio_volume_t *)obj;
+
+ if (!vlc_CPU_ARM_NEON())
+ return VLC_EGENERIC;
+ if (volume->format == VLC_CODEC_FL32)
+ volume->amplify = AmplifyFloat;
+ else
+ return VLC_EGENERIC;
+ return VLC_SUCCESS;
+}
+
+void amplify_float_arm_neon(float *, const float *, size_t, float);
+
+static void AmplifyFloat(audio_volume_t *volume, block_t *block, float amp)
+{
+ float *buf = (float *)block->p_buffer;
+ size_t length = block->i_buffer;
+
+ if (amp == 1.0)
+ return;
+
+ /* Unaligned header */
+ assert(((uintptr_t)buf & 3) == 0);
+ while (unlikely((uintptr_t)buf & 12))
+ {
+ *(buf++) *= amp;
+ length -= 4;
+ }
+ /* Unaligned footer */
+ assert((length & 3) == 0);
+ while (unlikely(length & 12))
+ {
+ length -= 4;
+ buf[length / 4] *= amp;
+ }
+
+ amplify_float_arm_neon(buf, buf, length, amp);
+ (void) volume;
+}
More information about the vlc-commits
mailing list