mirror of https://github.com/PCSX2/pcsx2.git
SPU2-X: Attempt to fix Cubic Interp mode; plus some cleanups to the XA Decoder.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2700 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
34eb64c3fe
commit
001a286415
|
@ -1,114 +1,114 @@
|
|||
/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2
|
||||
* Developed and maintained by the Pcsx2 Development Team.
|
||||
*
|
||||
* Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz]
|
||||
*
|
||||
* SPU2-X is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SPU2-X 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SPU2X_GLOBAL_H_
|
||||
#define _SPU2X_GLOBAL_H_
|
||||
|
||||
#define NOMINMAX
|
||||
|
||||
struct StereoOut16;
|
||||
struct StereoOut32;
|
||||
struct StereoOutFloat;
|
||||
|
||||
struct V_Core;
|
||||
|
||||
namespace soundtouch
|
||||
{
|
||||
class SoundTouch;
|
||||
}
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2
|
||||
* Developed and maintained by the Pcsx2 Development Team.
|
||||
*
|
||||
* Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz]
|
||||
*
|
||||
* SPU2-X is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SPU2-X 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SPU2X_GLOBAL_H_
|
||||
#define _SPU2X_GLOBAL_H_
|
||||
|
||||
#define NOMINMAX
|
||||
|
||||
struct StereoOut16;
|
||||
struct StereoOut32;
|
||||
struct StereoOutFloat;
|
||||
|
||||
struct V_Core;
|
||||
|
||||
namespace soundtouch
|
||||
{
|
||||
class SoundTouch;
|
||||
}
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
|
||||
#include "Pcsx2Defs.h"
|
||||
#include "Pcsx2Types.h"
|
||||
|
||||
namespace VersionInfo
|
||||
{
|
||||
static const u8 Release = 1;
|
||||
static const u8 Revision = 4; // increase that with each version
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Override Win32 min/max macros with the STL's type safe and macro
|
||||
// free varieties (much safer!)
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
template< typename T >
|
||||
static __forceinline void Clampify( T& src, T min, T max )
|
||||
{
|
||||
src = std::min( std::max( src, min ), max );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
static __forceinline T GetClamped( T src, T min, T max )
|
||||
{
|
||||
return std::min( std::max( src, min ), max );
|
||||
}
|
||||
|
||||
extern void SysMessage(const char *fmt, ...);
|
||||
extern void SysMessage(const wchar_t *fmt, ...);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Dev / Debug conditionals --
|
||||
// Consts for using if() statements instead of uglier #ifdef macros.
|
||||
// Abbreviated macros for dev/debug only consoles and msgboxes.
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
# define DevCon Console
|
||||
# define DevMsg MsgBox
|
||||
#else
|
||||
# define DevCon 0&&Console
|
||||
# define DevMsg
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
# define DbgCon Console
|
||||
#else
|
||||
# define DbgCon 0&&Console
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
# define SPU2_LOG
|
||||
#endif
|
||||
|
||||
#include "Utilities/Exceptions.h"
|
||||
#include "Utilities/SafeArray.h"
|
||||
|
||||
#include "ConvertUTF.h"
|
||||
|
||||
#include "defs.h"
|
||||
#include "regs.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "Debug.h"
|
||||
#include "SndOut.h"
|
||||
|
||||
#include "Pcsx2Defs.h"
|
||||
#include "Pcsx2Types.h"
|
||||
|
||||
namespace VersionInfo
|
||||
{
|
||||
static const u8 Release = 1;
|
||||
static const u8 Revision = 4; // increase that with each version
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Override Win32 min/max macros with the STL's type safe and macro
|
||||
// free varieties (much safer!)
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
template< typename T >
|
||||
static __forceinline void Clampify( T& src, T min, T max )
|
||||
{
|
||||
src = std::min( std::max( src, min ), max );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
static __forceinline T GetClamped( T src, T min, T max )
|
||||
{
|
||||
return std::min( std::max( src, min ), max );
|
||||
}
|
||||
|
||||
extern void SysMessage(const char *fmt, ...);
|
||||
extern void SysMessage(const wchar_t *fmt, ...);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Dev / Debug conditionals --
|
||||
// Consts for using if() statements instead of uglier #ifdef macros.
|
||||
// Abbreviated macros for dev/debug only consoles and msgboxes.
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
# define DevCon Console
|
||||
# define DevMsg MsgBox
|
||||
#else
|
||||
# define DevCon 0&&Console
|
||||
# define DevMsg
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
# define DbgCon Console
|
||||
#else
|
||||
# define DbgCon 0&&Console
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
# define SPU2_LOG
|
||||
#endif
|
||||
|
||||
#include "Utilities/Exceptions.h"
|
||||
#include "Utilities/SafeArray.h"
|
||||
|
||||
#include "ConvertUTF.h"
|
||||
|
||||
#include "defs.h"
|
||||
#include "regs.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "Debug.h"
|
||||
#include "SndOut.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,22 @@ static const s32 tbl_XA_Factor[5][2] =
|
|||
{ 122, -60 }
|
||||
};
|
||||
|
||||
static double K0[4] =
|
||||
{
|
||||
0.0,
|
||||
0.9375,
|
||||
1.796875,
|
||||
1.53125
|
||||
};
|
||||
|
||||
static double K1[4] =
|
||||
{
|
||||
0.0,
|
||||
0.0,
|
||||
-0.8125,
|
||||
-0.859375
|
||||
};
|
||||
|
||||
|
||||
// Performs a 64-bit multiplication between two values and returns the
|
||||
// high 32 bits as a result (discarding the fractional 32 bits).
|
||||
|
@ -77,59 +93,42 @@ StereoOut32 clamp_mix( const StereoOut32& sample, u8 bitshift )
|
|||
static void __forceinline XA_decode_block(s16* buffer, const s16* block, s32& prev1, s32& prev2)
|
||||
{
|
||||
const s32 header = *block;
|
||||
const s32 shift = ((header>> 0)&0xF)+16;
|
||||
const s32 shift = (header&0xF)+16;
|
||||
const s32 pred1 = tbl_XA_Factor[(header>> 4)&0xF][0];
|
||||
const s32 pred2 = tbl_XA_Factor[(header>> 4)&0xF][1];
|
||||
|
||||
const s8* blockbytes = (s8*)&block[1];
|
||||
const s8* blockbytes = (s8*)&block[1];
|
||||
const s8* blockend = &blockbytes[13];
|
||||
|
||||
for(int i=0; i<14; i++, blockbytes++)
|
||||
for(; blockbytes<=blockend; ++blockbytes)
|
||||
{
|
||||
s32 pcm, pcm2;
|
||||
{
|
||||
s32 data = ((*blockbytes)<<28) & 0xF0000000;
|
||||
pcm = data>>shift;
|
||||
pcm+=((pred1*prev1)+(pred2*prev2))>>6;
|
||||
s32 data = ((*blockbytes)<<28) & 0xF0000000;
|
||||
s32 pcm = (data >> shift) + (((pred1*prev1)+(pred2*prev2)) >> 6);
|
||||
|
||||
if(pcm> 32767) ConLog("pcm too high, is %d\n",pcm);
|
||||
else if(pcm<-32768) ConLog("pcm too low, is %d\n",pcm);
|
||||
Clampify( pcm, -0x8000, 0x7fff );
|
||||
*(buffer++) = pcm;
|
||||
|
||||
if(pcm> 32767) pcm= 32767;
|
||||
else if(pcm<-32768) pcm=-32768;
|
||||
*(buffer++) = pcm;
|
||||
}
|
||||
data = ((*blockbytes)<<24) & 0xF0000000;
|
||||
s32 pcm2 = (data >> shift) + (((pred1*pcm)+(pred2*prev1)) >> 6);
|
||||
|
||||
//prev2=prev1;
|
||||
//prev1=pcm;
|
||||
Clampify( pcm2, -0x8000, 0x7fff );
|
||||
*(buffer++) = pcm2;
|
||||
|
||||
{
|
||||
s32 data = ((*blockbytes)<<24) & 0xF0000000;
|
||||
pcm2 = data>>shift;
|
||||
pcm2+=((pred1*pcm)+(pred2*prev1))>>6;
|
||||
|
||||
if(pcm2> 32767) ConLog("pcm2 too high, is %d\n",pcm2);
|
||||
else if(pcm2<-32768) ConLog("pcm2 too low, is %d\n",pcm2);
|
||||
|
||||
if(pcm2> 32767) pcm2= 32767;
|
||||
else if(pcm2<-32768) pcm2=-32768;
|
||||
*(buffer++) = pcm2;
|
||||
}
|
||||
|
||||
prev2=pcm;
|
||||
prev1=pcm2;
|
||||
prev2 = pcm;
|
||||
prev1 = pcm2;
|
||||
}
|
||||
}
|
||||
|
||||
static void __forceinline XA_decode_block_unsaturated(s16* buffer, const s16* block, s32& prev1, s32& prev2)
|
||||
{
|
||||
const u8 header = *(u8*)block;
|
||||
s32 shift = (header&0xF) + 16;
|
||||
s32 pred1 = tbl_XA_Factor[header>>4][0];
|
||||
s32 pred2 = tbl_XA_Factor[header>>4][1];
|
||||
const s32 shift = (header&0xF) + 16;
|
||||
const s32 pred1 = tbl_XA_Factor[header>>4][0];
|
||||
const s32 pred2 = tbl_XA_Factor[header>>4][1];
|
||||
|
||||
const s8* blockbytes = (s8*)&block[1];
|
||||
|
||||
for(int i=0; i<14; i++, blockbytes++)
|
||||
for(uint i=0; i<14; i++, blockbytes++)
|
||||
{
|
||||
s32 pcm, pcm2;
|
||||
{
|
||||
|
@ -151,6 +150,7 @@ static void __forceinline XA_decode_block_unsaturated(s16* buffer, const s16* bl
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void __forceinline IncrementNextA( const V_Core& thiscore, V_Voice& vc )
|
||||
{
|
||||
// Important! Both cores signal IRQ when an address is read, regardless of
|
||||
|
@ -451,28 +451,36 @@ static s32 __forceinline GetVoiceValues_Cubic( V_Core& thiscore, uint voiceidx )
|
|||
vc.PV2 = vc.PV1;
|
||||
|
||||
vc.PV1 = GetNextDataBuffered( thiscore, voiceidx );
|
||||
vc.PV1 <<= 2;
|
||||
vc.SPc = vc.SP&4095; // just the fractional part, please!
|
||||
//vc.PV1 <<= 2;
|
||||
//vc.SPc = vc.SP&4095; // just the fractional part, please!
|
||||
vc.SP -= 4096;
|
||||
}
|
||||
|
||||
CalculateADSR( thiscore, voiceidx );
|
||||
|
||||
s32 z0 = vc.PV3 - vc.PV4 + vc.PV1 - vc.PV2;
|
||||
s32 z1 = (vc.PV4 - vc.PV3 - z0);
|
||||
s32 z2 = (vc.PV2 - vc.PV4);
|
||||
/*mu2 = mu*mu;
|
||||
a0 = y3 - y2 - y0 + y1; //p
|
||||
a1 = y0 - y1 - a0;
|
||||
a2 = y2 - y0;
|
||||
a3 = y1;
|
||||
|
||||
s32 mu = vc.SPc;
|
||||
return ( a0*mu*mu2 + a1*mu2 + a2*mu + a3 );*/
|
||||
|
||||
const s32 z0 = vc.PV4 - vc.PV3 - vc.PV1 + vc.PV2;
|
||||
const s32 z1 = vc.PV1 - vc.PV2 - z0;
|
||||
const s32 z2 = vc.PV3 - vc.PV1;
|
||||
|
||||
const s32 mu = vc.SP;
|
||||
|
||||
s32 val = (z0 * mu) >> 12;
|
||||
val = ((val + z1) * mu) >> 12;
|
||||
val = ((val + z2) * mu) >> 12;
|
||||
val += vc.PV3;
|
||||
val += vc.PV2;
|
||||
|
||||
// Note! It's very important that ADSR stay as accurate as possible. By the way
|
||||
// it is used, various sound effects can end prematurely if we truncate more than
|
||||
// one or two bits. (or maybe it's better with no truncation at all?)
|
||||
return MulShr32( val>>1, vc.ADSR.Value );
|
||||
return MulShr32( val, vc.ADSR.Value );
|
||||
}
|
||||
|
||||
// Noise values need to be mixed without going through interpolation, since it
|
||||
|
|
Loading…
Reference in New Issue