LCOV - code coverage report
Current view: top level - muse/framework/audio/engine/internal/fx/reverb - reverbmatrices.h Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 100 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2023 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #ifndef MUSE_AUDIO_REVERBMATRICES_H
      24              : #define MUSE_AUDIO_REVERBMATRICES_H
      25              : 
      26              : #include "log.h"
      27              : 
      28              : namespace muse::audio::fx {
      29              : namespace reverb_matrices {
      30              : template<int n>
      31              : inline void Hadamard(const float i[n], float o[n])
      32              : {
      33              :     UNUSED(i);
      34              :     UNUSED(o);
      35              : 
      36              :     // Hadamard matrix not defined for this size
      37              :     assert(false);
      38              : }
      39              : 
      40              : template<>
      41            0 : inline void Hadamard<8>(const float i[8], float o[8])
      42              : {
      43              :     // log2(n)*n adds n muls = 24 adds, 8 muls
      44              : 
      45            0 :     const float fact = 1.f / std::sqrt(8.f);
      46              : 
      47            0 :     float a[] = { i[7] + i[0], i[6] + i[1], i[5] + i[3], i[2] + i[4] };
      48            0 :     float b[] = { i[7] - i[0], i[6] - i[1], i[5] - i[3], i[2] - i[4] };
      49              : 
      50            0 :     float c[] = { a[0] + a[1], a[2] + a[3], b[0] + b[1], b[2] + b[3] };
      51            0 :     float d[] = { a[0] - a[1], a[2] - a[3], b[0] - b[1], b[2] - b[3] };
      52              : 
      53            0 :     o[0] = fact * (c[0] + c[1]);
      54            0 :     o[1] = fact * (c[2] + c[3]);
      55            0 :     o[2] = fact * (d[0] + d[1]);
      56            0 :     o[3] = fact * (d[2] + d[3]);
      57            0 :     o[4] = fact * (c[0] - c[1]);
      58            0 :     o[5] = fact * (c[2] - c[3]);
      59            0 :     o[6] = fact * (d[0] - d[1]);
      60            0 :     o[7] = fact * (d[2] - d[3]);
      61            0 : }
      62              : 
      63              : template<>
      64            0 : inline void Hadamard<12>(const float i[12], float o[12])
      65              : {
      66              :     // adds 12 + 24 + 24 = 60 adds, 12 muls
      67              : 
      68              :     // this might seem a bit crazy and it took me 4 attempts to get all signs and numbers right.. I don't have enough
      69              :     // autism. The 12x12 hadamard matrix is quite irregular (there exists only one).
      70              :     // I grouped operations as simd-friendly as I could.
      71              : 
      72            0 :     const float fact = 1.f / std::sqrt(12.f);
      73              : 
      74            0 :     float a[] = { i[7] + i[4], i[10] + i[11], i[2] + i[5], i[0] + i[1], i[8] + i[9], i[6] + i[3] };
      75            0 :     float b[] = { i[7] - i[4], i[10] - i[11], i[2] - i[5], i[0] - i[1], i[8] - i[9], i[6] - i[3] };
      76              : 
      77            0 :     float c[] = { a[0] + a[1], a[0] + b[1], b[0] + a[1], b[0] + b[1], a[0] - a[1], a[0] - b[1], b[0] - a[1], b[0] - b[1] };
      78            0 :     float d[] = { a[2] + a[3], a[2] + b[3], b[2] + a[3], b[2] + b[3], a[2] - a[3], a[2] - b[3], b[2] - a[3], b[2] - b[3] };
      79            0 :     float e[] = { a[4] + a[5], a[4] + b[5], b[4] + a[5], b[4] + b[5], a[4] - a[5], a[4] - b[5], b[4] - a[5], b[4] - b[5] };
      80              : 
      81            0 :     o[0] = fact * (c[0] + d[0] + e[0]);
      82            0 :     o[1] = fact * (c[3] + d[1] - e[5]);
      83            0 :     o[2] = fact * (c[7] - d[6] - e[1]);
      84            0 :     o[3] = fact * (c[4] + d[2] + e[6]);
      85            0 :     o[4] = fact * (c[3] - d[3] + e[4]);
      86            0 :     o[5] = fact * (c[7] - d[5] + e[1]);
      87            0 :     o[6] = fact * (c[6] + d[7] - e[6]);
      88            0 :     o[7] = fact * (c[4] - d[2] + e[2]);
      89            0 :     o[8] = fact * (c[1] - d[5] - e[3]);
      90            0 :     o[9] = fact * (c[0] - d[1] - e[5]);
      91            0 :     o[10] = fact * (c[2] + d[6] + e[7]);
      92            0 :     o[11] = fact * (c[5] + d[4] - e[2]);
      93            0 : }
      94              : 
      95              : template<>
      96            0 : inline void Hadamard<16>(const float i[16], float o[16])
      97              : {
      98              :     // 16 + 16 + 16 + 16 = 64 adds, 16 muls
      99              : 
     100            0 :     const float fact = 1.f / std::sqrt(16.f);
     101              : 
     102            0 :     float a[] = { i[10] + i[4], i[0] + i[5], i[15] + i[11], i[12] + i[7],
     103            0 :                   i[2] + i[14], i[1] + i[8], i[3] + i[9],   i[13] + i[6] };
     104            0 :     float b[] = { i[10] - i[4], i[0] - i[5], i[15] - i[11], i[12] - i[7],
     105            0 :                   i[2] - i[14], i[1] - i[8], i[3] - i[9],   i[13] - i[6] };
     106              : 
     107            0 :     float c[] = { a[0] + a[1], a[2] + a[3], a[4] + a[5], a[6] + a[7], b[0] + b[1], b[2] + b[3], b[4] + b[5], b[6] + b[7] };
     108            0 :     float d[] = { a[0] - a[1], a[2] - a[3], a[4] - a[5], a[6] - a[7], b[0] - b[1], b[2] - b[3], b[4] - b[5], b[6] - b[7] };
     109              : 
     110            0 :     float e[] = { c[0] + c[1], c[2] + c[3], d[0] + d[1], d[2] + d[3], c[4] + c[5], c[6] + c[7], d[4] + d[5], d[6] + d[7] };
     111            0 :     float f[] = { c[0] - c[1], c[2] - c[3], d[0] - d[1], d[2] - d[3], c[4] - c[5], c[6] - c[7], d[4] - d[5], d[6] - d[7] };
     112              : 
     113            0 :     o[0] = fact * (e[0] + e[1]);
     114            0 :     o[1] = fact * (e[2] + e[3]);
     115            0 :     o[2] = fact * (e[4] + e[5]);
     116            0 :     o[3] = fact * (e[6] + e[7]);
     117            0 :     o[4] = fact * (f[0] + f[1]);
     118            0 :     o[5] = fact * (f[2] + f[3]);
     119            0 :     o[6] = fact * (f[4] + f[5]);
     120            0 :     o[7] = fact * (f[6] + f[7]);
     121            0 :     o[8] = fact * (e[0] - e[1]);
     122            0 :     o[9] = fact * (e[2] - e[3]);
     123            0 :     o[10] = fact * (e[4] - e[5]);
     124            0 :     o[11] = fact * (e[6] - e[7]);
     125            0 :     o[12] = fact * (f[0] - f[1]);
     126            0 :     o[13] = fact * (f[2] - f[3]);
     127            0 :     o[14] = fact * (f[4] - f[5]);
     128            0 :     o[15] = fact * (f[6] - f[7]);
     129            0 : }
     130              : 
     131              : template<>
     132            0 : inline void Hadamard<24>(const float i[24], float o[24])
     133              : {
     134              :     // 24 + 48 + 48 = 120 adds, 24 muls
     135            0 :     const float fact = 1.f / std::sqrt(24.f);
     136              : 
     137            0 :     float a[] = { i[11] + i[12], i[23] + i[14], i[4] + i[2],   i[1] + i[22], i[3] + i[19], i[9] + i[0],
     138            0 :                   i[17] + i[7],  i[5] + i[10],  i[21] + i[13], i[6] + i[18], i[8] + i[15], i[20] + i[16] };
     139            0 :     float b[] = { i[11] - i[12], i[23] - i[14], i[4] - i[2],   i[1] - i[22], i[3] - i[19], i[9] - i[0],
     140            0 :                   i[17] - i[7],  i[5] - i[10],  i[21] - i[13], i[6] - i[18], i[8] - i[15], i[20] - i[16] };
     141              : 
     142            0 :     float c[] = { a[0] + a[1], a[0] + b[1], b[0] + a[1], b[0] + b[1], a[0] - a[1], a[0] - b[1], b[0] - a[1], b[0] - b[1] };
     143            0 :     float d[] = { a[2] + a[3], a[2] + b[3], b[2] + a[3], b[2] + b[3], a[2] - a[3], a[2] - b[3], b[2] - a[3], b[2] - b[3] };
     144            0 :     float e[] = { a[4] + a[5], a[4] + b[5], b[4] + a[5], b[4] + b[5], a[4] - a[5], a[4] - b[5], b[4] - a[5], b[4] - b[5] };
     145            0 :     float f[] = { a[6] + a[7], a[6] + b[7], b[6] + a[7], b[6] + b[7], a[6] - a[7], a[6] - b[7], b[6] - a[7], b[6] - b[7] };
     146            0 :     float g[] = { a[8] + a[9], a[8] + b[9], b[8] + a[9], b[8] + b[9], a[8] - a[9], a[8] - b[9], b[8] - a[9], b[8] - b[9] };
     147            0 :     float h[] = { a[10] + a[11], a[10] + b[11], b[10] + a[11], b[10] + b[11],
     148            0 :                   a[10] - a[11], a[10] - b[11], b[10] - a[11], b[10] - b[11] };
     149              : 
     150            0 :     o[0] = fact * (+c[0] + d[0] + e[0] + f[0] + g[0] + h[0]);
     151            0 :     o[1] = fact * (-c[2] - d[5] + e[7] + f[7] + g[3] + h[0]);
     152            0 :     o[2] = fact * (-c[7] - d[1] - e[2] + f[4] + g[5] - h[6]);
     153            0 :     o[3] = fact * (-c[6] - d[0] + e[3] - f[7] - g[7] + h[2]);
     154            0 :     o[4] = fact * (-c[6] + d[6] - e[3] - f[4] - g[4] - h[3]);
     155            0 :     o[5] = fact * (-c[6] + d[4] - e[5] + f[7] + g[7] + h[3]);
     156            0 :     o[6] = fact * (-c[4] + d[1] - e[1] - f[2] + g[4] + h[5]);
     157            0 :     o[7] = fact * (-c[3] + d[0] - e[0] + f[3] - g[7] - h[7]);
     158            0 :     o[8] = fact * (-c[5] + d[0] + e[6] - f[3] - g[4] - h[4]);
     159            0 :     o[9] = fact * (-c[3] - d[6] + e[4] - f[5] + g[7] + h[7]);
     160            0 :     o[10] = fact * (-c[7] + d[2] + e[1] - f[1] - g[2] + h[4]);
     161            0 :     o[11] = fact * (-c[4] - d[3] + e[0] - f[0] + g[3] - h[7]);
     162            0 :     o[12] = fact * (-c[1] + d[3] + e[0] + f[6] - g[3] - h[4]);
     163            0 :     o[13] = fact * (-c[2] + d[5] - e[6] + f[4] - g[5] + h[7]);
     164            0 :     o[14] = fact * (-c[7] - d[7] + e[2] + f[1] - g[1] - h[2]);
     165            0 :     o[15] = fact * (-c[4] - d[4] - e[3] + f[0] - g[0] + h[3]);
     166            0 :     o[16] = fact * (-c[1] + d[7] + e[3] + f[0] + g[6] - h[3]);
     167            0 :     o[17] = fact * (-c[2] + d[4] + e[5] - f[6] + g[4] - h[5]);
     168            0 :     o[18] = fact * (-c[5] - d[7] - e[7] + f[2] + g[1] - h[1]);
     169            0 :     o[19] = fact * (-c[3] - d[4] - e[4] - f[3] + g[0] - h[0]);
     170            0 :     o[20] = fact * (-c[5] + d[7] + e[7] + f[3] + g[0] + h[6]);
     171            0 :     o[21] = fact * (-c[1] - d[2] + e[4] + f[5] - g[6] + h[4]);
     172            0 :     o[22] = fact * (-c[0] + d[3] - e[7] - f[7] + g[2] + h[1]);
     173            0 :     o[23] = fact * (-c[0] - d[3] - e[4] - f[4] - g[3] + h[0]);
     174            0 : }
     175              : } // namespace reverb_matrices
     176              : } // namespace muse::audio::fx
     177              : 
     178              : #endif // MUSE_AUDIO_REVERBMATRICES_H
        

Generated by: LCOV version 2.0-1