mirror of
https://github.com/DaedalusX64/daedalus.git
synced 2025-04-02 10:21:48 -04:00
649 lines
19 KiB
C++
649 lines
19 KiB
C++
/*
|
||
Copyright (C) 2003 Azimer
|
||
Copyright (C) 2001,2006 StrmnNrmn
|
||
|
||
This program is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU General Public License
|
||
as published by the Free Software Foundation; either version 2
|
||
of the License, or (at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program; if not, write to the Free Software
|
||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
||
*/
|
||
|
||
//
|
||
// N.B. This source code is derived from Azimer's Audio plugin (v0.55?)
|
||
// and modified by StrmnNrmn to work with Daedalus PSP. Thanks Azimer!
|
||
// Drop me a line if you get chance :)
|
||
//
|
||
|
||
#include "stdafx.h"
|
||
|
||
#include <string.h>
|
||
|
||
#include "audiohle.h"
|
||
#include "AudioHLEProcessor.h"
|
||
|
||
#include "Debug/DBGConsole.h"
|
||
|
||
#include "Math/MathUtil.h"
|
||
#include "Utility/FastMemcpy.h"
|
||
|
||
inline s32 FixedPointMul16( s32 a, s32 b )
|
||
{
|
||
return s32( ( a * b ) >> 16 );
|
||
}
|
||
|
||
static void SPNOOP( AudioHLECommand command )
|
||
{
|
||
DBGConsole_Msg( 0, "AudioHLE: Unknown/Unimplemented Audio Command %i in ABI 3", command.cmd );
|
||
}
|
||
|
||
static void SETVOL3( AudioHLECommand command )
|
||
{
|
||
u8 Flags {(u8)(command.cmd0 >> 0x10)};
|
||
if (Flags & 0x4)
|
||
{ // 288
|
||
if (Flags & 0x2)
|
||
{ // 290
|
||
gAudioHLEState.VolLeft = (s16)command.cmd0; // 0x50
|
||
gAudioHLEState.EnvDry = (s16)(command.cmd1 >> 16); // 0x4E
|
||
gAudioHLEState.EnvWet = (s16)command.cmd1; // 0x4C
|
||
}
|
||
else
|
||
{
|
||
gAudioHLEState.VolTrgRight = (s16)command.cmd0; // 0x46
|
||
//gAudioHLEState.VolRampRight = (u16)(command.cmd1 >> 16) | (s32)(s16)(command.cmd1 << 0x10);
|
||
gAudioHLEState.VolRampRight = command.cmd1; // 0x48/0x4A
|
||
}
|
||
}
|
||
else
|
||
{
|
||
gAudioHLEState.VolTrgLeft = (s16)command.cmd0; // 0x40
|
||
gAudioHLEState.VolRampLeft = command.cmd1; // 0x42/0x44
|
||
}
|
||
}
|
||
|
||
static void ENVMIXER3( AudioHLECommand command )
|
||
{
|
||
u8 flags {(u8)((command.cmd0 >> 16) & 0xff)};
|
||
u32 addy {(command.cmd1 & 0xFFFFFF)};
|
||
|
||
s16 *inp {(s16 *)(gAudioHLEState.Buffer+0x4F0)};
|
||
s16 *out {(s16 *)(gAudioHLEState.Buffer+0x9D0)};
|
||
s16 *aux1 {(s16 *)(gAudioHLEState.Buffer+0xB40)};
|
||
s16 *aux2 {(s16 *)(gAudioHLEState.Buffer+0xCB0)};
|
||
s16 *aux3 {(s16 *)(gAudioHLEState.Buffer+0xE20)};
|
||
|
||
s32 MainR {},MainL {},AuxR {}, AuxL {};
|
||
s32 i1 {}, o1 {}, a1 {}, a2 {}, a3 {};
|
||
s32 LAdder {}, LAcc {}, LVol {}, RAdder {}, RAcc {}, RVol {};
|
||
s16 RSig {}, LSig {}, Wet {}, Dry {}, LTrg {}, RTrg {};
|
||
|
||
gAudioHLEState.VolRight = (s16)command.cmd0;
|
||
|
||
s16* buff {(s16*)(rdram+addy)};
|
||
|
||
if (flags & A_INIT)
|
||
{
|
||
LAdder = gAudioHLEState.VolRampLeft / 8;
|
||
LAcc = 0;
|
||
LVol = gAudioHLEState.VolLeft;
|
||
LSig = (s16)(gAudioHLEState.VolRampLeft >> 16);
|
||
|
||
RAdder = gAudioHLEState.VolRampRight / 8;
|
||
RAcc = 0;
|
||
RVol = gAudioHLEState.VolRight;
|
||
RSig = (s16)(gAudioHLEState.VolRampRight >> 16);
|
||
|
||
Wet = gAudioHLEState.EnvWet;
|
||
Dry = gAudioHLEState.EnvDry; // Save Wet/Dry values
|
||
LTrg = gAudioHLEState.VolTrgLeft; RTrg = gAudioHLEState.VolTrgRight; // Save Current Left/Right Targets
|
||
}
|
||
else
|
||
{
|
||
Wet = *(s16 *)(buff + 0); // 0-1
|
||
Dry = *(s16 *)(buff + 2); // 2-3
|
||
LTrg = *(s16 *)(buff + 4); // 4-5
|
||
RTrg = *(s16 *)(buff + 6); // 6-7
|
||
LAdder = *(s32 *)(buff + 8); // 8-9 (buff is a 16bit pointer)
|
||
RAdder = *(s32 *)(buff + 10); // 10-11
|
||
LAcc = *(s32 *)(buff + 12); // 12-13
|
||
RAcc = *(s32 *)(buff + 14); // 14-15
|
||
LVol = *(s32 *)(buff + 16); // 16-17
|
||
RVol = *(s32 *)(buff + 18); // 18-19
|
||
LSig = *(s16 *)(buff + 20); // 20-21
|
||
RSig = *(s16 *)(buff + 22); // 22-23
|
||
//u32 test = *(s32 *)(buff + 24); // 22-23
|
||
//if (test != 0x13371337)
|
||
// __asm int 3;
|
||
}
|
||
|
||
|
||
//if(!(flags&A_AUX)) {
|
||
// AuxIncRate=0;
|
||
// aux2=aux3=zero;
|
||
//}
|
||
|
||
for (s32 y {}; y < (0x170/2); y++) {
|
||
|
||
// Left
|
||
LAcc += LAdder;
|
||
LVol += (LAcc >> 16);
|
||
LAcc &= 0xFFFF;
|
||
|
||
// Right
|
||
RAcc += RAdder;
|
||
RVol += (RAcc >> 16);
|
||
RAcc &= 0xFFFF;
|
||
// ****************************************************************
|
||
// Clamp Left
|
||
if (LSig >= 0) { // VLT
|
||
if (LVol > LTrg) {
|
||
LVol = LTrg;
|
||
}
|
||
} else { // VGE
|
||
if (LVol < LTrg) {
|
||
LVol = LTrg;
|
||
}
|
||
}
|
||
|
||
// Clamp Right
|
||
if (RSig >= 0) { // VLT
|
||
if (RVol > RTrg) {
|
||
RVol = RTrg;
|
||
}
|
||
} else { // VGE
|
||
if (RVol < RTrg) {
|
||
RVol = RTrg;
|
||
}
|
||
}
|
||
// ****************************************************************
|
||
MainL = ((Dry * LVol) + 0x4000) >> 15;
|
||
MainR = ((Dry * RVol) + 0x4000) >> 15;
|
||
|
||
o1 = out [y^1];
|
||
a1 = aux1[y^1];
|
||
i1 = inp [y^1];
|
||
|
||
o1+=((i1*MainL)+0x4000)>>15;
|
||
a1+=((i1*MainR)+0x4000)>>15;
|
||
|
||
// ****************************************************************
|
||
|
||
o1 = Saturate<s16>( o1 );
|
||
a1 = Saturate<s16>( a1 );
|
||
|
||
// ****************************************************************
|
||
|
||
out[y^1]=o1;
|
||
aux1[y^1]=a1;
|
||
|
||
// ****************************************************************
|
||
//if (!(flags&A_AUX)) {
|
||
a2 = aux2[y^1];
|
||
a3 = aux3[y^1];
|
||
|
||
AuxL = ((Wet * LVol) + 0x4000) >> 15;
|
||
AuxR = ((Wet * RVol) + 0x4000) >> 15;
|
||
|
||
a2+=((i1*AuxL)+0x4000)>>15;
|
||
a3+=((i1*AuxR)+0x4000)>>15;
|
||
|
||
a2 = Saturate<s16>( a2 );
|
||
a3 = Saturate<s16>( a3 );
|
||
|
||
aux2[y^1]=a2;
|
||
aux3[y^1]=a3;
|
||
}
|
||
//}
|
||
|
||
*(s16 *)(buff + 0) = Wet; // 0-1
|
||
*(s16 *)(buff + 2) = Dry; // 2-3
|
||
*(s16 *)(buff + 4) = LTrg; // 4-5
|
||
*(s16 *)(buff + 6) = RTrg; // 6-7
|
||
*(s32 *)(buff + 8) = LAdder; // 8-9 (buff is a 16bit pointer)
|
||
*(s32 *)(buff + 10) = RAdder; // 10-11
|
||
*(s32 *)(buff + 12) = LAcc; // 12-13
|
||
*(s32 *)(buff + 14) = RAcc; // 14-15
|
||
*(s32 *)(buff + 16) = LVol; // 16-17
|
||
*(s32 *)(buff + 18) = RVol; // 18-19
|
||
*(s16 *)(buff + 20) = LSig; // 20-21
|
||
*(s16 *)(buff + 22) = RSig; // 22-23
|
||
//*(u32 *)(buff + 24) = 0x13371337; // 22-23
|
||
}
|
||
|
||
static void CLEARBUFF3( AudioHLECommand command )
|
||
{
|
||
u16 addr = (u16)(command.cmd0 & 0xffff);
|
||
u16 count = (u16)(command.cmd1 & 0xffff);
|
||
memset(gAudioHLEState.Buffer+addr+0x4f0, 0, count);
|
||
}
|
||
|
||
static void MIXER3( AudioHLECommand command )
|
||
{
|
||
// Needs accuracy verification...
|
||
u16 dmemin = (u16)(command.cmd1 >> 0x10) + 0x4f0;
|
||
u16 dmemout = (u16)(command.cmd1 & 0xFFFF) + 0x4f0;
|
||
//u8 flags = (u8)((command.cmd0 >> 16) & 0xff);
|
||
s32 gain = (s16)(command.cmd0 & 0xFFFF);
|
||
|
||
gAudioHLEState.Mixer( dmemout, dmemin, gain, 0x170 ); // NB - did mult gain by 2 above, then shifted by 16 inside mixer.
|
||
}
|
||
|
||
static void LOADBUFF3( AudioHLECommand command )
|
||
{
|
||
u32 v0 {};
|
||
u32 cnt {(((command.cmd0 >> 0xC)+3)&0xFFC)};
|
||
v0 = (command.cmd1 & 0xfffffc);
|
||
u32 src {(command.cmd0&0xffc)+0x4f0};
|
||
memcpy (gAudioHLEState.Buffer+src, rdram+v0, cnt);
|
||
|
||
}
|
||
|
||
static void SAVEBUFF3( AudioHLECommand command )
|
||
{
|
||
u32 v0 {};
|
||
u32 cnt {(((command.cmd0 >> 0xC)+3)&0xFFC)};
|
||
v0 = (command.cmd1 & 0xfffffc);
|
||
u32 src {(command.cmd0&0xffc)+0x4f0};
|
||
|
||
memcpy (rdram+v0, gAudioHLEState.Buffer+src, cnt);
|
||
|
||
}
|
||
|
||
// Loads an ADPCM table - Works 100% Now 03-13-01
|
||
static void LOADADPCM3( AudioHLECommand command )
|
||
{
|
||
u32 address(command.Abi3LoadADPCM.Address );// + gAudioHLEState.Segments[(command.cmd1>>24)&0xf];
|
||
u16 count( command.Abi3LoadADPCM.Count );
|
||
|
||
gAudioHLEState.LoadADPCM( address, count );
|
||
}
|
||
|
||
// Needs accuracy verification...
|
||
static void DMEMMOVE3( AudioHLECommand command )
|
||
{
|
||
u16 src( command.Abi3DmemMove.Src );
|
||
u16 dst( command.Abi3DmemMove.Dst );
|
||
u16 count( command.Abi3DmemMove.Count );
|
||
|
||
gAudioHLEState.DmemMove( dst + 0x4f0, src + 0x4f0, count );
|
||
}
|
||
|
||
static void SETLOOP3( AudioHLECommand command )
|
||
{
|
||
u32 loopval( command.Abi3SetLoop.LoopVal );// + gAudioHLEState.Segments[(command.cmd1>>24)&0xf];
|
||
|
||
gAudioHLEState.SetLoop( loopval );
|
||
}
|
||
|
||
// Verified to be 100% Accurate...
|
||
static void ADPCM3( AudioHLECommand command )
|
||
{
|
||
u8 Flags {(u8)((command.cmd1>>0x1c)&0xff)};
|
||
//u16 Gain=(u16)(command.cmd0&0xffff);
|
||
u32 Address {(command.cmd0 & 0xffffff)};// + gAudioHLEState.Segments[(command.cmd1>>24)&0xf];
|
||
u32 inPtr {(command.cmd1>>12)&0xf};
|
||
//s16 *out=(s16 *)(testbuff+(gAudioHLEState.OutBuffer>>2));
|
||
s16 *out {(s16 *)(gAudioHLEState.Buffer+(command.cmd1&0xfff)+0x4f0)};
|
||
//u8 *in=(u8 *)(gAudioHLEState.Buffer+((command.cmd1>>12)&0xf)+0x4f0);
|
||
s16 count {(s16)((command.cmd1 >> 16)&0xfff)};
|
||
u8 icode {}, code {};
|
||
s32 vscale {};
|
||
u16 index {}, j {};
|
||
s32 a[8] {};
|
||
s16 *book1 {},*book2 {};
|
||
|
||
memset(out,0,32);
|
||
|
||
if(!(Flags&0x1))
|
||
{
|
||
memcpy(out,&rdram[(Flags&0x2) ? gAudioHLEState.LoopVal : Address],32);
|
||
}
|
||
|
||
s32 l1 {out[15]};
|
||
s32 l2 {out[14]};
|
||
s32 inp1[8] {};
|
||
s32 inp2[8] {};
|
||
out+=16;
|
||
while(count>0)
|
||
{
|
||
// the first interation through, these values are
|
||
// either 0 in the case of A_INIT, from a special
|
||
// area of memory in the case of A_LOOP or just
|
||
// the values we calculated the last time
|
||
|
||
code = gAudioHLEState.Buffer[(0x4f0+inPtr)^3];
|
||
index = code&0xf;
|
||
index <<= 4; // index into the adpcm code table
|
||
book1 = (s16 *)&gAudioHLEState.ADPCMTable[index];
|
||
book2 = book1+8;
|
||
code >>= 4; // upper nibble is scale
|
||
vscale = (0x8000>>((12-code)-1)); // very strange. 0x8000 would be .5 in 16:16 format
|
||
// so this appears to be a fractional scale based
|
||
// on the 12 based inverse of the scale value. note
|
||
// that this could be negative, in which case we do
|
||
// not use the calculated vscale value... see the
|
||
// if(code>12) check below
|
||
|
||
inPtr++; // coded adpcm data lies next
|
||
j = 0;
|
||
while(j<8) // loop of 8, for 8 coded nibbles from 4 bytes
|
||
// which yields 8 s16 pcm values
|
||
{
|
||
icode = gAudioHLEState.Buffer[(0x4f0+inPtr)^3];
|
||
inPtr++;
|
||
|
||
inp1[j]=(s16)((icode&0xf0)<<8); // this will in effect be signed
|
||
|
||
// Conker and Banjo set this!
|
||
if ( code < 12 )
|
||
inp1[j] = ((s32)((s32)inp1[j]*(s32)vscale)>>16);
|
||
j++;
|
||
|
||
inp1[j] = (s16)((icode&0xf) << 12);
|
||
|
||
inp1[j] = ((s32)((s32)inp1[j]*(s32)vscale) >> 16);
|
||
j++;
|
||
}
|
||
|
||
j = 0;
|
||
while(j < 8)
|
||
{
|
||
icode=gAudioHLEState.Buffer[(0x4f0+inPtr)^3];
|
||
inPtr++;
|
||
|
||
inp2[j]=(s16)((icode&0xf0)<<8); // this will in effect be signed
|
||
|
||
if(code<12)
|
||
inp2[j]=((s32)((s32)inp2[j]*(s32)vscale)>>16);
|
||
|
||
j++;
|
||
|
||
inp2[j]=(s16)((icode&0xf)<<12);
|
||
|
||
inp2[j]=((s32)((s32)inp2[j]*(s32)vscale)>>16);
|
||
j++;
|
||
}
|
||
|
||
a[0]= (s32)book1[0]*(s32)l1;
|
||
a[0]+=(s32)book2[0]*(s32)l2;
|
||
a[0]+=(s32)inp1[0]*(s32)2048;
|
||
|
||
a[1] =(s32)book1[1]*(s32)l1;
|
||
a[1]+=(s32)book2[1]*(s32)l2;
|
||
a[1]+=(s32)book2[0]*inp1[0];
|
||
a[1]+=(s32)inp1[1]*(s32)2048;
|
||
|
||
a[2] =(s32)book1[2]*(s32)l1;
|
||
a[2]+=(s32)book2[2]*(s32)l2;
|
||
a[2]+=(s32)book2[1]*inp1[0];
|
||
a[2]+=(s32)book2[0]*inp1[1];
|
||
a[2]+=(s32)inp1[2]*(s32)2048;
|
||
|
||
a[3] =(s32)book1[3]*(s32)l1;
|
||
a[3]+=(s32)book2[3]*(s32)l2;
|
||
a[3]+=(s32)book2[2]*inp1[0];
|
||
a[3]+=(s32)book2[1]*inp1[1];
|
||
a[3]+=(s32)book2[0]*inp1[2];
|
||
a[3]+=(s32)inp1[3]*(s32)2048;
|
||
|
||
a[4] =(s32)book1[4]*(s32)l1;
|
||
a[4]+=(s32)book2[4]*(s32)l2;
|
||
a[4]+=(s32)book2[3]*inp1[0];
|
||
a[4]+=(s32)book2[2]*inp1[1];
|
||
a[4]+=(s32)book2[1]*inp1[2];
|
||
a[4]+=(s32)book2[0]*inp1[3];
|
||
a[4]+=(s32)inp1[4]*(s32)2048;
|
||
|
||
a[5] =(s32)book1[5]*(s32)l1;
|
||
a[5]+=(s32)book2[5]*(s32)l2;
|
||
a[5]+=(s32)book2[4]*inp1[0];
|
||
a[5]+=(s32)book2[3]*inp1[1];
|
||
a[5]+=(s32)book2[2]*inp1[2];
|
||
a[5]+=(s32)book2[1]*inp1[3];
|
||
a[5]+=(s32)book2[0]*inp1[4];
|
||
a[5]+=(s32)inp1[5]*(s32)2048;
|
||
|
||
a[6] =(s32)book1[6]*(s32)l1;
|
||
a[6]+=(s32)book2[6]*(s32)l2;
|
||
a[6]+=(s32)book2[5]*inp1[0];
|
||
a[6]+=(s32)book2[4]*inp1[1];
|
||
a[6]+=(s32)book2[3]*inp1[2];
|
||
a[6]+=(s32)book2[2]*inp1[3];
|
||
a[6]+=(s32)book2[1]*inp1[4];
|
||
a[6]+=(s32)book2[0]*inp1[5];
|
||
a[6]+=(s32)inp1[6]*(s32)2048;
|
||
|
||
a[7] =(s32)book1[7]*(s32)l1;
|
||
a[7]+=(s32)book2[7]*(s32)l2;
|
||
a[7]+=(s32)book2[6]*inp1[0];
|
||
a[7]+=(s32)book2[5]*inp1[1];
|
||
a[7]+=(s32)book2[4]*inp1[2];
|
||
a[7]+=(s32)book2[3]*inp1[3];
|
||
a[7]+=(s32)book2[2]*inp1[4];
|
||
a[7]+=(s32)book2[1]*inp1[5];
|
||
a[7]+=(s32)book2[0]*inp1[6];
|
||
a[7]+=(s32)inp1[7]*(s32)2048;
|
||
|
||
*(out++) = Saturate<s16>( a[1] >> 11 );
|
||
*(out++) = Saturate<s16>( a[0] >> 11 );
|
||
*(out++) = Saturate<s16>( a[3] >> 11 );
|
||
*(out++) = Saturate<s16>( a[2] >> 11 );
|
||
*(out++) = Saturate<s16>( a[5] >> 11 );
|
||
*(out++) = Saturate<s16>( a[4] >> 11 );
|
||
*(out++) = l2 = Saturate<s16>( a[7] >> 11 );
|
||
*(out++) = l1 = Saturate<s16>( a[6] >> 11 );
|
||
|
||
a[0]= (s32)book1[0]*(s32)l1;
|
||
a[0]+=(s32)book2[0]*(s32)l2;
|
||
a[0]+=(s32)inp2[0]*(s32)2048;
|
||
|
||
a[1] =(s32)book1[1]*(s32)l1;
|
||
a[1]+=(s32)book2[1]*(s32)l2;
|
||
a[1]+=(s32)book2[0]*inp2[0];
|
||
a[1]+=(s32)inp2[1]*(s32)2048;
|
||
|
||
a[2] =(s32)book1[2]*(s32)l1;
|
||
a[2]+=(s32)book2[2]*(s32)l2;
|
||
a[2]+=(s32)book2[1]*inp2[0];
|
||
a[2]+=(s32)book2[0]*inp2[1];
|
||
a[2]+=(s32)inp2[2]*(s32)2048;
|
||
|
||
a[3] =(s32)book1[3]*(s32)l1;
|
||
a[3]+=(s32)book2[3]*(s32)l2;
|
||
a[3]+=(s32)book2[2]*inp2[0];
|
||
a[3]+=(s32)book2[1]*inp2[1];
|
||
a[3]+=(s32)book2[0]*inp2[2];
|
||
a[3]+=(s32)inp2[3]*(s32)2048;
|
||
|
||
a[4] =(s32)book1[4]*(s32)l1;
|
||
a[4]+=(s32)book2[4]*(s32)l2;
|
||
a[4]+=(s32)book2[3]*inp2[0];
|
||
a[4]+=(s32)book2[2]*inp2[1];
|
||
a[4]+=(s32)book2[1]*inp2[2];
|
||
a[4]+=(s32)book2[0]*inp2[3];
|
||
a[4]+=(s32)inp2[4]*(s32)2048;
|
||
|
||
a[5] =(s32)book1[5]*(s32)l1;
|
||
a[5]+=(s32)book2[5]*(s32)l2;
|
||
a[5]+=(s32)book2[4]*inp2[0];
|
||
a[5]+=(s32)book2[3]*inp2[1];
|
||
a[5]+=(s32)book2[2]*inp2[2];
|
||
a[5]+=(s32)book2[1]*inp2[3];
|
||
a[5]+=(s32)book2[0]*inp2[4];
|
||
a[5]+=(s32)inp2[5]*(s32)2048;
|
||
|
||
a[6] =(s32)book1[6]*(s32)l1;
|
||
a[6]+=(s32)book2[6]*(s32)l2;
|
||
a[6]+=(s32)book2[5]*inp2[0];
|
||
a[6]+=(s32)book2[4]*inp2[1];
|
||
a[6]+=(s32)book2[3]*inp2[2];
|
||
a[6]+=(s32)book2[2]*inp2[3];
|
||
a[6]+=(s32)book2[1]*inp2[4];
|
||
a[6]+=(s32)book2[0]*inp2[5];
|
||
a[6]+=(s32)inp2[6]*(s32)2048;
|
||
|
||
a[7] =(s32)book1[7]*(s32)l1;
|
||
a[7]+=(s32)book2[7]*(s32)l2;
|
||
a[7]+=(s32)book2[6]*inp2[0];
|
||
a[7]+=(s32)book2[5]*inp2[1];
|
||
a[7]+=(s32)book2[4]*inp2[2];
|
||
a[7]+=(s32)book2[3]*inp2[3];
|
||
a[7]+=(s32)book2[2]*inp2[4];
|
||
a[7]+=(s32)book2[1]*inp2[5];
|
||
a[7]+=(s32)book2[0]*inp2[6];
|
||
a[7]+=(s32)inp2[7]*(s32)2048;
|
||
|
||
*(out++) = Saturate<s16>( a[1] >> 11 );
|
||
*(out++) = Saturate<s16>( a[0] >> 11 );
|
||
*(out++) = Saturate<s16>( a[3] >> 11 );
|
||
*(out++) = Saturate<s16>( a[2] >> 11 );
|
||
*(out++) = Saturate<s16>( a[5] >> 11 );
|
||
*(out++) = Saturate<s16>( a[4] >> 11 );
|
||
*(out++) = l2 = Saturate<s16>( a[7] >> 11 );
|
||
*(out++) = l1 = Saturate<s16>( a[6] >> 11 );
|
||
|
||
count-=32;
|
||
}
|
||
out-=16;
|
||
|
||
memcpy(&rdram[Address],out,32);
|
||
}
|
||
|
||
static void RESAMPLE3( AudioHLECommand command )
|
||
{
|
||
u8 Flags {(u8)((command.cmd1>>0x1e))};
|
||
u32 Pitch {((command.cmd1>>0xe)&0xffff) << 1};
|
||
u32 addy {(command.cmd0 & 0xffffff)};
|
||
u32 Accum {};
|
||
s16 *dst {};
|
||
s16 *src {};
|
||
dst = (s16 *)(gAudioHLEState.Buffer);
|
||
src = (s16 *)(gAudioHLEState.Buffer);
|
||
u32 srcPtr{ ((((command.cmd1>>2)&0xfff)+0x4f0)/2)};
|
||
u32 dstPtr {};//=(gAudioHLEState.OutBuffer/2);
|
||
|
||
srcPtr -= 1;
|
||
|
||
if (command.cmd1 & 0x3) {
|
||
dstPtr = 0x660/2;
|
||
} else {
|
||
dstPtr = 0x4f0/2;
|
||
}
|
||
|
||
if ((Flags & 0x1) == 0) {
|
||
src[srcPtr^1] = ((u16 *)rdram)[((addy/2))^1];
|
||
Accum = *(u16 *)(rdram+addy+10);
|
||
} else {
|
||
src[(srcPtr)^1] = 0;
|
||
Accum = 0;
|
||
}
|
||
|
||
for(u32 i {} ; i < 0x170/2;i++)
|
||
{
|
||
dst[dstPtr^1] = src[srcPtr^1] + FixedPointMul16( src[(srcPtr+1)^1] - src[srcPtr^1], Accum );
|
||
++dstPtr;
|
||
Accum += Pitch;
|
||
srcPtr += (Accum>>16);
|
||
Accum &= 0xFFFF;
|
||
}
|
||
|
||
((u16 *)rdram)[((addy/2))^1] = src[srcPtr^1];
|
||
*(u16 *)(rdram+addy+10) = u16( Accum );
|
||
}
|
||
|
||
static void INTERLEAVE3( AudioHLECommand command )
|
||
{
|
||
// Needs accuracy verification...
|
||
//inR = command.cmd1 & 0xFFFF;
|
||
//inL = (command.cmd1 >> 16) & 0xFFFF;
|
||
|
||
gAudioHLEState.Interleave( 0x4f0, 0x9d0, 0xb40, 0x170 );
|
||
}
|
||
|
||
/*
|
||
typedef struct {
|
||
u8 sync;
|
||
|
||
u8 error_protection : 1; // 0=yes, 1=no
|
||
u8 lay : 2; // 4-lay = layerI, II or III
|
||
u8 version : 1; // 3=mpeg 1.0, 2=mpeg 2.5 0=mpeg 2.0
|
||
u8 sync2 : 4;
|
||
|
||
u8 extension : 1; // Unknown
|
||
u8 padding : 1; // padding
|
||
u8 sampling_freq : 2; // see table below
|
||
u8 bitrate_index : 4; // see table below
|
||
|
||
u8 emphasis : 2; //see table below
|
||
u8 original : 1; // 0=no 1=yes
|
||
u8 copyright : 1; // 0=no 1=yes
|
||
u8 mode_ext : 2; // used with "joint stereo" mode
|
||
u8 mode : 2; // Channel Mode
|
||
} mp3struct;
|
||
|
||
mp3struct mp3;
|
||
FILE *mp3dat;
|
||
*/
|
||
|
||
static void WHATISTHIS( AudioHLECommand command )
|
||
{
|
||
}
|
||
|
||
//static FILE *fp = fopen ("d:\\mp3info.txt", "wt");
|
||
//u32 setaddr;
|
||
static void MP3ADDY( AudioHLECommand command )
|
||
{
|
||
//setaddr = (command.cmd1 & 0xffffff);
|
||
}
|
||
|
||
|
||
void MP3( AudioHLECommand command );
|
||
|
||
|
||
/*
|
||
|
||
FFT = Fast Fourier Transform
|
||
DCT = Discrete Cosine Transform
|
||
MPEG-1 Layer 3 retains Layer 2<>s 1152-sample window, as well as the FFT polyphase filter for
|
||
backward compatibility, but adds a modified DCT filter. DCT<43>s advantages over DFTs (discrete
|
||
Fourier transforms) include half as many multiply-accumulate operations and half the
|
||
generated coefficients because the sinusoidal portion of the calculation is absent, and DCT
|
||
generally involves simpler math. The finite lengths of a conventional DCTs<54> bandpass impulse
|
||
responses, however, may result in block-boundary effects. MDCTs overlap the analysis blocks
|
||
and lowpass-filter the decoded audio to remove aliases, eliminating these effects. MDCTs also
|
||
have a higher transform coding gain than the standard DCT, and their basic functions
|
||
correspond to better bandpass response.
|
||
|
||
MPEG-1 Layer 3<>s DCT sub-bands are unequally sized, and correspond to the human auditory
|
||
system<EFBFBD>s critical bands. In Layer 3 decoders must support both constant- and variable-bit-rate
|
||
bit streams. (However, many Layer 1 and 2 decoders also handle variable bit rates). Finally,
|
||
Layer 3 encoders Huffman-code the quantized coefficients before archiving or transmission for
|
||
additional lossless compression. Bit streams range from 32 to 320 kbps, and 128-kbps rates
|
||
achieve near-CD quality, an important specification to enable dual-channel ISDN
|
||
(integrated-services-digital-network) to be the future high-bandwidth pipe to the home.
|
||
|
||
*/
|
||
static void DISABLE( AudioHLECommand command )
|
||
{
|
||
//MessageBox (NULL, "Help", "ABI 3 Command 0", MB_OK);
|
||
//ChangeABI (5);
|
||
}
|
||
|
||
|
||
AudioHLEInstruction ABI3[0x20] =
|
||
{
|
||
DISABLE , ADPCM3 , CLEARBUFF3, ENVMIXER3 , LOADBUFF3, RESAMPLE3 , SAVEBUFF3, MP3,
|
||
MP3ADDY, SETVOL3, DMEMMOVE3 , LOADADPCM3 , MIXER3 , INTERLEAVE3, WHATISTHIS , SETLOOP3,
|
||
SPNOOP , SPNOOP, SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP,
|
||
SPNOOP , SPNOOP, SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP
|
||
};
|