├── .gitignore ├── LICENSE ├── README.md ├── USAT-schema.png ├── paper ├── allrad_decoders │ ├── 704ordered_decoder.json │ ├── 704ordered_layout.json │ ├── allrad_50_FOA_layout.json │ ├── allrad_50_FOA_maxre_decoder.json │ ├── allrad_704_5OA_basic_decoder.json │ ├── allrad_704_5OA_inphase_decoder.json │ ├── allrad_704_5OA_layout.json │ └── allrad_704_5OA_maxre_decoder.json ├── ex1_5OAto704.py ├── ex2_704to5OA.py ├── ex3_502to301irr.py ├── ex4_ObjectTo50.py ├── plots_paper │ ├── make_r_spherical_plots_all.r │ ├── panningPlots.py │ ├── physics_boxplots.py │ └── physics_mollweide.py └── saved_results │ ├── boxplot_decoding_5.0.2_to_3.0.1_irregular.png │ ├── boxplot_decoding_5oa_to_7.0.4.png │ ├── boxplot_rendering_to_5.1.png │ ├── boxplot_transcoding_7.0.4_to_5oa.png │ ├── ex1_50Ato704_ALLRAD_maxre │ ├── plot_energy_intensity_2D.png │ ├── plot_energy_intensity_3D.png │ ├── plot_pressure_velocity_2D.png │ ├── plot_pressure_velocity_2D_dB.png │ ├── plot_pressure_velocity_3D.png │ ├── plot_speaker_gains_2D.png │ ├── saved_asw_i.png │ ├── saved_asw_v.png │ ├── saved_delta_i.png │ ├── saved_delta_v.png │ ├── saved_energy_dB.png │ ├── saved_intensity_R.png │ ├── saved_intensity_T.png │ ├── saved_pressure_dB.png │ ├── saved_velocity_R.png │ ├── saved_velocity_T.png │ ├── speaker_gains-dB-ex1_50Ato704_ALLRAD_maxre.png │ └── speaker_gains-linear-ex1_50Ato704_ALLRAD_maxre.png │ ├── ex1_50Ato704_USAT │ ├── optimization_plots.png │ ├── plot_energy_intensity_2D.png │ ├── plot_energy_intensity_3D.png │ ├── plot_pressure_velocity_2D.png │ ├── plot_pressure_velocity_2D_dB.png │ ├── plot_pressure_velocity_3D.png │ ├── plot_speaker_gains_2D.png │ ├── saved_asw_i.png │ ├── saved_asw_v.png │ ├── saved_delta_i.png │ ├── saved_delta_v.png │ ├── saved_energy_dB.png │ ├── saved_intensity_R.png │ ├── saved_intensity_T.png │ ├── saved_pressure_dB.png │ ├── saved_velocity_R.png │ ├── saved_velocity_T.png │ ├── speaker_gains-dB-ex1_50Ato704_USAT.png │ └── speaker_gains-linear-ex1_50Ato704_USAT.png │ ├── ex2_704to5OA_USAT │ ├── optimization_plots.png │ ├── plot_energy_intensity_2D.png │ ├── plot_energy_intensity_3D.png │ ├── plot_pressure_velocity_2D.png │ ├── plot_pressure_velocity_2D_dB.png │ ├── plot_pressure_velocity_3D.png │ ├── plot_speaker_gains_2D.png │ ├── saved_asw_i.png │ ├── saved_asw_v.png │ ├── saved_delta_i.png │ ├── saved_delta_v.png │ ├── saved_energy_dB.png │ ├── saved_intensity_R.png │ ├── saved_intensity_T.png │ ├── saved_pressure_dB.png │ ├── saved_velocity_R.png │ └── saved_velocity_T.png │ ├── ex2_704to5OA_direct │ ├── plot_energy_intensity_2D.png │ ├── plot_energy_intensity_3D.png │ ├── plot_pressure_velocity_2D.png │ ├── plot_pressure_velocity_2D_dB.png │ ├── plot_pressure_velocity_3D.png │ ├── plot_speaker_gains_2D.png │ ├── saved_asw_i.png │ ├── saved_asw_v.png │ ├── saved_delta_i.png │ ├── saved_delta_v.png │ ├── saved_energy_dB.png │ ├── saved_intensity_R.png │ ├── saved_intensity_T.png │ ├── saved_pressure_dB.png │ ├── saved_velocity_R.png │ └── saved_velocity_T.png │ ├── ex3_50to301irr_USAT │ ├── optimization_plots.png │ ├── plot_energy_intensity_2D.png │ ├── plot_energy_intensity_3D.png │ ├── plot_pressure_velocity_2D.png │ ├── plot_pressure_velocity_2D_dB.png │ ├── plot_pressure_velocity_3D.png │ ├── plot_speaker_gains_2D.png │ ├── saved_asw_i.png │ ├── saved_asw_v.png │ ├── saved_delta_i.png │ ├── saved_delta_v.png │ ├── saved_energy_dB.png │ ├── saved_intensity_R.png │ ├── saved_intensity_T.png │ ├── saved_pressure_dB.png │ ├── saved_velocity_R.png │ ├── saved_velocity_T.png │ ├── speaker_gains-dB-ex3_50to301irr_USAT.png │ └── speaker_gains-linear-ex3_50to301irr_USAT.png │ ├── ex3_50to301irr_vbap │ ├── plot_energy_intensity_2D.png │ ├── plot_energy_intensity_3D.png │ ├── plot_pressure_velocity_2D.png │ ├── plot_pressure_velocity_2D_dB.png │ ├── plot_pressure_velocity_3D.png │ ├── plot_speaker_gains_2D.png │ ├── saved_asw_i.png │ ├── saved_asw_v.png │ ├── saved_delta_i.png │ ├── saved_delta_v.png │ ├── saved_energy_dB.png │ ├── saved_intensity_R.png │ ├── saved_intensity_T.png │ ├── saved_pressure_dB.png │ ├── saved_velocity_R.png │ ├── saved_velocity_T.png │ ├── speaker_gains-dB-ex3_50to301irr_vbap.png │ └── speaker_gains-linear-ex3_50to301irr_vbap.png │ ├── ex4_ObjectTo50_USAT │ ├── optimization_plots.png │ ├── plot_energy_intensity_2D.png │ ├── plot_energy_intensity_3D.png │ ├── plot_pressure_velocity_2D.png │ ├── plot_pressure_velocity_2D_dB.png │ ├── plot_pressure_velocity_3D.png │ ├── plot_speaker_gains_2D.png │ ├── speaker_gains-dB-ex4_ObjectTo50_USAT.png │ └── speaker_gains-linear-ex4_ObjectTo50_USAT.png │ ├── ex4_ObjectTo50_direct │ ├── plot_energy_intensity_2D.png │ ├── plot_energy_intensity_3D.png │ ├── plot_pressure_velocity_2D.png │ ├── plot_pressure_velocity_2D_dB.png │ ├── plot_pressure_velocity_3D.png │ ├── plot_speaker_gains_2D.png │ ├── speaker_gains-dB-ex4_ObjectTo50_direct.png │ └── speaker_gains-linear-ex4_ObjectTo50_direct.png │ └── ex4_ObjectTo50_vbip │ ├── plot_energy_intensity_2D.png │ ├── plot_energy_intensity_3D.png │ ├── plot_pressure_velocity_2D.png │ ├── plot_pressure_velocity_2D_dB.png │ ├── plot_pressure_velocity_3D.png │ ├── plot_speaker_gains_2D.png │ ├── speaker_gains-dB-panning51_vbip.png │ └── speaker_gains-linear-panning51_vbip.png ├── pyproject.toml ├── requirements.txt ├── tests ├── __init__.py ├── test_ambisonics_encoder.py ├── test_decoder_matrices.py ├── test_e_i_p_v.py └── test_vbap_encoder.py └── universal_transcoder ├── __init__.py ├── auxiliars ├── __init__.py ├── conventions.py ├── data │ ├── des.3.108.14.txt │ ├── des.3.60.9.txt │ └── des.3.80.11.txt ├── get_cloud_points.py ├── get_decoder_matrices.py ├── get_input_channels.py ├── get_left_right_pairs.py ├── my_coordinates.py └── typing.py ├── calculations ├── __init__.py ├── cost_function.py ├── energy_intensity.py ├── optimization.py ├── pressure_velocity.py └── set_up_system.py ├── encoders ├── __init__.py ├── ambisonics_encoder.py ├── t-design │ ├── ChatGPT_files │ │ └── unnamed.png │ ├── des.3.36.8.txt │ ├── des.3.56.9.txt │ └── des.3.60.10.txt └── vbap_encoder.py └── plots_and_logs ├── __init__.py ├── all_plots.py ├── common_plots_functions.py ├── e_i_plots.py ├── import_allrad_dec.py ├── p_v_plots.py ├── paper_plots_to_R.py ├── speakers_plots.py └── write_logs.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea* 2 | *.pyc 3 | *.pdf 4 | *.txt 5 | *.json 6 | venv* 7 | *npy 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2025 Dolby Laboratories 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /USAT-schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/USAT-schema.png -------------------------------------------------------------------------------- /paper/allrad_decoders/704ordered_layout.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "All-Round Ambisonic decoder (AllRAD) and loudspeaker layout", 3 | "Description": "This configuration file was created with the IEM AllRADecoder v0.9.4 plug-in. 20 Feb 2024 8:49:51pm", 4 | "LoudspeakerLayout": { 5 | "Name": "A loudspeaker layout", 6 | "Loudspeakers": [ 7 | { 8 | "Azimuth": 30.0, 9 | "Elevation": 0.0, 10 | "Radius": 1.0, 11 | "IsImaginary": false, 12 | "Channel": 1, 13 | "Gain": 1.0 14 | }, 15 | { 16 | "Azimuth": -30.0, 17 | "Elevation": 0.0, 18 | "Radius": 1.0, 19 | "IsImaginary": false, 20 | "Channel": 2, 21 | "Gain": 1.0 22 | }, 23 | { 24 | "Azimuth": 0.0, 25 | "Elevation": 0.0, 26 | "Radius": 1.0, 27 | "IsImaginary": false, 28 | "Channel": 3, 29 | "Gain": 1.0 30 | }, 31 | { 32 | "Azimuth": 90.0, 33 | "Elevation": 0.0, 34 | "Radius": 1.0, 35 | "IsImaginary": false, 36 | "Channel": 4, 37 | "Gain": 1.0 38 | }, 39 | { 40 | "Azimuth": -90.0, 41 | "Elevation": 0.0, 42 | "Radius": 1.0, 43 | "IsImaginary": false, 44 | "Channel": 5, 45 | "Gain": 1.0 46 | }, 47 | { 48 | "Azimuth": 120.0, 49 | "Elevation": 0.0, 50 | "Radius": 1.0, 51 | "IsImaginary": false, 52 | "Channel": 6, 53 | "Gain": 1.0 54 | }, 55 | { 56 | "Azimuth": -120.0, 57 | "Elevation": 0.0, 58 | "Radius": 1.0, 59 | "IsImaginary": false, 60 | "Channel": 7, 61 | "Gain": 1.0 62 | }, 63 | { 64 | "Azimuth": 45.0, 65 | "Elevation": 45.0, 66 | "Radius": 1.0, 67 | "IsImaginary": false, 68 | "Channel": 8, 69 | "Gain": 1.0 70 | }, 71 | { 72 | "Azimuth": -45.0, 73 | "Elevation": 45.0, 74 | "Radius": 1.0, 75 | "IsImaginary": false, 76 | "Channel": 9, 77 | "Gain": 1.0 78 | }, 79 | { 80 | "Azimuth": 135.0, 81 | "Elevation": 45.0, 82 | "Radius": 1.0, 83 | "IsImaginary": false, 84 | "Channel": 10, 85 | "Gain": 1.0 86 | }, 87 | { 88 | "Azimuth": -135.0, 89 | "Elevation": 45.0, 90 | "Radius": 1.0, 91 | "IsImaginary": false, 92 | "Channel": 11, 93 | "Gain": 1.0 94 | }, 95 | { 96 | "Azimuth": 0.0, 97 | "Elevation": -90.0, 98 | "Radius": 1.0, 99 | "IsImaginary": true, 100 | "Channel": 12, 101 | "Gain": 1.0 102 | } 103 | ] 104 | } 105 | } -------------------------------------------------------------------------------- /paper/allrad_decoders/allrad_50_FOA_layout.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "All-Round Ambisonic decoder (AllRAD) and loudspeaker layout", 3 | "Description": "This configuration file was created with the IEM AllRADecoder v0.9.4 plug-in. 12 Dec 2023 4:30:11pm", 4 | "LoudspeakerLayout": { 5 | "Name": "A loudspeaker layout", 6 | "Loudspeakers": [ 7 | { 8 | "Azimuth": -120.0, 9 | "Elevation": 0.0, 10 | "Radius": 1.0, 11 | "IsImaginary": false, 12 | "Channel": 2, 13 | "Gain": 1.0 14 | }, 15 | { 16 | "Azimuth": -30.0, 17 | "Elevation": 0.0, 18 | "Radius": 1.0, 19 | "IsImaginary": false, 20 | "Channel": 5, 21 | "Gain": 1.0 22 | }, 23 | { 24 | "Azimuth": 0.0, 25 | "Elevation": 0.0, 26 | "Radius": 1.0, 27 | "IsImaginary": false, 28 | "Channel": 6, 29 | "Gain": 1.0 30 | }, 31 | { 32 | "Azimuth": 30.0, 33 | "Elevation": 0.0, 34 | "Radius": 1.0, 35 | "IsImaginary": false, 36 | "Channel": 7, 37 | "Gain": 1.0 38 | }, 39 | { 40 | "Azimuth": 120.0, 41 | "Elevation": 0.0, 42 | "Radius": 1.0, 43 | "IsImaginary": false, 44 | "Channel": 10, 45 | "Gain": 1.0 46 | }, 47 | { 48 | "Azimuth": 0.0, 49 | "Elevation": -90.0, 50 | "Radius": 1.0, 51 | "IsImaginary": true, 52 | "Channel": 12, 53 | "Gain": 1.0 54 | }, 55 | { 56 | "Azimuth": 0.0, 57 | "Elevation": 90.0, 58 | "Radius": 1.0, 59 | "IsImaginary": true, 60 | "Channel": 13, 61 | "Gain": 1.0 62 | } 63 | ] 64 | } 65 | } -------------------------------------------------------------------------------- /paper/allrad_decoders/allrad_50_FOA_maxre_decoder.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "All-Round Ambisonic decoder (AllRAD) and loudspeaker layout", 3 | "Description": "This configuration file was created with the IEM AllRADecoder v0.9.4 plug-in. 12 Dec 2023 4:29:50pm", 4 | "Decoder": { 5 | "Name": "Decoder", 6 | "Description": "A 1st order Ambisonics decoder using the AllRAD approach.", 7 | "ExpectedInputNormalization": "n3d", 8 | "Weights": "maxrE", 9 | "WeightsAlreadyApplied": false, 10 | "Matrix": [ 11 | [ 12 | 0.398639053106308, 13 | -0.2140196859836578, 14 | -5.488759597938042e-7, 15 | -0.1863429248332977 16 | ], 17 | [ 18 | 0.2672039568424225, 19 | -0.1596160382032394, 20 | -0.0000173693842953071, 21 | 0.135953426361084 22 | ], 23 | [ 24 | 0.1865792721509933, 25 | -2.894687668231199e-6, 26 | 0.00002303599103470333, 27 | 0.1167110800743103 28 | ], 29 | [ 30 | 0.2672149538993835, 31 | 0.1596193313598633, 32 | -0.00001567145955050364, 33 | 0.1359520256519318 34 | ], 35 | [ 36 | 0.398630678653717, 37 | 0.2140232622623444, 38 | -3.350411134306341e-6, 39 | -0.1863408833742142 40 | ] 41 | ], 42 | "Routing": [ 43 | 2, 44 | 5, 45 | 6, 46 | 7, 47 | 10 48 | ] 49 | } 50 | } -------------------------------------------------------------------------------- /paper/allrad_decoders/allrad_704_5OA_layout.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "All-Round Ambisonic decoder (AllRAD) and loudspeaker layout", 3 | "Description": "This configuration file was created with the IEM AllRADecoder v0.9.4 plug-in. 11 Dec 2023 8:24:18pm", 4 | "LoudspeakerLayout": { 5 | "Name": "A loudspeaker layout", 6 | "Loudspeakers": [ 7 | { 8 | "Azimuth": -135.0, 9 | "Elevation": 45.0, 10 | "Radius": 1.0, 11 | "IsImaginary": false, 12 | "Channel": 1, 13 | "Gain": 1.0 14 | }, 15 | { 16 | "Azimuth": -120.0, 17 | "Elevation": 0.0, 18 | "Radius": 1.0, 19 | "IsImaginary": false, 20 | "Channel": 2, 21 | "Gain": 1.0 22 | }, 23 | { 24 | "Azimuth": -90.0, 25 | "Elevation": 0.0, 26 | "Radius": 1.0, 27 | "IsImaginary": false, 28 | "Channel": 3, 29 | "Gain": 1.0 30 | }, 31 | { 32 | "Azimuth": -45.0, 33 | "Elevation": 45.0, 34 | "Radius": 1.0, 35 | "IsImaginary": false, 36 | "Channel": 4, 37 | "Gain": 1.0 38 | }, 39 | { 40 | "Azimuth": -30.0, 41 | "Elevation": 0.0, 42 | "Radius": 1.0, 43 | "IsImaginary": false, 44 | "Channel": 5, 45 | "Gain": 1.0 46 | }, 47 | { 48 | "Azimuth": 0.0, 49 | "Elevation": 0.0, 50 | "Radius": 1.0, 51 | "IsImaginary": false, 52 | "Channel": 6, 53 | "Gain": 1.0 54 | }, 55 | { 56 | "Azimuth": 30.0, 57 | "Elevation": 0.0, 58 | "Radius": 1.0, 59 | "IsImaginary": false, 60 | "Channel": 7, 61 | "Gain": 1.0 62 | }, 63 | { 64 | "Azimuth": 45.0, 65 | "Elevation": 45.0, 66 | "Radius": 1.0, 67 | "IsImaginary": false, 68 | "Channel": 8, 69 | "Gain": 1.0 70 | }, 71 | { 72 | "Azimuth": 90.0, 73 | "Elevation": 0.0, 74 | "Radius": 1.0, 75 | "IsImaginary": false, 76 | "Channel": 9, 77 | "Gain": 1.0 78 | }, 79 | { 80 | "Azimuth": 120.0, 81 | "Elevation": 0.0, 82 | "Radius": 1.0, 83 | "IsImaginary": false, 84 | "Channel": 10, 85 | "Gain": 1.0 86 | }, 87 | { 88 | "Azimuth": 135.0, 89 | "Elevation": 45.0, 90 | "Radius": 1.0, 91 | "IsImaginary": false, 92 | "Channel": 11, 93 | "Gain": 1.0 94 | }, 95 | { 96 | "Azimuth": 0.0, 97 | "Elevation": -90.0, 98 | "Radius": 1.0, 99 | "IsImaginary": true, 100 | "Channel": 12, 101 | "Gain": 1.0 102 | } 103 | ] 104 | } 105 | } -------------------------------------------------------------------------------- /paper/ex1_5OAto704.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted 5 | provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 14 | promote products derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 20 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | POSSIBILITY OF SUCH DAMAGE. 24 | """ 25 | 26 | # FIFTH ORDER AMBISONICS DECODING TO 7.1.4. 27 | 28 | import os 29 | from pathlib import Path 30 | 31 | import numpy as np 32 | from universal_transcoder.auxiliars.get_cloud_points import ( 33 | get_all_sphere_points, 34 | get_equi_t_design_points, 35 | ) 36 | from universal_transcoder.auxiliars.get_input_channels import ( 37 | get_input_channels_ambisonics, 38 | ) 39 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 40 | from universal_transcoder.calculations.optimization import optimize 41 | from universal_transcoder.plots_and_logs.all_plots import plots_general 42 | from universal_transcoder.plots_and_logs.import_allrad_dec import get_allrad_decoder 43 | 44 | basepath = Path(__file__).resolve().parents[1] 45 | 46 | 47 | # USAT ####################################################### 48 | # Cloud of points to be encoded in input format (5OA) 49 | t_design = ( 50 | basepath / "universal_transcoder" / "encoders" / "t-design" / "des.3.56.9.txt" 51 | ) 52 | cloud_optimization = get_equi_t_design_points(t_design, False) 53 | 54 | # Input Ambisonics 5th Order 55 | order = 5 56 | input_matrix_optimization = get_input_channels_ambisonics(cloud_optimization, order) 57 | 58 | # Output Layout of speakers 7.1.4 (we are decoding, no virtual speakers) 59 | output_layout = MyCoordinates.mult_points( 60 | np.array( 61 | [ 62 | (30, 0, 1), # L 63 | (-30, 0, 1), # R 64 | (0, 0, 1), # C 65 | (90, 0, 1), # Ls 66 | (-90, 0, 1), # Rs 67 | (120, 0, 1), # Lb 68 | (-120, 0, 1), # Rb 69 | (45, 45, 1), # Tfl 70 | (-45, 45, 1), # Tfr 71 | (135, 45, 1), # Tbl 72 | (-135, 45, 1), # Tbr 73 | ] 74 | ) 75 | ) 76 | 77 | # Cloud of points to be encoded in input format (5OA) for plotting 78 | cloud_plots = get_all_sphere_points(1, False) 79 | 80 | # Input matrix for plotting 81 | input_matrix_plots = get_input_channels_ambisonics(cloud_plots, order) 82 | 83 | 84 | dictionary = { 85 | "input_matrix_optimization": input_matrix_optimization, 86 | "cloud_optimization": cloud_optimization, 87 | "output_layout": output_layout, 88 | "coefficients": { 89 | "energy": 5, 90 | "radial_intensity": 2, 91 | "transverse_intensity": 1, 92 | "pressure": 0, 93 | "radial_velocity": 0, 94 | "transverse_velocity": 0, 95 | "in_phase_quad": 10, 96 | "symmetry_quad": 2, 97 | "in_phase_lin": 0, 98 | "symmetry_lin": 0, 99 | "total_gains_lin": 0, 100 | "total_gains_quad": 0, 101 | }, 102 | "directional_weights": 1, 103 | "show_results": False, 104 | "results_file_name": "ex1_50Ato704_USAT", 105 | "save_results": True, 106 | "input_matrix_plots": input_matrix_plots, 107 | "cloud_plots": cloud_plots, 108 | } 109 | 110 | optimize(dictionary) 111 | ####################################################### 112 | 113 | # No optimization ##################################### 114 | ### AllRad 115 | 116 | file_name = "704ordered_decoder.json" 117 | order = 5 118 | 119 | # Import AllRad file (N3D and ACN) 120 | decoding_matrix = get_allrad_decoder( 121 | basepath / "paper" / "allrad_decoders" / file_name, 122 | type="maxre", # basic / maxre / inphase 123 | order=order, 124 | convention="sn3d", 125 | normalize_energy=True, 126 | layout=output_layout, 127 | ) 128 | 129 | # Input channels 130 | input_matrix = get_input_channels_ambisonics(cloud_plots, order) 131 | 132 | # Speaker matrix 133 | speaker_matrix = np.dot(input_matrix, decoding_matrix.T) 134 | 135 | # Call plots and save results 136 | show_results = False 137 | save_results = True 138 | save_plot_name = "ex1_50Ato704_ALLRAD_maxre" 139 | plots_general( 140 | output_layout, 141 | speaker_matrix, 142 | cloud_plots, 143 | show_results, 144 | save_results, 145 | save_plot_name, 146 | ) 147 | ####################################################### 148 | -------------------------------------------------------------------------------- /paper/ex2_704to5OA.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted 5 | provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 14 | promote products derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 20 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | POSSIBILITY OF SUCH DAMAGE. 24 | """ 25 | 26 | # TRANSCODING OF 7.1.5 to AMBISONICS 5TH ORDER 27 | from pathlib import Path 28 | import numpy as np 29 | from universal_transcoder.auxiliars.get_cloud_points import ( 30 | get_equi_circumference_points, 31 | get_equi_t_design_points, 32 | get_all_sphere_points, 33 | mix_clouds_of_points, 34 | ) 35 | from universal_transcoder.auxiliars.get_input_channels import ( 36 | get_input_channels_vbap, 37 | get_input_channels_ambisonics, 38 | ) 39 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 40 | from universal_transcoder.calculations.optimization import optimize 41 | from universal_transcoder.auxiliars.get_decoder_matrices import ( 42 | get_ambisonics_decoder_matrix, 43 | ) 44 | from universal_transcoder.plots_and_logs.all_plots import plots_general 45 | 46 | basepath = Path(__file__).resolve().parents[1] 47 | 48 | 49 | # USAT ####################################################### 50 | # Input Multichannel 7.0.4 51 | input_layout = MyCoordinates.mult_points( 52 | np.array( 53 | [ 54 | (30, 0, 1), # L 55 | (-30, 0, 1), # R 56 | (0, 0, 1), # C 57 | (90, 0, 1), # Ls 58 | (-90, 0, 1), # Rs 59 | (120, 0, 1), # Lb 60 | (-120, 0, 1), # Rb 61 | (45, 45, 1), # Tfl 62 | (-45, 45, 1), # Tfr 63 | (135, 45, 1), # Tbl 64 | (-135, 45, 1), # Tbr 65 | ] 66 | ) 67 | ) 68 | 69 | # Cloud of points to be encoded in input format (7.1.4) 70 | t_design_input = ( 71 | basepath / "universal_transcoder" / "encoders" / "t-design" / "des.3.56.9.txt" 72 | ) 73 | cloud_optimization_list = [ 74 | get_equi_t_design_points(t_design_input, False), 75 | get_equi_circumference_points(15, False), 76 | input_layout, 77 | ] 78 | cloud_optimization, weights = mix_clouds_of_points( 79 | cloud_optimization_list, 80 | list_of_weights=[0.6, 0.3, 0.1], 81 | discard_lower_hemisphere=True, 82 | ) 83 | 84 | # Input matrix for optimization 85 | input_matrix_optimization = get_input_channels_vbap(cloud_optimization, input_layout) 86 | 87 | # Set of virtual output speakers 88 | t_design_output = ( 89 | basepath / "universal_transcoder" / "encoders" / "t-design" / "des.3.60.10.txt" 90 | ) 91 | output_layout, _ = mix_clouds_of_points( 92 | [ 93 | get_equi_t_design_points(t_design_output, False), 94 | get_equi_circumference_points(36, False), 95 | ], 96 | list_of_weights=[1, 1], 97 | discard_lower_hemisphere=True, 98 | ) 99 | 100 | # Cloud of points to be encoded in input format (7.1.4) for plotting 101 | cloud_plots = get_all_sphere_points(1, False).discard_lower_hemisphere() 102 | 103 | # Input matrix for plotting 104 | input_matrix_plots = get_input_channels_vbap(cloud_plots, input_layout) 105 | 106 | # Transcoding to Ambisonics 5th order. Generate fixed Dspk 107 | order = 5 108 | Dspk = get_ambisonics_decoder_matrix(order, output_layout, "pseudo") 109 | 110 | 111 | dictionary = { 112 | "input_matrix_optimization": input_matrix_optimization, 113 | "cloud_optimization": cloud_optimization, 114 | "output_layout": output_layout, 115 | "Dspk": Dspk, 116 | "ambisonics_encoding_order": 5, 117 | "coefficients": { 118 | "energy": 0, 119 | "radial_intensity": 0.2, 120 | "transverse_intensity": 0.1, 121 | "pressure": 5, 122 | "radial_velocity": 2, 123 | "transverse_velocity": 1, 124 | "in_phase_quad": 0, 125 | "symmetry_quad": 0, 126 | "in_phase_lin": 0, 127 | "symmetry_lin": 0, 128 | "total_gains_lin": 0, 129 | "total_gains_quad": 0, 130 | }, 131 | "directional_weights": weights, 132 | "show_results": False, 133 | "save_results": True, 134 | "results_file_name": "ex2_704to5OA_USAT", 135 | "input_matrix_plots": input_matrix_plots, 136 | "cloud_plots": cloud_plots, 137 | } 138 | optimize(dictionary) 139 | ####################################################### 140 | 141 | 142 | # No optimization ##################################### 143 | input_matrix = get_input_channels_vbap(cloud_plots, input_layout) 144 | 145 | transcoding_matrix = get_input_channels_ambisonics(input_layout, 5) 146 | 147 | decoder_matrix = np.dot(Dspk, transcoding_matrix.T) 148 | 149 | speaker_signals = np.dot(input_matrix, decoder_matrix.T) 150 | 151 | show_results = False 152 | save_results = True 153 | save_plot_name = "ex2_704to5OA_direct" 154 | plots_general( 155 | output_layout, 156 | speaker_signals, 157 | cloud_plots, 158 | show_results, 159 | save_results, 160 | save_plot_name, 161 | ) 162 | ####################################################### 163 | -------------------------------------------------------------------------------- /paper/ex3_502to301irr.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted 5 | provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 14 | promote products derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 20 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | POSSIBILITY OF SUCH DAMAGE. 24 | """ 25 | 26 | import numpy as np 27 | from pathlib import Path 28 | from universal_transcoder.auxiliars.get_cloud_points import ( 29 | get_all_sphere_points, 30 | get_equi_circumference_points, 31 | mix_clouds_of_points, 32 | ) 33 | from universal_transcoder.auxiliars.get_input_channels import ( 34 | get_input_channels_vbap, 35 | ) 36 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 37 | from universal_transcoder.calculations.optimization import optimize 38 | from universal_transcoder.encoders.vbap_encoder import vbap_3D_encoder 39 | from universal_transcoder.plots_and_logs.all_plots import plots_general 40 | 41 | 42 | # Input and output layouts definition 43 | input_layout = MyCoordinates.mult_points( 44 | np.array( 45 | [ 46 | (30, 0, 1), 47 | (-30, 0, 1), 48 | (0, 0, 1), 49 | (110, 0, 1), 50 | (-110, 0, 1), 51 | (90, 45, 1), 52 | (-90, 45, 1), 53 | ] 54 | ) 55 | ) 56 | 57 | output_layout = MyCoordinates.mult_points( 58 | np.array( 59 | [ 60 | (10, 0, 1), 61 | (-45, 0, 1), 62 | (180, 0, 1), 63 | (0, 80, 1), 64 | ] 65 | ) 66 | ) 67 | 68 | show_results = False 69 | save_results = True 70 | 71 | # Transcoding using vbap 72 | decoding_matrix_vbap = np.zeros((4, 7)) 73 | for ci in range(7): 74 | vbap_gains = vbap_3D_encoder(input_layout[ci], output_layout) 75 | decoding_matrix_vbap[:, ci] = vbap_gains / np.sqrt(np.sum(vbap_gains**2)) 76 | 77 | 78 | # USAT ####################################################### 79 | # Clouds of points 80 | basepath = Path(__file__).resolve().parents[0] 81 | t_design = ( 82 | basepath / "universal_transcoder" / "encoders" / "t-design" / "des.3.56.9.txt" 83 | ) 84 | cloud_optimization_list = [ 85 | # get_equi_t_design_points(t_design, plot_show=False), 86 | get_equi_circumference_points(20, plot_show=False), 87 | input_layout, 88 | output_layout, 89 | ] 90 | cloud_optimization, weights = mix_clouds_of_points( 91 | cloud_optimization_list, 92 | list_of_weights=[0.5, 0.3, 0.1, 0.1], 93 | discard_lower_hemisphere=True, 94 | ) 95 | cloud_plots = get_all_sphere_points(1, plot_show=False).discard_lower_hemisphere() 96 | 97 | # Getting gain matrix 98 | input_matrix_optimization = get_input_channels_vbap(cloud_optimization, input_layout) 99 | input_matrix_plots = get_input_channels_vbap(cloud_plots, input_layout) 100 | 101 | T_initial = decoding_matrix_vbap + 0.001 * np.random.random_sample( 102 | decoding_matrix_vbap.shape 103 | ) 104 | optimization_dict = { 105 | "input_matrix_optimization": input_matrix_optimization, 106 | "cloud_optimization": cloud_optimization, 107 | "output_layout": output_layout, 108 | "coefficients": { 109 | "energy": 5, 110 | "radial_intensity": 2, 111 | "transverse_intensity": 1, 112 | "pressure": 0, 113 | "radial_velocity": 0, 114 | "transverse_velocity": 0, 115 | "in_phase_quad": 10000, 116 | "symmetry_quad": 0, 117 | "in_phase_lin": 0, 118 | "symmetry_lin": 0.0, 119 | "total_gains_lin": 0, 120 | "total_gains_quad": 0, 121 | "sparsity_quad": 0.01, 122 | "sparsity_lin": 0.001, 123 | }, 124 | "directional_weights": 1, # weights, 125 | "show_results": show_results, 126 | "save_results": save_results, 127 | "results_file_name": "ex3_50to301irr_USAT", 128 | "input_matrix_plots": input_matrix_plots, 129 | "cloud_plots": cloud_plots, 130 | "T_initial": T_initial, 131 | } 132 | transcoding_matrix = optimize(optimization_dict) 133 | ####################################################### 134 | 135 | 136 | # No optimization ##################################### 137 | 138 | np.set_printoptions(precision=2, suppress=True) 139 | 140 | print("\nTranscoding matrix (VBAP)") 141 | decoding_matrix_vbap_dB = 20 * np.log10(np.abs(decoding_matrix_vbap)) 142 | decoding_matrix_vbap_dB[decoding_matrix_vbap_dB < -30] = -np.inf 143 | print(decoding_matrix_vbap) 144 | print("In dB:") 145 | print(decoding_matrix_vbap_dB) 146 | # Corresponding plots 147 | input_matrix_plots = get_input_channels_vbap(cloud_plots, input_layout) 148 | speaker_signals = np.dot(input_matrix_plots, decoding_matrix_vbap.T) 149 | save_plot_name = "ex3_50to301irr_vbap" 150 | plots_general( 151 | output_layout, 152 | speaker_signals, 153 | cloud_plots, 154 | show_results, 155 | save_results, 156 | save_plot_name, 157 | ) 158 | 159 | print("\nTranscoding matrix in dB (USAT): ") 160 | transcoding_matrix_dB = 20 * np.log10(np.abs(transcoding_matrix)) 161 | transcoding_matrix_dB[transcoding_matrix_dB < -30] = -np.inf 162 | print(transcoding_matrix) 163 | print("In dB:") 164 | print(transcoding_matrix_dB) 165 | -------------------------------------------------------------------------------- /paper/ex4_ObjectTo50.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted 5 | provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 14 | promote products derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 20 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | POSSIBILITY OF SUCH DAMAGE. 24 | """ 25 | 26 | import numpy as np 27 | 28 | from universal_transcoder.auxiliars.get_cloud_points import ( 29 | get_equi_circumference_points, 30 | ) 31 | from universal_transcoder.auxiliars.get_input_channels import ( 32 | get_input_channels_vbap, 33 | ) 34 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 35 | from universal_transcoder.plots_and_logs.all_plots import plots_general 36 | from universal_transcoder.calculations.optimization import optimize 37 | 38 | 39 | # USAD ####################################################### 40 | # Cloud of points to be encoded in input format (one-to-one panning) 41 | n = 72 42 | cloud_optimization = get_equi_circumference_points(n, False) 43 | 44 | # Input matrix for optimization 45 | input_matrix_optimization = np.identity(n) 46 | 47 | # Set of output speakers 48 | output_layout = MyCoordinates.mult_points( 49 | np.array( 50 | [ 51 | (30, 0, 1), # L 52 | (-30, 0, 1), # R 53 | (0, 0, 1), # C 54 | (120, 0, 1), # Ls 55 | (-120, 0, 1), # Rs 56 | ] 57 | ) 58 | ) 59 | 60 | # Cloud of points to be encoded in input format (one-to-one panning) for plotting 61 | cloud_plots = cloud_optimization 62 | 63 | # Input matrix for plotting 64 | input_matrix_plots = input_matrix_optimization 65 | 66 | dictionary = { 67 | "input_matrix_optimization": input_matrix_optimization, 68 | "cloud_optimization": cloud_optimization, 69 | "output_layout": output_layout, 70 | "coefficients": { 71 | "energy": 5, 72 | "radial_intensity": 2, 73 | "transverse_intensity": 1, 74 | "pressure": 0, 75 | "radial_velocity": 0, 76 | "transverse_velocity": 0, 77 | "in_phase_quad": 10000, 78 | "symmetry_quad": 2, 79 | "in_phase_lin": 0, 80 | "symmetry_lin": 0, 81 | "total_gains_lin": 0, 82 | "total_gains_quad": 0, 83 | }, 84 | "directional_weights": 1, 85 | "show_results": False, 86 | "save_results": True, 87 | "input_matrix_plots": input_matrix_plots, 88 | "cloud_plots": cloud_plots, 89 | "results_file_name": "ex4_ObjectTo50_USAT", 90 | } 91 | optimize(dictionary) 92 | ############################################################## 93 | 94 | 95 | # VBAP ############################################ 96 | decoder_matrix = get_input_channels_vbap(cloud_plots, output_layout).T 97 | 98 | speaker_signals = np.dot(input_matrix_plots, decoder_matrix.T) 99 | 100 | show_results = False 101 | save_results = True 102 | save_plot_name = "ex4_ObjectTo50_direct" 103 | plots_general( 104 | output_layout, 105 | speaker_signals, 106 | cloud_plots, 107 | show_results, 108 | save_results, 109 | save_plot_name, 110 | ) 111 | ############################################################## 112 | 113 | 114 | # VBIP ############################################ 115 | decoder_matrix = get_input_channels_vbap(cloud_plots, output_layout, vbip=True).T 116 | 117 | speaker_signals = np.dot(input_matrix_plots, decoder_matrix.T) 118 | 119 | show_results = False 120 | save_results = True 121 | save_plot_name = "ex4_ObjectTo50_vbip" 122 | plots_general( 123 | output_layout, 124 | speaker_signals, 125 | cloud_plots, 126 | show_results, 127 | save_results, 128 | save_plot_name, 129 | ) 130 | ############################################################## 131 | -------------------------------------------------------------------------------- /paper/plots_paper/physics_boxplots.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import numpy as np 4 | import pandas as pd 5 | import seaborn as sns 6 | import matplotlib.pyplot as plt 7 | 8 | # Needed LaTeX packages: cm-super, type1cm, dvipng 9 | 10 | # Set up font in the header of the file 11 | # sns.set(style="ticks", font="Times New Roman", font) 12 | 13 | plt.rc( 14 | "font", 15 | **{ 16 | "family": "serif", 17 | "serif": ["Times New Roman"], 18 | "size": 9, 19 | } 20 | ) 21 | plt.rc("axes", **{"labelsize": 9, "titlesize": 9}) 22 | plt.rc("text", usetex=True) 23 | 24 | 25 | COLUMNS = ["azimuth", "elevation", "P", "V_r", "V_t", "E", "I_r", "I_t"] 26 | PLOTS_PATH = Path(__file__).resolve().parents[2] / "saved_results" 27 | LATEX_NAMES = { 28 | "P": r"$P$", 29 | "V_r": r"$V^R$", 30 | "V_t": r"$V^T$", 31 | "E": r"$E$", 32 | "I_r": r"$I^R$", 33 | "I_t": r"$I^T$", 34 | "ASW": "ASW", 35 | "P_dB": r"$P$", 36 | "E_dB": r"$E$", 37 | "delta": r"$\delta$", 38 | } 39 | 40 | 41 | def _get_path(name): 42 | return PLOTS_PATH / name / "signal_data.txt" 43 | 44 | 45 | def _save_plots(name): 46 | name_png = "boxplot_" + name.lower().replace(" ", "_") + ".png" 47 | name_pdf = "boxplot_" + name.lower().replace(" ", "_") + ".pdf" 48 | path_png = PLOTS_PATH / name_png 49 | path_pdf = PLOTS_PATH / name_pdf 50 | plt.savefig(path_pdf, bbox_inches="tight") 51 | plt.savefig(path_png, bbox_inches="tight") 52 | print("Plots saved in: %s" % PLOTS_PATH) 53 | 54 | 55 | def filter_elevation(df, remove_negative_elevation=True): 56 | elevation = df["elevation"] 57 | mask = np.ones(len(elevation), dtype=bool) 58 | prob = 1 - np.cos(np.deg2rad(elevation.to_numpy())) # Probability of removal 59 | prob_cumsum = np.cumsum(prob) 60 | prob_int = prob_cumsum.astype(int) 61 | mask[1:] = np.logical_not(prob_int[1:] - prob_int[:-1]) 62 | if remove_negative_elevation: 63 | mask[elevation < 0] = False 64 | return df[mask] 65 | 66 | 67 | def energy_to_db(energy): 68 | return 10 * np.log10(energy) 69 | 70 | 71 | def pressure_to_db(pressure): 72 | return 10 * np.log10(pressure) 73 | 74 | 75 | def radtrans_to_delta(iv_rad, iv_trans): 76 | return np.rad2deg(np.arctan2(iv_trans, iv_rad)) 77 | 78 | 79 | def radtrans_to_asw(iv_rad, iv_trans): 80 | iv = np.clip(np.sqrt(iv_rad**2 + iv_trans**2), 0, 1) 81 | return 3 / 8 * 2 * np.rad2deg(np.arccos(iv)) 82 | 83 | 84 | def box_plot( 85 | ut_txt_path, 86 | comp_txt_path, 87 | comp_name="comp", 88 | plot_type="pv", 89 | scale="human", 90 | title="", 91 | save_fig=True, 92 | ): 93 | ut_df = pd.read_csv(ut_txt_path, names=COLUMNS, header=None) 94 | ut_df["Method"] = "USAT" 95 | filter_elevation(ut_df) 96 | comp_df = pd.read_csv(comp_txt_path, names=COLUMNS, header=None) 97 | comp_df["Method"] = comp_name 98 | filter_elevation(comp_df) 99 | 100 | ref_df = pd.DataFrame( 101 | { 102 | "azimuth": [0], 103 | "elevation": [0], 104 | "P": [1], 105 | "V_r": [1], 106 | "V_t": [0], 107 | "E": [1], 108 | "I_r": [1], 109 | "I_t": [0], 110 | "Method": ["Ideal"], 111 | } 112 | ) 113 | 114 | df = pd.concat([ref_df, ut_df, comp_df]) 115 | 116 | # Selecting columns for the boxplot 117 | if scale == "linear": 118 | if plot_type == "pv": 119 | selected_columns = (["P", "V_r", "V_t"],) 120 | elif plot_type == "ei": 121 | selected_columns = (["E", "I_r", "I_t"],) 122 | else: 123 | raise ValueError("Wrong value for plot_type") 124 | unitlabels = ("",) 125 | elif scale == "human": 126 | if plot_type == "pv": 127 | df["P_dB"] = pressure_to_db(df["P"]) 128 | df["ASW"] = radtrans_to_asw(df["V_r"], df["V_t"]) 129 | df["delta"] = radtrans_to_delta(df["V_r"], df["V_t"]) 130 | selected_columns = (["P_dB"], ["ASW", "delta"]) 131 | elif plot_type == "ei": 132 | df["E_dB"] = energy_to_db(df["E"]) 133 | df["ASW"] = radtrans_to_asw(df["I_r"], df["I_t"]) 134 | df["delta"] = radtrans_to_delta(df["V_r"], df["V_t"]) 135 | selected_columns = (["E_dB"], ["ASW", "delta"]) 136 | else: 137 | raise ValueError("Wrong value for plot_type") 138 | 139 | unitlabels = ("dB", "deg") 140 | else: 141 | raise ValueError("Wrong value for plot_type") 142 | 143 | # Convert to longform 144 | df_long_list = [ 145 | pd.melt( 146 | df, 147 | id_vars="Method", 148 | value_vars=sc, 149 | var_name="Quantity", 150 | value_name="Value", 151 | ).replace({"Quantity": LATEX_NAMES}) 152 | for sc in selected_columns 153 | ] 154 | 155 | # Adding hue to the boxplot 156 | # Then when creating the figure 157 | mm = 1 / 25.4 # mm in inches 158 | width = 76 * mm # Replace by 159 mm for 2-column plots 159 | aspect_ratio = 0.75 # Replace by whatever apprpriate 160 | fig, axs = plt.subplots( 161 | 1, 162 | len(df_long_list), 163 | figsize=(width, aspect_ratio * width), 164 | width_ratios=[len(sc) for sc in selected_columns], 165 | ) 166 | # plt.suptitle(title) 167 | 168 | for ax, df, unit in zip(axs, df_long_list, unitlabels): 169 | sns.boxplot( 170 | ax=ax, 171 | data=df, 172 | x="Quantity", 173 | y="Value", 174 | hue="Method", 175 | showfliers=False, 176 | dodge=True, 177 | fill=False, 178 | ) 179 | 180 | ax.grid() 181 | ax.set_xlabel("") 182 | ax.set_ylabel(unit) 183 | ax.get_legend().remove() 184 | 185 | plt.subplots_adjust(bottom=0.4) 186 | lines, labels = axs[0].get_legend_handles_labels() 187 | fig.legend( 188 | lines, 189 | labels, 190 | title=None, 191 | loc="upper center", 192 | bbox_to_anchor=(0.5, 0.05), 193 | ncol=3, 194 | frameon=False, 195 | columnspacing=1, 196 | handletextpad=0.5, 197 | ) 198 | plt.tight_layout() 199 | 200 | # Display the plot 201 | if save_fig: 202 | _save_plots(title) 203 | else: 204 | plt.show() 205 | 206 | 207 | if __name__ == "__main__": 208 | box_plot( 209 | _get_path("ex1_50Ato704_USAT"), 210 | _get_path("ex1_50Ato704_ALLRAD_maxre"), 211 | plot_type="ei", 212 | comp_name="AllRad", 213 | title="Decoding 5OA to 7.0.4", 214 | ) 215 | box_plot( 216 | _get_path("ex2_704to5OA_USAT"), 217 | _get_path("ex2_704to5OA_direct"), 218 | plot_type="pv", 219 | comp_name="HOA enc.", 220 | title="Transcoding 7.0.4 to 5OA", 221 | ) 222 | box_plot( 223 | _get_path("ex3_50to301irr_USAT"), 224 | _get_path("ex3_50to301irr_vbap"), 225 | plot_type="ei", 226 | comp_name="Remapping", 227 | title="Decoding 5.0.2 to 3.0.1 irregular", 228 | ) 229 | box_plot( 230 | _get_path("ex4_ObjectTo50_USAT"), 231 | _get_path("ex4_ObjectTo50_direct"), 232 | plot_type="ei", 233 | comp_name="Tangent law", 234 | title="Rendering to 5.1", 235 | ) 236 | -------------------------------------------------------------------------------- /paper/plots_paper/physics_mollweide.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | 5 | PLOTS_PATH = Path("saved_results") 6 | R_SCRIPT_PATH = os.path.join("paper", "plots_paper", "make_r_spherical_plots") 7 | PDF_CROP_PATH = os.path.join(os.sep, "Users", "dscai", "src", "pdfcrop", "pdfcrop.pl") 8 | 9 | 10 | def _get_path(name): 11 | return PLOTS_PATH / name / "signal_data" 12 | 13 | 14 | def run_r_plots(file_name): 15 | txt_path = _get_path(file_name) 16 | folder, _ = os.path.split(txt_path) 17 | name = file_name.split("_")[0] 18 | # r_script = "_".join([R_SCRIPT_PATH, name]) + ".r" 19 | r_script = "_".join([R_SCRIPT_PATH, "all"]) + ".r" 20 | is_hemispherical = 0 if ("ex1_50Ato704" in file_name) else 1 21 | is_714 = 1 if ("7" in file_name) else 0 22 | 23 | # make plots 24 | os.system( 25 | " ".join( 26 | [ 27 | "Rscript --vanilla", 28 | r_script, 29 | str(txt_path), 30 | folder, 31 | str(is_hemispherical), 32 | str(is_714), 33 | ] 34 | ) 35 | ) 36 | 37 | # shrink pdfs 38 | pdfs = [file for file in os.listdir(folder) if os.path.splitext(file)[-1] == ".pdf"] 39 | for pdf in pdfs: 40 | file_path = os.path.join(folder, pdf) 41 | os.system(" ".join([PDF_CROP_PATH, file_path, file_path])) 42 | return 43 | 44 | 45 | if __name__ == "__main__": 46 | run_r_plots("ex1_50Ato704_USAT") 47 | run_r_plots("ex1_50Ato704_ALLRAD_maxre") 48 | # 49 | run_r_plots("ex2_704to5OA_USAT") 50 | run_r_plots("ex2_704to5OA_direct") 51 | # 52 | run_r_plots("ex3_50to301irr_USAT") 53 | run_r_plots("ex3_50to301irr_vbap") 54 | # 55 | -------------------------------------------------------------------------------- /paper/saved_results/boxplot_decoding_5.0.2_to_3.0.1_irregular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/boxplot_decoding_5.0.2_to_3.0.1_irregular.png -------------------------------------------------------------------------------- /paper/saved_results/boxplot_decoding_5oa_to_7.0.4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/boxplot_decoding_5oa_to_7.0.4.png -------------------------------------------------------------------------------- /paper/saved_results/boxplot_rendering_to_5.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/boxplot_rendering_to_5.1.png -------------------------------------------------------------------------------- /paper/saved_results/boxplot_transcoding_7.0.4_to_5oa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/boxplot_transcoding_7.0.4_to_5oa.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_energy_intensity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_energy_intensity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_energy_intensity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_energy_intensity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_pressure_velocity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_pressure_velocity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_pressure_velocity_2D_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_pressure_velocity_2D_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_pressure_velocity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_pressure_velocity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_speaker_gains_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/plot_speaker_gains_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_asw_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_asw_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_asw_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_asw_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_delta_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_delta_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_delta_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_delta_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_energy_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_energy_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_intensity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_intensity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_intensity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_intensity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_pressure_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_pressure_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_velocity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_velocity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_velocity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/saved_velocity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/speaker_gains-dB-ex1_50Ato704_ALLRAD_maxre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/speaker_gains-dB-ex1_50Ato704_ALLRAD_maxre.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_ALLRAD_maxre/speaker_gains-linear-ex1_50Ato704_ALLRAD_maxre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_ALLRAD_maxre/speaker_gains-linear-ex1_50Ato704_ALLRAD_maxre.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/optimization_plots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/optimization_plots.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/plot_energy_intensity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/plot_energy_intensity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/plot_energy_intensity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/plot_energy_intensity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/plot_pressure_velocity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/plot_pressure_velocity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/plot_pressure_velocity_2D_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/plot_pressure_velocity_2D_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/plot_pressure_velocity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/plot_pressure_velocity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/plot_speaker_gains_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/plot_speaker_gains_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/saved_asw_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/saved_asw_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/saved_asw_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/saved_asw_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/saved_delta_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/saved_delta_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/saved_delta_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/saved_delta_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/saved_energy_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/saved_energy_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/saved_intensity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/saved_intensity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/saved_intensity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/saved_intensity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/saved_pressure_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/saved_pressure_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/saved_velocity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/saved_velocity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/saved_velocity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/saved_velocity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/speaker_gains-dB-ex1_50Ato704_USAT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/speaker_gains-dB-ex1_50Ato704_USAT.png -------------------------------------------------------------------------------- /paper/saved_results/ex1_50Ato704_USAT/speaker_gains-linear-ex1_50Ato704_USAT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex1_50Ato704_USAT/speaker_gains-linear-ex1_50Ato704_USAT.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/optimization_plots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/optimization_plots.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/plot_energy_intensity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/plot_energy_intensity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/plot_energy_intensity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/plot_energy_intensity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/plot_pressure_velocity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/plot_pressure_velocity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/plot_pressure_velocity_2D_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/plot_pressure_velocity_2D_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/plot_pressure_velocity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/plot_pressure_velocity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/plot_speaker_gains_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/plot_speaker_gains_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/saved_asw_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/saved_asw_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/saved_asw_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/saved_asw_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/saved_delta_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/saved_delta_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/saved_delta_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/saved_delta_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/saved_energy_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/saved_energy_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/saved_intensity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/saved_intensity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/saved_intensity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/saved_intensity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/saved_pressure_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/saved_pressure_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/saved_velocity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/saved_velocity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_USAT/saved_velocity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_USAT/saved_velocity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/plot_energy_intensity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/plot_energy_intensity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/plot_energy_intensity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/plot_energy_intensity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/plot_pressure_velocity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/plot_pressure_velocity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/plot_pressure_velocity_2D_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/plot_pressure_velocity_2D_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/plot_pressure_velocity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/plot_pressure_velocity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/plot_speaker_gains_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/plot_speaker_gains_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/saved_asw_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/saved_asw_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/saved_asw_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/saved_asw_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/saved_delta_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/saved_delta_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/saved_delta_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/saved_delta_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/saved_energy_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/saved_energy_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/saved_intensity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/saved_intensity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/saved_intensity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/saved_intensity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/saved_pressure_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/saved_pressure_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/saved_velocity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/saved_velocity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex2_704to5OA_direct/saved_velocity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex2_704to5OA_direct/saved_velocity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/optimization_plots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/optimization_plots.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/plot_energy_intensity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/plot_energy_intensity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/plot_energy_intensity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/plot_energy_intensity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/plot_pressure_velocity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/plot_pressure_velocity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/plot_pressure_velocity_2D_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/plot_pressure_velocity_2D_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/plot_pressure_velocity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/plot_pressure_velocity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/plot_speaker_gains_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/plot_speaker_gains_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/saved_asw_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/saved_asw_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/saved_asw_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/saved_asw_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/saved_delta_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/saved_delta_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/saved_delta_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/saved_delta_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/saved_energy_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/saved_energy_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/saved_intensity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/saved_intensity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/saved_intensity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/saved_intensity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/saved_pressure_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/saved_pressure_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/saved_velocity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/saved_velocity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/saved_velocity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/saved_velocity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/speaker_gains-dB-ex3_50to301irr_USAT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/speaker_gains-dB-ex3_50to301irr_USAT.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_USAT/speaker_gains-linear-ex3_50to301irr_USAT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_USAT/speaker_gains-linear-ex3_50to301irr_USAT.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/plot_energy_intensity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/plot_energy_intensity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/plot_energy_intensity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/plot_energy_intensity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/plot_pressure_velocity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/plot_pressure_velocity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/plot_pressure_velocity_2D_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/plot_pressure_velocity_2D_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/plot_pressure_velocity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/plot_pressure_velocity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/plot_speaker_gains_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/plot_speaker_gains_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/saved_asw_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/saved_asw_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/saved_asw_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/saved_asw_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/saved_delta_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/saved_delta_i.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/saved_delta_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/saved_delta_v.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/saved_energy_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/saved_energy_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/saved_intensity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/saved_intensity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/saved_intensity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/saved_intensity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/saved_pressure_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/saved_pressure_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/saved_velocity_R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/saved_velocity_R.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/saved_velocity_T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/saved_velocity_T.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/speaker_gains-dB-ex3_50to301irr_vbap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/speaker_gains-dB-ex3_50to301irr_vbap.png -------------------------------------------------------------------------------- /paper/saved_results/ex3_50to301irr_vbap/speaker_gains-linear-ex3_50to301irr_vbap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex3_50to301irr_vbap/speaker_gains-linear-ex3_50to301irr_vbap.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_USAT/optimization_plots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_USAT/optimization_plots.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_USAT/plot_energy_intensity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_USAT/plot_energy_intensity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_USAT/plot_energy_intensity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_USAT/plot_energy_intensity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_USAT/plot_pressure_velocity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_USAT/plot_pressure_velocity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_USAT/plot_pressure_velocity_2D_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_USAT/plot_pressure_velocity_2D_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_USAT/plot_pressure_velocity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_USAT/plot_pressure_velocity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_USAT/plot_speaker_gains_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_USAT/plot_speaker_gains_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_USAT/speaker_gains-dB-ex4_ObjectTo50_USAT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_USAT/speaker_gains-dB-ex4_ObjectTo50_USAT.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_USAT/speaker_gains-linear-ex4_ObjectTo50_USAT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_USAT/speaker_gains-linear-ex4_ObjectTo50_USAT.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_direct/plot_energy_intensity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_direct/plot_energy_intensity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_direct/plot_energy_intensity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_direct/plot_energy_intensity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_direct/plot_pressure_velocity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_direct/plot_pressure_velocity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_direct/plot_pressure_velocity_2D_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_direct/plot_pressure_velocity_2D_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_direct/plot_pressure_velocity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_direct/plot_pressure_velocity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_direct/plot_speaker_gains_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_direct/plot_speaker_gains_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_direct/speaker_gains-dB-ex4_ObjectTo50_direct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_direct/speaker_gains-dB-ex4_ObjectTo50_direct.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_direct/speaker_gains-linear-ex4_ObjectTo50_direct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_direct/speaker_gains-linear-ex4_ObjectTo50_direct.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_vbip/plot_energy_intensity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_vbip/plot_energy_intensity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_vbip/plot_energy_intensity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_vbip/plot_energy_intensity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_vbip/plot_pressure_velocity_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_vbip/plot_pressure_velocity_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_vbip/plot_pressure_velocity_2D_dB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_vbip/plot_pressure_velocity_2D_dB.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_vbip/plot_pressure_velocity_3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_vbip/plot_pressure_velocity_3D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_vbip/plot_speaker_gains_2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_vbip/plot_speaker_gains_2D.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_vbip/speaker_gains-dB-panning51_vbip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_vbip/speaker_gains-dB-panning51_vbip.png -------------------------------------------------------------------------------- /paper/saved_results/ex4_ObjectTo50_vbip/speaker_gains-linear-panning51_vbip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/paper/saved_results/ex4_ObjectTo50_vbip/speaker_gains-linear-panning51_vbip.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "universal_transcoder" 3 | description = "This code consists of a universal transcoder tool. It generates a psychoacoustically motivated transcoding matrix to transform from any input format to any other given format or speaker layout." 4 | version = "2023.1000" 5 | authors = [ 6 | { name = "Amaia Sagasti" }, 7 | { name = "Davide Scaini" }, 8 | { name = "Daniel Arteaga" }, 9 | ] 10 | dynamic = ["dependencies"] 11 | [tool.setuptools.dynamic] 12 | dependencies = {file = ["requirements.txt"]} 13 | [tool.setuptools] 14 | packages = ["universal_transcoder"] 15 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | jax==0.4.13 2 | jaxlib==0.4.13 3 | pyfar==0.5.3 4 | matplotlib==3.7.1 5 | basemap 6 | pytest 7 | xarray -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_ambisonics_encoder.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import numpy as np 28 | 29 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 30 | from universal_transcoder.encoders.ambisonics_encoder import ambisonics_encoder 31 | 32 | 33 | def test_ambisonics_encoder1(): 34 | virtual = MyCoordinates.point(0, 0) 35 | n = 1 36 | wxyz = ambisonics_encoder(virtual, n) 37 | expected = np.array([1, 0, 0, 1]) 38 | np.testing.assert_allclose(wxyz, expected, atol=1e-15) 39 | 40 | 41 | def test_ambisonics_encoder2(): 42 | virtual = MyCoordinates.point(90, 0) 43 | n = 2 44 | wxyz = ambisonics_encoder(virtual, n) 45 | expected = np.array([1, 1, 0, 0, 0, 0, -0.5, 0, -0.8660254038]) 46 | np.testing.assert_allclose(wxyz, expected, atol=1e-15) # rtol=1e-07 47 | 48 | 49 | def test_ambisonics_encoder3(): 50 | virtual = MyCoordinates.point(90, 0) 51 | n = 4 52 | size = ambisonics_encoder(virtual, n).size 53 | expected = (n + 1) ** 2 54 | np.testing.assert_allclose(size, expected, atol=1e-15) # rtol=1e-07 55 | 56 | 57 | def test_ambisonics_encoder4(): 58 | virtual = MyCoordinates.point(90, 0) 59 | n = 5 60 | size = ambisonics_encoder(virtual, n).size 61 | expected = (n + 1) ** 2 62 | np.testing.assert_allclose(size, expected, atol=1e-15) # rtol=1e-07 63 | -------------------------------------------------------------------------------- /tests/test_decoder_matrices.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import numpy as np 28 | 29 | from universal_transcoder.auxiliars.get_decoder_matrices import get_vbap_decoder_matrix 30 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 31 | 32 | 33 | def test_decoder_matrices1(): # VBAP 2D-->2D 34 | layout_input = MyCoordinates.mult_points( 35 | np.array([(-90, 0, 1), (90, 0, 1), (180, 0, 1)]) 36 | ) 37 | layout_output = MyCoordinates.mult_points( 38 | np.array([(-90, 0, 1), (0, 0, 1), (90, 0, 1), (180, 0, 1)]) 39 | ) 40 | expected = np.array([(1, 0, 0), (0, 0, 0), (0, 1, 0), (0, 0, 1)]) 41 | 42 | result = get_vbap_decoder_matrix(layout_input, layout_output) 43 | print(result) 44 | np.testing.assert_allclose(result, expected, atol=1e-15) 45 | 46 | 47 | def test_decoder_matrices2(): # VBAP 3D-->3D 48 | layout_input = MyCoordinates.mult_points( 49 | np.array( 50 | [ 51 | (-130, 0, 1), 52 | (-40, 45, 1), 53 | (-25, 0, 1), 54 | (0, 0, 1), 55 | (25, 0, 1), 56 | (130, 0, 1), 57 | ] 58 | ) 59 | ) 60 | layout_output = MyCoordinates.mult_points( 61 | np.array( 62 | [ 63 | (-130, 0, 1), 64 | (-50, 0, 1), 65 | (-40, 45, 1), 66 | (0, 0, 1), 67 | (40, 45, 1), 68 | (50, 0, 1), 69 | (130, 0, 1), 70 | (180, 45, 1), 71 | ] 72 | ) 73 | ) 74 | 75 | expected = np.array( 76 | [ 77 | (1, 0, 0, 0, 0, 0, 0, 0), 78 | (0, 0, 1, 0, 0, 0, 0, 0), 79 | (0, 0.5, 0, 0.5, 0, 0, 0, 0), 80 | (0, 0, 0, 1, 0, 0, 0, 0), 81 | (0, 0, 0, 0.5, 0, 0.5, 0, 0), 82 | (0, 0, 0, 0, 0, 0, 1, 0), 83 | ] 84 | ).T 85 | 86 | result = get_vbap_decoder_matrix(layout_input, layout_output) 87 | np.testing.assert_allclose(result, expected, atol=1e-15) 88 | 89 | 90 | def test_decoder_matrices3(): # VBAP 3D-->2D 91 | layout_input = MyCoordinates.mult_points( 92 | np.array([(-90, 0, 1), (-90, 45, 1), (0, 0, 1), (90, 0, 1), (90, 45, 1)]) 93 | ) 94 | layout_output = MyCoordinates.mult_points( 95 | np.array([(-90, 0, 1), (0, 0, 1), (90, 0, 1)]) 96 | ) 97 | 98 | expected = np.array([(1, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1), (0, 0, 1)]).T 99 | 100 | result = get_vbap_decoder_matrix(layout_input, layout_output) 101 | print(result) 102 | np.testing.assert_allclose(result, expected, atol=1e-15) 103 | 104 | 105 | def test_decoder_matrices4(): # VBAP 2D-->3D 106 | layout_input = MyCoordinates.mult_points( 107 | np.array([(-90, 0, 1), (0, 0, 1), (90, 0, 1), (180, 0, 1)]) 108 | ) 109 | layout_output = MyCoordinates.mult_points( 110 | np.array( 111 | [(-90, 0, 1), (-90, 45, 1), (0, 0, 1), (90, 0, 1), (90, 45, 1), (180, 0, 1)] 112 | ) 113 | ) 114 | 115 | expected = np.array( 116 | [(1, 0, 0, 0, 0, 0), (0, 0, 1, 0, 0, 0), (0, 0, 0, 1, 0, 0), (0, 0, 0, 0, 0, 1)] 117 | ).T 118 | 119 | result = get_vbap_decoder_matrix(layout_input, layout_output) 120 | np.testing.assert_allclose(result, expected, atol=1e-15) 121 | -------------------------------------------------------------------------------- /tests/test_vbap_encoder.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import numpy as np 28 | 29 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 30 | from universal_transcoder.encoders.vbap_encoder import vbap_2D_encoder 31 | from universal_transcoder.encoders.vbap_encoder import vbap_3D_encoder 32 | 33 | 34 | # VBAP 3D 35 | def test_vbap_3D_encoder1(): 36 | virtual = MyCoordinates.point(0, 0) 37 | layout = MyCoordinates.mult_points( 38 | np.array( 39 | [ 40 | (-130, 0, 1), 41 | (-120, 45, 1), 42 | (-50, 0, 1), 43 | (-40, 45, 1), 44 | (0, 0, 1), 45 | (40, 45, 1), 46 | (50, 0, 1), 47 | (120, 45, 1), 48 | (130, 0, 1), 49 | ] 50 | ) 51 | ) 52 | speaker_gains = vbap_3D_encoder(virtual, layout) 53 | expected_gains = np.array([0, 0, 0, 0, 1, 0, 0, 0, 0]) 54 | np.testing.assert_allclose(speaker_gains, expected_gains, atol=1e-15) 55 | 56 | 57 | def test_vbap_3D_encoder2(): 58 | virtual = MyCoordinates.point(-25, 0) 59 | layout = MyCoordinates.mult_points( 60 | np.array( 61 | [ 62 | (-130, 0, 1), 63 | (-120, 45, 1), 64 | (-50, 0, 1), 65 | (-40, 45, 1), 66 | (0, 0, 1), 67 | (40, 45, 1), 68 | (50, 0, 1), 69 | (120, 45, 1), 70 | (130, 0, 1), 71 | ] 72 | ) 73 | ) 74 | speaker_gains = vbap_3D_encoder(virtual, layout) 75 | expected_gains = np.array([0, 0, 0.5, 0, 0.5, 0, 0, 0, 0]) 76 | np.testing.assert_allclose(speaker_gains, expected_gains, atol=1e-15) 77 | 78 | 79 | def test_vbap_3D_encoder3(): 80 | virtual = MyCoordinates.point(120, 45) 81 | layout = MyCoordinates.mult_points( 82 | np.array( 83 | [ 84 | (-130, 0, 1), 85 | (-120, 45, 1), 86 | (-50, 0, 1), 87 | (-40, 45, 1), 88 | (0, 0, 1), 89 | (40, 45, 1), 90 | (50, 0, 1), 91 | (120, 45, 1), 92 | (130, 0, 1), 93 | ] 94 | ) 95 | ) 96 | speaker_gains = vbap_3D_encoder(virtual, layout) 97 | expected_gains = np.array([0, 0, 0, 0, 0, 0, 0, 1, 0]) 98 | np.testing.assert_allclose(speaker_gains, expected_gains, atol=1e-15) 99 | 100 | 101 | def test_vbap_3D_encoder4(): 102 | layout = MyCoordinates.mult_points( 103 | np.array( 104 | [ 105 | (-130, 0, 1), 106 | (-120, 45, 1), 107 | (-50, 0, 1), 108 | (-40, 45, 1), 109 | (0, 0, 1), 110 | (40, 45, 1), 111 | (50, 0, 1), 112 | (120, 45, 1), 113 | (130, 0, 1), 114 | ] 115 | ) 116 | ) 117 | virtual = MyCoordinates.mult_points_cart( 118 | np.mean(layout.cart()[:3, :], axis=0, keepdims=True) 119 | ) 120 | speaker_gains = vbap_3D_encoder(virtual, layout) 121 | expected_gains = np.array([1 / 3, 1 / 3, 1 / 3, 0, 0, 0, 0, 0, 0]) 122 | np.testing.assert_allclose(speaker_gains, expected_gains, atol=1e-15) 123 | 124 | 125 | # VBAP 2D 126 | def test_vbap_2D_encoder1(): 127 | virtual = MyCoordinates.point(120, 0) 128 | layout = MyCoordinates.mult_points( 129 | np.array( 130 | [ 131 | (-130, 0, 1), 132 | (-120, 0, 1), 133 | (-50, 0, 1), 134 | (0, 0, 1), 135 | (50, 0, 1), 136 | (120, 0, 1), 137 | (130, 0, 1), 138 | ] 139 | ) 140 | ) 141 | speaker_gains = vbap_2D_encoder(virtual, layout) 142 | expected_gains = np.array([0, 0, 0, 0, 0, 1, 0]) 143 | np.testing.assert_allclose(speaker_gains, expected_gains, atol=1e-15) 144 | 145 | 146 | def test_vbap_2D_encoder2(): 147 | virtual = MyCoordinates.point(25, 0) 148 | layout = MyCoordinates.mult_points( 149 | np.array( 150 | [ 151 | (-130, 0, 1), 152 | (-120, 0, 1), 153 | (-50, 0, 1), 154 | (0, 0, 1), 155 | (50, 0, 1), 156 | (120, 0, 1), 157 | (130, 0, 1), 158 | ] 159 | ) 160 | ) 161 | speaker_gains = vbap_2D_encoder(virtual, layout) 162 | expected_gains = np.array([0, 0, 0, 0.5, 0.5, 0, 0]) 163 | np.testing.assert_allclose(speaker_gains, expected_gains, atol=1e-15) 164 | 165 | 166 | def test_vbap_2D_encoder3(): 167 | virtual = MyCoordinates.point(180, 0) 168 | layout = MyCoordinates.mult_points( 169 | np.array( 170 | [ 171 | (-130, 0, 1), 172 | (-120, 0, 1), 173 | (-50, 0, 1), 174 | (0, 0, 1), 175 | (50, 0, 1), 176 | (120, 0, 1), 177 | (130, 0, 1), 178 | ] 179 | ) 180 | ) 181 | speaker_gains = vbap_2D_encoder(virtual, layout) 182 | expected_gains = np.array([0.5, 0, 0, 0, 0, 0, 0.5]) 183 | np.testing.assert_allclose(speaker_gains, expected_gains, atol=1e-15) 184 | -------------------------------------------------------------------------------- /universal_transcoder/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/universal_transcoder/__init__.py -------------------------------------------------------------------------------- /universal_transcoder/auxiliars/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/universal_transcoder/auxiliars/__init__.py -------------------------------------------------------------------------------- /universal_transcoder/auxiliars/conventions.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import math as mh 28 | 29 | import numpy as np 30 | 31 | 32 | def get_convention(conventions: str, n: int): 33 | """Function to obtain the adapting matrix from one convention to another 34 | For now, only N3D to SN3D 35 | 36 | Args: 37 | conventions (string): conventions from and towards we desire 38 | n (int): desired ambisonics order 39 | 40 | Returns: 41 | adapter (numpy array): adapting matrix 42 | """ 43 | 44 | adapter = [] 45 | if conventions == "n3d2sn3d": 46 | # 0 - order 47 | if n >= 0: 48 | aux = 1 / mh.sqrt(2 * 0 + 1) 49 | adapter.append(aux) # W 50 | 51 | # 1 - order 52 | if n >= 1: 53 | aux = 1 / mh.sqrt(2 * 1 + 1) 54 | adapter.append(aux) # Y 55 | adapter.append(aux) # Z 56 | adapter.append(aux) # X 57 | 58 | # 2 - order 59 | if n >= 2: 60 | aux = 1 / mh.sqrt(2 * 2 + 1) 61 | adapter.append(aux) # V 62 | adapter.append(aux) # T 63 | adapter.append(aux) # R 64 | adapter.append(aux) # S 65 | adapter.append(aux) # U 66 | 67 | # 3 - order 68 | if n >= 3: 69 | aux = 1 / mh.sqrt(2 * 3 + 1) 70 | adapter.append(aux) # Q 71 | adapter.append(aux) # O 72 | adapter.append(aux) # M 73 | adapter.append(aux) # K 74 | adapter.append(aux) # L 75 | adapter.append(aux) # N 76 | adapter.append(aux) # P 77 | 78 | # 4 - order 79 | if n >= 4: 80 | aux = 1 / mh.sqrt(2 * 4 + 1) 81 | adapter.append(aux) # (4,-4) 82 | adapter.append(aux) # (4,-3) 83 | adapter.append(aux) # (4,-2) 84 | adapter.append(aux) # (4,-1) 85 | adapter.append(aux) # (4,-0) 86 | adapter.append(aux) # (4, 1) 87 | adapter.append(aux) # (4, 2) 88 | adapter.append(aux) # (4, 3) 89 | adapter.append(aux) # (4, 4) 90 | 91 | # 5 - order 92 | if n >= 5: 93 | aux = 1 / mh.sqrt(2 * 5 + 1) 94 | adapter.append(aux) # (5,-5) 95 | adapter.append(aux) # (5,-4) 96 | adapter.append(aux) # (5, -3) 97 | adapter.append(aux) # (5,-2) 98 | adapter.append(aux) # (5,-1) 99 | adapter.append(aux) # (5, 0) 100 | adapter.append(aux) # (5, 1) 101 | adapter.append(aux) # (5, 2) 102 | adapter.append(aux) # (5, 3) 103 | adapter.append(aux) # (5, 4) 104 | adapter.append(aux) # (5, 5) 105 | else: 106 | raise ValueError(f"Unsupported convention '{conventions}'") 107 | 108 | return np.asarray(adapter) 109 | -------------------------------------------------------------------------------- /universal_transcoder/auxiliars/data/des.3.108.14.txt: -------------------------------------------------------------------------------- 1 | -.6255209881602540E+00 2 | -.7673610045544000E+00 3 | .1409985179364700E+00 4 | -.7672427413700500E+00 5 | .1411116382934610E+00 6 | -.6256405368525180E+00 7 | .6254929286339920E+00 8 | .7673366024979470E+00 9 | .1412555651851610E+00 10 | .1412599782857530E+00 11 | -.6254973365383090E+00 12 | -.7673321969774169E+00 13 | .7672171775977220E+00 14 | .1411424450656330E+00 15 | .6256649363676060E+00 16 | .1409941047324360E+00 17 | .6255228978850370E+00 18 | .7673602587130800E+00 19 | .7673671213519559E+00 20 | -.1410034708464950E+00 21 | -.6255123678051890E+00 22 | -.1411074217386270E+00 23 | .6256300078253110E+00 24 | -.7672521025313510E+00 25 | -.7673415575795750E+00 26 | -.1412506125124700E+00 27 | .6254879682905210E+00 28 | -.1411466612794940E+00 29 | -.6256555691710420E+00 30 | .7672240407957190E+00 31 | -.6256319160421340E+00 32 | .7672476983004790E+00 33 | -.1411229077154560E+00 34 | .6256599755682080E+00 35 | -.7672232962446800E+00 36 | -.1411311754058560E+00 37 | .5571880480715090E+00 38 | -.4475345647833600E-01 39 | -.8291794782913420E+00 40 | -.4485587811454200E-01 41 | -.8292832145924940E+00 42 | .5570254035443200E+00 43 | -.5570231765605090E+00 44 | .4489683751235000E-01 45 | -.8292824939402920E+00 46 | -.8292769813537900E+00 47 | .5570303319042050E+00 48 | -.4490988238058500E-01 49 | .4500608513203000E-01 50 | -.8291787590336450E+00 51 | -.5571687696457081E+00 52 | -.8291849902738060E+00 53 | -.5571805246676550E+00 54 | .4474499788474600E-01 55 | .4474511262700700E-01 56 | .8291868870343290E+00 57 | .5571776927213760E+00 58 | .8292859037266960E+00 59 | -.5570225725340150E+00 60 | -.4484131541096600E-01 61 | -.4489531964450300E-01 62 | .8292750865916650E+00 63 | -.5570343266194679E+00 64 | .8291760679008749E+00 65 | .5571727652985150E+00 66 | .4500619990677900E-01 67 | .5570150477881700E+00 68 | .4485436035495000E-01 69 | .8292902525019150E+00 70 | -.5571799192991600E+00 71 | -.4499774138897400E-01 72 | .8291717197297990E+00 73 | -.2560655654109130E+00 74 | .8607703824921130E+00 75 | .4398917762759060E+00 76 | .8608171937494520E+00 77 | .4399428934535150E+00 78 | -.2558202678543430E+00 79 | .2559781138440990E+00 80 | -.8608464350244180E+00 81 | .4397938386773610E+00 82 | .4397804109275130E+00 83 | -.2559784640674000E+00 84 | .8608531907927870E+00 85 | -.8608968669378900E+00 86 | .4397427222396980E+00 87 | .2558963124660960E+00 88 | .4399052037052120E+00 89 | .2560581296938110E+00 90 | -.8607657323399810E+00 91 | -.8607663058143230E+00 92 | -.4398986385971350E+00 93 | -.2560674804326980E+00 94 | -.4399515654145460E+00 95 | .2558296190221410E+00 96 | .8608099825863290E+00 97 | .8608459790026740E+00 98 | -.4397869770942070E+00 99 | .2559914358201620E+00 100 | -.4397340492183260E+00 101 | -.2559092846502780E+00 102 | -.8608974410391970E+00 103 | -.2558221826891520E+00 104 | -.8608167398021460E+00 105 | -.4399426682200340E+00 106 | .2559096342559870E+00 107 | .8608927923347450E+00 108 | -.4397429467325800E+00 109 | -.2148474707463120E+00 110 | -.3239846898907800E-01 111 | .9761100878082740E+00 112 | -.3236168906853200E-01 113 | .9761498728347380E+00 114 | -.2146721846102970E+00 115 | .2146533912587150E+00 116 | .3222968714374900E-01 117 | .9761583728513260E+00 118 | .9761568906841750E+00 119 | -.2146621640237140E+00 120 | -.3221614667304400E-01 121 | .3218487197615700E-01 122 | .9761185894661391E+00 123 | .2148409488773350E+00 124 | .9761115692642290E+00 125 | .2148389643385310E+00 126 | .3241024144420400E-01 127 | .3240438731759700E-01 128 | -.9761127401675890E+00 129 | -.2148345274044470E+00 130 | -.9761504697174500E+00 131 | .2146677480389070E+00 132 | -.3237311264470600E-01 133 | -.3222757022524800E-01 134 | -.9761557221333460E+00 135 | .2146657631381940E+00 136 | -.9761179902309550E+00 137 | -.2148445483512370E+00 138 | .3217901787241900E-01 139 | -.2146592411125010E+00 140 | .3235957222646100E-01 141 | -.9761527894189130E+00 142 | .2148533206001200E+00 143 | -.3219079038364400E-01 144 | -.9761156712406470E+00 145 | -.5316579534180750E+00 146 | -.8273339530941490E+00 147 | -.1812687248945930E+00 148 | -.8272321878124060E+00 149 | -.1811732915871120E+00 150 | -.5318487998130590E+00 151 | .5316939693677690E+00 152 | .8273652744794220E+00 153 | -.1810199589093320E+00 154 | -.1810139371845850E+00 155 | -.5316957717831260E+00 156 | -.8273654336584780E+00 157 | .8272650003242400E+00 158 | -.1811153925205650E+00 159 | .5318174816895900E+00 160 | -.1812747464882220E+00 161 | .5316629623847160E+00 162 | .8273294148729020E+00 163 | .8273379129643990E+00 164 | .1812652358037510E+00 165 | -.5316529808631980E+00 166 | .1811784250571890E+00 167 | .5318388191844240E+00 168 | -.8272374802330430E+00 169 | -.8273707254762440E+00 170 | .1810234483059680E+00 171 | .5316842989860900E+00 172 | .1811102586154330E+00 173 | -.5318060097873780E+00 174 | .8272734990184800E+00 175 | -.5318438268704770E+00 176 | .8272376408031750E+00 177 | .1811629914142640E+00 178 | .5318078109206920E+00 179 | -.8272689621881080E+00 180 | .1811256923905430E+00 181 | -.6600529784314531E+00 182 | -.6410703014238900E+00 183 | -.3916106922647170E+00 184 | -.6409432781620240E+00 185 | -.3914906263600130E+00 186 | -.6602475321053179E+00 187 | .6601308161987530E+00 188 | .6411379932874460E+00 189 | -.3913685974476170E+00 190 | -.3913661271946650E+00 191 | -.6601299904344370E+00 192 | -.6411403514158810E+00 193 | .6410141926516800E+00 194 | -.3914886640099250E+00 195 | .6601798472922650E+00 196 | -.3916131622327060E+00 197 | .6600590826742870E+00 198 | .6410625075180110E+00 199 | .6410745322055420E+00 200 | .3916047718584040E+00 201 | -.6600523818722061E+00 202 | .3914935825762260E+00 203 | .6602408324135060E+00 204 | -.6409483739081900E+00 205 | -.6411454466952770E+00 206 | .3913745185133930E+00 207 | .6601200666850870E+00 208 | .3914857068510000E+00 209 | -.6601699246530760E+00 210 | .6410262178062029E+00 211 | -.6602469350652650E+00 212 | .6409507331154460E+00 213 | .3914794278831230E+00 214 | .6601690972978630E+00 215 | -.6410184249773530E+00 216 | .3914998618294490E+00 217 | -.8878095447864510E+00 218 | -.2962340013095760E+00 219 | .3521926016460220E+00 220 | -.2960667920239880E+00 221 | .3523564025129960E+00 222 | -.8878003268014290E+00 223 | .8877394975983099E+00 224 | .2961730845485540E+00 225 | .3524203291424820E+00 226 | .3524163117776850E+00 227 | -.8877438356676250E+00 228 | -.2961648619048960E+00 229 | .2960029751816160E+00 230 | .3522565288678170E+00 231 | .8878612372176340E+00 232 | .3521966187543760E+00 233 | .8878076464546130E+00 234 | .2962349146112020E+00 235 | .2962433087631600E+00 236 | -.3522028941708700E+00 237 | -.8878023560177780E+00 238 | -.3523574352146160E+00 239 | .8877950378573241E+00 240 | -.2960814222555850E+00 241 | -.2961794919204630E+00 242 | -.3524100372105150E+00 243 | .8877414456017140E+00 244 | -.3522554953175360E+00 245 | -.8878588486443870E+00 246 | .2960113695493150E+00 247 | -.8877931373857750E+00 248 | .2960732001098630E+00 249 | -.3523691322852040E+00 250 | .8878631845739851E+00 251 | -.2960122833498500E+00 252 | -.3522437985034650E+00 253 | -.2622350441333200E+00 254 | -.9631968323160830E+00 255 | -.5903087196255600E-01 256 | -.9631467531778790E+00 257 | -.5898607663367000E-01 258 | -.2624289896453470E+00 259 | .2622467591823790E+00 260 | .9632070203456430E+00 261 | -.5881218628148700E-01 262 | -.5880201827075200E-01 263 | -.2622502022937960E+00 264 | -.9632067036956030E+00 265 | .9631574262320920E+00 266 | -.5885698170873300E-01 267 | .2624188026763920E+00 268 | -.5904103993067700E-01 269 | .2622395302518100E+00 270 | .9631949877243000E+00 271 | .9631989104617060E+00 272 | .5903143538266000E-01 273 | -.2622272840915770E+00 274 | .5899352177531600E-01 275 | .2624167439246010E+00 276 | -.9631496337000580E+00 277 | -.9632095835159220E+00 278 | .5881162296107100E-01 279 | .2622374710596640E+00 280 | .5884953642617700E-01 281 | -.2624060718844200E+00 282 | .9631613496712860E+00 283 | -.2624212294120090E+00 284 | .9631493186694710E+00 285 | .5897871056935700E-01 286 | .2624095143628140E+00 287 | -.9631595066989900E+00 288 | .5886434767523200E-01 289 | -.7155075639675860E+00 290 | -.5512037701387860E+00 291 | .4292124528598390E+00 292 | -.5510696074929951E+00 293 | .4293431805847270E+00 294 | -.7155324737444880E+00 295 | .7154222023624230E+00 296 | .5511295351454290E+00 297 | .4294500062373780E+00 298 | .4294508199172310E+00 299 | -.7154282714111380E+00 300 | -.5511210227691270E+00 301 | .5509918383737999E+00 302 | .4293192792340250E+00 303 | .7156067010051250E+00 304 | .4292116388668970E+00 305 | .7155060331503000E+00 306 | .5512063910974860E+00 307 | .5512118694302640E+00 308 | -.4292194620397150E+00 309 | -.7154971197744480E+00 310 | -.4293412473175590E+00 311 | .7155235615710740E+00 312 | -.5510826854369940E+00 313 | -.5511341003106980E+00 314 | -.4294429977797900E+00 315 | .7154228925136690E+00 316 | -.4293212114664220E+00 317 | -.7156013233111630E+00 318 | .5509973171080930E+00 319 | -.7155220290294890E+00 320 | .5510741739856940E+00 321 | -.4293547260011320E+00 322 | .7156073906348100E+00 323 | -.5509999389950980E+00 324 | -.4293077330962450E+00 325 | -------------------------------------------------------------------------------- /universal_transcoder/auxiliars/data/des.3.60.9.txt: -------------------------------------------------------------------------------- 1 | .9839748285202770E+00 2 | .0000000000000000E+00 3 | .1783074222753860E+00 4 | -.3477336794164400E+00 5 | -.3932186551872460E+00 6 | -.8511523820164280E+00 7 | -.9839748285202760E+00 8 | .0000000000000000E+00 9 | -.1783074222753850E+00 10 | -.6362411491043150E+00 11 | .2149112329123390E+00 12 | .7409523346035960E+00 13 | .3477336794164400E+00 14 | .3932186551872470E+00 15 | .8511523820164270E+00 16 | .6362411491043160E+00 17 | -.2149112329123400E+00 18 | -.7409523346035950E+00 19 | .3477336794164400E+00 20 | -.3932186551872470E+00 21 | .8511523820164270E+00 22 | .6362411491043160E+00 23 | .2149112329123390E+00 24 | -.7409523346035950E+00 25 | -.3477336794164400E+00 26 | .3932186551872460E+00 27 | -.8511523820164280E+00 28 | -.6362411491043150E+00 29 | -.2149112329123390E+00 30 | .7409523346035960E+00 31 | .3932186551872460E+00 32 | -.8511523820164270E+00 33 | -.3477336794164410E+00 34 | -.8511523820164280E+00 35 | .3477336794164400E+00 36 | -.3932186551872460E+00 37 | -.3932186551872450E+00 38 | .8511523820164280E+00 39 | .3477336794164400E+00 40 | .8511523820164270E+00 41 | -.3477336794164400E+00 42 | .3932186551872460E+00 43 | -.7409523346035960E+00 44 | -.6362411491043150E+00 45 | .2149112329123380E+00 46 | .2149112329123390E+00 47 | .7409523346035970E+00 48 | .6362411491043140E+00 49 | .7409523346035960E+00 50 | .6362411491043150E+00 51 | -.2149112329123390E+00 52 | -.2149112329123390E+00 53 | -.7409523346035960E+00 54 | -.6362411491043150E+00 55 | -.3932186551872450E+00 56 | -.8511523820164280E+00 57 | .3477336794164400E+00 58 | .8511523820164270E+00 59 | .3477336794164400E+00 60 | .3932186551872470E+00 61 | .3932186551872470E+00 62 | .8511523820164270E+00 63 | -.3477336794164410E+00 64 | -.8511523820164280E+00 65 | -.3477336794164400E+00 66 | -.3932186551872460E+00 67 | .7409523346035960E+00 68 | -.6362411491043140E+00 69 | -.2149112329123390E+00 70 | -.2149112329123390E+00 71 | .7409523346035960E+00 72 | -.6362411491043150E+00 73 | -.7409523346035960E+00 74 | .6362411491043150E+00 75 | .2149112329123380E+00 76 | .2149112329123390E+00 77 | -.7409523346035960E+00 78 | .6362411491043150E+00 79 | -.1000000000000000E-14 80 | -.1783074222753860E+00 81 | -.9839748285202760E+00 82 | -.1000000000000000E-14 83 | .1783074222753860E+00 84 | .9839748285202760E+00 85 | -.7409523346035970E+00 86 | -.6362411491043150E+00 87 | -.2149112329123380E+00 88 | -.1783074222753860E+00 89 | .9839748285202760E+00 90 | .0000000000000000E+00 91 | .7409523346035960E+00 92 | .6362411491043150E+00 93 | .2149112329123390E+00 94 | .1783074222753850E+00 95 | -.9839748285202760E+00 96 | .0000000000000000E+00 97 | -.8511523820164280E+00 98 | .3477336794164400E+00 99 | .3932186551872450E+00 100 | .8511523820164270E+00 101 | -.3477336794164400E+00 102 | -.3932186551872460E+00 103 | .0000000000000000E+00 104 | -.1783074222753860E+00 105 | .9839748285202760E+00 106 | -.1000000000000000E-14 107 | .1783074222753860E+00 108 | -.9839748285202760E+00 109 | .7409523346035960E+00 110 | -.6362411491043150E+00 111 | .2149112329123390E+00 112 | .1783074222753860E+00 113 | .9839748285202760E+00 114 | .0000000000000000E+00 115 | -.7409523346035960E+00 116 | .6362411491043150E+00 117 | -.2149112329123380E+00 118 | -.1783074222753860E+00 119 | -.9839748285202760E+00 120 | .0000000000000000E+00 121 | .8511523820164270E+00 122 | .3477336794164400E+00 123 | -.3932186551872470E+00 124 | -.8511523820164280E+00 125 | -.3477336794164400E+00 126 | .3932186551872450E+00 127 | -.3932186551872460E+00 128 | -.8511523820164280E+00 129 | -.3477336794164400E+00 130 | .2149112329123390E+00 131 | .7409523346035960E+00 132 | -.6362411491043140E+00 133 | .3932186551872460E+00 134 | .8511523820164270E+00 135 | .3477336794164410E+00 136 | -.2149112329123380E+00 137 | -.7409523346035960E+00 138 | .6362411491043150E+00 139 | -.6362411491043150E+00 140 | .2149112329123390E+00 141 | -.7409523346035960E+00 142 | .6362411491043150E+00 143 | -.2149112329123390E+00 144 | .7409523346035960E+00 145 | -.3477336794164390E+00 146 | -.3932186551872450E+00 147 | .8511523820164280E+00 148 | -.3932186551872460E+00 149 | .8511523820164270E+00 150 | -.3477336794164400E+00 151 | .3477336794164400E+00 152 | .3932186551872470E+00 153 | -.8511523820164270E+00 154 | .3932186551872460E+00 155 | -.8511523820164270E+00 156 | .3477336794164410E+00 157 | -.2149112329123390E+00 158 | .7409523346035960E+00 159 | .6362411491043150E+00 160 | .2149112329123390E+00 161 | -.7409523346035960E+00 162 | -.6362411491043150E+00 163 | .6362411491043150E+00 164 | .2149112329123390E+00 165 | .7409523346035960E+00 166 | -.6362411491043150E+00 167 | -.2149112329123390E+00 168 | -.7409523346035960E+00 169 | .3477336794164400E+00 170 | -.3932186551872470E+00 171 | -.8511523820164270E+00 172 | -.3477336794164400E+00 173 | .3932186551872450E+00 174 | .8511523820164280E+00 175 | -.9839748285202760E+00 176 | .0000000000000000E+00 177 | .1783074222753850E+00 178 | .9839748285202760E+00 179 | .0000000000000000E+00 180 | -.1783074222753860E+00 181 | -------------------------------------------------------------------------------- /universal_transcoder/auxiliars/data/des.3.80.11.txt: -------------------------------------------------------------------------------- 1 | .7326040972910000E+00 2 | -.6631689185700000E+00 3 | .1532912981090000E+00 4 | .0000000000000000E+00 5 | .9341723589630000E+00 6 | -.3568220897730000E+00 7 | .0000000000000000E+00 8 | .9341723589630000E+00 9 | .3568220897730000E+00 10 | .5773502691900000E+00 11 | .5773502691900000E+00 12 | -.5773502691900000E+00 13 | -.5773502691900000E+00 14 | .5773502691900000E+00 15 | -.5773502691900000E+00 16 | -.5773502691900000E+00 17 | .5773502691900000E+00 18 | .5773502691900000E+00 19 | .5773502691900000E+00 20 | .5773502691900000E+00 21 | .5773502691900000E+00 22 | .9341723589630000E+00 23 | .3568220897730000E+00 24 | .0000000000000000E+00 25 | .3568220897730000E+00 26 | .0000000000000000E+00 27 | -.9341723589630000E+00 28 | -.3568220897730000E+00 29 | .0000000000000000E+00 30 | -.9341723589630000E+00 31 | -.9341723589630000E+00 32 | .3568220897730000E+00 33 | .0000000000000000E+00 34 | -.3568220897730000E+00 35 | .0000000000000000E+00 36 | .9341723589630000E+00 37 | .3568220897730000E+00 38 | .0000000000000000E+00 39 | .9341723589630000E+00 40 | .9341723589630000E+00 41 | -.3568220897730000E+00 42 | .0000000000000000E+00 43 | .5773502691900000E+00 44 | -.5773502691900000E+00 45 | -.5773502691900000E+00 46 | -.5773502691900000E+00 47 | -.5773502691900000E+00 48 | -.5773502691900000E+00 49 | -.9341723589630000E+00 50 | -.3568220897730000E+00 51 | .0000000000000000E+00 52 | -.5773502691900000E+00 53 | -.5773502691900000E+00 54 | .5773502691900000E+00 55 | .5773502691900000E+00 56 | -.5773502691900000E+00 57 | .5773502691900000E+00 58 | .0000000000000000E+00 59 | -.9341723589630000E+00 60 | -.3568220897730000E+00 61 | .0000000000000000E+00 62 | -.9341723589630000E+00 63 | .3568220897730000E+00 64 | -.4472172493640000E+00 65 | -.8395476905300000E+00 66 | -.3084743217780000E+00 67 | -.7326040972910000E+00 68 | -.6631689185700000E+00 69 | -.1532912981090000E+00 70 | -.2853868479260000E+00 71 | -.3867734581070000E+00 72 | .8769040079360000E+00 73 | .3735631740600000E-01 74 | -.2334821599980000E+00 75 | .9716432403470000E+00 76 | .6952477798850000E+00 77 | -.6862563924210000E+00 78 | -.2137350893660000E+00 79 | .4472172493640000E+00 80 | -.8395476905300000E+00 81 | .3084743217780000E+00 82 | .2853868479260000E+00 83 | -.3867734581070000E+00 84 | -.8769040079360000E+00 85 | -.3735631740600000E-01 86 | -.2334821599980000E+00 87 | -.9716432403470000E+00 88 | -.6952477798850000E+00 89 | -.6862563924210000E+00 90 | .2137350893660000E+00 91 | -.2334821599980000E+00 92 | -.9716432403470000E+00 93 | -.3735631740600000E-01 94 | -.9716432403470000E+00 95 | .3735631740600000E-01 96 | .2334821599980000E+00 97 | -.8395476905300000E+00 98 | .3084743217780000E+00 99 | .4472172493640000E+00 100 | .3084743217780000E+00 101 | -.4472172493640000E+00 102 | .8395476905300000E+00 103 | -.2137350893660000E+00 104 | -.6952477798850000E+00 105 | .6862563924210000E+00 106 | .6862563924210000E+00 107 | .2137350893660000E+00 108 | .6952477798850000E+00 109 | .8769040079360000E+00 110 | .2853868479260000E+00 111 | .3867734581070000E+00 112 | .3867734581070000E+00 113 | -.8769040079360000E+00 114 | -.2853868479260000E+00 115 | .2334821599980000E+00 116 | -.9716432403470000E+00 117 | .3735631740600000E-01 118 | .9716432403470000E+00 119 | .3735631740600000E-01 120 | -.2334821599980000E+00 121 | .8395476905300000E+00 122 | .3084743217780000E+00 123 | -.4472172493640000E+00 124 | -.3084743217780000E+00 125 | -.4472172493640000E+00 126 | -.8395476905300000E+00 127 | .2137350893660000E+00 128 | -.6952477798850000E+00 129 | -.6862563924210000E+00 130 | -.6862563924210000E+00 131 | .2137350893660000E+00 132 | -.6952477798850000E+00 133 | -.8769040079360000E+00 134 | .2853868479260000E+00 135 | -.3867734581070000E+00 136 | -.3867734581070000E+00 137 | -.8769040079360000E+00 138 | .2853868479260000E+00 139 | -.6631689185700000E+00 140 | -.1532912981090000E+00 141 | -.7326040972910000E+00 142 | -.6631689185700000E+00 143 | .1532912981090000E+00 144 | .7326040972910000E+00 145 | -.8769040079360000E+00 146 | -.2853868479260000E+00 147 | .3867734581070000E+00 148 | -.1532912981090000E+00 149 | .7326040972910000E+00 150 | .6631689185700000E+00 151 | .2137350893660000E+00 152 | .6952477798850000E+00 153 | .6862563924210000E+00 154 | .1532912981090000E+00 155 | -.7326040972910000E+00 156 | .6631689185700000E+00 157 | -.3084743217780000E+00 158 | .4472172493640000E+00 159 | .8395476905300000E+00 160 | .9716432403470000E+00 161 | -.3735631740600000E-01 162 | .2334821599980000E+00 163 | .6631689185700000E+00 164 | -.1532912981090000E+00 165 | .7326040972910000E+00 166 | .6631689185700000E+00 167 | .1532912981090000E+00 168 | -.7326040972910000E+00 169 | .8769040079360000E+00 170 | -.2853868479260000E+00 171 | -.3867734581070000E+00 172 | .1532912981090000E+00 173 | .7326040972910000E+00 174 | -.6631689185700000E+00 175 | -.2137350893660000E+00 176 | .6952477798850000E+00 177 | -.6862563924210000E+00 178 | -.1532912981090000E+00 179 | -.7326040972910000E+00 180 | -.6631689185700000E+00 181 | .3084743217780000E+00 182 | .4472172493640000E+00 183 | -.8395476905300000E+00 184 | -.9716432403470000E+00 185 | -.3735631740600000E-01 186 | -.2334821599980000E+00 187 | -.8395476905300000E+00 188 | -.3084743217780000E+00 189 | -.4472172493640000E+00 190 | -.3867734581070000E+00 191 | .8769040079360000E+00 192 | -.2853868479260000E+00 193 | -.2334821599980000E+00 194 | .9716432403470000E+00 195 | .3735631740600000E-01 196 | -.6862563924210000E+00 197 | -.2137350893660000E+00 198 | .6952477798850000E+00 199 | -.6952477798850000E+00 200 | .6862563924210000E+00 201 | -.2137350893660000E+00 202 | .2853868479260000E+00 203 | .3867734581070000E+00 204 | .8769040079360000E+00 205 | -.3735631740600000E-01 206 | .2334821599980000E+00 207 | .9716432403470000E+00 208 | .2334821599980000E+00 209 | .9716432403470000E+00 210 | -.3735631740600000E-01 211 | .4472172493640000E+00 212 | .8395476905300000E+00 213 | -.3084743217780000E+00 214 | .8395476905300000E+00 215 | -.3084743217780000E+00 216 | .4472172493640000E+00 217 | .3867734581070000E+00 218 | .8769040079360000E+00 219 | .2853868479260000E+00 220 | .6862563924210000E+00 221 | -.2137350893660000E+00 222 | -.6952477798850000E+00 223 | .6952477798850000E+00 224 | .6862563924210000E+00 225 | .2137350893660000E+00 226 | -.2853868479260000E+00 227 | .3867734581070000E+00 228 | -.8769040079360000E+00 229 | .3735631740600000E-01 230 | .2334821599980000E+00 231 | -.9716432403470000E+00 232 | -.4472172493640000E+00 233 | .8395476905300000E+00 234 | .3084743217780000E+00 235 | -.7326040972910000E+00 236 | .6631689185700000E+00 237 | .1532912981090000E+00 238 | .7326040972910000E+00 239 | .6631689185700000E+00 240 | -.1532912981090000E+00 241 | -------------------------------------------------------------------------------- /universal_transcoder/auxiliars/get_decoder_matrices.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import os 28 | from math import sqrt 29 | 30 | import jax.numpy as jnp 31 | import numpy as np 32 | from scipy import linalg 33 | 34 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 35 | from universal_transcoder.encoders.ambisonics_encoder import ambisonics_encoder 36 | from universal_transcoder.encoders.vbap_encoder import vbap_2D_encoder 37 | from universal_transcoder.encoders.vbap_encoder import vbap_3D_encoder 38 | 39 | os.environ["JAX_ENABLE_X64"] = "1" 40 | 41 | 42 | # VBAP 43 | def get_vbap_decoder_matrix(layout_input: MyCoordinates, layout_output: MyCoordinates): 44 | """Function to obtain the decoding matrix, based on VBAP, neccessary to transform 45 | from a multichannel layout to another 46 | 47 | Args: 48 | layout_input (pyfar.Coordinates): positions of input speaker layout 49 | azimut and elevation of each speaker (M speakers) 50 | layout_output (pyfar.Coordinates): positions of output speaker layout: 51 | azimut and elevation of each speaker (N speakers) 52 | 53 | Returns: 54 | decoder (jax.numpy array): decoding matrix of size NxM 55 | """ 56 | layout_input_sph = layout_input.sph_deg() 57 | layout_output_sph = layout_output.sph_deg() 58 | M = layout_input_sph.shape[0] 59 | N = layout_output_sph.shape[0] 60 | decoder = np.zeros((N, M), dtype=float) 61 | 62 | # Identify if output layout is 2D or 3D 63 | 64 | # 2D 65 | if jnp.count_nonzero(layout_output_sph, axis=0)[1] == 0: 66 | for m in range(M): 67 | input_speaker = layout_input_sph[m] 68 | virtual = MyCoordinates.point(input_speaker[0], input_speaker[1]) 69 | decoder[:, m] = vbap_2D_encoder(virtual, layout_output) 70 | 71 | # 3D 72 | else: 73 | for m in range(M): 74 | input_speaker = layout_input_sph[m] 75 | virtual = MyCoordinates.point(input_speaker[0], input_speaker[1]) 76 | decoder[:, m] = vbap_3D_encoder(virtual, layout_output) 77 | 78 | return jnp.array(decoder) 79 | 80 | 81 | # Ambisonics to speakers 82 | def get_ambisonics_decoder_matrix(order: int, layout_output: MyCoordinates, type: str): 83 | """Function to obtain the decoding matrix to decode ambisonics to a given 84 | speaker layout 85 | 86 | Args: 87 | order (int): ambisonics order from which to decode 88 | layout_output (pyfar.Coordinates): positions of output speaker layout: 89 | azimut and elevation of each speaker (N speakers) 90 | 91 | type: type of decoding matrix, pseudo-inverse or normalized 92 | 93 | Returns: 94 | decoder (jax.numpy array): decoding matrix of size NxnºambisonicsCh 95 | """ 96 | 97 | M = (order + 1) ** 2 98 | layout_output_sph = layout_output.sph_deg() 99 | N = layout_output_sph.shape[0] 100 | decoder = np.zeros((N, M), dtype=float) 101 | C = np.zeros((N, M), dtype=float) 102 | 103 | for n in range(N): 104 | spk = layout_output_sph[n] 105 | virtual = MyCoordinates.point(spk[0], spk[1]) 106 | ambisonics_enc = ambisonics_encoder(virtual, order) 107 | C[n, :] = ambisonics_enc 108 | 109 | if type == "norm": 110 | gLF = [] 111 | 112 | # 0 - order 113 | if order >= 0: 114 | gLF.append(1.0) # W 115 | 116 | # 1 - order 117 | if order >= 1: 118 | gLF.append(1.0 / sqrt(3.0)) # Y 119 | gLF.append(1.0 / sqrt(3.0)) # Z 120 | gLF.append(1.0 / sqrt(3.0)) # X 121 | 122 | # 2 - order 123 | if order >= 2: 124 | gLF.append(1.0 / sqrt(5.0)) # V 125 | gLF.append(1.0 / sqrt(5.0)) # T 126 | gLF.append(1.0 / sqrt(5.0)) # R 127 | gLF.append(1.0 / sqrt(5.0)) # S 128 | gLF.append(1.0 / sqrt(5.0)) # U 129 | 130 | # 3 - order 131 | if order >= 3: 132 | gLF.append(1.0 / sqrt(7.0)) # Q 133 | gLF.append(1.0 / sqrt(7.0)) # O 134 | gLF.append(1.0 / sqrt(7.0)) # M 135 | gLF.append(1.0 / sqrt(7.0)) # K 136 | gLF.append(1.0 / sqrt(7.0)) # L 137 | gLF.append(1.0 / sqrt(7.0)) # N 138 | gLF.append(1.0 / sqrt(7.0)) # P 139 | 140 | # 4 - order 141 | if order >= 4: 142 | gLF.append(1.0 / sqrt(9.0)) # 143 | gLF.append(1.0 / sqrt(9.0)) # 144 | gLF.append(1.0 / sqrt(9.0)) # 145 | gLF.append(1.0 / sqrt(9.0)) # 146 | gLF.append(1.0 / sqrt(9.0)) # 147 | gLF.append(1.0 / sqrt(9.0)) # 148 | gLF.append(1.0 / sqrt(9.0)) # 149 | gLF.append(1.0 / sqrt(9.0)) # 150 | gLF.append(1.0 / sqrt(9.0)) # 151 | 152 | # 5 - order 153 | if order >= 5: 154 | gLF.append(1.0 / sqrt(11.0)) # 155 | gLF.append(1.0 / sqrt(11.0)) # 156 | gLF.append(1.0 / sqrt(11.0)) # 157 | gLF.append(1.0 / sqrt(11.0)) # 158 | gLF.append(1.0 / sqrt(11.0)) # 159 | gLF.append(1.0 / sqrt(11.0)) # 160 | gLF.append(1.0 / sqrt(11.0)) # 161 | gLF.append(1.0 / sqrt(11.0)) # 162 | gLF.append(1.0 / sqrt(11.0)) # 163 | gLF.append(1.0 / sqrt(11.0)) # 164 | gLF.append(1.0 / sqrt(11.0)) # 165 | 166 | gLF = np.array(gLF) 167 | factor = np.tile(gLF, (N, 1)) 168 | decoder = (1.0 / N) * factor * C 169 | ret = jnp.array(decoder) 170 | 171 | elif type == "pseudo": 172 | ret = jnp.array(linalg.pinv(C).T) 173 | 174 | return ret 175 | -------------------------------------------------------------------------------- /universal_transcoder/auxiliars/get_input_channels.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import jax.numpy as jnp 28 | import numpy as np 29 | 30 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 31 | from universal_transcoder.auxiliars.typing import NpArray 32 | from universal_transcoder.encoders.ambisonics_encoder import ambisonics_encoder 33 | from universal_transcoder.encoders.vbap_encoder import vbap_2D_encoder, vbap_3D_encoder 34 | 35 | 36 | def get_input_channels_vbap( 37 | cloud_points: MyCoordinates, 38 | input_layout: MyCoordinates, 39 | normalize: bool = True, 40 | vbip: bool = False, 41 | ) -> np.ndarray: 42 | """Function to obtain the channel gains that encode in a multichannel layout for a cloud of points, where 43 | each row corresponds to the coding gains for one point, using VBAP 44 | 45 | Args: 46 | cloud_points (MyCoordinates): positions of the virtual sources pyfar.Coordinates 47 | (L points) 48 | input_layout (MyCoordinates): speaker positions given as pyfar.Coordinates 49 | (M speakers) 50 | normalize (bool): If activated, gains are normalized so that sum of all squares equals 1 51 | vbip (bool): Use vbip instead of vbap 52 | 53 | Returns: 54 | input_channels (numpy Array): LxM matrix of channel gains for input layout 55 | """ 56 | input_layout_sph = input_layout.sph_deg() 57 | cloud_points_sph = cloud_points.sph_deg() 58 | input_channels = np.zeros([cloud_points_sph.shape[0], input_layout_sph.shape[0]]) 59 | 60 | if jnp.count_nonzero(input_layout_sph, axis=0)[1] == 0: 61 | encoder = vbap_2D_encoder 62 | else: 63 | encoder = vbap_3D_encoder 64 | 65 | for i in range(cloud_points_sph.shape[0]): 66 | virtual = MyCoordinates.point( 67 | cloud_points_sph[i, 0], cloud_points_sph[i, 1], cloud_points_sph[i, 2] 68 | ) 69 | input_channels[i, :] = encoder(virtual, input_layout) 70 | if vbip: 71 | input_channels[i, :] = np.sqrt(input_channels[i, :]) 72 | 73 | if normalize: 74 | sum2 = np.sqrt(np.sum(input_channels**2, axis=1)) 75 | input_channels = input_channels / sum2[:, np.newaxis] 76 | 77 | return input_channels 78 | 79 | 80 | def get_input_channels_ambisonics(cloud_points: MyCoordinates, order: int) -> NpArray: 81 | """Function to obtain the channel gains for a cloud of points that encode in 82 | a given ambisonics order, where each row corresponds to the coding gains 83 | for one point in the given Ambi-order 84 | 85 | Args: 86 | cloud_points (MyCoordinates): positions of the virtual sources pyfar.Coordinates 87 | (L points) 88 | order (int): ambisonics order ((order+1)**2 = M channels) 89 | 90 | Returns: 91 | input_channels (numpy Array): LxM matrix of channel gains for input layout 92 | """ 93 | cloud_points_sph = cloud_points.sph_deg() 94 | input_channels = np.zeros([cloud_points_sph.shape[0], (order + 1) ** 2]) 95 | 96 | for i in range(cloud_points_sph.shape[0]): 97 | virtual = MyCoordinates.point( 98 | cloud_points_sph[i, 0], cloud_points_sph[i, 1], cloud_points_sph[i, 2] 99 | ) 100 | input_channels[i, :] = ambisonics_encoder(virtual, order) 101 | 102 | return input_channels 103 | 104 | 105 | def get_input_channels_micro_cardioid( 106 | cloud: MyCoordinates, 107 | mic_orientation: NpArray, 108 | mic_position: MyCoordinates, 109 | f: float, 110 | ) -> NpArray: 111 | """Function to obtain the gains for a cloud of points that encode in cardioid-microphone, where 112 | each row corresponds to the coding channels for one point 113 | 114 | Args: 115 | cloud (MyCoordinates): positions of the virtual sources pyfar.Coordinates 116 | (L points) 117 | mic_orientation (numpy Array): array specifying orientation of the microphones 118 | both in azimut and elevation 119 | mic_position (MyCoordinates) position of microphones 120 | pyfar.Coordinates (M microphones) 121 | f (float): frequency of input sound waves in Hz 122 | 123 | Returns: 124 | input_channels (numpy Array): LxM matrix of channel gains 125 | for input layout 126 | """ 127 | cloud_points_sph = cloud.sph_rad() 128 | mic_orientation_sph = mic_orientation * np.pi / 180 129 | mic_position_sph = mic_position.sph_rad() 130 | input_channels = np.zeros( 131 | [cloud_points_sph.shape[0], mic_orientation_sph.shape[0]], dtype=np.complex64 132 | ) 133 | 134 | for i in range(cloud_points_sph.shape[0]): 135 | for j in range(mic_orientation_sph.shape[0]): 136 | gain = (1 + np.cos(mic_orientation_sph[j, 0] - cloud_points_sph[i, 0])) / 2 137 | deltaR = mic_position_sph[j, 2] - mic_position_sph[j, 2] * np.cos( 138 | mic_position_sph[j, 0] - cloud_points_sph[i, 0] 139 | ) 140 | deltaT = deltaR / 340 141 | exponent = 2 * np.pi * f * deltaT 142 | input_channels[i, j] = gain * np.exp(-1j * exponent) 143 | 144 | return input_channels 145 | 146 | 147 | def get_input_channels_micro_omni( 148 | cloud: MyCoordinates, 149 | mic_orientation: NpArray, 150 | mic_position: MyCoordinates, 151 | f: float, 152 | ): 153 | """Function to obtain the gains for a cloud of points that encode in omni-microphone , where 154 | each row corresponds to the coded channels for one point 155 | 156 | Args: 157 | cloud (MyCoordinates): positions of the virtual sources pyfar.Coordinates 158 | (L points) 159 | mic_orientation (np Array): array specifying orientation of the microphones 160 | both in azimut and elevation 161 | mic_position (MyCoordinates) position of microphones 162 | pyfar.Coordinates (M microphones) 163 | f (float): frequency of input sound waves in Hz 164 | 165 | Returns: 166 | input_channels (numpy Array): LxM matrix of channel gains 167 | for input layout 168 | """ 169 | cloud_points_sph = cloud.sph_rad() 170 | mic_orientation_sph = mic_orientation * np.pi / 180 171 | mic_position_sph = mic_position.sph_rad() 172 | input_channels = np.zeros( 173 | [cloud_points_sph.shape[0], mic_orientation_sph.shape[0]], dtype=np.complex64 174 | ) 175 | 176 | for i in range(cloud_points_sph.shape[0]): 177 | for j in range(mic_orientation_sph.shape[0]): 178 | gain = 1 179 | deltaR = mic_position_sph[j, 2] - mic_position_sph[j, 2] * np.cos( 180 | mic_position_sph[j, 0] - cloud_points_sph[i, 0] 181 | ) 182 | deltaT = deltaR / 340 183 | exponent = 2 * np.pi * f * deltaT 184 | input_channels[i, j] = gain * np.exp(-1j * exponent) 185 | 186 | return input_channels 187 | -------------------------------------------------------------------------------- /universal_transcoder/auxiliars/get_left_right_pairs.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import numpy as np 28 | 29 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 30 | 31 | 32 | def angular_distance(theta1, e1, theta2, e2): 33 | """Function to calculate the angular distance between two points. 34 | Haversine formula (see Wikipedia) 35 | 36 | Args: 37 | theta1 (float): Radians. Latitude of point 1 38 | e1 (float): Radians. Longitude of point 1 39 | theta2 (float): Radians. Latitude of point 2 40 | e2 (float): Radians. Longitude of point 2 41 | 42 | Returns: 43 | dist (float): Angular distance 44 | """ 45 | # Implement haversine formula (see Wikipedia) 46 | dist = 2.0 * np.arcsin( 47 | np.sqrt( 48 | (np.sin((e1 - e2) / 2.0)) ** 2 49 | + np.cos(e1) * np.cos(e2) * (np.sin((theta1 - theta2) / 2.0)) ** 2 50 | ) 51 | ) 52 | return dist 53 | 54 | 55 | def get_left_right_pairs(points: MyCoordinates, tol: float = 2.0): 56 | """Function to find the symmetric pairs in a layout, a set of positions, 57 | with a tolerance (default 2 degrees) 58 | 59 | Args: 60 | layout (MyCoordinates): positions given as pyfar.Coordinates 61 | tol (float): Degrees of tolerance allowed to find pairs 62 | 63 | Returns: 64 | paired (Array): array which positions corresponds to those of the 65 | input layout, and in which points belonging to the same pair are "tagged" 66 | with the same number 67 | """ 68 | points_coord = points.sph_rad() 69 | thetas = points_coord[:, 0] 70 | phis = points_coord[:, 1] 71 | tol = tol * np.pi / 180 72 | pair_id = 1 73 | pairs = np.zeros(len(thetas), dtype=int) 74 | for i, theta in enumerate(thetas): 75 | if abs(pairs[i]) >= 1: 76 | continue 77 | else: 78 | non_zero_pos = np.nonzero(thetas[i + 1 : len(thetas)])[0] + (1 + i) 79 | for j in non_zero_pos: 80 | if angular_distance(theta, phis[i], -thetas[j], phis[j]) <= tol: 81 | # pair found 82 | pairs[i] = pair_id 83 | pairs[j] = -pair_id 84 | pair_id = pair_id + 1 85 | break 86 | return pairs 87 | -------------------------------------------------------------------------------- /universal_transcoder/auxiliars/my_coordinates.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import numpy as np 28 | import pyfar as pf 29 | 30 | from universal_transcoder.auxiliars.typing import NpArray 31 | 32 | 33 | class MyCoordinates(pf.Coordinates): 34 | """Class generated out of pyfar.Coordinates to extents its capabilities. 35 | Pyfar.Coordinates allows inputs belonging to [0º,360º] for azimut angle 36 | and [-90º,90º] for elevation. The main goal of the following methods is 37 | to allow azimut inputs of [-180º, 180º]. Additionally, there are methods to 38 | retreive the angles information in the above mentioned convention""" 39 | 40 | # Create Single Points # 41 | @classmethod 42 | def point(cls, theta, phi, d=1): 43 | if (theta > 180) or (theta < (-180)) or (phi > 90) or (phi < (-90)): 44 | raise ValueError( 45 | "Azimut position must be [-180,180] and elevation position must be [-90,90]" 46 | ) 47 | if theta < 0: # theta [-180,0] --> [0,360] 48 | theta = theta + 360 49 | point = cls(theta, phi, d, domain="sph", convention="top_elev", unit="deg") 50 | return point 51 | 52 | # Create Multi-points # 53 | @classmethod 54 | def mult_points(cls, positions: NpArray): 55 | thetas = positions[:, 0] 56 | phis = positions[:, 1] 57 | ds = positions[:, 2] 58 | # check correct format 59 | if ( 60 | (np.any(thetas > 180)) 61 | or (np.any(thetas < (-180))) 62 | or (np.any(phis > 90)) 63 | or (np.any(phis < (-90))) 64 | ): 65 | raise ValueError( 66 | "Azimut position must be [-180,180] and elevation position must be [-90,90]" 67 | ) 68 | # check correct order (ascending thetas) 69 | # sorted = np.all(np.diff(thetas) >= 0) 70 | # if sorted == False: 71 | # raise ValueError( 72 | # "Positions must be introduced in ascending order of azimut angle" 73 | # ) 74 | 75 | # put thetas [0,360] for pf.Coordinates 76 | for i in range(thetas.shape[0]): 77 | if thetas[i] < 0: 78 | thetas[i] = thetas[i] + 360 79 | 80 | # generate Coordinates space 81 | mult_points = cls( 82 | thetas, phis, ds, domain="sph", convention="top_elev", unit="deg" 83 | ) 84 | return mult_points 85 | 86 | # Create Multi-points - CARTESIAN COORDINATES # 87 | @classmethod 88 | def mult_points_cart(cls, positions: NpArray): 89 | x = positions[:, 0] 90 | y = positions[:, 1] 91 | z = positions[:, 2] 92 | 93 | # generate Coordinates space 94 | mult_points = cls(x, y, z, domain="cart", convention="right") 95 | return mult_points 96 | 97 | # Get (Multi)Point coordinates: Polar in Degrees or Radians; and Cartesian 98 | def sph_deg(self): 99 | sph_coord = self.get_sph(convention="top_elev", unit="deg") 100 | for i in range(sph_coord.shape[0]): 101 | if sph_coord[i][0] > 180: 102 | sph_coord[i][0] = sph_coord[i][0] - 360 103 | return sph_coord 104 | 105 | def sph_rad(self): 106 | sph_coord = self.get_sph(convention="top_elev", unit="rad") 107 | for i in range(sph_coord.shape[0]): 108 | if sph_coord[i][0] > np.pi: 109 | sph_coord[i][0] = sph_coord[i][0] - 2 * np.pi 110 | return sph_coord 111 | 112 | def cart(self): 113 | cart_coord = self.get_cart(convention="right") 114 | return cart_coord 115 | 116 | def discard_lower_hemisphere(self): 117 | """ 118 | Remove the lower hemisphere points from the cloud 119 | Returns: 120 | New cloudd of points with lower hemisphere removed 121 | """ 122 | return self[self.cart()[:, 2] >= 0] 123 | -------------------------------------------------------------------------------- /universal_transcoder/auxiliars/typing.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright 2024 Dolby Laboratories 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted 5 | provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 11 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 14 | promote products derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 20 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | POSSIBILITY OF SUCH DAMAGE. 24 | """ 25 | 26 | from typing import Union 27 | 28 | import jax 29 | import numpy 30 | 31 | NpArray = numpy.ndarray # Numpy Array 32 | JaxArray = jax.Array # Jax Array 33 | Array = Union[NpArray, JaxArray] # Either Numpy or Jax Array 34 | ArrayLike = ( 35 | jax.typing.ArrayLike 36 | ) # Anything that can be converted to a Jax or Numpy Array (e.g. Array, float, int, etc) 37 | -------------------------------------------------------------------------------- /universal_transcoder/calculations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/universal_transcoder/calculations/__init__.py -------------------------------------------------------------------------------- /universal_transcoder/calculations/energy_intensity.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import jax.numpy as jnp 28 | 29 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 30 | from universal_transcoder.auxiliars.typing import ArrayLike 31 | from universal_transcoder.auxiliars.typing import JaxArray 32 | 33 | 34 | def energy_calculation(speaker_signals: ArrayLike) -> JaxArray: 35 | """Function to obtain the energy of each virtual source of a cloud of points in an output 36 | layout out from the coded channel gains 37 | 38 | Args: 39 | speaker_signals (Array): speaker signals (P speakers) resulting from decoding 40 | the input set of encoded L directions (LxP size) 41 | 42 | Returns: 43 | energy (jax Array): contains the energy values for each virtual source (1xL) 44 | """ 45 | 46 | # Calculate energy 47 | energy = jnp.array(jnp.sum(speaker_signals**2, axis=1), dtype=jnp.float32) 48 | 49 | return energy 50 | 51 | 52 | def intensity_calculation( 53 | speaker_signals: ArrayLike, 54 | output_layout: MyCoordinates, 55 | ) -> JaxArray: 56 | """Function to obtain the intensity of each virtual source of a cloud of points in an output 57 | layout out from the coded channel gains 58 | 59 | Args: 60 | speaker_signals (Array): speaker signals (P speakers) resulting from decoding 61 | the input set of encoded L directions (LxP size) 62 | output_layout (MyCoordinates): positions of output speaker layout: (P speakers) 63 | 64 | Returns: 65 | intensity (jax array): intensity vector for each virtual source, 66 | cartesian coordinates (Lx3) 67 | """ 68 | 69 | # Energy calculation 70 | energy = energy_calculation(speaker_signals) 71 | 72 | # Cardinal coordinates - unitary vectors of output speakers - Ui 73 | U = output_layout.cart() 74 | 75 | # Intensity 76 | aux = jnp.dot(speaker_signals**2, U) 77 | intensity = jnp.array((1 / (energy + jnp.finfo(float).eps)).reshape(-1, 1) * aux) 78 | 79 | return intensity 80 | 81 | 82 | def radial_I_calculation( 83 | cloud_points: MyCoordinates, 84 | speaker_signals: ArrayLike, 85 | output_layout: MyCoordinates, 86 | ) -> JaxArray: 87 | """Function to obtain the radial intensity of each virtual source of a cloud of points in an output 88 | layout out from the coded channel gains 89 | 90 | Args: 91 | cloud_points (MyCoordinates): position of the virtual sources pyfar.Coordinates (L sources) 92 | speaker_signals (Array): speaker signals (P speakers) resulting from decoding 93 | the input set of encoded L directions (LxP size) 94 | output_layout (MyCoordinates): positions of output speaker layout: (P speakers) 95 | 96 | Returns: 97 | radial_intensity (jax.numpy array): contains the radial intensity values for each virtual 98 | source (1xL) 99 | """ 100 | # Intensity calculation 101 | intensity = intensity_calculation(speaker_signals, output_layout) 102 | 103 | # Cardinal coordinates direction virtual source - Vj 104 | V = cloud_points.cart() 105 | 106 | # Scalar product of intensity and V 107 | radial_intensity = jnp.sum(jnp.multiply(intensity, V), axis=1) 108 | 109 | return radial_intensity 110 | 111 | 112 | def transverse_I_calculation( 113 | cloud_points: MyCoordinates, 114 | speaker_signals: ArrayLike, 115 | output_layout: MyCoordinates, 116 | ) -> JaxArray: 117 | """Function to obtain the transverse intensity of each virtual source of a cloud of points in an output 118 | layout out from the coded channel gains 119 | 120 | Args: 121 | cloud_points (MyCoordinates): position of the virtual sources pyfar.Coordinates (L sources) 122 | speaker_signals (Array): speaker signals (P speakers) resulting from decoding 123 | the input set of encoded L directions (LxP size) 124 | output_layout (MyCoordinates): positions of output speaker layout: (P speakers) 125 | 126 | Returns: 127 | transversal_intensity (jax.numpy array): contains the transversal intensity values for each virtual 128 | source (1xL) 129 | """ 130 | # Intensity calculation 131 | intensity = intensity_calculation(speaker_signals, output_layout) 132 | 133 | # Cardinal coordinates direction virtual source - Vj 134 | V = cloud_points.cart() 135 | 136 | # Vectorial product of intensity and V 137 | transverse_intensity = jnp.array( 138 | jnp.linalg.norm(jnp.cross(intensity, V, axis=1), axis=1) 139 | ) 140 | 141 | return transverse_intensity 142 | 143 | 144 | def angular_error(radial: ArrayLike, transverse: ArrayLike) -> JaxArray: 145 | """Function to obtain the angular error of each virtual source of a cloud of points given the 146 | radial and transverse components of the intensity 147 | 148 | Args: 149 | radial (array): contains the radial intensity values for each virtual source (1xL) 150 | transverse (array): contains the transversal intensity values for each virtual source (1xL) 151 | 152 | Returns: 153 | error (jax array): contains the angular error values for each virtual source (1xL) 154 | """ 155 | tan = jnp.abs(transverse) / jnp.abs(radial) 156 | error_rad = jnp.arctan(tan) # -pi/2 to pi/2 157 | error = jnp.degrees(error_rad) # to degrees 158 | return error 159 | 160 | 161 | def width_angle(intensity: ArrayLike) -> JaxArray: 162 | """Function to obtain the width of each virtual source of a cloud of points given the 163 | radial component of the intensity 164 | 165 | Args: 166 | intensity (array): contains the radial intensity values for each virtual source (1xL) 167 | 168 | Returns: 169 | width (array): contains the width values for each virtual source (1xL) in degrees 170 | """ 171 | width = jnp.degrees(jnp.arccos(jnp.abs(intensity))) 172 | return width 173 | -------------------------------------------------------------------------------- /universal_transcoder/calculations/optimization.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import os 28 | import time 29 | from typing import Dict, Any 30 | from pathlib import Path 31 | 32 | import jax 33 | import jax.numpy as jnp 34 | import numpy as np 35 | from jax import grad 36 | from scipy.optimize import minimize 37 | 38 | from universal_transcoder.auxiliars.typing import ArrayLike 39 | from universal_transcoder.auxiliars.typing import NpArray 40 | from universal_transcoder.calculations.cost_function import State 41 | from universal_transcoder.calculations.set_up_system import ( 42 | set_up_general, 43 | ) 44 | from universal_transcoder.plots_and_logs.all_plots import ( 45 | plots_general, 46 | ) 47 | from universal_transcoder.plots_and_logs.write_logs import ( 48 | write_optimization_log, 49 | save_results, 50 | ) 51 | 52 | os.environ["JAX_ENABLE_X64"] = "1" 53 | 54 | 55 | def optimize(info: Dict[str, Any]) -> NpArray: 56 | """ 57 | Complete optimization process. Function to prepare the optimization, to call the 58 | optimization obtaining the final optimised transcoding matrix (NxM) for each given situation. 59 | Depending on the activated flags it also generates, saves or shows interesting information 60 | regarding the optimization process and the results. 61 | 62 | Args: 63 | info (dict): All the info needed for the optimization given as the following: 64 | dictionary = { 65 | "input_matrix_optimization": input, # Input matrix that encodes in input format LxM 66 | "cloud_optimization": cloud, # Cloud of points sampling the sphere (L) 67 | "output_layout": output_layout, # Output layout of speakers to decode (P speakers) 68 | "coefficients": { # List of coefficients to the cost function 69 | "energy": 0, 70 | "radial_intensity": 0, 71 | "transverse_intensity": 0, 72 | "pressure": 0, 73 | "radial_velocity": 0, 74 | "transverse_velocity": 0, 75 | "in_phase_lin": 0, 76 | "symmetry_lin": 0, 77 | "sparsity_lin": 0, 78 | "total_gains_quad": 0, 79 | "in_phase_quad": 0, 80 | "symmetry_quad": 0, 81 | "total_gains_quad": 0, 82 | "sparsity_quad": 0, 83 | }, 84 | "directional_weights": 1, # Weights given to different directions sampling the sphere (L) 85 | "show_results": True, # Flag to show results 86 | "save_results": False, # Flag to save results 87 | "cloud_plots": cloud, # Cloud of points sampling the sphere for the plots 88 | "input_matrix_plots": matrix, # Matrix that encodes in input format, for the plots 89 | "results_file_name": "name", # String of folder name where to save, if save_results=True 90 | } 91 | 92 | 93 | Returns: 94 | T_optimized (numpy Array complex64): optimized transcoding matrix (NxM) that transcodes 95 | from the input format to the output format 96 | """ 97 | # Save optimisation data in json 98 | if info["save_results"]: 99 | save_results(info) 100 | 101 | ## Set up optimisation 102 | current_state, T_flatten_initial = set_up_general(info) 103 | 104 | # Call optimization function 105 | T_flatten_optimized = bfgs_optim( 106 | current_state, 107 | T_flatten_initial, 108 | info["show_results"], 109 | info["save_results"], 110 | info["results_file_name"], 111 | ) 112 | 113 | # Adapt / reshape result of optimization --> transcoding matrix 114 | T_optimized = np.array(T_flatten_optimized).reshape( 115 | current_state.transcoding_matrix_shape 116 | ) 117 | 118 | # If show or save flags active 119 | if info["show_results"] or info["save_results"]: 120 | D = T_optimized 121 | # unless 122 | if "Dspk" in info.keys(): 123 | # D= Dspk x T 124 | D = jnp.dot(info["Dspk"], T_optimized) 125 | 126 | # Save T 127 | if info["save_results"]: 128 | folder = Path("saved_results") / info["results_file_name"] 129 | name = folder / (info["results_file_name"] + ".npy") 130 | folder.mkdir(parents=True, exist_ok=True) 131 | np.save(name, T_optimized) 132 | 133 | if "cloud_plots" in info: 134 | # Resulting speaker signals 135 | speaker_signals = jnp.dot(info["input_matrix_plots"], D.T) 136 | 137 | plots_general( 138 | info["output_layout"], 139 | speaker_signals, 140 | info["cloud_plots"], 141 | info["show_results"], 142 | info["save_results"], 143 | info["results_file_name"], 144 | ) 145 | else: 146 | # Resulting speaker signals 147 | speaker_signals = jnp.dot(info["input_matrix_optimization"], D.T) 148 | 149 | plots_general( 150 | info["output_layout"], 151 | speaker_signals, 152 | info["cloud_optimization"], 153 | info["show_results"], 154 | info["save_results"], 155 | info["results_file_name"], 156 | ) 157 | 158 | return T_optimized 159 | 160 | 161 | def bfgs_optim( 162 | current_state: State, 163 | flatten_initial_dec: ArrayLike, 164 | show_results: bool, 165 | save_results: bool, 166 | results_file_name, 167 | ) -> NpArray: 168 | """ 169 | Optimization function to generate an optimized flatten transcoding matrix using 170 | BFGS method. It can also print through terminal or save an optimisation log 171 | 172 | Args: 173 | current_state (class State): saving cloud, input_matrix(LxM), output_layout(P) 174 | and transcoding_matrix shape 175 | flatten_initial_dec (Array): not-optimized flatten transcoding matrix from 176 | input format to output_layout ((NxM)x1 size) 177 | show_results (bool): flag to show plots and results 178 | save_results (bool): flag to save plots and results 179 | results_file_name (String or None): in case save_results=True, then it is the 180 | String that gives name to the folder where results are saved 181 | 182 | Returns: 183 | dec_matrix_bfgs (Array): optimized flatten transcoding matrix ((NxM)x1 size) 184 | """ 185 | 186 | # Initial time 187 | start_time = time.time() 188 | 189 | # Optimization 190 | cost_values = [] 191 | cost_values.append( 192 | current_state.cost_function(flatten_initial_dec) 193 | ) # starting point 194 | 195 | # Function to save cost value in each iteration 196 | def callback_func(xk): 197 | cost_values.append(current_state.cost_function(xk)) 198 | 199 | # Include jit, reduces execution time 200 | cost_function_jit = jax.jit(current_state.cost_function) 201 | 202 | # Actual optimisation 203 | optimization_result = minimize( 204 | cost_function_jit, # current_state.cost_function, if jit unwanted 205 | flatten_initial_dec, 206 | jac=grad(cost_function_jit), # current_state.cost_function , if jit unwanted 207 | method="BFGS", 208 | callback=callback_func, 209 | ) 210 | 211 | # Final flatten optimised matrix 212 | dec_matrix_bfgs = optimization_result.x 213 | 214 | # End time 215 | execution_time = time.time() - start_time 216 | 217 | print("Optimization time ", execution_time) 218 | 219 | # Optimization Log 220 | if show_results or save_results: 221 | write_optimization_log( 222 | current_state, 223 | optimization_result, 224 | execution_time, 225 | cost_values, 226 | show_results, 227 | save_results, 228 | results_file_name, 229 | ) 230 | 231 | return dec_matrix_bfgs 232 | -------------------------------------------------------------------------------- /universal_transcoder/calculations/pressure_velocity.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import jax.numpy as jnp 28 | 29 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 30 | from universal_transcoder.auxiliars.typing import ArrayLike 31 | from universal_transcoder.auxiliars.typing import JaxArray 32 | 33 | 34 | def pressure_calculation(speaker_signals: ArrayLike) -> JaxArray: 35 | """Function to obtain the real and imaginary pressure of a virtual source in an output 36 | layout out of the coded channel gains 37 | 38 | Args: 39 | speaker_signals (Array): speaker signals (P speakers) resulting from decoding 40 | the input set of encoded L directions (LxP size) 41 | 42 | Returns: 43 | pressure (jax Array): contains the real pressure values for each virtual source (1xL) 44 | """ 45 | 46 | # Calculate pressure 47 | pressure = jnp.array(jnp.sum(speaker_signals, axis=1), dtype=jnp.float32) 48 | 49 | return pressure 50 | 51 | 52 | def velocity_calculation( 53 | speaker_signals: ArrayLike, 54 | output_layout: MyCoordinates, 55 | ) -> JaxArray: 56 | """Function to obtain the real and imaginary velocity of a virtual source in an 57 | output layout out of the coded channel gains 58 | 59 | Args: 60 | speaker_signals (Array): speaker signals (P speakers) resulting from decoding 61 | the input set of encoded L directions (LxP size) 62 | output_layout (MyCoordinates): positions of output speaker layout: (P speakers) 63 | 64 | Returns: 65 | velocity (jax.numpy array): real velocity vector for each virtual source, 66 | cartesian coordinates (Lx3) 67 | """ 68 | 69 | # Pressure calculation 70 | pressure = pressure_calculation(speaker_signals) 71 | 72 | # Cardinal coordinates - unitary vectors of output speakers - Ui 73 | U = output_layout.cart() 74 | 75 | # Velocity 76 | aux = jnp.dot(speaker_signals, U) 77 | velocity = jnp.array((1 / (pressure + jnp.finfo(float).eps)).reshape(-1, 1) * aux) 78 | 79 | return velocity 80 | 81 | 82 | def radial_V_calculation( 83 | cloud_points: MyCoordinates, 84 | speaker_signals: ArrayLike, 85 | output_layout: MyCoordinates, 86 | ) -> JaxArray: 87 | """Function to obtain the real and imag radial velocity of each virtual source of a cloud of 88 | points in an output layout out from the coded channel gains 89 | 90 | Args: 91 | cloud_points (MyCoordinates): position of the virtual sources pyfar.Coordinates (L sources) 92 | speaker_signals (Array): speaker signals (P speakers) resulting from decoding 93 | the input set of encoded L directions (LxP size) 94 | output_layout (MyCoordinates): positions of output speaker layout: (P speakers) 95 | 96 | Returns: 97 | radial_velocity (jax array): contains the real adial velocity values for each virtual 98 | source (1xL) 99 | """ 100 | # Velocity calculation 101 | velocity = velocity_calculation(speaker_signals, output_layout) 102 | 103 | # Cardinal coordinates direction virtual source - Vj 104 | V = cloud_points.cart() 105 | 106 | # Scalar product of velocity and V 107 | radial_velocity = jnp.sum(jnp.multiply(velocity, V), axis=1) 108 | 109 | return radial_velocity 110 | 111 | 112 | def transversal_V_calculation( 113 | cloud_points: MyCoordinates, 114 | speaker_signals: ArrayLike, 115 | output_layout: MyCoordinates, 116 | ) -> JaxArray: 117 | """Function to obtain the real and imaginary transverse velocity of each virtual source of a cloud of 118 | points in an output layout out from the coded channel gains 119 | 120 | Args: 121 | cloud_points (MyCoordinates): position of the virtual sources pyfar.Coordinates (L sources) 122 | speaker_signals (Array): speaker signals (P speakers) resulting from decoding 123 | the input set of encoded L directions (LxP size) 124 | output_layout (MyCoordinates): positions of output speaker layout: (P speakers) 125 | 126 | Returns: 127 | transversal_velocity (jax array): contains the real transversal velocity values for each virtual 128 | source (1xL) 129 | """ 130 | # Velocity calculation 131 | velocity = velocity_calculation(speaker_signals, output_layout) 132 | 133 | # Cardinal coordinates direction virtual source - Vj 134 | V = cloud_points.cart() 135 | 136 | # Vectorial product of velocity and V 137 | transverse_velocity = jnp.array( 138 | jnp.linalg.norm(jnp.cross(velocity, V, axis=1), axis=1) 139 | ) 140 | 141 | return transverse_velocity 142 | -------------------------------------------------------------------------------- /universal_transcoder/calculations/set_up_system.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | from typing import Dict, Any, Tuple 28 | 29 | import jax.numpy as jnp 30 | import numpy as np 31 | 32 | from universal_transcoder.auxiliars.typing import JaxArray 33 | from universal_transcoder.calculations.cost_function import State 34 | 35 | 36 | def set_up_general(info: Dict[str, Any]) -> Tuple[State, JaxArray]: 37 | """Function to prepare the system for optimization. It generates the initial transcoding matrix 38 | of the appropiate size and it stores in class State all the needed data for the optimization 39 | 40 | Args: 41 | info (dict): All the info needed for the optimization given as the following: 42 | dictionary = { 43 | "input_matrix_optimization": input, # Input matrix that encodes in input format LxM 44 | "cloud_optimization": cloud, # Cloud of points sampling the sphere (L) 45 | "output_layout": output_layout, # Output layout of speakers to decode (P speakers) 46 | "coefficients": { # List of coefficients to the cost function 47 | "energy": 0, 48 | "radial_intensity": 0, 49 | "transverse_intensity": 0, 50 | "pressure": 0, 51 | "radial_velocity": 0, 52 | "transverse_velocity": 0, 53 | "in_phase_lin": 0, 54 | "symmetry_lin": 0, 55 | "total_gains_quad": 0, 56 | "in_phase_quad": 0, 57 | "symmetry_quad": 0, 58 | "total_gains_quad": 0, 59 | }, 60 | "directional_weights": 1, # Weights given to different directions sampling the sphere (L) 61 | "show_results": True, # Flag to show results 62 | "save_results": False, # Flag to save results 63 | "cloud_plots": cloud, # Cloud of points sampling the sphere for plots 64 | "input_matrix_plots": matrix, # Matrix that encodes in input format, for plots 65 | "results_file_name": "name", # String of folder name where to save, if save_results=True 66 | } 67 | 68 | Returns: 69 | current_state (State): contains side-information that the optimization process needs (1xL) 70 | T_flatten_initial: (jax Array): vector of shape 1xNM to optimize 71 | """ 72 | cloud = info["cloud_optimization"] 73 | layout = info["output_layout"] 74 | input_matrix = info["input_matrix_optimization"] 75 | 76 | M = input_matrix.shape[1] 77 | P = layout.sph_deg().shape[0] 78 | 79 | # unless: 80 | if "Dspk" in info.keys(): 81 | # If "transcoding" is activated 82 | Dspk = info["Dspk"] 83 | P_aux = Dspk.shape[0] # number of output speakers, to check coherence 84 | N = Dspk.shape[1] # number of channels in desired transcoding format 85 | 86 | # check if P_aux matches P, otherwise, raise error, introduced wrong data 87 | if P_aux != P: 88 | raise ValueError( 89 | "Introduced Dspk signal shape does not match defined output_layout. " 90 | "Dspk shape is PxN being P the number of speakers in output_layout " 91 | "and N the number of channels of desired transcoding format." 92 | ) 93 | else: 94 | # assume 95 | Dspk = 1 96 | N = P 97 | 98 | # Generate Decoding initial matrix 99 | np.random.seed(0) 100 | save_shape = (N, M) 101 | if "T_initial" in info.keys(): 102 | T_flatten_initial = info["T_initial"].flatten() 103 | else: 104 | T_flatten_initial = jnp.ones(N * M) + 0.2 * jnp.array(np.random.randn(N * M)) 105 | 106 | # Create 'current state' class 107 | current_state = State(cloud, input_matrix, layout, save_shape, T_flatten_initial) 108 | 109 | # Set coefficients 110 | # Quadratic terms 111 | current_state.ce = info["coefficients"]["energy"] 112 | current_state.cir = info["coefficients"]["radial_intensity"] 113 | current_state.cit = info["coefficients"]["transverse_intensity"] 114 | current_state.cphquad = info["coefficients"]["in_phase_quad"] 115 | current_state.csymquad = info["coefficients"]["symmetry_quad"] 116 | current_state.cmingquad = info["coefficients"]["total_gains_quad"] 117 | try: 118 | current_state.csparsequad = info["coefficients"]["sparsity_quad"] 119 | except KeyError: 120 | current_state.csparsequad = 0 121 | 122 | # Linear terms 123 | current_state.cp = info["coefficients"]["pressure"] 124 | current_state.cvr = info["coefficients"]["radial_velocity"] 125 | current_state.cvt = info["coefficients"]["transverse_velocity"] 126 | current_state.cphlin = info["coefficients"]["in_phase_lin"] 127 | current_state.csymlin = info["coefficients"]["symmetry_lin"] 128 | current_state.cminglin = info["coefficients"]["total_gains_lin"] 129 | try: 130 | current_state.csparselin = info["coefficients"]["sparsity_lin"] 131 | except KeyError: 132 | current_state.csparselin = 0 133 | 134 | # Others 135 | current_state.static_decoding_matrix = Dspk 136 | 137 | # Set weights 138 | current_state.w = info["directional_weights"] 139 | 140 | # Calculate cost with initial transcoding matrix 141 | initial_cost = current_state.cost_function(T_flatten_initial) 142 | print("\nCost value for initial transcoding matrix: ", initial_cost) 143 | 144 | return current_state, T_flatten_initial 145 | -------------------------------------------------------------------------------- /universal_transcoder/encoders/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/universal_transcoder/encoders/__init__.py -------------------------------------------------------------------------------- /universal_transcoder/encoders/t-design/ChatGPT_files/unnamed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/universal_transcoder/encoders/t-design/ChatGPT_files/unnamed.png -------------------------------------------------------------------------------- /universal_transcoder/encoders/t-design/des.3.36.8.txt: -------------------------------------------------------------------------------- 1 | .5074754464108170E+00 2 | -.3062000132395710E+00 3 | .8054254920116630E+00 4 | -.3062000132395690E+00 5 | .8054254920116630E+00 6 | .5074754464108170E+00 7 | -.5074754464108170E+00 8 | .3062000132395700E+00 9 | .8054254920116630E+00 10 | .8054254920116630E+00 11 | .5074754464108170E+00 12 | -.3062000132395690E+00 13 | .3062000132395690E+00 14 | .8054254920116640E+00 15 | -.5074754464108170E+00 16 | .8054254920116630E+00 17 | -.5074754464108170E+00 18 | .3062000132395690E+00 19 | .3062000132395690E+00 20 | -.8054254920116630E+00 21 | .5074754464108160E+00 22 | -.8054254920116630E+00 23 | -.5074754464108170E+00 24 | -.3062000132395690E+00 25 | -.3062000132395700E+00 26 | -.8054254920116640E+00 27 | -.5074754464108160E+00 28 | -.8054254920116630E+00 29 | .5074754464108180E+00 30 | .3062000132395690E+00 31 | .5074754464108170E+00 32 | .3062000132395700E+00 33 | -.8054254920116630E+00 34 | -.5074754464108170E+00 35 | -.3062000132395700E+00 36 | -.8054254920116630E+00 37 | .6263636702652710E+00 38 | -.2435277754091940E+00 39 | -.7405152092807200E+00 40 | -.2435277754091950E+00 41 | -.7405152092807200E+00 42 | .6263636702652710E+00 43 | -.6263636702652710E+00 44 | .2435277754091940E+00 45 | -.7405152092807200E+00 46 | -.7405152092807200E+00 47 | .6263636702652700E+00 48 | -.2435277754091950E+00 49 | .2435277754091950E+00 50 | -.7405152092807190E+00 51 | -.6263636702652710E+00 52 | -.7405152092807200E+00 53 | -.6263636702652700E+00 54 | .2435277754091950E+00 55 | .2435277754091950E+00 56 | .7405152092807190E+00 57 | .6263636702652710E+00 58 | .7405152092807200E+00 59 | -.6263636702652700E+00 60 | -.2435277754091950E+00 61 | -.2435277754091950E+00 62 | .7405152092807200E+00 63 | -.6263636702652710E+00 64 | .7405152092807200E+00 65 | .6263636702652700E+00 66 | .2435277754091950E+00 67 | .6263636702652710E+00 68 | .2435277754091940E+00 69 | .7405152092807200E+00 70 | -.6263636702652710E+00 71 | -.2435277754091940E+00 72 | .7405152092807200E+00 73 | -.2862487234260350E+00 74 | .9571203270924580E+00 75 | -.4452356458542100E-01 76 | .9571203270924580E+00 77 | -.4452356458542000E-01 78 | -.2862487234260350E+00 79 | .2862487234260350E+00 80 | -.9571203270924580E+00 81 | -.4452356458542100E-01 82 | -.4452356458542000E-01 83 | -.2862487234260350E+00 84 | .9571203270924580E+00 85 | -.9571203270924580E+00 86 | -.4452356458541900E-01 87 | .2862487234260350E+00 88 | -.4452356458542100E-01 89 | .2862487234260340E+00 90 | -.9571203270924580E+00 91 | -.9571203270924580E+00 92 | .4452356458542000E-01 93 | -.2862487234260340E+00 94 | .4452356458542100E-01 95 | .2862487234260340E+00 96 | .9571203270924580E+00 97 | .9571203270924580E+00 98 | .4452356458542000E-01 99 | .2862487234260340E+00 100 | .4452356458542100E-01 101 | -.2862487234260340E+00 102 | -.9571203270924580E+00 103 | -.2862487234260340E+00 104 | -.9571203270924580E+00 105 | .4452356458542100E-01 106 | .2862487234260350E+00 107 | .9571203270924580E+00 108 | .4452356458542100E-01 109 | -------------------------------------------------------------------------------- /universal_transcoder/encoders/t-design/des.3.56.9.txt: -------------------------------------------------------------------------------- 1 | .1549160910043080E+00 2 | .9406666713134419E+00 3 | -.3019059758070950E+00 4 | -.1917028415266480E+00 5 | -.5963246724830760E+00 6 | .7795170976563380E+00 7 | .5773502691895790E+00 8 | .5773502691896970E+00 9 | .5773502691896010E+00 10 | .5773502691896970E+00 11 | .5773502691896260E+00 12 | -.5773502691895540E+00 13 | -.5773502691895960E+00 14 | .5773502691896540E+00 15 | .5773502691896280E+00 16 | .5773502691895370E+00 17 | -.5773502691896680E+00 18 | .5773502691896720E+00 19 | -.5773502691897150E+00 20 | .5773502691895830E+00 21 | -.5773502691895800E+00 22 | .5773502691896550E+00 23 | -.5773502691895980E+00 24 | -.5773502691896240E+00 25 | -.5773502691895550E+00 26 | -.5773502691896250E+00 27 | .5773502691896970E+00 28 | -.5773502691896720E+00 29 | -.5773502691895550E+00 30 | -.5773502691896500E+00 31 | -.3019059758070840E+00 32 | .1549160910043080E+00 33 | .9406666713134449E+00 34 | .7795170976563840E+00 35 | -.1917028415266140E+00 36 | -.5963246724830270E+00 37 | .1549160910042660E+00 38 | .9406666713134700E+00 39 | .3019059758070280E+00 40 | -.1917028415265970E+00 41 | -.5963246724830620E+00 42 | -.7795170976563610E+00 43 | .9406666713134220E+00 44 | -.3019059758071480E+00 45 | .1549160910043240E+00 46 | -.5963246724830310E+00 47 | .7795170976563870E+00 48 | -.1917028415265880E+00 49 | .3019059758071070E+00 50 | .1549160910043240E+00 51 | .9406666713134350E+00 52 | -.7795170976563760E+00 53 | -.1917028415266320E+00 54 | -.5963246724830320E+00 55 | .9406666713134390E+00 56 | .3019059758071080E+00 57 | .1549160910042990E+00 58 | -.5963246724830230E+00 59 | -.7795170976564010E+00 60 | -.1917028415265580E+00 61 | -.3019059758071050E+00 62 | .1549160910042870E+00 63 | -.9406666713134419E+00 64 | .7795170976563860E+00 65 | -.1917028415265490E+00 66 | .5963246724830450E+00 67 | .9406666713134570E+00 68 | -.3019059758070670E+00 69 | -.1549160910042740E+00 70 | -.5963246724831049E+00 71 | .7795170976563240E+00 72 | .1917028415266170E+00 73 | .3019059758071310E+00 74 | .1549160910043030E+00 75 | -.9406666713134310E+00 76 | -.7795170976563780E+00 77 | -.1917028415265660E+00 78 | .5963246724830500E+00 79 | .9406666713134740E+00 80 | .3019059758070270E+00 81 | -.1549160910042480E+00 82 | -.5963246724830970E+00 83 | -.7795170976563370E+00 84 | .1917028415265860E+00 85 | -.9406666713134230E+00 86 | -.3019059758071410E+00 87 | .1549160910043320E+00 88 | .5963246724830240E+00 89 | .7795170976563870E+00 90 | -.1917028415266130E+00 91 | -.1549160910043280E+00 92 | .9406666713134290E+00 93 | -.3019059758071250E+00 94 | .1917028415266380E+00 95 | -.5963246724830480E+00 96 | .7795170976563620E+00 97 | -.9406666713134400E+00 98 | .3019059758071010E+00 99 | .1549160910043060E+00 100 | .5963246724830160E+00 101 | -.7795170976564000E+00 102 | -.1917028415265820E+00 103 | -.1549160910042840E+00 104 | .9406666713134580E+00 105 | .3019059758070570E+00 106 | .1917028415265880E+00 107 | -.5963246724830350E+00 108 | -.7795170976563840E+00 109 | .1549160910042960E+00 110 | -.9406666713134400E+00 111 | -.3019059758071070E+00 112 | -.1917028415266090E+00 113 | .5963246724830870E+00 114 | .7795170976563390E+00 115 | -.3019059758070360E+00 116 | -.1549160910042770E+00 117 | .9406666713134660E+00 118 | .7795170976563460E+00 119 | .1917028415266300E+00 120 | -.5963246724830710E+00 121 | .1549160910042530E+00 122 | -.9406666713134680E+00 123 | .3019059758070410E+00 124 | -.1917028415265590E+00 125 | .5963246724830720E+00 126 | -.7795170976563630E+00 127 | .3019059758070600E+00 128 | -.1549160910042930E+00 129 | .9406666713134550E+00 130 | -.7795170976563370E+00 131 | .1917028415266490E+00 132 | -.5963246724830770E+00 133 | -.9406666713134580E+00 134 | -.3019059758070580E+00 135 | -.1549160910042810E+00 136 | .5963246724830989E+00 137 | .7795170976563220E+00 138 | .1917028415266400E+00 139 | -.9406666713134750E+00 140 | .3019059758070180E+00 141 | -.1549160910042550E+00 142 | .5963246724830910E+00 143 | -.7795170976563360E+00 144 | .1917028415266100E+00 145 | -.3019059758070560E+00 146 | -.1549160910042580E+00 147 | -.9406666713134620E+00 148 | .7795170976563480E+00 149 | .1917028415265650E+00 150 | .5963246724830900E+00 151 | .3019059758070810E+00 152 | -.1549160910042730E+00 153 | -.9406666713134521E+00 154 | -.7795170976563400E+00 155 | .1917028415265840E+00 156 | .5963246724830950E+00 157 | -.1549160910043150E+00 158 | -.9406666713134270E+00 159 | -.3019059758071370E+00 160 | .1917028415266000E+00 161 | .5963246724830600E+00 162 | .7795170976563630E+00 163 | -.1549160910042720E+00 164 | -.9406666713134550E+00 165 | .3019059758070710E+00 166 | .1917028415265490E+00 167 | .5963246724830460E+00 168 | -.7795170976563860E+00 169 | -------------------------------------------------------------------------------- /universal_transcoder/encoders/t-design/des.3.60.10.txt: -------------------------------------------------------------------------------- 1 | -.7538286671970170E+00 2 | .5459519080612600E+00 3 | -.3656211900262870E+00 4 | .5459519080612580E+00 5 | -.3656211900262900E+00 6 | -.7538286671970170E+00 7 | .7538286671970160E+00 8 | -.5459519080612610E+00 9 | -.3656211900262880E+00 10 | -.3656211900262890E+00 11 | -.7538286671970170E+00 12 | .5459519080612590E+00 13 | -.5459519080612580E+00 14 | -.3656211900262880E+00 15 | .7538286671970180E+00 16 | -.3656211900262890E+00 17 | .7538286671970170E+00 18 | -.5459519080612590E+00 19 | -.5459519080612580E+00 20 | .3656211900262890E+00 21 | -.7538286671970170E+00 22 | .3656211900262870E+00 23 | .7538286671970170E+00 24 | .5459519080612600E+00 25 | .5459519080612590E+00 26 | .3656211900262890E+00 27 | .7538286671970170E+00 28 | .3656211900262870E+00 29 | -.7538286671970180E+00 30 | -.5459519080612590E+00 31 | -.7538286671970170E+00 32 | -.5459519080612610E+00 33 | .3656211900262880E+00 34 | .7538286671970160E+00 35 | .5459519080612610E+00 36 | .3656211900262870E+00 37 | .7001810193637300E+00 38 | -.7131510658477930E+00 39 | .3408954976125600E-01 40 | -.7131510658477940E+00 41 | .3408954976125400E-01 42 | .7001810193637290E+00 43 | -.7001810193637300E+00 44 | .7131510658477930E+00 45 | .3408954976125600E-01 46 | .3408954976125500E-01 47 | .7001810193637300E+00 48 | -.7131510658477930E+00 49 | .7131510658477930E+00 50 | .3408954976125400E-01 51 | -.7001810193637300E+00 52 | .3408954976125700E-01 53 | -.7001810193637290E+00 54 | .7131510658477940E+00 55 | .7131510658477940E+00 56 | -.3408954976125500E-01 57 | .7001810193637280E+00 58 | -.3408954976125600E-01 59 | -.7001810193637290E+00 60 | -.7131510658477940E+00 61 | -.7131510658477940E+00 62 | -.3408954976125400E-01 63 | -.7001810193637290E+00 64 | -.3408954976125700E-01 65 | .7001810193637290E+00 66 | .7131510658477940E+00 67 | .7001810193637300E+00 68 | .7131510658477930E+00 69 | -.3408954976125700E-01 70 | -.7001810193637290E+00 71 | -.7131510658477940E+00 72 | -.3408954976125700E-01 73 | .2762302182617920E+00 74 | .7705072072573600E-01 75 | -.9579979399532590E+00 76 | .7705072072573500E-01 77 | -.9579979399532580E+00 78 | .2762302182617930E+00 79 | -.2762302182617920E+00 80 | -.7705072072573400E-01 81 | -.9579979399532590E+00 82 | -.9579979399532590E+00 83 | .2762302182617910E+00 84 | .7705072072573800E-01 85 | -.7705072072573500E-01 86 | -.9579979399532590E+00 87 | -.2762302182617920E+00 88 | -.9579979399532580E+00 89 | -.2762302182617930E+00 90 | -.7705072072573600E-01 91 | -.7705072072573600E-01 92 | .9579979399532580E+00 93 | .2762302182617940E+00 94 | .9579979399532590E+00 95 | -.2762302182617900E+00 96 | .7705072072573700E-01 97 | .7705072072573400E-01 98 | .9579979399532590E+00 99 | -.2762302182617920E+00 100 | .9579979399532580E+00 101 | .2762302182617930E+00 102 | -.7705072072573800E-01 103 | .2762302182617930E+00 104 | -.7705072072573600E-01 105 | .9579979399532580E+00 106 | -.2762302182617910E+00 107 | .7705072072573500E-01 108 | .9579979399532590E+00 109 | .4518191025552430E+00 110 | -.7833559375218190E+00 111 | .4268641162190700E+00 112 | -.7833559375218180E+00 113 | .4268641162190710E+00 114 | .4518191025552430E+00 115 | -.4518191025552430E+00 116 | .7833559375218190E+00 117 | .4268641162190700E+00 118 | .4268641162190710E+00 119 | .4518191025552420E+00 120 | -.7833559375218190E+00 121 | .7833559375218180E+00 122 | .4268641162190700E+00 123 | -.4518191025552440E+00 124 | .4268641162190720E+00 125 | -.4518191025552420E+00 126 | .7833559375218180E+00 127 | .7833559375218190E+00 128 | -.4268641162190700E+00 129 | .4518191025552420E+00 130 | -.4268641162190720E+00 131 | -.4518191025552410E+00 132 | -.7833559375218190E+00 133 | -.7833559375218180E+00 134 | -.4268641162190700E+00 135 | -.4518191025552430E+00 136 | -.4268641162190720E+00 137 | .4518191025552410E+00 138 | .7833559375218190E+00 139 | .4518191025552430E+00 140 | .7833559375218180E+00 141 | -.4268641162190710E+00 142 | -.4518191025552420E+00 143 | -.7833559375218190E+00 144 | -.4268641162190710E+00 145 | -.3385843599592600E+00 146 | -.9332100372395270E+00 147 | .1203314488667840E+00 148 | -.9332100372395260E+00 149 | .1203314488667870E+00 150 | -.3385843599592600E+00 151 | .3385843599592610E+00 152 | .9332100372395260E+00 153 | .1203314488667860E+00 154 | .1203314488667850E+00 155 | -.3385843599592610E+00 156 | -.9332100372395260E+00 157 | .9332100372395260E+00 158 | .1203314488667890E+00 159 | .3385843599592600E+00 160 | .1203314488667850E+00 161 | .3385843599592610E+00 162 | .9332100372395260E+00 163 | .9332100372395260E+00 164 | -.1203314488667870E+00 165 | -.3385843599592620E+00 166 | -.1203314488667840E+00 167 | .3385843599592620E+00 168 | -.9332100372395260E+00 169 | -.9332100372395260E+00 170 | -.1203314488667870E+00 171 | .3385843599592610E+00 172 | -.1203314488667840E+00 173 | -.3385843599592620E+00 174 | .9332100372395260E+00 175 | -.3385843599592620E+00 176 | .9332100372395260E+00 177 | -.1203314488667840E+00 178 | .3385843599592610E+00 179 | -.9332100372395270E+00 180 | -.1203314488667830E+00 181 | -------------------------------------------------------------------------------- /universal_transcoder/encoders/vbap_encoder.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import numpy as np 28 | from scipy.spatial import Delaunay 29 | 30 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 31 | 32 | 33 | def vbap_2D_encoder(point: MyCoordinates, layout: MyCoordinates): 34 | """Function to obtain the gains to encode in multichannel, 35 | for the speaker layout introduced (2D), using VBAP 36 | 37 | Args: 38 | point (MyCoordinates): position of the virtual source 39 | layout (MyCoordinates): positions of speaker layout, ranges: azimut [-180º,180º] 40 | and elevation [-90º,90º] of each speaker 41 | 42 | Returns: 43 | output (numpy array): gains for each speaker, sorted in the same order 44 | as was introduced in the input layout 45 | """ 46 | 47 | theta = point.sph_deg()[0][0] 48 | layout_sph = layout.get_sph(convention="top_elev", unit="deg")[:, 0] # only thetas 49 | layout_sph_sorted = np.sort(layout_sph) # Sort in ascending azimut order 50 | sort_positions = np.argsort(layout_sph) # Save original positions 51 | 52 | # Pair selection 53 | pair = None 54 | # Check all pair of speakers in the array 55 | for i in range(len(layout_sph_sorted) - 1): 56 | if theta >= layout_sph_sorted[i] and theta <= layout_sph_sorted[i + 1]: 57 | pair = ( 58 | sort_positions[i], 59 | sort_positions[i + 1], 60 | ) # Assign original positions 61 | break 62 | 63 | # If no pair was selected, then first and last speaker form a pair 64 | if pair is None: 65 | pair = (sort_positions[0], sort_positions[-1]) # Assign original positions 66 | 67 | # Polar to cartesian coordinates for input position 'p' (theta) 68 | p = point.cart()[0][0:2] 69 | if np.allclose(p, [0, 0], atol=0.0001): 70 | p = [-1, 0] # to the back 71 | 72 | # Cartesian coordinates for speakers positions (theta) 73 | layout_cart = layout.cart() 74 | L_12 = np.array([layout_cart[pair[0], 0:2], layout_cart[pair[1], 0:2]]) 75 | 76 | # Gains vector for the pair 77 | g = np.dot(p, np.linalg.inv(L_12)) 78 | 79 | # Gains normalization 80 | g_out = abs(g / np.sum(abs(g))) 81 | 82 | # Prepare output array 83 | output = np.zeros(layout_cart.shape[0]) 84 | output[pair[0]] = g_out[0] 85 | output[pair[1]] = g_out[1] 86 | 87 | return output 88 | 89 | 90 | def vbap_3D_encoder(point: MyCoordinates, layout: MyCoordinates): 91 | """Function to obtain the gains to encode in multichannel, 92 | for the speaker layout introduced (3D), using VBAP 93 | 94 | Args: 95 | point (MyCoordinates): position of the virtual source 96 | layout (MyCoordinates): positions of speaker layout, ranges: azimut [-180º,180º] 97 | and elevation [-90º,90º] of each speaker 98 | 99 | Returns: 100 | output (numpy array): gains for each speaker, sorted in the same order 101 | as was introduced in the input layout 102 | """ 103 | 104 | # Polar to cartesian coordinates for input position 'p' (theta,phi) 105 | p = point.cart()[0] 106 | 107 | # Triangulation of surface 108 | layout_cart = layout.cart() 109 | triangles = np.sort(Delaunay(layout_cart).convex_hull) 110 | 111 | # Gains calculation 112 | # Set starting value to a very low value 113 | g_min = -2 114 | 115 | for T in range(len(triangles)): 116 | # Current triangule 117 | now = triangles[T] 118 | 119 | # If speakers of triangule are co-linear, ignore them 120 | if ( 121 | layout_cart[now[0]][2] != 0 122 | or layout_cart[now[1]][2] != 0 123 | or layout_cart[now[2]][2] != 0 124 | ): 125 | L_123 = np.array( 126 | [layout_cart[now[0]], layout_cart[now[1]], layout_cart[now[2]]] 127 | ) 128 | 129 | # Gains vector for the triangle 130 | g = np.dot(p, np.linalg.inv(L_123)) 131 | 132 | # Check if min 'g' is the highest g_min for the moment 133 | g_min_check = np.min(g) 134 | if g_min_check > g_min: 135 | # If it is, g_min g_out vector and speakers of triangule are saved 136 | g_min = g_min_check 137 | g_out = g 138 | speakers = now 139 | 140 | # Gains normalization 141 | g_out = g_out / np.sum(g_out) 142 | 143 | # Prepare output array 144 | output = np.zeros(layout_cart.shape[0]) 145 | output[speakers[0]] = g_out[0] 146 | output[speakers[1]] = g_out[1] 147 | output[speakers[2]] = g_out[2] 148 | 149 | return output 150 | -------------------------------------------------------------------------------- /universal_transcoder/plots_and_logs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DolbyLaboratories/universal_transcoder/f3321f6eaaea4b61b48e219ee61b4be5a5d5d606/universal_transcoder/plots_and_logs/__init__.py -------------------------------------------------------------------------------- /universal_transcoder/plots_and_logs/all_plots.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import matplotlib.pyplot as plt 28 | 29 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 30 | from universal_transcoder.auxiliars.typing import Array 31 | from universal_transcoder.calculations.energy_intensity import ( 32 | energy_calculation, 33 | radial_I_calculation, 34 | transverse_I_calculation, 35 | ) 36 | from universal_transcoder.calculations.pressure_velocity import ( 37 | pressure_calculation, 38 | radial_V_calculation, 39 | transversal_V_calculation, 40 | ) 41 | from universal_transcoder.plots_and_logs.e_i_plots import plot_ei_2D, plot_ei_3D 42 | from universal_transcoder.plots_and_logs.p_v_plots import plot_pv_2D, plot_pv_3D 43 | from universal_transcoder.plots_and_logs.paper_plots_to_R import ( 44 | save_physics_to_file, 45 | ) 46 | from universal_transcoder.plots_and_logs.speakers_plots import ( 47 | plot_speaker_2D, 48 | ) 49 | 50 | 51 | def plots_general( 52 | output_layout: MyCoordinates, 53 | speaker_signals: Array, 54 | cloud: MyCoordinates, 55 | show_results: bool, 56 | save_results: bool, 57 | save_plot_name, 58 | ): 59 | """ 60 | Function group all plots and call them at once 61 | 62 | Args: 63 | output_layout (MyCoordinates): positions of output speaker layout: 64 | pyfar.Coordinates (P-speakers) 65 | speaker_signals (Array): speaker signals resulting from decoding 66 | to input set of encoded L directions (LxP size) 67 | cloud(MyCoordinates): set of points sampling the sphere (L) 68 | show_results (bool): Flag to show plots 69 | save_results (bool): Flag to save plots 70 | results_file_name(str): Path where to save the plots 71 | """ 72 | 73 | # Energy 74 | energy = energy_calculation(speaker_signals) 75 | # Intensity 76 | radial_i = radial_I_calculation(cloud, speaker_signals, output_layout) 77 | transverse_i = transverse_I_calculation(cloud, speaker_signals, output_layout) 78 | # Pressure 79 | pressure = pressure_calculation(speaker_signals) 80 | # Velocity 81 | radial_v = radial_V_calculation(cloud, speaker_signals, output_layout) 82 | transverse_v = transversal_V_calculation(cloud, speaker_signals, output_layout) 83 | 84 | plot_ei_2D( 85 | energy, 86 | radial_i, 87 | transverse_i, 88 | cloud, 89 | save_results, 90 | save_plot_name, 91 | ) 92 | plot_pv_2D( 93 | pressure, 94 | radial_v, 95 | transverse_v, 96 | cloud, 97 | save_results, 98 | save_plot_name, 99 | ) 100 | plot_speaker_2D( 101 | output_layout, 102 | speaker_signals, 103 | cloud, 104 | save_results, 105 | save_plot_name, 106 | ) 107 | plot_ei_3D( 108 | energy, 109 | radial_i, 110 | transverse_i, 111 | cloud, 112 | save_results, 113 | save_plot_name, 114 | ) 115 | plot_pv_3D( 116 | pressure, 117 | radial_v, 118 | transverse_v, 119 | cloud, 120 | save_results, 121 | save_plot_name, 122 | ) 123 | 124 | if show_results: 125 | plt.show() 126 | 127 | if save_results: 128 | # Generate txt file with data 129 | coordinates = cloud.sph_deg() 130 | azimuth = coordinates[:, 0] 131 | elevation = coordinates[:, 1] 132 | save_physics_to_file( 133 | azimuth, 134 | elevation, 135 | pressure, 136 | radial_v, 137 | transverse_v, 138 | energy, 139 | radial_i, 140 | transverse_i, 141 | save_plot_name, 142 | ) 143 | -------------------------------------------------------------------------------- /universal_transcoder/plots_and_logs/common_plots_functions.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import os 28 | 29 | import matplotlib.pyplot as plt 30 | import numpy as np 31 | 32 | 33 | def normalize_S(S, normalize): 34 | if normalize == "p": 35 | S = np.apply_along_axis(lambda x: x / np.sum(x), 0, S.T).T 36 | if normalize == "e": 37 | S = np.apply_along_axis(lambda x: x / np.sqrt(np.sum(x**2)), 0, S.T).T 38 | return S 39 | 40 | 41 | def save_plot(plot: plt, specific_path: str, file_name: str): 42 | """ 43 | Function save plots as png images 44 | 45 | Args: 46 | plot (plt): plot figure to be saved 47 | specific_path (str): path where to save 48 | file_name(str): name of the figure or image 49 | """ 50 | path = os.path.join("saved_results", specific_path) 51 | full_path = os.path.join(path, file_name) 52 | os.makedirs(path, exist_ok=True) 53 | plot.savefig(full_path, dpi=300, bbox_inches="tight") 54 | -------------------------------------------------------------------------------- /universal_transcoder/plots_and_logs/speakers_plots.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 Dolby Laboratories, Amaia Sagasti 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 | and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or 15 | promote products derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | """ 26 | 27 | import warnings 28 | from typing import Union 29 | 30 | import matplotlib.pyplot as plt 31 | import numpy as np 32 | 33 | from universal_transcoder.auxiliars.my_coordinates import MyCoordinates 34 | from universal_transcoder.auxiliars.typing import NpArray 35 | from universal_transcoder.plots_and_logs.common_plots_functions import save_plot 36 | 37 | warnings.filterwarnings( 38 | "ignore", category=RuntimeWarning 39 | ) # deactivate warnings in log10() calculation 40 | 41 | 42 | def plot_speaker_2D( 43 | output_layout: MyCoordinates, 44 | speaker_signals: NpArray, 45 | cloud: MyCoordinates, 46 | save_results: bool, 47 | results_file_name, 48 | ): 49 | """ 50 | Function to plot speaker gains for each speaker of an output layout. 2D plots. 51 | 52 | Args: 53 | output_layout (MyCoordinates): positions of output speaker layout: 54 | pyfar.Coordinates (P-speakers) 55 | speaker_signals (Array): speaker signals resulting from decoding 56 | to input set of encoded L directions (LxP size) 57 | cloud(MyCoordinates): set of points sampling the sphere (L) 58 | save_results (bool): Flag to save plots 59 | results_file_name(str): Path where to save the plots 60 | """ 61 | output_layout = output_layout.sph_deg() 62 | 63 | azimuth = cloud.sph_rad()[:, 0] 64 | elevation = cloud.sph_rad()[:, 1] 65 | mask_horizon = (elevation < 0.01) * (elevation > -0.01) 66 | 67 | speaker_gains = speaker_signals 68 | speaker_gains_db = 20 * np.log10(speaker_gains) 69 | 70 | # mask point at the horizon 71 | azimuth = azimuth[mask_horizon] 72 | speaker_gains = speaker_gains[mask_horizon, :] 73 | speaker_gains_db = speaker_gains_db[mask_horizon, :] 74 | 75 | sum_gains = np.sum(speaker_gains, axis=1) 76 | sum_gains_db = 20 * np.log10(sum_gains) 77 | lim = np.max(sum_gains) + 0.1 78 | lim_db = np.max(sum_gains_db) + 0.5 79 | lim_db = 5 80 | 81 | fig1 = plt.figure(figsize=(17, 9)) 82 | 83 | # Plot in XY 84 | ax2 = fig1.add_subplot(222) 85 | for i in range(output_layout.shape[0]): 86 | ax2.plot(azimuth, speaker_gains[:, i], label=("Speaker nº", i)) 87 | ax2.plot(azimuth, sum_gains.T, label=("Total gain")) 88 | plt.title("Speaker gains") 89 | plt.ylim(-0.05, lim) 90 | 91 | # Plot in XY in dBs 92 | ax3 = fig1.add_subplot(224) 93 | for i in range(output_layout.shape[0]): 94 | ax3.plot(azimuth, speaker_gains_db[:, i], label=("Speaker nº", i)) 95 | ax3.plot(azimuth, sum_gains_db, label=("Total gain")) 96 | plt.title("Speaker gains (dB)") 97 | plt.ylim(-40, lim_db) 98 | 99 | # Add last to close plot 100 | azimuth = np.hstack((azimuth, azimuth[0])) 101 | # print("Shapes ", speaker_gains.shape, speaker_gains[0, :].shape) 102 | speaker_gains = np.vstack((speaker_gains, speaker_gains[0, :])) 103 | speaker_gains_db = np.vstack((speaker_gains_db, speaker_gains_db[0, :])) 104 | sum_gains = np.hstack((sum_gains, sum_gains[0])) 105 | sum_gains_db = np.hstack((sum_gains_db, sum_gains_db[0])) 106 | 107 | # Plot in Polar 108 | 109 | ax = fig1.add_subplot(221, projection="polar") 110 | ax.legend(bbox_to_anchor=(0.5, -0.55), loc="lower center") 111 | for i in range(output_layout.shape[0]): 112 | ax.plot(azimuth, speaker_gains[:, i].T, label=("Speaker nº", i)) 113 | ax.plot(azimuth, sum_gains.T, label=("Total gain")) 114 | ax.set_theta_zero_location("N") 115 | plt.title("Speaker gains") 116 | plt.ylim(0, lim) 117 | 118 | # plt.show() 119 | 120 | # Save plots 121 | if save_results and (type(results_file_name) == str): 122 | file_name = "plot_speaker_gains_2D.png" 123 | save_plot(plt, results_file_name, file_name) 124 | 125 | 126 | def plot_speaker_3D( 127 | output_layout: MyCoordinates, 128 | speaker_signals: NpArray, 129 | cloud_points: MyCoordinates, 130 | save_results: bool, 131 | results_file_name: Union[bool, str] = False, 132 | ): 133 | """ 134 | Function to plot speaker gains for each speaker of an output layout. 135 | 3D projection on 2D plots. 136 | 137 | Args: 138 | output_layout (MyCoordinates): positions of output speaker layout: 139 | pyfar.Coordinates (P-speakers) 140 | speaker_signals (Array): speaker signals resulting from decoding 141 | to input set of encoded L directions (LxP size) 142 | cloud(MyCoordinates): set of points sampling the sphere (L) 143 | save_results (bool): Flag to save plots 144 | results_file_name(str): Path where to save the plots 145 | """ 146 | 147 | # Plot 148 | cloud_points_cart = cloud_points.cart() 149 | X = cloud_points_cart[:, 0] 150 | Y = cloud_points_cart[:, 1] 151 | Z = cloud_points_cart[:, 2] 152 | layout_sph = output_layout.sph_deg() 153 | number_spk = layout_sph.shape[0] 154 | fig = plt.figure(figsize=(17, 9)) 155 | for i in range(number_spk): 156 | ax = fig.add_subplot(1, number_spk, i + 1, projection="3d") 157 | sc = ax.scatter(X, Y, Z, c=speaker_signals[:, i], cmap="rainbow") 158 | ax.axis("equal") 159 | ax.set_xlabel("X axis", fontsize=6) 160 | ax.set_ylabel("Y axis", fontsize=6) 161 | ax.set_zlabel("Z axis", fontsize=6) 162 | ax.tick_params(labelsize=6) 163 | title = "Speaker position {}" 164 | plt.title(title.format(layout_sph[i, :]), fontsize=7) 165 | 166 | sc.set_clim(0, 1) 167 | plt.colorbar(sc) # To see colorbar scale 168 | # plt.show() 169 | 170 | # Save plots 171 | if save_results and (type(results_file_name) == str): 172 | file_name = "plot_speaker_gains_3D.png" 173 | save_plot(plt, results_file_name, file_name) 174 | --------------------------------------------------------------------------------