MythTV  master
audiooutputdownmix.cpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2010-2011 Jean-Yves Avenard
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18 
19 #include "audiooutputbase.h"
20 #include "audiooutputdownmix.h"
21 
22 #include <cstring>
23 
24 #define LOC QString("Downmixer: ")
25 
26 /*
27  SMPTE channel layout
28  DUAL-MONO L R
29  DUAL-MONO-LFE L R LFE
30  MONO M
31  MONO-LFE M LFE
32  STEREO L R
33  STEREO-LFE L R LFE
34  3F L R C
35  3F-LFE L R C LFE
36  2F1 L R S
37  2F1-LFE L R LFE S
38  3F1 L R C S
39  3F1-LFE L R C LFE S
40  2F2 L R LS RS
41  2F2-LFE L R LFE LS RS
42  3F2 L R C LS RS
43  3F2-LFE L R C LFE LS RS
44  3F3R-LFE L R C LFE BC LS RS
45  3F4-LFE L R C LFE Rls Rrs LS RS
46  */
47 
48 static const float m6db = 0.5;
49 static const float m3db = 0.7071067811865476F; // 3dB = SQRT(2)
50 static const float mm3db = -0.7071067811865476F; // -3dB = SQRT(1/2)
51 static const float msqrt_1_3 = -0.577350269189626F; // -SQRT(1/3)
52 static const float sqrt_2_3 = 0.816496580927726F; // SQRT(2/3)
53 static const float sqrt_2_3by3db = 0.577350269189626F; // SQRT(2/3)*-3dB = SQRT(2/3)*SQRT(1/2)=SQRT(1/3)
54 static const float msqrt_1_3bym3db = 0.408248290463863F; // -SQRT(1/3)*-3dB = -SQRT(1/3)*SQRT(1/2) = -SQRT(1/6)
55 
56 using two_speaker_ratio = std::array<float,2>;
57 using two_speaker_set = std::array<two_speaker_ratio,8>;
58 static const std::array<two_speaker_set,8> stereo_matrix
59 {{
60 //1F L R
61  {{
62  { 1, 1 }, // M
63  }},
64 
65 //2F L R
66  {{
67  { 1, 0 }, // L
68  { 0, 1 }, // R
69  }},
70 
71 //3F L R
72  {{
73  { 1, 0 }, // L
74  { 0, 1 }, // R
75  { 1, 1 }, // C
76  }},
77 
78 //3F1R L R
79  {{
80  { 1, 0 }, // L
81  { 0, 1 }, // R
82  { m3db, m3db }, // C
83  { mm3db, m3db }, // S
84  }},
85 
86 //3F2R L R
87  {{
88  { 1, 0 }, // L
89  { 0, 1 }, // R
90  { m3db, m3db }, // C
91  { sqrt_2_3, msqrt_1_3 }, // LS
92  { msqrt_1_3, sqrt_2_3 }, // RS
93  }},
94 
95 //3F2R.1 L R
96  {{
97  { 1, 0 }, // L
98  { 0, 1 }, // R
99  { m3db, m3db }, // C
100  { 0, 0 }, // LFE
101  { sqrt_2_3, msqrt_1_3 }, // LS
102  { msqrt_1_3, sqrt_2_3 }, // RS
103  }},
104 
105 // 3F3R.1 L R
106  {{
107  { 1, 0 }, // L
108  { 0, 1 }, // R
109  { m3db, m3db }, // C
110  { 0, 0 }, // LFE
111  { m6db, m6db }, // Cs
112  { sqrt_2_3, msqrt_1_3 }, // LS
113  { msqrt_1_3, sqrt_2_3 }, // RS
114  }},
115 
116 // 3F4R.1 L R
117  {{
118  { 1, 0 }, // L
119  { 0, 1 }, // R
120  { m3db, m3db }, // C
121  { 0, 0 }, // LFE
122  { sqrt_2_3by3db, msqrt_1_3bym3db }, // Rls
123  { msqrt_1_3bym3db, sqrt_2_3by3db }, // Rrs
124  { sqrt_2_3by3db, msqrt_1_3bym3db }, // LS
125  { msqrt_1_3bym3db, sqrt_2_3by3db }, // RS
126  }}
127 }};
128 
129 using six_speaker_ratio = std::array<float,6>;
130 using six_speaker_set = std::array<six_speaker_ratio,8>;
131 static const std::array<six_speaker_set,3> s51_matrix
132 {{
133  // 3F2R.1 in -> 3F2R.1 out
134  // L R C LFE LS RS
135  {{
136  { 1, 0, 0, 0, 0, 0 }, // L
137  { 0, 1, 0, 0, 0, 0 }, // R
138  { 0, 0, 1, 0, 0, 0 }, // C
139  { 0, 0, 0, 1, 0, 0 }, // LFE
140  { 0, 0, 0, 0, 1, 0 }, // LS
141  { 0, 0, 0, 0, 0, 1 }, // RS
142  }},
143  // 3F3R.1 in -> 3F2R.1 out
144  // Used coefficient found at http://www.yamahaproaudio.com/training/self_training/data/smqr_en.pdf
145  // L R C LFE LS RS
146  {{
147  { 1, 0, 0, 0, 0, 0 }, // L
148  { 0, 1, 0, 0, 0, 0 }, // R
149  { 0, 0, 1, 0, 0, 0 }, // C
150  { 0, 0, 0, 1, 0, 0 }, // LFE
151  { 0, 0, 0, 0, m3db, m3db }, // Cs
152  { 0, 0, 0, 0, 1, 0 }, // LS
153  { 0, 0, 0, 0, 0, 1 }, // RS
154  }},
155  // 3F4R.1 -> 3F2R.1 out
156  // L R C LFE LS RS
157  {{
158  { 1, 0, 0, 0, 0, 0 }, // L
159  { 0, 1, 0, 0, 0, 0 }, // R
160  { 0, 0, 1, 0, 0, 0 }, // C
161  { 0, 0, 0, 1, 0, 0 }, // LFE
162  { 0, 0, 0, 0, m3db, 0 }, // Rls
163  { 0, 0, 0, 0, 0, m3db }, // Rrs
164  { 0, 0, 0, 0, m3db, 0 }, // LS
165  { 0, 0, 0, 0, 0, m3db }, // RS
166  }}
167 }};
168 
169 int AudioOutputDownmix::DownmixFrames(int channels_in, int channels_out,
170  float *dst, const float *src, int frames)
171 {
172  if (channels_in < channels_out)
173  return -1;
174 
175  //VBAUDIO(LOC + QString("Downmixing %1 frames (in:%2 out:%3)")
176  // .arg(frames).arg(channels_in).arg(channels_out));
177  if (channels_out == 2)
178  {
179  int index = channels_in - 1;
180  for (int n=0; n < frames; n++)
181  {
182  for (int i=0; i < channels_out; i++)
183  {
184  float tmp = 0.0F;
185  for (int j=0; j < channels_in; j++)
186  tmp += src[j] * stereo_matrix[index][j][i];
187  *dst++ = tmp;
188  }
189  src += channels_in;
190  }
191  }
192  else if (channels_out == 6)
193  {
194  int index = channels_in - 6;
195  for (int n=0; n < frames; n++)
196  {
197  for (int i=0; i < channels_out; i++)
198  {
199  float tmp = 0.0F;
200  for (int j=0; j < channels_in; j++)
201  tmp += src[j] * s51_matrix[index][j][i];
202  *dst++ = tmp;
203  }
204  src += channels_in;
205  }
206  }
207  else
208  return -1;
209 
210  return frames;
211 }
msqrt_1_3bym3db
static const float msqrt_1_3bym3db
Definition: audiooutputdownmix.cpp:54
msqrt_1_3
static const float msqrt_1_3
Definition: audiooutputdownmix.cpp:51
sqrt_2_3by3db
static const float sqrt_2_3by3db
Definition: audiooutputdownmix.cpp:53
tmp
static guint32 * tmp
Definition: goom_core.cpp:30
m3db
static const float m3db
Definition: audiooutputdownmix.cpp:49
mm3db
static const float mm3db
Definition: audiooutputdownmix.cpp:50
sqrt_2_3
static const float sqrt_2_3
Definition: audiooutputdownmix.cpp:52
six_speaker_set
std::array< six_speaker_ratio, 8 > six_speaker_set
Definition: audiooutputdownmix.cpp:130
stereo_matrix
static const std::array< two_speaker_set, 8 > stereo_matrix
Definition: audiooutputdownmix.cpp:59
two_speaker_set
std::array< two_speaker_ratio, 8 > two_speaker_set
Definition: audiooutputdownmix.cpp:57
six_speaker_ratio
std::array< float, 6 > six_speaker_ratio
Definition: audiooutputdownmix.cpp:129
m6db
static const float m6db
Definition: audiooutputdownmix.cpp:48
audiooutputdownmix.h
s51_matrix
static const std::array< six_speaker_set, 3 > s51_matrix
Definition: audiooutputdownmix.cpp:132
audiooutputbase.h
AudioOutputDownmix::DownmixFrames
static int DownmixFrames(int channels_in, int channels_out, float *dst, const float *src, int frames)
Definition: audiooutputdownmix.cpp:169
two_speaker_ratio
std::array< float, 2 > two_speaker_ratio
Definition: audiooutputdownmix.cpp:56