📄 mixer.cpp
字号:
#include "stdafx.h"
#include "mixer.h"
const double TmixerMatrix::LEVEL_PLUS6DB=2.0;
const double TmixerMatrix::LEVEL_PLUS3DB=1.4142135623730951;
const double TmixerMatrix::LEVEL_3DB =0.7071067811865476;
const double TmixerMatrix::LEVEL_45DB =0.5946035575013605;
const double TmixerMatrix::LEVEL_6DB =0.5;
TmixerMatrix::TmixerMatrix(void)
{
for (int i=0;i<NCHANNELS;i++)
for (int j=0;j<NCHANNELS;j++)
matrix[i][j]=0;
}
TsampleFormat TmixerMatrix::calc_matrix(const TsampleFormat &infmt,const TmixerSettings *cfg)
{
TsampleFormat outfmt=infmt;
cfg->setFormatOut(outfmt,infmt);
int in_ch = infmt.makeChannelMask();
int out_ch = outfmt.makeChannelMask();
int in_nfront = infmt.nfront();
int in_nrear = infmt.nrear();
int out_nfront = outfmt.nfront();
int out_nrear = outfmt.nrear();
double clev=cfg->clev/100.0; // central mix level
double slev=cfg->slev/100.0; // surround mix level
double lfelev=cfg->lfelev/100.0; // lfe mix level
if (cfg->customMatrix)
for (int i=0;i<6;i++)
for (int j=0;j<6;j++)
matrix[i][j]=((int (*)[6])&cfg->matrix00)[i][j]/100000.0;
else
{
memset(&matrix, 0, sizeof(mixer_matrix_t));
if (infmt.dolby & outfmt.dolby) // Dolby modes are backwards-compatible
{
matrix[CH_L][CH_L] = 1;
matrix[CH_R][CH_R] = 1;
}
else if (outfmt.dolby) // Downmix to Dolby Surround/ProLogic/ProLogicII
{
if (in_nfront >= 2)
{
matrix[CH_L][CH_L] = 1;
matrix[CH_R][CH_R] = 1;
}
if (in_nfront != 2)
{
matrix[CH_C][CH_L] = 0.7071 * clev;
matrix[CH_C][CH_R] = 0.7071 * clev;
}
if (in_nrear == 1)
{
matrix[CH_S][CH_L] = -0.7071 * slev;
matrix[CH_S][CH_R] = +0.7071 * slev;
}
else if (in_nrear == 2)
{
switch (outfmt.dolby)
{
case TsampleFormat::DOLBY_PROLOGICII:
matrix[CH_SL][CH_L] = -0.8660*slev;
matrix[CH_SR][CH_L] = -0.5000*slev;
matrix[CH_SL][CH_R] = +0.5000*slev;
matrix[CH_SR][CH_R] = +0.8660*slev;
break;
case TsampleFormat::DOLBY_SURROUND:
case TsampleFormat::DOLBY_PROLOGIC:
default:
matrix[CH_SL][CH_L] = -slev;
matrix[CH_SR][CH_L] = -slev;
matrix[CH_SL][CH_R] = +slev;
matrix[CH_SR][CH_R] = +slev;
break;
}
}
}
else // A/52 standart mixes
{
// direct route equal channels
if (in_ch & out_ch & SPEAKER_FRONT_LEFT) matrix[CH_L ][CH_L ]=1.0;
if (in_ch & out_ch & SPEAKER_FRONT_RIGHT) matrix[CH_R ][CH_R ]=1.0;
if (in_ch & out_ch & SPEAKER_FRONT_CENTER) matrix[CH_C ][CH_C ]=clev;
if (in_ch & out_ch & SPEAKER_BACK_LEFT) matrix[CH_SL][CH_SL]=slev;
if (in_ch & out_ch & SPEAKER_BACK_RIGHT) matrix[CH_SR][CH_SR]=slev;
// calc matrix for fbw channels
if (out_nfront == 1)
{
if (in_nfront != 1)
{
matrix[CH_L][CH_M]=LEVEL_3DB;
matrix[CH_R][CH_M]=LEVEL_3DB;
}
if (in_nfront == 3)
{
matrix[CH_C][CH_M] = clev * LEVEL_PLUS3DB;
}
if (in_nrear == 1)
{
matrix[CH_S][CH_M] = slev * LEVEL_3DB;
}
else
{
matrix[CH_SL][CH_M] = slev * LEVEL_3DB;
matrix[CH_SR][CH_M] = slev * LEVEL_3DB;
}
}
else // not mono modes
{
if (out_nfront == 2)
{
if (in_nfront == 1)
{
matrix[CH_M][CH_L] = LEVEL_3DB;
matrix[CH_M][CH_R] = LEVEL_3DB;
}
else if (in_nfront == 3)
{
matrix[CH_C][CH_L] = clev;
matrix[CH_C][CH_R] = clev;
}
}
if (in_nrear == 1)
{
if (out_nrear == 0)
{
matrix[CH_S][CH_L] = slev * LEVEL_3DB;
matrix[CH_S][CH_R] = slev * LEVEL_3DB;
}
else if (out_nrear == 2)
{
matrix[CH_S][CH_SL] = slev * LEVEL_3DB;
matrix[CH_S][CH_SR] = slev * LEVEL_3DB;
}
}
else if (in_nrear == 2)
{
if (out_nrear == 0)
{
matrix[CH_SL][CH_L] = slev;
matrix[CH_SR][CH_R] = slev;
}
else if (out_nrear == 1)
{
matrix[CH_SL][CH_S] = slev * LEVEL_3DB;
matrix[CH_SR][CH_S] = slev * LEVEL_3DB;
}
}
}
}
// Expand stereo & Voice control
bool expand_stereo_allowed = cfg->expandStereo && !in_nrear;
bool voice_control_allowed = cfg->voiceControl && (in_nfront == 2);
if ((voice_control_allowed || expand_stereo_allowed) && !outfmt.dolby)
{
if (voice_control_allowed && out_nfront != 2)
{
// C' = clev * (L + R) * LEVEL_3DB
matrix[CH_L][CH_M] = clev * LEVEL_3DB;
matrix[CH_R][CH_M] = clev * LEVEL_3DB;
}
if (expand_stereo_allowed && in_nfront == 2 && out_nrear)
{
if (out_nrear == 1)
{
// S' = slev * (L - R)
matrix[CH_L][CH_S] = + slev;
matrix[CH_R][CH_S] = - slev;
}
if (out_nrear == 2)
{
// SL' = slev * 1/2 (L - R)
// SR' = slev * 1/2 (R - L)
matrix[CH_L][CH_SL] = + 0.5 * slev;
matrix[CH_R][CH_SL] = - 0.5 * slev;
matrix[CH_L][CH_SR] = - 0.5 * slev;
matrix[CH_R][CH_SR] = + 0.5 * slev;
}
}
if (in_nfront != 1)
{
if (expand_stereo_allowed && voice_control_allowed)
{
// L' = L * 1/2 (slev + clev) - R * 1/2 (slev - clev)
// R' = R * 1/2 (slev + clev) - L * 1/2 (slev - clev)
matrix[CH_L][CH_L] = + 0.5 * (slev + clev);
matrix[CH_R][CH_L] = - 0.5 * (slev - clev);
matrix[CH_L][CH_R] = - 0.5 * (slev - clev);
matrix[CH_R][CH_R] = + 0.5 * (slev + clev);
}
else if (expand_stereo_allowed)
{
matrix[CH_L][CH_L] = + 0.5 * (slev + 1);
matrix[CH_R][CH_L] = - 0.5 * (slev - 1);
matrix[CH_L][CH_R] = - 0.5 * (slev - 1);
matrix[CH_R][CH_R] = + 0.5 * (slev + 1);
}
else // if (voice_control_allowed)
{
matrix[CH_L][CH_L] = + 0.5 * (1 + clev);
matrix[CH_R][CH_L] = - 0.5 * (1 - clev);
matrix[CH_L][CH_R] = - 0.5 * (1 - clev);
matrix[CH_R][CH_R] = + 0.5 * (1 + clev);
}
}
}
// LFE mixing
if (in_ch & out_ch & SPEAKER_LOW_FREQUENCY)
matrix[CH_LFE][CH_LFE] = lfelev;
// mix LFE into front channels if exists in input
// and absent in output
if (in_ch & ~out_ch & SPEAKER_LOW_FREQUENCY)
{
if (out_nfront > 1)
{
matrix[CH_LFE][CH_L] = lfelev;
matrix[CH_LFE][CH_R] = lfelev;
}
else
matrix[CH_LFE][CH_C] = lfelev;
}
}
if (cfg->normalizeMatrix)
{
double levels[NCHANNELS] = { 0, 0, 0, 0, 0, 0 };
double max_level;
double norm;
int i, j;
for (i = 0; i < NCHANNELS; i++)
for (j = 0; j < NCHANNELS; j++)
levels[i] += matrix[j][i];
max_level = levels[0];
for (i = 1; i < NCHANNELS; i++)
if (levels[i] > max_level)
max_level = levels[i];
if (max_level > 0)
norm = 1.0/max_level;
else
norm = 1.0;
for (i = 0; i < NCHANNELS; i++)
for (j = 0; j < NCHANNELS; j++)
matrix[j][i] *= norm;
}
for (int i = 0; i < NCHANNELS; i++)
for (int j = 0; j < NCHANNELS; j++)
matrix[j][i] = limit(matrix[j][i],-4.0,4.0);
return outfmt;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -