diff --git a/libvisual/libvisual/CMakeLists.txt b/libvisual/libvisual/CMakeLists.txt index c784cf717..d1f71d1de 100644 --- a/libvisual/libvisual/CMakeLists.txt +++ b/libvisual/libvisual/CMakeLists.txt @@ -62,12 +62,11 @@ SET(libvisual_SOURCES lv_param_validators.c lv_cpu.c lv_error.c - lv_math.c lv_gl.c - lv_alpha_blend.c lv_util.c lv_actor.cpp + lv_alpha_blend.cpp lv_audio.cpp lv_bin.cpp lv_buffer.cpp @@ -76,6 +75,7 @@ SET(libvisual_SOURCES lv_fourier.cpp lv_input.cpp lv_libvisual.cpp + lv_math.cpp lv_morph.cpp lv_param.cpp lv_plugin.cpp diff --git a/libvisual/libvisual/lv_alpha_blend.c b/libvisual/libvisual/lv_alpha_blend.c deleted file mode 100644 index 8ec690ce2..000000000 --- a/libvisual/libvisual/lv_alpha_blend.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include "lv_alpha_blend.h" -#include "lv_common.h" -#include "lv_cpu.h" -#include "lv_alpha_blend_orc.h" - -#pragma pack(1) - -typedef struct { -#if VISUAL_LITTLE_ENDIAN == 1 - uint16_t b:5, g:6, r:5; -#else - uint16_t r:5, g:6, b:5; -#endif -} rgb16_t; - -#pragma pack() - -void visual_alpha_blend_8 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha) -{ - simd_interpolate_8 (dest, src1, src2, alpha, (int) size); -} - -void visual_alpha_blend_16 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha) -{ - rgb16_t *destr = (rgb16_t *) dest; - rgb16_t *src1r = (rgb16_t *) src1; - rgb16_t *src2r = (rgb16_t *) src2; - visual_size_t i; - - for (i = 0; i < size / 2; i++) { - destr[i].r = (alpha * (src2r[i].r - src1r[i].r)) / 255 + src1r[i].r; - destr[i].g = (alpha * (src2r[i].g - src1r[i].g)) / 255 + src1r[i].g; - destr[i].b = (alpha * (src2r[i].b - src1r[i].b)) / 255 + src1r[i].b; - } -} - -void visual_alpha_blend_24 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha) -{ - simd_interpolate_8 (dest, src1, src2, alpha, (int) size * 3); -} - -void visual_alpha_blend_32 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha) -{ - simd_interpolate_8 (dest, src1, src2, alpha, (int) size * 4); -} diff --git a/libvisual/libvisual/lv_alpha_blend.cpp b/libvisual/libvisual/lv_alpha_blend.cpp new file mode 100644 index 000000000..60c1182aa --- /dev/null +++ b/libvisual/libvisual/lv_alpha_blend.cpp @@ -0,0 +1,99 @@ +#include "config.h" +#include "lv_alpha_blend.h" +#include "lv_common.h" +#include "lv_cpu.h" +#include "lv_alpha_blend_orc.h" +#include + +namespace { + + #pragma pack(1) + + struct rgb16_t { + #if VISUAL_LITTLE_ENDIAN == 1 + std::uint16_t b:5, g:6, r:5; + #else + std::uint16_t r:5, g:6, b:5; + #endif + }; + + #pragma pack() + + static_assert (sizeof (rgb16_t) == 2); + +} // anonymous namespace + +namespace LV { + + void alpha_blend_8 (std::span dst, std::span src1, std::span src2, std::uint8_t alpha) + { + assert (dst.data () != src1.data ()); + assert (dst.data () != src2.data ()); + assert (src1.size () == src2.size ()); + + auto size {static_cast (std::min (dst.size (), src1.size ()))}; + ::simd_interpolate_8 (dst.data (), src1.data (), src2.data (), alpha, size); + } + + void alpha_blend_16 (std::span dst, std::span src1, std::span src2, std::uint8_t alpha) + { + assert (dst.data () != src1.data ()); + assert (dst.data () != src2.data ()); + assert (src1.size () == src2.size ()); + + auto dst_ptr = reinterpret_cast (dst.data ()); + auto src1_ptr = reinterpret_cast (src1.data ()); + auto src2_ptr = reinterpret_cast (src2.data ()); + + auto size {static_cast (std::min (dst.size (), src1.size ()))}; + auto pixel_count {size / sizeof (rgb16_t)}; + + for (std::size_t i {0}; i < pixel_count; i++) { + dst_ptr[i].r = (alpha * (src2_ptr[i].r - src1_ptr[i].r)) / 255 + src1_ptr[i].r; + dst_ptr[i].g = (alpha * (src2_ptr[i].g - src1_ptr[i].g)) / 255 + src1_ptr[i].g; + dst_ptr[i].b = (alpha * (src2_ptr[i].b - src1_ptr[i].b)) / 255 + src1_ptr[i].b; + } + } + + void alpha_blend_24 (std::span dst, std::span src1, std::span src2, std::uint8_t alpha) + { + assert (dst.data () != src1.data ()); + assert (dst.data () != src2.data ()); + assert (src1.size () == src2.size ()); + + auto size {static_cast (std::min (dst.size (), src1.size ()))}; + ::simd_interpolate_8 (dst.data (), src1.data (), src2.data (), alpha, size * 3); + } + + void alpha_blend_32 (std::span dst, std::span src1, std::span src2, std::uint8_t alpha) + { + assert (dst.data () != src1.data ()); + assert (dst.data () != src2.data ()); + assert (src1.size () == src2.size ()); + + auto size {static_cast (std::min (dst.size (), src1.size ()))}; + ::simd_interpolate_8 (dst.data (), src1.data (), src2.data (), alpha, size * 4); + } + +} // LV namespace + + +void visual_alpha_blend_8 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha) +{ + simd_interpolate_8 (dest, src1, src2, alpha, (int) size); +} + +void visual_alpha_blend_16 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha) +{ + LV::alpha_blend_16 ({dest, size}, {src1, size}, {src2, size}, alpha); +} + +void visual_alpha_blend_24 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha) +{ + simd_interpolate_8 (dest, src1, src2, alpha, (int) size * 3); +} + +void visual_alpha_blend_32 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha) +{ + simd_interpolate_8 (dest, src1, src2, alpha, (int) size * 4); +} diff --git a/libvisual/libvisual/lv_alpha_blend.h b/libvisual/libvisual/lv_alpha_blend.h index 636bf5b81..849c9728c 100644 --- a/libvisual/libvisual/lv_alpha_blend.h +++ b/libvisual/libvisual/lv_alpha_blend.h @@ -5,6 +5,22 @@ #include #include +#ifdef __cplusplus + +#include +#include + +namespace LV { + + LV_API void alpha_blend_8 (std::span dst, std::span src1, std::span src2, std::uint8_t alpha); + LV_API void alpha_blend_16 (std::span dst, std::span src1, std::span src2, std::uint8_t alpha); + LV_API void alpha_blend_24 (std::span dst, std::span src1, std::span src2, std::uint8_t alpha); + LV_API void alpha_blend_32 (std::span dst, std::span src1, std::span src2, std::uint8_t alpha); + +} // LV namespace + +#endif /* __cplusplus */ + LV_BEGIN_DECLS LV_API void visual_alpha_blend_8 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha); diff --git a/libvisual/libvisual/lv_buffer.h b/libvisual/libvisual/lv_buffer.h index 8f6a3f728..9eca7b15d 100644 --- a/libvisual/libvisual/lv_buffer.h +++ b/libvisual/libvisual/lv_buffer.h @@ -37,6 +37,7 @@ #include #include +#include #include namespace LV { @@ -88,6 +89,24 @@ namespace LV { */ void destroy_content (); + /** + * Returns an std::span that is a view of the entire buffer. + */ + template + std::span as_span () noexcept + { + return {static_cast (get_data ()), get_size () / sizeof (T)}; + } + + /** + * Returns an std::span that is a view of the entire buffer. + */ + template + std::span as_span () const noexcept + { + return {static_cast (get_data ()), get_size () / sizeof (T)}; + } + /** * Sets the data pair (data and its size). * diff --git a/libvisual/libvisual/lv_math.c b/libvisual/libvisual/lv_math.c deleted file mode 100644 index d580430b1..000000000 --- a/libvisual/libvisual/lv_math.c +++ /dev/null @@ -1,109 +0,0 @@ -/* Libvisual - The audio visualisation framework. - * - * Copyright (C) 2012 Libvisual team - * 2004-2006 Dennis Smit - * - * Authors: Chong Kai Xiong - * Dennis Smit - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "lv_math.h" -#include "lv_common.h" -#include "lv_math_orc.h" -#include - -int visual_math_is_power_of_2 (int n) -{ - return (n > 0) && !(n & (n - 1)); -} - -unsigned int visual_math_round_power_of_2 (unsigned int n) -{ - n--; - n |= n >> 1; - n |= n >> 2; - n |= n >> 4; - n |= n >> 8; - n |= n >> 16; -#if SIZEOF_INT > 4 - n |= n >> 32; -#endif - n++; - - return n; -} - -void visual_math_simd_mul_floats_float (float *LV_RESTRICT dest, const float *LV_RESTRICT src, float k, visual_size_t count) -{ - simd_mul_floats_float (dest, src, k, (int) count); -} - -void visual_math_simd_add_floats_float (float *LV_RESTRICT dest, const float *LV_RESTRICT src, float adder, visual_size_t count) -{ - simd_add_floats_float (dest, src, adder, (int) count); -} - -void visual_math_simd_mul_floats_floats (float *LV_RESTRICT dest, const float *LV_RESTRICT src1, const float *LV_RESTRICT src2, visual_size_t count) -{ - simd_mul_floats_floats (dest, src1, src2, (int) count); -} - -void visual_math_simd_floats_to_int32s (int32_t *LV_RESTRICT ints, const float *LV_RESTRICT flts, visual_size_t count) -{ - simd_floats_to_int32s ((uint32_t *LV_RESTRICT) ints, flts, (int) count); -} - -void visual_math_simd_int32s_to_floats (float *LV_RESTRICT flts, const int32_t *LV_RESTRICT ints, visual_size_t count) -{ - simd_int32s_to_floats (flts, (const uint32_t *LV_RESTRICT) ints, (int) count); -} - -void visual_math_simd_floats_to_int32s_mul_float (int32_t *LV_RESTRICT ints, const float *LV_RESTRICT flts, float k, visual_size_t count) -{ - simd_floats_to_int32s_mul_float ((uint32_t *LV_RESTRICT) ints, flts, k, (int) count); -} - -void visual_math_simd_int32s_to_floats_mul_float (float *LV_RESTRICT flts, const int32_t *LV_RESTRICT ints, float k, visual_size_t count) -{ - simd_int32s_to_floats_mul_float (flts, (const uint32_t *LV_RESTRICT) ints, k, (int) count); -} - -void visual_math_simd_denorm_floats_to_int32s (int32_t *LV_RESTRICT ints, const float *LV_RESTRICT flts, float k, visual_size_t count) -{ - simd_denorm_floats_to_int32s ((uint32_t *LV_RESTRICT) ints, flts, k, (int) count); -} - -void visual_math_simd_denorm_neg_floats_to_int32s (int32_t *LV_RESTRICT ints, const float *LV_RESTRICT flts, float k, visual_size_t count) -{ - simd_denorm_neg_floats_to_int32s ((uint32_t *LV_RESTRICT) ints, flts, k, (int) count); -} - -void visual_math_simd_sqrt_floats (float *LV_RESTRICT dest, const float *LV_RESTRICT src, visual_size_t count) -{ - simd_sqrt_floats (dest, src, (int) count); -} - -void visual_math_simd_complex_norm (float *LV_RESTRICT dest, const float *LV_RESTRICT real, const float *LV_RESTRICT imag, visual_size_t count) -{ - simd_complex_norm (dest, real, imag, (int) count); -} - -void visual_math_simd_complex_scaled_norm (float *LV_RESTRICT dest, const float *LV_RESTRICT real, const float *LV_RESTRICT imag, float k, visual_size_t count) -{ - simd_complex_scaled_norm (dest, real, imag, k, (int) count); -} diff --git a/libvisual/libvisual/lv_math.cpp b/libvisual/libvisual/lv_math.cpp new file mode 100644 index 000000000..b26670c96 --- /dev/null +++ b/libvisual/libvisual/lv_math.cpp @@ -0,0 +1,206 @@ +/* Libvisual - The audio visualisation framework. + * + * Copyright (C) 2012 Libvisual team + * 2004-2006 Dennis Smit + * + * Authors: Chong Kai Xiong + * Dennis Smit + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "lv_math.h" +#include "lv_common.h" +#include "lv_math_orc.h" +#include +#include +#include + +// NOTE: The ORC SIMD routines use uint32_t instead of int32_t for some reason. We are forced +// to perform signed to unsigned casts for routines accepting 32-bit integer vectors. + +namespace LV::Math { + + void simd_add (std::span dst, std::span src, float adder) + { + assert (dst.data () != src.data ()); + + auto count {static_cast (std::min (dst.size (), src.size ()))}; + ::simd_add_floats_float (dst.data (), src.data (), adder, count); + } + + void simd_mul (std::span dst, std::span src, float k) + { + assert (dst.data () != src.data ()); + + auto count {static_cast (std::min (dst.size (), src.size ()))}; + ::simd_mul_floats_float (dst.data (), src.data (), k, count); + } + + void simd_mul (std::span dst, std::span src1, std::span src2) + { + assert (dst.data () != src1.data ()); + assert (src1.data () != src2.data ()); + + auto count {static_cast (std::min (dst.size (), std::min (src1.size (), src2.size ())))}; + ::simd_mul_floats_floats (dst.data (), src1.data (), src2.data (), count); + } + + void simd_convert (std::span ints, std::span flts) + { + auto count {static_cast (std::min (ints.size (), flts.size ()))}; + ::simd_floats_to_int32s (reinterpret_cast (ints.data ()), flts.data (), count); + } + + void simd_convert (std::span flts, std::span ints) + { + auto count {static_cast (std::min (flts.size (), ints.size ()))}; + ::simd_int32s_to_floats (flts.data (), reinterpret_cast (ints.data ()), count); + } + + void simd_mul (std::span ints, std::span flts, float k) + { + auto count {static_cast (std::min (ints.size (), flts.size ()))}; + ::simd_floats_to_int32s_mul_float (reinterpret_cast (ints.data ()), flts.data (), k, count); + } + + void simd_mul (std::span flts, std::span ints, float k) + { + auto count {static_cast (std::min (flts.size (), ints.size ()))}; + ::simd_int32s_to_floats_mul_float (flts.data (), reinterpret_cast (ints.data ()), k, count); + } + + void simd_convert_denorm (std::span ints, std::span flts, float k) + { + auto count {static_cast (std::min (ints.size (), flts.size ()))}; + ::simd_denorm_floats_to_int32s (reinterpret_cast (ints.data ()), flts.data (), k, count); + } + + void simd_convert_denorm_neg (std::span ints, std::span flts, float k) + { + auto count {static_cast (std::min (ints.size (), flts.size ()))}; + ::simd_denorm_neg_floats_to_int32s (reinterpret_cast (ints.data ()), flts.data (), k, count); + } + + void simd_sqrt (std::span dst, std::span src) + { + assert (dst.data () != src.data ()); + + auto count {static_cast (std::min (dst.size (), src.size ()))}; + ::simd_sqrt_floats (dst.data (), src.data (), count); + } + + void simd_complex_norm (std::span dst, std::span real, std::span imag) + { + assert (real.data () != dst.data ()); + assert (real.size () == imag.size ()); + + auto count {static_cast (std::min (dst.size (), real.size()))}; + ::simd_complex_norm (dst.data (), real.data (), imag.data (), count); + } + + void simd_complex_scaled_norm (std::span dst, std::span real, std::span imag, float k) + { + assert (real.data () != dst.data ()); + assert (real.data () != imag.data ()); + assert (real.size () == imag.size ()); + + auto size {static_cast (std::min (dst.size (), real.size ()))}; + ::simd_complex_scaled_norm (dst.data (), real.data (), imag.data (), k, size); + } + +} // LV::Math namespace + +int visual_math_is_power_of_2 (int n) +{ + return (n > 0) && !(n & (n - 1)); +} + +unsigned int visual_math_round_power_of_2 (unsigned int n) +{ + n--; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; +#if SIZEOF_INT > 4 + n |= n >> 32; +#endif + n++; + + return n; +} + +void visual_math_simd_mul_floats_float (float *LV_RESTRICT dest, const float *LV_RESTRICT src, float k, visual_size_t count) +{ + simd_mul_floats_float (dest, src, k, (int) count); +} + +void visual_math_simd_add_floats_float (float *LV_RESTRICT dest, const float *LV_RESTRICT src, float adder, visual_size_t count) +{ + simd_add_floats_float (dest, src, adder, (int) count); +} + +void visual_math_simd_mul_floats_floats (float *LV_RESTRICT dest, const float *LV_RESTRICT src1, const float *LV_RESTRICT src2, visual_size_t count) +{ + simd_mul_floats_floats (dest, src1, src2, (int) count); +} + +void visual_math_simd_floats_to_int32s (int32_t *LV_RESTRICT ints, const float *LV_RESTRICT flts, visual_size_t count) +{ + simd_floats_to_int32s ((uint32_t *LV_RESTRICT) ints, flts, (int) count); +} + +void visual_math_simd_int32s_to_floats (float *LV_RESTRICT flts, const int32_t *LV_RESTRICT ints, visual_size_t count) +{ + simd_int32s_to_floats (flts, (const uint32_t *LV_RESTRICT) ints, (int) count); +} + +void visual_math_simd_floats_to_int32s_mul_float (int32_t *LV_RESTRICT ints, const float *LV_RESTRICT flts, float k, visual_size_t count) +{ + simd_floats_to_int32s_mul_float ((uint32_t *LV_RESTRICT) ints, flts, k, (int) count); +} + +void visual_math_simd_int32s_to_floats_mul_float (float *LV_RESTRICT flts, const int32_t *LV_RESTRICT ints, float k, visual_size_t count) +{ + simd_int32s_to_floats_mul_float (flts, (const uint32_t *LV_RESTRICT) ints, k, (int) count); +} + +void visual_math_simd_denorm_floats_to_int32s (int32_t *LV_RESTRICT ints, const float *LV_RESTRICT flts, float k, visual_size_t count) +{ + simd_denorm_floats_to_int32s ((uint32_t *LV_RESTRICT) ints, flts, k, (int) count); +} + +void visual_math_simd_denorm_neg_floats_to_int32s (int32_t *LV_RESTRICT ints, const float *LV_RESTRICT flts, float k, visual_size_t count) +{ + simd_denorm_neg_floats_to_int32s ((uint32_t *LV_RESTRICT) ints, flts, k, (int) count); +} + +void visual_math_simd_sqrt_floats (float *LV_RESTRICT dest, const float *LV_RESTRICT src, visual_size_t count) +{ + simd_sqrt_floats (dest, src, (int) count); +} + +void visual_math_simd_complex_norm (float *LV_RESTRICT dest, const float *LV_RESTRICT real, const float *LV_RESTRICT imag, visual_size_t count) +{ + simd_complex_norm (dest, real, imag, (int) count); +} + +void visual_math_simd_complex_scaled_norm (float *LV_RESTRICT dest, const float *LV_RESTRICT real, const float *LV_RESTRICT imag, float k, visual_size_t count) +{ + simd_complex_scaled_norm (dest, real, imag, k, (int) count); +} diff --git a/libvisual/libvisual/lv_math.h b/libvisual/libvisual/lv_math.h index 98bc1820e..2cd105be7 100644 --- a/libvisual/libvisual/lv_math.h +++ b/libvisual/libvisual/lv_math.h @@ -30,13 +30,31 @@ #ifdef __cplusplus -#include +#include +#include +#include -namespace LV { +namespace LV::Math { - // empty at the moment + LV_API void simd_add (std::span dst, std::span src, float adder); -} // LV namespce + LV_API void simd_mul (std::span dst, std::span src1, std::span src2); + LV_API void simd_mul (std::span dst, std::span src, float k); + LV_API void simd_mul (std::span ints, std::span flts, float k); + LV_API void simd_mul (std::span flts, std::span ints, float k); + + LV_API void simd_convert (std::span ints, std::span flts); + LV_API void simd_convert (std::span flts, std::span ints); + + LV_API void simd_convert_denorm (std::span ints, std::span flts, float k); + LV_API void simd_convert_denorm_neg (std::span ints, std::span flts, float k); + + LV_API void simd_sqrt (std::span dst, std::span src); + + LV_API void simd_complex_norm (std::span dst, std::span real, std::span imag); + LV_API void simd_complex_scaled_norm (std::span dst, std::span real, std::span imag, float k); + +} // LV::Math namespce #endif /* __cplusplus */ diff --git a/libvisual/po/POTFILES.in b/libvisual/po/POTFILES.in index b8e7db8e1..c66ec4492 100644 --- a/libvisual/po/POTFILES.in +++ b/libvisual/po/POTFILES.in @@ -1,7 +1,7 @@ libvisual/lv_libvisual.cpp libvisual/lv_libvisual_c.cpp libvisual/lv_actor.cpp -libvisual/lv_alpha_blend.c +libvisual/lv_alpha_blend.cpp libvisual/lv_audio.cpp libvisual/lv_audio_c.cpp libvisual/lv_buffer.cpp