1 /** @addtogroup dsp_extra
2  *  @{
3  */
4 /*
5   Copyright (C) 2016 D Levin (https://www.kfrlib.com)
6   This file is part of KFR
7 
8   KFR is free software: you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation, either version 2 of the License, or
11   (at your option) any later version.
12 
13   KFR is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17 
18   You should have received a copy of the GNU General Public License
19   along with KFR.
20 
21   If GPL is not suitable for your project, you must purchase a commercial license to use KFR.
22   Buying a commercial license is mandatory as soon as you develop commercial activities without
23   disclosing the source code of your own applications.
24   See https://www.kfrlib.com for details.
25  */
26 #pragma once
27 
28 #include "../base.hpp"
29 
30 namespace kfr
31 {
32 inline namespace CMT_ARCH_NAME
33 {
34 
35 /**
36  * @brief Returns template expression that returns the sum of all the inputs
37  */
38 template <typename... E>
mixdown(E &&...e)39 internal::expression_function<fn::add, E...> mixdown(E&&... e)
40 {
41     return internal::expression_function<fn::add, E...>(fn::add(), std::forward<E>(e)...);
42 }
43 
44 namespace internal
45 {
46 struct stereo_matrix
47 {
48     template <typename T, size_t N>
operator ()kfr::CMT_ARCH_NAME::internal::stereo_matrix49     KFR_MEM_INTRINSIC vec<vec<T, 2>, N> operator()(const vec<vec<T, 2>, N>& x) const
50     {
51         return process(x, csizeseq<N>);
52     }
53     template <typename T, size_t N, size_t... indices>
processkfr::CMT_ARCH_NAME::internal::stereo_matrix54     KFR_MEM_INTRINSIC vec<vec<T, 2>, N> process(const vec<vec<T, 2>, N>& x, csizes_t<indices...>) const
55     {
56         return vec<vec<T, 2>, N>(hadd(transpose(x[indices] * matrix))...);
57     }
58     const f64x2x2 matrix;
59 };
60 } // namespace internal
61 
62 template <int = 0>
matrix_sum_diff()63 CMT_GNU_CONSTEXPR f64x2x2 matrix_sum_diff()
64 {
65     return { f64x2{ 1, 1 }, f64x2{ 1, -1 } };
66 }
67 template <int = 0>
matrix_halfsum_halfdiff()68 CMT_GNU_CONSTEXPR f64x2x2 matrix_halfsum_halfdiff()
69 {
70     return { f64x2{ 0.5, 0.5 }, f64x2{ 0.5, -0.5 } };
71 }
72 
73 /**
74  * @brief Returns template expression that returns the vector of length 2 containing mix of the left and right
75  * channels
76  */
77 template <typename Left, typename Right,
78           typename Result =
79               internal::expression_function<internal::stereo_matrix, internal::expression_pack<Left, Right>>>
mixdown_stereo(Left && left,Right && right,const f64x2x2 & matrix)80 Result mixdown_stereo(Left&& left, Right&& right, const f64x2x2& matrix)
81 {
82     return Result(internal::stereo_matrix{ matrix },
83                   pack(std::forward<Left>(left), std::forward<Right>(right)));
84 }
85 } // namespace CMT_ARCH_NAME
86 } // namespace kfr
87