diff --git a/modules/Makefile.am b/modules/Makefile.am index 8d76d7ff5f..9bb9e7756c 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -32,6 +32,7 @@ include hw/vaapi/Makefile.am include hw/vdpau/Makefile.am include hw/mmal/Makefile.am include isa/arm/Makefile.am +include isa/riscv/Makefile.am include keystore/Makefile.am include logger/Makefile.am include lua/Makefile.am diff --git a/modules/isa/riscv/Makefile.am b/modules/isa/riscv/Makefile.am new file mode 100644 index 0000000000..73bbb5a7e2 --- /dev/null +++ b/modules/isa/riscv/Makefile.am @@ -0,0 +1,9 @@ +riscvdir = $(pluginsdir)/riscv + +libvolume_rvv_plugin_la_SOURCES = isa/riscv/mixer.c isa/riscv/rvv_amplify.S +libvolume_rvv_plugin_la_LIBADD = $(AM_LIBADD) $(LIBM) + +if HAVE_RVV +riscv_LTLIBRARIES = \ + libvolume_rvv_plugin.la +endif diff --git a/modules/isa/riscv/mixer.c b/modules/isa/riscv/mixer.c new file mode 100644 index 0000000000..1bde504a22 --- /dev/null +++ b/modules/isa/riscv/mixer.c @@ -0,0 +1,134 @@ +/***************************************************************************** + * mixer.c: RISC-V V audio volume mixer module + ***************************************************************************** + * Copyright (C) 2012, 2022 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 +#include +#include + +#include +#include +#include +#include +#include + +void rvv_amplify_f32(void *, const void *, size_t, float); +void rvv_amplify_f64(void *, const void *, size_t, double); +void rvv_amplify_i16(void *, const void *, size_t, uint16_t); +void rvv_amplify_i32(void *, const void *, size_t, uint32_t); +void rvv_amplify_u8(void *, const void *, size_t, uint8_t); + +static void AmplifyFloat(audio_volume_t *volume, block_t *block, float amp) +{ + void *buf = block->p_buffer; + + if (amp != 1.f) + rvv_amplify_f32(buf, buf, block->i_buffer, amp); + + (void) volume; +} + +static void AmplifyDouble(audio_volume_t *volume, block_t *block, float amp) +{ + void *buf = block->p_buffer; + + if (amp != 1.f) + rvv_amplify_f64(buf, buf, block->i_buffer, amp); + + (void) volume; +} + +static void AmplifyShort(audio_volume_t *volume, block_t *block, float amp) +{ + void *buf = block->p_buffer; + uint_fast16_t fixed_amp = lroundf(ldexpf(amp, 16)); + + if (amp != 1.f) + rvv_amplify_i16(buf, buf, block->i_buffer, fixed_amp); + + (void) volume; +} + +static void AmplifyInt(audio_volume_t *volume, block_t *block, float amp) +{ + void *buf = block->p_buffer; + uint_fast32_t fixed_amp = lroundf(ldexpf(amp, 32)); + + if (amp != 1.f) + rvv_amplify_i32(buf, buf, block->i_buffer, fixed_amp); + + (void) volume; +} + +static void AmplifyByte(audio_volume_t *volume, block_t *block, float amp) +{ + void *buf = block->p_buffer; + uint_fast8_t fixed_amp = lroundf(ldexpf(amp, 8)); + + if (amp != 1.f) + rvv_amplify_u8(buf, buf, block->i_buffer, fixed_amp); + + (void) volume; +} + +static int Probe(vlc_object_t *obj) +{ + audio_volume_t *volume = (audio_volume_t *)obj; + + if (!vlc_CPU_RV_V()) + return VLC_ENOTSUP; + + switch (volume->format) { + case VLC_CODEC_FL32: + volume->amplify = AmplifyFloat; + break; + + case VLC_CODEC_FL64: + volume->amplify = AmplifyDouble; + break; + + case VLC_CODEC_S16N: + volume->amplify = AmplifyShort; + break; + + case VLC_CODEC_S32N: + volume->amplify = AmplifyInt; + break; + + case VLC_CODEC_U8: + volume->amplify = AmplifyByte; + break; + + default: + return VLC_ENOTSUP; + } + + return VLC_SUCCESS; +} + +vlc_module_begin() + set_subcategory(SUBCAT_AUDIO_AFILTER) + set_description("RISC-V V optimisation for audio volume") + set_capability("audio volume", 20) + set_callback(Probe) +vlc_module_end() diff --git a/modules/isa/riscv/rvv_amplify.S b/modules/isa/riscv/rvv_amplify.S new file mode 100644 index 0000000000..f6501fecfe --- /dev/null +++ b/modules/isa/riscv/rvv_amplify.S @@ -0,0 +1,103 @@ +/***************************************************************************** + * amplify.S: RISC-V V software amplification + ****************************************************************************** + * Copyright (C) 2022 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. + *****************************************************************************/ + + .option arch, +v + .text + .align 2 + + .globl rvv_amplify_f32 + .type rvv_amplify_f32, %function +rvv_amplify_f32: + srli a2, a2, 2 +#if defined (__riscv_float_abi_soft) + fmv.w.x fa0, a3 +#endif +1: vsetvli t0, a2, e32, m8, ta, ma + slli t1, t0, 2 + vle32.v v16, (a1) + add a1, a1, t1 + vfmul.vf v16, v16, fa0 + sub a2, a2, t0 + vse32.v v16, (a0) + add a0, a0, t1 + bnez a2, 1b + ret + + .globl rvv_amplify_f64 + .type rvv_amplify_f64, %function +rvv_amplify_f64: + srli a2, a2, 3 +#if defined (__riscv_float_abi_soft) || defined (__riscv_float_abi_single) + fmv.d.x fa0, a3 +#endif +1: vsetvli t0, a2, e64, m8, ta, ma + slli t1, t0, 3 + vle64.v v16, (a1) + add a1, a1, t1 + vfmul.vf v16, v16, fa0 + sub a2, a2, t0 + vse64.v v16, (a0) + add a0, a0, t1 + bnez a2, 1b + ret + + .globl rvv_amplify_i16 + .type rvv_amplify_i16, %function +rvv_amplify_i16: + srli a2, a2, 1 +1: vsetvli t0, a2, e16, m8, ta, ma + slli t1, t0, 1 + vle16.v v16, (a1) + add a1, a1, t1 + vmulhsu.vx v16, v16, a3 + sub a2, a2, t0 + vse16.v v16, (a0) + add a0, a0, t1 + bnez a2, 1b + ret + + .globl rvv_amplify_i32 + .type rvv_amplify_i32, %function +rvv_amplify_i32: + srli a2, a2, 2 +1: vsetvli t0, a2, e32, m8, ta, ma + slli t1, t0, 2 + vle32.v v16, (a1) + add a1, a1, t1 + vmulhsu.vx v16, v16, a3 + sub a2, a2, t0 + vse32.v v16, (a0) + add a0, a0, t1 + bnez a2, 1b + ret + + .globl rvv_amplify_u8 + .type rvv_amplify_u8, %function +rvv_amplify_u8: +1: vsetvli t0, a2, e8, m8, ta, ma + vle8.v v16, (a1) + add a1, a1, t0 + vmulhu.vx v16, v16, a3 + sub a2, a2, t0 + vse8.v v16, (a0) + add a0, a0, t0 + bnez a2, 1b + ret +