[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