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 int matrix[4][2] = { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 } };
57 
58 static const float stereo_matrix[8][8][2] =
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 static const float s51_matrix[3][8][6] =
130 {
131  // 3F2R.1 in -> 3F2R.1 out
132  // L R C LFE LS RS
133  {
134  { 1, 0, 0, 0, 0, 0 }, // L
135  { 0, 1, 0, 0, 0, 0 }, // R
136  { 0, 0, 1, 0, 0, 0 }, // C
137  { 0, 0, 0, 1, 0, 0 }, // LFE
138  { 0, 0, 0, 0, 1, 0 }, // LS
139  { 0, 0, 0, 0, 0, 1 }, // RS
140  },
141  // 3F3R.1 in -> 3F2R.1 out
142  // Used coefficient found at http://www.yamahaproaudio.com/training/self_training/data/smqr_en.pdf
143  // L R C LFE LS RS
144  {
145  { 1, 0, 0, 0, 0, 0 }, // L
146  { 0, 1, 0, 0, 0, 0 }, // R
147  { 0, 0, 1, 0, 0, 0 }, // C
148  { 0, 0, 0, 1, 0, 0 }, // LFE
149  { 0, 0, 0, 0, m3db, m3db }, // Cs
150  { 0, 0, 0, 0, 1, 0 }, // LS
151  { 0, 0, 0, 0, 0, 1 }, // RS
152  },
153  // 3F4R.1 -> 3F2R.1 out
154  // L R C LFE LS RS
155  {
156  { 1, 0, 0, 0, 0, 0 }, // L
157  { 0, 1, 0, 0, 0, 0 }, // R
158  { 0, 0, 1, 0, 0, 0 }, // C
159  { 0, 0, 0, 1, 0, 0 }, // LFE
160  { 0, 0, 0, 0, m3db, 0 }, // Rls
161  { 0, 0, 0, 0, 0, m3db }, // Rrs
162  { 0, 0, 0, 0, m3db, 0 }, // LS
163  { 0, 0, 0, 0, 0, m3db }, // RS
164  }
165 };
166 
167 int AudioOutputDownmix::DownmixFrames(int channels_in, int channels_out,
168  float *dst, const float *src, int frames)
169 {
170  if (channels_in < channels_out)
171  return -1;
172 
173  //VBAUDIO(LOC + QString("Downmixing %1 frames (in:%2 out:%3)")
174  // .arg(frames).arg(channels_in).arg(channels_out));
175  if (channels_out == 2)
176  {
177  int index = channels_in - 1;
178  for (int n=0; n < frames; n++)
179  {
180  for (int i=0; i < channels_out; i++)
181  {
182  float tmp = 0.0F;
183  for (int j=0; j < channels_in; j++)
184  tmp += src[j] * stereo_matrix[index][j][i];
185  *dst++ = tmp;
186  }
187  src += channels_in;
188  }
189  }
190  else if (channels_out == 6)
191  {
192  int index = channels_in - 6;
193  for (int n=0; n < frames; n++)
194  {
195  for (int i=0; i < channels_out; i++)
196  {
197  float tmp = 0.0F;
198  for (int j=0; j < channels_in; j++)
199  tmp += src[j] * s51_matrix[index][j][i];
200  *dst++ = tmp;
201  }
202  src += channels_in;
203  }
204  }
205  else
206  return -1;
207 
208  return frames;
209 }
static const float mm3db
static int DownmixFrames(int channels_in, int channels_out, float *dst, const float *src, int frames)
static const float msqrt_1_3bym3db
int matrix[4][2]
static const float m6db
static guint32 * tmp
Definition: goom_core.c:35
static const float msqrt_1_3
static const float stereo_matrix[8][8][2]
static const float sqrt_2_3
const char * frames[3]
Definition: element.c:46
static const float sqrt_2_3by3db
static const float m3db
static const float s51_matrix[3][8][6]