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 
25 
26 #define LOC QString("Downmixer: ")
27 
28 /*
29  SMPTE channel layout
30  DUAL-MONO L R
31  DUAL-MONO-LFE L R LFE
32  MONO M
33  MONO-LFE M LFE
34  STEREO L R
35  STEREO-LFE L R LFE
36  3F L R C
37  3F-LFE L R C LFE
38  2F1 L R S
39  2F1-LFE L R LFE S
40  3F1 L R C S
41  3F1-LFE L R C LFE S
42  2F2 L R LS RS
43  2F2-LFE L R LFE LS RS
44  3F2 L R C LS RS
45  3F2-LFE L R C LFE LS RS
46  3F3R-LFE L R C LFE BC LS RS
47  3F4-LFE L R C LFE Rls Rrs LS RS
48  */
49 
50 static const float m6db = 0.5;
51 static const float m3db = 0.7071067811865476F; // 3dB = SQRT(2)
52 static const float mm3db = -0.7071067811865476F; // -3dB = SQRT(1/2)
53 static const float msqrt_1_3 = -0.577350269189626F; // -SQRT(1/3)
54 static const float sqrt_2_3 = 0.816496580927726F; // SQRT(2/3)
55 static const float sqrt_2_3by3db = 0.577350269189626F; // SQRT(2/3)*-3dB = SQRT(2/3)*SQRT(1/2)=SQRT(1/3)
56 static const float msqrt_1_3bym3db = 0.408248290463863F; // -SQRT(1/3)*-3dB = -SQRT(1/3)*SQRT(1/2) = -SQRT(1/6)
57 
58 using two_speaker_ratio = std::array<float,2>;
59 using two_speaker_set = std::array<two_speaker_ratio,8>;
60 static const std::array<two_speaker_set,8> stereo_matrix
61 {{
62 //1F L R
63  {{
64  { 1, 1 }, // M
65  }},
66 
67 //2F L R
68  {{
69  { 1, 0 }, // L
70  { 0, 1 }, // R
71  }},
72 
73 //3F L R
74  {{
75  { 1, 0 }, // L
76  { 0, 1 }, // R
77  { 1, 1 }, // C
78  }},
79 
80 //3F1R L R
81  {{
82  { 1, 0 }, // L
83  { 0, 1 }, // R
84  { m3db, m3db }, // C
85  { mm3db, m3db }, // S
86  }},
87 
88 //3F2R L R
89  {{
90  { 1, 0 }, // L
91  { 0, 1 }, // R
92  { m3db, m3db }, // C
93  { sqrt_2_3, msqrt_1_3 }, // LS
94  { msqrt_1_3, sqrt_2_3 }, // RS
95  }},
96 
97 //3F2R.1 L R
98  {{
99  { 1, 0 }, // L
100  { 0, 1 }, // R
101  { m3db, m3db }, // C
102  { 0, 0 }, // LFE
103  { sqrt_2_3, msqrt_1_3 }, // LS
104  { msqrt_1_3, sqrt_2_3 }, // RS
105  }},
106 
107 // 3F3R.1 L R
108  {{
109  { 1, 0 }, // L
110  { 0, 1 }, // R
111  { m3db, m3db }, // C
112  { 0, 0 }, // LFE
113  { m6db, m6db }, // Cs
114  { sqrt_2_3, msqrt_1_3 }, // LS
115  { msqrt_1_3, sqrt_2_3 }, // RS
116  }},
117 
118 // 3F4R.1 L R
119  {{
120  { 1, 0 }, // L
121  { 0, 1 }, // R
122  { m3db, m3db }, // C
123  { 0, 0 }, // LFE
124  { sqrt_2_3by3db, msqrt_1_3bym3db }, // Rls
125  { msqrt_1_3bym3db, sqrt_2_3by3db }, // Rrs
126  { sqrt_2_3by3db, msqrt_1_3bym3db }, // LS
127  { msqrt_1_3bym3db, sqrt_2_3by3db }, // RS
128  }}
129 }};
130 
131 using six_speaker_ratio = std::array<float,6>;
132 using six_speaker_set = std::array<six_speaker_ratio,8>;
133 static const std::array<six_speaker_set,3> s51_matrix
134 {{
135  // 3F2R.1 in -> 3F2R.1 out
136  // L R C LFE LS RS
137  {{
138  { 1, 0, 0, 0, 0, 0 }, // L
139  { 0, 1, 0, 0, 0, 0 }, // R
140  { 0, 0, 1, 0, 0, 0 }, // C
141  { 0, 0, 0, 1, 0, 0 }, // LFE
142  { 0, 0, 0, 0, 1, 0 }, // LS
143  { 0, 0, 0, 0, 0, 1 }, // RS
144  }},
145  // 3F3R.1 in -> 3F2R.1 out
146  // Used coefficient found at http://www.yamahaproaudio.com/training/self_training/data/smqr_en.pdf
147  // L R C LFE LS RS
148  {{
149  { 1, 0, 0, 0, 0, 0 }, // L
150  { 0, 1, 0, 0, 0, 0 }, // R
151  { 0, 0, 1, 0, 0, 0 }, // C
152  { 0, 0, 0, 1, 0, 0 }, // LFE
153  { 0, 0, 0, 0, m3db, m3db }, // Cs
154  { 0, 0, 0, 0, 1, 0 }, // LS
155  { 0, 0, 0, 0, 0, 1 }, // RS
156  }},
157  // 3F4R.1 -> 3F2R.1 out
158  // L R C LFE LS RS
159  {{
160  { 1, 0, 0, 0, 0, 0 }, // L
161  { 0, 1, 0, 0, 0, 0 }, // R
162  { 0, 0, 1, 0, 0, 0 }, // C
163  { 0, 0, 0, 1, 0, 0 }, // LFE
164  { 0, 0, 0, 0, m3db, 0 }, // Rls
165  { 0, 0, 0, 0, 0, m3db }, // Rrs
166  { 0, 0, 0, 0, m3db, 0 }, // LS
167  { 0, 0, 0, 0, 0, m3db }, // RS
168  }}
169 }};
170 
171 int AudioOutputDownmix::DownmixFrames(int channels_in, int channels_out,
172  float *dst, const float *src, int frames)
173 {
174  if (channels_in < channels_out)
175  return -1;
176 
177  //LOG(VB_AUDIO, LOG_INFO, LOC + LOC + QString("Downmixing %1 frames (in:%2 out:%3)")
178  // .arg(frames).arg(channels_in).arg(channels_out));
179  if (channels_out == 2)
180  {
181  int index = channels_in - 1;
182  for (int n=0; n < frames; n++)
183  {
184  for (int i=0; i < channels_out; i++)
185  {
186  float tmp = 0.0F;
187  for (int j=0; j < channels_in; j++)
188  tmp += src[j] * stereo_matrix[index][j][i];
189  *dst++ = tmp;
190  }
191  src += channels_in;
192  }
193  }
194  else if (channels_out == 6)
195  {
196  int index = channels_in - 6;
197  for (int n=0; n < frames; n++)
198  {
199  for (int i=0; i < channels_out; i++)
200  {
201  float tmp = 0.0F;
202  for (int j=0; j < channels_in; j++)
203  tmp += src[j] * s51_matrix[index][j][i];
204  *dst++ = tmp;
205  }
206  src += channels_in;
207  }
208  }
209  else
210  {
211  return -1;
212  }
213 
214  return frames;
215 }
msqrt_1_3bym3db
static const float msqrt_1_3bym3db
Definition: audiooutputdownmix.cpp:56
msqrt_1_3
static const float msqrt_1_3
Definition: audiooutputdownmix.cpp:53
sqrt_2_3by3db
static const float sqrt_2_3by3db
Definition: audiooutputdownmix.cpp:55
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
m3db
static const float m3db
Definition: audiooutputdownmix.cpp:51
mm3db
static const float mm3db
Definition: audiooutputdownmix.cpp:52
sqrt_2_3
static const float sqrt_2_3
Definition: audiooutputdownmix.cpp:54
mythlogging.h
six_speaker_set
std::array< six_speaker_ratio, 8 > six_speaker_set
Definition: audiooutputdownmix.cpp:132
stereo_matrix
static const std::array< two_speaker_set, 8 > stereo_matrix
Definition: audiooutputdownmix.cpp:61
two_speaker_set
std::array< two_speaker_ratio, 8 > two_speaker_set
Definition: audiooutputdownmix.cpp:59
six_speaker_ratio
std::array< float, 6 > six_speaker_ratio
Definition: audiooutputdownmix.cpp:131
m6db
static const float m6db
Definition: audiooutputdownmix.cpp:50
audiooutputdownmix.h
s51_matrix
static const std::array< six_speaker_set, 3 > s51_matrix
Definition: audiooutputdownmix.cpp:134
audiooutputbase.h
AudioOutputDownmix::DownmixFrames
static int DownmixFrames(int channels_in, int channels_out, float *dst, const float *src, int frames)
Definition: audiooutputdownmix.cpp:171
two_speaker_ratio
std::array< float, 2 > two_speaker_ratio
Definition: audiooutputdownmix.cpp:58