MythTV  0.26-pre
audiooutputdownmix.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2010-2011 Jean-Yves Avenard
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00017 */
00018 
00019 #include "audiooutputbase.h"
00020 #include "audiooutputdownmix.h"
00021 
00022 #include "string.h"
00023 
00024 #define LOC QString("Downmixer: ")
00025 
00026 /*
00027  SMPTE channel layout
00028  DUAL-MONO      L   R
00029  DUAL-MONO-LFE  L   R   LFE
00030  MONO           M
00031  MONO-LFE       M   LFE
00032  STEREO         L   R
00033  STEREO-LFE     L   R   LFE
00034  3F             L   R   C
00035  3F-LFE         L   R   C    LFE
00036  2F1            L   R   S
00037  2F1-LFE        L   R   LFE  S
00038  3F1            L   R   C    S
00039  3F1-LFE        L   R   C    LFE S
00040  2F2            L   R   LS   RS
00041  2F2-LFE        L   R   LFE  LS   RS
00042  3F2            L   R   C    LS   RS
00043  3F2-LFE        L   R   C    LFE  LS   RS
00044  3F3R-LFE       L   R   C    LFE  BC   LS   RS
00045  3F4-LFE        L   R   C    LFE  Rls  Rrs  LS   RS
00046  */
00047 
00048 static const float m6db = 0.5;
00049 static const float m3db = 0.7071067811865476f;           // 3dB  = SQRT(2)
00050 static const float mm3db = -0.7071067811865476f;         // -3dB = SQRT(1/2)
00051 static const float msqrt_1_3 = -0.577350269189626f;      // -SQRT(1/3)
00052 static const float sqrt_2_3 = 0.816496580927726f;        // SQRT(2/3)
00053 static const float sqrt_2_3by3db = 0.577350269189626f;   // SQRT(2/3)*-3dB = SQRT(2/3)*SQRT(1/2)=SQRT(1/3)
00054 static const float msqrt_1_3bym3db = 0.408248290463863f; // -SQRT(1/3)*-3dB = -SQRT(1/3)*SQRT(1/2) = -SQRT(1/6)
00055 
00056 int matrix[4][2] = { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 } };
00057 
00058 static const float stereo_matrix[8][8][2] =
00059 {
00060 //1F      L                R
00061     {
00062         { 1,               1 },                 // M
00063     },
00064 
00065 //2F      L                R
00066     {
00067         { 1,               0 },                 // L
00068         { 0,               1 },                 // R
00069     },
00070 
00071 //3F      L                R
00072     {
00073         { 1,               0 },                 // L
00074         { 0,               1 },                 // R
00075         { 1,               1 },                 // C
00076     },
00077 
00078 //3F1R    L                R
00079     {
00080         { 1,               0 },                 // L
00081         { 0,               1 },                 // R
00082         { m3db,            m3db },              // C
00083         { mm3db,           m3db },              // S
00084     },
00085 
00086 //3F2R    L                R
00087     {
00088         { 1,               0 },                 // L
00089         { 0,               1 },                 // R
00090         { m3db,            m3db },              // C
00091         { sqrt_2_3,        msqrt_1_3 },         // LS
00092         { msqrt_1_3,       sqrt_2_3 },          // RS
00093     },
00094 
00095 //3F2R.1  L                R
00096     {
00097         { 1,               0 },                 // L
00098         { 0,               1 },                 // R
00099         { m3db,            m3db },              // C
00100         { 0,               0 },                 // LFE
00101         { sqrt_2_3,        msqrt_1_3 },         // LS
00102         { msqrt_1_3,       sqrt_2_3 },          // RS
00103     },
00104 
00105 // 3F3R.1 L                R
00106     {
00107         { 1,               0 },                 // L
00108         { 0,               1 },                 // R
00109         { m3db,            m3db },              // C
00110         { 0,               0 },                 // LFE
00111         { m6db,            m6db },              // Cs
00112         { sqrt_2_3,        msqrt_1_3 },         // LS
00113         { msqrt_1_3,       sqrt_2_3 },          // RS
00114     },
00115 
00116 // 3F4R.1 L                R
00117     {
00118         { 1,               0 },                 // L
00119         { 0,               1 },                 // R
00120         { m3db,            m3db },              // C
00121         { 0,               0 },                 // LFE
00122         { sqrt_2_3by3db,   msqrt_1_3bym3db },   // Rls
00123         { msqrt_1_3bym3db, sqrt_2_3by3db },     // Rrs
00124         { sqrt_2_3by3db,   msqrt_1_3bym3db },   // LS
00125         { msqrt_1_3bym3db, sqrt_2_3by3db },     // RS
00126     }
00127 };
00128 
00129 static const float s51_matrix[3][8][6] =
00130 {
00131     // 3F2R.1 in -> 3F2R.1 out
00132     // L  R  C  LFE         LS       RS
00133     {
00134         { 1, 0, 0, 0,       0,       0 },     // L
00135         { 0, 1, 0, 0,       0,       0 },     // R
00136         { 0, 0, 1, 0,       0,       0 },     // C
00137         { 0, 0, 0, 1,       0,       0 },     // LFE
00138         { 0, 0, 0, 0,       1,       0 },     // LS
00139         { 0, 0, 0, 0,       0,       1 },     // RS
00140     },
00141     // 3F3R.1 in -> 3F2R.1 out
00142     // Used coefficient found at http://www.yamahaproaudio.com/training/self_training/data/smqr_en.pdf
00143     // L  R  C  LFE         LS       RS
00144     {
00145         { 1, 0, 0, 0,       0,       0 },     // L
00146         { 0, 1, 0, 0,       0,       0 },     // R
00147         { 0, 0, 1, 0,       0,       0 },     // C
00148         { 0, 0, 0, 1,       0,       0 },     // LFE
00149         { 0, 0, 0, 0,       m3db,    m3db },  // Cs
00150         { 0, 0, 0, 0,       1,       0 },     // LS
00151         { 0, 0, 0, 0,       0,       1 },     // RS
00152     },
00153     // 3F4R.1 -> 3F2R.1 out
00154     // L  R  C  LFE         LS       RS
00155     {
00156         { 1, 0, 0, 0,       0,       0 },     // L
00157         { 0, 1, 0, 0,       0,       0 },     // R
00158         { 0, 0, 1, 0,       0,       0 },     // C
00159         { 0, 0, 0, 1,       0,       0 },     // LFE
00160         { 0, 0, 0, 0,       m3db,    0 },     // Rls
00161         { 0, 0, 0, 0,       0,       m3db },  // Rrs
00162         { 0, 0, 0, 0,       m3db,    0 },     // LS
00163         { 0, 0, 0, 0,       0,       m3db },  // RS
00164     }
00165 };
00166 
00167 int AudioOutputDownmix::DownmixFrames(int channels_in, int  channels_out,
00168                                       float *dst, float *src, int frames)
00169 {
00170     if (channels_in < channels_out)
00171         return -1;
00172 
00173     //VBAUDIO(LOC + QString("Downmixing %1 frames (in:%2 out:%3)")
00174     //    .arg(frames).arg(channels_in).arg(channels_out));
00175     if (channels_out == 2)
00176     {
00177         float tmp;
00178         int index = channels_in - 1;
00179         for (int n=0; n < frames; n++)
00180         {
00181             for (int i=0; i < channels_out; i++)
00182             {
00183                 tmp = 0.0f;
00184                 for (int j=0; j < channels_in; j++)
00185                     tmp += src[j] * stereo_matrix[index][j][i];
00186                 *dst++ = tmp;
00187             }
00188             src += channels_in;
00189         }
00190     }
00191     else if (channels_out == 6)
00192     {
00193         float tmp;
00194         int index = channels_in - 6;
00195         for (int n=0; n < frames; n++)
00196         {
00197             for (int i=0; i < channels_out; i++)
00198             {
00199                 tmp = 0.0f;
00200                 for (int j=0; j < channels_in; j++)
00201                     tmp += src[j] * s51_matrix[index][j][i];
00202                 *dst++ = tmp;
00203             }
00204             src += channels_in;
00205         }
00206     }
00207     else
00208         return -1;
00209 
00210     return frames;
00211 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends