fmodex/fmod/lib/neural_thx/Neural_THX_522_Encode.c

189 lines
8.4 KiB
C
Executable file

// _____________
// _________________
// _____/~\___________/\_
// ______/\_/\_________/\____
// ______/\___/\_______/\______
// _____/\_____/\_____/\_______
// ____/\_______/\___/\________
// __/\_________/\_/\________
// /\___________/~\_______
// ___________________
// _____________
//
//***************************************************************************//
//* *//
//* Project : Neural Audio - THX *//
//* File : Neural_THX_522_Encode.c *//
//* Description : Neural Surround Downmix implementation *//
//* Author(s) : Jeff Thompson *//
//* *//
//* Copyright (c) Neural Audio Corp. 2008 *//
//* *//
//***************************************************************************//
#include "Neural_THX_Encoders.h"
#include <stdlib.h>
//***************************************************************************//
//* Neural_THX_522_Encode_INIT(...) *//
//***************************************************************************//
int Neural_THX_522_Encode_INIT(unsigned int Framesize,
unsigned int ChanConfig,
unsigned int SampleRate,
Neural_THX_522_Encode_Struct * pParams)
{
//Forward and inverse overlapped FFT's
FFT_Overlapped_Stereo_INIT(&pParams->FFTSourceLR,pParams->TempBuffer0,pParams->TempBuffer1,NEURAL_FRAMESIZE);
FFT_Overlapped_INIT(&pParams->FFTSourceC,pParams->TempBuffer0,pParams->TempBuffer1,NEURAL_FRAMESIZE);
FFT_Overlapped_Stereo_INIT(&pParams->FFTSourceLsRs,pParams->TempBuffer0,pParams->TempBuffer1,NEURAL_FRAMESIZE);
IFFT_Overlapped_Stereo_INIT(&pParams->InvFFTDownmixLR,pParams->TempBuffer0,pParams->TempBuffer1,NEURAL_FRAMESIZE);
//Initialize phase shifts
FreqDomain_PhaseShift_INIT(-22.5f,NEURAL_FRAMESIZE,&pParams->PhaseShift_L);
FreqDomain_PhaseShift_INIT(+22.5f,NEURAL_FRAMESIZE,&pParams->PhaseShift_R);
FreqDomain_PhaseShift_INIT(-90.0f,NEURAL_FRAMESIZE,&pParams->PhaseShift_Ls);
FreqDomain_PhaseShift_INIT(+90.0f,NEURAL_FRAMESIZE,&pParams->PhaseShift_Rs);
LR4_LP_INIT(&pParams->LFE_LP);
//Init final limiters
Limiter_INIT(pParams->TempBuffer0,&pParams->FinalLimiterL);
Limiter_INIT(pParams->TempBuffer0,&pParams->FinalLimiterR);
return NRLSUR_OK;
}
//***************************************************************************//
//* Neural_THX_522_Encode(...) *//
//***************************************************************************//
int Neural_THX_522_Encode(float * PtrInL,
float * PtrInR,
float * PtrInC,
float * PtrInLFE,
float * PtrInLs,
float * PtrInRs,
float * PtrOutL,
float * PtrOutR,
THX_bool UseFinalLimiting,
float LFE_Cutoff,
unsigned int Framesize,
unsigned int ChanConfig,
unsigned int SampleRate,
Neural_THX_522_Encode_Struct * pParams)
{
//Neural Surround Downmix
//***********************************************************
//***** Low-pass filter the LFE channel (if selected) *****
//***********************************************************
if(LFE_Cutoff > 40.0f && LFE_Cutoff < 200.0f){
LR4_LP(PtrInLFE,PtrInLFE,LFE_Cutoff,NEURAL_FRAMESIZE,SampleRate,&pParams->LFE_LP);
}
//First sum LFE channel into Center channel
Add2(PtrInC,PtrInLFE,PtrInC,NEURAL_FRAMESIZE);
//****************************************************************************************************
//***** Begin downmix by transforming all signals to frequency domain and performing phase shift *****
//****************************************************************************************************
//Convert all input channels to freq domain
//L-R channels
FFT_Overlapped_Stereo(PtrInL,pParams->Input_RealL,pParams->Input_ImagL,
PtrInR,pParams->Input_RealR,pParams->Input_ImagR,
NEURAL_FRAMESIZE,&pParams->FFTSourceLR);
//C channel
FFT_Overlapped(PtrInC,pParams->Input_RealC,pParams->Input_ImagC,
NEURAL_FRAMESIZE,&pParams->FFTSourceC);
//Ls-Rs channels
FFT_Overlapped_Stereo(PtrInLs,pParams->Input_RealLs,pParams->Input_ImagLs,
PtrInRs,pParams->Input_RealRs,pParams->Input_ImagRs,
NEURAL_FRAMESIZE,&pParams->FFTSourceLsRs);
//Phase shift L channel
FreqDomain_PhaseShift(pParams->Input_RealL,pParams->Input_ImagL,
pParams->Input_RealL,pParams->Input_ImagL,
-22.5f,NEURAL_FRAMESIZE,SampleRate,&pParams->PhaseShift_L);
//Phase shift R channel
FreqDomain_PhaseShift(pParams->Input_RealR,pParams->Input_ImagR,
pParams->Input_RealR,pParams->Input_ImagR,
+22.5f,NEURAL_FRAMESIZE,SampleRate,&pParams->PhaseShift_R);
//Phase shift Ls channel
FreqDomain_PhaseShift(pParams->Input_RealLs,pParams->Input_ImagLs,
pParams->Input_RealLs,pParams->Input_ImagLs,
-90.0f,NEURAL_FRAMESIZE,SampleRate,&pParams->PhaseShift_Ls);
//Phase shift Rs channel
FreqDomain_PhaseShift(pParams->Input_RealRs,pParams->Input_ImagRs,
pParams->Input_RealRs,pParams->Input_ImagRs,
+90.0f,NEURAL_FRAMESIZE,SampleRate,&pParams->PhaseShift_Rs);
//Scale center and lfe channels by -3dB
ScaleArray(pParams->Input_RealC,(float)MINUS_3DB,NEURAL_FRAMESIZE);
ScaleArray(pParams->Input_ImagC,(float)MINUS_3DB,NEURAL_FRAMESIZE);
//Add center and lfe channels to left/right phase shifted channels
//L channel
Add2(pParams->Input_RealL,pParams->Input_RealC,pParams->Downmix_RealL,NEURAL_FRAMESIZE);
Add2(pParams->Input_ImagL,pParams->Input_ImagC,pParams->Downmix_ImagL,NEURAL_FRAMESIZE);
//R channel
Add2(pParams->Input_RealR,pParams->Input_RealC,pParams->Downmix_RealR,NEURAL_FRAMESIZE);
Add2(pParams->Input_ImagR,pParams->Input_ImagC,pParams->Downmix_ImagR,NEURAL_FRAMESIZE);
//***********************************************************
//***** Combine the front channels with the surrounds *****
//***********************************************************
ScaleArray(pParams->Input_RealLs,(float)CROSSSHARENORM,NEURAL_FRAMESIZE);
ScaleArray(pParams->Input_ImagLs,(float)CROSSSHARENORM,NEURAL_FRAMESIZE);
ScaleArray(pParams->Input_RealRs,(float)CROSSSHARENORM,NEURAL_FRAMESIZE);
ScaleArray(pParams->Input_ImagRs,(float)CROSSSHARENORM,NEURAL_FRAMESIZE);
Add2(pParams->Downmix_RealL,pParams->Input_RealLs,pParams->Downmix_RealL,NEURAL_FRAMESIZE);
Add2(pParams->Downmix_ImagL,pParams->Input_ImagLs,pParams->Downmix_ImagL,NEURAL_FRAMESIZE);
Add2(pParams->Downmix_RealR,pParams->Input_RealRs,pParams->Downmix_RealR,NEURAL_FRAMESIZE);
Add2(pParams->Downmix_ImagR,pParams->Input_ImagRs,pParams->Downmix_ImagR,NEURAL_FRAMESIZE);
CopyArray(pParams->Input_RealLs,pParams->TempBuffer0,NEURAL_FRAMESIZE);
ScaleArray(pParams->TempBuffer0,-CROSSSHARECONSTANT,Framesize);
Add2(pParams->Downmix_RealR,pParams->TempBuffer0,pParams->Downmix_RealR,NEURAL_FRAMESIZE);
CopyArray(pParams->Input_ImagLs,pParams->TempBuffer0,NEURAL_FRAMESIZE);
ScaleArray(pParams->TempBuffer0,-CROSSSHARECONSTANT,Framesize);
Add2(pParams->Downmix_ImagR,pParams->TempBuffer0,pParams->Downmix_ImagR,NEURAL_FRAMESIZE);
CopyArray(pParams->Input_RealRs,pParams->TempBuffer0,NEURAL_FRAMESIZE);
ScaleArray(pParams->TempBuffer0,-CROSSSHARECONSTANT,Framesize);
Add2(pParams->Downmix_RealL,pParams->TempBuffer0,pParams->Downmix_RealL,NEURAL_FRAMESIZE);
CopyArray(pParams->Input_ImagRs,pParams->TempBuffer0,NEURAL_FRAMESIZE);
ScaleArray(pParams->TempBuffer0,-CROSSSHARECONSTANT,Framesize);
Add2(pParams->Downmix_ImagL,pParams->TempBuffer0,pParams->Downmix_ImagL,NEURAL_FRAMESIZE);
//***********************************************************
//***** Inverse filterbank back to time signals *****
//***********************************************************
IFFT_Overlapped_Stereo(pParams->Downmix_RealL,pParams->Downmix_ImagL,PtrOutL,
pParams->Downmix_RealR,pParams->Downmix_ImagR,PtrOutR,
NEURAL_FRAMESIZE,&pParams->InvFFTDownmixLR);
if(UseFinalLimiting){
//Perform final limiting on the output signals
Limiter(PtrOutL,PtrOutL,
(float)AUDIO_VAL_MAX,
-6.0f,-0.1f,
0.0f,500.0f,
NEURAL_FRAMESIZE,SampleRate,&pParams->FinalLimiterL);
Limiter(PtrOutR,PtrOutR,
(float)AUDIO_VAL_MAX,
-6.0f,-0.1f,
0.0f,500.0f,
NEURAL_FRAMESIZE,SampleRate,&pParams->FinalLimiterR);
}
//That's all folks
SaturateArray(PtrOutL,(float)AUDIO_VAL_MAX,NEURAL_FRAMESIZE);
SaturateArray(PtrOutR,(float)AUDIO_VAL_MAX,NEURAL_FRAMESIZE);
return NRLSUR_OK;
}