mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
initial checkin
This commit is contained in:
190
MAC_SDK/Source/Console/Console.cpp
Normal file
190
MAC_SDK/Source/Console/Console.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
/***************************************************************************************
|
||||
MAC Console Frontend (MAC.exe)
|
||||
|
||||
Pretty simple and straightforward console front end. If somebody ever wants to add
|
||||
more functionality like tagging, auto-verify, etc., that'd be excellent.
|
||||
|
||||
Copyrighted (c) 2000 - 2003 Matthew T. Ashland. All Rights Reserved.
|
||||
***************************************************************************************/
|
||||
#include "All.h"
|
||||
#include <stdio.h>
|
||||
#include "GlobalFunctions.h"
|
||||
#include "MACLib.h"
|
||||
#include "CharacterHelper.h"
|
||||
|
||||
// defines
|
||||
#define COMPRESS_MODE 0
|
||||
#define DECOMPRESS_MODE 1
|
||||
#define VERIFY_MODE 2
|
||||
#define CONVERT_MODE 3
|
||||
#define UNDEFINED_MODE -1
|
||||
|
||||
// global variables
|
||||
TICK_COUNT_TYPE g_nInitialTickCount = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
Displays the proper usage for MAC.exe
|
||||
***************************************************************************************/
|
||||
void DisplayProperUsage(FILE * pFile)
|
||||
{
|
||||
fprintf(pFile, "Proper Usage: [EXE] [Input File] [Output File] [Mode]\n\n");
|
||||
|
||||
fprintf(pFile, "Modes: \n");
|
||||
fprintf(pFile, " Compress (fast): '-c1000'\n");
|
||||
fprintf(pFile, " Compress (normal): '-c2000'\n");
|
||||
fprintf(pFile, " Compress (high): '-c3000'\n");
|
||||
fprintf(pFile, " Compress (extra high): '-c4000'\n");
|
||||
fprintf(pFile, " Compress (insane): '-c5000'\n");
|
||||
fprintf(pFile, " Decompress: '-d'\n");
|
||||
fprintf(pFile, " Verify: '-v'\n");
|
||||
fprintf(pFile, " Convert: '-nXXXX'\n\n");
|
||||
|
||||
fprintf(pFile, "Examples:\n");
|
||||
fprintf(pFile, " Compress: mac.exe \"Metallica - One.wav\" \"Metallica - One.ape\" -c2000\n");
|
||||
fprintf(pFile, " Decompress: mac.exe \"Metallica - One.ape\" \"Metallica - One.wav\" -d\n");
|
||||
fprintf(pFile, " Verify: mac.exe \"Metallica - One.ape\" -v\n");
|
||||
fprintf(pFile, " (note: int filenames must be put inside of quotations)\n");
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Progress callback
|
||||
***************************************************************************************/
|
||||
void CALLBACK ProgressCallback(int nPercentageDone)
|
||||
{
|
||||
// get the current tick count
|
||||
TICK_COUNT_TYPE nTickCount;
|
||||
TICK_COUNT_READ(nTickCount);
|
||||
|
||||
// calculate the progress
|
||||
double dProgress = nPercentageDone / 1.e5; // [0...1]
|
||||
double dElapsed = (double) (nTickCount - g_nInitialTickCount) / TICK_COUNT_FREQ; // seconds
|
||||
double dRemaining = dElapsed * ((1.0 / dProgress) - 1.0); // seconds
|
||||
|
||||
// output the progress
|
||||
fprintf(stderr, "Progress: %.1f%% (%.1f seconds remaining, %.1f seconds total) \r",
|
||||
dProgress * 100, dRemaining, dElapsed);
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Main (the main function)
|
||||
***************************************************************************************/
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
// variable declares
|
||||
CSmartPtr<wchar_t> spInputFilename; CSmartPtr<wchar_t> spOutputFilename;
|
||||
int nRetVal = ERROR_UNDEFINED;
|
||||
int nMode = UNDEFINED_MODE;
|
||||
int nCompressionLevel;
|
||||
int nPercentageDone;
|
||||
|
||||
// output the header
|
||||
fprintf(stderr, CONSOLE_NAME);
|
||||
|
||||
// make sure there are at least four arguments (could be more for EAC compatibility)
|
||||
if (argc < 3)
|
||||
{
|
||||
DisplayProperUsage(stderr);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// store the input file
|
||||
spInputFilename.Assign(GetUTF16FromANSI(argv[1]), TRUE);
|
||||
|
||||
// store the output file
|
||||
spOutputFilename.Assign(GetUTF16FromANSI(argv[2]), TRUE);
|
||||
|
||||
// verify that the input file exists
|
||||
if (!FileExists(spInputFilename))
|
||||
{
|
||||
fprintf(stderr, "Input File Not Found...\n\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// if the output file equals '-v', then use this as the next argument
|
||||
char cMode[256];
|
||||
strcpy(cMode, argv[2]);
|
||||
|
||||
if (_strnicmp(cMode, "-v", 2) != 0)
|
||||
{
|
||||
// verify is the only mode that doesn't use at least the third argument
|
||||
if (argc < 4)
|
||||
{
|
||||
DisplayProperUsage(stderr);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// check for and skip if necessary the -b XXXXXX arguments (3,4)
|
||||
strcpy(cMode, argv[3]);
|
||||
}
|
||||
|
||||
// get the mode
|
||||
nMode = UNDEFINED_MODE;
|
||||
if (_strnicmp(cMode, "-c", 2) == 0)
|
||||
nMode = COMPRESS_MODE;
|
||||
else if (_strnicmp(cMode, "-d", 2) == 0)
|
||||
nMode = DECOMPRESS_MODE;
|
||||
else if (_strnicmp(cMode, "-v", 2) == 0)
|
||||
nMode = VERIFY_MODE;
|
||||
else if (_strnicmp(cMode, "-n", 2) == 0)
|
||||
nMode = CONVERT_MODE;
|
||||
|
||||
// error check the mode
|
||||
if (nMode == UNDEFINED_MODE)
|
||||
{
|
||||
DisplayProperUsage(stderr);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// get and error check the compression level
|
||||
if (nMode == COMPRESS_MODE || nMode == CONVERT_MODE)
|
||||
{
|
||||
nCompressionLevel = atoi(&cMode[2]);
|
||||
if (nCompressionLevel != 1000 && nCompressionLevel != 2000 &&
|
||||
nCompressionLevel != 3000 && nCompressionLevel != 4000 &&
|
||||
nCompressionLevel != 5000)
|
||||
{
|
||||
DisplayProperUsage(stderr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// set the initial tick count
|
||||
TICK_COUNT_READ(g_nInitialTickCount);
|
||||
|
||||
// process
|
||||
int nKillFlag = 0;
|
||||
if (nMode == COMPRESS_MODE)
|
||||
{
|
||||
char cCompressionLevel[16];
|
||||
if (nCompressionLevel == 1000) { strcpy(cCompressionLevel, "fast"); }
|
||||
if (nCompressionLevel == 2000) { strcpy(cCompressionLevel, "normal"); }
|
||||
if (nCompressionLevel == 3000) { strcpy(cCompressionLevel, "high"); }
|
||||
if (nCompressionLevel == 4000) { strcpy(cCompressionLevel, "extra high"); }
|
||||
if (nCompressionLevel == 5000) { strcpy(cCompressionLevel, "insane"); }
|
||||
|
||||
fprintf(stderr, "Compressing (%s)...\n", cCompressionLevel);
|
||||
nRetVal = CompressFileW(spInputFilename, spOutputFilename, nCompressionLevel, &nPercentageDone, ProgressCallback, &nKillFlag);
|
||||
}
|
||||
else if (nMode == DECOMPRESS_MODE)
|
||||
{
|
||||
fprintf(stderr, "Decompressing...\n");
|
||||
nRetVal = DecompressFileW(spInputFilename, spOutputFilename, &nPercentageDone, ProgressCallback, &nKillFlag);
|
||||
}
|
||||
else if (nMode == VERIFY_MODE)
|
||||
{
|
||||
fprintf(stderr, "Verifying...\n");
|
||||
nRetVal = VerifyFileW(spInputFilename, &nPercentageDone, ProgressCallback, &nKillFlag);
|
||||
}
|
||||
else if (nMode == CONVERT_MODE)
|
||||
{
|
||||
fprintf(stderr, "Converting...\n");
|
||||
nRetVal = ConvertFileW(spInputFilename, spOutputFilename, nCompressionLevel, &nPercentageDone, ProgressCallback, &nKillFlag);
|
||||
}
|
||||
|
||||
if (nRetVal == ERROR_SUCCESS)
|
||||
fprintf(stderr, "\nSuccess...\n");
|
||||
else
|
||||
fprintf(stderr, "\nError: %i\n", nRetVal);
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
114
MAC_SDK/Source/Console/Console.dsp
Normal file
114
MAC_SDK/Source/Console/Console.dsp
Normal file
@@ -0,0 +1,114 @@
|
||||
# Microsoft Developer Studio Project File - Name="Console" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=Console - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Console.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Console.mak" CFG="Console - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Console - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Console - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/Monkey's Audio/Console", GKAAAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Console - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\MACLib\\" /I "..\Shared\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 maclib.lib kernel32.lib user32.lib gdi32.lib /nologo /subsystem:console /profile /machine:I386 /out:"Release/MAC.exe" /libpath:"..\MACLib\Release"
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Cmds=copy Release\MAC.exe C:\MAC\Application\MAC.exe
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "Console - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\MACLib\\" /I "..\Shared\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 maclib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/MAC.exe" /pdbtype:sept /libpath:"..\MACLib\Debug"
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Cmds=copy Debug\MAC.exe C:\MAC\Application\MAC.exe
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Console - Win32 Release"
|
||||
# Name "Console - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Console.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=".\Resource Script.rc"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
185
MAC_SDK/Source/Console/Console.vcproj
Normal file
185
MAC_SDK/Source/Console/Console.vcproj
Normal file
@@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="Console"
|
||||
ProjectGUID="{CC3FC224-9557-45F3-9B8F-C29AE1DBCE82}"
|
||||
SccProjectName=""$/Monkey's Audio/Console", GKAAAAAA"
|
||||
SccLocalPath=".">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\Debug"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="1">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\MACLib\,..\Shared\"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\Debug/Console.pch"
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
ObjectFile=".\Debug/"
|
||||
ProgramDataBaseFileName=".\Debug/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="unicows.lib kernel32.lib advapi32.lib user32.lib gdi32.lib shell32.lib comdlg32.lib version.lib mpr.lib rasapi32.lib winmm.lib winspool.lib vfw32.lib secur32.lib oleacc.lib oledlg.lib sensapi.lib maclib.lib"
|
||||
OutputFile="Debug/MAC.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories="..\MACLib\Debug"
|
||||
IgnoreDefaultLibraryNames="kernel32.lib;advapi32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;version.lib;mpr.lib;rasapi32.lib;winmm.lib;winspool.lib;vfw32.lib;secur32.lib;oleacc.lib;oledlg.lib;sensapi.lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile=".\Debug/MAC.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\Debug/Console.tlb"
|
||||
HeaderFileName=""/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy Debug\MAC.exe C:\MAC\Application\MAC.exe"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\Release"
|
||||
IntermediateDirectory=".\Release"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="1">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\MACLib\,..\Shared\"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\Release/Console.pch"
|
||||
AssemblerListingLocation=".\Release/"
|
||||
ObjectFile=".\Release/"
|
||||
ProgramDataBaseFileName=".\Release/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="unicows.lib kernel32.lib advapi32.lib user32.lib gdi32.lib shell32.lib comdlg32.lib version.lib mpr.lib rasapi32.lib winmm.lib winspool.lib vfw32.lib secur32.lib oleacc.lib oledlg.lib sensapi.lib maclib.lib"
|
||||
OutputFile="Release/MAC.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories="..\MACLib\Release"
|
||||
IgnoreDefaultLibraryNames="kernel32.lib;advapi32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;version.lib;mpr.lib;rasapi32.lib;winmm.lib;winspool.lib;vfw32.lib;secur32.lib;oleacc.lib;oledlg.lib;sensapi.lib"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\Release/Console.tlb"
|
||||
HeaderFileName=""/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy Release\MAC.exe D:\Data\MAC\Application\MAC.exe"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<File
|
||||
RelativePath="Console.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Shared\Unicows.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="Resource Script.rc">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="resource.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
103
MAC_SDK/Source/Console/Resource Script.rc
Normal file
103
MAC_SDK/Source/Console/Resource Script.rc
Normal file
@@ -0,0 +1,103 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,9,9,0
|
||||
PRODUCTVERSION 3,9,9,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Console front-end for Monkey's Audio"
|
||||
VALUE "CompanyName", "Matthew T. Ashland"
|
||||
VALUE "FileDescription", "Monkey's Audio Console Front-End"
|
||||
VALUE "FileVersion", "3.99"
|
||||
VALUE "InternalName", "MAC"
|
||||
VALUE "LegalCopyright", "Copyright <20> 2000-2004"
|
||||
VALUE "OriginalFilename", "MAC.exe"
|
||||
VALUE "ProductName", "Monkey's Audio"
|
||||
VALUE "ProductVersion", "3.99"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
15
MAC_SDK/Source/Console/resource.h
Normal file
15
MAC_SDK/Source/Console/resource.h
Normal file
@@ -0,0 +1,15 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by Resource Script.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
25
MAC_SDK/Source/Credits.txt
Normal file
25
MAC_SDK/Source/Credits.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
Source Code Credits: (listed in alphabetical order by first name)
|
||||
|
||||
Chun-Yu Shei:
|
||||
- cool suggestion for a slightly more optimized GetSaturatedShortFromInt(...) routine
|
||||
|
||||
David Bryant:
|
||||
- lots of ideas and support from continued discussions
|
||||
|
||||
Florin Ghido:
|
||||
- planted the seed for a more efficient stereo decorrelator
|
||||
|
||||
Frank Klemm:
|
||||
- helped with several Linux building issues, APEv2 tags, and MD5 checksums
|
||||
|
||||
Janne Hyv<79>rinen: (case@mobiili.net)
|
||||
- donated some nice UTF / ANSI conversion code for APE version 2 tagging
|
||||
|
||||
Torgeir Strand Henriksen: (torgshen@stud.iet.hist.no)
|
||||
- did all the footwork to enable BACKWARDS_COMPATIBILITY without requiring assembly
|
||||
|
||||
Michael Bevin: (support@lossless-audio.com)
|
||||
- had a good entropy idea for improving entropy coding ( http://www.lossless-audio.com/theory.htm )
|
||||
|
||||
Igor Janos: (radscorpion@radlight.com)
|
||||
- wrote the APE DirectShow filter
|
||||
79
MAC_SDK/Source/History.txt
Normal file
79
MAC_SDK/Source/History.txt
Normal file
@@ -0,0 +1,79 @@
|
||||
History:
|
||||
|
||||
Monkey's Audio 3.99 Update 4
|
||||
|
||||
1. Fixed: Decoder could erroneously report a CRC error on the last frame of some files.
|
||||
|
||||
Monkey's Audio 3.99 Update 3
|
||||
|
||||
1. Changed: Worked on making data types more standard / cross-platform friendly.
|
||||
2. Changed: Switched code from tab-based to space based. (may still be some out-of-whack formatting)
|
||||
3. Fixed: Building ID3 tags could cause a crash.
|
||||
4. Fixed: APL builder treated the last part of a CUE time as a hundreth of a second instead of as a frame. (1 / 75 of a second)
|
||||
5. Fixed: File Info dialog used by Winamp plugin wouldn't accept / save Unicode tag values properly.
|
||||
6. Fixed: APL files could output noise or silence at the end of the file in some cases.
|
||||
|
||||
Monkey's Audio 3.99 Update 2
|
||||
|
||||
1. Fixed: Possible buffer overflow attack weakness in APE tagging code.
|
||||
2. Fixed: MACDll.dll was not doing ANSI to Unicode conversions properly.
|
||||
3. Changed: Added Unicode versions of interface wrappers to MACDll.dll.
|
||||
4. Changed: Updated Winamp plugin to better handle Unicode.
|
||||
5. Changed: Removed peak-level normalize from file and Winamp plugin. (newer players can do normalize / replay gain during playback)
|
||||
6. Changed: Updated Cool Edit filter to 3.99.
|
||||
|
||||
Monkey's Audio 3.99 Update 1
|
||||
|
||||
1. Fixed: MACDll.dll wasn't working on Win9x / ME systems.
|
||||
2. Changed: MAC.exe updated to 3.99.
|
||||
|
||||
Monkey's Audio 3.99
|
||||
|
||||
1. Changed: Decoding engine better at handling corrupt streams / loss of internet connection while playing.
|
||||
2. Changed: Simplified assembly code building for 3rd party developers.
|
||||
3. NEW: Improved entropy coder for increased compression.
|
||||
4. Changed: Removed RKAU support. (since it is no longer commonly used)
|
||||
|
||||
Monkey's Audio 3.98a1
|
||||
|
||||
1. Changed: Now natively using APE tag version 2 tagging. (updated spec for better streaming and international support)
|
||||
2. Changed: Using smaller frame sizes with Fast, Normal, and High for faster, smoother seeking.
|
||||
3. NEW: Added built-in MD5 checking, for super secure, super fast file verification.
|
||||
4. Changed: Using a new and improved file header format.
|
||||
5. NEW: Added "Insane" mode for when compression is all that matters.
|
||||
6. NEW: Introduced new GUI.
|
||||
- full Unicode support
|
||||
- few or no dependencies
|
||||
- multi-thread friendly -- can process multiple files at once
|
||||
- XML based external plugin architecture
|
||||
|
||||
Monkey's Audio 3.97 (July 7, 2002)
|
||||
|
||||
1. Changed: "Save File List Between Sessions" now on by default in front end.
|
||||
2. Changed: Replaced usage of "#pragma once" with more non-MS compiler friendly alterternative.
|
||||
3. NEW: MakeAPL now supports command line APL generation. (pass a .CUE file (no wildcards yet) -- operates in silent mode using existing settings)
|
||||
4. Changed: Assembly support no longer required for backwards compatibility. (thanks Torgeir Strand Henriksen)
|
||||
5. Changed: Several non-Windows buildability issues.
|
||||
6. Changed: Using NASM to compile all assembly code. (aids cross-platform buildability)
|
||||
7. Changed: Encapsulated the APELink code.
|
||||
8. Changed: Tags aren't analyzed immediately when opening an http:// or m01p:// stream.
|
||||
9. Changed: Added more functionality to the APL parser.
|
||||
10. Changed: Added CreateIAPEDecompressEx2(...) to allow the creation of a ranged decoder.
|
||||
|
||||
Monkey's Audio 3.96 (April 7, 2002)
|
||||
|
||||
1. Fixed: WAV analysis could hang on invalid wav files.
|
||||
2. Changed: Monkey's Audio would try to analyze files with file extensions not related to Monkey's Audio.
|
||||
3. NEW: Added APE_DECOMPRESS_AVERAGE_BITRATE field so APL's can report the bitrate for the region they represent.
|
||||
4. Changed: Improved overall non-Windows build-ability. (MACLib.lib doesn't require <windows.h> to build)
|
||||
5. Changed: APL parser no longer requires Windows.
|
||||
6. Fixed: APE tagging code would fail to save tags for files with existing ID3v1 tags.
|
||||
7. Fixed: MakeAPL would not run on Win95 / 98.
|
||||
8. Changed: More non-Windows build-ability issues.
|
||||
9. Changed: Minor assembly optimizations. (like a 2% performance improvement)
|
||||
10. Changed: MACLib now builds with gcc under Linux. (no backwards compatibility or assembly support yet)
|
||||
11. Fixed: Bitstream fix / change that may have accounted for decompression failures in extremely rare cases.
|
||||
12. Changed: Slight NNFilter optimization. (thanks to Chun-Yu Shei)
|
||||
13. Changed: Turned off "Explorer" by default for the Monkey's Audio GUI. (doesn't work well under XP... will still leave it in for a while)
|
||||
14. Changed: Included the WavPack 3.93.
|
||||
15. Changed: Changed the history reporting method.
|
||||
48
MAC_SDK/Source/License.htm
Normal file
48
MAC_SDK/Source/License.htm
Normal file
@@ -0,0 +1,48 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Well</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p align="center"><font face="Verdana" size="4">Monkey's Audio Source Code
|
||||
License Agreement</font></p>
|
||||
<p><font face="Verdana" size="2"><b>License Agreement</b></font></p>
|
||||
<p><font face="Verdana" size="2">1. The use of any of the Monkey<65>s Audio source code or any component thereof from another program requires
|
||||
express written permission from the author of Monkey<65>s Audio.</font></p>
|
||||
<p><font face="Verdana" size="2">2. The use of Monkey's Audio or the Monkey's Audio source code for any commercial purposes including, but not
|
||||
limited to, implementation in shareware packages is strictly prohibited without first obtaining written
|
||||
permission from the author.</font></p>
|
||||
<p><font face="Verdana" size="2">3. All code changes and improvements must be
|
||||
contributed back to the Monkey's Audio project free from restrictions or
|
||||
royalties for the sake of the common good.</font></p>
|
||||
<p><font face="Verdana" size="2">4. Although the software has been tested thoroughly, the author is in no way responsible for damages due to
|
||||
bugs or misuse. </font></p>
|
||||
<p><font face="Verdana" size="2">5. If you do not completely agree with all of
|
||||
the previous stipulations, you must cease using this source code and remove it
|
||||
from your storage device.</font></p>
|
||||
<p> </p>
|
||||
<p><font face="Verdana" size="2"><b>Non-legally Binding License Description</b></font></p>
|
||||
<p><font face="Verdana" size="2">The above license is designed to protect both
|
||||
me, and the Monkey's Audio project. However, anyone who has ever been kind
|
||||
enough to request permission to use Monkey's Audio has been granted the right to
|
||||
do as they please, completely free of charge or royalty. So, the license
|
||||
exists not to hinder what considerate people can do with Monkey's Audio, but
|
||||
instead to protect against the (hopefully few) inconsiderate people.</font></p>
|
||||
<p align="center" style="margin:0in;margin-bottom:.0001pt;text-align:center"> </p>
|
||||
<p align="center" style="margin:0in;margin-bottom:.0001pt;text-align:center"> </p>
|
||||
<p align="center" style="margin:0in;margin-bottom:.0001pt;text-align:center"><i><font face="Verdana" size="2">All
|
||||
rights not expressly granted here are reserved by Matthew T. Ashland.</font></i></p>
|
||||
<p align="center" style="margin:0in;margin-bottom:.0001pt;text-align:center"><font size="2"><font face="Verdana"><span style="mso-bidi-font-family: Arial Unicode MS"> </span></font></font></p>
|
||||
<p align="center" style="margin:0in;margin-bottom:.0001pt;text-align:center"><font face="Verdana" size="2">-
|
||||
All materials and programs copyrighted <20>2000-2002 by Matthew T. Ashland -</font></p>
|
||||
<p align="center" style="margin:0in;margin-bottom:.0001pt;text-align:center"><font face="Verdana" size="2">-
|
||||
All rights reserved. -</font></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
233
MAC_SDK/Source/MACDll/MACDll.cpp
Normal file
233
MAC_SDK/Source/MACDll/MACDll.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
#include "MACDll.h"
|
||||
#include "resource.h"
|
||||
#include "WinFileIO.h"
|
||||
#include "APEInfoDialog.h"
|
||||
#include "WAVInfoDialog.h"
|
||||
#include "APEDecompress.h"
|
||||
#include "APECompressCreate.h"
|
||||
#include "APECompressCore.h"
|
||||
#include "APECompress.h"
|
||||
#include "APEInfo.h"
|
||||
#include "APETag.h"
|
||||
#include "CharacterHelper.h"
|
||||
|
||||
int __stdcall GetVersionNumber()
|
||||
{
|
||||
return MAC_VERSION_NUMBER;
|
||||
}
|
||||
|
||||
int __stdcall GetInterfaceCompatibility(int nVersion, BOOL bDisplayWarningsOnFailure, HWND hwndParent)
|
||||
{
|
||||
int nRetVal = 0;
|
||||
if (nVersion > MAC_VERSION_NUMBER)
|
||||
{
|
||||
nRetVal = -1;
|
||||
if (bDisplayWarningsOnFailure)
|
||||
{
|
||||
TCHAR cMessage[1024];
|
||||
_stprintf(cMessage, _T("You system does not have a new enough version of Monkey's Audio installed.\n")
|
||||
_T("Please visit www.monkeysaudio.com for the latest version.\n\n(version %.2f or later required)"),
|
||||
float(nVersion) / float(1000));
|
||||
MessageBox(hwndParent, cMessage, _T("Please Update Monkey's Audio"), MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
}
|
||||
else if (nVersion < 3940)
|
||||
{
|
||||
nRetVal = -1;
|
||||
if (bDisplayWarningsOnFailure)
|
||||
{
|
||||
TCHAR cMessage[1024];
|
||||
_stprintf(cMessage, _T("This program is trying to use an old version of Monkey's Audio.\n")
|
||||
_T("Please contact the author about updating their support for Monkey's Audio.\n\n")
|
||||
_T("Monkey's Audio currently installed: %.2f\nProgram is searching for: %.2f"),
|
||||
float(MAC_VERSION_NUMBER) / float(1000), float(nVersion) / float(1000));
|
||||
MessageBox(hwndParent, cMessage, _T("Program Requires Updating"), MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int __stdcall ShowFileInfoDialog(const str_ansi * pFilename, HWND hwndWindow)
|
||||
{
|
||||
// convert the filename
|
||||
CSmartPtr<wchar_t> spFilename(GetUTF16FromANSI(pFilename), TRUE);
|
||||
|
||||
// make sure the file exists
|
||||
WIN32_FIND_DATA FindData = { 0 };
|
||||
HANDLE hFind = FindFirstFile(spFilename, &FindData);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
MessageBox(hwndWindow, _T("File not found."), _T("File Info"), MB_OK);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
FindClose(hFind);
|
||||
}
|
||||
|
||||
// see what type the file is
|
||||
if ((_tcsicmp(&spFilename[_tcslen(spFilename) - 4], _T(".ape")) == 0) ||
|
||||
(_tcsicmp(&spFilename[_tcslen(spFilename) - 4], _T(".apl")) == 0))
|
||||
{
|
||||
CAPEInfoDialog APEInfoDialog;
|
||||
APEInfoDialog.ShowAPEInfoDialog(spFilename, GetModuleHandle(_T("MACDll.dll")), (LPCTSTR) IDD_APE_INFO, hwndWindow);
|
||||
return 0;
|
||||
}
|
||||
else if (_tcsicmp(&spFilename[_tcslen(spFilename) - 4], _T(".wav")) == 0)
|
||||
{
|
||||
CWAVInfoDialog WAVInfoDialog;
|
||||
WAVInfoDialog.ShowWAVInfoDialog(spFilename, GetModuleHandle(_T("MACDll.dll")), (LPCTSTR) IDD_WAV_INFO, hwndWindow);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox(hwndWindow, _T("File type not supported. (only .ape, .apl, and .wav files currently supported)"), _T("File Info: Unsupported File Type"), MB_OK);
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
int __stdcall TagFileSimple(const str_ansi * pFilename, const char * pArtist, const char * pAlbum, const char * pTitle, const char * pComment, const char * pGenre, const char * pYear, const char * pTrack, BOOL bClearFirst, BOOL bUseOldID3)
|
||||
{
|
||||
CSmartPtr<wchar_t> spFilename(GetUTF16FromANSI(pFilename), TRUE);
|
||||
|
||||
IO_CLASS_NAME FileIO;
|
||||
if (FileIO.Open(spFilename) != 0)
|
||||
return -1;
|
||||
|
||||
CAPETag APETag(&FileIO, TRUE);
|
||||
|
||||
if (bClearFirst)
|
||||
APETag.ClearFields();
|
||||
|
||||
APETag.SetFieldString(APE_TAG_FIELD_ARTIST, pArtist, TRUE);
|
||||
APETag.SetFieldString(APE_TAG_FIELD_ALBUM, pAlbum, TRUE);
|
||||
APETag.SetFieldString(APE_TAG_FIELD_TITLE, pTitle, TRUE);
|
||||
APETag.SetFieldString(APE_TAG_FIELD_GENRE, pGenre, TRUE);
|
||||
APETag.SetFieldString(APE_TAG_FIELD_YEAR, pYear, TRUE);
|
||||
APETag.SetFieldString(APE_TAG_FIELD_COMMENT, pComment, TRUE);
|
||||
APETag.SetFieldString(APE_TAG_FIELD_TRACK, pTrack, TRUE);
|
||||
|
||||
if (APETag.Save(bUseOldID3) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __stdcall GetID3Tag(const str_ansi * pFilename, ID3_TAG * pID3Tag)
|
||||
{
|
||||
CSmartPtr<wchar_t> spFilename(GetUTF16FromANSI(pFilename), TRUE);
|
||||
|
||||
IO_CLASS_NAME FileIO;
|
||||
if (FileIO.Open(spFilename) != 0)
|
||||
return -1;
|
||||
|
||||
CAPETag APETag(&FileIO, TRUE);
|
||||
|
||||
return APETag.CreateID3Tag(pID3Tag);
|
||||
}
|
||||
|
||||
int __stdcall RemoveTag(char * pFilename)
|
||||
{
|
||||
CSmartPtr<wchar_t> spFilename(GetUTF16FromANSI(pFilename), TRUE);
|
||||
|
||||
int nErrorCode = ERROR_SUCCESS;
|
||||
CSmartPtr<IAPEDecompress> spAPEDecompress(CreateIAPEDecompress(spFilename, &nErrorCode));
|
||||
if (spAPEDecompress == NULL) return -1;
|
||||
GET_TAG(spAPEDecompress)->Remove(FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
CAPEDecompress wrapper(s)
|
||||
*****************************************************************************************/
|
||||
APE_DECOMPRESS_HANDLE __stdcall c_APEDecompress_Create(const str_ansi * pFilename, int * pErrorCode)
|
||||
{
|
||||
CSmartPtr<wchar_t> spFilename(GetUTF16FromANSI(pFilename), TRUE);
|
||||
return (APE_DECOMPRESS_HANDLE) CreateIAPEDecompress(spFilename, pErrorCode);
|
||||
}
|
||||
|
||||
APE_DECOMPRESS_HANDLE __stdcall c_APEDecompress_CreateW(const str_utf16 * pFilename, int * pErrorCode)
|
||||
{
|
||||
return (APE_DECOMPRESS_HANDLE) CreateIAPEDecompress(pFilename, pErrorCode);
|
||||
}
|
||||
|
||||
void __stdcall c_APEDecompress_Destroy(APE_DECOMPRESS_HANDLE hAPEDecompress)
|
||||
{
|
||||
IAPEDecompress * pAPEDecompress = (IAPEDecompress *) hAPEDecompress;
|
||||
if (pAPEDecompress)
|
||||
delete pAPEDecompress;
|
||||
}
|
||||
|
||||
int __stdcall c_APEDecompress_GetData(APE_DECOMPRESS_HANDLE hAPEDecompress, char * pBuffer, int nBlocks, int * pBlocksRetrieved)
|
||||
{
|
||||
return ((IAPEDecompress *) hAPEDecompress)->GetData(pBuffer, nBlocks, pBlocksRetrieved);
|
||||
}
|
||||
|
||||
int __stdcall c_APEDecompress_Seek(APE_DECOMPRESS_HANDLE hAPEDecompress, int nBlockOffset)
|
||||
{
|
||||
return ((IAPEDecompress *) hAPEDecompress)->Seek(nBlockOffset);
|
||||
}
|
||||
|
||||
int __stdcall c_APEDecompress_GetInfo(APE_DECOMPRESS_HANDLE hAPEDecompress, APE_DECOMPRESS_FIELDS Field, int nParam1, int nParam2)
|
||||
{
|
||||
return ((IAPEDecompress *) hAPEDecompress)->GetInfo(Field, nParam1, nParam2);
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
CAPECompress wrapper(s)
|
||||
*****************************************************************************************/
|
||||
APE_COMPRESS_HANDLE __stdcall c_APECompress_Create(int * pErrorCode)
|
||||
{
|
||||
return (APE_COMPRESS_HANDLE) CreateIAPECompress(pErrorCode);
|
||||
}
|
||||
|
||||
void __stdcall c_APECompress_Destroy(APE_COMPRESS_HANDLE hAPECompress)
|
||||
{
|
||||
IAPECompress * pAPECompress = (IAPECompress *) hAPECompress;
|
||||
if (pAPECompress)
|
||||
delete pAPECompress;
|
||||
}
|
||||
|
||||
int __stdcall c_APECompress_Start(APE_COMPRESS_HANDLE hAPECompress, const char * pOutputFilename, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel, const void * pHeaderData, int nHeaderBytes)
|
||||
{
|
||||
CSmartPtr<wchar_t> spOutputFilename(GetUTF16FromANSI(pOutputFilename), TRUE);
|
||||
return ((IAPECompress *) hAPECompress)->Start(spOutputFilename, pwfeInput, nMaxAudioBytes, nCompressionLevel, pHeaderData, nHeaderBytes);
|
||||
}
|
||||
|
||||
int __stdcall c_APECompress_StartW(APE_COMPRESS_HANDLE hAPECompress, const str_utf16 * pOutputFilename, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel, const void * pHeaderData, int nHeaderBytes)
|
||||
{
|
||||
return ((IAPECompress *) hAPECompress)->Start(pOutputFilename, pwfeInput, nMaxAudioBytes, nCompressionLevel, pHeaderData, nHeaderBytes);
|
||||
}
|
||||
|
||||
int __stdcall c_APECompress_AddData(APE_COMPRESS_HANDLE hAPECompress, unsigned char * pData, int nBytes)
|
||||
{
|
||||
return ((IAPECompress *) hAPECompress)->AddData(pData, nBytes);
|
||||
}
|
||||
|
||||
int __stdcall c_APECompress_GetBufferBytesAvailable(APE_COMPRESS_HANDLE hAPECompress)
|
||||
{
|
||||
return ((IAPECompress *) hAPECompress)->GetBufferBytesAvailable();
|
||||
}
|
||||
|
||||
unsigned char * __stdcall c_APECompress_LockBuffer(APE_COMPRESS_HANDLE hAPECompress, int * pBytesAvailable)
|
||||
{
|
||||
return ((IAPECompress *) hAPECompress)->LockBuffer(pBytesAvailable);
|
||||
}
|
||||
|
||||
int __stdcall c_APECompress_UnlockBuffer(APE_COMPRESS_HANDLE hAPECompress, int nBytesAdded, BOOL bProcess)
|
||||
{
|
||||
return ((IAPECompress *) hAPECompress)->UnlockBuffer(nBytesAdded, bProcess);
|
||||
}
|
||||
|
||||
int __stdcall c_APECompress_Finish(APE_COMPRESS_HANDLE hAPECompress, unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes)
|
||||
{
|
||||
return ((IAPECompress *) hAPECompress)->Finish(pTerminatingData, nTerminatingBytes, nWAVTerminatingBytes);
|
||||
}
|
||||
|
||||
int __stdcall c_APECompress_Kill(APE_COMPRESS_HANDLE hAPECompress)
|
||||
{
|
||||
return ((IAPECompress *) hAPECompress)->Kill();
|
||||
}
|
||||
38
MAC_SDK/Source/MACDll/MACDll.def
Normal file
38
MAC_SDK/Source/MACDll/MACDll.def
Normal file
@@ -0,0 +1,38 @@
|
||||
LIBRARY MACDll
|
||||
|
||||
EXPORTS
|
||||
|
||||
; basic functions
|
||||
CompressFile
|
||||
DecompressFile
|
||||
ConvertFile
|
||||
VerifyFile
|
||||
|
||||
; interface wrappers
|
||||
c_APEDecompress_Create
|
||||
c_APEDecompress_Destroy
|
||||
c_APEDecompress_GetData
|
||||
c_APEDecompress_Seek
|
||||
c_APEDecompress_GetInfo
|
||||
|
||||
c_APECompress_Create
|
||||
c_APECompress_Destroy
|
||||
c_APECompress_Start
|
||||
c_APECompress_AddData
|
||||
c_APECompress_GetBufferBytesAvailable
|
||||
c_APECompress_LockBuffer
|
||||
c_APECompress_UnlockBuffer
|
||||
c_APECompress_Finish
|
||||
c_APECompress_Kill
|
||||
|
||||
; helpers / miscellaneous
|
||||
GetVersionNumber
|
||||
GetInterfaceCompatibility
|
||||
ShowFileInfoDialog
|
||||
RemoveTag
|
||||
TagFileSimple
|
||||
GetID3Tag
|
||||
FillWaveHeader
|
||||
FillWaveFormatEx
|
||||
|
||||
|
||||
160
MAC_SDK/Source/MACDll/MACDll.dsp
Normal file
160
MAC_SDK/Source/MACDll/MACDll.dsp
Normal file
@@ -0,0 +1,160 @@
|
||||
# Microsoft Developer Studio Project File - Name="MACDll" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=MACDll - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "MACDll.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "MACDll.mak" CFG="MACDll - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "MACDll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "MACDll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/Monkey's Audio/MACDll", KCAAAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "MACDll - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MACDLL_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /G6 /MT /W3 /GX /Ox /Ot /Og /Oi /Ob2 /I "..\MACLib\\" /I "..\Shared\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MACDLL_EXPORTS" /FR /YX /FD /c
|
||||
# SUBTRACT CPP /Oa
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib maclib.lib /nologo /dll /machine:I386 /libpath:"..\MACLib\Release"
|
||||
# SUBTRACT LINK32 /profile
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Performing post build step...
|
||||
PostBuild_Cmds=copy Release\MACDll.dll c:\Windows\System32\MACDll.dll
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "MACDll - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MACDLL_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\MACLib\\" /I "..\Shared\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MACDLL_EXPORTS" /FD /GZ /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 maclib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\MACLib\Debug"
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Performing post build step...
|
||||
PostBuild_Cmds=copy Debug\MACDll.dll c:\Windows\System32\MACDll.dll
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "MACDll - Win32 Release"
|
||||
# Name "MACDll - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\APEInfoDialog.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MACDll.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MACDll.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=".\Resource Script.rc"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\WAVInfoDialog.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\APEInfoDialog.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MACDll.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\WAVInfoDialog.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=".\Monkey Head (1).ico"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=".\Monkey Head.ico"
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
99
MAC_SDK/Source/MACDll/MACDll.h
Normal file
99
MAC_SDK/Source/MACDll/MACDll.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*****************************************************************************************
|
||||
Monkey's Audio MACDll.h (include for using MACDll.dll in your projects)
|
||||
Copyright (C) 2000-2004 by Matthew T. Ashland All Rights Reserved.
|
||||
|
||||
Overview:
|
||||
|
||||
Basically all this dll does is wrap MACLib.lib, so browse through MACLib.h for documentation
|
||||
on how to use the interfaces.
|
||||
|
||||
Questions / Suggestions:
|
||||
|
||||
Please direct questions or comments to the Monkey's Audio developers board:
|
||||
http://www.monkeysaudio.com/cgi-bin/YaBB/YaBB.cgi -> Developers
|
||||
or, if necessary, matt @ monkeysaudio.com
|
||||
*****************************************************************************************/
|
||||
|
||||
#ifndef APE_MACDLL_H
|
||||
#define APE_MACDLL_H
|
||||
|
||||
/*****************************************************************************************
|
||||
Includes
|
||||
*****************************************************************************************/
|
||||
#include "All.h"
|
||||
#include "MACLib.h"
|
||||
|
||||
/*****************************************************************************************
|
||||
Defines (implemented elsewhere)
|
||||
*****************************************************************************************/
|
||||
struct ID3_TAG;
|
||||
|
||||
/*****************************************************************************************
|
||||
Helper functions
|
||||
*****************************************************************************************/
|
||||
extern "C"
|
||||
{
|
||||
__declspec( dllexport ) int __stdcall GetVersionNumber();
|
||||
__declspec( dllexport ) int __stdcall GetInterfaceCompatibility(int nVersion, BOOL bDisplayWarningsOnFailure = TRUE, HWND hwndParent = NULL);
|
||||
__declspec( dllexport ) int __stdcall ShowFileInfoDialog(const str_ansi * pFilename, HWND hwndWindow);
|
||||
__declspec( dllexport ) int __stdcall TagFileSimple(const str_ansi * pFilename, const char * pArtist, const char * pAlbum, const char * pTitle, const char * pComment, const char * pGenre, const char * pYear, const char * pTrack, BOOL bClearFirst, BOOL bUseOldID3);
|
||||
__declspec( dllexport ) int __stdcall GetID3Tag(const str_ansi * pFilename, ID3_TAG * pID3Tag);
|
||||
__declspec( dllexport ) int __stdcall RemoveTag(const str_ansi * pFilename);
|
||||
}
|
||||
|
||||
typedef int (__stdcall * proc_GetVersionNumber)();
|
||||
typedef int (__stdcall * proc_GetInterfaceCompatibility)(int, BOOL, HWND);
|
||||
|
||||
/*****************************************************************************************
|
||||
IAPECompress wrapper(s)
|
||||
*****************************************************************************************/
|
||||
typedef void * APE_COMPRESS_HANDLE;
|
||||
|
||||
typedef APE_COMPRESS_HANDLE (__stdcall * proc_APECompress_Create)(int *);
|
||||
typedef void (__stdcall * proc_APECompress_Destroy)(APE_COMPRESS_HANDLE);
|
||||
typedef int (__stdcall * proc_APECompress_Start)(APE_COMPRESS_HANDLE, const char *, const WAVEFORMATEX *, int, int, const void *, int);
|
||||
typedef int (__stdcall * proc_APECompress_StartW)(APE_COMPRESS_HANDLE, const char *, const WAVEFORMATEX *, int, int, const void *, int);
|
||||
typedef int (__stdcall * proc_APECompress_AddData)(APE_COMPRESS_HANDLE, unsigned char *, int);
|
||||
typedef int (__stdcall * proc_APECompress_GetBufferBytesAvailable)(APE_COMPRESS_HANDLE);
|
||||
typedef unsigned char * (__stdcall * proc_APECompress_LockBuffer)(APE_COMPRESS_HANDLE, int *);
|
||||
typedef int (__stdcall * proc_APECompress_UnlockBuffer)(APE_COMPRESS_HANDLE, int, BOOL);
|
||||
typedef int (__stdcall * proc_APECompress_Finish)(APE_COMPRESS_HANDLE, unsigned char *, int, int);
|
||||
typedef int (__stdcall * proc_APECompress_Kill)(APE_COMPRESS_HANDLE);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec( dllexport ) APE_COMPRESS_HANDLE __stdcall c_APECompress_Create(int * pErrorCode = NULL);
|
||||
__declspec( dllexport ) void __stdcall c_APECompress_Destroy(APE_COMPRESS_HANDLE hAPECompress);
|
||||
__declspec( dllexport ) int __stdcall c_APECompress_Start(APE_COMPRESS_HANDLE hAPECompress, const char * pOutputFilename, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes = MAX_AUDIO_BYTES_UNKNOWN, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, const unsigned char * pHeaderData = NULL, int nHeaderBytes = CREATE_WAV_HEADER_ON_DECOMPRESSION);
|
||||
__declspec( dllexport ) int __stdcall c_APECompress_StartW(APE_COMPRESS_HANDLE hAPECompress, const str_utf16 * pOutputFilename, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes = MAX_AUDIO_BYTES_UNKNOWN, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, const unsigned char * pHeaderData = NULL, int nHeaderBytes = CREATE_WAV_HEADER_ON_DECOMPRESSION);
|
||||
__declspec( dllexport ) int __stdcall c_APECompress_AddData(APE_COMPRESS_HANDLE hAPECompress, unsigned char * pData, int nBytes);
|
||||
__declspec( dllexport ) int __stdcall c_APECompress_GetBufferBytesAvailable(APE_COMPRESS_HANDLE hAPECompress);
|
||||
__declspec( dllexport ) unsigned char * __stdcall c_APECompress_LockBuffer(APE_COMPRESS_HANDLE hAPECompress, int * pBytesAvailable);
|
||||
__declspec( dllexport ) int __stdcall c_APECompress_UnlockBuffer(APE_COMPRESS_HANDLE hAPECompress, int nBytesAdded, BOOL bProcess = TRUE);
|
||||
__declspec( dllexport ) int __stdcall c_APECompress_Finish(APE_COMPRESS_HANDLE hAPECompress, unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes);
|
||||
__declspec( dllexport ) int __stdcall c_APECompress_Kill(APE_COMPRESS_HANDLE hAPECompress);
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
IAPEDecompress wrapper(s)
|
||||
*****************************************************************************************/
|
||||
typedef void * APE_DECOMPRESS_HANDLE;
|
||||
|
||||
typedef APE_DECOMPRESS_HANDLE (__stdcall * proc_APEDecompress_Create)(const char *, int *);
|
||||
typedef APE_DECOMPRESS_HANDLE (__stdcall * proc_APEDecompress_CreateW)(const char *, int *);
|
||||
typedef void (__stdcall * proc_APEDecompress_Destroy)(APE_DECOMPRESS_HANDLE);
|
||||
typedef int (__stdcall * proc_APEDecompress_GetData)(APE_DECOMPRESS_HANDLE, char *, int, int *);
|
||||
typedef int (__stdcall * proc_APEDecompress_Seek)(APE_DECOMPRESS_HANDLE, int);
|
||||
typedef int (__stdcall * proc_APEDecompress_GetInfo)(APE_DECOMPRESS_HANDLE, APE_DECOMPRESS_FIELDS, int, int);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec( dllexport ) APE_DECOMPRESS_HANDLE __stdcall c_APEDecompress_Create(const str_ansi * pFilename, int * pErrorCode = NULL);
|
||||
__declspec( dllexport ) APE_DECOMPRESS_HANDLE __stdcall c_APEDecompress_CreateW(const str_utf16 * pFilename, int * pErrorCode = NULL);
|
||||
__declspec( dllexport ) void __stdcall c_APEDecompress_Destroy(APE_DECOMPRESS_HANDLE hAPEDecompress);
|
||||
__declspec( dllexport ) int __stdcall c_APEDecompress_GetData(APE_DECOMPRESS_HANDLE hAPEDecompress, char * pBuffer, int nBlocks, int * pBlocksRetrieved);
|
||||
__declspec( dllexport ) int __stdcall c_APEDecompress_Seek(APE_DECOMPRESS_HANDLE hAPEDecompress, int nBlockOffset);
|
||||
__declspec( dllexport ) int __stdcall c_APEDecompress_GetInfo(APE_DECOMPRESS_HANDLE hAPEDecompress, APE_DECOMPRESS_FIELDS Field, int nParam1 = 0, int nParam2 = 0);
|
||||
}
|
||||
|
||||
#endif // #ifndef APE_MACDLL_H
|
||||
261
MAC_SDK/Source/MACDll/MACDll.vcproj
Normal file
261
MAC_SDK/Source/MACDll/MACDll.vcproj
Normal file
@@ -0,0 +1,261 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="MACDll"
|
||||
ProjectGUID="{F7EE0746-C0AD-4045-B8B9-1CB2AFDFCB96}"
|
||||
SccProjectName=""$/Monkey's Audio/MACDll", KCAAAAAA"
|
||||
SccAuxPath=""
|
||||
SccLocalPath="."
|
||||
SccProvider="MSSCCI:Microsoft Visual SourceSafe">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\Release"
|
||||
IntermediateDirectory=".\Release"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="1">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\MACLib\,..\Shared\"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MACDLL_EXPORTS"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\Release/MACDll.pch"
|
||||
AssemblerListingLocation=".\Release/"
|
||||
ObjectFile=".\Release/"
|
||||
ProgramDataBaseFileName=".\Release/"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="unicows.lib kernel32.lib advapi32.lib user32.lib gdi32.lib shell32.lib comdlg32.lib version.lib mpr.lib rasapi32.lib winmm.lib winspool.lib vfw32.lib secur32.lib oleacc.lib oledlg.lib sensapi.lib maclib.lib"
|
||||
OutputFile=".\Release/MACDll.dll"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories="..\MACLib\Release"
|
||||
IgnoreDefaultLibraryNames="kernel32.lib;advapi32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;version.lib;mpr.lib;rasapi32.lib;winmm.lib;winspool.lib;vfw32.lib;secur32.lib;oleacc.lib;oledlg.lib;sensapi.lib"
|
||||
ModuleDefinitionFile=".\MACDll.def"
|
||||
ProgramDatabaseFile=".\Release/MACDll.pdb"
|
||||
ImportLibrary=".\Release/MACDll.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Release/MACDll.tlb"
|
||||
HeaderFileName=""/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="Performing post build step..."
|
||||
CommandLine="copy Release\MACDll.dll c:\Windows\System32\MACDll.dll"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\Debug"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="1">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\MACLib\,..\Shared\"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MACDLL_EXPORTS;"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
PrecompiledHeaderFile=".\Debug/MACDll.pch"
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
ObjectFile=".\Debug/"
|
||||
ProgramDataBaseFileName=".\Debug/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="unicows.lib kernel32.lib advapi32.lib user32.lib gdi32.lib shell32.lib comdlg32.lib version.lib mpr.lib rasapi32.lib winmm.lib winspool.lib vfw32.lib secur32.lib oleacc.lib oledlg.lib sensapi.lib maclib.lib"
|
||||
OutputFile=".\Debug/MACDll.dll"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories="..\MACLib\Debug"
|
||||
IgnoreDefaultLibraryNames="kernel32.lib;advapi32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;version.lib;mpr.lib;rasapi32.lib;winmm.lib;winspool.lib;vfw32.lib;secur32.lib;oleacc.lib;oledlg.lib;sensapi.lib"
|
||||
ModuleDefinitionFile=".\MACDll.def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile=".\Debug/MACDll.pdb"
|
||||
ImportLibrary=".\Debug/MACDll.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Debug/MACDll.tlb"
|
||||
HeaderFileName=""/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="Performing post build step..."
|
||||
CommandLine="copy Debug\MACDll.dll c:\Windows\System32\MACDll.dll"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<File
|
||||
RelativePath="..\Shared\APEInfoDialog.cpp">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
AdditionalIncludeDirectories=""
|
||||
BrowseInformation="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
BasicRuntimeChecks="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MACDll.cpp">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
AdditionalIncludeDirectories=""
|
||||
BrowseInformation="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
BasicRuntimeChecks="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MACDll.def">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Resource Script.rc">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Shared\Unicows.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Shared\WAVInfoDialog.cpp">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
AdditionalIncludeDirectories=""
|
||||
BrowseInformation="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
BasicRuntimeChecks="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl">
|
||||
<File
|
||||
RelativePath="..\Shared\APEInfoDialog.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MACDll.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="resource.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Shared\WAVInfoDialog.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
|
||||
<File
|
||||
RelativePath="Monkey Head (1).ico">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Monkey Head.ico">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
BIN
MAC_SDK/Source/MACDll/Monkey Head (1).ico
Normal file
BIN
MAC_SDK/Source/MACDll/Monkey Head (1).ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
MAC_SDK/Source/MACDll/Monkey Head.ico
Normal file
BIN
MAC_SDK/Source/MACDll/Monkey Head.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
226
MAC_SDK/Source/MACDll/Resource Script.rc
Normal file
226
MAC_SDK/Source/MACDll/Resource Script.rc
Normal file
@@ -0,0 +1,226 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_WAV_INFO, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 195
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 95
|
||||
END
|
||||
|
||||
IDD_APE_INFO, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 242
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 211
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_MONKEY_LEFT ICON "Monkey Head.ico"
|
||||
IDI_MONKEY_RIGHT ICON "Monkey Head (1).ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_WAV_INFO DIALOG 0, 0, 202, 102
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION |
|
||||
WS_SYSMENU
|
||||
CAPTION "WAV File Info"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
ICON IDI_MONKEY_LEFT,IDC_STATIC,2,2,20,20
|
||||
ICON IDI_MONKEY_RIGHT,IDC_STATIC,180,0,20,20
|
||||
GROUPBOX "Size Info",IDC_STATIC,5,28,93,68
|
||||
GROUPBOX "Audio Info",IDC_STATIC,105,28,92,47
|
||||
LTEXT "Bits Per Sample:",3002,115,60,78,8,SS_NOPREFIX
|
||||
LTEXT "Channels:",3001,115,50,78,8,SS_NOPREFIX
|
||||
LTEXT "Sample Rate:",3000,115,39,78,8,SS_NOPREFIX
|
||||
LTEXT "Track Length:",2001,15,50,78,8,SS_NOPREFIX
|
||||
LTEXT "File Size:",2000,15,39,78,8,SS_NOPREFIX
|
||||
LTEXT "Terminating Bytes:",2004,15,82,78,8,SS_NOPREFIX
|
||||
LTEXT "Header Bytes:",2003,15,71,78,8,SS_NOPREFIX
|
||||
LTEXT "Audio Bytes:",2002,15,60,78,8,SS_NOPREFIX
|
||||
PUSHBUTTON "OK",4000,105,81,92,15
|
||||
CTEXT "File Name...",1000,26,2,152,18
|
||||
END
|
||||
|
||||
IDD_APE_INFO DIALOG 0, 0, 249, 218
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION |
|
||||
WS_SYSMENU
|
||||
CAPTION "APE File Info"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
EDITTEXT 5000,49,99,189,12,ES_AUTOHSCROLL
|
||||
EDITTEXT 5001,49,115,189,12,ES_AUTOHSCROLL
|
||||
EDITTEXT 5002,49,131,189,12,ES_AUTOHSCROLL
|
||||
EDITTEXT 5003,49,147,189,12,ES_AUTOHSCROLL
|
||||
EDITTEXT 5004,49,163,24,12,ES_AUTOHSCROLL
|
||||
COMBOBOX 5005,109,163,77,85,CBS_DROPDOWN | CBS_OEMCONVERT |
|
||||
CBS_SORT | WS_VSCROLL | WS_TABSTOP
|
||||
EDITTEXT 5006,220,163,18,12,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "Save Tag",6000,11,195,69,12
|
||||
PUSHBUTTON "Remove Tag",6001,90,195,69,12
|
||||
PUSHBUTTON "Cancel",6002,169,195,69,12
|
||||
ICON IDI_MONKEY_LEFT,IDC_STATIC,3,3,20,20
|
||||
ICON IDI_MONKEY_RIGHT,IDC_STATIC,225,3,20,20
|
||||
CONTROL "Format Flags:",2002,"Static",SS_LEFTNOWORDWRAP |
|
||||
SS_NOPREFIX | WS_GROUP,11,61,59,8
|
||||
CONTROL "Mode:",2001,"Static",SS_LEFTNOWORDWRAP | SS_NOPREFIX |
|
||||
WS_GROUP,11,50,59,8
|
||||
CONTROL "Version:",2000,"Static",SS_LEFTNOWORDWRAP | SS_NOPREFIX |
|
||||
WS_GROUP,11,39,59,8
|
||||
GROUPBOX "Format Info",IDC_STATIC,5,29,70,56
|
||||
GROUPBOX "Audio Info",IDC_STATIC,79,29,78,56
|
||||
CONTROL "Bits Per Sample:",3002,"Static",SS_LEFTNOWORDWRAP |
|
||||
SS_NOPREFIX | WS_GROUP,86,61,66,8
|
||||
CONTROL "Channels:",3001,"Static",SS_LEFTNOWORDWRAP |
|
||||
SS_NOPREFIX | WS_GROUP,86,50,66,8
|
||||
CONTROL "Sample Rate:",3000,"Static",SS_LEFTNOWORDWRAP |
|
||||
SS_NOPREFIX | WS_GROUP,86,39,66,8
|
||||
GROUPBOX "Tag Info",IDC_STATIC,5,88,240,94
|
||||
LTEXT "Album:",IDC_STATIC,11,134,23,8,SS_NOPREFIX
|
||||
LTEXT "Artist:",IDC_STATIC,11,118,23,8,SS_NOPREFIX
|
||||
LTEXT "Title:",IDC_STATIC,11,102,18,8,SS_NOPREFIX
|
||||
LTEXT "Comment:",IDC_STATIC,11,150,33,8,SS_NOPREFIX
|
||||
LTEXT "Year:",IDC_STATIC,11,166,18,8,SS_NOPREFIX
|
||||
LTEXT "Genre: ",IDC_STATIC,82,166,24,8,SS_NOPREFIX
|
||||
CONTROL "Length:",4000,"Static",SS_LEFTNOWORDWRAP | SS_NOPREFIX |
|
||||
WS_GROUP,167,39,71,8
|
||||
CONTROL "Compression:",4003,"Static",SS_LEFTNOWORDWRAP |
|
||||
SS_NOPREFIX | WS_GROUP,167,72,71,8
|
||||
LTEXT "Track:",IDC_STATIC,195,166,22,8,SS_NOPREFIX
|
||||
GROUPBOX "Exit",IDC_STATIC,5,185,240,29
|
||||
CONTROL "Peak Level:",3003,"Static",SS_LEFTNOWORDWRAP |
|
||||
SS_NOPREFIX | WS_GROUP,86,72,66,8
|
||||
EDITTEXT 1000,28,4,193,18,ES_CENTER | ES_MULTILINE |
|
||||
ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
|
||||
CONTROL "APE:",4002,"Static",SS_LEFTNOWORDWRAP | SS_NOPREFIX |
|
||||
WS_GROUP,167,61,71,8
|
||||
CONTROL "Tagged:",2003,"Static",SS_LEFTNOWORDWRAP | SS_NOPREFIX |
|
||||
WS_GROUP,11,71,59,9
|
||||
GROUPBOX "Length / Size Info",IDC_STATIC,161,29,83,56
|
||||
CONTROL "WAV:",4001,"Static",SS_LEFTNOWORDWRAP | SS_NOPREFIX |
|
||||
WS_GROUP,167,50,71,8
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,9,9,0
|
||||
PRODUCTVERSION 3,9,9,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Compression and decompression library for Monkey's Audio"
|
||||
VALUE "CompanyName", "Matthew T. Ashland"
|
||||
VALUE "FileDescription", "Monkey's Audio DLL Library"
|
||||
VALUE "FileVersion", "3.99"
|
||||
VALUE "LegalCopyright", "Copyright <20> 2000-2004"
|
||||
VALUE "OriginalFilename", "MACDll.dll"
|
||||
VALUE "ProductName", "Monkey's Audio"
|
||||
VALUE "ProductVersion", "3.99"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
20
MAC_SDK/Source/MACDll/resource.h
Normal file
20
MAC_SDK/Source/MACDll/resource.h
Normal file
@@ -0,0 +1,20 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by Resource Script.rc
|
||||
//
|
||||
#define IDD_DIALOG1 101
|
||||
#define IDD_WAV_INFO 101
|
||||
#define IDD_APE_INFO 103
|
||||
#define IDI_MONKEY_LEFT 105
|
||||
#define IDI_MONKEY_RIGHT 106
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 149
|
||||
#define _APS_NEXT_COMMAND_VALUE 40002
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
246
MAC_SDK/Source/MACLib/APECompress.cpp
Normal file
246
MAC_SDK/Source/MACLib/APECompress.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
#include "All.h"
|
||||
#include "APECompress.h"
|
||||
#include IO_HEADER_FILE
|
||||
#include "APECompressCreate.h"
|
||||
#include "WAVInputSource.h"
|
||||
|
||||
CAPECompress::CAPECompress()
|
||||
{
|
||||
m_nBufferHead = 0;
|
||||
m_nBufferTail = 0;
|
||||
m_nBufferSize = 0;
|
||||
m_bBufferLocked = FALSE;
|
||||
m_bOwnsOutputIO = FALSE;
|
||||
m_pioOutput = NULL;
|
||||
|
||||
m_spAPECompressCreate.Assign(new CAPECompressCreate());
|
||||
|
||||
m_pBuffer = NULL;
|
||||
}
|
||||
|
||||
CAPECompress::~CAPECompress()
|
||||
{
|
||||
SAFE_ARRAY_DELETE(m_pBuffer)
|
||||
|
||||
if (m_bOwnsOutputIO)
|
||||
{
|
||||
SAFE_DELETE(m_pioOutput)
|
||||
}
|
||||
}
|
||||
|
||||
int CAPECompress::Start(const wchar_t * pOutputFilename, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel, const void * pHeaderData, int nHeaderBytes)
|
||||
{
|
||||
m_pioOutput = new IO_CLASS_NAME;
|
||||
m_bOwnsOutputIO = TRUE;
|
||||
|
||||
if (m_pioOutput->Create(pOutputFilename) != 0)
|
||||
{
|
||||
return ERROR_INVALID_OUTPUT_FILE;
|
||||
}
|
||||
|
||||
m_spAPECompressCreate->Start(m_pioOutput, pwfeInput, nMaxAudioBytes, nCompressionLevel,
|
||||
pHeaderData, nHeaderBytes);
|
||||
|
||||
SAFE_ARRAY_DELETE(m_pBuffer)
|
||||
m_nBufferSize = m_spAPECompressCreate->GetFullFrameBytes();
|
||||
m_pBuffer = new unsigned char [m_nBufferSize];
|
||||
memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX));
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPECompress::StartEx(CIO * pioOutput, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel, const void * pHeaderData, int nHeaderBytes)
|
||||
{
|
||||
m_pioOutput = pioOutput;
|
||||
m_bOwnsOutputIO = FALSE;
|
||||
|
||||
m_spAPECompressCreate->Start(m_pioOutput, pwfeInput, nMaxAudioBytes, nCompressionLevel,
|
||||
pHeaderData, nHeaderBytes);
|
||||
|
||||
SAFE_ARRAY_DELETE(m_pBuffer)
|
||||
m_nBufferSize = m_spAPECompressCreate->GetFullFrameBytes();
|
||||
m_pBuffer = new unsigned char [m_nBufferSize];
|
||||
memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX));
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPECompress::GetBufferBytesAvailable()
|
||||
{
|
||||
return m_nBufferSize - m_nBufferTail;
|
||||
}
|
||||
|
||||
int CAPECompress::UnlockBuffer(int nBytesAdded, BOOL bProcess)
|
||||
{
|
||||
if (m_bBufferLocked == FALSE)
|
||||
return ERROR_UNDEFINED;
|
||||
|
||||
m_nBufferTail += nBytesAdded;
|
||||
m_bBufferLocked = FALSE;
|
||||
|
||||
if (bProcess)
|
||||
{
|
||||
int nRetVal = ProcessBuffer();
|
||||
if (nRetVal != 0) { return nRetVal; }
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
unsigned char * CAPECompress::LockBuffer(int * pBytesAvailable)
|
||||
{
|
||||
if (m_pBuffer == NULL) { return NULL; }
|
||||
|
||||
if (m_bBufferLocked)
|
||||
return NULL;
|
||||
|
||||
m_bBufferLocked = TRUE;
|
||||
|
||||
if (pBytesAvailable)
|
||||
*pBytesAvailable = GetBufferBytesAvailable();
|
||||
|
||||
return &m_pBuffer[m_nBufferTail];
|
||||
}
|
||||
|
||||
int CAPECompress::AddData(unsigned char * pData, int nBytes)
|
||||
{
|
||||
if (m_pBuffer == NULL) return ERROR_INSUFFICIENT_MEMORY;
|
||||
|
||||
int nBytesDone = 0;
|
||||
|
||||
while (nBytesDone < nBytes)
|
||||
{
|
||||
// lock the buffer
|
||||
int nBytesAvailable = 0;
|
||||
unsigned char * pBuffer = LockBuffer(&nBytesAvailable);
|
||||
if (pBuffer == NULL || nBytesAvailable <= 0)
|
||||
return ERROR_UNDEFINED;
|
||||
|
||||
// calculate how many bytes to copy and add that much to the buffer
|
||||
int nBytesToProcess = min(nBytesAvailable, nBytes - nBytesDone);
|
||||
memcpy(pBuffer, &pData[nBytesDone], nBytesToProcess);
|
||||
|
||||
// unlock the buffer (fail if not successful)
|
||||
int nRetVal = UnlockBuffer(nBytesToProcess);
|
||||
if (nRetVal != ERROR_SUCCESS)
|
||||
return nRetVal;
|
||||
|
||||
// update our progress
|
||||
nBytesDone += nBytesToProcess;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPECompress::Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes)
|
||||
{
|
||||
RETURN_ON_ERROR(ProcessBuffer(TRUE))
|
||||
return m_spAPECompressCreate->Finish(pTerminatingData, nTerminatingBytes, nWAVTerminatingBytes);
|
||||
}
|
||||
|
||||
int CAPECompress::Kill()
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPECompress::ProcessBuffer(BOOL bFinalize)
|
||||
{
|
||||
if (m_pBuffer == NULL) { return ERROR_UNDEFINED; }
|
||||
|
||||
try
|
||||
{
|
||||
// process as much as possible
|
||||
int nThreshold = (bFinalize) ? 0 : m_spAPECompressCreate->GetFullFrameBytes();
|
||||
|
||||
while ((m_nBufferTail - m_nBufferHead) >= nThreshold)
|
||||
{
|
||||
int nFrameBytes = min(m_spAPECompressCreate->GetFullFrameBytes(), m_nBufferTail - m_nBufferHead);
|
||||
|
||||
if (nFrameBytes == 0)
|
||||
break;
|
||||
|
||||
int nRetVal = m_spAPECompressCreate->EncodeFrame(&m_pBuffer[m_nBufferHead], nFrameBytes);
|
||||
if (nRetVal != 0) { return nRetVal; }
|
||||
|
||||
m_nBufferHead += nFrameBytes;
|
||||
}
|
||||
|
||||
// shift the buffer
|
||||
if (m_nBufferHead != 0)
|
||||
{
|
||||
int nBytesLeft = m_nBufferTail - m_nBufferHead;
|
||||
|
||||
if (nBytesLeft != 0)
|
||||
memmove(m_pBuffer, &m_pBuffer[m_nBufferHead], nBytesLeft);
|
||||
|
||||
m_nBufferTail -= m_nBufferHead;
|
||||
m_nBufferHead = 0;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return ERROR_UNDEFINED;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPECompress::AddDataFromInputSource(CInputSource * pInputSource, int nMaxBytes, int * pBytesAdded)
|
||||
{
|
||||
// error check the parameters
|
||||
if (pInputSource == NULL) return ERROR_BAD_PARAMETER;
|
||||
|
||||
// initialize
|
||||
if (pBytesAdded) *pBytesAdded = 0;
|
||||
|
||||
// lock the buffer
|
||||
int nBytesAvailable = 0;
|
||||
unsigned char * pBuffer = LockBuffer(&nBytesAvailable);
|
||||
if ((pBuffer == NULL) || (nBytesAvailable == 0))
|
||||
return ERROR_INSUFFICIENT_MEMORY;
|
||||
|
||||
// calculate the 'ideal' number of bytes
|
||||
unsigned int nBytesRead = 0;
|
||||
|
||||
int nIdealBytes = m_spAPECompressCreate->GetFullFrameBytes() - (m_nBufferTail - m_nBufferHead);
|
||||
if (nIdealBytes > 0)
|
||||
{
|
||||
// get the data
|
||||
int nBytesToAdd = nBytesAvailable;
|
||||
|
||||
if (nMaxBytes > 0)
|
||||
{
|
||||
if (nBytesToAdd > nMaxBytes) nBytesToAdd = nMaxBytes;
|
||||
}
|
||||
|
||||
if (nBytesToAdd > nIdealBytes) nBytesToAdd = nIdealBytes;
|
||||
|
||||
// always make requests along block boundaries
|
||||
while ((nBytesToAdd % m_wfeInput.nBlockAlign) != 0)
|
||||
nBytesToAdd--;
|
||||
|
||||
int nBlocksToAdd = nBytesToAdd / m_wfeInput.nBlockAlign;
|
||||
|
||||
// get data
|
||||
int nBlocksAdded = 0;
|
||||
int nRetVal = pInputSource->GetData(pBuffer, nBlocksToAdd, &nBlocksAdded);
|
||||
if (nRetVal != 0)
|
||||
return ERROR_IO_READ;
|
||||
else
|
||||
nBytesRead = (nBlocksAdded * m_wfeInput.nBlockAlign);
|
||||
|
||||
// store the bytes read
|
||||
if (pBytesAdded)
|
||||
*pBytesAdded = nBytesRead;
|
||||
}
|
||||
|
||||
// unlock the data and process
|
||||
int nRetVal = UnlockBuffer(nBytesRead, TRUE);
|
||||
if (nRetVal != 0)
|
||||
{
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
56
MAC_SDK/Source/MACLib/APECompress.h
Normal file
56
MAC_SDK/Source/MACLib/APECompress.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef APE_APECOMPRESS_H
|
||||
#define APE_APECOMPRESS_H
|
||||
|
||||
#include "MACLib.h"
|
||||
class CAPECompressCreate;
|
||||
|
||||
/*************************************************************************************************
|
||||
CAPECompress - uses the CAPECompressHub to provide a simpler compression interface (with buffering, etc)
|
||||
*************************************************************************************************/
|
||||
class CAPECompress : public IAPECompress
|
||||
{
|
||||
public:
|
||||
|
||||
CAPECompress();
|
||||
~CAPECompress();
|
||||
|
||||
// start encoding
|
||||
int Start(const wchar_t * pOutputFilename, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, const void * pHeaderData = NULL, int nHeaderBytes = CREATE_WAV_HEADER_ON_DECOMPRESSION);
|
||||
int StartEx(CIO * pioOutput, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, const void * pHeaderData = NULL, int nHeaderBytes = CREATE_WAV_HEADER_ON_DECOMPRESSION);
|
||||
|
||||
// add data / compress data
|
||||
|
||||
// allows linear, immediate access to the buffer (fast)
|
||||
int GetBufferBytesAvailable();
|
||||
int UnlockBuffer(int nBytesAdded, BOOL bProcess = TRUE);
|
||||
unsigned char * LockBuffer(int * pBytesAvailable);
|
||||
|
||||
// slower, but easier than locking and unlocking (copies data)
|
||||
int AddData(unsigned char * pData, int nBytes);
|
||||
|
||||
// use a CIO (input source) to add data
|
||||
int AddDataFromInputSource(CInputSource * pInputSource, int nMaxBytes = -1, int * pBytesAdded = NULL);
|
||||
|
||||
// finish / kill
|
||||
int Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes);
|
||||
int Kill();
|
||||
|
||||
private:
|
||||
|
||||
int ProcessBuffer(BOOL bFinalize = FALSE);
|
||||
|
||||
CSmartPtr<CAPECompressCreate> m_spAPECompressCreate;
|
||||
|
||||
int m_nBufferHead;
|
||||
int m_nBufferTail;
|
||||
int m_nBufferSize;
|
||||
unsigned char * m_pBuffer;
|
||||
BOOL m_bBufferLocked;
|
||||
|
||||
CIO * m_pioOutput;
|
||||
BOOL m_bOwnsOutputIO;
|
||||
WAVEFORMATEX m_wfeInput;
|
||||
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_APECOMPRESS_H
|
||||
126
MAC_SDK/Source/MACLib/APECompressCore.cpp
Normal file
126
MAC_SDK/Source/MACLib/APECompressCore.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
#include "All.h"
|
||||
#include "APECompressCore.h"
|
||||
|
||||
#include "BitArray.h"
|
||||
#include "Prepare.h"
|
||||
#include "NewPredictor.h"
|
||||
|
||||
CAPECompressCore::CAPECompressCore(CIO * pIO, const WAVEFORMATEX * pwfeInput, int nMaxFrameBlocks, int nCompressionLevel)
|
||||
{
|
||||
m_spBitArray.Assign(new CBitArray(pIO));
|
||||
m_spDataX.Assign(new int [nMaxFrameBlocks], TRUE);
|
||||
m_spDataY.Assign(new int [nMaxFrameBlocks], TRUE);
|
||||
m_spTempData.Assign(new int [nMaxFrameBlocks], TRUE);
|
||||
m_spPrepare.Assign(new CPrepare);
|
||||
m_spPredictorX.Assign(new CPredictorCompressNormal(nCompressionLevel));
|
||||
m_spPredictorY.Assign(new CPredictorCompressNormal(nCompressionLevel));
|
||||
|
||||
memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX));
|
||||
m_nPeakLevel = 0;
|
||||
}
|
||||
|
||||
CAPECompressCore::~CAPECompressCore()
|
||||
{
|
||||
}
|
||||
|
||||
int CAPECompressCore::EncodeFrame(const void * pInputData, int nInputBytes)
|
||||
{
|
||||
// variables
|
||||
const int nInputBlocks = nInputBytes / m_wfeInput.nBlockAlign;
|
||||
int nSpecialCodes = 0;
|
||||
|
||||
// always start a new frame on a byte boundary
|
||||
m_spBitArray->AdvanceToByteBoundary();
|
||||
|
||||
// do the preparation stage
|
||||
RETURN_ON_ERROR(Prepare(pInputData, nInputBytes, &nSpecialCodes))
|
||||
|
||||
m_spPredictorX->Flush();
|
||||
m_spPredictorY->Flush();
|
||||
|
||||
m_spBitArray->FlushState(m_BitArrayStateX);
|
||||
m_spBitArray->FlushState(m_BitArrayStateY);
|
||||
|
||||
m_spBitArray->FlushBitArray();
|
||||
|
||||
if (m_wfeInput.nChannels == 2)
|
||||
{
|
||||
BOOL bEncodeX = TRUE;
|
||||
BOOL bEncodeY = TRUE;
|
||||
|
||||
if ((nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE) &&
|
||||
(nSpecialCodes & SPECIAL_FRAME_RIGHT_SILENCE))
|
||||
{
|
||||
bEncodeX = FALSE;
|
||||
bEncodeY = FALSE;
|
||||
}
|
||||
|
||||
if (nSpecialCodes & SPECIAL_FRAME_PSEUDO_STEREO)
|
||||
{
|
||||
bEncodeY = FALSE;
|
||||
}
|
||||
|
||||
if (bEncodeX && bEncodeY)
|
||||
{
|
||||
int nLastX = 0;
|
||||
for (int z = 0; z < nInputBlocks; z++)
|
||||
{
|
||||
m_spBitArray->EncodeValue(m_spPredictorY->CompressValue(m_spDataY[z], nLastX), m_BitArrayStateY);
|
||||
m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z], m_spDataY[z]), m_BitArrayStateX);
|
||||
|
||||
nLastX = m_spDataX[z];
|
||||
}
|
||||
}
|
||||
else if (bEncodeX)
|
||||
{
|
||||
for (int z = 0; z < nInputBlocks; z++)
|
||||
{
|
||||
RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z]), m_BitArrayStateX))
|
||||
}
|
||||
}
|
||||
else if (bEncodeY)
|
||||
{
|
||||
for (int z = 0; z < nInputBlocks; z++)
|
||||
{
|
||||
RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorY->CompressValue(m_spDataY[z]), m_BitArrayStateY))
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_wfeInput.nChannels == 1)
|
||||
{
|
||||
if (!(nSpecialCodes & SPECIAL_FRAME_MONO_SILENCE))
|
||||
{
|
||||
for (int z = 0; z < nInputBlocks; z++)
|
||||
{
|
||||
RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z]), m_BitArrayStateX))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_spBitArray->Finalize();
|
||||
|
||||
// return success
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CAPECompressCore::Prepare(const void * pInputData, int nInputBytes, int * pSpecialCodes)
|
||||
{
|
||||
// variable declares
|
||||
*pSpecialCodes = 0;
|
||||
unsigned int nCRC = 0;
|
||||
|
||||
// do the preparation
|
||||
RETURN_ON_ERROR(m_spPrepare->Prepare((unsigned char *) pInputData, nInputBytes, &m_wfeInput, m_spDataX, m_spDataY,
|
||||
&nCRC, pSpecialCodes, &m_nPeakLevel))
|
||||
|
||||
// store the CRC
|
||||
RETURN_ON_ERROR(m_spBitArray->EncodeUnsignedLong(nCRC))
|
||||
|
||||
// store any special codes
|
||||
if (*pSpecialCodes != 0)
|
||||
{
|
||||
RETURN_ON_ERROR(m_spBitArray->EncodeUnsignedLong(*pSpecialCodes))
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
41
MAC_SDK/Source/MACLib/APECompressCore.h
Normal file
41
MAC_SDK/Source/MACLib/APECompressCore.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef APE_APECOMPRESSCORE_H
|
||||
#define APE_APECOMPRESSCORE_H
|
||||
|
||||
#include "APECompress.h"
|
||||
#include "BitArray.h"
|
||||
|
||||
class CPrepare;
|
||||
class IPredictorCompress;
|
||||
|
||||
/*************************************************************************************************
|
||||
CAPECompressCore - manages the core of compression and bitstream output
|
||||
*************************************************************************************************/
|
||||
class CAPECompressCore
|
||||
{
|
||||
public:
|
||||
CAPECompressCore(CIO * pIO, const WAVEFORMATEX * pwfeInput, int nMaxFrameBlocks, int nCompressionLevel);
|
||||
~CAPECompressCore();
|
||||
|
||||
int EncodeFrame(const void * pInputData, int nInputBytes);
|
||||
|
||||
CBitArray * GetBitArray() { return m_spBitArray.GetPtr(); }
|
||||
int GetPeakLevel() { return m_nPeakLevel; }
|
||||
|
||||
private:
|
||||
|
||||
int Prepare(const void * pInputData, int nInputBytes, int * pSpecialCodes);
|
||||
|
||||
CSmartPtr<CBitArray> m_spBitArray;
|
||||
CSmartPtr<IPredictorCompress> m_spPredictorX;
|
||||
CSmartPtr<IPredictorCompress> m_spPredictorY;
|
||||
BIT_ARRAY_STATE m_BitArrayStateX;
|
||||
BIT_ARRAY_STATE m_BitArrayStateY;
|
||||
CSmartPtr<int> m_spDataX;
|
||||
CSmartPtr<int> m_spDataY;
|
||||
CSmartPtr<int> m_spTempData;
|
||||
CSmartPtr<CPrepare> m_spPrepare;
|
||||
WAVEFORMATEX m_wfeInput;
|
||||
int m_nPeakLevel;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_APECOMPRESSCORE_H
|
||||
218
MAC_SDK/Source/MACLib/APECompressCreate.cpp
Normal file
218
MAC_SDK/Source/MACLib/APECompressCreate.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
#include "All.h"
|
||||
#include "IO.h"
|
||||
#include "APECompressCreate.h"
|
||||
|
||||
#include "APECompressCore.h"
|
||||
|
||||
CAPECompressCreate::CAPECompressCreate()
|
||||
{
|
||||
m_nMaxFrames = 0;
|
||||
}
|
||||
|
||||
CAPECompressCreate::~CAPECompressCreate()
|
||||
{
|
||||
}
|
||||
|
||||
int CAPECompressCreate::Start(CIO * pioOutput, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel, const void * pHeaderData, int nHeaderBytes)
|
||||
{
|
||||
// verify the parameters
|
||||
if (pioOutput == NULL || pwfeInput == NULL)
|
||||
return ERROR_BAD_PARAMETER;
|
||||
|
||||
// verify the wave format
|
||||
if ((pwfeInput->nChannels != 1) && (pwfeInput->nChannels != 2))
|
||||
{
|
||||
return ERROR_INPUT_FILE_UNSUPPORTED_CHANNEL_COUNT;
|
||||
}
|
||||
if ((pwfeInput->wBitsPerSample != 8) && (pwfeInput->wBitsPerSample != 16) && (pwfeInput->wBitsPerSample != 24))
|
||||
{
|
||||
return ERROR_INPUT_FILE_UNSUPPORTED_BIT_DEPTH;
|
||||
}
|
||||
|
||||
// initialize (creates the base classes)
|
||||
m_nSamplesPerFrame = 73728;
|
||||
if (nCompressionLevel == COMPRESSION_LEVEL_EXTRA_HIGH)
|
||||
m_nSamplesPerFrame *= 4;
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_INSANE)
|
||||
m_nSamplesPerFrame *= 16;
|
||||
|
||||
m_spIO.Assign(pioOutput, FALSE, FALSE);
|
||||
m_spAPECompressCore.Assign(new CAPECompressCore(m_spIO, pwfeInput, m_nSamplesPerFrame, nCompressionLevel));
|
||||
|
||||
// copy the format
|
||||
memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX));
|
||||
|
||||
// the compression level
|
||||
m_nCompressionLevel = nCompressionLevel;
|
||||
m_nFrameIndex = 0;
|
||||
m_nLastFrameBlocks = m_nSamplesPerFrame;
|
||||
|
||||
// initialize the file
|
||||
if (nMaxAudioBytes < 0)
|
||||
nMaxAudioBytes = 2147483647;
|
||||
|
||||
uint32 nMaxAudioBlocks = nMaxAudioBytes / pwfeInput->nBlockAlign;
|
||||
int nMaxFrames = nMaxAudioBlocks / m_nSamplesPerFrame;
|
||||
if ((nMaxAudioBlocks % m_nSamplesPerFrame) != 0) nMaxFrames++;
|
||||
|
||||
InitializeFile(m_spIO, &m_wfeInput, nMaxFrames,
|
||||
m_nCompressionLevel, pHeaderData, nHeaderBytes);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPECompressCreate::GetFullFrameBytes()
|
||||
{
|
||||
return m_nSamplesPerFrame * m_wfeInput.nBlockAlign;
|
||||
}
|
||||
|
||||
int CAPECompressCreate::EncodeFrame(const void * pInputData, int nInputBytes)
|
||||
{
|
||||
int nInputBlocks = nInputBytes / m_wfeInput.nBlockAlign;
|
||||
|
||||
if ((nInputBlocks < m_nSamplesPerFrame) && (m_nLastFrameBlocks < m_nSamplesPerFrame))
|
||||
{
|
||||
return -1; // can only pass a smaller frame for the very last time
|
||||
}
|
||||
|
||||
// update the seek table
|
||||
m_spAPECompressCore->GetBitArray()->AdvanceToByteBoundary();
|
||||
int nRetVal = SetSeekByte(m_nFrameIndex, m_spIO->GetPosition() + (m_spAPECompressCore->GetBitArray()->GetCurrentBitIndex() / 8));
|
||||
if (nRetVal != ERROR_SUCCESS)
|
||||
return nRetVal;
|
||||
|
||||
// compress
|
||||
nRetVal = m_spAPECompressCore->EncodeFrame(pInputData, nInputBytes);
|
||||
|
||||
// update stats
|
||||
m_nLastFrameBlocks = nInputBlocks;
|
||||
m_nFrameIndex++;
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int CAPECompressCreate::Finish(const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes)
|
||||
{
|
||||
// clear the bit array
|
||||
RETURN_ON_ERROR(m_spAPECompressCore->GetBitArray()->OutputBitArray(TRUE));
|
||||
|
||||
// finalize the file
|
||||
RETURN_ON_ERROR(FinalizeFile(m_spIO, m_nFrameIndex, m_nLastFrameBlocks,
|
||||
pTerminatingData, nTerminatingBytes, nWAVTerminatingBytes, m_spAPECompressCore->GetPeakLevel()));
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPECompressCreate::SetSeekByte(int nFrame, int nByteOffset)
|
||||
{
|
||||
if (nFrame >= m_nMaxFrames) return ERROR_APE_COMPRESS_TOO_MUCH_DATA;
|
||||
m_spSeekTable[nFrame] = nByteOffset;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPECompressCreate::InitializeFile(CIO * pIO, const WAVEFORMATEX * pwfeInput, int nMaxFrames, int nCompressionLevel, const void * pHeaderData, int nHeaderBytes)
|
||||
{
|
||||
// error check the parameters
|
||||
if (pIO == NULL || pwfeInput == NULL || nMaxFrames <= 0)
|
||||
return ERROR_BAD_PARAMETER;
|
||||
|
||||
APE_DESCRIPTOR APEDescriptor; memset(&APEDescriptor, 0, sizeof(APEDescriptor));
|
||||
APE_HEADER APEHeader; memset(&APEHeader, 0, sizeof(APEHeader));
|
||||
|
||||
// create the descriptor (only fill what we know)
|
||||
APEDescriptor.cID[0] = 'M';
|
||||
APEDescriptor.cID[1] = 'A';
|
||||
APEDescriptor.cID[2] = 'C';
|
||||
APEDescriptor.cID[3] = ' ';
|
||||
APEDescriptor.nVersion = MAC_VERSION_NUMBER;
|
||||
|
||||
APEDescriptor.nDescriptorBytes = sizeof(APEDescriptor);
|
||||
APEDescriptor.nHeaderBytes = sizeof(APEHeader);
|
||||
APEDescriptor.nSeekTableBytes = nMaxFrames * sizeof(unsigned int);
|
||||
APEDescriptor.nHeaderDataBytes = (nHeaderBytes == CREATE_WAV_HEADER_ON_DECOMPRESSION) ? 0 : nHeaderBytes;
|
||||
|
||||
// create the header (only fill what we know now)
|
||||
APEHeader.nBitsPerSample = pwfeInput->wBitsPerSample;
|
||||
APEHeader.nChannels = pwfeInput->nChannels;
|
||||
APEHeader.nSampleRate = pwfeInput->nSamplesPerSec;
|
||||
|
||||
APEHeader.nCompressionLevel = (uint16) nCompressionLevel;
|
||||
APEHeader.nFormatFlags = (nHeaderBytes == CREATE_WAV_HEADER_ON_DECOMPRESSION) ? MAC_FORMAT_FLAG_CREATE_WAV_HEADER : 0;
|
||||
|
||||
APEHeader.nBlocksPerFrame = m_nSamplesPerFrame;
|
||||
|
||||
// write the data to the file
|
||||
unsigned int nBytesWritten = 0;
|
||||
RETURN_ON_ERROR(pIO->Write(&APEDescriptor, sizeof(APEDescriptor), &nBytesWritten))
|
||||
RETURN_ON_ERROR(pIO->Write(&APEHeader, sizeof(APEHeader), &nBytesWritten))
|
||||
|
||||
// write an empty seek table
|
||||
m_spSeekTable.Assign(new uint32 [nMaxFrames], TRUE);
|
||||
if (m_spSeekTable == NULL) { return ERROR_INSUFFICIENT_MEMORY; }
|
||||
ZeroMemory(m_spSeekTable, nMaxFrames * 4);
|
||||
RETURN_ON_ERROR(pIO->Write(m_spSeekTable, (nMaxFrames * 4), &nBytesWritten))
|
||||
m_nMaxFrames = nMaxFrames;
|
||||
|
||||
// write the WAV data
|
||||
if ((pHeaderData != NULL) && (nHeaderBytes > 0) && (nHeaderBytes != CREATE_WAV_HEADER_ON_DECOMPRESSION))
|
||||
{
|
||||
m_spAPECompressCore->GetBitArray()->GetMD5Helper().AddData(pHeaderData, nHeaderBytes);
|
||||
RETURN_ON_ERROR(pIO->Write((void *) pHeaderData, nHeaderBytes, &nBytesWritten))
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int CAPECompressCreate::FinalizeFile(CIO * pIO, int nNumberOfFrames, int nFinalFrameBlocks, const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, int nPeakLevel)
|
||||
{
|
||||
// store the tail position
|
||||
int nTailPosition = pIO->GetPosition();
|
||||
|
||||
// append the terminating data
|
||||
unsigned int nBytesWritten = 0;
|
||||
unsigned int nBytesRead = 0;
|
||||
int nRetVal = 0;
|
||||
if (nTerminatingBytes > 0)
|
||||
{
|
||||
m_spAPECompressCore->GetBitArray()->GetMD5Helper().AddData(pTerminatingData, nTerminatingBytes);
|
||||
if (pIO->Write((void *) pTerminatingData, nTerminatingBytes, &nBytesWritten) != 0) { return ERROR_IO_WRITE; }
|
||||
}
|
||||
|
||||
// go to the beginning and update the information
|
||||
nRetVal = pIO->Seek(0, FILE_BEGIN);
|
||||
|
||||
// get the descriptor
|
||||
APE_DESCRIPTOR APEDescriptor;
|
||||
nRetVal = pIO->Read(&APEDescriptor, sizeof(APEDescriptor), &nBytesRead);
|
||||
if ((nRetVal != 0) || (nBytesRead != sizeof(APEDescriptor))) { return ERROR_IO_READ; }
|
||||
|
||||
// get the header
|
||||
APE_HEADER APEHeader;
|
||||
nRetVal = pIO->Read(&APEHeader, sizeof(APEHeader), &nBytesRead);
|
||||
if (nRetVal != 0 || nBytesRead != sizeof(APEHeader)) { return ERROR_IO_READ; }
|
||||
|
||||
// update the header
|
||||
APEHeader.nFinalFrameBlocks = nFinalFrameBlocks;
|
||||
APEHeader.nTotalFrames = nNumberOfFrames;
|
||||
|
||||
// update the descriptor
|
||||
APEDescriptor.nAPEFrameDataBytes = nTailPosition - (APEDescriptor.nDescriptorBytes + APEDescriptor.nHeaderBytes + APEDescriptor.nSeekTableBytes + APEDescriptor.nHeaderDataBytes);
|
||||
APEDescriptor.nAPEFrameDataBytesHigh = 0;
|
||||
APEDescriptor.nTerminatingDataBytes = nTerminatingBytes;
|
||||
|
||||
// update the MD5
|
||||
m_spAPECompressCore->GetBitArray()->GetMD5Helper().AddData(&APEHeader, sizeof(APEHeader));
|
||||
m_spAPECompressCore->GetBitArray()->GetMD5Helper().AddData(m_spSeekTable, m_nMaxFrames * 4);
|
||||
m_spAPECompressCore->GetBitArray()->GetMD5Helper().GetResult(APEDescriptor.cFileMD5);
|
||||
|
||||
// set the pointer and re-write the updated header and peak level
|
||||
nRetVal = pIO->Seek(0, FILE_BEGIN);
|
||||
if (pIO->Write(&APEDescriptor, sizeof(APEDescriptor), &nBytesWritten) != 0) { return ERROR_IO_WRITE; }
|
||||
if (pIO->Write(&APEHeader, sizeof(APEHeader), &nBytesWritten) != 0) { return ERROR_IO_WRITE; }
|
||||
|
||||
// write the updated seek table
|
||||
if (pIO->Write(m_spSeekTable, m_nMaxFrames * 4, &nBytesWritten) != 0) { return ERROR_IO_WRITE; }
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
43
MAC_SDK/Source/MACLib/APECompressCreate.h
Normal file
43
MAC_SDK/Source/MACLib/APECompressCreate.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef APE_APECOMPRESSCREATE_H
|
||||
#define APE_APECOMPRESSCREATE_H
|
||||
|
||||
#include "APECompress.h"
|
||||
|
||||
class CAPECompressCore;
|
||||
|
||||
class CAPECompressCreate
|
||||
{
|
||||
public:
|
||||
CAPECompressCreate();
|
||||
~CAPECompressCreate();
|
||||
|
||||
int InitializeFile(CIO * pIO, const WAVEFORMATEX * pwfeInput, int nMaxFrames, int nCompressionLevel, const void * pHeaderData, int nHeaderBytes);
|
||||
int FinalizeFile(CIO * pIO, int nNumberOfFrames, int nFinalFrameBlocks, const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes, int nPeakLevel);
|
||||
|
||||
int SetSeekByte(int nFrame, int nByteOffset);
|
||||
|
||||
int Start(CIO * pioOutput, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, const void * pHeaderData = NULL, int nHeaderBytes = CREATE_WAV_HEADER_ON_DECOMPRESSION);
|
||||
|
||||
int GetFullFrameBytes();
|
||||
int EncodeFrame(const void * pInputData, int nInputBytes);
|
||||
|
||||
int Finish(const void * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
CSmartPtr<uint32> m_spSeekTable;
|
||||
int m_nMaxFrames;
|
||||
|
||||
CSmartPtr<CIO> m_spIO;
|
||||
CSmartPtr<CAPECompressCore> m_spAPECompressCore;
|
||||
|
||||
WAVEFORMATEX m_wfeInput;
|
||||
int m_nCompressionLevel;
|
||||
int m_nSamplesPerFrame;
|
||||
int m_nFrameIndex;
|
||||
int m_nLastFrameBlocks;
|
||||
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_APECOMPRESSCREATE_H
|
||||
479
MAC_SDK/Source/MACLib/APEDecompress.cpp
Normal file
479
MAC_SDK/Source/MACLib/APEDecompress.cpp
Normal file
@@ -0,0 +1,479 @@
|
||||
#include "All.h"
|
||||
#include "APEDecompress.h"
|
||||
|
||||
#include "APEInfo.h"
|
||||
#include "Prepare.h"
|
||||
#include "UnBitArray.h"
|
||||
#include "NewPredictor.h"
|
||||
|
||||
#define DECODE_BLOCK_SIZE 4096
|
||||
|
||||
CAPEDecompress::CAPEDecompress(int * pErrorCode, CAPEInfo * pAPEInfo, int nStartBlock, int nFinishBlock)
|
||||
{
|
||||
*pErrorCode = ERROR_SUCCESS;
|
||||
|
||||
// open / analyze the file
|
||||
m_spAPEInfo.Assign(pAPEInfo);
|
||||
|
||||
// version check (this implementation only works with 3.93 and later files)
|
||||
if (GetInfo(APE_INFO_FILE_VERSION) < 3930)
|
||||
{
|
||||
*pErrorCode = ERROR_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
// get format information
|
||||
GetInfo(APE_INFO_WAVEFORMATEX, (int) &m_wfeInput);
|
||||
m_nBlockAlign = GetInfo(APE_INFO_BLOCK_ALIGN);
|
||||
|
||||
// initialize other stuff
|
||||
m_bDecompressorInitialized = FALSE;
|
||||
m_nCurrentFrame = 0;
|
||||
m_nCurrentBlock = 0;
|
||||
m_nCurrentFrameBufferBlock = 0;
|
||||
m_nFrameBufferFinishedBlocks = 0;
|
||||
m_bErrorDecodingCurrentFrame = FALSE;
|
||||
|
||||
// set the "real" start and finish blocks
|
||||
m_nStartBlock = (nStartBlock < 0) ? 0 : min(nStartBlock, GetInfo(APE_INFO_TOTAL_BLOCKS));
|
||||
m_nFinishBlock = (nFinishBlock < 0) ? GetInfo(APE_INFO_TOTAL_BLOCKS) : min(nFinishBlock, GetInfo(APE_INFO_TOTAL_BLOCKS));
|
||||
m_bIsRanged = (m_nStartBlock != 0) || (m_nFinishBlock != GetInfo(APE_INFO_TOTAL_BLOCKS));
|
||||
}
|
||||
|
||||
CAPEDecompress::~CAPEDecompress()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int CAPEDecompress::InitializeDecompressor()
|
||||
{
|
||||
// check if we have anything to do
|
||||
if (m_bDecompressorInitialized)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// update the initialized flag
|
||||
m_bDecompressorInitialized = TRUE;
|
||||
|
||||
// create a frame buffer
|
||||
m_cbFrameBuffer.CreateBuffer((GetInfo(APE_INFO_BLOCKS_PER_FRAME) + DECODE_BLOCK_SIZE) * m_nBlockAlign, m_nBlockAlign * 64);
|
||||
|
||||
// create decoding components
|
||||
m_spUnBitArray.Assign((CUnBitArrayBase *) CreateUnBitArray(this, GetInfo(APE_INFO_FILE_VERSION)));
|
||||
|
||||
if (GetInfo(APE_INFO_FILE_VERSION) >= 3950)
|
||||
{
|
||||
m_spNewPredictorX.Assign(new CPredictorDecompress3950toCurrent(GetInfo(APE_INFO_COMPRESSION_LEVEL), GetInfo(APE_INFO_FILE_VERSION)));
|
||||
m_spNewPredictorY.Assign(new CPredictorDecompress3950toCurrent(GetInfo(APE_INFO_COMPRESSION_LEVEL), GetInfo(APE_INFO_FILE_VERSION)));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spNewPredictorX.Assign(new CPredictorDecompressNormal3930to3950(GetInfo(APE_INFO_COMPRESSION_LEVEL), GetInfo(APE_INFO_FILE_VERSION)));
|
||||
m_spNewPredictorY.Assign(new CPredictorDecompressNormal3930to3950(GetInfo(APE_INFO_COMPRESSION_LEVEL), GetInfo(APE_INFO_FILE_VERSION)));
|
||||
}
|
||||
|
||||
// seek to the beginning
|
||||
return Seek(0);
|
||||
}
|
||||
|
||||
int CAPEDecompress::GetData(char * pBuffer, int nBlocks, int * pBlocksRetrieved)
|
||||
{
|
||||
int nRetVal = ERROR_SUCCESS;
|
||||
if (pBlocksRetrieved) *pBlocksRetrieved = 0;
|
||||
|
||||
// make sure we're initialized
|
||||
RETURN_ON_ERROR(InitializeDecompressor())
|
||||
|
||||
// cap
|
||||
int nBlocksUntilFinish = m_nFinishBlock - m_nCurrentBlock;
|
||||
const int nBlocksToRetrieve = min(nBlocks, nBlocksUntilFinish);
|
||||
|
||||
// get the data
|
||||
unsigned char * pOutputBuffer = (unsigned char *) pBuffer;
|
||||
int nBlocksLeft = nBlocksToRetrieve; int nBlocksThisPass = 1;
|
||||
while ((nBlocksLeft > 0) && (nBlocksThisPass > 0))
|
||||
{
|
||||
// fill up the frame buffer
|
||||
int nDecodeRetVal = FillFrameBuffer();
|
||||
if (nDecodeRetVal != ERROR_SUCCESS)
|
||||
nRetVal = nDecodeRetVal;
|
||||
|
||||
// analyze how much to remove from the buffer
|
||||
const int nFrameBufferBlocks = m_nFrameBufferFinishedBlocks;
|
||||
nBlocksThisPass = min(nBlocksLeft, nFrameBufferBlocks);
|
||||
|
||||
// remove as much as possible
|
||||
if (nBlocksThisPass > 0)
|
||||
{
|
||||
m_cbFrameBuffer.Get(pOutputBuffer, nBlocksThisPass * m_nBlockAlign);
|
||||
pOutputBuffer += nBlocksThisPass * m_nBlockAlign;
|
||||
nBlocksLeft -= nBlocksThisPass;
|
||||
m_nFrameBufferFinishedBlocks -= nBlocksThisPass;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the blocks retrieved
|
||||
int nBlocksRetrieved = nBlocksToRetrieve - nBlocksLeft;
|
||||
|
||||
// update position
|
||||
m_nCurrentBlock += nBlocksRetrieved;
|
||||
if (pBlocksRetrieved) *pBlocksRetrieved = nBlocksRetrieved;
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int CAPEDecompress::Seek(int nBlockOffset)
|
||||
{
|
||||
RETURN_ON_ERROR(InitializeDecompressor())
|
||||
|
||||
// use the offset
|
||||
nBlockOffset += m_nStartBlock;
|
||||
|
||||
// cap (to prevent seeking too far)
|
||||
if (nBlockOffset >= m_nFinishBlock)
|
||||
nBlockOffset = m_nFinishBlock - 1;
|
||||
if (nBlockOffset < m_nStartBlock)
|
||||
nBlockOffset = m_nStartBlock;
|
||||
|
||||
// seek to the perfect location
|
||||
int nBaseFrame = nBlockOffset / GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
int nBlocksToSkip = nBlockOffset % GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
int nBytesToSkip = nBlocksToSkip * m_nBlockAlign;
|
||||
|
||||
m_nCurrentBlock = nBaseFrame * GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
m_nCurrentFrameBufferBlock = nBaseFrame * GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
m_nCurrentFrame = nBaseFrame;
|
||||
m_nFrameBufferFinishedBlocks = 0;
|
||||
m_cbFrameBuffer.Empty();
|
||||
RETURN_ON_ERROR(SeekToFrame(m_nCurrentFrame));
|
||||
|
||||
// skip necessary blocks
|
||||
CSmartPtr<char> spTempBuffer(new char [nBytesToSkip], TRUE);
|
||||
if (spTempBuffer == NULL) return ERROR_INSUFFICIENT_MEMORY;
|
||||
|
||||
int nBlocksRetrieved = 0;
|
||||
GetData(spTempBuffer, nBlocksToSkip, &nBlocksRetrieved);
|
||||
if (nBlocksRetrieved != nBlocksToSkip)
|
||||
return ERROR_UNDEFINED;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Decodes blocks of data
|
||||
*****************************************************************************************/
|
||||
int CAPEDecompress::FillFrameBuffer()
|
||||
{
|
||||
int nRetVal = ERROR_SUCCESS;
|
||||
|
||||
// determine the maximum blocks we can decode
|
||||
// note that we won't do end capping because we can't use data
|
||||
// until EndFrame(...) successfully handles the frame
|
||||
// that means we may decode a little extra in end capping cases
|
||||
// but this allows robust error handling of bad frames
|
||||
int nMaxBlocks = m_cbFrameBuffer.MaxAdd() / m_nBlockAlign;
|
||||
|
||||
// loop and decode data
|
||||
int nBlocksLeft = nMaxBlocks;
|
||||
while (nBlocksLeft > 0)
|
||||
{
|
||||
int nFrameBlocks = GetInfo(APE_INFO_FRAME_BLOCKS, m_nCurrentFrame);
|
||||
if (nFrameBlocks < 0)
|
||||
break;
|
||||
|
||||
int nFrameOffsetBlocks = m_nCurrentFrameBufferBlock % GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
int nFrameBlocksLeft = nFrameBlocks - nFrameOffsetBlocks;
|
||||
int nBlocksThisPass = min(nFrameBlocksLeft, nBlocksLeft);
|
||||
|
||||
// start the frame if we need to
|
||||
if (nFrameOffsetBlocks == 0)
|
||||
StartFrame();
|
||||
|
||||
// store the frame buffer bytes before we start
|
||||
int nFrameBufferBytes = m_cbFrameBuffer.MaxGet();
|
||||
|
||||
// decode data
|
||||
DecodeBlocksToFrameBuffer(nBlocksThisPass);
|
||||
|
||||
// end the frame if we need to
|
||||
if ((nFrameOffsetBlocks + nBlocksThisPass) >= nFrameBlocks)
|
||||
{
|
||||
EndFrame();
|
||||
if (m_bErrorDecodingCurrentFrame)
|
||||
{
|
||||
// remove any decoded data from the buffer
|
||||
m_cbFrameBuffer.RemoveTail(m_cbFrameBuffer.MaxGet() - nFrameBufferBytes);
|
||||
|
||||
// add silence
|
||||
unsigned char cSilence = (GetInfo(APE_INFO_BITS_PER_SAMPLE) == 8) ? 127 : 0;
|
||||
for (int z = 0; z < nFrameBlocks * m_nBlockAlign; z++)
|
||||
{
|
||||
*m_cbFrameBuffer.GetDirectWritePointer() = cSilence;
|
||||
m_cbFrameBuffer.UpdateAfterDirectWrite(1);
|
||||
}
|
||||
|
||||
// seek to try to synchronize after an error
|
||||
SeekToFrame(m_nCurrentFrame);
|
||||
|
||||
// save the return value
|
||||
nRetVal = ERROR_INVALID_CHECKSUM;
|
||||
}
|
||||
}
|
||||
|
||||
nBlocksLeft -= nBlocksThisPass;
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
void CAPEDecompress::DecodeBlocksToFrameBuffer(int nBlocks)
|
||||
{
|
||||
// decode the samples
|
||||
int nBlocksProcessed = 0;
|
||||
|
||||
try
|
||||
{
|
||||
if (m_wfeInput.nChannels == 2)
|
||||
{
|
||||
if ((m_nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE) &&
|
||||
(m_nSpecialCodes & SPECIAL_FRAME_RIGHT_SILENCE))
|
||||
{
|
||||
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++)
|
||||
{
|
||||
m_Prepare.Unprepare(0, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
|
||||
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
|
||||
}
|
||||
}
|
||||
else if (m_nSpecialCodes & SPECIAL_FRAME_PSEUDO_STEREO)
|
||||
{
|
||||
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++)
|
||||
{
|
||||
int X = m_spNewPredictorX->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateX));
|
||||
m_Prepare.Unprepare(X, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
|
||||
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_spAPEInfo->GetInfo(APE_INFO_FILE_VERSION) >= 3950)
|
||||
{
|
||||
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++)
|
||||
{
|
||||
int nY = m_spUnBitArray->DecodeValueRange(m_BitArrayStateY);
|
||||
int nX = m_spUnBitArray->DecodeValueRange(m_BitArrayStateX);
|
||||
int Y = m_spNewPredictorY->DecompressValue(nY, m_nLastX);
|
||||
int X = m_spNewPredictorX->DecompressValue(nX, Y);
|
||||
m_nLastX = X;
|
||||
|
||||
m_Prepare.Unprepare(X, Y, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
|
||||
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++)
|
||||
{
|
||||
int X = m_spNewPredictorX->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateX));
|
||||
int Y = m_spNewPredictorY->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateY));
|
||||
|
||||
m_Prepare.Unprepare(X, Y, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
|
||||
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_nSpecialCodes & SPECIAL_FRAME_MONO_SILENCE)
|
||||
{
|
||||
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++)
|
||||
{
|
||||
m_Prepare.Unprepare(0, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
|
||||
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++)
|
||||
{
|
||||
int X = m_spNewPredictorX->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateX));
|
||||
m_Prepare.Unprepare(X, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC);
|
||||
m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
m_bErrorDecodingCurrentFrame = TRUE;
|
||||
}
|
||||
|
||||
m_nCurrentFrameBufferBlock += nBlocks;
|
||||
}
|
||||
|
||||
void CAPEDecompress::StartFrame()
|
||||
{
|
||||
m_nCRC = 0xFFFFFFFF;
|
||||
|
||||
// get the frame header
|
||||
m_nStoredCRC = m_spUnBitArray->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_INT);
|
||||
m_bErrorDecodingCurrentFrame = FALSE;
|
||||
|
||||
// get any 'special' codes if the file uses them (for silence, FALSE stereo, etc.)
|
||||
m_nSpecialCodes = 0;
|
||||
if (GET_USES_SPECIAL_FRAMES(m_spAPEInfo))
|
||||
{
|
||||
if (m_nStoredCRC & 0x80000000)
|
||||
{
|
||||
m_nSpecialCodes = m_spUnBitArray->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_INT);
|
||||
}
|
||||
m_nStoredCRC &= 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
m_spNewPredictorX->Flush();
|
||||
m_spNewPredictorY->Flush();
|
||||
|
||||
m_spUnBitArray->FlushState(m_BitArrayStateX);
|
||||
m_spUnBitArray->FlushState(m_BitArrayStateY);
|
||||
|
||||
m_spUnBitArray->FlushBitArray();
|
||||
|
||||
m_nLastX = 0;
|
||||
}
|
||||
|
||||
void CAPEDecompress::EndFrame()
|
||||
{
|
||||
m_nFrameBufferFinishedBlocks += GetInfo(APE_INFO_FRAME_BLOCKS, m_nCurrentFrame);
|
||||
m_nCurrentFrame++;
|
||||
|
||||
// finalize
|
||||
m_spUnBitArray->Finalize();
|
||||
|
||||
// check the CRC
|
||||
m_nCRC = m_nCRC ^ 0xFFFFFFFF;
|
||||
m_nCRC >>= 1;
|
||||
if (m_nCRC != m_nStoredCRC)
|
||||
m_bErrorDecodingCurrentFrame = TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Seek to the proper frame (if necessary) and do any alignment of the bit array
|
||||
*****************************************************************************************/
|
||||
int CAPEDecompress::SeekToFrame(int nFrameIndex)
|
||||
{
|
||||
int nSeekRemainder = (GetInfo(APE_INFO_SEEK_BYTE, nFrameIndex) - GetInfo(APE_INFO_SEEK_BYTE, 0)) % 4;
|
||||
return m_spUnBitArray->FillAndResetBitArray(GetInfo(APE_INFO_SEEK_BYTE, nFrameIndex) - nSeekRemainder, nSeekRemainder * 8);
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Get information from the decompressor
|
||||
*****************************************************************************************/
|
||||
int CAPEDecompress::GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1, int nParam2)
|
||||
{
|
||||
int nRetVal = 0;
|
||||
BOOL bHandled = TRUE;
|
||||
|
||||
switch (Field)
|
||||
{
|
||||
case APE_DECOMPRESS_CURRENT_BLOCK:
|
||||
nRetVal = m_nCurrentBlock - m_nStartBlock;
|
||||
break;
|
||||
case APE_DECOMPRESS_CURRENT_MS:
|
||||
{
|
||||
int nSampleRate = m_spAPEInfo->GetInfo(APE_INFO_SAMPLE_RATE, 0, 0);
|
||||
if (nSampleRate > 0)
|
||||
nRetVal = int((double(m_nCurrentBlock) * double(1000)) / double(nSampleRate));
|
||||
break;
|
||||
}
|
||||
case APE_DECOMPRESS_TOTAL_BLOCKS:
|
||||
nRetVal = m_nFinishBlock - m_nStartBlock;
|
||||
break;
|
||||
case APE_DECOMPRESS_LENGTH_MS:
|
||||
{
|
||||
int nSampleRate = m_spAPEInfo->GetInfo(APE_INFO_SAMPLE_RATE, 0, 0);
|
||||
if (nSampleRate > 0)
|
||||
nRetVal = int((double(m_nFinishBlock - m_nStartBlock) * double(1000)) / double(nSampleRate));
|
||||
break;
|
||||
}
|
||||
case APE_DECOMPRESS_CURRENT_BITRATE:
|
||||
nRetVal = GetInfo(APE_INFO_FRAME_BITRATE, m_nCurrentFrame);
|
||||
break;
|
||||
case APE_DECOMPRESS_AVERAGE_BITRATE:
|
||||
{
|
||||
if (m_bIsRanged)
|
||||
{
|
||||
// figure the frame range
|
||||
const int nBlocksPerFrame = GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
int nStartFrame = m_nStartBlock / nBlocksPerFrame;
|
||||
int nFinishFrame = (m_nFinishBlock + nBlocksPerFrame - 1) / nBlocksPerFrame;
|
||||
|
||||
// get the number of bytes in the first and last frame
|
||||
int nTotalBytes = (GetInfo(APE_INFO_FRAME_BYTES, nStartFrame) * (m_nStartBlock % nBlocksPerFrame)) / nBlocksPerFrame;
|
||||
if (nFinishFrame != nStartFrame)
|
||||
nTotalBytes += (GetInfo(APE_INFO_FRAME_BYTES, nFinishFrame) * (m_nFinishBlock % nBlocksPerFrame)) / nBlocksPerFrame;
|
||||
|
||||
// get the number of bytes in between
|
||||
const int nTotalFrames = GetInfo(APE_INFO_TOTAL_FRAMES);
|
||||
for (int nFrame = nStartFrame + 1; (nFrame < nFinishFrame) && (nFrame < nTotalFrames); nFrame++)
|
||||
nTotalBytes += GetInfo(APE_INFO_FRAME_BYTES, nFrame);
|
||||
|
||||
// figure the bitrate
|
||||
int nTotalMS = int((double(m_nFinishBlock - m_nStartBlock) * double(1000)) / double(GetInfo(APE_INFO_SAMPLE_RATE)));
|
||||
if (nTotalMS != 0)
|
||||
nRetVal = (nTotalBytes * 8) / nTotalMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
nRetVal = GetInfo(APE_INFO_AVERAGE_BITRATE);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
bHandled = FALSE;
|
||||
}
|
||||
|
||||
if (!bHandled && m_bIsRanged)
|
||||
{
|
||||
bHandled = TRUE;
|
||||
|
||||
switch (Field)
|
||||
{
|
||||
case APE_INFO_WAV_HEADER_BYTES:
|
||||
nRetVal = sizeof(WAVE_HEADER);
|
||||
break;
|
||||
case APE_INFO_WAV_HEADER_DATA:
|
||||
{
|
||||
char * pBuffer = (char *) nParam1;
|
||||
int nMaxBytes = nParam2;
|
||||
|
||||
if (sizeof(WAVE_HEADER) > nMaxBytes)
|
||||
{
|
||||
nRetVal = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
WAVEFORMATEX wfeFormat; GetInfo(APE_INFO_WAVEFORMATEX, (int) &wfeFormat, 0);
|
||||
WAVE_HEADER WAVHeader; FillWaveHeader(&WAVHeader,
|
||||
(m_nFinishBlock - m_nStartBlock) * GetInfo(APE_INFO_BLOCK_ALIGN),
|
||||
&wfeFormat, 0);
|
||||
memcpy(pBuffer, &WAVHeader, sizeof(WAVE_HEADER));
|
||||
nRetVal = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case APE_INFO_WAV_TERMINATING_BYTES:
|
||||
nRetVal = 0;
|
||||
break;
|
||||
case APE_INFO_WAV_TERMINATING_DATA:
|
||||
nRetVal = 0;
|
||||
break;
|
||||
default:
|
||||
bHandled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bHandled == FALSE)
|
||||
nRetVal = m_spAPEInfo->GetInfo(Field, nParam1, nParam2);
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
72
MAC_SDK/Source/MACLib/APEDecompress.h
Normal file
72
MAC_SDK/Source/MACLib/APEDecompress.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef APE_APEDECOMPRESS_H
|
||||
#define APE_APEDECOMPRESS_H
|
||||
|
||||
#include "APEDecompress.h"
|
||||
|
||||
class CUnBitArray;
|
||||
class CPrepare;
|
||||
class CAPEInfo;
|
||||
class IPredictorDecompress;
|
||||
#include "UnBitArrayBase.h"
|
||||
#include "MACLib.h"
|
||||
#include "Prepare.h"
|
||||
#include "CircleBuffer.h"
|
||||
|
||||
class CAPEDecompress : public IAPEDecompress
|
||||
{
|
||||
public:
|
||||
|
||||
CAPEDecompress(int * pErrorCode, CAPEInfo * pAPEInfo, int nStartBlock = -1, int nFinishBlock = -1);
|
||||
~CAPEDecompress();
|
||||
|
||||
int GetData(char * pBuffer, int nBlocks, int * pBlocksRetrieved);
|
||||
int Seek(int nBlockOffset);
|
||||
|
||||
int GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1 = 0, int nParam2 = 0);
|
||||
|
||||
protected:
|
||||
|
||||
// file info
|
||||
int m_nBlockAlign;
|
||||
int m_nCurrentFrame;
|
||||
|
||||
// start / finish information
|
||||
int m_nStartBlock;
|
||||
int m_nFinishBlock;
|
||||
int m_nCurrentBlock;
|
||||
BOOL m_bIsRanged;
|
||||
BOOL m_bDecompressorInitialized;
|
||||
|
||||
// decoding tools
|
||||
CPrepare m_Prepare;
|
||||
WAVEFORMATEX m_wfeInput;
|
||||
unsigned int m_nCRC;
|
||||
unsigned int m_nStoredCRC;
|
||||
int m_nSpecialCodes;
|
||||
|
||||
int SeekToFrame(int nFrameIndex);
|
||||
void DecodeBlocksToFrameBuffer(int nBlocks);
|
||||
int FillFrameBuffer();
|
||||
void StartFrame();
|
||||
void EndFrame();
|
||||
int InitializeDecompressor();
|
||||
|
||||
// more decoding components
|
||||
CSmartPtr<CAPEInfo> m_spAPEInfo;
|
||||
CSmartPtr<CUnBitArrayBase> m_spUnBitArray;
|
||||
UNBIT_ARRAY_STATE m_BitArrayStateX;
|
||||
UNBIT_ARRAY_STATE m_BitArrayStateY;
|
||||
|
||||
CSmartPtr<IPredictorDecompress> m_spNewPredictorX;
|
||||
CSmartPtr<IPredictorDecompress> m_spNewPredictorY;
|
||||
|
||||
int m_nLastX;
|
||||
|
||||
// decoding buffer
|
||||
BOOL m_bErrorDecodingCurrentFrame;
|
||||
int m_nCurrentFrameBufferBlock;
|
||||
int m_nFrameBufferFinishedBlocks;
|
||||
CCircleBuffer m_cbFrameBuffer;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_APEDECOMPRESS_H
|
||||
280
MAC_SDK/Source/MACLib/APEHeader.cpp
Normal file
280
MAC_SDK/Source/MACLib/APEHeader.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
#include "All.h"
|
||||
#include "APEHeader.h"
|
||||
#include "MACLib.h"
|
||||
#include "APEInfo.h"
|
||||
|
||||
// TODO: should push and pop the file position
|
||||
|
||||
CAPEHeader::CAPEHeader(CIO * pIO)
|
||||
{
|
||||
m_pIO = pIO;
|
||||
}
|
||||
|
||||
CAPEHeader::~CAPEHeader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int CAPEHeader::FindDescriptor(BOOL bSeek)
|
||||
{
|
||||
// store the original location and seek to the beginning
|
||||
int nOriginalFileLocation = m_pIO->GetPosition();
|
||||
m_pIO->Seek(0, FILE_BEGIN);
|
||||
|
||||
// set the default junk bytes to 0
|
||||
int nJunkBytes = 0;
|
||||
|
||||
// skip an ID3v2 tag (which we really don't support anyway...)
|
||||
unsigned int nBytesRead = 0;
|
||||
unsigned char cID3v2Header[10];
|
||||
m_pIO->Read((unsigned char *) cID3v2Header, 10, &nBytesRead);
|
||||
if (cID3v2Header[0] == 'I' && cID3v2Header[1] == 'D' && cID3v2Header[2] == '3')
|
||||
{
|
||||
// why is it so hard to figure the lenght of an ID3v2 tag ?!?
|
||||
unsigned int nLength = *((unsigned int *) &cID3v2Header[6]);
|
||||
|
||||
unsigned int nSyncSafeLength = 0;
|
||||
nSyncSafeLength = (cID3v2Header[6] & 127) << 21;
|
||||
nSyncSafeLength += (cID3v2Header[7] & 127) << 14;
|
||||
nSyncSafeLength += (cID3v2Header[8] & 127) << 7;
|
||||
nSyncSafeLength += (cID3v2Header[9] & 127);
|
||||
|
||||
BOOL bHasTagFooter = FALSE;
|
||||
|
||||
if (cID3v2Header[5] & 16)
|
||||
{
|
||||
bHasTagFooter = TRUE;
|
||||
nJunkBytes = nSyncSafeLength + 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
nJunkBytes = nSyncSafeLength + 10;
|
||||
}
|
||||
|
||||
// error check
|
||||
if (cID3v2Header[5] & 64)
|
||||
{
|
||||
// this ID3v2 length calculator algorithm can't cope with extended headers
|
||||
// we should be ok though, because the scan for the MAC header below should
|
||||
// really do the trick
|
||||
}
|
||||
|
||||
m_pIO->Seek(nJunkBytes, FILE_BEGIN);
|
||||
|
||||
// scan for padding (slow and stupid, but who cares here...)
|
||||
if (!bHasTagFooter)
|
||||
{
|
||||
char cTemp = 0;
|
||||
m_pIO->Read((unsigned char *) &cTemp, 1, &nBytesRead);
|
||||
while (cTemp == 0 && nBytesRead == 1)
|
||||
{
|
||||
nJunkBytes++;
|
||||
m_pIO->Read((unsigned char *) &cTemp, 1, &nBytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_pIO->Seek(nJunkBytes, FILE_BEGIN);
|
||||
|
||||
// scan until we hit the APE_DESCRIPTOR, the end of the file, or 1 MB later
|
||||
unsigned int nGoalID = (' ' << 24) | ('C' << 16) | ('A' << 8) | ('M');
|
||||
unsigned int nReadID = 0;
|
||||
int nRetVal = m_pIO->Read(&nReadID, 4, &nBytesRead);
|
||||
if (nRetVal != 0 || nBytesRead != 4) return ERROR_UNDEFINED;
|
||||
|
||||
nBytesRead = 1;
|
||||
int nScanBytes = 0;
|
||||
while ((nGoalID != nReadID) && (nBytesRead == 1) && (nScanBytes < (1024 * 1024)))
|
||||
{
|
||||
unsigned char cTemp;
|
||||
m_pIO->Read(&cTemp, 1, &nBytesRead);
|
||||
nReadID = (((unsigned int) cTemp) << 24) | (nReadID >> 8);
|
||||
nJunkBytes++;
|
||||
nScanBytes++;
|
||||
}
|
||||
|
||||
if (nGoalID != nReadID)
|
||||
nJunkBytes = -1;
|
||||
|
||||
// seek to the proper place (depending on result and settings)
|
||||
if (bSeek && (nJunkBytes != -1))
|
||||
{
|
||||
// successfully found the start of the file (seek to it and return)
|
||||
m_pIO->Seek(nJunkBytes, FILE_BEGIN);
|
||||
}
|
||||
else
|
||||
{
|
||||
// restore the original file pointer
|
||||
m_pIO->Seek(nOriginalFileLocation, FILE_BEGIN);
|
||||
}
|
||||
|
||||
return nJunkBytes;
|
||||
}
|
||||
|
||||
int CAPEHeader::Analyze(APE_FILE_INFO * pInfo)
|
||||
{
|
||||
// error check
|
||||
if ((m_pIO == NULL) || (pInfo == NULL))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
// variables
|
||||
unsigned int nBytesRead = 0;
|
||||
|
||||
// find the descriptor
|
||||
pInfo->nJunkHeaderBytes = FindDescriptor(TRUE);
|
||||
if (pInfo->nJunkHeaderBytes < 0)
|
||||
return ERROR_UNDEFINED;
|
||||
|
||||
// read the first 8 bytes of the descriptor (ID and version)
|
||||
APE_COMMON_HEADER CommonHeader; memset(&CommonHeader, 0, sizeof(APE_COMMON_HEADER));
|
||||
m_pIO->Read(&CommonHeader, sizeof(APE_COMMON_HEADER), &nBytesRead);
|
||||
|
||||
// make sure we're at the ID
|
||||
if (CommonHeader.cID[0] != 'M' || CommonHeader.cID[1] != 'A' || CommonHeader.cID[2] != 'C' || CommonHeader.cID[3] != ' ')
|
||||
return ERROR_UNDEFINED;
|
||||
|
||||
int nRetVal = ERROR_UNDEFINED;
|
||||
|
||||
if (CommonHeader.nVersion >= 3980)
|
||||
{
|
||||
// current header format
|
||||
nRetVal = AnalyzeCurrent(pInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// legacy support
|
||||
nRetVal = AnalyzeOld(pInfo);
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int CAPEHeader::AnalyzeCurrent(APE_FILE_INFO * pInfo)
|
||||
{
|
||||
// variable declares
|
||||
unsigned int nBytesRead = 0;
|
||||
pInfo->spAPEDescriptor.Assign(new APE_DESCRIPTOR); memset(pInfo->spAPEDescriptor, 0, sizeof(APE_DESCRIPTOR));
|
||||
APE_HEADER APEHeader; memset(&APEHeader, 0, sizeof(APEHeader));
|
||||
|
||||
// read the descriptor
|
||||
m_pIO->Seek(pInfo->nJunkHeaderBytes, FILE_BEGIN);
|
||||
m_pIO->Read(pInfo->spAPEDescriptor, sizeof(APE_DESCRIPTOR), &nBytesRead);
|
||||
|
||||
if ((pInfo->spAPEDescriptor->nDescriptorBytes - nBytesRead) > 0)
|
||||
m_pIO->Seek(pInfo->spAPEDescriptor->nDescriptorBytes - nBytesRead, FILE_CURRENT);
|
||||
|
||||
// read the header
|
||||
m_pIO->Read(&APEHeader, sizeof(APEHeader), &nBytesRead);
|
||||
|
||||
if ((pInfo->spAPEDescriptor->nHeaderBytes - nBytesRead) > 0)
|
||||
m_pIO->Seek(pInfo->spAPEDescriptor->nHeaderBytes - nBytesRead, FILE_CURRENT);
|
||||
|
||||
// fill the APE info structure
|
||||
pInfo->nVersion = int(pInfo->spAPEDescriptor->nVersion);
|
||||
pInfo->nCompressionLevel = int(APEHeader.nCompressionLevel);
|
||||
pInfo->nFormatFlags = int(APEHeader.nFormatFlags);
|
||||
pInfo->nTotalFrames = int(APEHeader.nTotalFrames);
|
||||
pInfo->nFinalFrameBlocks = int(APEHeader.nFinalFrameBlocks);
|
||||
pInfo->nBlocksPerFrame = int(APEHeader.nBlocksPerFrame);
|
||||
pInfo->nChannels = int(APEHeader.nChannels);
|
||||
pInfo->nSampleRate = int(APEHeader.nSampleRate);
|
||||
pInfo->nBitsPerSample = int(APEHeader.nBitsPerSample);
|
||||
pInfo->nBytesPerSample = pInfo->nBitsPerSample / 8;
|
||||
pInfo->nBlockAlign = pInfo->nBytesPerSample * pInfo->nChannels;
|
||||
pInfo->nTotalBlocks = (APEHeader.nTotalFrames == 0) ? 0 : ((APEHeader.nTotalFrames - 1) * pInfo->nBlocksPerFrame) + APEHeader.nFinalFrameBlocks;
|
||||
pInfo->nWAVHeaderBytes = (APEHeader.nFormatFlags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER) ? sizeof(WAVE_HEADER) : pInfo->spAPEDescriptor->nHeaderDataBytes;
|
||||
pInfo->nWAVTerminatingBytes = pInfo->spAPEDescriptor->nTerminatingDataBytes;
|
||||
pInfo->nWAVDataBytes = pInfo->nTotalBlocks * pInfo->nBlockAlign;
|
||||
pInfo->nWAVTotalBytes = pInfo->nWAVDataBytes + pInfo->nWAVHeaderBytes + pInfo->nWAVTerminatingBytes;
|
||||
pInfo->nAPETotalBytes = m_pIO->GetSize();
|
||||
pInfo->nLengthMS = int((double(pInfo->nTotalBlocks) * double(1000)) / double(pInfo->nSampleRate));
|
||||
pInfo->nAverageBitrate = (pInfo->nLengthMS <= 0) ? 0 : int((double(pInfo->nAPETotalBytes) * double(8)) / double(pInfo->nLengthMS));
|
||||
pInfo->nDecompressedBitrate = (pInfo->nBlockAlign * pInfo->nSampleRate * 8) / 1000;
|
||||
pInfo->nSeekTableElements = pInfo->spAPEDescriptor->nSeekTableBytes / 4;
|
||||
|
||||
// get the seek tables (really no reason to get the whole thing if there's extra)
|
||||
pInfo->spSeekByteTable.Assign(new uint32 [pInfo->nSeekTableElements], TRUE);
|
||||
if (pInfo->spSeekByteTable == NULL) { return ERROR_UNDEFINED; }
|
||||
|
||||
m_pIO->Read((unsigned char *) pInfo->spSeekByteTable.GetPtr(), 4 * pInfo->nSeekTableElements, &nBytesRead);
|
||||
|
||||
// get the wave header
|
||||
if (!(APEHeader.nFormatFlags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER))
|
||||
{
|
||||
pInfo->spWaveHeaderData.Assign(new unsigned char [pInfo->nWAVHeaderBytes], TRUE);
|
||||
if (pInfo->spWaveHeaderData == NULL) { return ERROR_UNDEFINED; }
|
||||
m_pIO->Read((unsigned char *) pInfo->spWaveHeaderData, pInfo->nWAVHeaderBytes, &nBytesRead);
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPEHeader::AnalyzeOld(APE_FILE_INFO * pInfo)
|
||||
{
|
||||
// variable declares
|
||||
unsigned int nBytesRead = 0;
|
||||
|
||||
// read the MAC header from the file
|
||||
APE_HEADER_OLD APEHeader;
|
||||
m_pIO->Seek(pInfo->nJunkHeaderBytes, FILE_BEGIN);
|
||||
m_pIO->Read((unsigned char *) &APEHeader, sizeof(APEHeader), &nBytesRead);
|
||||
|
||||
// fail on 0 length APE files (catches non-finalized APE files)
|
||||
if (APEHeader.nTotalFrames == 0)
|
||||
return ERROR_UNDEFINED;
|
||||
|
||||
int nPeakLevel = -1;
|
||||
if (APEHeader.nFormatFlags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL)
|
||||
m_pIO->Read((unsigned char *) &nPeakLevel, 4, &nBytesRead);
|
||||
|
||||
if (APEHeader.nFormatFlags & MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS)
|
||||
m_pIO->Read((unsigned char *) &pInfo->nSeekTableElements, 4, &nBytesRead);
|
||||
else
|
||||
pInfo->nSeekTableElements = APEHeader.nTotalFrames;
|
||||
|
||||
// fill the APE info structure
|
||||
pInfo->nVersion = int(APEHeader.nVersion);
|
||||
pInfo->nCompressionLevel = int(APEHeader.nCompressionLevel);
|
||||
pInfo->nFormatFlags = int(APEHeader.nFormatFlags);
|
||||
pInfo->nTotalFrames = int(APEHeader.nTotalFrames);
|
||||
pInfo->nFinalFrameBlocks = int(APEHeader.nFinalFrameBlocks);
|
||||
pInfo->nBlocksPerFrame = ((APEHeader.nVersion >= 3900) || ((APEHeader.nVersion >= 3800) && (APEHeader.nCompressionLevel == COMPRESSION_LEVEL_EXTRA_HIGH))) ? 73728 : 9216;
|
||||
if ((APEHeader.nVersion >= 3950)) pInfo->nBlocksPerFrame = 73728 * 4;
|
||||
pInfo->nChannels = int(APEHeader.nChannels);
|
||||
pInfo->nSampleRate = int(APEHeader.nSampleRate);
|
||||
pInfo->nBitsPerSample = (pInfo->nFormatFlags & MAC_FORMAT_FLAG_8_BIT) ? 8 : ((pInfo->nFormatFlags & MAC_FORMAT_FLAG_24_BIT) ? 24 : 16);
|
||||
pInfo->nBytesPerSample = pInfo->nBitsPerSample / 8;
|
||||
pInfo->nBlockAlign = pInfo->nBytesPerSample * pInfo->nChannels;
|
||||
pInfo->nTotalBlocks = (APEHeader.nTotalFrames == 0) ? 0 : ((APEHeader.nTotalFrames - 1) * pInfo->nBlocksPerFrame) + APEHeader.nFinalFrameBlocks;
|
||||
pInfo->nWAVHeaderBytes = (APEHeader.nFormatFlags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER) ? sizeof(WAVE_HEADER) : APEHeader.nHeaderBytes;
|
||||
pInfo->nWAVTerminatingBytes = int(APEHeader.nTerminatingBytes);
|
||||
pInfo->nWAVDataBytes = pInfo->nTotalBlocks * pInfo->nBlockAlign;
|
||||
pInfo->nWAVTotalBytes = pInfo->nWAVDataBytes + pInfo->nWAVHeaderBytes + pInfo->nWAVTerminatingBytes;
|
||||
pInfo->nAPETotalBytes = m_pIO->GetSize();
|
||||
pInfo->nLengthMS = int((double(pInfo->nTotalBlocks) * double(1000)) / double(pInfo->nSampleRate));
|
||||
pInfo->nAverageBitrate = (pInfo->nLengthMS <= 0) ? 0 : int((double(pInfo->nAPETotalBytes) * double(8)) / double(pInfo->nLengthMS));
|
||||
pInfo->nDecompressedBitrate = (pInfo->nBlockAlign * pInfo->nSampleRate * 8) / 1000;
|
||||
|
||||
// get the wave header
|
||||
if (!(APEHeader.nFormatFlags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER))
|
||||
{
|
||||
pInfo->spWaveHeaderData.Assign(new unsigned char [APEHeader.nHeaderBytes], TRUE);
|
||||
if (pInfo->spWaveHeaderData == NULL) { return ERROR_UNDEFINED; }
|
||||
m_pIO->Read((unsigned char *) pInfo->spWaveHeaderData, APEHeader.nHeaderBytes, &nBytesRead);
|
||||
}
|
||||
|
||||
// get the seek tables (really no reason to get the whole thing if there's extra)
|
||||
pInfo->spSeekByteTable.Assign(new uint32 [pInfo->nSeekTableElements], TRUE);
|
||||
if (pInfo->spSeekByteTable == NULL) { return ERROR_UNDEFINED; }
|
||||
|
||||
m_pIO->Read((unsigned char *) pInfo->spSeekByteTable.GetPtr(), 4 * pInfo->nSeekTableElements, &nBytesRead);
|
||||
|
||||
if (APEHeader.nVersion <= 3800)
|
||||
{
|
||||
pInfo->spSeekBitTable.Assign(new unsigned char [pInfo->nSeekTableElements], TRUE);
|
||||
if (pInfo->spSeekBitTable == NULL) { return ERROR_UNDEFINED; }
|
||||
|
||||
m_pIO->Read((unsigned char *) pInfo->spSeekBitTable, pInfo->nSeekTableElements, &nBytesRead);
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
57
MAC_SDK/Source/MACLib/APEHeader.h
Normal file
57
MAC_SDK/Source/MACLib/APEHeader.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef APE_HEADER_H
|
||||
#define APE_HEADER_H
|
||||
|
||||
/*****************************************************************************************
|
||||
APE header that all APE files have in common (old and new)
|
||||
*****************************************************************************************/
|
||||
struct APE_COMMON_HEADER
|
||||
{
|
||||
char cID[4]; // should equal 'MAC '
|
||||
uint16 nVersion; // version number * 1000 (3.81 = 3810)
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
APE header structure for old APE files (3.97 and earlier)
|
||||
*****************************************************************************************/
|
||||
struct APE_HEADER_OLD
|
||||
{
|
||||
char cID[4]; // should equal 'MAC '
|
||||
uint16 nVersion; // version number * 1000 (3.81 = 3810)
|
||||
uint16 nCompressionLevel; // the compression level
|
||||
uint16 nFormatFlags; // any format flags (for future use)
|
||||
uint16 nChannels; // the number of channels (1 or 2)
|
||||
uint32 nSampleRate; // the sample rate (typically 44100)
|
||||
uint32 nHeaderBytes; // the bytes after the MAC header that compose the WAV header
|
||||
uint32 nTerminatingBytes; // the bytes after that raw data (for extended info)
|
||||
uint32 nTotalFrames; // the number of frames in the file
|
||||
uint32 nFinalFrameBlocks; // the number of samples in the final frame
|
||||
};
|
||||
|
||||
struct APE_FILE_INFO;
|
||||
class CIO;
|
||||
|
||||
/*****************************************************************************************
|
||||
CAPEHeader - makes managing APE headers a little smoother (and the format change as of 3.98)
|
||||
*****************************************************************************************/
|
||||
class CAPEHeader
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
CAPEHeader(CIO * pIO);
|
||||
~CAPEHeader();
|
||||
|
||||
int Analyze(APE_FILE_INFO * pInfo);
|
||||
|
||||
protected:
|
||||
|
||||
int AnalyzeCurrent(APE_FILE_INFO * pInfo);
|
||||
int AnalyzeOld(APE_FILE_INFO * pInfo);
|
||||
|
||||
int FindDescriptor(BOOL bSeek);
|
||||
|
||||
CIO * m_pIO;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_HEADER_H
|
||||
|
||||
361
MAC_SDK/Source/MACLib/APEInfo.cpp
Normal file
361
MAC_SDK/Source/MACLib/APEInfo.cpp
Normal file
@@ -0,0 +1,361 @@
|
||||
/*****************************************************************************************
|
||||
CAPEInfo:
|
||||
-a class to make working with APE files and getting information about them simple
|
||||
*****************************************************************************************/
|
||||
#include "All.h"
|
||||
#include "APEInfo.h"
|
||||
#include IO_HEADER_FILE
|
||||
#include "APECompress.h"
|
||||
#include "APEHeader.h"
|
||||
|
||||
/*****************************************************************************************
|
||||
Construction
|
||||
*****************************************************************************************/
|
||||
CAPEInfo::CAPEInfo(int * pErrorCode, const wchar_t * pFilename, CAPETag * pTag)
|
||||
{
|
||||
*pErrorCode = ERROR_SUCCESS;
|
||||
CloseFile();
|
||||
|
||||
// open the file
|
||||
m_spIO.Assign(new IO_CLASS_NAME);
|
||||
|
||||
if (m_spIO->Open(pFilename) != 0)
|
||||
{
|
||||
CloseFile();
|
||||
*pErrorCode = ERROR_INVALID_INPUT_FILE;
|
||||
return;
|
||||
}
|
||||
|
||||
// get the file information
|
||||
if (GetFileInformation(TRUE) != 0)
|
||||
{
|
||||
CloseFile();
|
||||
*pErrorCode = ERROR_INVALID_INPUT_FILE;
|
||||
return;
|
||||
}
|
||||
|
||||
// get the tag (do this second so that we don't do it on failure)
|
||||
if (pTag == NULL)
|
||||
{
|
||||
// we don't want to analyze right away for non-local files
|
||||
// since a single I/O object is shared, we can't tag and read at the same time (i.e. in multiple threads)
|
||||
BOOL bAnalyzeNow = TRUE;
|
||||
if ((wcsnicmp(pFilename, L"http://", 7) == 0) || (wcsnicmp(pFilename, L"m01p://", 7) == 0))
|
||||
bAnalyzeNow = FALSE;
|
||||
|
||||
m_spAPETag.Assign(new CAPETag(m_spIO, bAnalyzeNow));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spAPETag.Assign(pTag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CAPEInfo::CAPEInfo(int * pErrorCode, CIO * pIO, CAPETag * pTag)
|
||||
{
|
||||
*pErrorCode = ERROR_SUCCESS;
|
||||
CloseFile();
|
||||
|
||||
m_spIO.Assign(pIO, FALSE, FALSE);
|
||||
|
||||
// get the file information
|
||||
if (GetFileInformation(TRUE) != 0)
|
||||
{
|
||||
CloseFile();
|
||||
*pErrorCode = ERROR_INVALID_INPUT_FILE;
|
||||
return;
|
||||
}
|
||||
|
||||
// get the tag (do this second so that we don't do it on failure)
|
||||
if (pTag == NULL)
|
||||
m_spAPETag.Assign(new CAPETag(m_spIO, TRUE));
|
||||
else
|
||||
m_spAPETag.Assign(pTag);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************
|
||||
Destruction
|
||||
*****************************************************************************************/
|
||||
CAPEInfo::~CAPEInfo()
|
||||
{
|
||||
CloseFile();
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Close the file
|
||||
*****************************************************************************************/
|
||||
int CAPEInfo::CloseFile()
|
||||
{
|
||||
m_spIO.Delete();
|
||||
m_APEFileInfo.spWaveHeaderData.Delete();
|
||||
m_APEFileInfo.spSeekBitTable.Delete();
|
||||
m_APEFileInfo.spSeekByteTable.Delete();
|
||||
m_APEFileInfo.spAPEDescriptor.Delete();
|
||||
|
||||
m_spAPETag.Delete();
|
||||
|
||||
// re-initialize variables
|
||||
m_APEFileInfo.nSeekTableElements = 0;
|
||||
m_bHasFileInformationLoaded = FALSE;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Get the file information about the file
|
||||
*****************************************************************************************/
|
||||
int CAPEInfo::GetFileInformation(BOOL bGetTagInformation)
|
||||
{
|
||||
// quit if there is no simple file
|
||||
if (m_spIO == NULL) { return -1; }
|
||||
|
||||
// quit if the file information has already been loaded
|
||||
if (m_bHasFileInformationLoaded) { return ERROR_SUCCESS; }
|
||||
|
||||
// use a CAPEHeader class to help us analyze the file
|
||||
CAPEHeader APEHeader(m_spIO);
|
||||
int nRetVal = APEHeader.Analyze(&m_APEFileInfo);
|
||||
|
||||
// update our internal state
|
||||
if (nRetVal == ERROR_SUCCESS)
|
||||
m_bHasFileInformationLoaded = TRUE;
|
||||
|
||||
// return
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Primary query function
|
||||
*****************************************************************************************/
|
||||
int CAPEInfo::GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1, int nParam2)
|
||||
{
|
||||
int nRetVal = -1;
|
||||
|
||||
switch (Field)
|
||||
{
|
||||
case APE_INFO_FILE_VERSION:
|
||||
nRetVal = m_APEFileInfo.nVersion;
|
||||
break;
|
||||
case APE_INFO_COMPRESSION_LEVEL:
|
||||
nRetVal = m_APEFileInfo.nCompressionLevel;
|
||||
break;
|
||||
case APE_INFO_FORMAT_FLAGS:
|
||||
nRetVal = m_APEFileInfo.nFormatFlags;
|
||||
break;
|
||||
case APE_INFO_SAMPLE_RATE:
|
||||
nRetVal = m_APEFileInfo.nSampleRate;
|
||||
break;
|
||||
case APE_INFO_BITS_PER_SAMPLE:
|
||||
nRetVal = m_APEFileInfo.nBitsPerSample;
|
||||
break;
|
||||
case APE_INFO_BYTES_PER_SAMPLE:
|
||||
nRetVal = m_APEFileInfo.nBytesPerSample;
|
||||
break;
|
||||
case APE_INFO_CHANNELS:
|
||||
nRetVal = m_APEFileInfo.nChannels;
|
||||
break;
|
||||
case APE_INFO_BLOCK_ALIGN:
|
||||
nRetVal = m_APEFileInfo.nBlockAlign;
|
||||
break;
|
||||
case APE_INFO_BLOCKS_PER_FRAME:
|
||||
nRetVal = m_APEFileInfo.nBlocksPerFrame;
|
||||
break;
|
||||
case APE_INFO_FINAL_FRAME_BLOCKS:
|
||||
nRetVal = m_APEFileInfo.nFinalFrameBlocks;
|
||||
break;
|
||||
case APE_INFO_TOTAL_FRAMES:
|
||||
nRetVal = m_APEFileInfo.nTotalFrames;
|
||||
break;
|
||||
case APE_INFO_WAV_HEADER_BYTES:
|
||||
nRetVal = m_APEFileInfo.nWAVHeaderBytes;
|
||||
break;
|
||||
case APE_INFO_WAV_TERMINATING_BYTES:
|
||||
nRetVal = m_APEFileInfo.nWAVTerminatingBytes;
|
||||
break;
|
||||
case APE_INFO_WAV_DATA_BYTES:
|
||||
nRetVal = m_APEFileInfo.nWAVDataBytes;
|
||||
break;
|
||||
case APE_INFO_WAV_TOTAL_BYTES:
|
||||
nRetVal = m_APEFileInfo.nWAVTotalBytes;
|
||||
break;
|
||||
case APE_INFO_APE_TOTAL_BYTES:
|
||||
nRetVal = m_APEFileInfo.nAPETotalBytes;
|
||||
break;
|
||||
case APE_INFO_TOTAL_BLOCKS:
|
||||
nRetVal = m_APEFileInfo.nTotalBlocks;
|
||||
break;
|
||||
case APE_INFO_LENGTH_MS:
|
||||
nRetVal = m_APEFileInfo.nLengthMS;
|
||||
break;
|
||||
case APE_INFO_AVERAGE_BITRATE:
|
||||
nRetVal = m_APEFileInfo.nAverageBitrate;
|
||||
break;
|
||||
case APE_INFO_FRAME_BITRATE:
|
||||
{
|
||||
int nFrame = nParam1;
|
||||
|
||||
nRetVal = 0;
|
||||
|
||||
int nFrameBytes = GetInfo(APE_INFO_FRAME_BYTES, nFrame);
|
||||
int nFrameBlocks = GetInfo(APE_INFO_FRAME_BLOCKS, nFrame);
|
||||
if ((nFrameBytes > 0) && (nFrameBlocks > 0) && m_APEFileInfo.nSampleRate > 0)
|
||||
{
|
||||
int nFrameMS = (nFrameBlocks * 1000) / m_APEFileInfo.nSampleRate;
|
||||
if (nFrameMS != 0)
|
||||
{
|
||||
nRetVal = (nFrameBytes * 8) / nFrameMS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case APE_INFO_DECOMPRESSED_BITRATE:
|
||||
nRetVal = m_APEFileInfo.nDecompressedBitrate;
|
||||
break;
|
||||
case APE_INFO_PEAK_LEVEL:
|
||||
nRetVal = -1; // no longer supported
|
||||
break;
|
||||
case APE_INFO_SEEK_BIT:
|
||||
{
|
||||
int nFrame = nParam1;
|
||||
if (GET_FRAMES_START_ON_BYTES_BOUNDARIES(this))
|
||||
{
|
||||
nRetVal = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nFrame < 0 || nFrame >= m_APEFileInfo.nTotalFrames)
|
||||
nRetVal = 0;
|
||||
else
|
||||
nRetVal = m_APEFileInfo.spSeekBitTable[nFrame];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case APE_INFO_SEEK_BYTE:
|
||||
{
|
||||
int nFrame = nParam1;
|
||||
if (nFrame < 0 || nFrame >= m_APEFileInfo.nTotalFrames)
|
||||
nRetVal = 0;
|
||||
else
|
||||
nRetVal = m_APEFileInfo.spSeekByteTable[nFrame] + m_APEFileInfo.nJunkHeaderBytes;
|
||||
break;
|
||||
}
|
||||
case APE_INFO_WAV_HEADER_DATA:
|
||||
{
|
||||
char * pBuffer = (char *) nParam1;
|
||||
int nMaxBytes = nParam2;
|
||||
|
||||
if (m_APEFileInfo.nFormatFlags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER)
|
||||
{
|
||||
if (sizeof(WAVE_HEADER) > nMaxBytes)
|
||||
{
|
||||
nRetVal = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
WAVEFORMATEX wfeFormat; GetInfo(APE_INFO_WAVEFORMATEX, (int) &wfeFormat, 0);
|
||||
WAVE_HEADER WAVHeader; FillWaveHeader(&WAVHeader, m_APEFileInfo.nWAVDataBytes, &wfeFormat,
|
||||
m_APEFileInfo.nWAVTerminatingBytes);
|
||||
memcpy(pBuffer, &WAVHeader, sizeof(WAVE_HEADER));
|
||||
nRetVal = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_APEFileInfo.nWAVHeaderBytes > nMaxBytes)
|
||||
{
|
||||
nRetVal = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pBuffer, m_APEFileInfo.spWaveHeaderData, m_APEFileInfo.nWAVHeaderBytes);
|
||||
nRetVal = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case APE_INFO_WAV_TERMINATING_DATA:
|
||||
{
|
||||
char * pBuffer = (char *) nParam1;
|
||||
int nMaxBytes = nParam2;
|
||||
|
||||
if (m_APEFileInfo.nWAVTerminatingBytes > nMaxBytes)
|
||||
{
|
||||
nRetVal = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_APEFileInfo.nWAVTerminatingBytes > 0)
|
||||
{
|
||||
// variables
|
||||
int nOriginalFileLocation = m_spIO->GetPosition();
|
||||
unsigned int nBytesRead = 0;
|
||||
|
||||
// check for a tag
|
||||
m_spIO->Seek(-(m_spAPETag->GetTagBytes() + m_APEFileInfo.nWAVTerminatingBytes), FILE_END);
|
||||
m_spIO->Read(pBuffer, m_APEFileInfo.nWAVTerminatingBytes, &nBytesRead);
|
||||
|
||||
// restore the file pointer
|
||||
m_spIO->Seek(nOriginalFileLocation, FILE_BEGIN);
|
||||
}
|
||||
nRetVal = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case APE_INFO_WAVEFORMATEX:
|
||||
{
|
||||
WAVEFORMATEX * pWaveFormatEx = (WAVEFORMATEX *) nParam1;
|
||||
FillWaveFormatEx(pWaveFormatEx, m_APEFileInfo.nSampleRate, m_APEFileInfo.nBitsPerSample, m_APEFileInfo.nChannels);
|
||||
nRetVal = 0;
|
||||
break;
|
||||
}
|
||||
case APE_INFO_IO_SOURCE:
|
||||
nRetVal = (int) m_spIO.GetPtr();
|
||||
break;
|
||||
case APE_INFO_FRAME_BYTES:
|
||||
{
|
||||
int nFrame = nParam1;
|
||||
|
||||
// bound-check the frame index
|
||||
if ((nFrame < 0) || (nFrame >= m_APEFileInfo.nTotalFrames))
|
||||
{
|
||||
nRetVal = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nFrame != (m_APEFileInfo.nTotalFrames - 1))
|
||||
nRetVal = GetInfo(APE_INFO_SEEK_BYTE, nFrame + 1) - GetInfo(APE_INFO_SEEK_BYTE, nFrame);
|
||||
else
|
||||
nRetVal = m_spIO->GetSize() - m_spAPETag->GetTagBytes() - m_APEFileInfo.nWAVTerminatingBytes - GetInfo(APE_INFO_SEEK_BYTE, nFrame);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case APE_INFO_FRAME_BLOCKS:
|
||||
{
|
||||
int nFrame = nParam1;
|
||||
|
||||
// bound-check the frame index
|
||||
if ((nFrame < 0) || (nFrame >= m_APEFileInfo.nTotalFrames))
|
||||
{
|
||||
nRetVal = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nFrame != (m_APEFileInfo.nTotalFrames - 1))
|
||||
nRetVal = m_APEFileInfo.nBlocksPerFrame;
|
||||
else
|
||||
nRetVal = m_APEFileInfo.nFinalFrameBlocks;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case APE_INFO_TAG:
|
||||
nRetVal = (int) m_spAPETag.GetPtr();
|
||||
break;
|
||||
case APE_INTERNAL_INFO:
|
||||
nRetVal = (int) &m_APEFileInfo;
|
||||
break;
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
100
MAC_SDK/Source/MACLib/APEInfo.h
Normal file
100
MAC_SDK/Source/MACLib/APEInfo.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*****************************************************************************************
|
||||
APEInfo.h
|
||||
Copyright (C) 2000 by Matthew T. Ashland All Rights Reserved.
|
||||
|
||||
Simple method for working with APE files... it encapsulates reading, writing and getting
|
||||
file information. Just create a CAPEInfo class, call OpenFile(), and use the class methods
|
||||
to do whatever you need... the destructor will take care of any cleanup
|
||||
|
||||
Notes:
|
||||
-Most all functions return 0 upon success, and some error code (other than 0) on
|
||||
failure. However, all of the file functions that are wrapped from the Win32 API
|
||||
return 0 on failure and some other number on success. This applies to ReadFile,
|
||||
WriteFile, SetFilePointer, etc...
|
||||
|
||||
WARNING:
|
||||
-This class driven system for using Monkey's Audio is still in development, so
|
||||
I can't make any guarantees that the classes and libraries won't change before
|
||||
everything gets finalized. Use them at your own risk
|
||||
*****************************************************************************************/
|
||||
|
||||
#ifndef APE_APEINFO_H
|
||||
#define APE_APEINFO_H
|
||||
|
||||
#include "IO.h"
|
||||
#include "APETag.h"
|
||||
#include "MACLib.h"
|
||||
|
||||
/*****************************************************************************************
|
||||
APE_FILE_INFO - structure which describes most aspects of an APE file
|
||||
(used internally for speed and ease)
|
||||
*****************************************************************************************/
|
||||
struct APE_FILE_INFO
|
||||
{
|
||||
int nVersion; // file version number * 1000 (3.93 = 3930)
|
||||
int nCompressionLevel; // the compression level
|
||||
int nFormatFlags; // format flags
|
||||
int nTotalFrames; // the total number frames (frames are used internally)
|
||||
int nBlocksPerFrame; // the samples in a frame (frames are used internally)
|
||||
int nFinalFrameBlocks; // the number of samples in the final frame
|
||||
int nChannels; // audio channels
|
||||
int nSampleRate; // audio samples per second
|
||||
int nBitsPerSample; // audio bits per sample
|
||||
int nBytesPerSample; // audio bytes per sample
|
||||
int nBlockAlign; // audio block align (channels * bytes per sample)
|
||||
int nWAVHeaderBytes; // header bytes of the original WAV
|
||||
int nWAVDataBytes; // data bytes of the original WAV
|
||||
int nWAVTerminatingBytes; // terminating bytes of the original WAV
|
||||
int nWAVTotalBytes; // total bytes of the original WAV
|
||||
int nAPETotalBytes; // total bytes of the APE file
|
||||
int nTotalBlocks; // the total number audio blocks
|
||||
int nLengthMS; // the length in milliseconds
|
||||
int nAverageBitrate; // the kbps (i.e. 637 kpbs)
|
||||
int nDecompressedBitrate; // the kbps of the decompressed audio (i.e. 1440 kpbs for CD audio)
|
||||
int nJunkHeaderBytes; // used for ID3v2, etc.
|
||||
int nSeekTableElements; // the number of elements in the seek table(s)
|
||||
|
||||
CSmartPtr<uint32> spSeekByteTable; // the seek table (byte)
|
||||
CSmartPtr<unsigned char> spSeekBitTable; // the seek table (bits -- legacy)
|
||||
CSmartPtr<unsigned char> spWaveHeaderData; // the pre-audio header data
|
||||
CSmartPtr<APE_DESCRIPTOR> spAPEDescriptor; // the descriptor (only with newer files)
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
Helper macros (sort of hacky)
|
||||
*****************************************************************************************/
|
||||
#define GET_USES_CRC(APE_INFO) (((APE_INFO)->GetInfo(APE_INFO_FORMAT_FLAGS) & MAC_FORMAT_FLAG_CRC) ? TRUE : FALSE)
|
||||
#define GET_FRAMES_START_ON_BYTES_BOUNDARIES(APE_INFO) (((APE_INFO)->GetInfo(APE_INFO_FILE_VERSION) > 3800) ? TRUE : FALSE)
|
||||
#define GET_USES_SPECIAL_FRAMES(APE_INFO) (((APE_INFO)->GetInfo(APE_INFO_FILE_VERSION) > 3820) ? TRUE : FALSE)
|
||||
#define GET_IO(APE_INFO) ((CIO *) (APE_INFO)->GetInfo(APE_INFO_IO_SOURCE))
|
||||
#define GET_TAG(APE_INFO) ((CAPETag *) (APE_INFO)->GetInfo(APE_INFO_TAG))
|
||||
|
||||
/*****************************************************************************************
|
||||
CAPEInfo - use this for all work with APE files
|
||||
*****************************************************************************************/
|
||||
class CAPEInfo
|
||||
{
|
||||
public:
|
||||
|
||||
// construction and destruction
|
||||
CAPEInfo(int * pErrorCode, const wchar_t * pFilename, CAPETag * pTag = NULL);
|
||||
CAPEInfo(int * pErrorCode, CIO * pIO, CAPETag * pTag = NULL);
|
||||
virtual ~CAPEInfo();
|
||||
|
||||
// query for information
|
||||
int GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1 = 0, int nParam2 = 0);
|
||||
|
||||
private:
|
||||
|
||||
// internal functions
|
||||
int GetFileInformation(BOOL bGetTagInformation = TRUE);
|
||||
int CloseFile();
|
||||
|
||||
// internal variables
|
||||
BOOL m_bHasFileInformationLoaded;
|
||||
CSmartPtr<CIO> m_spIO;
|
||||
CSmartPtr<CAPETag> m_spAPETag;
|
||||
APE_FILE_INFO m_APEFileInfo;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_APEINFO_H
|
||||
120
MAC_SDK/Source/MACLib/APELink.cpp
Normal file
120
MAC_SDK/Source/MACLib/APELink.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include "All.h"
|
||||
#include "APELink.h"
|
||||
#include "CharacterHelper.h"
|
||||
#include IO_HEADER_FILE
|
||||
|
||||
#define APE_LINK_HEADER "[Monkey's Audio Image Link File]"
|
||||
#define APE_LINK_IMAGE_FILE_TAG "Image File="
|
||||
#define APE_LINK_START_BLOCK_TAG "Start Block="
|
||||
#define APE_LINK_FINISH_BLOCK_TAG "Finish Block="
|
||||
|
||||
CAPELink::CAPELink(const str_utf16 * pFilename)
|
||||
{
|
||||
// empty
|
||||
m_bIsLinkFile = FALSE;
|
||||
m_nStartBlock = 0;
|
||||
m_nFinishBlock = 0;
|
||||
m_cImageFilename[0] = 0;
|
||||
|
||||
// open the file
|
||||
IO_CLASS_NAME ioLinkFile;
|
||||
if (ioLinkFile.Open(pFilename) == ERROR_SUCCESS)
|
||||
{
|
||||
// create a buffer
|
||||
CSmartPtr<char> spBuffer(new char [1024], TRUE);
|
||||
|
||||
// fill the buffer from the file and null terminate it
|
||||
unsigned int nBytesRead = 0;
|
||||
ioLinkFile.Read(spBuffer.GetPtr(), 1023, &nBytesRead);
|
||||
spBuffer[nBytesRead] = 0;
|
||||
|
||||
// call the other constructor (uses a buffer instead of opening the file)
|
||||
ParseData(spBuffer, pFilename);
|
||||
}
|
||||
}
|
||||
|
||||
CAPELink::CAPELink(const char * pData, const str_utf16 * pFilename)
|
||||
{
|
||||
ParseData(pData, pFilename);
|
||||
}
|
||||
|
||||
CAPELink::~CAPELink()
|
||||
{
|
||||
}
|
||||
|
||||
void CAPELink::ParseData(const char * pData, const str_utf16 * pFilename)
|
||||
{
|
||||
// empty
|
||||
m_bIsLinkFile = FALSE;
|
||||
m_nStartBlock = 0;
|
||||
m_nFinishBlock = 0;
|
||||
m_cImageFilename[0] = 0;
|
||||
|
||||
if (pData != NULL)
|
||||
{
|
||||
// parse out the information
|
||||
char * pHeader = (char*)strstr(pData, APE_LINK_HEADER);
|
||||
char * pImageFile = (char*)strstr(pData, APE_LINK_IMAGE_FILE_TAG);
|
||||
char * pStartBlock = (char*)strstr(pData, APE_LINK_START_BLOCK_TAG);
|
||||
char * pFinishBlock = (char*)strstr(pData, APE_LINK_FINISH_BLOCK_TAG);
|
||||
|
||||
if (pHeader && pImageFile && pStartBlock && pFinishBlock)
|
||||
{
|
||||
if ((_strnicmp(pHeader, APE_LINK_HEADER, strlen(APE_LINK_HEADER)) == 0) &&
|
||||
(_strnicmp(pImageFile, APE_LINK_IMAGE_FILE_TAG, strlen(APE_LINK_IMAGE_FILE_TAG)) == 0) &&
|
||||
(_strnicmp(pStartBlock, APE_LINK_START_BLOCK_TAG, strlen(APE_LINK_START_BLOCK_TAG)) == 0) &&
|
||||
(_strnicmp(pFinishBlock, APE_LINK_FINISH_BLOCK_TAG, strlen(APE_LINK_FINISH_BLOCK_TAG)) == 0))
|
||||
{
|
||||
// get the start and finish blocks
|
||||
m_nStartBlock = atoi(&pStartBlock[strlen(APE_LINK_START_BLOCK_TAG)]);
|
||||
m_nFinishBlock = atoi(&pFinishBlock[strlen(APE_LINK_FINISH_BLOCK_TAG)]);
|
||||
|
||||
// get the path
|
||||
char cImageFile[MAX_PATH + 1]; int nIndex = 0;
|
||||
char * pImageCharacter = &pImageFile[strlen(APE_LINK_IMAGE_FILE_TAG)];
|
||||
while ((*pImageCharacter != 0) && (*pImageCharacter != '\r') && (*pImageCharacter != '\n'))
|
||||
cImageFile[nIndex++] = *pImageCharacter++;
|
||||
cImageFile[nIndex] = 0;
|
||||
|
||||
CSmartPtr<str_utf16> spImageFileUTF16(GetUTF16FromUTF8((UCHAR *) cImageFile), TRUE);
|
||||
|
||||
// process the path
|
||||
if (wcsrchr(spImageFileUTF16, '\\') == NULL)
|
||||
{
|
||||
str_utf16 cImagePath[MAX_PATH + 1];
|
||||
wcscpy(cImagePath, pFilename);
|
||||
wcscpy(wcsrchr(cImagePath, '\\') + 1, spImageFileUTF16);
|
||||
wcscpy(m_cImageFilename, cImagePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscpy(m_cImageFilename, spImageFileUTF16);
|
||||
}
|
||||
|
||||
// this is a valid link file
|
||||
m_bIsLinkFile = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CAPELink::GetStartBlock()
|
||||
{
|
||||
return m_nStartBlock;
|
||||
}
|
||||
|
||||
int CAPELink::GetFinishBlock()
|
||||
{
|
||||
return m_nFinishBlock;
|
||||
}
|
||||
|
||||
const str_utf16 * CAPELink::GetImageFilename()
|
||||
{
|
||||
return m_cImageFilename;
|
||||
}
|
||||
|
||||
BOOL CAPELink::GetIsLinkFile()
|
||||
{
|
||||
return m_bIsLinkFile;
|
||||
}
|
||||
|
||||
30
MAC_SDK/Source/MACLib/APELink.h
Normal file
30
MAC_SDK/Source/MACLib/APELink.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef APE_APELINK_H
|
||||
#define APE_APELINK_H
|
||||
|
||||
#include "IO.h"
|
||||
#include "APEInfo.h"
|
||||
|
||||
class CAPELink
|
||||
{
|
||||
public:
|
||||
|
||||
CAPELink(const str_utf16 * pFilename);
|
||||
CAPELink(const char * pData, const str_utf16 * pFilename);
|
||||
~CAPELink();
|
||||
|
||||
BOOL GetIsLinkFile();
|
||||
int GetStartBlock();
|
||||
int GetFinishBlock();
|
||||
const wchar_t * GetImageFilename();
|
||||
|
||||
protected:
|
||||
|
||||
BOOL m_bIsLinkFile;
|
||||
int m_nStartBlock;
|
||||
int m_nFinishBlock;
|
||||
str_utf16 m_cImageFilename[MAX_PATH];
|
||||
|
||||
void ParseData(const char * pData, const str_utf16 * pFilename);
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_APELINK_H
|
||||
426
MAC_SDK/Source/MACLib/APESimple.cpp
Normal file
426
MAC_SDK/Source/MACLib/APESimple.cpp
Normal file
@@ -0,0 +1,426 @@
|
||||
#include "All.h"
|
||||
#include "APEInfo.h"
|
||||
#include "APECompress.h"
|
||||
#include "APEDecompress.h"
|
||||
#include "WAVInputSource.h"
|
||||
#include IO_HEADER_FILE
|
||||
#include "MACProgressHelper.h"
|
||||
#include "GlobalFunctions.h"
|
||||
#include "MD5.h"
|
||||
#include "CharacterHelper.h"
|
||||
|
||||
#define UNMAC_DECODER_OUTPUT_NONE 0
|
||||
#define UNMAC_DECODER_OUTPUT_WAV 1
|
||||
#define UNMAC_DECODER_OUTPUT_APE 2
|
||||
|
||||
#define BLOCKS_PER_DECODE 9216
|
||||
|
||||
int DecompressCore(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nOutputMode, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
|
||||
|
||||
/*****************************************************************************************
|
||||
ANSI wrappers
|
||||
*****************************************************************************************/
|
||||
int __stdcall CompressFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag)
|
||||
{
|
||||
CSmartPtr<str_utf16> spInputFile(GetUTF16FromANSI(pInputFilename), TRUE);
|
||||
CSmartPtr<str_utf16> spOutputFile(GetUTF16FromANSI(pOutputFilename), TRUE);
|
||||
return CompressFileW(spInputFile, spOutputFile, nCompressionLevel, pPercentageDone, ProgressCallback, pKillFlag);
|
||||
}
|
||||
|
||||
int __stdcall DecompressFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag)
|
||||
{
|
||||
CSmartPtr<str_utf16> spInputFile(GetUTF16FromANSI(pInputFilename), TRUE);
|
||||
CSmartPtr<str_utf16> spOutputFile(GetUTF16FromANSI(pOutputFilename), TRUE);
|
||||
return DecompressFileW(spInputFile, pOutputFilename ? spOutputFile : NULL, pPercentageDone, ProgressCallback, pKillFlag);
|
||||
}
|
||||
|
||||
int __stdcall ConvertFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag)
|
||||
{
|
||||
CSmartPtr<str_utf16> spInputFile(GetUTF16FromANSI(pInputFilename), TRUE);
|
||||
CSmartPtr<str_utf16> spOutputFile(GetUTF16FromANSI(pOutputFilename), TRUE);
|
||||
return ConvertFileW(spInputFile, spOutputFile, nCompressionLevel, pPercentageDone, ProgressCallback, pKillFlag);
|
||||
}
|
||||
|
||||
int __stdcall VerifyFile(const str_ansi * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag, BOOL bQuickVerifyIfPossible)
|
||||
{
|
||||
CSmartPtr<str_utf16> spInputFile(GetUTF16FromANSI(pInputFilename), TRUE);
|
||||
return VerifyFileW(spInputFile, pPercentageDone, ProgressCallback, pKillFlag, FALSE);
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Compress file
|
||||
*****************************************************************************************/
|
||||
int __stdcall CompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag)
|
||||
{
|
||||
// declare the variables
|
||||
int nFunctionRetVal = ERROR_SUCCESS;
|
||||
WAVEFORMATEX WaveFormatEx;
|
||||
CSmartPtr<CMACProgressHelper> spMACProgressHelper;
|
||||
CSmartPtr<unsigned char> spBuffer;
|
||||
CSmartPtr<IAPECompress> spAPECompress;
|
||||
|
||||
try
|
||||
{
|
||||
// create the input source
|
||||
int nRetVal = ERROR_UNDEFINED;
|
||||
int nAudioBlocks = 0; int nHeaderBytes = 0; int nTerminatingBytes = 0;
|
||||
CSmartPtr<CInputSource> spInputSource(CreateInputSource(pInputFilename, &WaveFormatEx, &nAudioBlocks,
|
||||
&nHeaderBytes, &nTerminatingBytes, &nRetVal));
|
||||
|
||||
if ((spInputSource == NULL) || (nRetVal != ERROR_SUCCESS))
|
||||
throw nRetVal;
|
||||
|
||||
// create the compressor
|
||||
spAPECompress.Assign(CreateIAPECompress());
|
||||
if (spAPECompress == NULL) throw ERROR_UNDEFINED;
|
||||
|
||||
// figure the audio bytes
|
||||
int nAudioBytes = nAudioBlocks * WaveFormatEx.nBlockAlign;
|
||||
|
||||
// start the encoder
|
||||
if (nHeaderBytes > 0) spBuffer.Assign(new unsigned char [nHeaderBytes], TRUE);
|
||||
THROW_ON_ERROR(spInputSource->GetHeaderData(spBuffer.GetPtr()))
|
||||
THROW_ON_ERROR(spAPECompress->Start(pOutputFilename, &WaveFormatEx, nAudioBytes,
|
||||
nCompressionLevel, spBuffer.GetPtr(), nHeaderBytes));
|
||||
|
||||
spBuffer.Delete();
|
||||
|
||||
// set-up the progress
|
||||
spMACProgressHelper.Assign(new CMACProgressHelper(nAudioBytes, pPercentageDone, ProgressCallback, pKillFlag));
|
||||
|
||||
// master loop
|
||||
int nBytesLeft = nAudioBytes;
|
||||
|
||||
while (nBytesLeft > 0)
|
||||
{
|
||||
int nBytesAdded = 0;
|
||||
THROW_ON_ERROR(spAPECompress->AddDataFromInputSource(spInputSource.GetPtr(), nBytesLeft, &nBytesAdded))
|
||||
|
||||
nBytesLeft -= nBytesAdded;
|
||||
|
||||
// update the progress
|
||||
spMACProgressHelper->UpdateProgress(nAudioBytes - nBytesLeft);
|
||||
|
||||
// process the kill flag
|
||||
if (spMACProgressHelper->ProcessKillFlag(TRUE) != ERROR_SUCCESS)
|
||||
throw(ERROR_USER_STOPPED_PROCESSING);
|
||||
}
|
||||
|
||||
// finalize the file
|
||||
if (nTerminatingBytes > 0) spBuffer.Assign(new unsigned char [nTerminatingBytes], TRUE);
|
||||
THROW_ON_ERROR(spInputSource->GetTerminatingData(spBuffer.GetPtr()));
|
||||
THROW_ON_ERROR(spAPECompress->Finish(spBuffer.GetPtr(), nTerminatingBytes, nTerminatingBytes))
|
||||
|
||||
// update the progress to 100%
|
||||
spMACProgressHelper->UpdateProgressComplete();
|
||||
}
|
||||
catch(int nErrorCode)
|
||||
{
|
||||
nFunctionRetVal = (nErrorCode == 0) ? ERROR_UNDEFINED : nErrorCode;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
nFunctionRetVal = ERROR_UNDEFINED;
|
||||
}
|
||||
|
||||
// kill the compressor if we failed
|
||||
if ((nFunctionRetVal != 0) && (spAPECompress != NULL))
|
||||
spAPECompress->Kill();
|
||||
|
||||
// return
|
||||
return nFunctionRetVal;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************
|
||||
Verify file
|
||||
*****************************************************************************************/
|
||||
int __stdcall VerifyFileW(const str_utf16 * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag, BOOL bQuickVerifyIfPossible)
|
||||
{
|
||||
// error check the function parameters
|
||||
if (pInputFilename == NULL)
|
||||
{
|
||||
return ERROR_INVALID_FUNCTION_PARAMETER;
|
||||
}
|
||||
|
||||
|
||||
// return value
|
||||
int nRetVal = ERROR_UNDEFINED;
|
||||
|
||||
// see if we can quick verify
|
||||
if (bQuickVerifyIfPossible)
|
||||
{
|
||||
CSmartPtr<IAPEDecompress> spAPEDecompress;
|
||||
try
|
||||
{
|
||||
int nFunctionRetVal = ERROR_SUCCESS;
|
||||
|
||||
spAPEDecompress.Assign(CreateIAPEDecompress(pInputFilename, &nFunctionRetVal));
|
||||
if (spAPEDecompress == NULL || nFunctionRetVal != ERROR_SUCCESS) throw(nFunctionRetVal);
|
||||
|
||||
APE_FILE_INFO * pInfo = (APE_FILE_INFO *) spAPEDecompress->GetInfo(APE_INTERNAL_INFO);
|
||||
if ((pInfo->nVersion < 3980) || (pInfo->spAPEDescriptor == NULL))
|
||||
throw(ERROR_UPSUPPORTED_FILE_VERSION);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
bQuickVerifyIfPossible = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// if we can and should quick verify, then do it
|
||||
if (bQuickVerifyIfPossible)
|
||||
{
|
||||
// variable declares
|
||||
int nFunctionRetVal = ERROR_SUCCESS;
|
||||
unsigned int nBytesRead = 0;
|
||||
CSmartPtr<IAPEDecompress> spAPEDecompress;
|
||||
|
||||
// run the quick verify
|
||||
try
|
||||
{
|
||||
spAPEDecompress.Assign(CreateIAPEDecompress(pInputFilename, &nFunctionRetVal));
|
||||
if (spAPEDecompress == NULL || nFunctionRetVal != ERROR_SUCCESS) throw(nFunctionRetVal);
|
||||
|
||||
CMD5Helper MD5Helper;
|
||||
|
||||
CIO * pIO = GET_IO(spAPEDecompress);
|
||||
APE_FILE_INFO * pInfo = (APE_FILE_INFO *) spAPEDecompress->GetInfo(APE_INTERNAL_INFO);
|
||||
|
||||
if ((pInfo->nVersion < 3980) || (pInfo->spAPEDescriptor == NULL))
|
||||
throw(ERROR_UPSUPPORTED_FILE_VERSION);
|
||||
|
||||
int nHead = pInfo->nJunkHeaderBytes + pInfo->spAPEDescriptor->nDescriptorBytes;
|
||||
int nStart = nHead + pInfo->spAPEDescriptor->nHeaderBytes + pInfo->spAPEDescriptor->nSeekTableBytes;
|
||||
|
||||
pIO->Seek(nHead, FILE_BEGIN);
|
||||
int nHeadBytes = nStart - nHead;
|
||||
CSmartPtr<unsigned char> spHeadBuffer(new unsigned char [nHeadBytes], TRUE);
|
||||
if ((pIO->Read(spHeadBuffer, nHeadBytes, &nBytesRead) != ERROR_SUCCESS) || (nHeadBytes != int(nBytesRead)))
|
||||
throw(ERROR_IO_READ);
|
||||
|
||||
int nBytesLeft = pInfo->spAPEDescriptor->nHeaderDataBytes + pInfo->spAPEDescriptor->nAPEFrameDataBytes + pInfo->spAPEDescriptor->nTerminatingDataBytes;
|
||||
CSmartPtr<unsigned char> spBuffer(new unsigned char [16384], TRUE);
|
||||
nBytesRead = 1;
|
||||
while ((nBytesLeft > 0) && (nBytesRead > 0))
|
||||
{
|
||||
int nBytesToRead = min(16384, nBytesLeft);
|
||||
if (pIO->Read(spBuffer, nBytesToRead, &nBytesRead) != ERROR_SUCCESS)
|
||||
throw(ERROR_IO_READ);
|
||||
|
||||
MD5Helper.AddData(spBuffer, nBytesRead);
|
||||
nBytesLeft -= nBytesRead;
|
||||
}
|
||||
|
||||
if (nBytesLeft != 0)
|
||||
throw(ERROR_IO_READ);
|
||||
|
||||
MD5Helper.AddData(spHeadBuffer, nHeadBytes);
|
||||
|
||||
unsigned char cResult[16];
|
||||
MD5Helper.GetResult(cResult);
|
||||
|
||||
if (memcmp(cResult, pInfo->spAPEDescriptor->cFileMD5, 16) != 0)
|
||||
nFunctionRetVal = ERROR_INVALID_CHECKSUM;
|
||||
|
||||
}
|
||||
catch(int nErrorCode)
|
||||
{
|
||||
nFunctionRetVal = (nErrorCode == 0) ? ERROR_UNDEFINED : nErrorCode;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
nFunctionRetVal = ERROR_UNDEFINED;
|
||||
}
|
||||
|
||||
// return value
|
||||
nRetVal = nFunctionRetVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
nRetVal = DecompressCore(pInputFilename, NULL, UNMAC_DECODER_OUTPUT_NONE, -1, pPercentageDone, ProgressCallback, pKillFlag);
|
||||
}
|
||||
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Decompress file
|
||||
*****************************************************************************************/
|
||||
int __stdcall DecompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag)
|
||||
{
|
||||
if (pOutputFilename == NULL)
|
||||
return VerifyFileW(pInputFilename, pPercentageDone, ProgressCallback, pKillFlag);
|
||||
else
|
||||
return DecompressCore(pInputFilename, pOutputFilename, UNMAC_DECODER_OUTPUT_WAV, -1, pPercentageDone, ProgressCallback, pKillFlag);
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Convert file
|
||||
*****************************************************************************************/
|
||||
int __stdcall ConvertFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag)
|
||||
{
|
||||
return DecompressCore(pInputFilename, pOutputFilename, UNMAC_DECODER_OUTPUT_APE, nCompressionLevel, pPercentageDone, ProgressCallback, pKillFlag);
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Decompress a file using the specified output method
|
||||
*****************************************************************************************/
|
||||
int DecompressCore(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nOutputMode, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag)
|
||||
{
|
||||
// error check the function parameters
|
||||
if (pInputFilename == NULL)
|
||||
{
|
||||
return ERROR_INVALID_FUNCTION_PARAMETER;
|
||||
}
|
||||
|
||||
// variable declares
|
||||
int nFunctionRetVal = ERROR_SUCCESS;
|
||||
CSmartPtr<IO_CLASS_NAME> spioOutput;
|
||||
CSmartPtr<IAPECompress> spAPECompress;
|
||||
CSmartPtr<IAPEDecompress> spAPEDecompress;
|
||||
CSmartPtr<unsigned char> spTempBuffer;
|
||||
CSmartPtr<CMACProgressHelper> spMACProgressHelper;
|
||||
WAVEFORMATEX wfeInput;
|
||||
|
||||
try
|
||||
{
|
||||
// create the decoder
|
||||
spAPEDecompress.Assign(CreateIAPEDecompress(pInputFilename, &nFunctionRetVal));
|
||||
if (spAPEDecompress == NULL || nFunctionRetVal != ERROR_SUCCESS) throw(nFunctionRetVal);
|
||||
|
||||
// get the input format
|
||||
THROW_ON_ERROR(spAPEDecompress->GetInfo(APE_INFO_WAVEFORMATEX, (int) &wfeInput))
|
||||
|
||||
// allocate space for the header
|
||||
spTempBuffer.Assign(new unsigned char [spAPEDecompress->GetInfo(APE_INFO_WAV_HEADER_BYTES)], TRUE);
|
||||
if (spTempBuffer == NULL) throw(ERROR_INSUFFICIENT_MEMORY);
|
||||
|
||||
// get the header
|
||||
THROW_ON_ERROR(spAPEDecompress->GetInfo(APE_INFO_WAV_HEADER_DATA, (int) spTempBuffer.GetPtr(), spAPEDecompress->GetInfo(APE_INFO_WAV_HEADER_BYTES)));
|
||||
|
||||
// initialize the output
|
||||
if (nOutputMode == UNMAC_DECODER_OUTPUT_WAV)
|
||||
{
|
||||
// create the file
|
||||
spioOutput.Assign(new IO_CLASS_NAME); THROW_ON_ERROR(spioOutput->Create(pOutputFilename))
|
||||
|
||||
// output the header
|
||||
THROW_ON_ERROR(WriteSafe(spioOutput, spTempBuffer, spAPEDecompress->GetInfo(APE_INFO_WAV_HEADER_BYTES)));
|
||||
}
|
||||
else if (nOutputMode == UNMAC_DECODER_OUTPUT_APE)
|
||||
{
|
||||
// quit if there is nothing to do
|
||||
if (spAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) == MAC_VERSION_NUMBER && spAPEDecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL) == nCompressionLevel)
|
||||
throw(ERROR_SKIPPED);
|
||||
|
||||
// create and start the compressor
|
||||
spAPECompress.Assign(CreateIAPECompress());
|
||||
THROW_ON_ERROR(spAPECompress->Start(pOutputFilename, &wfeInput, spAPEDecompress->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS) * spAPEDecompress->GetInfo(APE_INFO_BLOCK_ALIGN),
|
||||
nCompressionLevel, spTempBuffer, spAPEDecompress->GetInfo(APE_INFO_WAV_HEADER_BYTES)))
|
||||
}
|
||||
|
||||
// allocate space for decompression
|
||||
spTempBuffer.Assign(new unsigned char [spAPEDecompress->GetInfo(APE_INFO_BLOCK_ALIGN) * BLOCKS_PER_DECODE], TRUE);
|
||||
if (spTempBuffer == NULL) throw(ERROR_INSUFFICIENT_MEMORY);
|
||||
|
||||
int nBlocksLeft = spAPEDecompress->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS);
|
||||
|
||||
// create the progress helper
|
||||
spMACProgressHelper.Assign(new CMACProgressHelper(nBlocksLeft / BLOCKS_PER_DECODE, pPercentageDone, ProgressCallback, pKillFlag));
|
||||
|
||||
// main decoding loop
|
||||
while (nBlocksLeft > 0)
|
||||
{
|
||||
// decode data
|
||||
int nBlocksDecoded = -1;
|
||||
int nRetVal = spAPEDecompress->GetData((char *) spTempBuffer.GetPtr(), BLOCKS_PER_DECODE, &nBlocksDecoded);
|
||||
if (nRetVal != ERROR_SUCCESS)
|
||||
throw(ERROR_INVALID_CHECKSUM);
|
||||
|
||||
// handle the output
|
||||
if (nOutputMode == UNMAC_DECODER_OUTPUT_WAV)
|
||||
{
|
||||
unsigned int nBytesToWrite = (nBlocksDecoded * spAPEDecompress->GetInfo(APE_INFO_BLOCK_ALIGN));
|
||||
unsigned int nBytesWritten = 0;
|
||||
int nRetVal = spioOutput->Write(spTempBuffer, nBytesToWrite, &nBytesWritten);
|
||||
if ((nRetVal != 0) || (nBytesToWrite != nBytesWritten))
|
||||
throw(ERROR_IO_WRITE);
|
||||
}
|
||||
else if (nOutputMode == UNMAC_DECODER_OUTPUT_APE)
|
||||
{
|
||||
THROW_ON_ERROR(spAPECompress->AddData(spTempBuffer, nBlocksDecoded * spAPEDecompress->GetInfo(APE_INFO_BLOCK_ALIGN)))
|
||||
}
|
||||
|
||||
// update amount remaining
|
||||
nBlocksLeft -= nBlocksDecoded;
|
||||
|
||||
// update progress and kill flag
|
||||
spMACProgressHelper->UpdateProgress();
|
||||
if (spMACProgressHelper->ProcessKillFlag(TRUE) != 0)
|
||||
throw(ERROR_USER_STOPPED_PROCESSING);
|
||||
}
|
||||
|
||||
// terminate the output
|
||||
if (nOutputMode == UNMAC_DECODER_OUTPUT_WAV)
|
||||
{
|
||||
// write any terminating WAV data
|
||||
if (spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES) > 0)
|
||||
{
|
||||
spTempBuffer.Assign(new unsigned char[spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES)], TRUE);
|
||||
if (spTempBuffer == NULL) throw(ERROR_INSUFFICIENT_MEMORY);
|
||||
THROW_ON_ERROR(spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_DATA, (int) spTempBuffer.GetPtr(), spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES)))
|
||||
|
||||
unsigned int nBytesToWrite = spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES);
|
||||
unsigned int nBytesWritten = 0;
|
||||
int nRetVal = spioOutput->Write(spTempBuffer, nBytesToWrite, &nBytesWritten);
|
||||
if ((nRetVal != 0) || (nBytesToWrite != nBytesWritten))
|
||||
throw(ERROR_IO_WRITE);
|
||||
}
|
||||
}
|
||||
else if (nOutputMode == UNMAC_DECODER_OUTPUT_APE)
|
||||
{
|
||||
// write the WAV data and any tag
|
||||
int nTagBytes = GET_TAG(spAPEDecompress)->GetTagBytes();
|
||||
BOOL bHasTag = (nTagBytes > 0);
|
||||
int nTerminatingBytes = nTagBytes;
|
||||
nTerminatingBytes += spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES);
|
||||
|
||||
if (nTerminatingBytes > 0)
|
||||
{
|
||||
spTempBuffer.Assign(new unsigned char[nTerminatingBytes], TRUE);
|
||||
if (spTempBuffer == NULL) throw(ERROR_INSUFFICIENT_MEMORY);
|
||||
|
||||
THROW_ON_ERROR(spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_DATA, (int) spTempBuffer.GetPtr(), nTerminatingBytes))
|
||||
|
||||
if (bHasTag)
|
||||
{
|
||||
unsigned int nBytesRead = 0;
|
||||
THROW_ON_ERROR(GET_IO(spAPEDecompress)->Seek(-(nTagBytes), FILE_END))
|
||||
THROW_ON_ERROR(GET_IO(spAPEDecompress)->Read(&spTempBuffer[spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES)], nTagBytes, &nBytesRead))
|
||||
}
|
||||
|
||||
THROW_ON_ERROR(spAPECompress->Finish(spTempBuffer, nTerminatingBytes, spAPEDecompress->GetInfo(APE_INFO_WAV_TERMINATING_BYTES)));
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_ON_ERROR(spAPECompress->Finish(NULL, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
// fire the "complete" progress notification
|
||||
spMACProgressHelper->UpdateProgressComplete();
|
||||
}
|
||||
catch(int nErrorCode)
|
||||
{
|
||||
nFunctionRetVal = (nErrorCode == 0) ? ERROR_UNDEFINED : nErrorCode;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
nFunctionRetVal = ERROR_UNDEFINED;
|
||||
}
|
||||
|
||||
// return
|
||||
return nFunctionRetVal;
|
||||
}
|
||||
743
MAC_SDK/Source/MACLib/APETag.cpp
Normal file
743
MAC_SDK/Source/MACLib/APETag.cpp
Normal file
@@ -0,0 +1,743 @@
|
||||
#include "All.h"
|
||||
#include "ID3Genres.h"
|
||||
#include "APETag.h"
|
||||
#include "CharacterHelper.h"
|
||||
#include "IO.h"
|
||||
#include IO_HEADER_FILE
|
||||
|
||||
/*****************************************************************************************
|
||||
CAPETagField
|
||||
*****************************************************************************************/
|
||||
|
||||
CAPETagField::CAPETagField(const str_utf16 * pFieldName, const void * pFieldValue, int nFieldBytes, int nFlags)
|
||||
{
|
||||
// field name
|
||||
m_spFieldNameUTF16.Assign(new str_utf16 [wcslen(pFieldName) + 1], TRUE);
|
||||
memcpy(m_spFieldNameUTF16, pFieldName, (wcslen(pFieldName) + 1) * sizeof(str_utf16));
|
||||
|
||||
// data (we'll always allocate two extra bytes and memset to 0 so we're safely NULL terminated)
|
||||
m_nFieldValueBytes = max(nFieldBytes, 0);
|
||||
m_spFieldValue.Assign(new char [m_nFieldValueBytes + 2], TRUE);
|
||||
memset(m_spFieldValue, 0, m_nFieldValueBytes + 2);
|
||||
if (m_nFieldValueBytes > 0)
|
||||
memcpy(m_spFieldValue, pFieldValue, m_nFieldValueBytes);
|
||||
|
||||
// flags
|
||||
m_nFieldFlags = nFlags;
|
||||
}
|
||||
|
||||
CAPETagField::~CAPETagField()
|
||||
{
|
||||
}
|
||||
|
||||
int CAPETagField::GetFieldSize()
|
||||
{
|
||||
CSmartPtr<char> spFieldNameANSI(GetANSIFromUTF16(m_spFieldNameUTF16), TRUE);
|
||||
return (strlen(spFieldNameANSI) + 1) + m_nFieldValueBytes + 4 + 4;
|
||||
}
|
||||
|
||||
const str_utf16 * CAPETagField::GetFieldName()
|
||||
{
|
||||
return m_spFieldNameUTF16;
|
||||
}
|
||||
|
||||
const char * CAPETagField::GetFieldValue()
|
||||
{
|
||||
return m_spFieldValue;
|
||||
}
|
||||
|
||||
int CAPETagField::GetFieldValueSize()
|
||||
{
|
||||
return m_nFieldValueBytes;
|
||||
}
|
||||
|
||||
int CAPETagField::GetFieldFlags()
|
||||
{
|
||||
return m_nFieldFlags;
|
||||
}
|
||||
|
||||
int CAPETagField::SaveField(char * pBuffer)
|
||||
{
|
||||
*((int *) pBuffer) = m_nFieldValueBytes;
|
||||
pBuffer += 4;
|
||||
*((int *) pBuffer) = m_nFieldFlags;
|
||||
pBuffer += 4;
|
||||
|
||||
CSmartPtr<char> spFieldNameANSI((char *) GetANSIFromUTF16(m_spFieldNameUTF16), TRUE);
|
||||
strcpy(pBuffer, spFieldNameANSI);
|
||||
pBuffer += strlen(spFieldNameANSI) + 1;
|
||||
|
||||
memcpy(pBuffer, m_spFieldValue, m_nFieldValueBytes);
|
||||
|
||||
return GetFieldSize();
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************
|
||||
CAPETag
|
||||
*****************************************************************************************/
|
||||
|
||||
CAPETag::CAPETag(const str_utf16 * pFilename, BOOL bAnalyze)
|
||||
{
|
||||
m_spIO.Assign(new IO_CLASS_NAME);
|
||||
m_spIO->Open(pFilename);
|
||||
|
||||
m_bAnalyzed = FALSE;
|
||||
m_nFields = 0;
|
||||
m_nTagBytes = 0;
|
||||
m_bIgnoreReadOnly = FALSE;
|
||||
|
||||
if (bAnalyze)
|
||||
{
|
||||
Analyze();
|
||||
}
|
||||
}
|
||||
|
||||
CAPETag::CAPETag(CIO * pIO, BOOL bAnalyze)
|
||||
{
|
||||
m_spIO.Assign(pIO, FALSE, FALSE); // we don't own the IO source
|
||||
m_bAnalyzed = FALSE;
|
||||
m_nFields = 0;
|
||||
m_nTagBytes = 0;
|
||||
|
||||
if (bAnalyze)
|
||||
{
|
||||
Analyze();
|
||||
}
|
||||
}
|
||||
|
||||
CAPETag::~CAPETag()
|
||||
{
|
||||
ClearFields();
|
||||
}
|
||||
|
||||
int CAPETag::GetTagBytes()
|
||||
{
|
||||
if (m_bAnalyzed == FALSE) { Analyze(); }
|
||||
|
||||
return m_nTagBytes;
|
||||
}
|
||||
|
||||
CAPETagField * CAPETag::GetTagField(int nIndex)
|
||||
{
|
||||
if (m_bAnalyzed == FALSE) { Analyze(); }
|
||||
|
||||
if ((nIndex >= 0) && (nIndex < m_nFields))
|
||||
{
|
||||
return m_aryFields[nIndex];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CAPETag::Save(BOOL bUseOldID3)
|
||||
{
|
||||
if (Remove(FALSE) != ERROR_SUCCESS)
|
||||
return -1;
|
||||
|
||||
if (m_nFields == 0) { return ERROR_SUCCESS; }
|
||||
|
||||
int nRetVal = -1;
|
||||
|
||||
if (bUseOldID3 == FALSE)
|
||||
{
|
||||
int z = 0;
|
||||
|
||||
// calculate the size of the whole tag
|
||||
int nFieldBytes = 0;
|
||||
for (z = 0; z < m_nFields; z++)
|
||||
nFieldBytes += m_aryFields[z]->GetFieldSize();
|
||||
|
||||
// sort the fields
|
||||
SortFields();
|
||||
|
||||
// build the footer
|
||||
APE_TAG_FOOTER APETagFooter(m_nFields, nFieldBytes);
|
||||
|
||||
// make a buffer for the tag
|
||||
int nTotalTagBytes = APETagFooter.GetTotalTagBytes();
|
||||
CSmartPtr<char> spRawTag(new char [nTotalTagBytes], TRUE);
|
||||
|
||||
// save the fields
|
||||
int nLocation = 0;
|
||||
for (z = 0; z < m_nFields; z++)
|
||||
nLocation += m_aryFields[z]->SaveField(&spRawTag[nLocation]);
|
||||
|
||||
// add the footer to the buffer
|
||||
memcpy(&spRawTag[nLocation], &APETagFooter, APE_TAG_FOOTER_BYTES);
|
||||
nLocation += APE_TAG_FOOTER_BYTES;
|
||||
|
||||
// dump the tag to the I/O source
|
||||
nRetVal = WriteBufferToEndOfIO(spRawTag, nTotalTagBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// build the ID3 tag
|
||||
ID3_TAG ID3Tag;
|
||||
CreateID3Tag(&ID3Tag);
|
||||
nRetVal = WriteBufferToEndOfIO(&ID3Tag, sizeof(ID3_TAG));
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int CAPETag::WriteBufferToEndOfIO(void * pBuffer, int nBytes)
|
||||
{
|
||||
int nOriginalPosition = m_spIO->GetPosition();
|
||||
|
||||
unsigned int nBytesWritten = 0;
|
||||
m_spIO->Seek(0, FILE_END);
|
||||
|
||||
int nRetVal = m_spIO->Write(pBuffer, nBytes, &nBytesWritten);
|
||||
|
||||
m_spIO->Seek(nOriginalPosition, FILE_BEGIN);
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int CAPETag::Analyze()
|
||||
{
|
||||
// clean-up
|
||||
ID3_TAG ID3Tag;
|
||||
ClearFields();
|
||||
m_nTagBytes = 0;
|
||||
|
||||
m_bAnalyzed = TRUE;
|
||||
|
||||
// store the original location
|
||||
int nOriginalPosition = m_spIO->GetPosition();
|
||||
|
||||
// check for a tag
|
||||
unsigned int nBytesRead;
|
||||
int nRetVal;
|
||||
m_bHasID3Tag = FALSE;
|
||||
m_bHasAPETag = FALSE;
|
||||
m_nAPETagVersion = -1;
|
||||
m_spIO->Seek(-ID3_TAG_BYTES, FILE_END);
|
||||
nRetVal = m_spIO->Read((unsigned char *) &ID3Tag, sizeof(ID3_TAG), &nBytesRead);
|
||||
|
||||
if ((nBytesRead == sizeof(ID3_TAG)) && (nRetVal == 0))
|
||||
{
|
||||
if (ID3Tag.Header[0] == 'T' && ID3Tag.Header[1] == 'A' && ID3Tag.Header[2] == 'G')
|
||||
{
|
||||
m_bHasID3Tag = TRUE;
|
||||
m_nTagBytes += ID3_TAG_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
// set the fields
|
||||
if (m_bHasID3Tag)
|
||||
{
|
||||
SetFieldID3String(APE_TAG_FIELD_ARTIST, ID3Tag.Artist, 30);
|
||||
SetFieldID3String(APE_TAG_FIELD_ALBUM, ID3Tag.Album, 30);
|
||||
SetFieldID3String(APE_TAG_FIELD_TITLE, ID3Tag.Title, 30);
|
||||
SetFieldID3String(APE_TAG_FIELD_COMMENT, ID3Tag.Comment, 28);
|
||||
SetFieldID3String(APE_TAG_FIELD_YEAR, ID3Tag.Year, 4);
|
||||
|
||||
char cTemp[16]; sprintf(cTemp, "%d", ID3Tag.Track);
|
||||
SetFieldString(APE_TAG_FIELD_TRACK, cTemp, FALSE);
|
||||
|
||||
if ((ID3Tag.Genre == GENRE_UNDEFINED) || (ID3Tag.Genre >= GENRE_COUNT))
|
||||
SetFieldString(APE_TAG_FIELD_GENRE, APE_TAG_GENRE_UNDEFINED);
|
||||
else
|
||||
SetFieldString(APE_TAG_FIELD_GENRE, g_ID3Genre[ID3Tag.Genre]);
|
||||
}
|
||||
|
||||
// try loading the APE tag
|
||||
if (m_bHasID3Tag == FALSE)
|
||||
{
|
||||
APE_TAG_FOOTER APETagFooter;
|
||||
m_spIO->Seek(-int(APE_TAG_FOOTER_BYTES), FILE_END);
|
||||
nRetVal = m_spIO->Read((unsigned char *) &APETagFooter, APE_TAG_FOOTER_BYTES, &nBytesRead);
|
||||
if ((nBytesRead == APE_TAG_FOOTER_BYTES) && (nRetVal == 0))
|
||||
{
|
||||
if (APETagFooter.GetIsValid(FALSE))
|
||||
{
|
||||
m_bHasAPETag = TRUE;
|
||||
m_nAPETagVersion = APETagFooter.GetVersion();
|
||||
|
||||
int nRawFieldBytes = APETagFooter.GetFieldBytes();
|
||||
m_nTagBytes += APETagFooter.GetTotalTagBytes();
|
||||
|
||||
CSmartPtr<char> spRawTag(new char [nRawFieldBytes], TRUE);
|
||||
m_spIO->Seek(-(APETagFooter.GetTotalTagBytes() - APETagFooter.GetFieldsOffset()), FILE_END);
|
||||
nRetVal = m_spIO->Read((unsigned char *) spRawTag.GetPtr(), nRawFieldBytes, &nBytesRead);
|
||||
|
||||
if ((nRetVal == 0) && (nRawFieldBytes == int(nBytesRead)))
|
||||
{
|
||||
// parse out the raw fields
|
||||
int nLocation = 0;
|
||||
for (int z = 0; z < APETagFooter.GetNumberFields(); z++)
|
||||
{
|
||||
int nMaximumFieldBytes = nRawFieldBytes - nLocation;
|
||||
|
||||
int nBytes = 0;
|
||||
if (LoadField(&spRawTag[nLocation], nMaximumFieldBytes, &nBytes) != ERROR_SUCCESS)
|
||||
{
|
||||
// if LoadField(...) fails, it means that the tag is corrupt (accidently or intentionally)
|
||||
// we'll just bail out -- leaving the fields we've already set
|
||||
break;
|
||||
}
|
||||
nLocation += nBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restore the file pointer
|
||||
m_spIO->Seek(nOriginalPosition, FILE_BEGIN);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPETag::ClearFields()
|
||||
{
|
||||
for (int z = 0; z < m_nFields; z++)
|
||||
{
|
||||
SAFE_DELETE(m_aryFields[z])
|
||||
}
|
||||
|
||||
m_nFields = 0;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPETag::GetTagFieldIndex(const str_utf16 * pFieldName)
|
||||
{
|
||||
if (m_bAnalyzed == FALSE) { Analyze(); }
|
||||
if (pFieldName == NULL) return -1;
|
||||
|
||||
for (int z = 0; z < m_nFields; z++)
|
||||
{
|
||||
if (wcsicmp(m_aryFields[z]->GetFieldName(), pFieldName) == 0)
|
||||
return z;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
CAPETagField * CAPETag::GetTagField(const str_utf16 * pFieldName)
|
||||
{
|
||||
int nIndex = GetTagFieldIndex(pFieldName);
|
||||
return (nIndex != -1) ? m_aryFields[nIndex] : NULL;
|
||||
}
|
||||
|
||||
int CAPETag::GetFieldString(const str_utf16 * pFieldName, str_ansi * pBuffer, int * pBufferCharacters, BOOL bUTF8Encode)
|
||||
{
|
||||
int nOriginalCharacters = *pBufferCharacters;
|
||||
str_utf16 * pUTF16 = new str_utf16 [*pBufferCharacters + 1];
|
||||
pUTF16[0] = 0;
|
||||
|
||||
int nRetVal = GetFieldString(pFieldName, pUTF16, pBufferCharacters);
|
||||
if (nRetVal == ERROR_SUCCESS)
|
||||
{
|
||||
CSmartPtr<str_ansi> spANSI(bUTF8Encode ? (str_ansi *) GetUTF8FromUTF16(pUTF16) : GetANSIFromUTF16(pUTF16), TRUE);
|
||||
if (int(strlen(spANSI)) > nOriginalCharacters)
|
||||
{
|
||||
memset(pBuffer, 0, nOriginalCharacters * sizeof(str_ansi));
|
||||
*pBufferCharacters = 0;
|
||||
nRetVal = ERROR_UNDEFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(pBuffer, spANSI);
|
||||
*pBufferCharacters = strlen(spANSI);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] pUTF16;
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
|
||||
int CAPETag::GetFieldString(const str_utf16 * pFieldName, str_utf16 * pBuffer, int * pBufferCharacters)
|
||||
{
|
||||
if (m_bAnalyzed == FALSE) { Analyze(); }
|
||||
|
||||
int nRetVal = ERROR_UNDEFINED;
|
||||
|
||||
if (*pBufferCharacters > 0)
|
||||
{
|
||||
CAPETagField * pAPETagField = GetTagField(pFieldName);
|
||||
if (pAPETagField == NULL)
|
||||
{
|
||||
// the field doesn't exist -- return an empty string
|
||||
memset(pBuffer, 0, *pBufferCharacters * sizeof(str_utf16));
|
||||
*pBufferCharacters = 0;
|
||||
}
|
||||
else if (pAPETagField->GetIsUTF8Text() || (m_nAPETagVersion < 2000))
|
||||
{
|
||||
// get the value in UTF-16 format
|
||||
CSmartPtr<str_utf16> spUTF16;
|
||||
if (m_nAPETagVersion >= 2000)
|
||||
spUTF16.Assign(GetUTF16FromUTF8((str_utf8 *) pAPETagField->GetFieldValue()), TRUE);
|
||||
else
|
||||
spUTF16.Assign(GetUTF16FromANSI(pAPETagField->GetFieldValue()), TRUE);
|
||||
|
||||
// get the number of characters
|
||||
int nCharacters = (wcslen(spUTF16) + 1);
|
||||
if (nCharacters > *pBufferCharacters)
|
||||
{
|
||||
// we'll fail here, because it's not clear what would get returned (null termination, size, etc.)
|
||||
// and we really don't want to cause buffer overruns on the client side
|
||||
*pBufferCharacters = nCharacters;
|
||||
}
|
||||
else
|
||||
{
|
||||
// just copy in
|
||||
*pBufferCharacters = nCharacters;
|
||||
memcpy(pBuffer, spUTF16.GetPtr(), *pBufferCharacters * sizeof(str_utf16));
|
||||
nRetVal = ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// memset the whole buffer to NULL (so everything left over is NULL terminated)
|
||||
memset(pBuffer, 0, *pBufferCharacters * sizeof(str_utf16));
|
||||
|
||||
// do a binary dump (need to convert from wchar's to bytes)
|
||||
int nBufferBytes = (*pBufferCharacters - 1) * sizeof(str_utf16);
|
||||
nRetVal = GetFieldBinary(pFieldName, pBuffer, &nBufferBytes);
|
||||
*pBufferCharacters = (nBufferBytes / sizeof(str_utf16)) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int CAPETag::GetFieldBinary(const str_utf16 * pFieldName, void * pBuffer, int * pBufferBytes)
|
||||
{
|
||||
if (m_bAnalyzed == FALSE) { Analyze(); }
|
||||
|
||||
int nRetVal = ERROR_UNDEFINED;
|
||||
|
||||
if (*pBufferBytes > 0)
|
||||
{
|
||||
CAPETagField * pAPETagField = GetTagField(pFieldName);
|
||||
if (pAPETagField == NULL)
|
||||
{
|
||||
memset(pBuffer, 0, *pBufferBytes);
|
||||
*pBufferBytes = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pAPETagField->GetFieldValueSize() > *pBufferBytes)
|
||||
{
|
||||
// we'll fail here, because partial data may be worse than no data
|
||||
memset(pBuffer, 0, *pBufferBytes);
|
||||
*pBufferBytes = pAPETagField->GetFieldValueSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
// memcpy
|
||||
*pBufferBytes = pAPETagField->GetFieldValueSize();
|
||||
memcpy(pBuffer, pAPETagField->GetFieldValue(), *pBufferBytes);
|
||||
nRetVal = ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int CAPETag::CreateID3Tag(ID3_TAG * pID3Tag)
|
||||
{
|
||||
// error check
|
||||
if (pID3Tag == NULL) { return -1; }
|
||||
if (m_bAnalyzed == FALSE) { Analyze(); }
|
||||
if (m_nFields == 0) { return -1; }
|
||||
|
||||
// empty
|
||||
ZeroMemory(pID3Tag, ID3_TAG_BYTES);
|
||||
|
||||
// header
|
||||
pID3Tag->Header[0] = 'T'; pID3Tag->Header[1] = 'A'; pID3Tag->Header[2] = 'G';
|
||||
|
||||
// standard fields
|
||||
GetFieldID3String(APE_TAG_FIELD_ARTIST, pID3Tag->Artist, 30);
|
||||
GetFieldID3String(APE_TAG_FIELD_ALBUM, pID3Tag->Album, 30);
|
||||
GetFieldID3String(APE_TAG_FIELD_TITLE, pID3Tag->Title, 30);
|
||||
GetFieldID3String(APE_TAG_FIELD_COMMENT, pID3Tag->Comment, 28);
|
||||
GetFieldID3String(APE_TAG_FIELD_YEAR, pID3Tag->Year, 4);
|
||||
|
||||
// track number
|
||||
str_utf16 cBuffer[256] = { 0 }; int nBufferCharacters = 255;
|
||||
GetFieldString(APE_TAG_FIELD_TRACK, cBuffer, &nBufferCharacters);
|
||||
pID3Tag->Track = (unsigned char) _wtoi(cBuffer);
|
||||
|
||||
// genre
|
||||
cBuffer[0] = 0; nBufferCharacters = 255;
|
||||
GetFieldString(APE_TAG_FIELD_GENRE, cBuffer, &nBufferCharacters);
|
||||
|
||||
// convert the genre string to an index
|
||||
pID3Tag->Genre = 255;
|
||||
int nGenreIndex = 0;
|
||||
BOOL bFound = FALSE;
|
||||
while ((nGenreIndex < GENRE_COUNT) && (bFound == FALSE))
|
||||
{
|
||||
if (_wcsicmp(cBuffer, g_ID3Genre[nGenreIndex]) == 0)
|
||||
{
|
||||
pID3Tag->Genre = nGenreIndex;
|
||||
bFound = TRUE;
|
||||
}
|
||||
|
||||
nGenreIndex++;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPETag::LoadField(const char * pBuffer, int nMaximumBytes, int * pBytes)
|
||||
{
|
||||
// set bytes to 0
|
||||
if (pBytes) *pBytes = 0;
|
||||
|
||||
// size and flags
|
||||
int nLocation = 0;
|
||||
int nFieldValueSize = *((int *) &pBuffer[nLocation]);
|
||||
nLocation += 4;
|
||||
int nFieldFlags = *((int *) &pBuffer[nLocation]);
|
||||
nLocation += 4;
|
||||
|
||||
// safety check (so we can't get buffer overflow attacked)
|
||||
int nMaximumRead = nMaximumBytes - 8 - nFieldValueSize;
|
||||
BOOL bSafe = TRUE;
|
||||
for (int z = 0; (z < nMaximumRead) && (bSafe == TRUE); z++)
|
||||
{
|
||||
int nCharacter = pBuffer[nLocation + z];
|
||||
if (nCharacter == 0)
|
||||
break;
|
||||
if ((nCharacter < 0x20) || (nCharacter > 0x7E))
|
||||
bSafe = FALSE;
|
||||
}
|
||||
if (bSafe == FALSE)
|
||||
return -1;
|
||||
|
||||
// name
|
||||
int nNameCharacters = strlen(&pBuffer[nLocation]);
|
||||
CSmartPtr<str_utf8> spNameUTF8(new str_utf8 [nNameCharacters + 1], TRUE);
|
||||
memcpy(spNameUTF8, &pBuffer[nLocation], (nNameCharacters + 1) * sizeof(str_utf8));
|
||||
nLocation += nNameCharacters + 1;
|
||||
CSmartPtr<str_utf16> spNameUTF16(GetUTF16FromUTF8(spNameUTF8.GetPtr()), TRUE);
|
||||
|
||||
// value
|
||||
CSmartPtr<char> spFieldBuffer(new char [nFieldValueSize], TRUE);
|
||||
memcpy(spFieldBuffer, &pBuffer[nLocation], nFieldValueSize);
|
||||
nLocation += nFieldValueSize;
|
||||
|
||||
// update the bytes
|
||||
if (pBytes) *pBytes = nLocation;
|
||||
|
||||
// set
|
||||
return SetFieldBinary(spNameUTF16.GetPtr(), spFieldBuffer, nFieldValueSize, nFieldFlags);
|
||||
}
|
||||
|
||||
int CAPETag::SetFieldString(const str_utf16 * pFieldName, const str_utf16 * pFieldValue)
|
||||
{
|
||||
// remove if empty
|
||||
if ((pFieldValue == NULL) || (wcslen(pFieldValue) <= 0))
|
||||
return RemoveField(pFieldName);
|
||||
|
||||
// UTF-8 encode the value and call the UTF-8 SetField(...)
|
||||
CSmartPtr<str_utf8> spFieldValueUTF8(GetUTF8FromUTF16((str_utf16 *) pFieldValue), TRUE);
|
||||
return SetFieldString(pFieldName, (const char *) spFieldValueUTF8.GetPtr(), TRUE);
|
||||
}
|
||||
|
||||
int CAPETag::SetFieldString(const str_utf16 * pFieldName, const char * pFieldValue, BOOL bAlreadyUTF8Encoded)
|
||||
{
|
||||
// remove if empty
|
||||
if ((pFieldValue == NULL) || (strlen(pFieldValue) <= 0))
|
||||
return RemoveField(pFieldName);
|
||||
|
||||
// get the length and call the binary SetField(...)
|
||||
if (bAlreadyUTF8Encoded == FALSE)
|
||||
{
|
||||
CSmartPtr<char> spUTF8((char *) GetUTF8FromANSI(pFieldValue), TRUE);
|
||||
int nFieldBytes = strlen(spUTF8.GetPtr());
|
||||
return SetFieldBinary(pFieldName, spUTF8.GetPtr(), nFieldBytes, TAG_FIELD_FLAG_DATA_TYPE_TEXT_UTF8);
|
||||
}
|
||||
else
|
||||
{
|
||||
int nFieldBytes = strlen(pFieldValue);
|
||||
return SetFieldBinary(pFieldName, pFieldValue, nFieldBytes, TAG_FIELD_FLAG_DATA_TYPE_TEXT_UTF8);
|
||||
}
|
||||
}
|
||||
|
||||
int CAPETag::SetFieldBinary(const str_utf16 * pFieldName, const void * pFieldValue, int nFieldBytes, int nFieldFlags)
|
||||
{
|
||||
if (m_bAnalyzed == FALSE) { Analyze(); }
|
||||
if (pFieldName == NULL) return -1;
|
||||
|
||||
// check to see if we're trying to remove the field (by setting it to NULL or an empty string)
|
||||
BOOL bRemoving = (pFieldValue == NULL) || (nFieldBytes <= 0);
|
||||
|
||||
// get the index
|
||||
int nFieldIndex = GetTagFieldIndex(pFieldName);
|
||||
if (nFieldIndex != -1)
|
||||
{
|
||||
// existing field
|
||||
|
||||
// fail if we're read-only (and not ignoring the read-only flag)
|
||||
if ((m_bIgnoreReadOnly == FALSE) && (m_aryFields[nFieldIndex]->GetIsReadOnly()))
|
||||
return -1;
|
||||
|
||||
// erase the existing field
|
||||
SAFE_DELETE(m_aryFields[nFieldIndex])
|
||||
|
||||
if (bRemoving)
|
||||
{
|
||||
return RemoveField(nFieldIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bRemoving)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
nFieldIndex = m_nFields;
|
||||
m_nFields++;
|
||||
}
|
||||
|
||||
// create the field and add it to the field array
|
||||
m_aryFields[nFieldIndex] = new CAPETagField(pFieldName, pFieldValue, nFieldBytes, nFieldFlags);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPETag::RemoveField(int nIndex)
|
||||
{
|
||||
if ((nIndex >= 0) && (nIndex < m_nFields))
|
||||
{
|
||||
SAFE_DELETE(m_aryFields[nIndex])
|
||||
memmove(&m_aryFields[nIndex], &m_aryFields[nIndex + 1], (256 - nIndex - 1) * sizeof(CAPETagField *));
|
||||
m_nFields--;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CAPETag::RemoveField(const str_utf16 * pFieldName)
|
||||
{
|
||||
return RemoveField(GetTagFieldIndex(pFieldName));
|
||||
}
|
||||
|
||||
int CAPETag::Remove(BOOL bUpdate)
|
||||
{
|
||||
// variables
|
||||
unsigned int nBytesRead = 0;
|
||||
int nRetVal = 0;
|
||||
int nOriginalPosition = m_spIO->GetPosition();
|
||||
|
||||
BOOL bID3Removed = TRUE;
|
||||
BOOL bAPETagRemoved = TRUE;
|
||||
|
||||
BOOL bFailedToRemove = FALSE;
|
||||
|
||||
while (bID3Removed || bAPETagRemoved)
|
||||
{
|
||||
bID3Removed = FALSE;
|
||||
bAPETagRemoved = FALSE;
|
||||
|
||||
// ID3 tag
|
||||
if (m_spIO->GetSize() > ID3_TAG_BYTES)
|
||||
{
|
||||
char cTagHeader[3];
|
||||
m_spIO->Seek(-ID3_TAG_BYTES, FILE_END);
|
||||
nRetVal = m_spIO->Read(cTagHeader, 3, &nBytesRead);
|
||||
if ((nRetVal == 0) && (nBytesRead == 3))
|
||||
{
|
||||
if (strncmp(cTagHeader, "TAG", 3) == 0)
|
||||
{
|
||||
m_spIO->Seek(-ID3_TAG_BYTES, FILE_END);
|
||||
if (m_spIO->SetEOF() != 0)
|
||||
bFailedToRemove = TRUE;
|
||||
else
|
||||
bID3Removed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// APE Tag
|
||||
if (m_spIO->GetSize() > APE_TAG_FOOTER_BYTES && bFailedToRemove == FALSE)
|
||||
{
|
||||
APE_TAG_FOOTER APETagFooter;
|
||||
m_spIO->Seek(-int(APE_TAG_FOOTER_BYTES), FILE_END);
|
||||
nRetVal = m_spIO->Read(&APETagFooter, APE_TAG_FOOTER_BYTES, &nBytesRead);
|
||||
if ((nRetVal == 0) && (nBytesRead == APE_TAG_FOOTER_BYTES))
|
||||
{
|
||||
if (APETagFooter.GetIsValid(TRUE))
|
||||
{
|
||||
m_spIO->Seek(-APETagFooter.GetTotalTagBytes(), FILE_END);
|
||||
|
||||
if (m_spIO->SetEOF() != 0)
|
||||
bFailedToRemove = TRUE;
|
||||
else
|
||||
bAPETagRemoved = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_spIO->Seek(nOriginalPosition, FILE_BEGIN);
|
||||
|
||||
if (bUpdate && bFailedToRemove == FALSE)
|
||||
{
|
||||
Analyze();
|
||||
}
|
||||
|
||||
return bFailedToRemove ? -1 : 0;
|
||||
}
|
||||
|
||||
int CAPETag::SetFieldID3String(const str_utf16 * pFieldName, const char * pFieldValue, int nBytes)
|
||||
{
|
||||
// allocate a buffer and terminate it
|
||||
CSmartPtr<str_ansi> spBuffer(new str_ansi [nBytes + 1], TRUE);
|
||||
spBuffer[nBytes] = 0;
|
||||
|
||||
// make a capped copy of the string
|
||||
memcpy(spBuffer.GetPtr(), pFieldValue, nBytes);
|
||||
|
||||
// remove trailing white-space
|
||||
char * pEnd = &spBuffer[nBytes];
|
||||
while (((*pEnd == ' ') || (*pEnd == 0)) && pEnd >= &spBuffer[0]) { *pEnd-- = 0; }
|
||||
|
||||
// set the field
|
||||
SetFieldString(pFieldName, spBuffer, FALSE);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPETag::GetFieldID3String(const str_utf16 * pFieldName, char * pBuffer, int nBytes)
|
||||
{
|
||||
int nBufferCharacters = 255; str_utf16 cBuffer[256] = {0};
|
||||
GetFieldString(pFieldName, cBuffer, &nBufferCharacters);
|
||||
|
||||
CSmartPtr<str_ansi> spBufferANSI(GetANSIFromUTF16(cBuffer), TRUE);
|
||||
|
||||
memset(pBuffer, 0, nBytes);
|
||||
strncpy(pBuffer, spBufferANSI.GetPtr(), nBytes);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPETag::SortFields()
|
||||
{
|
||||
// sort the tag fields by size (so that the smallest fields are at the front of the tag)
|
||||
qsort(m_aryFields, m_nFields, sizeof(CAPETagField *), CompareFields);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPETag::CompareFields(const void * pA, const void * pB)
|
||||
{
|
||||
CAPETagField * pFieldA = *((CAPETagField **) pA);
|
||||
CAPETagField * pFieldB = *((CAPETagField **) pB);
|
||||
|
||||
return (pFieldA->GetFieldSize() - pFieldB->GetFieldSize());
|
||||
}
|
||||
293
MAC_SDK/Source/MACLib/APETag.h
Normal file
293
MAC_SDK/Source/MACLib/APETag.h
Normal file
@@ -0,0 +1,293 @@
|
||||
#ifndef APE_APETAG_H
|
||||
#define APE_APETAG_H
|
||||
|
||||
class CIO;
|
||||
|
||||
/*****************************************************************************************
|
||||
APETag version history / supported formats
|
||||
|
||||
1.0 (1000) - Original APE tag spec. Fully supported by this code.
|
||||
2.0 (2000) - Refined APE tag spec (better streaming support, UTF encoding). Fully supported by this code.
|
||||
|
||||
Notes:
|
||||
- also supports reading of ID3v1.1 tags
|
||||
- all saving done in the APE Tag format using CURRENT_APE_TAG_VERSION
|
||||
*****************************************************************************************/
|
||||
|
||||
/*****************************************************************************************
|
||||
APETag layout
|
||||
|
||||
1) Header - APE_TAG_FOOTER (optional) (32 bytes)
|
||||
2) Fields (array):
|
||||
Value Size (4 bytes)
|
||||
Flags (4 bytes)
|
||||
Field Name (? ANSI bytes -- requires NULL terminator -- in range of 0x20 (space) to 0x7E (tilde))
|
||||
Value ([Value Size] bytes)
|
||||
3) Footer - APE_TAG_FOOTER (32 bytes)
|
||||
*****************************************************************************************/
|
||||
|
||||
/*****************************************************************************************
|
||||
Notes
|
||||
|
||||
-When saving images, store the filename (no directory -- i.e. Cover.jpg) in UTF-8 followed
|
||||
by a null terminator, followed by the image data.
|
||||
*****************************************************************************************/
|
||||
|
||||
/*****************************************************************************************
|
||||
The version of the APE tag
|
||||
*****************************************************************************************/
|
||||
#define CURRENT_APE_TAG_VERSION 2000
|
||||
|
||||
/*****************************************************************************************
|
||||
"Standard" APE tag fields
|
||||
*****************************************************************************************/
|
||||
#define APE_TAG_FIELD_TITLE L"Title"
|
||||
#define APE_TAG_FIELD_ARTIST L"Artist"
|
||||
#define APE_TAG_FIELD_ALBUM L"Album"
|
||||
#define APE_TAG_FIELD_COMMENT L"Comment"
|
||||
#define APE_TAG_FIELD_YEAR L"Year"
|
||||
#define APE_TAG_FIELD_TRACK L"Track"
|
||||
#define APE_TAG_FIELD_GENRE L"Genre"
|
||||
#define APE_TAG_FIELD_COVER_ART_FRONT L"Cover Art (front)"
|
||||
#define APE_TAG_FIELD_NOTES L"Notes"
|
||||
#define APE_TAG_FIELD_LYRICS L"Lyrics"
|
||||
#define APE_TAG_FIELD_COPYRIGHT L"Copyright"
|
||||
#define APE_TAG_FIELD_BUY_URL L"Buy URL"
|
||||
#define APE_TAG_FIELD_ARTIST_URL L"Artist URL"
|
||||
#define APE_TAG_FIELD_PUBLISHER_URL L"Publisher URL"
|
||||
#define APE_TAG_FIELD_FILE_URL L"File URL"
|
||||
#define APE_TAG_FIELD_COPYRIGHT_URL L"Copyright URL"
|
||||
#define APE_TAG_FIELD_MJ_METADATA L"Media Jukebox Metadata"
|
||||
#define APE_TAG_FIELD_TOOL_NAME L"Tool Name"
|
||||
#define APE_TAG_FIELD_TOOL_VERSION L"Tool Version"
|
||||
#define APE_TAG_FIELD_PEAK_LEVEL L"Peak Level"
|
||||
#define APE_TAG_FIELD_REPLAY_GAIN_RADIO L"Replay Gain (radio)"
|
||||
#define APE_TAG_FIELD_REPLAY_GAIN_ALBUM L"Replay Gain (album)"
|
||||
#define APE_TAG_FIELD_COMPOSER L"Composer"
|
||||
#define APE_TAG_FIELD_KEYWORDS L"Keywords"
|
||||
|
||||
/*****************************************************************************************
|
||||
Standard APE tag field values
|
||||
*****************************************************************************************/
|
||||
#define APE_TAG_GENRE_UNDEFINED L"Undefined"
|
||||
|
||||
/*****************************************************************************************
|
||||
ID3 v1.1 tag
|
||||
*****************************************************************************************/
|
||||
#define ID3_TAG_BYTES 128
|
||||
struct ID3_TAG
|
||||
{
|
||||
char Header[3]; // should equal 'TAG'
|
||||
char Title[30]; // title
|
||||
char Artist[30]; // artist
|
||||
char Album[30]; // album
|
||||
char Year[4]; // year
|
||||
char Comment[29]; // comment
|
||||
unsigned char Track; // track
|
||||
unsigned char Genre; // genre
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
Footer (and header) flags
|
||||
*****************************************************************************************/
|
||||
#define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31)
|
||||
#define APE_TAG_FLAG_CONTAINS_FOOTER (1 << 30)
|
||||
#define APE_TAG_FLAG_IS_HEADER (1 << 29)
|
||||
|
||||
#define APE_TAG_FLAGS_DEFAULT (APE_TAG_FLAG_CONTAINS_FOOTER)
|
||||
|
||||
/*****************************************************************************************
|
||||
Tag field flags
|
||||
*****************************************************************************************/
|
||||
#define TAG_FIELD_FLAG_READ_ONLY (1 << 0)
|
||||
|
||||
#define TAG_FIELD_FLAG_DATA_TYPE_MASK (6)
|
||||
#define TAG_FIELD_FLAG_DATA_TYPE_TEXT_UTF8 (0 << 1)
|
||||
#define TAG_FIELD_FLAG_DATA_TYPE_BINARY (1 << 1)
|
||||
#define TAG_FIELD_FLAG_DATA_TYPE_EXTERNAL_INFO (2 << 1)
|
||||
#define TAG_FIELD_FLAG_DATA_TYPE_RESERVED (3 << 1)
|
||||
|
||||
/*****************************************************************************************
|
||||
The footer at the end of APE tagged files (can also optionally be at the front of the tag)
|
||||
*****************************************************************************************/
|
||||
#define APE_TAG_FOOTER_BYTES 32
|
||||
|
||||
class APE_TAG_FOOTER
|
||||
{
|
||||
protected:
|
||||
|
||||
char m_cID[8]; // should equal 'APETAGEX'
|
||||
int m_nVersion; // equals CURRENT_APE_TAG_VERSION
|
||||
int m_nSize; // the complete size of the tag, including this footer (excludes header)
|
||||
int m_nFields; // the number of fields in the tag
|
||||
int m_nFlags; // the tag flags
|
||||
char m_cReserved[8]; // reserved for later use (must be zero)
|
||||
|
||||
public:
|
||||
|
||||
APE_TAG_FOOTER(int nFields = 0, int nFieldBytes = 0)
|
||||
{
|
||||
memcpy(m_cID, "APETAGEX", 8);
|
||||
memset(m_cReserved, 0, 8);
|
||||
m_nFields = nFields;
|
||||
m_nFlags = APE_TAG_FLAGS_DEFAULT;
|
||||
m_nSize = nFieldBytes + APE_TAG_FOOTER_BYTES;
|
||||
m_nVersion = CURRENT_APE_TAG_VERSION;
|
||||
}
|
||||
|
||||
int GetTotalTagBytes() { return m_nSize + (GetHasHeader() ? APE_TAG_FOOTER_BYTES : 0); }
|
||||
int GetFieldBytes() { return m_nSize - APE_TAG_FOOTER_BYTES; }
|
||||
int GetFieldsOffset() { return GetHasHeader() ? APE_TAG_FOOTER_BYTES : 0; }
|
||||
int GetNumberFields() { return m_nFields; }
|
||||
BOOL GetHasHeader() { return (m_nFlags & APE_TAG_FLAG_CONTAINS_HEADER) ? TRUE : FALSE; }
|
||||
BOOL GetIsHeader() { return (m_nFlags & APE_TAG_FLAG_IS_HEADER) ? TRUE : FALSE; }
|
||||
int GetVersion() { return m_nVersion; }
|
||||
|
||||
BOOL GetIsValid(BOOL bAllowHeader)
|
||||
{
|
||||
BOOL bValid = (strncmp(m_cID, "APETAGEX", 8) == 0) &&
|
||||
(m_nVersion <= CURRENT_APE_TAG_VERSION) &&
|
||||
(m_nFields <= 65536) &&
|
||||
(GetFieldBytes() <= (1024 * 1024 * 16));
|
||||
|
||||
if (bValid && (bAllowHeader == FALSE) && GetIsHeader())
|
||||
bValid = FALSE;
|
||||
|
||||
return bValid ? TRUE : FALSE;
|
||||
}
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
CAPETagField class (an APE tag is an array of these)
|
||||
*****************************************************************************************/
|
||||
class CAPETagField
|
||||
{
|
||||
public:
|
||||
|
||||
// create a tag field (use nFieldBytes = -1 for null-terminated strings)
|
||||
CAPETagField(const str_utf16 * pFieldName, const void * pFieldValue, int nFieldBytes = -1, int nFlags = 0);
|
||||
|
||||
// destructor
|
||||
~CAPETagField();
|
||||
|
||||
// gets the size of the entire field in bytes (name, value, and metadata)
|
||||
int GetFieldSize();
|
||||
|
||||
// get the name of the field
|
||||
const str_utf16 * GetFieldName();
|
||||
|
||||
// get the value of the field
|
||||
const char * GetFieldValue();
|
||||
|
||||
// get the size of the value (in bytes)
|
||||
int GetFieldValueSize();
|
||||
|
||||
// get any special flags
|
||||
int GetFieldFlags();
|
||||
|
||||
// output the entire field to a buffer (GetFieldSize() bytes)
|
||||
int SaveField(char * pBuffer);
|
||||
|
||||
// checks to see if the field is read-only
|
||||
BOOL GetIsReadOnly() { return (m_nFieldFlags & TAG_FIELD_FLAG_READ_ONLY) ? TRUE : FALSE; }
|
||||
BOOL GetIsUTF8Text() { return ((m_nFieldFlags & TAG_FIELD_FLAG_DATA_TYPE_MASK) == TAG_FIELD_FLAG_DATA_TYPE_TEXT_UTF8) ? TRUE : FALSE; }
|
||||
|
||||
// set helpers (use with EXTREME caution)
|
||||
void SetFieldFlags(int nFlags) { m_nFieldFlags = nFlags; }
|
||||
|
||||
private:
|
||||
|
||||
CSmartPtr<str_utf16> m_spFieldNameUTF16;
|
||||
CSmartPtr<char> m_spFieldValue;
|
||||
int m_nFieldFlags;
|
||||
int m_nFieldValueBytes;
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
CAPETag class
|
||||
*****************************************************************************************/
|
||||
class CAPETag
|
||||
{
|
||||
public:
|
||||
|
||||
// create an APE tag
|
||||
// bAnalyze determines whether it will analyze immediately or on the first request
|
||||
// be careful with multiple threads / file pointer movement if you don't analyze immediately
|
||||
CAPETag(CIO * pIO, BOOL bAnalyze = TRUE);
|
||||
CAPETag(const str_utf16 * pFilename, BOOL bAnalyze = TRUE);
|
||||
|
||||
// destructor
|
||||
~CAPETag();
|
||||
|
||||
// save the tag to the I/O source (bUseOldID3 forces it to save as an ID3v1.1 tag instead of an APE tag)
|
||||
int Save(BOOL bUseOldID3 = FALSE);
|
||||
|
||||
// removes any tags from the file (bUpdate determines whether is should re-analyze after removing the tag)
|
||||
int Remove(BOOL bUpdate = TRUE);
|
||||
|
||||
// sets the value of a field (use nFieldBytes = -1 for null terminated strings)
|
||||
// note: using NULL or "" for a string type will remove the field
|
||||
int SetFieldString(const str_utf16 * pFieldName, const str_utf16 * pFieldValue);
|
||||
int SetFieldString(const str_utf16 * pFieldName, const char * pFieldValue, BOOL bAlreadyUTF8Encoded);
|
||||
int SetFieldBinary(const str_utf16 * pFieldName, const void * pFieldValue, int nFieldBytes, int nFieldFlags);
|
||||
|
||||
// gets the value of a field (returns -1 and an empty buffer if the field doesn't exist)
|
||||
int GetFieldBinary(const str_utf16 * pFieldName, void * pBuffer, int * pBufferBytes);
|
||||
int GetFieldString(const str_utf16 * pFieldName, str_utf16 * pBuffer, int * pBufferCharacters);
|
||||
int GetFieldString(const str_utf16 * pFieldName, str_ansi * pBuffer, int * pBufferCharacters, BOOL bUTF8Encode = FALSE);
|
||||
|
||||
// remove a specific field
|
||||
int RemoveField(const str_utf16 * pFieldName);
|
||||
int RemoveField(int nIndex);
|
||||
|
||||
// clear all the fields
|
||||
int ClearFields();
|
||||
|
||||
// get the total tag bytes in the file from the last analyze
|
||||
// need to call Save() then Analyze() to update any changes
|
||||
int GetTagBytes();
|
||||
|
||||
// fills in an ID3_TAG using the current fields (useful for quickly converting the tag)
|
||||
int CreateID3Tag(ID3_TAG * pID3Tag);
|
||||
|
||||
// see whether the file has an ID3 or APE tag
|
||||
BOOL GetHasID3Tag() { if (m_bAnalyzed == FALSE) { Analyze(); } return m_bHasID3Tag; }
|
||||
BOOL GetHasAPETag() { if (m_bAnalyzed == FALSE) { Analyze(); } return m_bHasAPETag; }
|
||||
int GetAPETagVersion() { return GetHasAPETag() ? m_nAPETagVersion : -1; }
|
||||
|
||||
// gets a desired tag field (returns NULL if not found)
|
||||
// again, be careful, because this a pointer to the actual field in this class
|
||||
CAPETagField * GetTagField(const str_utf16 * pFieldName);
|
||||
CAPETagField * GetTagField(int nIndex);
|
||||
|
||||
// options
|
||||
void SetIgnoreReadOnly(BOOL bIgnoreReadOnly) { m_bIgnoreReadOnly = bIgnoreReadOnly; }
|
||||
|
||||
private:
|
||||
|
||||
// private functions
|
||||
int Analyze();
|
||||
int GetTagFieldIndex(const str_utf16 * pFieldName);
|
||||
int WriteBufferToEndOfIO(void * pBuffer, int nBytes);
|
||||
int LoadField(const char * pBuffer, int nMaximumBytes, int * pBytes);
|
||||
int SortFields();
|
||||
static int CompareFields(const void * pA, const void * pB);
|
||||
|
||||
// helper set / get field functions
|
||||
int SetFieldID3String(const str_utf16 * pFieldName, const char * pFieldValue, int nBytes);
|
||||
int GetFieldID3String(const str_utf16 * pFieldName, char * pBuffer, int nBytes);
|
||||
|
||||
// private data
|
||||
CSmartPtr<CIO> m_spIO;
|
||||
BOOL m_bAnalyzed;
|
||||
int m_nTagBytes;
|
||||
int m_nFields;
|
||||
CAPETagField * m_aryFields[256];
|
||||
BOOL m_bHasAPETag;
|
||||
int m_nAPETagVersion;
|
||||
BOOL m_bHasID3Tag;
|
||||
BOOL m_bIgnoreReadOnly;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_APETAG_H
|
||||
|
||||
12
MAC_SDK/Source/MACLib/Assembly/Assembly.h
Normal file
12
MAC_SDK/Source/MACLib/Assembly/Assembly.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef APE_ASSEMBLY_H
|
||||
#define APE_ASSEMBLY_H
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void Adapt(short * pM, const short * pAdapt, int nDirection, int nOrder);
|
||||
int CalculateDotProduct(const short * pA, const short * pB, int nOrder);
|
||||
BOOL GetMMXAvailable();
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_ASSEMBLY_H
|
||||
|
||||
181
MAC_SDK/Source/MACLib/Assembly/Assembly.nas
Normal file
181
MAC_SDK/Source/MACLib/Assembly/Assembly.nas
Normal file
@@ -0,0 +1,181 @@
|
||||
|
||||
%include "Tools.inc"
|
||||
|
||||
segment_code
|
||||
|
||||
;
|
||||
; void Adapt ( short* pM, const short* pAdapt, int nDirection, int nOrder )
|
||||
;
|
||||
; [esp+16] nOrder
|
||||
; [esp+12] nDirection
|
||||
; [esp+ 8] pAdapt
|
||||
; [esp+ 4] pM
|
||||
; [esp+ 0] Return Address
|
||||
|
||||
align 16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
proc Adapt
|
||||
|
||||
mov eax, [esp + 4] ; pM
|
||||
mov ecx, [esp + 8] ; pAdapt
|
||||
mov edx, [esp + 16] ; nOrder
|
||||
shr edx, 4
|
||||
|
||||
cmp dword [esp + 12], byte 0 ; nDirection
|
||||
jle short AdaptSub
|
||||
|
||||
AdaptAddLoop:
|
||||
movq mm0, [eax]
|
||||
paddw mm0, [ecx]
|
||||
movq [eax], mm0
|
||||
movq mm1, [eax + 8]
|
||||
paddw mm1, [ecx + 8]
|
||||
movq [eax + 8], mm1
|
||||
movq mm2, [eax + 16]
|
||||
paddw mm2, [ecx + 16]
|
||||
movq [eax + 16], mm2
|
||||
movq mm3, [eax + 24]
|
||||
paddw mm3, [ecx + 24]
|
||||
movq [eax + 24], mm3
|
||||
add eax, byte 32
|
||||
add ecx, byte 32
|
||||
dec edx
|
||||
jnz AdaptAddLoop
|
||||
|
||||
emms
|
||||
ret
|
||||
|
||||
align 16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
AdaptSub: je short AdaptDone
|
||||
|
||||
AdaptSubLoop:
|
||||
movq mm0, [eax]
|
||||
psubw mm0, [ecx]
|
||||
movq [eax], mm0
|
||||
movq mm1, [eax + 8]
|
||||
psubw mm1, [ecx + 8]
|
||||
movq [eax + 8], mm1
|
||||
movq mm2, [eax + 16]
|
||||
psubw mm2, [ecx + 16]
|
||||
movq [eax + 16], mm2
|
||||
movq mm3, [eax + 24]
|
||||
psubw mm3, [ecx + 24]
|
||||
movq [eax + 24], mm3
|
||||
add eax, byte 32
|
||||
add ecx, byte 32
|
||||
dec edx
|
||||
jnz AdaptSubLoop
|
||||
|
||||
emms
|
||||
AdaptDone:
|
||||
|
||||
endproc
|
||||
|
||||
;
|
||||
; int CalculateDotProduct ( const short* pA, const short* pB, int nOrder )
|
||||
;
|
||||
; [esp+12] nOrder
|
||||
; [esp+ 8] pB
|
||||
; [esp+ 4] pA
|
||||
; [esp+ 0] Return Address
|
||||
|
||||
align 16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
proc CalculateDotProduct
|
||||
|
||||
mov eax, [esp + 4] ; pA
|
||||
mov ecx, [esp + 8] ; pB
|
||||
mov edx, [esp + 12] ; nOrder
|
||||
shr edx, 4
|
||||
pxor mm7, mm7
|
||||
|
||||
loopDot: movq mm0, [eax]
|
||||
pmaddwd mm0, [ecx]
|
||||
paddd mm7, mm0
|
||||
movq mm1, [eax + 8]
|
||||
pmaddwd mm1, [ecx + 8]
|
||||
paddd mm7, mm1
|
||||
movq mm2, [eax + 16]
|
||||
pmaddwd mm2, [ecx + 16]
|
||||
paddd mm7, mm2
|
||||
movq mm3, [eax + 24]
|
||||
pmaddwd mm3, [ecx + 24]
|
||||
add eax, byte 32
|
||||
add ecx, byte 32
|
||||
paddd mm7, mm3
|
||||
dec edx
|
||||
jnz loopDot
|
||||
|
||||
movq mm6, mm7
|
||||
psrlq mm7, 32
|
||||
paddd mm6, mm7
|
||||
movd [esp + 4], mm6
|
||||
emms
|
||||
mov eax, [esp + 4]
|
||||
endproc
|
||||
|
||||
|
||||
;
|
||||
; BOOL GetMMXAvailable ( void );
|
||||
;
|
||||
|
||||
proc GetMMXAvailable
|
||||
pushad
|
||||
pushfd
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 0x200000
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
cmp eax, ecx
|
||||
jz short return ; no CPUID command, so no MMX
|
||||
|
||||
mov eax,1
|
||||
CPUID
|
||||
test edx,0x800000
|
||||
return: popad
|
||||
setnz al
|
||||
and eax, byte 1
|
||||
endproc
|
||||
|
||||
end
|
||||
BIN
MAC_SDK/Source/MACLib/Assembly/Assembly.obj
Normal file
BIN
MAC_SDK/Source/MACLib/Assembly/Assembly.obj
Normal file
Binary file not shown.
180
MAC_SDK/Source/MACLib/Assembly/Assembly64.bak
Normal file
180
MAC_SDK/Source/MACLib/Assembly/Assembly64.bak
Normal file
@@ -0,0 +1,180 @@
|
||||
|
||||
%include "Tools64.inc"
|
||||
|
||||
segment_code
|
||||
|
||||
;
|
||||
; void Adapt ( short* pM, const short* pAdapt, int nDirection, int nOrder )
|
||||
;
|
||||
; r9d nOrder
|
||||
; r8d nDirection
|
||||
; rdx pAdapt
|
||||
; rcx pM
|
||||
; [esp+ 0] Return Address
|
||||
|
||||
align 16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
proc Adapt
|
||||
|
||||
shr r9d, 4
|
||||
|
||||
cmp r8d, byte 0 ; nDirection
|
||||
jle short AdaptSub
|
||||
|
||||
AdaptAddLoop:
|
||||
movq mm0, [rcx]
|
||||
paddw mm0, [rdx]
|
||||
movq [rcx], mm0
|
||||
movq mm1, [rcx + 8]
|
||||
paddw mm1, [rdx + 8]
|
||||
movq [rcx + 8], mm1
|
||||
movq mm2, [rcx + 16]
|
||||
paddw mm2, [rdx + 16]
|
||||
movq [rcx + 16], mm2
|
||||
movq mm3, [rcx + 24]
|
||||
paddw mm3, [rdx + 24]
|
||||
movq [rcx + 24], mm3
|
||||
add rcx, byte 32
|
||||
add rdx, byte 32
|
||||
dec r9d
|
||||
jnz AdaptAddLoop
|
||||
|
||||
emms
|
||||
ret
|
||||
|
||||
align 16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
AdaptSub: je short AdaptDone
|
||||
|
||||
AdaptSubLoop:
|
||||
movq mm0, [rcx]
|
||||
psubw mm0, [rdx]
|
||||
movq [rcx], mm0
|
||||
movq mm1, [rcx + 8]
|
||||
psubw mm1, [rdx + 8]
|
||||
movq [rcx + 8], mm1
|
||||
movq mm2, [rcx + 16]
|
||||
psubw mm2, [rdx + 16]
|
||||
movq [rcx + 16], mm2
|
||||
movq mm3, [rcx + 24]
|
||||
psubw mm3, [rdx + 24]
|
||||
movq [rcx + 24], mm3
|
||||
add rcx, byte 32
|
||||
add rdx, byte 32
|
||||
dec r9d
|
||||
jnz AdaptSubLoop
|
||||
|
||||
emms
|
||||
AdaptDone:
|
||||
|
||||
endproc
|
||||
|
||||
;
|
||||
; int CalculateDotProduct ( const short* pA, const short* pB, int nOrder )
|
||||
;
|
||||
; [esp+12] nOrder
|
||||
; [esp+ 8] pB
|
||||
; [esp+ 4] pA
|
||||
; [esp+ 0] Return Address
|
||||
|
||||
align 16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
proc CalculateDotProduct
|
||||
|
||||
shr r8d, 4
|
||||
pxor mm7, mm7
|
||||
|
||||
loopDot: movq mm0, [rcx] ;pA
|
||||
pmaddwd mm0, [rdx] ;pB
|
||||
paddd mm7, mm0
|
||||
movq mm1, [rcx + 8]
|
||||
pmaddwd mm1, [rdx + 8]
|
||||
paddd mm7, mm1
|
||||
movq mm2, [rcx + 16]
|
||||
pmaddwd mm2, [rdx + 16]
|
||||
paddd mm7, mm2
|
||||
movq mm3, [rcx + 24]
|
||||
pmaddwd mm3, [rdx + 24]
|
||||
add rcx, byte 32
|
||||
add rdx, byte 32
|
||||
paddd mm7, mm3
|
||||
dec r8d
|
||||
jnz loopDot
|
||||
|
||||
movq mm6, mm7
|
||||
psrlq mm7, 32
|
||||
paddd mm6, mm7
|
||||
movd eax, mm6
|
||||
emms
|
||||
endproc
|
||||
|
||||
|
||||
;
|
||||
; BOOL GetMMXAvailable ( void );
|
||||
;
|
||||
|
||||
proc GetMMXAvailable
|
||||
push rax
|
||||
push rcx
|
||||
push rdx
|
||||
push rbx
|
||||
pushfq
|
||||
pop rax
|
||||
mov rcx, rax
|
||||
xor rax, 0x200000
|
||||
push rax
|
||||
popfq
|
||||
pushfq
|
||||
pop rax
|
||||
cmp rax, rcx
|
||||
jz short return ; no CPUID command, so no MMX
|
||||
|
||||
mov rax,1
|
||||
CPUID
|
||||
test rdx,0x800000
|
||||
return: pop rbx
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rax
|
||||
setnz al
|
||||
and eax, byte 1
|
||||
endproc
|
||||
|
||||
end
|
||||
240
MAC_SDK/Source/MACLib/Assembly/Assembly64.nas
Normal file
240
MAC_SDK/Source/MACLib/Assembly/Assembly64.nas
Normal file
@@ -0,0 +1,240 @@
|
||||
|
||||
%include "Tools64.inc"
|
||||
|
||||
segment_code
|
||||
|
||||
;
|
||||
; void Adapt ( short* pM, const short* pAdapt, int nDirection, int nOrder )
|
||||
;
|
||||
; r9d nOrder
|
||||
; r8d nDirection
|
||||
; rdx pAdapt
|
||||
; rcx pM
|
||||
; [esp+ 0] Return Address
|
||||
|
||||
align 16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
proc Adapt
|
||||
|
||||
shr r9d, 4
|
||||
|
||||
cmp r8d, byte 0 ; nDirection
|
||||
jle short AdaptSub
|
||||
|
||||
AdaptAddLoop:
|
||||
movq mm0, [rcx]
|
||||
paddw mm0, [rdx]
|
||||
movq [rcx], mm0
|
||||
movq mm1, [rcx + 8]
|
||||
paddw mm1, [rdx + 8]
|
||||
movq [rcx + 8], mm1
|
||||
movq mm2, [rcx + 16]
|
||||
paddw mm2, [rdx + 16]
|
||||
movq [rcx + 16], mm2
|
||||
movq mm3, [rcx + 24]
|
||||
paddw mm3, [rdx + 24]
|
||||
movq [rcx + 24], mm3
|
||||
add rcx, byte 32
|
||||
add rdx, byte 32
|
||||
dec r9d
|
||||
jnz AdaptAddLoop
|
||||
|
||||
emms
|
||||
ret
|
||||
|
||||
align 16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
AdaptSub: je short AdaptDone
|
||||
|
||||
AdaptSubLoop:
|
||||
movq mm0, [rcx]
|
||||
psubw mm0, [rdx]
|
||||
movq [rcx], mm0
|
||||
movq mm1, [rcx + 8]
|
||||
psubw mm1, [rdx + 8]
|
||||
movq [rcx + 8], mm1
|
||||
movq mm2, [rcx + 16]
|
||||
psubw mm2, [rdx + 16]
|
||||
movq [rcx + 16], mm2
|
||||
movq mm3, [rcx + 24]
|
||||
psubw mm3, [rdx + 24]
|
||||
movq [rcx + 24], mm3
|
||||
add rcx, byte 32
|
||||
add rdx, byte 32
|
||||
dec r9d
|
||||
jnz AdaptSubLoop
|
||||
|
||||
emms
|
||||
AdaptDone:
|
||||
|
||||
endproc
|
||||
|
||||
;
|
||||
; int CalculateDotProduct ( const short* pA, const short* pB, int nOrder )
|
||||
;
|
||||
; [esp+12] nOrder
|
||||
; [esp+ 8] pB
|
||||
; [esp+ 4] pA
|
||||
; [esp+ 0] Return Address
|
||||
|
||||
align 16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
proc CalculateDotProduct
|
||||
|
||||
shr r8d, 4
|
||||
pxor mm7, mm7
|
||||
|
||||
loopDot: movq mm0, [rcx] ;pA
|
||||
pmaddwd mm0, [rdx] ;pB
|
||||
paddd mm7, mm0
|
||||
movq mm1, [rcx + 8]
|
||||
pmaddwd mm1, [rdx + 8]
|
||||
paddd mm7, mm1
|
||||
movq mm2, [rcx + 16]
|
||||
pmaddwd mm2, [rdx + 16]
|
||||
paddd mm7, mm2
|
||||
movq mm3, [rcx + 24]
|
||||
pmaddwd mm3, [rdx + 24]
|
||||
add rcx, byte 32
|
||||
add rdx, byte 32
|
||||
paddd mm7, mm3
|
||||
dec r8d
|
||||
jnz loopDot
|
||||
|
||||
movq mm6, mm7
|
||||
psrlq mm7, 32
|
||||
paddd mm6, mm7
|
||||
movd eax, mm6
|
||||
emms
|
||||
endproc
|
||||
|
||||
;
|
||||
; int CalculateDotProduct ( const short* pA, const short* pB, int nOrder )
|
||||
;
|
||||
; [esp+12] nOrder
|
||||
; [esp+ 8] pB
|
||||
; [esp+ 4] pA
|
||||
; [esp+ 0] Return Address
|
||||
|
||||
align 16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
proc CalculateDotProductXMM
|
||||
|
||||
shr r8d, 4
|
||||
pxor xmm7, xmm7
|
||||
|
||||
loopDotXMM: movdqu xmm0, [rcx] ;pA
|
||||
pmaddwd xmm0, [rdx] ;pB
|
||||
paddd xmm7, xmm0
|
||||
movdqu xmm1, [rcx + 16]
|
||||
pmaddwd xmm1, [rdx + 16]
|
||||
; paddd xmm7, xmm1
|
||||
; movq xmm2, [rcx + 32]
|
||||
; pmaddwd xmm2, [rdx + 32]
|
||||
; paddd xmm7, mm2
|
||||
; movq xmm3, [rcx + 48]
|
||||
; pmaddwd xmm3, [rdx + 48]
|
||||
add rcx, byte 32
|
||||
add rdx, byte 32
|
||||
; paddd xmm7, xmm3
|
||||
paddd xmm7, xmm1
|
||||
dec r8d
|
||||
jnz loopDotXMM
|
||||
|
||||
movq xmm5, xmm7
|
||||
psrldq xmm5, 16
|
||||
movq xmm4, xmm5
|
||||
psrlq xmm5, 32
|
||||
movq xmm6, xmm7
|
||||
psrlq xmm7, 32
|
||||
paddd xmm6, xmm4
|
||||
paddd xmm6, xmm5
|
||||
paddd xmm6, xmm7
|
||||
movd eax, xmm6
|
||||
emms
|
||||
endproc
|
||||
|
||||
|
||||
;
|
||||
; BOOL GetMMXAvailable ( void );
|
||||
;
|
||||
|
||||
proc GetMMXAvailable
|
||||
push rax
|
||||
push rcx
|
||||
push rdx
|
||||
push rbx
|
||||
pushfq
|
||||
pop rax
|
||||
mov rcx, rax
|
||||
xor rax, 0x200000
|
||||
push rax
|
||||
popfq
|
||||
pushfq
|
||||
pop rax
|
||||
cmp rax, rcx
|
||||
jz short return ; no CPUID command, so no MMX
|
||||
|
||||
mov rax,1
|
||||
CPUID
|
||||
test rdx,0x800000
|
||||
return: pop rbx
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rax
|
||||
setnz al
|
||||
and eax, byte 1
|
||||
endproc
|
||||
|
||||
; end
|
||||
BIN
MAC_SDK/Source/MACLib/Assembly/Assembly64.obj
Normal file
BIN
MAC_SDK/Source/MACLib/Assembly/Assembly64.obj
Normal file
Binary file not shown.
117
MAC_SDK/Source/MACLib/Assembly/Tools.inc
Normal file
117
MAC_SDK/Source/MACLib/Assembly/Tools.inc
Normal file
@@ -0,0 +1,117 @@
|
||||
;
|
||||
; (C) Ururi 1999
|
||||
;
|
||||
|
||||
BITS 32
|
||||
|
||||
%ifdef WIN32
|
||||
%define _NAMING
|
||||
%define segment_code segment .text align=32 class=CODE use32
|
||||
%define segment_data segment .data align=32 class=DATA use32
|
||||
%ifdef __BORLANDC__
|
||||
%define segment_bss segment .data align=32 class=DATA use32
|
||||
%else
|
||||
%define segment_bss segment .bss align=32 class=DATA use32
|
||||
%endif
|
||||
|
||||
%elifdef AOUT
|
||||
%define _NAMING
|
||||
%define segment_code segment .text
|
||||
%define segment_data segment .data
|
||||
%define segment_bss segment .bss
|
||||
|
||||
%else
|
||||
%define segment_code segment .text align=32 class=CODE use32
|
||||
%define segment_data segment .data align=32 class=DATA use32
|
||||
%define segment_bss segment .bss align=32 class=DATA use32
|
||||
%endif
|
||||
|
||||
%define pmov movq
|
||||
%define pmovd movd
|
||||
|
||||
%define pupldq punpckldq
|
||||
%define puphdq punpckhdq
|
||||
%define puplwd punpcklwd
|
||||
%define puphwd punpckhwd
|
||||
|
||||
%imacro globaldef 1
|
||||
%ifdef _NAMING
|
||||
%define %1 _%1
|
||||
%endif
|
||||
global %1
|
||||
%endmacro
|
||||
|
||||
%imacro externdef 1
|
||||
%ifdef _NAMING
|
||||
%define %1 _%1
|
||||
%endif
|
||||
extern %1
|
||||
%endmacro
|
||||
|
||||
%imacro proc 1
|
||||
%push proc
|
||||
global _%1
|
||||
global %1
|
||||
_%1:
|
||||
%1:
|
||||
%assign %$STACK 0
|
||||
%assign %$STACKN 0
|
||||
%assign %$ARG 4
|
||||
%endmacro
|
||||
|
||||
%imacro endproc 0
|
||||
%ifnctx proc
|
||||
%error expected 'proc' before 'endproc'.
|
||||
%else
|
||||
%if %$STACK > 0
|
||||
add esp, %$STACK
|
||||
%endif
|
||||
|
||||
%if %$STACK <> (-%$STACKN)
|
||||
%error STACKLEVEL mismatch check 'local', 'alloc', 'pushd', 'popd'
|
||||
%endif
|
||||
|
||||
ret
|
||||
%pop
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%idefine sp(a) esp+%$STACK+a
|
||||
|
||||
%imacro arg 1
|
||||
%00 equ %$ARG
|
||||
%assign %$ARG %$ARG+%1
|
||||
%endmacro
|
||||
|
||||
%imacro local 1
|
||||
%assign %$STACKN %$STACKN-%1
|
||||
%00 equ %$STACKN
|
||||
%endmacro
|
||||
|
||||
%imacro alloc 0
|
||||
sub esp, (-%$STACKN)-%$STACK
|
||||
%assign %$STACK (-%$STACKN)
|
||||
%endmacro
|
||||
|
||||
%imacro pushd 1-*
|
||||
%rep %0
|
||||
push %1
|
||||
%assign %$STACK %$STACK+4
|
||||
%rotate 1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
%imacro popd 1-*
|
||||
%rep %0
|
||||
%rotate -1
|
||||
pop %1
|
||||
%assign %$STACK %$STACK-4
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
%macro algn 1
|
||||
align 16
|
||||
%rep (65536-%1) & 15
|
||||
nop
|
||||
%endrep
|
||||
%endm
|
||||
119
MAC_SDK/Source/MACLib/Assembly/Tools64.inc
Normal file
119
MAC_SDK/Source/MACLib/Assembly/Tools64.inc
Normal file
@@ -0,0 +1,119 @@
|
||||
;
|
||||
; (C) Ururi 1999
|
||||
;
|
||||
|
||||
BITS 64
|
||||
|
||||
CPU X64
|
||||
|
||||
%ifdef WIN32
|
||||
%define _NAMING
|
||||
%define segment_code segment .text align=32 class=CODE use32
|
||||
%define segment_data segment .data align=32 class=DATA use32
|
||||
%ifdef __BORLANDC__
|
||||
%define segment_bss segment .data align=32 class=DATA use32
|
||||
%else
|
||||
%define segment_bss segment .bss align=32 class=DATA use32
|
||||
%endif
|
||||
|
||||
%elifdef AOUT
|
||||
%define _NAMING
|
||||
%define segment_code segment .text
|
||||
%define segment_data segment .data
|
||||
%define segment_bss segment .bss
|
||||
|
||||
%else
|
||||
%define segment_code segment .text align=32 class=CODE use32
|
||||
%define segment_data segment .data align=32 class=DATA use32
|
||||
%define segment_bss segment .bss align=32 class=DATA use32
|
||||
%endif
|
||||
|
||||
%define pmov movq
|
||||
%define pmovd movd
|
||||
|
||||
%define pupldq punpckldq
|
||||
%define puphdq punpckhdq
|
||||
%define puplwd punpcklwd
|
||||
%define puphwd punpckhwd
|
||||
|
||||
%imacro globaldef 1
|
||||
%ifdef _NAMING
|
||||
%define %1 _%1
|
||||
%endif
|
||||
global %1
|
||||
%endmacro
|
||||
|
||||
%imacro externdef 1
|
||||
%ifdef _NAMING
|
||||
%define %1 _%1
|
||||
%endif
|
||||
extern %1
|
||||
%endmacro
|
||||
|
||||
%imacro proc 1
|
||||
%push proc
|
||||
global _%1
|
||||
global %1
|
||||
_%1:
|
||||
%1:
|
||||
%assign %$STACK 0
|
||||
%assign %$STACKN 0
|
||||
%assign %$ARG 4
|
||||
%endmacro
|
||||
|
||||
%imacro endproc 0
|
||||
%ifnctx proc
|
||||
%error expected 'proc' before 'endproc'.
|
||||
%else
|
||||
%if %$STACK > 0
|
||||
add esp, %$STACK
|
||||
%endif
|
||||
|
||||
%if %$STACK <> (-%$STACKN)
|
||||
%error STACKLEVEL mismatch check 'local', 'alloc', 'pushd', 'popd'
|
||||
%endif
|
||||
|
||||
ret
|
||||
%pop
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%idefine sp(a) esp+%$STACK+a
|
||||
|
||||
%imacro arg 1
|
||||
%00 equ %$ARG
|
||||
%assign %$ARG %$ARG+%1
|
||||
%endmacro
|
||||
|
||||
%imacro local 1
|
||||
%assign %$STACKN %$STACKN-%1
|
||||
%00 equ %$STACKN
|
||||
%endmacro
|
||||
|
||||
%imacro alloc 0
|
||||
sub esp, (-%$STACKN)-%$STACK
|
||||
%assign %$STACK (-%$STACKN)
|
||||
%endmacro
|
||||
|
||||
%imacro pushd 1-*
|
||||
%rep %0
|
||||
push %1
|
||||
%assign %$STACK %$STACK+4
|
||||
%rotate 1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
%imacro popd 1-*
|
||||
%rep %0
|
||||
%rotate -1
|
||||
pop %1
|
||||
%assign %$STACK %$STACK-4
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
%macro algn 1
|
||||
align 16
|
||||
%rep (65536-%1) & 15
|
||||
nop
|
||||
%endrep
|
||||
%endm
|
||||
41
MAC_SDK/Source/MACLib/Assembly/hhh
Normal file
41
MAC_SDK/Source/MACLib/Assembly/hhh
Normal file
@@ -0,0 +1,41 @@
|
||||
usage: nasm [-@ response file] [-o outfile] [-f format] [-l listfile]
|
||||
[options...] [--] filename
|
||||
or nasm -v for version info
|
||||
|
||||
-t assemble in SciTech TASM compatible mode
|
||||
-g generate debug information in selected format.
|
||||
-E (or -e) preprocess only (writes output to stdout by default)
|
||||
-a don't preprocess (assemble only)
|
||||
-M generate Makefile dependencies on stdout
|
||||
-MG d:o, missing files assumed generated
|
||||
|
||||
-Z<file> redirect error messages to file
|
||||
-s redirect error messages to stdout
|
||||
|
||||
-F format select a debugging format
|
||||
|
||||
-I<path> adds a pathname to the include file path
|
||||
-O<digit> optimize branch offsets (-O0 disables, default)
|
||||
-P<file> pre-includes a file
|
||||
-D<macro>[=<value>] pre-defines a macro
|
||||
-U<macro> undefines a macro
|
||||
-X<format> specifies error reporting format (gnu or vc)
|
||||
-w+foo enables warning foo (equiv. -Wfoo)
|
||||
-w-foo disable warning foo (equiv. -Wno-foo)
|
||||
Warnings:
|
||||
error treat warnings as errors (default off)
|
||||
macro-params macro calls with wrong parameter count (default on)
|
||||
macro-selfref cyclic macro references (default off)
|
||||
macro-defaults macros with more default than optional parameters (default on)
|
||||
orphan-labels labels alone on lines without trailing `:' (default on)
|
||||
number-overflow numeric constants does not fit in 64 bits (default on)
|
||||
gnu-elf-extensions using 8- or 16-bit relocation in ELF32, a GNU extension (default off)
|
||||
float-overflow floating point overflow (default on)
|
||||
float-denorm floating point denormal (default off)
|
||||
float-underflow floating point underflow (default off)
|
||||
float-toolong too many digits in floating-point number (default on)
|
||||
|
||||
response files should contain command line parameters, one per line.
|
||||
|
||||
For a list of valid output formats, use -hf.
|
||||
For a list of debug formats, use -f <form> -y.
|
||||
434
MAC_SDK/Source/MACLib/BitArray.cpp
Normal file
434
MAC_SDK/Source/MACLib/BitArray.cpp
Normal file
@@ -0,0 +1,434 @@
|
||||
/************************************************************************************
|
||||
Includes
|
||||
************************************************************************************/
|
||||
#include "All.h"
|
||||
#include "BitArray.h"
|
||||
#include "MD5.h"
|
||||
|
||||
/************************************************************************************
|
||||
Declares
|
||||
************************************************************************************/
|
||||
#define BIT_ARRAY_ELEMENTS (4096) // the number of elements in the bit array (4 MB)
|
||||
#define BIT_ARRAY_BYTES (BIT_ARRAY_ELEMENTS * 4) // the number of bytes in the bit array
|
||||
#define BIT_ARRAY_BITS (BIT_ARRAY_BYTES * 8) // the number of bits in the bit array
|
||||
|
||||
#define MAX_ELEMENT_BITS 128
|
||||
#define REFILL_BIT_THRESHOLD (BIT_ARRAY_BITS - MAX_ELEMENT_BITS)
|
||||
|
||||
#define CODE_BITS 32
|
||||
#define TOP_VALUE ((unsigned int) 1 << (CODE_BITS - 1))
|
||||
#define SHIFT_BITS (CODE_BITS - 9)
|
||||
#define EXTRA_BITS ((CODE_BITS - 2) % 8 + 1)
|
||||
#define BOTTOM_VALUE (TOP_VALUE >> 8)
|
||||
|
||||
/************************************************************************************
|
||||
Lookup tables
|
||||
************************************************************************************/
|
||||
const uint32 K_SUM_MIN_BOUNDARY[32] = {0,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,0,0,0,0};
|
||||
|
||||
#define MODEL_ELEMENTS 64
|
||||
#define RANGE_OVERFLOW_TOTAL_WIDTH 65536
|
||||
#define RANGE_OVERFLOW_SHIFT 16
|
||||
|
||||
const uint32 RANGE_TOTAL[64] = {0,19578,36160,48417,56323,60899,63265,64435,64971,65232,65351,65416,65447,65466,65476,65482,65485,65488,65490,65491,65492,65493,65494,65495,65496,65497,65498,65499,65500,65501,65502,65503,65504,65505,65506,65507,65508,65509,65510,65511,65512,65513,65514,65515,65516,65517,65518,65519,65520,65521,65522,65523,65524,65525,65526,65527,65528,65529,65530,65531,65532,65533,65534,65535,};
|
||||
const uint32 RANGE_WIDTH[64] = {19578,16582,12257,7906,4576,2366,1170,536,261,119,65,31,19,10,6,3,3,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,};
|
||||
|
||||
#ifdef BUILD_RANGE_TABLE
|
||||
int g_aryOverflows[256] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
int g_nTotalOverflow = 0;
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
Constructor
|
||||
************************************************************************************/
|
||||
CBitArray::CBitArray(CIO *pIO)
|
||||
{
|
||||
// allocate memory for the bit array
|
||||
m_pBitArray = new uint32 [BIT_ARRAY_ELEMENTS];
|
||||
memset(m_pBitArray, 0, BIT_ARRAY_BYTES);
|
||||
|
||||
// initialize other variables
|
||||
m_nCurrentBitIndex = 0;
|
||||
m_pIO = pIO;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Destructor
|
||||
************************************************************************************/
|
||||
CBitArray::~CBitArray()
|
||||
{
|
||||
// free the bit array
|
||||
SAFE_ARRAY_DELETE(m_pBitArray)
|
||||
#ifdef BUILD_RANGE_TABLE
|
||||
OutputRangeTable();
|
||||
#endif
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Output the bit array via the CIO (typically saves to disk)
|
||||
************************************************************************************/
|
||||
int CBitArray::OutputBitArray(BOOL bFinalize)
|
||||
{
|
||||
// write the entire file to disk
|
||||
unsigned int nBytesWritten = 0;
|
||||
unsigned int nBytesToWrite = 0;
|
||||
unsigned int nRetVal = 0;
|
||||
|
||||
if (bFinalize)
|
||||
{
|
||||
nBytesToWrite = ((m_nCurrentBitIndex >> 5) * 4) + 4;
|
||||
|
||||
m_MD5.AddData(m_pBitArray, nBytesToWrite);
|
||||
|
||||
RETURN_ON_ERROR(m_pIO->Write(m_pBitArray, nBytesToWrite, &nBytesWritten))
|
||||
|
||||
// reset the bit pointer
|
||||
m_nCurrentBitIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nBytesToWrite = (m_nCurrentBitIndex >> 5) * 4;
|
||||
|
||||
m_MD5.AddData(m_pBitArray, nBytesToWrite);
|
||||
|
||||
RETURN_ON_ERROR(m_pIO->Write(m_pBitArray, nBytesToWrite, &nBytesWritten))
|
||||
|
||||
// move the last value to the front of the bit array
|
||||
m_pBitArray[0] = m_pBitArray[m_nCurrentBitIndex >> 5];
|
||||
m_nCurrentBitIndex = (m_nCurrentBitIndex & 31);
|
||||
|
||||
// zero the rest of the memory (may not need the +1 because of frame byte alignment)
|
||||
memset(&m_pBitArray[1], 0, min(nBytesToWrite + 1, BIT_ARRAY_BYTES - 1));
|
||||
}
|
||||
|
||||
// return a success
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Range coding macros -- ugly, but outperform inline's (every cycle counts here)
|
||||
************************************************************************************/
|
||||
#define PUTC(VALUE) m_pBitArray[m_nCurrentBitIndex >> 5] |= ((VALUE) & 0xFF) << (24 - (m_nCurrentBitIndex & 31)); m_nCurrentBitIndex += 8;
|
||||
#define PUTC_NOCAP(VALUE) m_pBitArray[m_nCurrentBitIndex >> 5] |= (VALUE) << (24 - (m_nCurrentBitIndex & 31)); m_nCurrentBitIndex += 8;
|
||||
|
||||
#define NORMALIZE_RANGE_CODER \
|
||||
while (m_RangeCoderInfo.range <= BOTTOM_VALUE) \
|
||||
{ \
|
||||
if (m_RangeCoderInfo.low < (0xFF << SHIFT_BITS)) \
|
||||
{ \
|
||||
PUTC(m_RangeCoderInfo.buffer); \
|
||||
for ( ; m_RangeCoderInfo.help; m_RangeCoderInfo.help--) { PUTC_NOCAP(0xFF); } \
|
||||
m_RangeCoderInfo.buffer = (m_RangeCoderInfo.low >> SHIFT_BITS); \
|
||||
} \
|
||||
else if (m_RangeCoderInfo.low & TOP_VALUE) \
|
||||
{ \
|
||||
PUTC(m_RangeCoderInfo.buffer + 1); \
|
||||
m_nCurrentBitIndex += (m_RangeCoderInfo.help * 8); \
|
||||
m_RangeCoderInfo.help = 0; \
|
||||
m_RangeCoderInfo.buffer = (m_RangeCoderInfo.low >> SHIFT_BITS); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
m_RangeCoderInfo.help++; \
|
||||
} \
|
||||
\
|
||||
m_RangeCoderInfo.low = (m_RangeCoderInfo.low << 8) & (TOP_VALUE - 1); \
|
||||
m_RangeCoderInfo.range <<= 8; \
|
||||
}
|
||||
|
||||
#define ENCODE_FAST(RANGE_WIDTH, RANGE_TOTAL, SHIFT) \
|
||||
NORMALIZE_RANGE_CODER \
|
||||
const int nTemp = m_RangeCoderInfo.range >> (SHIFT); \
|
||||
m_RangeCoderInfo.range = nTemp * (RANGE_WIDTH); \
|
||||
m_RangeCoderInfo.low += nTemp * (RANGE_TOTAL);
|
||||
|
||||
#define ENCODE_DIRECT(VALUE, SHIFT) \
|
||||
NORMALIZE_RANGE_CODER \
|
||||
m_RangeCoderInfo.range = m_RangeCoderInfo.range >> (SHIFT); \
|
||||
m_RangeCoderInfo.low += m_RangeCoderInfo.range * (VALUE);
|
||||
|
||||
/************************************************************************************
|
||||
Directly encode bits to the bitstream
|
||||
************************************************************************************/
|
||||
int CBitArray::EncodeBits(unsigned int nValue, int nBits)
|
||||
{
|
||||
// make sure there is room for the data
|
||||
// this is a little slower than ensuring a huge block to start with, but it's safer
|
||||
if (m_nCurrentBitIndex > REFILL_BIT_THRESHOLD)
|
||||
{
|
||||
RETURN_ON_ERROR(OutputBitArray())
|
||||
}
|
||||
|
||||
ENCODE_DIRECT(nValue, nBits);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Encodes an unsigned int to the bit array (no rice coding)
|
||||
************************************************************************************/
|
||||
int CBitArray::EncodeUnsignedLong(unsigned int n)
|
||||
{
|
||||
// make sure there are at least 8 bytes in the buffer
|
||||
if (m_nCurrentBitIndex > (BIT_ARRAY_BYTES - 8))
|
||||
{
|
||||
RETURN_ON_ERROR(OutputBitArray())
|
||||
}
|
||||
|
||||
// encode the value
|
||||
uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5;
|
||||
int nBitIndex = m_nCurrentBitIndex & 31;
|
||||
|
||||
if (nBitIndex == 0)
|
||||
{
|
||||
m_pBitArray[nBitArrayIndex] = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pBitArray[nBitArrayIndex] |= n >> nBitIndex;
|
||||
m_pBitArray[nBitArrayIndex + 1] = n << (32 - nBitIndex);
|
||||
}
|
||||
|
||||
m_nCurrentBitIndex += 32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Advance to a byte boundary (for frame alignment)
|
||||
************************************************************************************/
|
||||
void CBitArray::AdvanceToByteBoundary()
|
||||
{
|
||||
while (m_nCurrentBitIndex % 8)
|
||||
m_nCurrentBitIndex++;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Encode a value
|
||||
************************************************************************************/
|
||||
int CBitArray::EncodeValue(int nEncode, BIT_ARRAY_STATE & BitArrayState)
|
||||
{
|
||||
// make sure there is room for the data
|
||||
// this is a little slower than ensuring a huge block to start with, but it's safer
|
||||
if (m_nCurrentBitIndex > REFILL_BIT_THRESHOLD)
|
||||
{
|
||||
RETURN_ON_ERROR(OutputBitArray())
|
||||
}
|
||||
|
||||
// convert to unsigned
|
||||
nEncode = (nEncode > 0) ? nEncode * 2 - 1 : -nEncode * 2;
|
||||
|
||||
int nOriginalKSum = BitArrayState.nKSum;
|
||||
|
||||
// get the working k
|
||||
int nTempK = (BitArrayState.k) ? BitArrayState.k - 1 : 0;
|
||||
|
||||
// update nKSum
|
||||
BitArrayState.nKSum += ((nEncode + 1) / 2) - ((BitArrayState.nKSum + 16) >> 5);
|
||||
|
||||
// update k
|
||||
if (BitArrayState.nKSum < K_SUM_MIN_BOUNDARY[BitArrayState.k])
|
||||
BitArrayState.k--;
|
||||
else if (BitArrayState.nKSum >= K_SUM_MIN_BOUNDARY[BitArrayState.k + 1])
|
||||
BitArrayState.k++;
|
||||
|
||||
// figure the pivot value
|
||||
int nPivotValue = max(nOriginalKSum / 32, 1);
|
||||
int nOverflow = nEncode / nPivotValue;
|
||||
int nBase = nEncode - (nOverflow * nPivotValue);
|
||||
|
||||
// store the overflow
|
||||
if (nOverflow < (MODEL_ELEMENTS - 1))
|
||||
{
|
||||
ENCODE_FAST(RANGE_WIDTH[nOverflow], RANGE_TOTAL[nOverflow], RANGE_OVERFLOW_SHIFT);
|
||||
|
||||
#ifdef BUILD_RANGE_TABLE
|
||||
g_aryOverflows[nOverflow]++;
|
||||
g_nTotalOverflow++;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// store the "special" overflow (tells that perfect k is encoded next)
|
||||
ENCODE_FAST(RANGE_WIDTH[MODEL_ELEMENTS - 1], RANGE_TOTAL[MODEL_ELEMENTS - 1], RANGE_OVERFLOW_SHIFT);
|
||||
|
||||
#ifdef BUILD_RANGE_TABLE
|
||||
g_aryOverflows[MODEL_ELEMENTS - 1]++;
|
||||
g_nTotalOverflow++;
|
||||
#endif
|
||||
|
||||
// code the overflow using straight bits
|
||||
ENCODE_DIRECT((nOverflow >> 16) & 0xFFFF, 16);
|
||||
ENCODE_DIRECT(nOverflow & 0xFFFF, 16);
|
||||
}
|
||||
|
||||
// code the base
|
||||
{
|
||||
if (nPivotValue >= (1 << 16))
|
||||
{
|
||||
int nPivotValueBits = 0;
|
||||
while ((nPivotValue >> nPivotValueBits) > 0) { nPivotValueBits++; }
|
||||
int nSplitFactor = 1 << (nPivotValueBits - 16);
|
||||
|
||||
// we know that base is smaller than pivot coming into this
|
||||
// however, after we divide both by an integer, they could be the same
|
||||
// we account by adding one to the pivot, but this hurts compression
|
||||
// by (1 / nSplitFactor) -- therefore we maximize the split factor
|
||||
// that gets one added to it
|
||||
|
||||
// encode the pivot as two pieces
|
||||
int nPivotValueA = (nPivotValue / nSplitFactor) + 1;
|
||||
int nPivotValueB = nSplitFactor;
|
||||
|
||||
int nBaseA = nBase / nSplitFactor;
|
||||
int nBaseB = nBase % nSplitFactor;
|
||||
|
||||
{
|
||||
NORMALIZE_RANGE_CODER
|
||||
const int nTemp = m_RangeCoderInfo.range / nPivotValueA;
|
||||
m_RangeCoderInfo.range = nTemp;
|
||||
m_RangeCoderInfo.low += nTemp * nBaseA;
|
||||
}
|
||||
|
||||
{
|
||||
NORMALIZE_RANGE_CODER
|
||||
const int nTemp = m_RangeCoderInfo.range / nPivotValueB;
|
||||
m_RangeCoderInfo.range = nTemp;
|
||||
m_RangeCoderInfo.low += nTemp * nBaseB;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
NORMALIZE_RANGE_CODER
|
||||
const int nTemp = m_RangeCoderInfo.range / nPivotValue;
|
||||
m_RangeCoderInfo.range = nTemp;
|
||||
m_RangeCoderInfo.low += nTemp * nBase;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Flush
|
||||
************************************************************************************/
|
||||
void CBitArray::FlushBitArray()
|
||||
{
|
||||
// advance to a byte boundary (for alignment)
|
||||
AdvanceToByteBoundary();
|
||||
|
||||
// the range coder
|
||||
m_RangeCoderInfo.low = 0; // full code range
|
||||
m_RangeCoderInfo.range = TOP_VALUE;
|
||||
m_RangeCoderInfo.buffer = 0;
|
||||
m_RangeCoderInfo.help = 0; // no bytes to follow
|
||||
}
|
||||
|
||||
void CBitArray::FlushState(BIT_ARRAY_STATE & BitArrayState)
|
||||
{
|
||||
// k and ksum
|
||||
BitArrayState.k = 10;
|
||||
BitArrayState.nKSum = (1 << BitArrayState.k) * 16;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Finalize
|
||||
************************************************************************************/
|
||||
void CBitArray::Finalize()
|
||||
{
|
||||
NORMALIZE_RANGE_CODER
|
||||
|
||||
unsigned int nTemp = (m_RangeCoderInfo.low >> SHIFT_BITS) + 1;
|
||||
|
||||
if (nTemp > 0xFF) // we have a carry
|
||||
{
|
||||
PUTC(m_RangeCoderInfo.buffer + 1);
|
||||
for ( ; m_RangeCoderInfo.help; m_RangeCoderInfo.help--)
|
||||
{
|
||||
PUTC(0);
|
||||
}
|
||||
}
|
||||
else // no carry
|
||||
{
|
||||
PUTC(m_RangeCoderInfo.buffer);
|
||||
for ( ; m_RangeCoderInfo.help; m_RangeCoderInfo.help--)
|
||||
{
|
||||
PUTC(((unsigned char) 0xFF));
|
||||
}
|
||||
}
|
||||
|
||||
// we must output these bytes so the decoder can properly work at the end of the stream
|
||||
PUTC(nTemp & 0xFF);
|
||||
PUTC(0);
|
||||
PUTC(0);
|
||||
PUTC(0);
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Build a range table (for development / debugging)
|
||||
************************************************************************************/
|
||||
#ifdef BUILD_RANGE_TABLE
|
||||
void CBitArray::OutputRangeTable()
|
||||
{
|
||||
int z;
|
||||
|
||||
if (g_nTotalOverflow == 0) return;
|
||||
|
||||
int nTotal = 0;
|
||||
int aryWidth[256]; ZeroMemory(aryWidth, 256 * 4);
|
||||
for (z = 0; z < MODEL_ELEMENTS; z++)
|
||||
{
|
||||
aryWidth[z] = int(((float(g_aryOverflows[z]) * float(65536)) + (g_nTotalOverflow / 2)) / float(g_nTotalOverflow));
|
||||
if (aryWidth[z] == 0) aryWidth[z] = 1;
|
||||
nTotal += aryWidth[z];
|
||||
}
|
||||
|
||||
z = 0;
|
||||
while (nTotal > 65536)
|
||||
{
|
||||
if (aryWidth[z] != 1)
|
||||
{
|
||||
aryWidth[z]--;
|
||||
nTotal--;
|
||||
}
|
||||
z++;
|
||||
if (z == MODEL_ELEMENTS) z = 0;
|
||||
}
|
||||
|
||||
z = 0;
|
||||
while (nTotal < 65536)
|
||||
{
|
||||
aryWidth[z++]++;
|
||||
nTotal++;
|
||||
if (z == MODEL_ELEMENTS) z = 0;
|
||||
}
|
||||
|
||||
int aryTotal[256]; ZeroMemory(aryTotal, 256 * 4);
|
||||
for (z = 0; z < MODEL_ELEMENTS; z++)
|
||||
{
|
||||
for (int q = 0; q < z; q++)
|
||||
{
|
||||
aryTotal[z] += aryWidth[q];
|
||||
}
|
||||
}
|
||||
|
||||
TCHAR buf[1024];
|
||||
_stprintf(buf, _T("const uint32 RANGE_TOTAL[%d] = {"), MODEL_ELEMENTS);
|
||||
ODS(buf);
|
||||
for (z = 0; z < MODEL_ELEMENTS; z++)
|
||||
{
|
||||
_stprintf(buf, _T("%d,"), aryTotal[z]);
|
||||
OutputDebugString(buf);
|
||||
}
|
||||
ODS(_T("};\n"));
|
||||
|
||||
_stprintf(buf, _T("const uint32 RANGE_WIDTH[%d] = {"), MODEL_ELEMENTS);
|
||||
ODS(buf);
|
||||
for (z = 0; z < MODEL_ELEMENTS; z++)
|
||||
{
|
||||
_stprintf(buf, _T("%d,"), aryWidth[z]);
|
||||
OutputDebugString(buf);
|
||||
}
|
||||
ODS(_T("};\n\n"));
|
||||
}
|
||||
#endif // #ifdef BUILD_RANGE_TABLE
|
||||
62
MAC_SDK/Source/MACLib/BitArray.h
Normal file
62
MAC_SDK/Source/MACLib/BitArray.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef APE_BITARRAY_H
|
||||
#define APE_BITARRAY_H
|
||||
|
||||
#include "IO.h"
|
||||
#include "MD5.h"
|
||||
|
||||
//#define BUILD_RANGE_TABLE
|
||||
|
||||
struct RANGE_CODER_STRUCT_COMPRESS
|
||||
{
|
||||
unsigned int low; // low end of interval
|
||||
unsigned int range; // length of interval
|
||||
unsigned int help; // bytes_to_follow resp. intermediate value
|
||||
unsigned char buffer; // buffer for input / output
|
||||
};
|
||||
|
||||
struct BIT_ARRAY_STATE
|
||||
{
|
||||
uint32 k;
|
||||
uint32 nKSum;
|
||||
};
|
||||
|
||||
class CBitArray
|
||||
{
|
||||
public:
|
||||
|
||||
// construction / destruction
|
||||
CBitArray(CIO *pIO);
|
||||
~CBitArray();
|
||||
|
||||
// encoding
|
||||
int EncodeUnsignedLong(unsigned int n);
|
||||
int EncodeValue(int nEncode, BIT_ARRAY_STATE & BitArrayState);
|
||||
int EncodeBits(unsigned int nValue, int nBits);
|
||||
|
||||
// output (saving)
|
||||
int OutputBitArray(BOOL bFinalize = FALSE);
|
||||
|
||||
// other functions
|
||||
void Finalize();
|
||||
void AdvanceToByteBoundary();
|
||||
inline uint32 GetCurrentBitIndex() { return m_nCurrentBitIndex; }
|
||||
void FlushState(BIT_ARRAY_STATE & BitArrayState);
|
||||
void FlushBitArray();
|
||||
inline CMD5Helper & GetMD5Helper() { return m_MD5; }
|
||||
|
||||
private:
|
||||
|
||||
// data members
|
||||
uint32 * m_pBitArray;
|
||||
CIO * m_pIO;
|
||||
uint32 m_nCurrentBitIndex;
|
||||
RANGE_CODER_STRUCT_COMPRESS m_RangeCoderInfo;
|
||||
CMD5Helper m_MD5;
|
||||
|
||||
#ifdef BUILD_RANGE_TABLE
|
||||
void OutputRangeTable();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_BITARRAY_H
|
||||
157
MAC_SDK/Source/MACLib/MACLib.cpp
Normal file
157
MAC_SDK/Source/MACLib/MACLib.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
#include "All.h"
|
||||
#include "MACLib.h"
|
||||
|
||||
#include "APECompress.h"
|
||||
#include "APECompressCreate.h"
|
||||
#include "APECompressCore.h"
|
||||
#include "APECompress.h"
|
||||
#include "APEDecompress.h"
|
||||
#include "APEInfo.h"
|
||||
#include "APELink.h"
|
||||
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
#include "Old/APEDecompressOld.h"
|
||||
#endif
|
||||
|
||||
IAPEDecompress * CreateIAPEDecompressCore(CAPEInfo * pAPEInfo, int nStartBlock, int nFinishBlock, int * pErrorCode)
|
||||
{
|
||||
IAPEDecompress * pAPEDecompress = NULL;
|
||||
if (pAPEInfo != NULL && *pErrorCode == ERROR_SUCCESS)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pAPEInfo->GetInfo(APE_INFO_FILE_VERSION) >= 3930)
|
||||
pAPEDecompress = new CAPEDecompress(pErrorCode, pAPEInfo, nStartBlock, nFinishBlock);
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
else
|
||||
pAPEDecompress = new CAPEDecompressOld(pErrorCode, pAPEInfo, nStartBlock, nFinishBlock);
|
||||
#endif
|
||||
|
||||
if (pAPEDecompress == NULL || *pErrorCode != ERROR_SUCCESS)
|
||||
{
|
||||
SAFE_DELETE(pAPEDecompress)
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
SAFE_DELETE(pAPEDecompress)
|
||||
*pErrorCode = ERROR_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
return pAPEDecompress;
|
||||
}
|
||||
|
||||
IAPEDecompress * __stdcall CreateIAPEDecompress(const str_utf16 * pFilename, int * pErrorCode)
|
||||
{
|
||||
// error check the parameters
|
||||
if ((pFilename == NULL) || (wcslen(pFilename) == 0))
|
||||
{
|
||||
if (pErrorCode) *pErrorCode = ERROR_BAD_PARAMETER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// variables
|
||||
int nErrorCode = ERROR_UNDEFINED;
|
||||
CAPEInfo * pAPEInfo = NULL;
|
||||
int nStartBlock = -1; int nFinishBlock = -1;
|
||||
|
||||
// get the extension
|
||||
const str_utf16 * pExtension = &pFilename[wcslen(pFilename)];
|
||||
while ((pExtension > pFilename) && (*pExtension != '.'))
|
||||
pExtension--;
|
||||
|
||||
// take the appropriate action (based on the extension)
|
||||
if (wcsicmp(pExtension, L".apl") == 0)
|
||||
{
|
||||
// "link" file (.apl linked large APE file)
|
||||
CAPELink APELink(pFilename);
|
||||
if (APELink.GetIsLinkFile())
|
||||
{
|
||||
pAPEInfo = new CAPEInfo(&nErrorCode, APELink.GetImageFilename(), new CAPETag(pFilename, TRUE));
|
||||
nStartBlock = APELink.GetStartBlock(); nFinishBlock = APELink.GetFinishBlock();
|
||||
}
|
||||
}
|
||||
else if ((wcsicmp(pExtension, L".mac") == 0) || (wcsicmp(pExtension, L".ape") == 0))
|
||||
{
|
||||
// plain .ape file
|
||||
pAPEInfo = new CAPEInfo(&nErrorCode, pFilename);
|
||||
}
|
||||
|
||||
// fail if we couldn't get the file information
|
||||
if (pAPEInfo == NULL)
|
||||
{
|
||||
if (pErrorCode) *pErrorCode = ERROR_INVALID_INPUT_FILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// create and return
|
||||
IAPEDecompress * pAPEDecompress = CreateIAPEDecompressCore(pAPEInfo, nStartBlock, nFinishBlock, &nErrorCode);
|
||||
if (pErrorCode) *pErrorCode = nErrorCode;
|
||||
return pAPEDecompress;
|
||||
}
|
||||
|
||||
IAPEDecompress * __stdcall CreateIAPEDecompressEx(CIO * pIO, int * pErrorCode)
|
||||
{
|
||||
int nErrorCode = ERROR_UNDEFINED;
|
||||
CAPEInfo * pAPEInfo = new CAPEInfo(&nErrorCode, pIO);
|
||||
IAPEDecompress * pAPEDecompress = CreateIAPEDecompressCore(pAPEInfo, -1, -1, &nErrorCode);
|
||||
if (pErrorCode) *pErrorCode = nErrorCode;
|
||||
return pAPEDecompress;
|
||||
}
|
||||
|
||||
|
||||
IAPEDecompress * __stdcall CreateIAPEDecompressEx2(CAPEInfo * pAPEInfo, int nStartBlock, int nFinishBlock, int * pErrorCode)
|
||||
{
|
||||
int nErrorCode = ERROR_SUCCESS;
|
||||
IAPEDecompress * pAPEDecompress = CreateIAPEDecompressCore(pAPEInfo, nStartBlock, nFinishBlock, &nErrorCode);
|
||||
if (pErrorCode) *pErrorCode = nErrorCode;
|
||||
return pAPEDecompress;
|
||||
}
|
||||
|
||||
IAPECompress * __stdcall CreateIAPECompress(int * pErrorCode)
|
||||
{
|
||||
if (pErrorCode)
|
||||
*pErrorCode = ERROR_SUCCESS;
|
||||
|
||||
return new CAPECompress();
|
||||
}
|
||||
|
||||
int __stdcall FillWaveFormatEx(WAVEFORMATEX * pWaveFormatEx, int nSampleRate, int nBitsPerSample, int nChannels)
|
||||
{
|
||||
pWaveFormatEx->cbSize = 0;
|
||||
pWaveFormatEx->nSamplesPerSec = nSampleRate;
|
||||
pWaveFormatEx->wBitsPerSample = nBitsPerSample;
|
||||
pWaveFormatEx->nChannels = nChannels;
|
||||
pWaveFormatEx->wFormatTag = 1;
|
||||
|
||||
pWaveFormatEx->nBlockAlign = (pWaveFormatEx->wBitsPerSample / 8) * pWaveFormatEx->nChannels;
|
||||
pWaveFormatEx->nAvgBytesPerSec = pWaveFormatEx->nBlockAlign * pWaveFormatEx->nSamplesPerSec;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int __stdcall FillWaveHeader(WAVE_HEADER * pWAVHeader, int nAudioBytes, WAVEFORMATEX * pWaveFormatEx, int nTerminatingBytes)
|
||||
{
|
||||
try
|
||||
{
|
||||
// RIFF header
|
||||
memcpy(pWAVHeader->cRIFFHeader, "RIFF", 4);
|
||||
pWAVHeader->nRIFFBytes = (nAudioBytes + 44) - 8 + nTerminatingBytes;
|
||||
|
||||
// format header
|
||||
memcpy(pWAVHeader->cDataTypeID, "WAVE", 4);
|
||||
memcpy(pWAVHeader->cFormatHeader, "fmt ", 4);
|
||||
|
||||
// the format chunk is the first 16 bytes of a waveformatex
|
||||
pWAVHeader->nFormatBytes = 16;
|
||||
memcpy(&pWAVHeader->nFormatTag, pWaveFormatEx, 16);
|
||||
|
||||
// the data header
|
||||
memcpy(pWAVHeader->cDataHeader, "data", 4);
|
||||
pWAVHeader->nDataBytes = nAudioBytes;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
catch(...) { return ERROR_UNDEFINED; }
|
||||
}
|
||||
462
MAC_SDK/Source/MACLib/MACLib.dsp
Normal file
462
MAC_SDK/Source/MACLib/MACLib.dsp
Normal file
@@ -0,0 +1,462 @@
|
||||
# Microsoft Developer Studio Project File - Name="MACLib" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=MACLib - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "MACLib.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "MACLib.mak" CFG="MACLib - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "MACLib - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "MACLib - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/Monkey's Audio/MACLib", SCAAAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "MACLib - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /G6 /MT /W3 /GX /Ox /Ot /Og /Oi /Ob2 /I "..\Shared" /D "WIN32" /D "NDEBUG" /D "_LIB" /D "_UNICODE" /D "UNICODE" /FR /YX"all.h" /FD /c
|
||||
# SUBTRACT CPP /Oa
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
# Begin Special Build Tool
|
||||
ProjDir=.
|
||||
SOURCE="$(InputPath)"
|
||||
PreLink_Desc=Building assembly...
|
||||
PreLink_Cmds=cd $(ProjDir)\Assembly nasmw -d WIN32 -f win32 -o Assembly.obj Assembly.nas
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "MACLib - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\Shared" /D "WIN32" /D "_DEBUG" /D "_LIB" /D "_UNICODE" /D "UNICODE" /FD /GZ /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
# Begin Special Build Tool
|
||||
ProjDir=.
|
||||
SOURCE="$(InputPath)"
|
||||
PreLink_Desc=Building assembly...
|
||||
PreLink_Cmds=cd $(ProjDir)\Assembly nasmw -d WIN32 -f win32 -o Assembly.obj Assembly.nas
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "MACLib - Win32 Release"
|
||||
# Name "MACLib - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Group "Compress"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APECompress.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APECompressCore.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APECompressCreate.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BitArray.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Decompress"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Group "Old"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=".\Old\Anti-Predictor.cpp"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\AntiPredictorExtraHigh.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\AntiPredictorFast.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\AntiPredictorHigh.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\AntiPredictorNormal.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\APEDecompressCore.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\APEDecompressOld.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\UnBitArrayOld.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\UnMAC.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APEDecompress.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\UnBitArray.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\UnBitArrayBase.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Info"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APEHeader.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APEInfo.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APELink.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APETag.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\WAVInputSource.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Tools"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Group "IO"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\StdLibFileIO.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\WinFileIO.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\CharacterHelper.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\CircleBuffer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\GlobalFunctions.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MACProgressHelper.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MD5.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Prepare.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Prediction"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Group "Filters"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\NNFilter.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\NewPredictor.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APESimple.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MACLib.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Group "Compress (h)"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APECompress.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APECompressCore.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APECompressCreate.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BitArray.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Decompress (h)"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Group "Old (h)"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=".\Old\Anti-Predictor.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\APEDecompressCore.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\APEDecompressOld.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\UnBitArrayOld.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Old\UnMAC.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APEDecompress.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\UnBitArray.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\UnBitArrayBase.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Info (h)"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APEHeader.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APEInfo.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APELink.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\APETag.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\WAVInputSource.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Tools (h)"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Group "IO (h)"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\IO.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\StdLibFileIO.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\WinFileIO.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\CharacterHelper.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\CircleBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\GlobalFunctions.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MACProgressHelper.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md5.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\NoWindows.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Prepare.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\SmartPtr.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Prediction (h)"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Group "Filters (h)"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\NNFilter.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\RollBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ScaledFirstOrderFilter.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\NewPredictor.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Predictor.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Shared\All.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Assembly\Assembly.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MACLib.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Credits.txt
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\History.txt
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\To Do.txt"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Assembly\Assembly.obj
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
450
MAC_SDK/Source/MACLib/MACLib.h
Normal file
450
MAC_SDK/Source/MACLib/MACLib.h
Normal file
@@ -0,0 +1,450 @@
|
||||
/*****************************************************************************************
|
||||
Monkey's Audio MACLib.h (include for using MACLib.lib in your projects)
|
||||
Copyright (C) 2000-2003 by Matthew T. Ashland All Rights Reserved.
|
||||
|
||||
Overview:
|
||||
|
||||
There are two main interfaces... create one (using CreateIAPExxx) and go to town:
|
||||
|
||||
IAPECompress - for creating APE files
|
||||
IAPEDecompress - for decompressing and analyzing APE files
|
||||
|
||||
Note(s):
|
||||
|
||||
Unless otherwise specified, functions return ERROR_SUCCESS (0) on success and an
|
||||
error code on failure.
|
||||
|
||||
The terminology "Sample" refers to a single sample value, and "Block" refers
|
||||
to a collection of "Channel" samples. For simplicity, MAC typically uses blocks
|
||||
everywhere so that channel mis-alignment cannot happen. (i.e. on a CD, a sample is
|
||||
2 bytes and a block is 4 bytes ([2 bytes per sample] * [2 channels] = 4 bytes))
|
||||
|
||||
Questions / Suggestions:
|
||||
|
||||
Please direct questions or comments to the Monkey's Audio developers board:
|
||||
http://www.monkeysaudio.com/cgi-bin/YaBB/YaBB.cgi -> Developers
|
||||
or, if necessary, matt @ monkeysaudio.com
|
||||
*****************************************************************************************/
|
||||
|
||||
#ifndef APE_MACLIB_H
|
||||
#define APE_MACLIB_H
|
||||
|
||||
/*************************************************************************************************
|
||||
APE File Format Overview: (pieces in order -- only valid for the latest version APE files)
|
||||
|
||||
JUNK - any amount of "junk" before the APE_DESCRIPTOR (so people that put ID3v2 tags on the files aren't hosed)
|
||||
APE_DESCRIPTOR - defines the sizes (and offsets) of all the pieces, as well as the MD5 checksum
|
||||
APE_HEADER - describes all of the necessary information about the APE file
|
||||
SEEK TABLE - the table that represents seek offsets [optional]
|
||||
HEADER DATA - the pre-audio data from the original file [optional]
|
||||
APE FRAMES - the actual compressed audio (broken into frames for seekability)
|
||||
TERMINATING DATA - the post-audio data from the original file [optional]
|
||||
TAG - describes all the properties of the file [optional]
|
||||
|
||||
Notes:
|
||||
|
||||
Junk:
|
||||
|
||||
This block may not be supported in the future, so don't write any software that adds meta data
|
||||
before the APE_DESCRIPTOR. Please use the APE Tag for any meta data.
|
||||
|
||||
Seek Table:
|
||||
|
||||
A 32-bit unsigned integer array of offsets from the header to the frame data. May become "delta"
|
||||
values someday to better suit huge files.
|
||||
|
||||
MD5 Hash:
|
||||
|
||||
Since the header is the last part written to an APE file, you must calculate the MD5 checksum out of order.
|
||||
So, you first calculate from the tail of the seek table to the end of the terminating data.
|
||||
Then, go back and do from the end of the descriptor to the tail of the seek table.
|
||||
You may wish to just cache the header data when starting and run it last, so you don't
|
||||
need to seek back in the I/O.
|
||||
*************************************************************************************************/
|
||||
|
||||
/*****************************************************************************************
|
||||
Defines
|
||||
*****************************************************************************************/
|
||||
#define COMPRESSION_LEVEL_FAST 1000
|
||||
#define COMPRESSION_LEVEL_NORMAL 2000
|
||||
#define COMPRESSION_LEVEL_HIGH 3000
|
||||
#define COMPRESSION_LEVEL_EXTRA_HIGH 4000
|
||||
#define COMPRESSION_LEVEL_INSANE 5000
|
||||
|
||||
#define MAC_FORMAT_FLAG_8_BIT 1 // is 8-bit [OBSOLETE]
|
||||
#define MAC_FORMAT_FLAG_CRC 2 // uses the new CRC32 error detection [OBSOLETE]
|
||||
#define MAC_FORMAT_FLAG_HAS_PEAK_LEVEL 4 // uint32 nPeakLevel after the header [OBSOLETE]
|
||||
#define MAC_FORMAT_FLAG_24_BIT 8 // is 24-bit [OBSOLETE]
|
||||
#define MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS 16 // has the number of seek elements after the peak level
|
||||
#define MAC_FORMAT_FLAG_CREATE_WAV_HEADER 32 // create the wave header on decompression (not stored)
|
||||
|
||||
#define CREATE_WAV_HEADER_ON_DECOMPRESSION -1
|
||||
#define MAX_AUDIO_BYTES_UNKNOWN -1
|
||||
|
||||
typedef void (__stdcall * APE_PROGRESS_CALLBACK) (int);
|
||||
|
||||
/*****************************************************************************************
|
||||
WAV header structure
|
||||
*****************************************************************************************/
|
||||
struct WAVE_HEADER
|
||||
{
|
||||
// RIFF header
|
||||
char cRIFFHeader[4];
|
||||
unsigned int nRIFFBytes;
|
||||
|
||||
// data type
|
||||
char cDataTypeID[4];
|
||||
|
||||
// wave format
|
||||
char cFormatHeader[4];
|
||||
unsigned int nFormatBytes;
|
||||
|
||||
unsigned short nFormatTag;
|
||||
unsigned short nChannels;
|
||||
unsigned int nSamplesPerSec;
|
||||
unsigned int nAvgBytesPerSec;
|
||||
unsigned short nBlockAlign;
|
||||
unsigned short nBitsPerSample;
|
||||
|
||||
// data chunk header
|
||||
char cDataHeader[4];
|
||||
unsigned int nDataBytes;
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
APE_DESCRIPTOR structure (file header that describes lengths, offsets, etc.)
|
||||
*****************************************************************************************/
|
||||
struct APE_DESCRIPTOR
|
||||
{
|
||||
char cID[4]; // should equal 'MAC '
|
||||
uint16 nVersion; // version number * 1000 (3.81 = 3810)
|
||||
|
||||
uint32 nDescriptorBytes; // the number of descriptor bytes (allows later expansion of this header)
|
||||
uint32 nHeaderBytes; // the number of header APE_HEADER bytes
|
||||
uint32 nSeekTableBytes; // the number of bytes of the seek table
|
||||
uint32 nHeaderDataBytes; // the number of header data bytes (from original file)
|
||||
uint32 nAPEFrameDataBytes; // the number of bytes of APE frame data
|
||||
uint32 nAPEFrameDataBytesHigh; // the high order number of APE frame data bytes
|
||||
uint32 nTerminatingDataBytes; // the terminating data of the file (not including tag data)
|
||||
|
||||
uint8 cFileMD5[16]; // the MD5 hash of the file (see notes for usage... it's a littly tricky)
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
APE_HEADER structure (describes the format, duration, etc. of the APE file)
|
||||
*****************************************************************************************/
|
||||
struct APE_HEADER
|
||||
{
|
||||
uint16 nCompressionLevel; // the compression level (see defines I.E. COMPRESSION_LEVEL_FAST)
|
||||
uint16 nFormatFlags; // any format flags (for future use)
|
||||
|
||||
uint32 nBlocksPerFrame; // the number of audio blocks in one frame
|
||||
uint32 nFinalFrameBlocks; // the number of audio blocks in the final frame
|
||||
uint32 nTotalFrames; // the total number of frames
|
||||
|
||||
uint16 nBitsPerSample; // the bits per sample (typically 16)
|
||||
uint16 nChannels; // the number of channels (1 or 2)
|
||||
uint32 nSampleRate; // the sample rate (typically 44100)
|
||||
};
|
||||
|
||||
/*************************************************************************************************
|
||||
Classes (fully defined elsewhere)
|
||||
*************************************************************************************************/
|
||||
class CIO;
|
||||
class CInputSource;
|
||||
class CAPEInfo;
|
||||
|
||||
/*************************************************************************************************
|
||||
IAPEDecompress fields - used when querying for information
|
||||
|
||||
Note(s):
|
||||
-the distinction between APE_INFO_XXXX and APE_DECOMPRESS_XXXX is that the first is querying the APE
|
||||
information engine, and the other is querying the decompressor, and since the decompressor can be
|
||||
a range of an APE file (for APL), differences will arise. Typically, use the APE_DECOMPRESS_XXXX
|
||||
fields when querying for info about the length, etc. so APL will work properly.
|
||||
(i.e. (APE_INFO_TOTAL_BLOCKS != APE_DECOMPRESS_TOTAL_BLOCKS) for APL files)
|
||||
*************************************************************************************************/
|
||||
enum APE_DECOMPRESS_FIELDS
|
||||
{
|
||||
APE_INFO_FILE_VERSION = 1000, // version of the APE file * 1000 (3.93 = 3930) [ignored, ignored]
|
||||
APE_INFO_COMPRESSION_LEVEL = 1001, // compression level of the APE file [ignored, ignored]
|
||||
APE_INFO_FORMAT_FLAGS = 1002, // format flags of the APE file [ignored, ignored]
|
||||
APE_INFO_SAMPLE_RATE = 1003, // sample rate (Hz) [ignored, ignored]
|
||||
APE_INFO_BITS_PER_SAMPLE = 1004, // bits per sample [ignored, ignored]
|
||||
APE_INFO_BYTES_PER_SAMPLE = 1005, // number of bytes per sample [ignored, ignored]
|
||||
APE_INFO_CHANNELS = 1006, // channels [ignored, ignored]
|
||||
APE_INFO_BLOCK_ALIGN = 1007, // block alignment [ignored, ignored]
|
||||
APE_INFO_BLOCKS_PER_FRAME = 1008, // number of blocks in a frame (frames are used internally) [ignored, ignored]
|
||||
APE_INFO_FINAL_FRAME_BLOCKS = 1009, // blocks in the final frame (frames are used internally) [ignored, ignored]
|
||||
APE_INFO_TOTAL_FRAMES = 1010, // total number frames (frames are used internally) [ignored, ignored]
|
||||
APE_INFO_WAV_HEADER_BYTES = 1011, // header bytes of the decompressed WAV [ignored, ignored]
|
||||
APE_INFO_WAV_TERMINATING_BYTES = 1012, // terminating bytes of the decompressed WAV [ignored, ignored]
|
||||
APE_INFO_WAV_DATA_BYTES = 1013, // data bytes of the decompressed WAV [ignored, ignored]
|
||||
APE_INFO_WAV_TOTAL_BYTES = 1014, // total bytes of the decompressed WAV [ignored, ignored]
|
||||
APE_INFO_APE_TOTAL_BYTES = 1015, // total bytes of the APE file [ignored, ignored]
|
||||
APE_INFO_TOTAL_BLOCKS = 1016, // total blocks of audio data [ignored, ignored]
|
||||
APE_INFO_LENGTH_MS = 1017, // length in ms (1 sec = 1000 ms) [ignored, ignored]
|
||||
APE_INFO_AVERAGE_BITRATE = 1018, // average bitrate of the APE [ignored, ignored]
|
||||
APE_INFO_FRAME_BITRATE = 1019, // bitrate of specified APE frame [frame index, ignored]
|
||||
APE_INFO_DECOMPRESSED_BITRATE = 1020, // bitrate of the decompressed WAV [ignored, ignored]
|
||||
APE_INFO_PEAK_LEVEL = 1021, // peak audio level (obsolete) (-1 is unknown) [ignored, ignored]
|
||||
APE_INFO_SEEK_BIT = 1022, // bit offset [frame index, ignored]
|
||||
APE_INFO_SEEK_BYTE = 1023, // byte offset [frame index, ignored]
|
||||
APE_INFO_WAV_HEADER_DATA = 1024, // error code [buffer *, max bytes]
|
||||
APE_INFO_WAV_TERMINATING_DATA = 1025, // error code [buffer *, max bytes]
|
||||
APE_INFO_WAVEFORMATEX = 1026, // error code [waveformatex *, ignored]
|
||||
APE_INFO_IO_SOURCE = 1027, // I/O source (CIO *) [ignored, ignored]
|
||||
APE_INFO_FRAME_BYTES = 1028, // bytes (compressed) of the frame [frame index, ignored]
|
||||
APE_INFO_FRAME_BLOCKS = 1029, // blocks in a given frame [frame index, ignored]
|
||||
APE_INFO_TAG = 1030, // point to tag (CAPETag *) [ignored, ignored]
|
||||
|
||||
APE_DECOMPRESS_CURRENT_BLOCK = 2000, // current block location [ignored, ignored]
|
||||
APE_DECOMPRESS_CURRENT_MS = 2001, // current millisecond location [ignored, ignored]
|
||||
APE_DECOMPRESS_TOTAL_BLOCKS = 2002, // total blocks in the decompressors range [ignored, ignored]
|
||||
APE_DECOMPRESS_LENGTH_MS = 2003, // total blocks in the decompressors range [ignored, ignored]
|
||||
APE_DECOMPRESS_CURRENT_BITRATE = 2004, // current bitrate [ignored, ignored]
|
||||
APE_DECOMPRESS_AVERAGE_BITRATE = 2005, // average bitrate (works with ranges) [ignored, ignored]
|
||||
|
||||
APE_INTERNAL_INFO = 3000, // for internal use -- don't use (returns APE_FILE_INFO *) [ignored, ignored]
|
||||
};
|
||||
|
||||
/*************************************************************************************************
|
||||
IAPEDecompress - interface for working with existing APE files (decoding, seeking, analyzing, etc.)
|
||||
*************************************************************************************************/
|
||||
class IAPEDecompress
|
||||
{
|
||||
public:
|
||||
|
||||
// destructor (needed so implementation's destructor will be called)
|
||||
virtual ~IAPEDecompress() {}
|
||||
|
||||
/*********************************************************************************************
|
||||
* Decompress / Seek
|
||||
*********************************************************************************************/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GetData(...) - gets raw decompressed audio
|
||||
//
|
||||
// Parameters:
|
||||
// char * pBuffer
|
||||
// a pointer to a buffer to put the data into
|
||||
// int nBlocks
|
||||
// the number of audio blocks desired (see note at intro about blocks vs. samples)
|
||||
// int * pBlocksRetrieved
|
||||
// the number of blocks actually retrieved (could be less at end of file or on critical failure)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual int GetData(char * pBuffer, int nBlocks, int * pBlocksRetrieved) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Seek(...) - seeks
|
||||
//
|
||||
// Parameters:
|
||||
// int nBlockOffset
|
||||
// the block to seek to (see note at intro about blocks vs. samples)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual int Seek(int nBlockOffset) = 0;
|
||||
|
||||
/*********************************************************************************************
|
||||
* Get Information
|
||||
*********************************************************************************************/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GetInfo(...) - get information about the APE file or the state of the decompressor
|
||||
//
|
||||
// Parameters:
|
||||
// APE_DECOMPRESS_FIELDS Field
|
||||
// the field we're querying (see APE_DECOMPRESS_FIELDS above for more info)
|
||||
// int nParam1
|
||||
// generic parameter... usage is listed in APE_DECOMPRESS_FIELDS
|
||||
// int nParam2
|
||||
// generic parameter... usage is listed in APE_DECOMPRESS_FIELDS
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual int GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1 = 0, int nParam2 = 0) = 0;
|
||||
};
|
||||
|
||||
/*************************************************************************************************
|
||||
IAPECompress - interface for creating APE files
|
||||
|
||||
Usage:
|
||||
|
||||
To create an APE file, you Start(...), then add data (in a variety of ways), then Finish(...)
|
||||
*************************************************************************************************/
|
||||
class IAPECompress
|
||||
{
|
||||
public:
|
||||
|
||||
// destructor (needed so implementation's destructor will be called)
|
||||
virtual ~IAPECompress() {}
|
||||
|
||||
/*********************************************************************************************
|
||||
* Start
|
||||
*********************************************************************************************/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Start(...) / StartEx(...) - starts encoding
|
||||
//
|
||||
// Parameters:
|
||||
// CIO * pioOutput / const str_utf16 * pFilename
|
||||
// the output... either a filename or an I/O source
|
||||
// WAVEFORMATEX * pwfeInput
|
||||
// format of the audio to encode (use FillWaveFormatEx() if necessary)
|
||||
// int nMaxAudioBytes
|
||||
// the absolute maximum audio bytes that will be encoded... encoding fails with a
|
||||
// ERROR_APE_COMPRESS_TOO_MUCH_DATA if you attempt to encode more than specified here
|
||||
// (if unknown, use MAX_AUDIO_BYTES_UNKNOWN to allocate as much storage in the seek table as
|
||||
// possible... limit is then 2 GB of data (~4 hours of CD music)... this wastes around
|
||||
// 30kb, so only do it if completely necessary)
|
||||
// int nCompressionLevel
|
||||
// the compression level for the APE file (fast - extra high)
|
||||
// (note: extra-high is much slower for little gain)
|
||||
// const void * pHeaderData
|
||||
// a pointer to a buffer containing the WAV header (data before the data block in the WAV)
|
||||
// (note: use NULL for on-the-fly encoding... see next parameter)
|
||||
// int nHeaderBytes
|
||||
// number of bytes in the header data buffer (use CREATE_WAV_HEADER_ON_DECOMPRESSION and
|
||||
// NULL for the pHeaderData and MAC will automatically create the appropriate WAV header
|
||||
// on decompression)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual int Start(const str_utf16 * pOutputFilename, const WAVEFORMATEX * pwfeInput,
|
||||
int nMaxAudioBytes = MAX_AUDIO_BYTES_UNKNOWN, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL,
|
||||
const void * pHeaderData = NULL, int nHeaderBytes = CREATE_WAV_HEADER_ON_DECOMPRESSION) = 0;
|
||||
|
||||
virtual int StartEx(CIO * pioOutput, const WAVEFORMATEX * pwfeInput,
|
||||
int nMaxAudioBytes = MAX_AUDIO_BYTES_UNKNOWN, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL,
|
||||
const void * pHeaderData = NULL, int nHeaderBytes = CREATE_WAV_HEADER_ON_DECOMPRESSION) = 0;
|
||||
|
||||
/*********************************************************************************************
|
||||
* Add / Compress Data
|
||||
* - there are 3 ways to add data:
|
||||
* 1) simple call AddData(...)
|
||||
* 2) lock MAC's buffer, copy into it, and unlock (LockBuffer(...) / UnlockBuffer(...))
|
||||
* 3) from an I/O source (AddDataFromInputSource(...))
|
||||
*********************************************************************************************/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// AddData(...) - adds data to the encoder
|
||||
//
|
||||
// Parameters:
|
||||
// unsigned char * pData
|
||||
// a pointer to a buffer containing the raw audio data
|
||||
// int nBytes
|
||||
// the number of bytes in the buffer
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual int AddData(unsigned char * pData, int nBytes) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GetBufferBytesAvailable(...) - returns the number of bytes available in the buffer
|
||||
// (helpful when locking)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual int GetBufferBytesAvailable() = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// LockBuffer(...) - locks MAC's buffer so we can copy into it
|
||||
//
|
||||
// Parameters:
|
||||
// int * pBytesAvailable
|
||||
// returns the number of bytes available in the buffer (DO NOT COPY MORE THAN THIS IN)
|
||||
//
|
||||
// Return:
|
||||
// pointer to the buffer (add at that location)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual unsigned char * LockBuffer(int * pBytesAvailable) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UnlockBuffer(...) - releases the buffer
|
||||
//
|
||||
// Parameters:
|
||||
// int nBytesAdded
|
||||
// the number of bytes copied into the buffer
|
||||
// BOOL bProcess
|
||||
// whether MAC should process as much as possible of the buffer
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual int UnlockBuffer(int nBytesAdded, BOOL bProcess = TRUE) = 0;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// AddDataFromInputSource(...) - use a CInputSource (input source) to add data
|
||||
//
|
||||
// Parameters:
|
||||
// CInputSource * pInputSource
|
||||
// a pointer to the input source
|
||||
// int nMaxBytes
|
||||
// the maximum number of bytes to let MAC add (-1 if MAC can add any amount)
|
||||
// int * pBytesAdded
|
||||
// returns the number of bytes added from the I/O source
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual int AddDataFromInputSource(CInputSource * pInputSource, int nMaxBytes = -1, int * pBytesAdded = NULL) = 0;
|
||||
|
||||
/*********************************************************************************************
|
||||
* Finish / Kill
|
||||
*********************************************************************************************/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Finish(...) - ends encoding and finalizes the file
|
||||
//
|
||||
// Parameters:
|
||||
// unsigned char * pTerminatingData
|
||||
// a pointer to a buffer containing the information to place at the end of the APE file
|
||||
// (comprised of the WAV terminating data (data after the data block in the WAV) followed
|
||||
// by any tag information)
|
||||
// int nTerminatingBytes
|
||||
// number of bytes in the terminating data buffer
|
||||
// int nWAVTerminatingBytes
|
||||
// the number of bytes of the terminating data buffer that should be appended to a decoded
|
||||
// WAV file (it's basically nTerminatingBytes - the bytes that make up the tag)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual int Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Kill(...) - stops encoding and deletes the output file
|
||||
// --- NOT CURRENTLY IMPLEMENTED ---
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual int Kill() = 0;
|
||||
};
|
||||
|
||||
/*************************************************************************************************
|
||||
Functions to create the interfaces
|
||||
|
||||
Usage:
|
||||
Interface creation returns a NULL pointer on failure (and fills error code if it was passed in)
|
||||
|
||||
Usage example:
|
||||
int nErrorCode;
|
||||
IAPEDecompress * pAPEDecompress = CreateIAPEDecompress("c:\\1.ape", &nErrorCode);
|
||||
if (pAPEDecompress == NULL)
|
||||
{
|
||||
// failure... nErrorCode will have specific code
|
||||
}
|
||||
|
||||
*************************************************************************************************/
|
||||
extern "C"
|
||||
{
|
||||
IAPEDecompress * __stdcall CreateIAPEDecompress(const str_utf16 * pFilename, int * pErrorCode = NULL);
|
||||
IAPEDecompress * __stdcall CreateIAPEDecompressEx(CIO * pIO, int * pErrorCode = NULL);
|
||||
IAPEDecompress * __stdcall CreateIAPEDecompressEx2(CAPEInfo * pAPEInfo, int nStartBlock = -1, int nFinishBlock = -1, int * pErrorCode = NULL);
|
||||
IAPECompress * __stdcall CreateIAPECompress(int * pErrorCode = NULL);
|
||||
}
|
||||
|
||||
/*************************************************************************************************
|
||||
Simple functions - see the SDK sample projects for usage examples
|
||||
*************************************************************************************************/
|
||||
extern "C"
|
||||
{
|
||||
// process whole files
|
||||
DLLEXPORT int __stdcall CompressFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, int * pPercentageDone = NULL, APE_PROGRESS_CALLBACK ProgressCallback = 0, int * pKillFlag = NULL);
|
||||
DLLEXPORT int __stdcall DecompressFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
|
||||
DLLEXPORT int __stdcall ConvertFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
|
||||
DLLEXPORT int __stdcall VerifyFile(const str_ansi * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
|
||||
|
||||
DLLEXPORT int __stdcall CompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, int * pPercentageDone = NULL, APE_PROGRESS_CALLBACK ProgressCallback = 0, int * pKillFlag = NULL);
|
||||
DLLEXPORT int __stdcall DecompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
|
||||
DLLEXPORT int __stdcall ConvertFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
|
||||
DLLEXPORT int __stdcall VerifyFileW(const str_utf16 * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag, BOOL bQuickVerifyIfPossible = FALSE);
|
||||
|
||||
// helper functions
|
||||
DLLEXPORT int __stdcall FillWaveFormatEx(WAVEFORMATEX * pWaveFormatEx, int nSampleRate = 44100, int nBitsPerSample = 16, int nChannels = 2);
|
||||
DLLEXPORT int __stdcall FillWaveHeader(WAVE_HEADER * pWAVHeader, int nAudioBytes, WAVEFORMATEX * pWaveFormatEx, int nTerminatingBytes = 0);
|
||||
}
|
||||
|
||||
#endif // #ifndef APE_MACLIB_H
|
||||
34
MAC_SDK/Source/MACLib/MACLib.sln
Normal file
34
MAC_SDK/Source/MACLib/MACLib.sln
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MACLib", "MACLib.vcproj", "{0B9C97D4-61B8-4294-A1DF-BA90752A1779}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sample 2", "..\..\Decompress\Sample 2\Sample 2.vcproj", "{E7B72EF2-1C5A-45EF-BA35-6094BCF560B1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|x64.Build.0 = Debug|x64
|
||||
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|Win32.Build.0 = Release|Win32
|
||||
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|x64.ActiveCfg = Release|x64
|
||||
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|x64.Build.0 = Release|x64
|
||||
{E7B72EF2-1C5A-45EF-BA35-6094BCF560B1}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{E7B72EF2-1C5A-45EF-BA35-6094BCF560B1}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{E7B72EF2-1C5A-45EF-BA35-6094BCF560B1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E7B72EF2-1C5A-45EF-BA35-6094BCF560B1}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{E7B72EF2-1C5A-45EF-BA35-6094BCF560B1}.Release|Win32.Build.0 = Release|Win32
|
||||
{E7B72EF2-1C5A-45EF-BA35-6094BCF560B1}.Release|x64.ActiveCfg = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
2183
MAC_SDK/Source/MACLib/MACLib.vcproj
Normal file
2183
MAC_SDK/Source/MACLib/MACLib.vcproj
Normal file
File diff suppressed because it is too large
Load Diff
1019
MAC_SDK/Source/MACLib/MACLib.vcproj.7.10.old
Normal file
1019
MAC_SDK/Source/MACLib/MACLib.vcproj.7.10.old
Normal file
File diff suppressed because it is too large
Load Diff
82
MAC_SDK/Source/MACLib/MACProgressHelper.cpp
Normal file
82
MAC_SDK/Source/MACLib/MACProgressHelper.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "All.h"
|
||||
#include "MACProgressHelper.h"
|
||||
|
||||
CMACProgressHelper::CMACProgressHelper(int nTotalSteps, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag)
|
||||
{
|
||||
m_pKillFlag = pKillFlag;
|
||||
|
||||
m_bUseCallback = FALSE;
|
||||
if (ProgressCallback != NULL)
|
||||
{
|
||||
m_bUseCallback = TRUE;
|
||||
m_CallbackFunction = ProgressCallback;
|
||||
}
|
||||
|
||||
m_pPercentageDone = pPercentageDone;
|
||||
|
||||
m_nTotalSteps = nTotalSteps;
|
||||
m_nCurrentStep = 0;
|
||||
m_nLastCallbackFiredPercentageDone = 0;
|
||||
|
||||
UpdateProgress(0);
|
||||
}
|
||||
|
||||
CMACProgressHelper::~CMACProgressHelper()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CMACProgressHelper::UpdateProgress(int nCurrentStep, BOOL bForceUpdate)
|
||||
{
|
||||
// update the step
|
||||
if (nCurrentStep == -1)
|
||||
m_nCurrentStep++;
|
||||
else
|
||||
m_nCurrentStep = nCurrentStep;
|
||||
|
||||
// figure the percentage done
|
||||
float fPercentageDone = float(m_nCurrentStep) / float(max(m_nTotalSteps, 1));
|
||||
int nPercentageDone = (int) (fPercentageDone * 1000 * 100);
|
||||
if (nPercentageDone > 100000) nPercentageDone = 100000;
|
||||
|
||||
// update the percent done pointer
|
||||
if (m_pPercentageDone)
|
||||
{
|
||||
*m_pPercentageDone = nPercentageDone;
|
||||
}
|
||||
|
||||
// fire the callback
|
||||
if (m_bUseCallback)
|
||||
{
|
||||
if (bForceUpdate || (nPercentageDone - m_nLastCallbackFiredPercentageDone) >= 1000)
|
||||
{
|
||||
m_CallbackFunction(nPercentageDone);
|
||||
m_nLastCallbackFiredPercentageDone = nPercentageDone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CMACProgressHelper::ProcessKillFlag(BOOL bSleep)
|
||||
{
|
||||
// process any messages (allows repaint, etc.)
|
||||
if (bSleep)
|
||||
{
|
||||
PUMP_MESSAGE_LOOP
|
||||
}
|
||||
|
||||
if (m_pKillFlag)
|
||||
{
|
||||
while (*m_pKillFlag == KILL_FLAG_PAUSE)
|
||||
{
|
||||
SLEEP(50);
|
||||
PUMP_MESSAGE_LOOP
|
||||
}
|
||||
|
||||
if ((*m_pKillFlag != KILL_FLAG_CONTINUE) && (*m_pKillFlag != KILL_FLAG_PAUSE))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
37
MAC_SDK/Source/MACLib/MACProgressHelper.h
Normal file
37
MAC_SDK/Source/MACLib/MACProgressHelper.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef APE_MACPROGRESSHELPER_H
|
||||
#define APE_MACPROGRESSHELPER_H
|
||||
|
||||
#define KILL_FLAG_CONTINUE 0
|
||||
#define KILL_FLAG_PAUSE -1
|
||||
#define KILL_FLAG_STOP 1
|
||||
|
||||
typedef void (__stdcall * APE_PROGRESS_CALLBACK) (int);
|
||||
|
||||
class CMACProgressHelper
|
||||
{
|
||||
public:
|
||||
|
||||
CMACProgressHelper(int nTotalSteps, int *pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int *pKillFlag);
|
||||
virtual ~CMACProgressHelper();
|
||||
|
||||
void UpdateProgress(int nCurrentStep = -1, BOOL bForceUpdate = FALSE);
|
||||
void UpdateProgressComplete() { UpdateProgress(m_nTotalSteps, TRUE); }
|
||||
|
||||
int ProcessKillFlag(BOOL bSleep = TRUE);
|
||||
|
||||
private:
|
||||
|
||||
BOOL m_bUseCallback;
|
||||
APE_PROGRESS_CALLBACK m_CallbackFunction;
|
||||
|
||||
int *m_pPercentageDone;
|
||||
|
||||
int m_nTotalSteps;
|
||||
int m_nCurrentStep;
|
||||
int m_nLastCallbackFiredPercentageDone;
|
||||
|
||||
int *m_pKillFlag;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_MACPROGRESSHELPER_H
|
||||
|
||||
264
MAC_SDK/Source/MACLib/MD5.cpp
Normal file
264
MAC_SDK/Source/MACLib/MD5.cpp
Normal file
@@ -0,0 +1,264 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm".
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "All.h"
|
||||
#include <string.h>
|
||||
#include "MD5.h"
|
||||
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
/*
|
||||
* Block copy and convert byte order to little-endian.
|
||||
* dst must be 32bit aligned.
|
||||
* Length is the number of 32bit words
|
||||
*/
|
||||
static void
|
||||
CopyToLittleEndian ( uint32_t* dst,
|
||||
const uint8_t* src,
|
||||
size_t length )
|
||||
{
|
||||
for ( ; length--; src += 4; dst++ ) {
|
||||
*dst = (( (uint32_t) src [3] ) << 24) |
|
||||
(( (uint32_t) src [2] ) << 16) |
|
||||
(( (uint32_t) src [1] ) << 8) |
|
||||
(( (uint32_t) src [0] ) << 0);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Assembler versions of __MD5Transform, MD5Init and MD5Update
|
||||
currently exist for x86 and little-endian ARM.
|
||||
For other targets, we need to use the C versions below.
|
||||
*/
|
||||
|
||||
#if !(defined (__i386__) || ((defined (__arm__) && (__BYTE_ORDER == __LITTLE_ENDIAN))))
|
||||
|
||||
/*
|
||||
Initialise the MD5 context.
|
||||
*/
|
||||
void
|
||||
MD5Init ( MD5_CTX* context )
|
||||
{
|
||||
context -> count [0] = 0;
|
||||
context -> count [1] = 0;
|
||||
|
||||
context -> state [0] = 0x67452301; /* Load magic constants. */
|
||||
context -> state [1] = 0xefcdab89;
|
||||
context -> state [2] = 0x98badcfe;
|
||||
context -> state [3] = 0x10325476;
|
||||
}
|
||||
|
||||
#define ROTATE_LEFT(x, n) ((x << n) | (x >> (32-n)))
|
||||
|
||||
#define F(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define G(x, y, z) (y ^ (z & (x ^ y)))
|
||||
#define H(x, y, z) (x ^ y ^ z)
|
||||
#define I(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
#define FF(a, b, c, d, x, s, ac) { (a) += F (b, c, d) + (x) + (uint32_t)(ac); (a) = ROTATE_LEFT (a, s); (a) += (b); }
|
||||
#define GG(a, b, c, d, x, s, ac) { (a) += G (b, c, d) + (x) + (uint32_t)(ac); (a) = ROTATE_LEFT (a, s); (a) += (b); }
|
||||
#define HH(a, b, c, d, x, s, ac) { (a) += H (b, c, d) + (x) + (uint32_t)(ac); (a) = ROTATE_LEFT (a, s); (a) += (b); }
|
||||
#define II(a, b, c, d, x, s, ac) { (a) += I (b, c, d) + (x) + (uint32_t)(ac); (a) = ROTATE_LEFT (a, s); (a) += (b); }
|
||||
|
||||
static void
|
||||
__MD5Transform ( uint32_t state [4],
|
||||
const uint8_t* in,
|
||||
int repeat )
|
||||
{
|
||||
const uint32_t* x;
|
||||
uint32_t a = state [0];
|
||||
uint32_t b = state [1];
|
||||
uint32_t c = state [2];
|
||||
uint32_t d = state [3];
|
||||
|
||||
for ( ; repeat; repeat-- ) {
|
||||
uint32_t tempBuffer [16];
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
|
||||
CopyToLittleEndian (tempBuffer, in, 16);
|
||||
x = tempBuffer;
|
||||
#else
|
||||
if ( (unsigned int)in & 3 ) {
|
||||
memcpy ( tempBuffer, in, 64 );
|
||||
x = tempBuffer;
|
||||
}
|
||||
else {
|
||||
x = (const uint32_t*) in;
|
||||
}
|
||||
#endif
|
||||
|
||||
FF (a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ /* Round 1 */
|
||||
FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
|
||||
FF (c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
|
||||
FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
|
||||
FF (a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
|
||||
FF (d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
|
||||
FF (c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
|
||||
FF (b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
|
||||
FF (a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
|
||||
FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
|
||||
FF (c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
|
||||
FF (b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
|
||||
FF (a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
|
||||
FF (d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
|
||||
FF (c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
|
||||
FF (b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
|
||||
|
||||
GG (a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ /* Round 2 */
|
||||
GG (d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
|
||||
GG (c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
|
||||
GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
|
||||
GG (a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
|
||||
GG (d, a, b, c, x[10], 9, 0x02441453); /* 22 */
|
||||
GG (c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
|
||||
GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
|
||||
GG (a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
|
||||
GG (d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
|
||||
GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
|
||||
GG (b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
|
||||
GG (a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
|
||||
GG (d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
|
||||
GG (c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
|
||||
GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
HH (a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ /* Round 3 */
|
||||
HH (d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
|
||||
HH (c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
|
||||
HH (b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
|
||||
HH (a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
|
||||
HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
|
||||
HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
|
||||
HH (b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
|
||||
HH (a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
|
||||
HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
|
||||
HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
|
||||
HH (b, c, d, a, x[ 6], 23, 0x04881d05); /* 44 */
|
||||
HH (a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
|
||||
HH (d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
|
||||
HH (c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
|
||||
HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
|
||||
|
||||
II (a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ /* Round 4 */
|
||||
II (d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
|
||||
II (c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
|
||||
II (b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
|
||||
II (a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
|
||||
II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
|
||||
II (c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
|
||||
II (b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
|
||||
II (a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
|
||||
II (d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
|
||||
II (c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
|
||||
II (b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
|
||||
II (a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
|
||||
II (d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
|
||||
II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
|
||||
II (b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
|
||||
|
||||
state [0] = a = a + state [0];
|
||||
state [1] = b = b + state [1];
|
||||
state [2] = c = c + state [2];
|
||||
state [3] = d = d + state [3];
|
||||
|
||||
in += 64;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
MD5 block update operation:
|
||||
Process another sub-string of the message and update the context.
|
||||
*/
|
||||
|
||||
void
|
||||
MD5Update ( MD5_CTX* context,
|
||||
const uint8_t* input,
|
||||
size_t inputBytes )
|
||||
{
|
||||
int byteIndex;
|
||||
unsigned int partLen;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
byteIndex = (context -> count[0] >> 3) & 0x3F;
|
||||
|
||||
/* Update number of bits: count += 8 * inputBytes */
|
||||
if ( (context -> count [0] += inputBytes << 3) < (inputBytes << 3) )
|
||||
context -> count [1]++;
|
||||
context -> count [1] += inputBytes >> (32 - 3);
|
||||
|
||||
partLen = (64 - byteIndex);
|
||||
|
||||
/* Transform as many times as possible. */
|
||||
if ( inputBytes >= partLen ) {
|
||||
memcpy ( context -> buffer + byteIndex, input, partLen );
|
||||
__MD5Transform ( context -> state, (const uint8_t*) context -> buffer, 1 );
|
||||
len = ( inputBytes - partLen ) >> 6;
|
||||
__MD5Transform ( context -> state, input + partLen, len );
|
||||
i = partLen + (len << 6);
|
||||
byteIndex = 0;
|
||||
}
|
||||
else {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
/* Buffer remaining input */
|
||||
memcpy ( (context -> buffer) + byteIndex, input + i, inputBytes - i );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
MD5Final ( uint8_t digest [16],
|
||||
MD5_CTX* context )
|
||||
{
|
||||
static uint8_t finalBlock [64];
|
||||
uint32_t bits [2];
|
||||
int byteIndex;
|
||||
int finalBlockLength;
|
||||
|
||||
byteIndex = (context -> count[0] >> 3) & 0x3F;
|
||||
finalBlockLength = (byteIndex < 56 ? 56 : 120) - byteIndex;
|
||||
finalBlock[0] = 0x80;
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
CopyToLittleEndian ( bits, (const uint8_t*) context -> count, 2 );
|
||||
#else
|
||||
memcpy ( bits, context->count, 8 );
|
||||
#endif
|
||||
|
||||
MD5Update ( context, finalBlock, finalBlockLength );
|
||||
MD5Update ( context, (const uint8_t*) bits, 8 );
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
CopyToLittleEndian ( (uint32_t*) digest, (const uint8_t*) context -> state, 4 );
|
||||
#else
|
||||
memcpy ( digest, context -> state, 16 );
|
||||
#endif
|
||||
|
||||
memset ( context, 0, sizeof (*context) );
|
||||
}
|
||||
|
||||
95
MAC_SDK/Source/MACLib/MultichannelNNFilter.h
Normal file
95
MAC_SDK/Source/MACLib/MultichannelNNFilter.h
Normal file
@@ -0,0 +1,95 @@
|
||||
#ifndef APE_MULTICHANNEL_NNFILTER_H
|
||||
#define APE_MULTICHANNEL_NNFILTER_H
|
||||
|
||||
#include "NNFilter.h"
|
||||
|
||||
class CMultichannelNNFilter
|
||||
{
|
||||
public:
|
||||
|
||||
CMultichannelNNFilter(int nOrder1, int nOrder2, int nShift)
|
||||
{
|
||||
m_pNNFilterA = new CNNFilter(nOrder1 + nOrder2, 11, 3980);
|
||||
m_pNNFilterB = new CNNFilter(nOrder1 + nOrder2, 11, 3980);
|
||||
|
||||
m_rbA.Create(NN_WINDOW_ELEMENTS, nOrder1 + nOrder2 + 1);
|
||||
m_rbB.Create(NN_WINDOW_ELEMENTS, nOrder1 + nOrder2 + 1);
|
||||
|
||||
m_nShift = nShift;
|
||||
|
||||
m_nOrder1 = nOrder1;
|
||||
}
|
||||
|
||||
|
||||
~CMultichannelNNFilter()
|
||||
{
|
||||
SAFE_DELETE(m_pNNFilterA)
|
||||
SAFE_DELETE(m_pNNFilterB)
|
||||
}
|
||||
|
||||
void Flush()
|
||||
{
|
||||
m_pNNFilterA->Flush();
|
||||
m_pNNFilterB->Flush();
|
||||
|
||||
m_rbA.Flush();
|
||||
m_rbB.Flush();
|
||||
|
||||
}
|
||||
|
||||
inline void Compress(int & nA, int & nB)
|
||||
{
|
||||
if (m_nShift <= 0)
|
||||
return;
|
||||
|
||||
m_rbA[0] = GetSaturatedShortFromInt(nA); m_rbB[0] = GetSaturatedShortFromInt(nB);
|
||||
m_rbA[-m_nOrder1 - 1] = m_rbB[-1]; m_rbB[-m_nOrder1 - 1] = m_rbA[0];
|
||||
|
||||
nA -= (m_pNNFilterA->GetPrediction(&m_rbA[-1]) >> m_nShift);
|
||||
nB -= (m_pNNFilterB->GetPrediction(&m_rbB[-1]) >> m_nShift);
|
||||
|
||||
m_pNNFilterA->AdaptAfterPrediction(&m_rbA[-1], -m_nOrder1, nA);
|
||||
m_pNNFilterB->AdaptAfterPrediction(&m_rbB[-1], -m_nOrder1, nB);
|
||||
|
||||
m_rbA.IncrementSafe(); m_rbB.IncrementSafe();
|
||||
}
|
||||
|
||||
inline void Decompress(int & nA, int & nB)
|
||||
{
|
||||
if (m_nShift <= 0)
|
||||
return;
|
||||
|
||||
m_rbA[-m_nOrder1 - 1] = m_rbB[-1];
|
||||
int nOutputA = nA + (m_pNNFilterA->GetPrediction(&m_rbA[-1]) >> m_nShift);
|
||||
m_rbA[0] = GetSaturatedShortFromInt(nOutputA);
|
||||
|
||||
m_rbB[-m_nOrder1 - 1] = m_rbA[0];
|
||||
int nOutputB = nB + (m_pNNFilterB->GetPrediction(&m_rbB[-1]) >> m_nShift);
|
||||
m_rbB[0] = GetSaturatedShortFromInt(nOutputB);
|
||||
|
||||
m_pNNFilterA->AdaptAfterPrediction(&m_rbA[-1], -m_nOrder1, nA);
|
||||
m_pNNFilterB->AdaptAfterPrediction(&m_rbB[-1], -m_nOrder1, nB);
|
||||
|
||||
m_rbA.IncrementSafe(); m_rbB.IncrementSafe();
|
||||
|
||||
nA = nOutputA; nB = nOutputB;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
CNNFilter * m_pNNFilterA;
|
||||
CNNFilter * m_pNNFilterB;
|
||||
|
||||
int m_nShift;
|
||||
int m_nOrder1;
|
||||
|
||||
CRollBuffer<short> m_rbA;
|
||||
CRollBuffer<short> m_rbB;
|
||||
|
||||
inline short GetSaturatedShortFromInt(int nValue) const
|
||||
{
|
||||
return short((nValue == short(nValue)) ? nValue : (nValue >> 31) ^ 0x7FFF);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_MULTICHANNEL_NNFILTER_H
|
||||
168
MAC_SDK/Source/MACLib/NNFilter.cpp
Normal file
168
MAC_SDK/Source/MACLib/NNFilter.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "All.h"
|
||||
#include "GlobalFunctions.h"
|
||||
#include "NNFilter.h"
|
||||
#include "Assembly/Assembly.h"
|
||||
|
||||
CNNFilter::CNNFilter(int nOrder, int nShift, int nVersion)
|
||||
{
|
||||
if ((nOrder <= 0) || ((nOrder % 16) != 0)) throw(1);
|
||||
m_nOrder = nOrder;
|
||||
m_nShift = nShift;
|
||||
m_nVersion = nVersion;
|
||||
|
||||
m_bMMXAvailable = GetMMXAvailable();
|
||||
|
||||
m_rbInput.Create(NN_WINDOW_ELEMENTS, m_nOrder);
|
||||
m_rbDeltaM.Create(NN_WINDOW_ELEMENTS, m_nOrder);
|
||||
m_paryM = new short [m_nOrder];
|
||||
|
||||
#ifdef NN_TEST_MMX
|
||||
srand(GetTickCount());
|
||||
#endif
|
||||
}
|
||||
|
||||
CNNFilter::~CNNFilter()
|
||||
{
|
||||
SAFE_ARRAY_DELETE(m_paryM)
|
||||
}
|
||||
|
||||
void CNNFilter::Flush()
|
||||
{
|
||||
memset(&m_paryM[0], 0, m_nOrder * sizeof(short));
|
||||
m_rbInput.Flush();
|
||||
m_rbDeltaM.Flush();
|
||||
m_nRunningAverage = 0;
|
||||
}
|
||||
|
||||
int CNNFilter::Compress(int nInput)
|
||||
{
|
||||
// convert the input to a short and store it
|
||||
m_rbInput[0] = GetSaturatedShortFromInt(nInput);
|
||||
|
||||
// figure a dot product
|
||||
int nDotProduct;
|
||||
if (m_bMMXAvailable)
|
||||
nDotProduct = CalculateDotProduct(&m_rbInput[-m_nOrder], &m_paryM[0], m_nOrder);
|
||||
else
|
||||
nDotProduct = CalculateDotProductNoMMX(&m_rbInput[-m_nOrder], &m_paryM[0], m_nOrder);
|
||||
|
||||
// calculate the output
|
||||
int nOutput = nInput - ((nDotProduct + (1 << (m_nShift - 1))) >> m_nShift);
|
||||
|
||||
// adapt
|
||||
if (m_bMMXAvailable)
|
||||
Adapt(&m_paryM[0], &m_rbDeltaM[-m_nOrder], -nOutput, m_nOrder);
|
||||
else
|
||||
AdaptNoMMX(&m_paryM[0], &m_rbDeltaM[-m_nOrder], nOutput, m_nOrder);
|
||||
|
||||
int nTempABS = abs(nInput);
|
||||
|
||||
if (nTempABS > (m_nRunningAverage * 3))
|
||||
m_rbDeltaM[0] = ((nInput >> 25) & 64) - 32;
|
||||
else if (nTempABS > (m_nRunningAverage * 4) / 3)
|
||||
m_rbDeltaM[0] = ((nInput >> 26) & 32) - 16;
|
||||
else if (nTempABS > 0)
|
||||
m_rbDeltaM[0] = ((nInput >> 27) & 16) - 8;
|
||||
else
|
||||
m_rbDeltaM[0] = 0;
|
||||
|
||||
m_nRunningAverage += (nTempABS - m_nRunningAverage) / 16;
|
||||
|
||||
m_rbDeltaM[-1] >>= 1;
|
||||
m_rbDeltaM[-2] >>= 1;
|
||||
m_rbDeltaM[-8] >>= 1;
|
||||
|
||||
// increment and roll if necessary
|
||||
m_rbInput.IncrementSafe();
|
||||
m_rbDeltaM.IncrementSafe();
|
||||
|
||||
return nOutput;
|
||||
}
|
||||
|
||||
int CNNFilter::Decompress(int nInput)
|
||||
{
|
||||
// figure a dot product
|
||||
int nDotProduct;
|
||||
|
||||
if (m_bMMXAvailable)
|
||||
nDotProduct = CalculateDotProduct(&m_rbInput[-m_nOrder], &m_paryM[0], m_nOrder);
|
||||
else
|
||||
nDotProduct = CalculateDotProductNoMMX(&m_rbInput[-m_nOrder], &m_paryM[0], m_nOrder);
|
||||
|
||||
// adapt
|
||||
if (m_bMMXAvailable)
|
||||
Adapt(&m_paryM[0], &m_rbDeltaM[-m_nOrder], -nInput, m_nOrder);
|
||||
else
|
||||
AdaptNoMMX(&m_paryM[0], &m_rbDeltaM[-m_nOrder], nInput, m_nOrder);
|
||||
|
||||
// store the output value
|
||||
int nOutput = nInput + ((nDotProduct + (1 << (m_nShift - 1))) >> m_nShift);
|
||||
|
||||
// update the input buffer
|
||||
m_rbInput[0] = GetSaturatedShortFromInt(nOutput);
|
||||
|
||||
if (m_nVersion >= 3980)
|
||||
{
|
||||
int nTempABS = abs(nOutput);
|
||||
|
||||
if (nTempABS > (m_nRunningAverage * 3))
|
||||
m_rbDeltaM[0] = ((nOutput >> 25) & 64) - 32;
|
||||
else if (nTempABS > (m_nRunningAverage * 4) / 3)
|
||||
m_rbDeltaM[0] = ((nOutput >> 26) & 32) - 16;
|
||||
else if (nTempABS > 0)
|
||||
m_rbDeltaM[0] = ((nOutput >> 27) & 16) - 8;
|
||||
else
|
||||
m_rbDeltaM[0] = 0;
|
||||
|
||||
m_nRunningAverage += (nTempABS - m_nRunningAverage) / 16;
|
||||
|
||||
m_rbDeltaM[-1] >>= 1;
|
||||
m_rbDeltaM[-2] >>= 1;
|
||||
m_rbDeltaM[-8] >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rbDeltaM[0] = (nOutput == 0) ? 0 : ((nOutput >> 28) & 8) - 4;
|
||||
m_rbDeltaM[-4] >>= 1;
|
||||
m_rbDeltaM[-8] >>= 1;
|
||||
}
|
||||
|
||||
// increment and roll if necessary
|
||||
m_rbInput.IncrementSafe();
|
||||
m_rbDeltaM.IncrementSafe();
|
||||
|
||||
return nOutput;
|
||||
}
|
||||
|
||||
void CNNFilter::AdaptNoMMX(short * pM, short * pAdapt, int nDirection, int nOrder)
|
||||
{
|
||||
nOrder >>= 4;
|
||||
|
||||
if (nDirection < 0)
|
||||
{
|
||||
while (nOrder--)
|
||||
{
|
||||
EXPAND_16_TIMES(*pM++ += *pAdapt++;)
|
||||
}
|
||||
}
|
||||
else if (nDirection > 0)
|
||||
{
|
||||
while (nOrder--)
|
||||
{
|
||||
EXPAND_16_TIMES(*pM++ -= *pAdapt++;)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CNNFilter::CalculateDotProductNoMMX(short * pA, short * pB, int nOrder)
|
||||
{
|
||||
int nDotProduct = 0;
|
||||
nOrder >>= 4;
|
||||
|
||||
while (nOrder--)
|
||||
{
|
||||
EXPAND_16_TIMES(nDotProduct += *pA++ * *pB++;)
|
||||
}
|
||||
|
||||
return nDotProduct;
|
||||
}
|
||||
42
MAC_SDK/Source/MACLib/NNFilter.h
Normal file
42
MAC_SDK/Source/MACLib/NNFilter.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef APE_NNFILTER_H
|
||||
#define APE_NNFILTER_H
|
||||
|
||||
#include "RollBuffer.h"
|
||||
#define NN_WINDOW_ELEMENTS 512
|
||||
//#define NN_TEST_MMX
|
||||
|
||||
class CNNFilter
|
||||
{
|
||||
public:
|
||||
|
||||
CNNFilter(int nOrder, int nShift, int nVersion);
|
||||
~CNNFilter();
|
||||
|
||||
int Compress(int nInput);
|
||||
int Decompress(int nInput);
|
||||
void Flush();
|
||||
|
||||
private:
|
||||
|
||||
int m_nOrder;
|
||||
int m_nShift;
|
||||
int m_nVersion;
|
||||
BOOL m_bMMXAvailable;
|
||||
int m_nRunningAverage;
|
||||
|
||||
CRollBuffer<short> m_rbInput;
|
||||
CRollBuffer<short> m_rbDeltaM;
|
||||
|
||||
short * m_paryM;
|
||||
// short * m_paryM_ptr;
|
||||
|
||||
inline short GetSaturatedShortFromInt(int nValue) const
|
||||
{
|
||||
return short((nValue == short(nValue)) ? nValue : (nValue >> 31) ^ 0x7FFF);
|
||||
}
|
||||
|
||||
inline int CalculateDotProductNoMMX(short * pA, short * pB, int nOrder);
|
||||
inline void AdaptNoMMX(short * pM, short * pAdapt, int nDirection, int nOrder);
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_NNFILTER_H
|
||||
408
MAC_SDK/Source/MACLib/NewPredictor.cpp
Normal file
408
MAC_SDK/Source/MACLib/NewPredictor.cpp
Normal file
@@ -0,0 +1,408 @@
|
||||
#include "All.h"
|
||||
#include "APECompress.h"
|
||||
#include "NewPredictor.h"
|
||||
|
||||
/*****************************************************************************************
|
||||
CPredictorCompressNormal
|
||||
*****************************************************************************************/
|
||||
CPredictorCompressNormal::CPredictorCompressNormal(int nCompressionLevel)
|
||||
: IPredictorCompress(nCompressionLevel)
|
||||
{
|
||||
if (nCompressionLevel == COMPRESSION_LEVEL_FAST)
|
||||
{
|
||||
m_pNNFilter = NULL;
|
||||
m_pNNFilter1 = NULL;
|
||||
m_pNNFilter2 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_NORMAL)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(16, 11, MAC_VERSION_NUMBER);
|
||||
m_pNNFilter1 = NULL;
|
||||
m_pNNFilter2 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_HIGH)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(64, 11, MAC_VERSION_NUMBER);
|
||||
m_pNNFilter1 = NULL;
|
||||
m_pNNFilter2 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_EXTRA_HIGH)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(256, 13, MAC_VERSION_NUMBER);
|
||||
m_pNNFilter1 = new CNNFilter(32, 10, MAC_VERSION_NUMBER);
|
||||
m_pNNFilter2 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_INSANE)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(1024 + 256, 15, MAC_VERSION_NUMBER);
|
||||
m_pNNFilter1 = new CNNFilter(256, 13, MAC_VERSION_NUMBER);
|
||||
m_pNNFilter2 = new CNNFilter(16, 11, MAC_VERSION_NUMBER);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
throw(1);
|
||||
}
|
||||
}
|
||||
|
||||
CPredictorCompressNormal::~CPredictorCompressNormal()
|
||||
{
|
||||
SAFE_DELETE(m_pNNFilter)
|
||||
SAFE_DELETE(m_pNNFilter1)
|
||||
SAFE_DELETE(m_pNNFilter2)
|
||||
}
|
||||
|
||||
int CPredictorCompressNormal::Flush()
|
||||
{
|
||||
if (m_pNNFilter) m_pNNFilter->Flush();
|
||||
if (m_pNNFilter1) m_pNNFilter1->Flush();
|
||||
if (m_pNNFilter2) m_pNNFilter2->Flush();
|
||||
|
||||
m_rbPrediction.Flush();
|
||||
m_rbAdapt.Flush();
|
||||
m_Stage1FilterA.Flush(); m_Stage1FilterB.Flush();
|
||||
|
||||
memset(m_aryM, 0, sizeof(m_aryM));
|
||||
|
||||
int * paryM = &m_aryM[8];
|
||||
paryM[0] = 360;
|
||||
paryM[-1] = 317;
|
||||
paryM[-2] = -109;
|
||||
paryM[-3] = 98;
|
||||
|
||||
m_nCurrentIndex = 0;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CPredictorCompressNormal::CompressValue(int nA, int nB)
|
||||
{
|
||||
// roll the buffers if necessary
|
||||
if (m_nCurrentIndex == WINDOW_BLOCKS)
|
||||
{
|
||||
m_rbPrediction.Roll(); m_rbAdapt.Roll();
|
||||
m_nCurrentIndex = 0;
|
||||
}
|
||||
|
||||
// stage 1: simple, non-adaptive order 1 prediction
|
||||
nA = m_Stage1FilterA.Compress(nA);
|
||||
nB = m_Stage1FilterB.Compress(nB);
|
||||
|
||||
// stage 2: adaptive offset filter(s)
|
||||
m_rbPrediction[0] = nA;
|
||||
m_rbPrediction[-2] = m_rbPrediction[-1] - m_rbPrediction[-2];
|
||||
|
||||
m_rbPrediction[-5] = nB;
|
||||
m_rbPrediction[-6] = m_rbPrediction[-5] - m_rbPrediction[-6];
|
||||
|
||||
int * paryM = &m_aryM[8];
|
||||
|
||||
int nPredictionA = (m_rbPrediction[-1] * paryM[0]) + (m_rbPrediction[-2] * paryM[-1]) + (m_rbPrediction[-3] * paryM[-2]) + (m_rbPrediction[-4] * paryM[-3]);
|
||||
int nPredictionB = (m_rbPrediction[-5] * paryM[-4]) + (m_rbPrediction[-6] * paryM[-5]) + (m_rbPrediction[-7] * paryM[-6]) + (m_rbPrediction[-8] * paryM[-7]) + (m_rbPrediction[-9] * paryM[-8]);
|
||||
|
||||
int nOutput = nA - ((nPredictionA + (nPredictionB >> 1)) >> 10);
|
||||
|
||||
// adapt
|
||||
m_rbAdapt[0] = (m_rbPrediction[-1]) ? ((m_rbPrediction[-1] >> 30) & 2) - 1 : 0;
|
||||
m_rbAdapt[-1] = (m_rbPrediction[-2]) ? ((m_rbPrediction[-2] >> 30) & 2) - 1 : 0;
|
||||
m_rbAdapt[-4] = (m_rbPrediction[-5]) ? ((m_rbPrediction[-5] >> 30) & 2) - 1 : 0;
|
||||
m_rbAdapt[-5] = (m_rbPrediction[-6]) ? ((m_rbPrediction[-6] >> 30) & 2) - 1 : 0;
|
||||
|
||||
if (nOutput > 0)
|
||||
{
|
||||
int * pM = &paryM[-8]; int * pAdapt = &m_rbAdapt[-8];
|
||||
EXPAND_9_TIMES(*pM++ -= *pAdapt++;)
|
||||
}
|
||||
else if (nOutput < 0)
|
||||
{
|
||||
int * pM = &paryM[-8]; int * pAdapt = &m_rbAdapt[-8];
|
||||
EXPAND_9_TIMES(*pM++ += *pAdapt++;)
|
||||
}
|
||||
|
||||
// stage 3: NNFilters
|
||||
if (m_pNNFilter)
|
||||
{
|
||||
nOutput = m_pNNFilter->Compress(nOutput);
|
||||
|
||||
if (m_pNNFilter1)
|
||||
{
|
||||
nOutput = m_pNNFilter1->Compress(nOutput);
|
||||
|
||||
if (m_pNNFilter2)
|
||||
nOutput = m_pNNFilter2->Compress(nOutput);
|
||||
}
|
||||
}
|
||||
|
||||
m_rbPrediction.IncrementFast(); m_rbAdapt.IncrementFast();
|
||||
m_nCurrentIndex++;
|
||||
|
||||
return nOutput;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
CPredictorDecompressNormal3930to3950
|
||||
*****************************************************************************************/
|
||||
CPredictorDecompressNormal3930to3950::CPredictorDecompressNormal3930to3950(int nCompressionLevel, int nVersion)
|
||||
: IPredictorDecompress(nCompressionLevel, nVersion)
|
||||
{
|
||||
m_pBuffer[0] = new int [HISTORY_ELEMENTS + WINDOW_BLOCKS];
|
||||
|
||||
if (nCompressionLevel == COMPRESSION_LEVEL_FAST)
|
||||
{
|
||||
m_pNNFilter = NULL;
|
||||
m_pNNFilter1 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_NORMAL)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(16, 11, nVersion);
|
||||
m_pNNFilter1 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_HIGH)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(64, 11, nVersion);
|
||||
m_pNNFilter1 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_EXTRA_HIGH)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(256, 13, nVersion);
|
||||
m_pNNFilter1 = new CNNFilter(32, 10, nVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw(1);
|
||||
}
|
||||
}
|
||||
|
||||
CPredictorDecompressNormal3930to3950::~CPredictorDecompressNormal3930to3950()
|
||||
{
|
||||
SAFE_DELETE(m_pNNFilter)
|
||||
SAFE_DELETE(m_pNNFilter1)
|
||||
SAFE_ARRAY_DELETE(m_pBuffer[0])
|
||||
}
|
||||
|
||||
int CPredictorDecompressNormal3930to3950::Flush()
|
||||
{
|
||||
if (m_pNNFilter) m_pNNFilter->Flush();
|
||||
if (m_pNNFilter1) m_pNNFilter1->Flush();
|
||||
|
||||
ZeroMemory(m_pBuffer[0], (HISTORY_ELEMENTS + 1) * sizeof(int));
|
||||
ZeroMemory(&m_aryM[0], M_COUNT * sizeof(int));
|
||||
|
||||
m_aryM[0] = 360;
|
||||
m_aryM[1] = 317;
|
||||
m_aryM[2] = -109;
|
||||
m_aryM[3] = 98;
|
||||
|
||||
m_pInputBuffer = &m_pBuffer[0][HISTORY_ELEMENTS];
|
||||
|
||||
m_nLastValue = 0;
|
||||
m_nCurrentIndex = 0;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CPredictorDecompressNormal3930to3950::DecompressValue(int nInput, int)
|
||||
{
|
||||
if (m_nCurrentIndex == WINDOW_BLOCKS)
|
||||
{
|
||||
// copy forward and adjust pointers
|
||||
memcpy(&m_pBuffer[0][0], &m_pBuffer[0][WINDOW_BLOCKS], HISTORY_ELEMENTS * sizeof(int));
|
||||
m_pInputBuffer = &m_pBuffer[0][HISTORY_ELEMENTS];
|
||||
|
||||
m_nCurrentIndex = 0;
|
||||
}
|
||||
|
||||
// stage 2: NNFilter
|
||||
if (m_pNNFilter1)
|
||||
nInput = m_pNNFilter1->Decompress(nInput);
|
||||
if (m_pNNFilter)
|
||||
nInput = m_pNNFilter->Decompress(nInput);
|
||||
|
||||
// stage 1: multiple predictors (order 2 and offset 1)
|
||||
|
||||
int p1 = m_pInputBuffer[-1];
|
||||
int p2 = m_pInputBuffer[-1] - m_pInputBuffer[-2];
|
||||
int p3 = m_pInputBuffer[-2] - m_pInputBuffer[-3];
|
||||
int p4 = m_pInputBuffer[-3] - m_pInputBuffer[-4];
|
||||
|
||||
m_pInputBuffer[0] = nInput + (((p1 * m_aryM[0]) + (p2 * m_aryM[1]) + (p3 * m_aryM[2]) + (p4 * m_aryM[3])) >> 9);
|
||||
|
||||
if (nInput > 0)
|
||||
{
|
||||
m_aryM[0] -= ((p1 >> 30) & 2) - 1;
|
||||
m_aryM[1] -= ((p2 >> 30) & 2) - 1;
|
||||
m_aryM[2] -= ((p3 >> 30) & 2) - 1;
|
||||
m_aryM[3] -= ((p4 >> 30) & 2) - 1;
|
||||
}
|
||||
else if (nInput < 0)
|
||||
{
|
||||
m_aryM[0] += ((p1 >> 30) & 2) - 1;
|
||||
m_aryM[1] += ((p2 >> 30) & 2) - 1;
|
||||
m_aryM[2] += ((p3 >> 30) & 2) - 1;
|
||||
m_aryM[3] += ((p4 >> 30) & 2) - 1;
|
||||
}
|
||||
|
||||
int nRetVal = m_pInputBuffer[0] + ((m_nLastValue * 31) >> 5);
|
||||
m_nLastValue = nRetVal;
|
||||
|
||||
m_nCurrentIndex++;
|
||||
m_pInputBuffer++;
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
CPredictorDecompress3950toCurrent
|
||||
*****************************************************************************************/
|
||||
CPredictorDecompress3950toCurrent::CPredictorDecompress3950toCurrent(int nCompressionLevel, int nVersion)
|
||||
: IPredictorDecompress(nCompressionLevel, nVersion)
|
||||
{
|
||||
m_nVersion = nVersion;
|
||||
|
||||
if (nCompressionLevel == COMPRESSION_LEVEL_FAST)
|
||||
{
|
||||
m_pNNFilter = NULL;
|
||||
m_pNNFilter1 = NULL;
|
||||
m_pNNFilter2 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_NORMAL)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(16, 11, nVersion);
|
||||
m_pNNFilter1 = NULL;
|
||||
m_pNNFilter2 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_HIGH)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(64, 11, nVersion);
|
||||
m_pNNFilter1 = NULL;
|
||||
m_pNNFilter2 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_EXTRA_HIGH)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(256, 13, nVersion);
|
||||
m_pNNFilter1 = new CNNFilter(32, 10, nVersion);
|
||||
m_pNNFilter2 = NULL;
|
||||
}
|
||||
else if (nCompressionLevel == COMPRESSION_LEVEL_INSANE)
|
||||
{
|
||||
m_pNNFilter = new CNNFilter(1024 + 256, 15, MAC_VERSION_NUMBER);
|
||||
m_pNNFilter1 = new CNNFilter(256, 13, MAC_VERSION_NUMBER);
|
||||
m_pNNFilter2 = new CNNFilter(16, 11, MAC_VERSION_NUMBER);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
throw(1);
|
||||
}
|
||||
}
|
||||
|
||||
CPredictorDecompress3950toCurrent::~CPredictorDecompress3950toCurrent()
|
||||
{
|
||||
SAFE_DELETE(m_pNNFilter)
|
||||
SAFE_DELETE(m_pNNFilter1)
|
||||
SAFE_DELETE(m_pNNFilter2)
|
||||
}
|
||||
|
||||
int CPredictorDecompress3950toCurrent::Flush()
|
||||
{
|
||||
if (m_pNNFilter) m_pNNFilter->Flush();
|
||||
if (m_pNNFilter1) m_pNNFilter1->Flush();
|
||||
if (m_pNNFilter2) m_pNNFilter2->Flush();
|
||||
|
||||
ZeroMemory(m_aryMA, sizeof(m_aryMA));
|
||||
ZeroMemory(m_aryMB, sizeof(m_aryMB));
|
||||
|
||||
m_rbPredictionA.Flush();
|
||||
m_rbPredictionB.Flush();
|
||||
m_rbAdaptA.Flush();
|
||||
m_rbAdaptB.Flush();
|
||||
|
||||
m_aryMA[0] = 360;
|
||||
m_aryMA[1] = 317;
|
||||
m_aryMA[2] = -109;
|
||||
m_aryMA[3] = 98;
|
||||
|
||||
m_Stage1FilterA.Flush();
|
||||
m_Stage1FilterB.Flush();
|
||||
|
||||
m_nLastValueA = 0;
|
||||
|
||||
m_nCurrentIndex = 0;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CPredictorDecompress3950toCurrent::DecompressValue(int nA, int nB)
|
||||
{
|
||||
if (m_nCurrentIndex == WINDOW_BLOCKS)
|
||||
{
|
||||
// copy forward and adjust pointers
|
||||
m_rbPredictionA.Roll(); m_rbPredictionB.Roll();
|
||||
m_rbAdaptA.Roll(); m_rbAdaptB.Roll();
|
||||
|
||||
m_nCurrentIndex = 0;
|
||||
}
|
||||
|
||||
// stage 2: NNFilter
|
||||
if (m_pNNFilter2)
|
||||
nA = m_pNNFilter2->Decompress(nA);
|
||||
if (m_pNNFilter1)
|
||||
nA = m_pNNFilter1->Decompress(nA);
|
||||
if (m_pNNFilter)
|
||||
nA = m_pNNFilter->Decompress(nA);
|
||||
|
||||
// stage 1: multiple predictors (order 2 and offset 1)
|
||||
m_rbPredictionA[0] = m_nLastValueA;
|
||||
m_rbPredictionA[-1] = m_rbPredictionA[0] - m_rbPredictionA[-1];
|
||||
|
||||
m_rbPredictionB[0] = m_Stage1FilterB.Compress(nB);
|
||||
m_rbPredictionB[-1] = m_rbPredictionB[0] - m_rbPredictionB[-1];
|
||||
|
||||
int nPredictionA = (m_rbPredictionA[0] * m_aryMA[0]) + (m_rbPredictionA[-1] * m_aryMA[1]) + (m_rbPredictionA[-2] * m_aryMA[2]) + (m_rbPredictionA[-3] * m_aryMA[3]);
|
||||
int nPredictionB = (m_rbPredictionB[0] * m_aryMB[0]) + (m_rbPredictionB[-1] * m_aryMB[1]) + (m_rbPredictionB[-2] * m_aryMB[2]) + (m_rbPredictionB[-3] * m_aryMB[3]) + (m_rbPredictionB[-4] * m_aryMB[4]);
|
||||
|
||||
int nCurrentA = nA + ((nPredictionA + (nPredictionB >> 1)) >> 10);
|
||||
|
||||
m_rbAdaptA[0] = (m_rbPredictionA[0]) ? ((m_rbPredictionA[0] >> 30) & 2) - 1 : 0;
|
||||
m_rbAdaptA[-1] = (m_rbPredictionA[-1]) ? ((m_rbPredictionA[-1] >> 30) & 2) - 1 : 0;
|
||||
|
||||
m_rbAdaptB[0] = (m_rbPredictionB[0]) ? ((m_rbPredictionB[0] >> 30) & 2) - 1 : 0;
|
||||
m_rbAdaptB[-1] = (m_rbPredictionB[-1]) ? ((m_rbPredictionB[-1] >> 30) & 2) - 1 : 0;
|
||||
|
||||
if (nA > 0)
|
||||
{
|
||||
m_aryMA[0] -= m_rbAdaptA[0];
|
||||
m_aryMA[1] -= m_rbAdaptA[-1];
|
||||
m_aryMA[2] -= m_rbAdaptA[-2];
|
||||
m_aryMA[3] -= m_rbAdaptA[-3];
|
||||
|
||||
m_aryMB[0] -= m_rbAdaptB[0];
|
||||
m_aryMB[1] -= m_rbAdaptB[-1];
|
||||
m_aryMB[2] -= m_rbAdaptB[-2];
|
||||
m_aryMB[3] -= m_rbAdaptB[-3];
|
||||
m_aryMB[4] -= m_rbAdaptB[-4];
|
||||
}
|
||||
else if (nA < 0)
|
||||
{
|
||||
m_aryMA[0] += m_rbAdaptA[0];
|
||||
m_aryMA[1] += m_rbAdaptA[-1];
|
||||
m_aryMA[2] += m_rbAdaptA[-2];
|
||||
m_aryMA[3] += m_rbAdaptA[-3];
|
||||
|
||||
m_aryMB[0] += m_rbAdaptB[0];
|
||||
m_aryMB[1] += m_rbAdaptB[-1];
|
||||
m_aryMB[2] += m_rbAdaptB[-2];
|
||||
m_aryMB[3] += m_rbAdaptB[-3];
|
||||
m_aryMB[4] += m_rbAdaptB[-4];
|
||||
}
|
||||
|
||||
int nRetVal = m_Stage1FilterA.Decompress(nCurrentA);
|
||||
m_nLastValueA = nCurrentA;
|
||||
|
||||
m_rbPredictionA.IncrementFast(); m_rbPredictionB.IncrementFast();
|
||||
m_rbAdaptA.IncrementFast(); m_rbAdaptB.IncrementFast();
|
||||
|
||||
m_nCurrentIndex++;
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
111
MAC_SDK/Source/MACLib/NewPredictor.h
Normal file
111
MAC_SDK/Source/MACLib/NewPredictor.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef APE_NEWPREDICTOR_H
|
||||
#define APE_NEWPREDICTOR_H
|
||||
|
||||
#include "Predictor.h"
|
||||
|
||||
#include "RollBuffer.h"
|
||||
#include "NNFilter.h"
|
||||
#include "ScaledFirstOrderFilter.h"
|
||||
|
||||
/*************************************************************************************************
|
||||
Functions to create the interfaces
|
||||
*************************************************************************************************/
|
||||
IPredictorCompress * __stdcall CreateIPredictorCompress();
|
||||
IPredictorDecompress * __stdcall CreateIPredictorDecompress();
|
||||
|
||||
#define WINDOW_BLOCKS 512
|
||||
|
||||
#define BUFFER_COUNT 1
|
||||
#define HISTORY_ELEMENTS 8
|
||||
#define M_COUNT 8
|
||||
|
||||
class CPredictorCompressNormal : public IPredictorCompress
|
||||
{
|
||||
public:
|
||||
CPredictorCompressNormal(int nCompressionLevel);
|
||||
virtual ~CPredictorCompressNormal();
|
||||
|
||||
int CompressValue(int nA, int nB = 0);
|
||||
int Flush();
|
||||
|
||||
protected:
|
||||
|
||||
// buffer information
|
||||
CRollBufferFast<int, WINDOW_BLOCKS, 10> m_rbPrediction;
|
||||
CRollBufferFast<int, WINDOW_BLOCKS, 9> m_rbAdapt;
|
||||
|
||||
CScaledFirstOrderFilter<31, 5> m_Stage1FilterA;
|
||||
CScaledFirstOrderFilter<31, 5> m_Stage1FilterB;
|
||||
|
||||
// adaption
|
||||
int m_aryM[9];
|
||||
|
||||
// other
|
||||
int m_nCurrentIndex;
|
||||
CNNFilter * m_pNNFilter;
|
||||
CNNFilter * m_pNNFilter1;
|
||||
CNNFilter * m_pNNFilter2;
|
||||
};
|
||||
|
||||
class CPredictorDecompressNormal3930to3950 : public IPredictorDecompress
|
||||
{
|
||||
public:
|
||||
CPredictorDecompressNormal3930to3950(int nCompressionLevel, int nVersion);
|
||||
virtual ~CPredictorDecompressNormal3930to3950();
|
||||
|
||||
int DecompressValue(int nInput, int);
|
||||
int Flush();
|
||||
|
||||
protected:
|
||||
|
||||
// buffer information
|
||||
int * m_pBuffer[BUFFER_COUNT];
|
||||
|
||||
// adaption
|
||||
int m_aryM[M_COUNT];
|
||||
|
||||
// buffer pointers
|
||||
int * m_pInputBuffer;
|
||||
|
||||
// other
|
||||
int m_nCurrentIndex;
|
||||
int m_nLastValue;
|
||||
CNNFilter * m_pNNFilter;
|
||||
CNNFilter * m_pNNFilter1;
|
||||
};
|
||||
|
||||
class CPredictorDecompress3950toCurrent : public IPredictorDecompress
|
||||
{
|
||||
public:
|
||||
CPredictorDecompress3950toCurrent(int nCompressionLevel, int nVersion);
|
||||
virtual ~CPredictorDecompress3950toCurrent();
|
||||
|
||||
int DecompressValue(int nA, int nB = 0);
|
||||
int Flush();
|
||||
|
||||
protected:
|
||||
|
||||
// adaption
|
||||
int m_aryMA[M_COUNT];
|
||||
int m_aryMB[M_COUNT];
|
||||
|
||||
// buffer pointers
|
||||
CRollBufferFast<int, WINDOW_BLOCKS, 8> m_rbPredictionA;
|
||||
CRollBufferFast<int, WINDOW_BLOCKS, 8> m_rbPredictionB;
|
||||
|
||||
CRollBufferFast<int, WINDOW_BLOCKS, 8> m_rbAdaptA;
|
||||
CRollBufferFast<int, WINDOW_BLOCKS, 8> m_rbAdaptB;
|
||||
|
||||
CScaledFirstOrderFilter<31, 5> m_Stage1FilterA;
|
||||
CScaledFirstOrderFilter<31, 5> m_Stage1FilterB;
|
||||
|
||||
// other
|
||||
int m_nCurrentIndex;
|
||||
int m_nLastValueA;
|
||||
int m_nVersion;
|
||||
CNNFilter * m_pNNFilter;
|
||||
CNNFilter * m_pNNFilter1;
|
||||
CNNFilter * m_pNNFilter2;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_NEWPREDICTOR_H
|
||||
178
MAC_SDK/Source/MACLib/Old/APEDecompressCore.cpp
Normal file
178
MAC_SDK/Source/MACLib/Old/APEDecompressCore.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#include "All.h"
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
#include "UnMAC.h"
|
||||
#include "APEDecompressCore.h"
|
||||
#include "../APEInfo.h"
|
||||
#include "GlobalFunctions.h"
|
||||
#include "../UnBitArrayBase.h"
|
||||
#include "Anti-Predictor.h"
|
||||
#include "UnMAC.h"
|
||||
#include "../Prepare.h"
|
||||
#include "../UnBitArray.h"
|
||||
#include "../Assembly/Assembly.h"
|
||||
|
||||
CAPEDecompressCore::CAPEDecompressCore(CIO * pIO, IAPEDecompress * pAPEDecompress)
|
||||
{
|
||||
m_pAPEDecompress = pAPEDecompress;
|
||||
|
||||
// initialize the bit array
|
||||
m_pUnBitArray = CreateUnBitArray(pAPEDecompress, pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
|
||||
|
||||
if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) >= 3930)
|
||||
throw(0);
|
||||
|
||||
m_pAntiPredictorX = CreateAntiPredictor(pAPEDecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL), pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
|
||||
m_pAntiPredictorY = CreateAntiPredictor(pAPEDecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL), pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
|
||||
|
||||
m_pDataX = new int [pAPEDecompress->GetInfo(APE_INFO_BLOCKS_PER_FRAME) + 16];
|
||||
m_pDataY = new int [pAPEDecompress->GetInfo(APE_INFO_BLOCKS_PER_FRAME) + 16];
|
||||
m_pTempData = new int [pAPEDecompress->GetInfo(APE_INFO_BLOCKS_PER_FRAME) + 16];
|
||||
|
||||
m_nBlocksProcessed = 0;
|
||||
|
||||
// check to see if MMX is available
|
||||
m_bMMXAvailable = GetMMXAvailable();
|
||||
}
|
||||
|
||||
CAPEDecompressCore::~CAPEDecompressCore()
|
||||
{
|
||||
SAFE_DELETE(m_pUnBitArray)
|
||||
|
||||
SAFE_DELETE(m_pAntiPredictorX)
|
||||
SAFE_DELETE(m_pAntiPredictorY)
|
||||
|
||||
SAFE_ARRAY_DELETE(m_pDataX)
|
||||
SAFE_ARRAY_DELETE(m_pDataY)
|
||||
SAFE_ARRAY_DELETE(m_pTempData)
|
||||
}
|
||||
|
||||
void CAPEDecompressCore::GenerateDecodedArrays(int nBlocks, int nSpecialCodes, int nFrameIndex, int nCPULoadBalancingFactor)
|
||||
{
|
||||
CUnBitArray * pBitArray = (CUnBitArray *) m_pUnBitArray;
|
||||
|
||||
if (m_pAPEDecompress->GetInfo(APE_INFO_CHANNELS) == 2)
|
||||
{
|
||||
if ((nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE) && (nSpecialCodes & SPECIAL_FRAME_RIGHT_SILENCE))
|
||||
{
|
||||
memset(m_pDataX, 0, nBlocks * 4);
|
||||
memset(m_pDataY, 0, nBlocks * 4);
|
||||
}
|
||||
else if (nSpecialCodes & SPECIAL_FRAME_PSEUDO_STEREO)
|
||||
{
|
||||
GenerateDecodedArray(m_pDataX, nBlocks, nFrameIndex, m_pAntiPredictorX, nCPULoadBalancingFactor);
|
||||
memset(m_pDataY, 0, nBlocks * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
GenerateDecodedArray(m_pDataX, nBlocks, nFrameIndex, m_pAntiPredictorX, nCPULoadBalancingFactor);
|
||||
GenerateDecodedArray(m_pDataY, nBlocks, nFrameIndex, m_pAntiPredictorY, nCPULoadBalancingFactor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE)
|
||||
{
|
||||
memset(m_pDataX, 0, nBlocks * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
GenerateDecodedArray(m_pDataX, nBlocks, nFrameIndex, m_pAntiPredictorX, nCPULoadBalancingFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CAPEDecompressCore::GenerateDecodedArray(int * Input_Array, uint32 Number_of_Elements, int Frame_Index, CAntiPredictor *pAntiPredictor, int CPULoadBalancingFactor)
|
||||
{
|
||||
const int nFrameBytes = m_pAPEDecompress->GetInfo(APE_INFO_FRAME_BYTES, Frame_Index);
|
||||
|
||||
// run the prediction sequence
|
||||
switch (m_pAPEDecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL))
|
||||
{
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_FAST
|
||||
case COMPRESSION_LEVEL_FAST:
|
||||
if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) < 3320)
|
||||
{
|
||||
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
|
||||
pAntiPredictor->AntiPredict(m_pTempData, Input_Array, Number_of_Elements);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pUnBitArray->GenerateArray(Input_Array, Number_of_Elements, nFrameBytes);
|
||||
pAntiPredictor->AntiPredict(Input_Array, NULL, Number_of_Elements);
|
||||
}
|
||||
|
||||
break;
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_FAST
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_NORMAL
|
||||
|
||||
case COMPRESSION_LEVEL_NORMAL:
|
||||
{
|
||||
// get the array from the bitstream
|
||||
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
|
||||
pAntiPredictor->AntiPredict(m_pTempData, Input_Array, Number_of_Elements);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_NORMAL
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_HIGH
|
||||
case COMPRESSION_LEVEL_HIGH:
|
||||
// get the array from the bitstream
|
||||
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
|
||||
pAntiPredictor->AntiPredict(m_pTempData, Input_Array, Number_of_Elements);
|
||||
break;
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_HIGH
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
case COMPRESSION_LEVEL_EXTRA_HIGH:
|
||||
|
||||
unsigned int aryCoefficientsA[64], aryCoefficientsB[64], nNumberOfCoefficients;
|
||||
|
||||
#define GET_COEFFICIENTS(NumberOfCoefficientsBits, ValueBits) \
|
||||
nNumberOfCoefficients = m_pUnBitArray->DecodeValue(DECODE_VALUE_METHOD_X_BITS, NumberOfCoefficientsBits); \
|
||||
for (unsigned int z = 0; z <= nNumberOfCoefficients; z++) \
|
||||
{ \
|
||||
aryCoefficientsA[z] = m_pUnBitArray->DecodeValue(DECODE_VALUE_METHOD_X_BITS, ValueBits); \
|
||||
aryCoefficientsB[z] = m_pUnBitArray->DecodeValue(DECODE_VALUE_METHOD_X_BITS, ValueBits); \
|
||||
} \
|
||||
|
||||
if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) < 3320)
|
||||
{
|
||||
GET_COEFFICIENTS(4, 6)
|
||||
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
|
||||
((CAntiPredictorExtraHigh0000To3320 *) pAntiPredictor)->AntiPredict(m_pTempData, Input_Array, Number_of_Elements, nNumberOfCoefficients, &aryCoefficientsA[0], &aryCoefficientsB[0]);
|
||||
}
|
||||
else if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) < 3600)
|
||||
{
|
||||
GET_COEFFICIENTS(3, 5)
|
||||
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
|
||||
((CAntiPredictorExtraHigh3320To3600 *) pAntiPredictor)->AntiPredict(m_pTempData, Input_Array, Number_of_Elements, nNumberOfCoefficients, &aryCoefficientsA[0], &aryCoefficientsB[0]);
|
||||
}
|
||||
else if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) < 3700)
|
||||
{
|
||||
GET_COEFFICIENTS(3, 6)
|
||||
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
|
||||
((CAntiPredictorExtraHigh3600To3700 *) pAntiPredictor)->AntiPredict(m_pTempData, Input_Array, Number_of_Elements, nNumberOfCoefficients, &aryCoefficientsA[0], &aryCoefficientsB[0]);
|
||||
}
|
||||
else if (m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION) < 3800)
|
||||
{
|
||||
GET_COEFFICIENTS(3, 6)
|
||||
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
|
||||
((CAntiPredictorExtraHigh3700To3800 *) pAntiPredictor)->AntiPredict(m_pTempData, Input_Array, Number_of_Elements, nNumberOfCoefficients, &aryCoefficientsA[0], &aryCoefficientsB[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pUnBitArray->GenerateArray(m_pTempData, Number_of_Elements, nFrameBytes);
|
||||
((CAntiPredictorExtraHigh3800ToCurrent *) pAntiPredictor)->AntiPredict(m_pTempData, Input_Array, Number_of_Elements, m_bMMXAvailable, CPULoadBalancingFactor, m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
|
||||
}
|
||||
|
||||
break;
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef BACKWARDS_COMPATIBILITY
|
||||
37
MAC_SDK/Source/MACLib/Old/APEDecompressCore.h
Normal file
37
MAC_SDK/Source/MACLib/Old/APEDecompressCore.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef APE_DECOMPRESS_CORE_H
|
||||
#define APE_DECOMPRESS_CORE_H
|
||||
|
||||
class CAPEDecompressCore
|
||||
{
|
||||
public:
|
||||
|
||||
CAPEDecompressCore(CIO * pIO, IAPEDecompress * pAPEDecompress);
|
||||
~CAPEDecompressCore();
|
||||
|
||||
void GenerateDecodedArrays(int nBlocks, int nSpecialCodes, int nFrameIndex, int nCPULoadBalancingFactor);
|
||||
void GenerateDecodedArray(int *Input_Array, uint32 Number_of_Elements, int Frame_Index, CAntiPredictor *pAntiPredictor, int CPULoadBalancingFactor = 0);
|
||||
|
||||
int * GetDataX() { return m_pDataX; }
|
||||
int * GetDataY() { return m_pDataY; }
|
||||
|
||||
CUnBitArrayBase * GetUnBitArrray() { return m_pUnBitArray; }
|
||||
|
||||
int * m_pTempData;
|
||||
int * m_pDataX;
|
||||
int * m_pDataY;
|
||||
|
||||
CAntiPredictor * m_pAntiPredictorX;
|
||||
CAntiPredictor * m_pAntiPredictorY;
|
||||
|
||||
CUnBitArrayBase * m_pUnBitArray;
|
||||
BIT_ARRAY_STATE m_BitArrayStateX;
|
||||
BIT_ARRAY_STATE m_BitArrayStateY;
|
||||
|
||||
IAPEDecompress * m_pAPEDecompress;
|
||||
|
||||
BOOL m_bMMXAvailable;
|
||||
int m_nBlocksProcessed;
|
||||
};
|
||||
|
||||
|
||||
#endif // #ifndef APE_DECOMPRESS_CORE_H
|
||||
279
MAC_SDK/Source/MACLib/Old/APEDecompressOld.cpp
Normal file
279
MAC_SDK/Source/MACLib/Old/APEDecompressOld.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
#include "All.h"
|
||||
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
#include "UnMAC.h"
|
||||
#include "APEDecompressOld.h"
|
||||
#include "../APEInfo.h"
|
||||
|
||||
CAPEDecompressOld::CAPEDecompressOld(int * pErrorCode, CAPEInfo * pAPEInfo, int nStartBlock, int nFinishBlock)
|
||||
{
|
||||
*pErrorCode = ERROR_SUCCESS;
|
||||
|
||||
// open / analyze the file
|
||||
m_spAPEInfo.Assign(pAPEInfo);
|
||||
|
||||
// version check (this implementation only works with 3.92 and earlier files)
|
||||
if (GetInfo(APE_INFO_FILE_VERSION) > 3920)
|
||||
{
|
||||
*pErrorCode = ERROR_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
// create the buffer
|
||||
m_nBlockAlign = GetInfo(APE_INFO_BLOCK_ALIGN);
|
||||
|
||||
// initialize other stuff
|
||||
m_nBufferTail = 0;
|
||||
m_bDecompressorInitialized = FALSE;
|
||||
m_nCurrentFrame = 0;
|
||||
m_nCurrentBlock = 0;
|
||||
|
||||
// set the "real" start and finish blocks
|
||||
m_nStartBlock = (nStartBlock < 0) ? 0 : min(nStartBlock, GetInfo(APE_INFO_TOTAL_BLOCKS));
|
||||
m_nFinishBlock = (nFinishBlock < 0) ? GetInfo(APE_INFO_TOTAL_BLOCKS) : min(nFinishBlock, GetInfo(APE_INFO_TOTAL_BLOCKS));
|
||||
m_bIsRanged = (m_nStartBlock != 0) || (m_nFinishBlock != GetInfo(APE_INFO_TOTAL_BLOCKS));
|
||||
}
|
||||
|
||||
CAPEDecompressOld::~CAPEDecompressOld()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int CAPEDecompressOld::InitializeDecompressor()
|
||||
{
|
||||
// check if we have anything to do
|
||||
if (m_bDecompressorInitialized)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// initialize the decoder
|
||||
RETURN_ON_ERROR(m_UnMAC.Initialize(this))
|
||||
|
||||
int nMaximumDecompressedFrameBytes = m_nBlockAlign * GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
int nTotalBufferBytes = max(65536, (nMaximumDecompressedFrameBytes + 16) * 2);
|
||||
m_spBuffer.Assign(new char [nTotalBufferBytes], TRUE);
|
||||
if (m_spBuffer == NULL)
|
||||
return ERROR_INSUFFICIENT_MEMORY;
|
||||
|
||||
// update the initialized flag
|
||||
m_bDecompressorInitialized = TRUE;
|
||||
|
||||
// seek to the beginning
|
||||
return Seek(0);
|
||||
}
|
||||
|
||||
int CAPEDecompressOld::GetData(char * pBuffer, int nBlocks, int * pBlocksRetrieved)
|
||||
{
|
||||
if (pBlocksRetrieved) *pBlocksRetrieved = 0;
|
||||
|
||||
RETURN_ON_ERROR(InitializeDecompressor())
|
||||
|
||||
// cap
|
||||
int nBlocksUntilFinish = m_nFinishBlock - m_nCurrentBlock;
|
||||
nBlocks = min(nBlocks, nBlocksUntilFinish);
|
||||
|
||||
int nBlocksRetrieved = 0;
|
||||
|
||||
// fulfill as much of the request as possible
|
||||
int nTotalBytesNeeded = nBlocks * m_nBlockAlign;
|
||||
int nBytesLeft = nTotalBytesNeeded;
|
||||
int nBlocksDecoded = 1;
|
||||
|
||||
while (nBytesLeft > 0 && nBlocksDecoded > 0)
|
||||
{
|
||||
// empty the buffer
|
||||
int nBytesAvailable = m_nBufferTail;
|
||||
int nIntialBytes = min(nBytesLeft, nBytesAvailable);
|
||||
if (nIntialBytes > 0)
|
||||
{
|
||||
memcpy(&pBuffer[nTotalBytesNeeded - nBytesLeft], &m_spBuffer[0], nIntialBytes);
|
||||
|
||||
if ((m_nBufferTail - nIntialBytes) > 0)
|
||||
memmove(&m_spBuffer[0], &m_spBuffer[nIntialBytes], m_nBufferTail - nIntialBytes);
|
||||
|
||||
nBytesLeft -= nIntialBytes;
|
||||
m_nBufferTail -= nIntialBytes;
|
||||
|
||||
}
|
||||
|
||||
// decode more
|
||||
if (nBytesLeft > 0)
|
||||
{
|
||||
nBlocksDecoded = m_UnMAC.DecompressFrame((unsigned char *) &m_spBuffer[m_nBufferTail], m_nCurrentFrame++, 0);
|
||||
if (nBlocksDecoded == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
m_nBufferTail += (nBlocksDecoded * m_nBlockAlign);
|
||||
}
|
||||
}
|
||||
|
||||
nBlocksRetrieved = (nTotalBytesNeeded - nBytesLeft) / m_nBlockAlign;
|
||||
|
||||
// update the position
|
||||
m_nCurrentBlock += nBlocksRetrieved;
|
||||
|
||||
if (pBlocksRetrieved) *pBlocksRetrieved = nBlocksRetrieved;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPEDecompressOld::Seek(int nBlockOffset)
|
||||
{
|
||||
RETURN_ON_ERROR(InitializeDecompressor())
|
||||
|
||||
// use the offset
|
||||
nBlockOffset += m_nStartBlock;
|
||||
|
||||
// cap (to prevent seeking too far)
|
||||
if (nBlockOffset >= m_nFinishBlock)
|
||||
nBlockOffset = m_nFinishBlock - 1;
|
||||
if (nBlockOffset < m_nStartBlock)
|
||||
nBlockOffset = m_nStartBlock;
|
||||
|
||||
// flush the buffer
|
||||
m_nBufferTail = 0;
|
||||
|
||||
// seek to the perfect location
|
||||
int nBaseFrame = nBlockOffset / GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
int nBlocksToSkip = nBlockOffset % GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
int nBytesToSkip = nBlocksToSkip * m_nBlockAlign;
|
||||
|
||||
// skip necessary blocks
|
||||
int nMaximumDecompressedFrameBytes = m_nBlockAlign * GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
char *pTempBuffer = new char [nMaximumDecompressedFrameBytes + 16];
|
||||
ZeroMemory(pTempBuffer, nMaximumDecompressedFrameBytes + 16);
|
||||
|
||||
m_nCurrentFrame = nBaseFrame;
|
||||
|
||||
int nBlocksDecoded = m_UnMAC.DecompressFrame((unsigned char *) pTempBuffer, m_nCurrentFrame++, 0);
|
||||
|
||||
if (nBlocksDecoded == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nBytesToKeep = (nBlocksDecoded * m_nBlockAlign) - nBytesToSkip;
|
||||
memcpy(&m_spBuffer[m_nBufferTail], &pTempBuffer[nBytesToSkip], nBytesToKeep);
|
||||
m_nBufferTail += nBytesToKeep;
|
||||
|
||||
delete [] pTempBuffer;
|
||||
|
||||
|
||||
m_nCurrentBlock = nBlockOffset;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CAPEDecompressOld::GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1, int nParam2)
|
||||
{
|
||||
int nRetVal = 0;
|
||||
BOOL bHandled = TRUE;
|
||||
|
||||
switch (Field)
|
||||
{
|
||||
case APE_DECOMPRESS_CURRENT_BLOCK:
|
||||
nRetVal = m_nCurrentBlock - m_nStartBlock;
|
||||
break;
|
||||
case APE_DECOMPRESS_CURRENT_MS:
|
||||
{
|
||||
int nSampleRate = m_spAPEInfo->GetInfo(APE_INFO_SAMPLE_RATE, 0, 0);
|
||||
if (nSampleRate > 0)
|
||||
nRetVal = int((double(m_nCurrentBlock) * double(1000)) / double(nSampleRate));
|
||||
break;
|
||||
}
|
||||
case APE_DECOMPRESS_TOTAL_BLOCKS:
|
||||
nRetVal = m_nFinishBlock - m_nStartBlock;
|
||||
break;
|
||||
case APE_DECOMPRESS_LENGTH_MS:
|
||||
{
|
||||
int nSampleRate = m_spAPEInfo->GetInfo(APE_INFO_SAMPLE_RATE, 0, 0);
|
||||
if (nSampleRate > 0)
|
||||
nRetVal = int((double(m_nFinishBlock - m_nStartBlock) * double(1000)) / double(nSampleRate));
|
||||
break;
|
||||
}
|
||||
case APE_DECOMPRESS_CURRENT_BITRATE:
|
||||
nRetVal = GetInfo(APE_INFO_FRAME_BITRATE, m_nCurrentFrame);
|
||||
break;
|
||||
case APE_DECOMPRESS_AVERAGE_BITRATE:
|
||||
{
|
||||
if (m_bIsRanged)
|
||||
{
|
||||
// figure the frame range
|
||||
const int nBlocksPerFrame = GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
int nStartFrame = m_nStartBlock / nBlocksPerFrame;
|
||||
int nFinishFrame = (m_nFinishBlock + nBlocksPerFrame - 1) / nBlocksPerFrame;
|
||||
|
||||
// get the number of bytes in the first and last frame
|
||||
int nTotalBytes = (GetInfo(APE_INFO_FRAME_BYTES, nStartFrame) * (m_nStartBlock % nBlocksPerFrame)) / nBlocksPerFrame;
|
||||
if (nFinishFrame != nStartFrame)
|
||||
nTotalBytes += (GetInfo(APE_INFO_FRAME_BYTES, nFinishFrame) * (m_nFinishBlock % nBlocksPerFrame)) / nBlocksPerFrame;
|
||||
|
||||
// get the number of bytes in between
|
||||
const int nTotalFrames = GetInfo(APE_INFO_TOTAL_FRAMES);
|
||||
for (int nFrame = nStartFrame + 1; (nFrame < nFinishFrame) && (nFrame < nTotalFrames); nFrame++)
|
||||
nTotalBytes += GetInfo(APE_INFO_FRAME_BYTES, nFrame);
|
||||
|
||||
// figure the bitrate
|
||||
int nTotalMS = int((double(m_nFinishBlock - m_nStartBlock) * double(1000)) / double(GetInfo(APE_INFO_SAMPLE_RATE)));
|
||||
if (nTotalMS != 0)
|
||||
nRetVal = (nTotalBytes * 8) / nTotalMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
nRetVal = GetInfo(APE_INFO_AVERAGE_BITRATE);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
bHandled = FALSE;
|
||||
}
|
||||
|
||||
if (!bHandled && m_bIsRanged)
|
||||
{
|
||||
bHandled = TRUE;
|
||||
|
||||
switch (Field)
|
||||
{
|
||||
case APE_INFO_WAV_HEADER_BYTES:
|
||||
nRetVal = sizeof(WAVE_HEADER);
|
||||
break;
|
||||
case APE_INFO_WAV_HEADER_DATA:
|
||||
{
|
||||
char * pBuffer = (char *) nParam1;
|
||||
int nMaxBytes = nParam2;
|
||||
|
||||
if (sizeof(WAVE_HEADER) > nMaxBytes)
|
||||
{
|
||||
nRetVal = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
WAVEFORMATEX wfeFormat; GetInfo(APE_INFO_WAVEFORMATEX, (int) &wfeFormat, 0);
|
||||
WAVE_HEADER WAVHeader; FillWaveHeader(&WAVHeader,
|
||||
(m_nFinishBlock - m_nStartBlock) * GetInfo(APE_INFO_BLOCK_ALIGN),
|
||||
&wfeFormat, 0);
|
||||
memcpy(pBuffer, &WAVHeader, sizeof(WAVE_HEADER));
|
||||
nRetVal = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case APE_INFO_WAV_TERMINATING_BYTES:
|
||||
nRetVal = 0;
|
||||
break;
|
||||
case APE_INFO_WAV_TERMINATING_DATA:
|
||||
nRetVal = 0;
|
||||
break;
|
||||
default:
|
||||
bHandled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bHandled == FALSE)
|
||||
nRetVal = m_spAPEInfo->GetInfo(Field, nParam1, nParam2);
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
#endif // #ifdef BACKWARDS_COMPATIBILITY
|
||||
43
MAC_SDK/Source/MACLib/Old/APEDecompressOld.h
Normal file
43
MAC_SDK/Source/MACLib/Old/APEDecompressOld.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef _apedecompressold_h_
|
||||
#define _apedecompressold_h_
|
||||
|
||||
#include "../APEDecompress.h"
|
||||
#include "UnMAC.h"
|
||||
|
||||
class CAPEDecompressOld : public IAPEDecompress
|
||||
{
|
||||
public:
|
||||
CAPEDecompressOld(int * pErrorCode, CAPEInfo * pAPEInfo, int nStartBlock = -1, int nFinishBlock = -1);
|
||||
~CAPEDecompressOld();
|
||||
|
||||
int GetData(char * pBuffer, int nBlocks, int * pBlocksRetrieved);
|
||||
int Seek(int nBlockOffset);
|
||||
|
||||
int GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1 = 0, int nParam2 = 0);
|
||||
|
||||
protected:
|
||||
|
||||
// buffer
|
||||
CSmartPtr<char> m_spBuffer;
|
||||
int m_nBufferTail;
|
||||
|
||||
// file info
|
||||
int m_nBlockAlign;
|
||||
int m_nCurrentFrame;
|
||||
|
||||
// start / finish information
|
||||
int m_nStartBlock;
|
||||
int m_nFinishBlock;
|
||||
int m_nCurrentBlock;
|
||||
BOOL m_bIsRanged;
|
||||
|
||||
// decoding tools
|
||||
CUnMAC m_UnMAC;
|
||||
CSmartPtr<CAPEInfo> m_spAPEInfo;
|
||||
|
||||
BOOL m_bDecompressorInitialized;
|
||||
int InitializeDecompressor();
|
||||
};
|
||||
|
||||
#endif //_apedecompressold_h_
|
||||
|
||||
394
MAC_SDK/Source/MACLib/Old/Anti-Predictor.cpp
Normal file
394
MAC_SDK/Source/MACLib/Old/Anti-Predictor.cpp
Normal file
@@ -0,0 +1,394 @@
|
||||
#include "All.h"
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
#include "../MACLib.h"
|
||||
#include "Anti-Predictor.h"
|
||||
|
||||
CAntiPredictor * CreateAntiPredictor(int nCompressionLevel, int nVersion)
|
||||
{
|
||||
CAntiPredictor *pAntiPredictor = NULL;
|
||||
|
||||
switch (nCompressionLevel)
|
||||
{
|
||||
#ifdef ENABLE_COMPRESSION_MODE_FAST
|
||||
case COMPRESSION_LEVEL_FAST:
|
||||
if (nVersion < 3320)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorFast0000To3320;
|
||||
}
|
||||
else
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorFast3320ToCurrent;
|
||||
}
|
||||
break;
|
||||
#endif //ENABLE_COMPRESSION_MODE_FAST
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_NORMAL
|
||||
|
||||
case COMPRESSION_LEVEL_NORMAL:
|
||||
if (nVersion < 3320)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorNormal0000To3320;
|
||||
}
|
||||
else if (nVersion < 3800)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorNormal3320To3800;
|
||||
}
|
||||
else
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorNormal3800ToCurrent;
|
||||
}
|
||||
break;
|
||||
|
||||
#endif //ENABLE_COMPRESSION_MODE_NORMAL
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_HIGH
|
||||
case COMPRESSION_LEVEL_HIGH:
|
||||
if (nVersion < 3320)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorHigh0000To3320;
|
||||
}
|
||||
else if (nVersion < 3600)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorHigh3320To3600;
|
||||
}
|
||||
else if (nVersion < 3700)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorHigh3600To3700;
|
||||
}
|
||||
else if (nVersion < 3800)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorHigh3700To3800;
|
||||
}
|
||||
else
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorHigh3800ToCurrent;
|
||||
}
|
||||
break;
|
||||
#endif //ENABLE_COMPRESSION_MODE_HIGH
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
case COMPRESSION_LEVEL_EXTRA_HIGH:
|
||||
if (nVersion < 3320)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorExtraHigh0000To3320;
|
||||
}
|
||||
else if (nVersion < 3600)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorExtraHigh3320To3600;
|
||||
}
|
||||
else if (nVersion < 3700)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorExtraHigh3600To3700;
|
||||
}
|
||||
else if (nVersion < 3800)
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorExtraHigh3700To3800;
|
||||
}
|
||||
else
|
||||
{
|
||||
pAntiPredictor = (CAntiPredictor *) new CAntiPredictorExtraHigh3800ToCurrent;
|
||||
}
|
||||
break;
|
||||
#endif //ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
}
|
||||
|
||||
return pAntiPredictor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CAntiPredictor::CAntiPredictor()
|
||||
{
|
||||
}
|
||||
|
||||
CAntiPredictor::~CAntiPredictor()
|
||||
{
|
||||
}
|
||||
|
||||
void CAntiPredictor::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void CAntiPredictorOffset::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Offset, int DeltaM)
|
||||
{
|
||||
|
||||
memcpy(pOutputArray, pInputArray, Offset * 4);
|
||||
|
||||
int *ip = &pInputArray[Offset];
|
||||
int *ipo = &pOutputArray[0];
|
||||
int *op = &pOutputArray[Offset];
|
||||
int m = 0;
|
||||
|
||||
for (; op < &pOutputArray[NumberOfElements]; ip++, ipo++, op++)
|
||||
{
|
||||
*op = *ip + ((*ipo * m) >> 12);
|
||||
|
||||
(*ipo ^ *ip) > 0 ? m += DeltaM : m -= DeltaM;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
|
||||
int CAntiPredictorExtraHighHelper::ConventionalDotProduct(short *bip, short *bbm, short *pIPAdaptFactor, int op, int nNumberOfIterations)
|
||||
{
|
||||
// dot product
|
||||
int nDotProduct = 0;
|
||||
short *pMaxBBM = &bbm[nNumberOfIterations];
|
||||
|
||||
if (op == 0)
|
||||
{
|
||||
while(bbm < pMaxBBM)
|
||||
{
|
||||
EXPAND_32_TIMES(nDotProduct += *bip++ * *bbm++;)
|
||||
}
|
||||
}
|
||||
else if (op > 0)
|
||||
{
|
||||
while(bbm < pMaxBBM)
|
||||
{
|
||||
EXPAND_32_TIMES(nDotProduct += *bip++ * *bbm; *bbm++ += *pIPAdaptFactor++;)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(bbm < pMaxBBM)
|
||||
{
|
||||
EXPAND_32_TIMES(nDotProduct += *bip++ * *bbm; *bbm++ -= *pIPAdaptFactor++;)
|
||||
}
|
||||
}
|
||||
|
||||
// use the dot product
|
||||
return nDotProduct;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ASSEMBLY
|
||||
|
||||
#define MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_HEAD \
|
||||
__asm movq mm0, [esi] \
|
||||
__asm add esi, 8 \
|
||||
__asm movq mm1, [esi] \
|
||||
__asm add esi, 8 \
|
||||
__asm movq mm2, [esi] \
|
||||
__asm add esi, 8 \
|
||||
\
|
||||
__asm movq mm3, [edi] \
|
||||
__asm add edi, 8 \
|
||||
__asm movq mm4, [edi] \
|
||||
__asm add edi, 8 \
|
||||
__asm movq mm5, [edi] \
|
||||
__asm sub edi, 16 \
|
||||
\
|
||||
__asm pmaddwd mm0, mm3 \
|
||||
__asm pmaddwd mm1, mm4 \
|
||||
__asm pmaddwd mm2, mm5 \
|
||||
\
|
||||
__asm paddd mm7, mm0 \
|
||||
__asm paddd mm7, mm1 \
|
||||
__asm paddd mm7, mm2 \
|
||||
|
||||
|
||||
#define MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD \
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_HEAD \
|
||||
\
|
||||
__asm paddw mm3, DWORD PTR [eax] \
|
||||
__asm movq [edi], mm3 \
|
||||
__asm add eax, 8 \
|
||||
__asm add edi, 8 \
|
||||
__asm paddw mm4, DWORD PTR [eax] \
|
||||
__asm movq [edi], mm4 \
|
||||
__asm add eax, 8 \
|
||||
__asm add edi, 8 \
|
||||
__asm paddw mm5, DWORD PTR [eax] \
|
||||
__asm movq [edi], mm5 \
|
||||
__asm add eax, 8 \
|
||||
__asm add edi, 8
|
||||
|
||||
#define MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT \
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_HEAD \
|
||||
\
|
||||
__asm psubw mm3, DWORD PTR [eax] \
|
||||
__asm movq [edi], mm3 \
|
||||
__asm add eax, 8 \
|
||||
__asm add edi, 8 \
|
||||
__asm psubw mm4, DWORD PTR [eax] \
|
||||
__asm movq [edi], mm4 \
|
||||
__asm add eax, 8 \
|
||||
__asm add edi, 8 \
|
||||
__asm psubw mm5, DWORD PTR [eax] \
|
||||
__asm movq [edi], mm5 \
|
||||
__asm add eax, 8 \
|
||||
__asm add edi, 8
|
||||
|
||||
int CAntiPredictorExtraHighHelper::MMXDotProduct(short *bip, short *bbm, short *pIPAdaptFactor, int op, int nNumberOfIterations)
|
||||
{
|
||||
int nDotProduct;
|
||||
nNumberOfIterations = (nNumberOfIterations / 128);
|
||||
|
||||
if (op > 0)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
|
||||
mov eax, DWORD PTR [pIPAdaptFactor]
|
||||
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi, DWORD PTR bip[0]
|
||||
mov edi, DWORD PTR bbm[0]
|
||||
|
||||
pxor mm7, mm7
|
||||
|
||||
LBL_ADD_AGAIN:
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// process 8 mm registers full
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_ADD
|
||||
|
||||
// fill the registers
|
||||
movq mm0, [esi]
|
||||
add esi, 8
|
||||
movq mm1, [esi]
|
||||
add esi, 8
|
||||
|
||||
movq mm3, [edi]
|
||||
add edi, 8
|
||||
movq mm4, [edi]
|
||||
sub edi, 8
|
||||
|
||||
pmaddwd mm0, mm3
|
||||
pmaddwd mm1, mm4
|
||||
|
||||
paddd mm7, mm0
|
||||
paddd mm7, mm1
|
||||
|
||||
paddw mm3, DWORD PTR [eax]
|
||||
movq [edi], mm3
|
||||
add eax, 8
|
||||
add edi, 8
|
||||
paddw mm4, DWORD PTR [eax]
|
||||
movq [edi], mm4
|
||||
add eax, 8
|
||||
add edi, 8
|
||||
|
||||
sub nNumberOfIterations, 1
|
||||
cmp nNumberOfIterations, 0
|
||||
jg LBL_ADD_AGAIN
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// clean-up
|
||||
///////////////////////////////////////////////////////////////
|
||||
// mm7 has the final dot-product (split into two dwords)
|
||||
movq mm6, mm7
|
||||
psrlq mm7, 32
|
||||
paddd mm6, mm7
|
||||
movd nDotProduct, mm6
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop eax
|
||||
emms
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
|
||||
mov eax, DWORD PTR [pIPAdaptFactor]
|
||||
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi, DWORD PTR bip[0]
|
||||
mov edi, DWORD PTR bbm[0]
|
||||
|
||||
pxor mm7, mm7
|
||||
|
||||
LBL_SUBTRACT_AGAIN:
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// process 8 mm registers full
|
||||
/////////////////////////////////////////////////////////
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
|
||||
MMX_DOT_PRODUCT_3800_TO_CURRENT_PROCESS_CHUNK_SUBTRACT
|
||||
|
||||
// fill the registers
|
||||
movq mm0, [esi]
|
||||
add esi, 8
|
||||
movq mm1, [esi]
|
||||
add esi, 8
|
||||
|
||||
movq mm3, [edi]
|
||||
add edi, 8
|
||||
movq mm4, [edi]
|
||||
sub edi, 8
|
||||
|
||||
pmaddwd mm0, mm3
|
||||
pmaddwd mm1, mm4
|
||||
|
||||
paddd mm7, mm0
|
||||
paddd mm7, mm1
|
||||
|
||||
psubw mm3, DWORD PTR [eax]
|
||||
movq [edi], mm3
|
||||
add eax, 8
|
||||
add edi, 8
|
||||
psubw mm4, DWORD PTR [eax]
|
||||
movq [edi], mm4
|
||||
add eax, 8
|
||||
add edi, 8
|
||||
|
||||
sub nNumberOfIterations, 1
|
||||
cmp nNumberOfIterations, 0
|
||||
jg LBL_SUBTRACT_AGAIN
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// clean-up
|
||||
///////////////////////////////////////////////////////////////
|
||||
// mm7 has the final dot-product (split into two dwords)
|
||||
movq mm6, mm7
|
||||
psrlq mm7, 32
|
||||
paddd mm6, mm7
|
||||
movd nDotProduct, mm6
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop eax
|
||||
emms
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nDotProduct;
|
||||
}
|
||||
|
||||
#endif // #ifdef ENABLE_ASSEMBLY
|
||||
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
|
||||
#endif // #ifdef BACKWARDS_COMPATIBILITY
|
||||
253
MAC_SDK/Source/MACLib/Old/Anti-Predictor.h
Normal file
253
MAC_SDK/Source/MACLib/Old/Anti-Predictor.h
Normal file
@@ -0,0 +1,253 @@
|
||||
#ifndef APE_ANTIPREDICTOR_H
|
||||
#define APE_ANTIPREDICTOR_H
|
||||
|
||||
class CAntiPredictor;
|
||||
|
||||
CAntiPredictor * CreateAntiPredictor(int nCompressionLevel, int nVersion);
|
||||
|
||||
/*****************************************************************************************
|
||||
Base class for all anti-predictors
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictor
|
||||
{
|
||||
public:
|
||||
|
||||
// construction/destruction
|
||||
CAntiPredictor();
|
||||
~CAntiPredictor();
|
||||
|
||||
// functions
|
||||
virtual void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
Offset anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorOffset : public CAntiPredictor
|
||||
{
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Offset, int DeltaM);
|
||||
};
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_FAST
|
||||
|
||||
/*****************************************************************************************
|
||||
Fast anti-predictor (from original 'fast' mode...updated for version 3.32)
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorFast0000To3320 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
Fast anti-predictor (new 'fast' mode release with version 3.32)
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorFast3320ToCurrent : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_FAST
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_NORMAL
|
||||
/*****************************************************************************************
|
||||
Normal anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorNormal0000To3320 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
Normal anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorNormal3320To3800 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
Normal anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorNormal3800ToCurrent : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_NORMAL
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_HIGH
|
||||
|
||||
/*****************************************************************************************
|
||||
High anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorHigh0000To3320 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
High anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorHigh3320To3600 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
High anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorHigh3600To3700 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
High anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorHigh3700To3800 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
High anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorHigh3800ToCurrent : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements);
|
||||
|
||||
};
|
||||
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_HIGH
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high helper
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorExtraHighHelper
|
||||
{
|
||||
public:
|
||||
int ConventionalDotProduct(short *bip, short *bbm, short *pIPAdaptFactor, int op, int nNumberOfIterations);
|
||||
|
||||
#ifdef ENABLE_ASSEMBLY
|
||||
int MMXDotProduct(short *bip, short *bbm, short *pIPAdaptFactor, int op, int nNumberOfIterations);
|
||||
#endif // #ifdef ENABLE_ASSEMBLY
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorExtraHigh0000To3320 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB);
|
||||
|
||||
private:
|
||||
void AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g, int dm, int Max_Order);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorExtraHigh3320To3600 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB);
|
||||
|
||||
private:
|
||||
void AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g, int dm, int Max_Order);
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorExtraHigh3600To3700 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB);
|
||||
|
||||
private:
|
||||
void AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g1, int g2, int Max_Order);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorExtraHigh3700To3800 : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB);
|
||||
|
||||
private:
|
||||
void AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g1, int g2, int Max_Order);
|
||||
};
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high anti-predictor
|
||||
*****************************************************************************************/
|
||||
class CAntiPredictorExtraHigh3800ToCurrent : public CAntiPredictor {
|
||||
|
||||
public:
|
||||
|
||||
// functions
|
||||
void AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, BOOL bMMXAvailable, int CPULoadBalancingFactor, int nVersion);
|
||||
};
|
||||
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
|
||||
#endif // #ifndef APE_ANTIPREDICTOR_H
|
||||
330
MAC_SDK/Source/MACLib/Old/AntiPredictorExtraHigh.cpp
Normal file
330
MAC_SDK/Source/MACLib/Old/AntiPredictorExtraHigh.cpp
Normal file
@@ -0,0 +1,330 @@
|
||||
#include "All.h"
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
#include "Anti-Predictor.h"
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high 0000 to 3320 implementation
|
||||
*****************************************************************************************/
|
||||
void CAntiPredictorExtraHigh0000To3320::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB) {
|
||||
for (int z = Iterations; z >= 0; z--){
|
||||
AntiPredictorOffset(pInputArray, pOutputArray, NumberOfElements, pOffsetValueArrayB[z], -1, 64);
|
||||
AntiPredictorOffset(pOutputArray, pInputArray, NumberOfElements, pOffsetValueArrayA[z], 1, 64);
|
||||
}
|
||||
|
||||
CAntiPredictorHigh0000To3320 AntiPredictor;
|
||||
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
|
||||
}
|
||||
|
||||
void CAntiPredictorExtraHigh0000To3320::AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g, int dm, int Max_Order)
|
||||
{
|
||||
int q;
|
||||
|
||||
if ((g==0) || (Number_of_Elements <= Max_Order)) {
|
||||
memcpy(Output_Array, Input_Array, Number_of_Elements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(Output_Array, Input_Array, Max_Order * 4);
|
||||
|
||||
int m = 512;
|
||||
|
||||
if (dm > 0)
|
||||
for (q = Max_Order; q < Number_of_Elements; q++) {
|
||||
Output_Array[q] = Input_Array[q] + (Output_Array[q - g] >> 3);
|
||||
}
|
||||
|
||||
else
|
||||
for (q = Max_Order; q < Number_of_Elements; q++) {
|
||||
Output_Array[q] = Input_Array[q] - (Output_Array[q - g] >> 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high 3320 to 3600 implementation
|
||||
*****************************************************************************************/
|
||||
void CAntiPredictorExtraHigh3320To3600::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB)
|
||||
{
|
||||
for (int z = Iterations; z >= 0; z--)
|
||||
{
|
||||
AntiPredictorOffset(pInputArray, pOutputArray, NumberOfElements, pOffsetValueArrayB[z], -1, 32);
|
||||
AntiPredictorOffset(pOutputArray, pInputArray, NumberOfElements, pOffsetValueArrayA[z], 1, 32);
|
||||
}
|
||||
|
||||
CAntiPredictorHigh0000To3320 AntiPredictor;
|
||||
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
|
||||
}
|
||||
|
||||
|
||||
void CAntiPredictorExtraHigh3320To3600::AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g, int dm, int Max_Order)
|
||||
{
|
||||
|
||||
int q;
|
||||
|
||||
if ((g==0) || (Number_of_Elements <= Max_Order)) {
|
||||
memcpy(Output_Array, Input_Array, Number_of_Elements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(Output_Array, Input_Array, Max_Order * 4);
|
||||
|
||||
int m = 512;
|
||||
|
||||
if (dm > 0)
|
||||
for (q = Max_Order; q < Number_of_Elements; q++) {
|
||||
Output_Array[q] = Input_Array[q] + ((Output_Array[q - g] * m) >> 12);
|
||||
(Input_Array[q] ^ Output_Array[q - g]) > 0 ? m += 8 : m -= 8;
|
||||
}
|
||||
|
||||
else
|
||||
for (q = Max_Order; q < Number_of_Elements; q++) {
|
||||
Output_Array[q] = Input_Array[q] - ((Output_Array[q - g] * m) >> 12);
|
||||
(Input_Array[q] ^ Output_Array[q - g]) > 0 ? m -= 8 : m += 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high 3600 to 3700 implementation
|
||||
*****************************************************************************************/
|
||||
void CAntiPredictorExtraHigh3600To3700::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB) {
|
||||
for (int z = Iterations; z >= 0; ){
|
||||
|
||||
AntiPredictorOffset(pInputArray, pOutputArray, NumberOfElements, pOffsetValueArrayA[z], pOffsetValueArrayB[z], 64);
|
||||
z--;
|
||||
|
||||
if (z >= 0) {
|
||||
AntiPredictorOffset(pOutputArray, pInputArray, NumberOfElements, pOffsetValueArrayA[z], pOffsetValueArrayB[z], 64);
|
||||
z--;
|
||||
}
|
||||
else {
|
||||
memcpy(pInputArray, pOutputArray, NumberOfElements * 4);
|
||||
goto Exit_Loop;
|
||||
z--;
|
||||
}
|
||||
}
|
||||
|
||||
Exit_Loop:
|
||||
CAntiPredictorHigh3600To3700 AntiPredictor;
|
||||
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
|
||||
}
|
||||
|
||||
void CAntiPredictorExtraHigh3600To3700::AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g1, int g2, int Max_Order) {
|
||||
int q;
|
||||
|
||||
if ((g1==0) || (g2==0) || (Number_of_Elements <= Max_Order)) {
|
||||
memcpy(Output_Array, Input_Array, Number_of_Elements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(Output_Array, Input_Array, Max_Order * 4);
|
||||
|
||||
int m = 64;
|
||||
int m2 = 64;
|
||||
|
||||
for (q = Max_Order; q < Number_of_Elements; q++) {
|
||||
Output_Array[q] = Input_Array[q] + ((Output_Array[q - g1] * m) >> 9) - ((Output_Array[q - g2] * m2) >> 9);
|
||||
(Input_Array[q] ^ Output_Array[q - g1]) > 0 ? m++ : m--;
|
||||
(Input_Array[q] ^ Output_Array[q - g2]) > 0 ? m2-- : m2++;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high 3700 to 3800 implementation
|
||||
*****************************************************************************************/
|
||||
void CAntiPredictorExtraHigh3700To3800::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, int Iterations, unsigned int *pOffsetValueArrayA, unsigned int *pOffsetValueArrayB) {
|
||||
for (int z = Iterations; z >= 0; ) {
|
||||
|
||||
AntiPredictorOffset(pInputArray, pOutputArray, NumberOfElements, pOffsetValueArrayA[z], pOffsetValueArrayB[z], 64);
|
||||
z--;
|
||||
|
||||
if (z >= 0) {
|
||||
AntiPredictorOffset(pOutputArray, pInputArray, NumberOfElements, pOffsetValueArrayA[z], pOffsetValueArrayB[z], 64);
|
||||
z--;
|
||||
}
|
||||
else {
|
||||
memcpy(pInputArray, pOutputArray, NumberOfElements * 4);
|
||||
goto Exit_Loop;
|
||||
z--;
|
||||
}
|
||||
}
|
||||
|
||||
Exit_Loop:
|
||||
CAntiPredictorHigh3700To3800 AntiPredictor;
|
||||
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
|
||||
|
||||
}
|
||||
|
||||
void CAntiPredictorExtraHigh3700To3800::AntiPredictorOffset(int* Input_Array, int* Output_Array, int Number_of_Elements, int g1, int g2, int Max_Order) {
|
||||
int q;
|
||||
|
||||
if ((g1==0) || (g2==0) || (Number_of_Elements <= Max_Order)) {
|
||||
memcpy(Output_Array, Input_Array, Number_of_Elements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(Output_Array, Input_Array, Max_Order * 4);
|
||||
|
||||
int m = 64;
|
||||
int m2 = 64;
|
||||
|
||||
for (q = Max_Order; q < Number_of_Elements; q++) {
|
||||
Output_Array[q] = Input_Array[q] + ((Output_Array[q - g1] * m) >> 9) - ((Output_Array[q - g2] * m2) >> 9);
|
||||
(Input_Array[q] ^ Output_Array[q - g1]) > 0 ? m++ : m--;
|
||||
(Input_Array[q] ^ Output_Array[q - g2]) > 0 ? m2-- : m2++;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Extra high 3800 to Current
|
||||
*****************************************************************************************/
|
||||
void CAntiPredictorExtraHigh3800ToCurrent::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements, BOOL bMMXAvailable, int CPULoadBalancingFactor, int nVersion)
|
||||
{
|
||||
const int nFilterStageElements = (nVersion < 3830) ? 128 : 256;
|
||||
const int nFilterStageShift = (nVersion < 3830) ? 11 : 12;
|
||||
const int nMaxElements = (nVersion < 3830) ? 134 : 262;
|
||||
const int nFirstElement = (nVersion < 3830) ? 128 : 256;
|
||||
const int nStageCShift = (nVersion < 3830) ? 10 : 11;
|
||||
|
||||
//short frame handling
|
||||
if (NumberOfElements < nMaxElements) {
|
||||
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
//make the first five samples identical in both arrays
|
||||
memcpy(pOutputArray, pInputArray, nFirstElement * 4);
|
||||
|
||||
//variable declares and initializations
|
||||
//short bm[nFirstElement]; memset(bm, 0, nFirstElement * 2);
|
||||
short bm[256]; memset(bm, 0, 256 * 2);
|
||||
int m2 = 64, m3 = 115, m4 = 64, m5 = 740, m6 = 0;
|
||||
int p4 = pInputArray[nFirstElement - 1];
|
||||
int p3 = (pInputArray[nFirstElement - 1] - pInputArray[nFirstElement - 2]) << 1;
|
||||
int p2 = pInputArray[nFirstElement - 1] + ((pInputArray[nFirstElement - 3] - pInputArray[nFirstElement - 2]) << 3);// - pInputArray[3] + pInputArray[2];
|
||||
int *op = &pOutputArray[nFirstElement];
|
||||
int *ip = &pInputArray[nFirstElement];
|
||||
int IPP2 = ip[-2];
|
||||
int IPP1 = ip[-1];
|
||||
int p7 = 2 * ip[-1] - ip[-2];
|
||||
int opp = op[-1];
|
||||
int Original;
|
||||
CAntiPredictorExtraHighHelper Helper;
|
||||
|
||||
//undo the initial prediction stuff
|
||||
int q; // loop variable
|
||||
for (q = 1; q < nFirstElement; q++) {
|
||||
pOutputArray[q] += pOutputArray[q - 1];
|
||||
}
|
||||
|
||||
//pump the primary loop
|
||||
short *IPAdaptFactor = (short *) calloc(NumberOfElements, 2);
|
||||
short *IPShort = (short *) calloc(NumberOfElements, 2);
|
||||
for (q = 0; q < nFirstElement; q++) {
|
||||
IPAdaptFactor[q] = ((pInputArray[q] >> 30) & 2) - 1;
|
||||
IPShort[q] = short(pInputArray[q]);
|
||||
}
|
||||
|
||||
int FM[9]; memset(&FM[0], 0, 9 * 4);
|
||||
int FP[9]; memset(&FP[0], 0, 9 * 4);
|
||||
|
||||
for (q = nFirstElement; op < &pOutputArray[NumberOfElements]; op++, ip++, q++) {
|
||||
//CPU load-balancing
|
||||
if (CPULoadBalancingFactor > 0) {
|
||||
if ((q % CPULoadBalancingFactor) == 0) { SLEEP(1); }
|
||||
}
|
||||
|
||||
if (nVersion >= 3830)
|
||||
{
|
||||
int *pFP = &FP[8];
|
||||
int *pFM = &FM[8];
|
||||
int nDotProduct = 0;
|
||||
FP[0] = ip[0];
|
||||
|
||||
if (FP[0] == 0)
|
||||
{
|
||||
EXPAND_8_TIMES(nDotProduct += *pFP * *pFM--; *pFP-- = *(pFP - 1);)
|
||||
}
|
||||
else if (FP[0] > 0)
|
||||
{
|
||||
EXPAND_8_TIMES(nDotProduct += *pFP * *pFM; *pFM-- += ((*pFP >> 30) & 2) - 1; *pFP-- = *(pFP - 1);)
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPAND_8_TIMES(nDotProduct += *pFP * *pFM; *pFM-- -= ((*pFP >> 30) & 2) - 1; *pFP-- = *(pFP - 1);)
|
||||
}
|
||||
|
||||
*ip -= nDotProduct >> 9;
|
||||
}
|
||||
|
||||
Original = *ip;
|
||||
|
||||
IPShort[q] = short(*ip);
|
||||
IPAdaptFactor[q] = ((ip[0] >> 30) & 2) - 1;
|
||||
|
||||
#ifdef ENABLE_ASSEMBLY
|
||||
if (bMMXAvailable && (Original != 0))
|
||||
{
|
||||
*ip -= (Helper.MMXDotProduct(&IPShort[q-nFirstElement], &bm[0], &IPAdaptFactor[q-nFirstElement], Original, nFilterStageElements) >> nFilterStageShift);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ip -= (Helper.ConventionalDotProduct(&IPShort[q-nFirstElement], &bm[0], &IPAdaptFactor[q-nFirstElement], Original, nFilterStageElements) >> nFilterStageShift);
|
||||
}
|
||||
#else
|
||||
*ip -= (Helper.ConventionalDotProduct(&IPShort[q-nFirstElement], &bm[0], &IPAdaptFactor[q-nFirstElement], Original, nFilterStageElements) >> nFilterStageShift);
|
||||
#endif
|
||||
|
||||
IPShort[q] = short(*ip);
|
||||
IPAdaptFactor[q] = ((ip[0] >> 30) & 2) - 1;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
*op = *ip + (((p2 * m2) + (p3 * m3) + (p4 * m4)) >> 11);
|
||||
|
||||
if (*ip > 0) {
|
||||
m2 -= ((p2 >> 30) & 2) - 1;
|
||||
m3 -= ((p3 >> 28) & 8) - 4;
|
||||
m4 -= ((p4 >> 28) & 8) - 4;
|
||||
}
|
||||
else if (*ip < 0) {
|
||||
m2 += ((p2 >> 30) & 2) - 1;
|
||||
m3 += ((p3 >> 28) & 8) - 4;
|
||||
m4 += ((p4 >> 28) & 8) - 4;
|
||||
}
|
||||
|
||||
|
||||
p2 = *op + ((IPP2 - p4) << 3);
|
||||
p3 = (*op - p4) << 1;
|
||||
IPP2 = p4;
|
||||
p4 = *op;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
*op += (((p7 * m5) - (opp * m6)) >> nStageCShift);
|
||||
|
||||
if (p4 > 0) {
|
||||
m5 -= ((p7 >> 29) & 4) - 2;
|
||||
m6 += ((opp >> 30) & 2) - 1;
|
||||
}
|
||||
else if (p4 < 0) {
|
||||
m5 += ((p7 >> 29) & 4) - 2;
|
||||
m6 -= ((opp >> 30) & 2) - 1;
|
||||
}
|
||||
|
||||
p7 = 2 * *op - opp;
|
||||
opp = *op;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
*op += ((op[-1] * 31) >> 5);
|
||||
|
||||
}
|
||||
|
||||
free(IPAdaptFactor);
|
||||
free(IPShort);
|
||||
}
|
||||
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
|
||||
#endif // #ifdef BACKWARDS_COMPATIBILITY
|
||||
88
MAC_SDK/Source/MACLib/Old/AntiPredictorFast.cpp
Normal file
88
MAC_SDK/Source/MACLib/Old/AntiPredictorFast.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "All.h"
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
#include "Anti-Predictor.h"
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_FAST
|
||||
|
||||
void CAntiPredictorFast0000To3320::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements) {
|
||||
|
||||
//short frame handling
|
||||
if (NumberOfElements < 32) {
|
||||
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
//the initial
|
||||
pOutputArray[0] = pInputArray[0];
|
||||
pOutputArray[1] = pInputArray[1] + pOutputArray[0];
|
||||
pOutputArray[2] = pInputArray[2] + pOutputArray[1];
|
||||
pOutputArray[3] = pInputArray[3] + pOutputArray[2];
|
||||
pOutputArray[4] = pInputArray[4] + pOutputArray[3];
|
||||
pOutputArray[5] = pInputArray[5] + pOutputArray[4];
|
||||
pOutputArray[6] = pInputArray[6] + pOutputArray[5];
|
||||
pOutputArray[7] = pInputArray[7] + pOutputArray[6];
|
||||
|
||||
//the rest
|
||||
int p, pw;
|
||||
int m = 4000;
|
||||
int *ip, *op, *op1;
|
||||
|
||||
op1 = &pOutputArray[7];
|
||||
p = (*op1 * 2) - pOutputArray[6];
|
||||
pw = (p * m) >> 12;
|
||||
|
||||
for (op = &pOutputArray[8], ip = &pInputArray[8]; ip < &pInputArray[NumberOfElements]; ip++, op++, op1++) {
|
||||
*op = *ip + pw;
|
||||
|
||||
|
||||
//adjust m
|
||||
if (*ip > 0)
|
||||
m += (p > 0) ? 4 : -4;
|
||||
else if (*ip < 0)
|
||||
m += (p > 0) ? -4 : 4;
|
||||
|
||||
p = (*op * 2) - *op1;
|
||||
pw = (p * m) >> 12;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
///////note: no output - overwrites input/////////////////
|
||||
void CAntiPredictorFast3320ToCurrent::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements) {
|
||||
|
||||
//short frame handling
|
||||
if (NumberOfElements < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
//variable declares
|
||||
int p;
|
||||
int m = 375;
|
||||
int *ip;
|
||||
int IP2 = pInputArray[1];
|
||||
int IP3 = pInputArray[0];
|
||||
int OP1 = pInputArray[1];
|
||||
|
||||
//the decompression loop (order 2 followed by order 1)
|
||||
for (ip = &pInputArray[2]; ip < &pInputArray[NumberOfElements]; ip++) {
|
||||
|
||||
//make a prediction for order 2
|
||||
p = IP2 + IP2 - IP3;
|
||||
|
||||
//rollback the values
|
||||
IP3 = IP2;
|
||||
IP2 = *ip + ((p * m) >> 9);
|
||||
|
||||
//adjust m for the order 2
|
||||
(*ip ^ p) > 0 ? m++ : m--;
|
||||
|
||||
//set the output value
|
||||
*ip = IP2 + OP1;
|
||||
OP1 = *ip;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_FAST
|
||||
|
||||
#endif // #ifdef BACKWARDS_COMPATIBILITY
|
||||
484
MAC_SDK/Source/MACLib/Old/AntiPredictorHigh.cpp
Normal file
484
MAC_SDK/Source/MACLib/Old/AntiPredictorHigh.cpp
Normal file
@@ -0,0 +1,484 @@
|
||||
#include "All.h"
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
#include "Anti-Predictor.h"
|
||||
|
||||
#ifdef ENABLE_COMPRESSION_MODE_HIGH
|
||||
|
||||
void CAntiPredictorHigh0000To3320::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
|
||||
{
|
||||
// variable declares
|
||||
int p, pw;
|
||||
int q;
|
||||
int m;
|
||||
|
||||
// short frame handling
|
||||
if (NumberOfElements < 32)
|
||||
{
|
||||
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// order 5
|
||||
////////////////////////////////////////
|
||||
memcpy(pOutputArray, pInputArray, 32);
|
||||
|
||||
// initialize values
|
||||
m = 0;
|
||||
|
||||
for (q = 8; q < NumberOfElements; q++)
|
||||
{
|
||||
p = (5 * pOutputArray[q - 1]) - (10 * pOutputArray[q - 2]) + (12 * pOutputArray[q - 3]) - (7 * pOutputArray[q - 4]) + pOutputArray[q - 5];
|
||||
|
||||
pw = (p * m) >> 12;
|
||||
|
||||
pOutputArray[q] = pInputArray[q] + pw;
|
||||
|
||||
// adjust m
|
||||
if (pInputArray[q] > 0)
|
||||
(p > 0) ? m += 1 : m -= 1;
|
||||
else if (pInputArray[q] < 0)
|
||||
(p > 0) ? m -= 1 : m += 1;
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// order 4
|
||||
///////////////////////////////////////
|
||||
memcpy(pInputArray, pOutputArray, 32);
|
||||
m = 0;
|
||||
|
||||
for (q = 8; q < NumberOfElements; q++)
|
||||
{
|
||||
p = (4 * pInputArray[q - 1]) - (6 * pInputArray[q - 2]) + (4 * pInputArray[q - 3]) - pInputArray[q - 4];
|
||||
pw = (p * m) >> 12;
|
||||
|
||||
pInputArray[q] = pOutputArray[q] + pw;
|
||||
|
||||
// adjust m
|
||||
if (pOutputArray[q] > 0)
|
||||
(p > 0) ? m += 2 : m -= 2;
|
||||
else if (pOutputArray[q] < 0)
|
||||
(p > 0) ? m -= 2 : m += 2;
|
||||
}
|
||||
|
||||
CAntiPredictorNormal0000To3320 AntiPredictor;
|
||||
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
|
||||
}
|
||||
|
||||
void CAntiPredictorHigh3320To3600::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
|
||||
{
|
||||
// short frame handling
|
||||
if (NumberOfElements < 8)
|
||||
{
|
||||
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
// do the offset anti-prediction
|
||||
CAntiPredictorOffset AntiPredictorOffset;
|
||||
AntiPredictorOffset.AntiPredict(pInputArray, pOutputArray, NumberOfElements, 2, 12);
|
||||
AntiPredictorOffset.AntiPredict(pOutputArray, pInputArray, NumberOfElements, 3, 12);
|
||||
|
||||
AntiPredictorOffset.AntiPredict(pInputArray, pOutputArray, NumberOfElements, 4, 12);
|
||||
AntiPredictorOffset.AntiPredict(pOutputArray, pInputArray, NumberOfElements, 5, 12);
|
||||
|
||||
AntiPredictorOffset.AntiPredict(pInputArray, pOutputArray, NumberOfElements, 6, 12);
|
||||
AntiPredictorOffset.AntiPredict(pOutputArray, pInputArray, NumberOfElements, 7, 12);
|
||||
|
||||
// use the normal mode
|
||||
CAntiPredictorNormal3320To3800 AntiPredictor;
|
||||
AntiPredictor.AntiPredict(pInputArray, pOutputArray, NumberOfElements);
|
||||
}
|
||||
|
||||
void CAntiPredictorHigh3600To3700::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
|
||||
{
|
||||
// variable declares
|
||||
int q;
|
||||
|
||||
// short frame handling
|
||||
if (NumberOfElements < 16)
|
||||
{
|
||||
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
// make the first five samples identical in both arrays
|
||||
memcpy(pOutputArray, pInputArray, 13 * 4);
|
||||
|
||||
// initialize values
|
||||
int bm1 = 0;
|
||||
int bm2 = 0;
|
||||
int bm3 = 0;
|
||||
int bm4 = 0;
|
||||
int bm5 = 0;
|
||||
int bm6 = 0;
|
||||
int bm7 = 0;
|
||||
int bm8 = 0;
|
||||
int bm9 = 0;
|
||||
int bm10 = 0;
|
||||
int bm11 = 0;
|
||||
int bm12 = 0;
|
||||
int bm13 = 0;
|
||||
|
||||
int m2 = 64;
|
||||
|
||||
int m3 = 28;
|
||||
int m4 = 16;
|
||||
int OP0;
|
||||
int OP1 = pOutputArray[12];
|
||||
int p4 = pInputArray[12];
|
||||
int p3 = (pInputArray[12] - pInputArray[11]) << 1;
|
||||
int p2 = pInputArray[12] + ((pInputArray[10] - pInputArray[11]) << 3);// - pInputArray[3] + pInputArray[2];
|
||||
int bp1 = pOutputArray[12];
|
||||
int bp2 = pOutputArray[11];
|
||||
int bp3 = pOutputArray[10];
|
||||
int bp4 = pOutputArray[9];
|
||||
int bp5 = pOutputArray[8];
|
||||
int bp6 = pOutputArray[7];
|
||||
int bp7 = pOutputArray[6];
|
||||
int bp8 = pOutputArray[5];
|
||||
int bp9 = pOutputArray[4];
|
||||
int bp10 = pOutputArray[3];
|
||||
int bp11 = pOutputArray[2];
|
||||
int bp12 = pOutputArray[1];
|
||||
int bp13 = pOutputArray[0];
|
||||
|
||||
for (q = 13; q < NumberOfElements; q++)
|
||||
{
|
||||
pInputArray[q] = pInputArray[q] - 1;
|
||||
OP0 = (pInputArray[q] - ((bp1 * bm1) >> 8) + ((bp2 * bm2) >> 8) - ((bp3 * bm3) >> 8) - ((bp4 * bm4) >> 8) - ((bp5 * bm5) >> 8) - ((bp6 * bm6) >> 8) - ((bp7 * bm7) >> 8) - ((bp8 * bm8) >> 8) - ((bp9 * bm9) >> 8) + ((bp10 * bm10) >> 8) + ((bp11 * bm11) >> 8) + ((bp12 * bm12) >> 8) + ((bp13 * bm13) >> 8));
|
||||
|
||||
if (pInputArray[q] > 0)
|
||||
{
|
||||
bm1 -= bp1 > 0 ? 1 : -1;
|
||||
bm2 += bp2 >= 0 ? 1 : -1;
|
||||
bm3 -= bp3 > 0 ? 1 : -1;
|
||||
bm4 -= bp4 >= 0 ? 1 : -1;
|
||||
bm5 -= bp5 > 0 ? 1 : -1;
|
||||
bm6 -= bp6 >= 0 ? 1 : -1;
|
||||
bm7 -= bp7 > 0 ? 1 : -1;
|
||||
bm8 -= bp8 >= 0 ? 1 : -1;
|
||||
bm9 -= bp9 > 0 ? 1 : -1;
|
||||
bm10 += bp10 >= 0 ? 1 : -1;
|
||||
bm11 += bp11 > 0 ? 1 : -1;
|
||||
bm12 += bp12 >= 0 ? 1 : -1;
|
||||
bm13 += bp13 > 0 ? 1 : -1;
|
||||
}
|
||||
else if (pInputArray[q] < 0)
|
||||
{
|
||||
bm1 -= bp1 <= 0 ? 1 : -1;
|
||||
bm2 += bp2 < 0 ? 1 : -1;
|
||||
bm3 -= bp3 <= 0 ? 1 : -1;
|
||||
bm4 -= bp4 < 0 ? 1 : -1;
|
||||
bm5 -= bp5 <= 0 ? 1 : -1;
|
||||
bm6 -= bp6 < 0 ? 1 : -1;
|
||||
bm7 -= bp7 <= 0 ? 1 : -1;
|
||||
bm8 -= bp8 < 0 ? 1 : -1;
|
||||
bm9 -= bp9 <= 0 ? 1 : -1;
|
||||
bm10 += bp10 < 0 ? 1 : -1;
|
||||
bm11 += bp11 <= 0 ? 1 : -1;
|
||||
bm12 += bp12 < 0 ? 1 : -1;
|
||||
bm13 += bp13 <= 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
bp13 = bp12;
|
||||
bp12 = bp11;
|
||||
bp11 = bp10;
|
||||
bp10 = bp9;
|
||||
bp9 = bp8;
|
||||
bp8 = bp7;
|
||||
bp7 = bp6;
|
||||
bp6 = bp5;
|
||||
bp5 = bp4;
|
||||
bp4 = bp3;
|
||||
bp3 = bp2;
|
||||
bp2 = bp1;
|
||||
bp1 = OP0;
|
||||
|
||||
pInputArray[q] = OP0 + ((p2 * m2) >> 11) + ((p3 * m3) >> 9) + ((p4 * m4) >> 9);
|
||||
|
||||
if (OP0 > 0)
|
||||
{
|
||||
m2 -= p2 > 0 ? -1 : 1;
|
||||
m3 -= p3 > 0 ? -1 : 1;
|
||||
m4 -= p4 > 0 ? -1 : 1;
|
||||
}
|
||||
else if (OP0 < 0)
|
||||
{
|
||||
m2 -= p2 > 0 ? 1 : -1;
|
||||
m3 -= p3 > 0 ? 1 : -1;
|
||||
m4 -= p4 > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
p2 = pInputArray[q] + ((pInputArray[q - 2] - pInputArray[q - 1]) << 3);
|
||||
p3 = (pInputArray[q] - pInputArray[q - 1]) << 1;
|
||||
p4 = pInputArray[q];
|
||||
pOutputArray[q] = pInputArray[q];// + ((p3 * m3) >> 9);
|
||||
}
|
||||
|
||||
m4 = 370;
|
||||
int m5 = 3900;
|
||||
|
||||
pOutputArray[1] = pInputArray[1] + pOutputArray[0];
|
||||
pOutputArray[2] = pInputArray[2] + pOutputArray[1];
|
||||
pOutputArray[3] = pInputArray[3] + pOutputArray[2];
|
||||
pOutputArray[4] = pInputArray[4] + pOutputArray[3];
|
||||
pOutputArray[5] = pInputArray[5] + pOutputArray[4];
|
||||
pOutputArray[6] = pInputArray[6] + pOutputArray[5];
|
||||
pOutputArray[7] = pInputArray[7] + pOutputArray[6];
|
||||
pOutputArray[8] = pInputArray[8] + pOutputArray[7];
|
||||
pOutputArray[9] = pInputArray[9] + pOutputArray[8];
|
||||
pOutputArray[10] = pInputArray[10] + pOutputArray[9];
|
||||
pOutputArray[11] = pInputArray[11] + pOutputArray[10];
|
||||
pOutputArray[12] = pInputArray[12] + pOutputArray[11];
|
||||
|
||||
p4 = (2 * pInputArray[12]) - pInputArray[11];
|
||||
int p6 = 0;
|
||||
int p5 = pOutputArray[12];
|
||||
int IP0, IP1;
|
||||
int m6 = 0;
|
||||
|
||||
IP1 = pInputArray[12];
|
||||
for (q = 13; q < NumberOfElements; q++)
|
||||
{
|
||||
IP0 = pOutputArray[q] + ((p4 * m4) >> 9) - ((p6 * m6) >> 10);
|
||||
(pOutputArray[q] ^ p4) >= 0 ? m4++ : m4--;
|
||||
(pOutputArray[q] ^ p6) >= 0 ? m6-- : m6++;
|
||||
p4 = (2 * IP0) - IP1;
|
||||
p6 = IP0;
|
||||
|
||||
pOutputArray[q] = IP0 + ((p5 * 31) >> 5);
|
||||
p5 = pOutputArray[q];
|
||||
|
||||
IP1 = IP0;
|
||||
}
|
||||
}
|
||||
|
||||
void CAntiPredictorHigh3700To3800::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
|
||||
{
|
||||
// the frame to start prediction on
|
||||
#define FIRST_ELEMENT 16
|
||||
|
||||
int x = 100;
|
||||
int y = -25;
|
||||
|
||||
// short frame handling
|
||||
if (NumberOfElements < 20)
|
||||
{
|
||||
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
// make the first five samples identical in both arrays
|
||||
memcpy(pOutputArray, pInputArray, FIRST_ELEMENT * 4);
|
||||
|
||||
// variable declares and initializations
|
||||
int bm[FIRST_ELEMENT]; memset(bm, 0, FIRST_ELEMENT * 4);
|
||||
int m2 = 64, m3 = 115, m4 = 64, m5 = 740, m6 = 0;
|
||||
int p4 = pInputArray[FIRST_ELEMENT - 1];
|
||||
int p3 = (pInputArray[FIRST_ELEMENT - 1] - pInputArray[FIRST_ELEMENT - 2]) << 1;
|
||||
int p2 = pInputArray[FIRST_ELEMENT - 1] + ((pInputArray[FIRST_ELEMENT - 3] - pInputArray[FIRST_ELEMENT - 2]) << 3);// - pInputArray[3] + pInputArray[2];
|
||||
int *op = &pOutputArray[FIRST_ELEMENT];
|
||||
int *ip = &pInputArray[FIRST_ELEMENT];
|
||||
int IPP2 = ip[-2];
|
||||
int IPP1 = ip[-1];
|
||||
int p7 = 2 * ip[-1] - ip[-2];
|
||||
int opp = op[-1];
|
||||
int Original;
|
||||
|
||||
// undo the initial prediction stuff
|
||||
for (int q = 1; q < FIRST_ELEMENT; q++) {
|
||||
pOutputArray[q] += pOutputArray[q - 1];
|
||||
}
|
||||
|
||||
// pump the primary loop
|
||||
for (;op < &pOutputArray[NumberOfElements]; op++, ip++) {
|
||||
|
||||
Original = *ip - 1;
|
||||
*ip = Original - (((ip[-1] * bm[0]) + (ip[-2] * bm[1]) + (ip[-3] * bm[2]) + (ip[-4] * bm[3]) + (ip[-5] * bm[4]) + (ip[-6] * bm[5]) + (ip[-7] * bm[6]) + (ip[-8] * bm[7]) + (ip[-9] * bm[8]) + (ip[-10] * bm[9]) + (ip[-11] * bm[10]) + (ip[-12] * bm[11]) + (ip[-13] * bm[12]) + (ip[-14] * bm[13]) + (ip[-15] * bm[14]) + (ip[-16] * bm[15])) >> 8);
|
||||
|
||||
if (Original > 0)
|
||||
{
|
||||
bm[0] -= ip[-1] > 0 ? 1 : -1;
|
||||
bm[1] += ((unsigned int(ip[-2]) >> 30) & 2) - 1;
|
||||
bm[2] -= ip[-3] > 0 ? 1 : -1;
|
||||
bm[3] += ((unsigned int(ip[-4]) >> 30) & 2) - 1;
|
||||
bm[4] -= ip[-5] > 0 ? 1 : -1;
|
||||
bm[5] += ((unsigned int(ip[-6]) >> 30) & 2) - 1;
|
||||
bm[6] -= ip[-7] > 0 ? 1 : -1;
|
||||
bm[7] += ((unsigned int(ip[-8]) >> 30) & 2) - 1;
|
||||
bm[8] -= ip[-9] > 0 ? 1 : -1;
|
||||
bm[9] += ((unsigned int(ip[-10]) >> 30) & 2) - 1;
|
||||
bm[10] -= ip[-11] > 0 ? 1 : -1;
|
||||
bm[11] += ((unsigned int(ip[-12]) >> 30) & 2) - 1;
|
||||
bm[12] -= ip[-13] > 0 ? 1 : -1;
|
||||
bm[13] += ((unsigned int(ip[-14]) >> 30) & 2) - 1;
|
||||
bm[14] -= ip[-15] > 0 ? 1 : -1;
|
||||
bm[15] += ((unsigned int(ip[-16]) >> 30) & 2) - 1;
|
||||
}
|
||||
else if (Original < 0)
|
||||
{
|
||||
bm[0] -= ip[-1] <= 0 ? 1 : -1;
|
||||
bm[1] -= ((unsigned int(ip[-2]) >> 30) & 2) - 1;
|
||||
bm[2] -= ip[-3] <= 0 ? 1 : -1;
|
||||
bm[3] -= ((unsigned int(ip[-4]) >> 30) & 2) - 1;
|
||||
bm[4] -= ip[-5] <= 0 ? 1 : -1;
|
||||
bm[5] -= ((unsigned int(ip[-6]) >> 30) & 2) - 1;
|
||||
bm[6] -= ip[-7] <= 0 ? 1 : -1;
|
||||
bm[7] -= ((unsigned int(ip[-8]) >> 30) & 2) - 1;
|
||||
bm[8] -= ip[-9] <= 0 ? 1 : -1;
|
||||
bm[9] -= ((unsigned int(ip[-10]) >> 30) & 2) - 1;
|
||||
bm[10] -= ip[-11] <= 0 ? 1 : -1;
|
||||
bm[11] -= ((unsigned int(ip[-12]) >> 30) & 2) - 1;
|
||||
bm[12] -= ip[-13] <= 0 ? 1 : -1;
|
||||
bm[13] -= ((unsigned int(ip[-14]) >> 30) & 2) - 1;
|
||||
bm[14] -= ip[-15] <= 0 ? 1 : -1;
|
||||
bm[15] -= ((unsigned int(ip[-16]) >> 30) & 2) - 1;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
*op = *ip + (((p2 * m2) + (p3 * m3) + (p4 * m4)) >> 11);
|
||||
|
||||
if (*ip > 0)
|
||||
{
|
||||
m2 -= p2 > 0 ? -1 : 1;
|
||||
m3 -= p3 > 0 ? -4 : 4;
|
||||
m4 -= p4 > 0 ? -4 : 4;
|
||||
}
|
||||
else if (*ip < 0)
|
||||
{
|
||||
m2 -= p2 > 0 ? 1 : -1;
|
||||
m3 -= p3 > 0 ? 4 : -4;
|
||||
m4 -= p4 > 0 ? 4 : -4;
|
||||
}
|
||||
|
||||
p4 = *op;
|
||||
p2 = p4 + ((IPP2 - IPP1) << 3);
|
||||
p3 = (p4 - IPP1) << 1;
|
||||
|
||||
IPP2 = IPP1;
|
||||
IPP1 = p4;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
*op += (((p7 * m5) - (opp * m6)) >> 10);
|
||||
|
||||
(IPP1 ^ p7) >= 0 ? m5+=2 : m5-=2;
|
||||
(IPP1 ^ opp) >= 0 ? m6-- : m6++;
|
||||
|
||||
p7 = 2 * *op - opp;
|
||||
opp = *op;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
*op += ((op[-1] * 31) >> 5);
|
||||
}
|
||||
}
|
||||
|
||||
void CAntiPredictorHigh3800ToCurrent::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
|
||||
{
|
||||
// the frame to start prediction on
|
||||
#define FIRST_ELEMENT 16
|
||||
|
||||
// short frame handling
|
||||
if (NumberOfElements < 20)
|
||||
{
|
||||
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
// make the first five samples identical in both arrays
|
||||
memcpy(pOutputArray, pInputArray, FIRST_ELEMENT * 4);
|
||||
|
||||
// variable declares and initializations
|
||||
int bm[FIRST_ELEMENT]; memset(bm, 0, FIRST_ELEMENT * 4);
|
||||
int m2 = 64, m3 = 115, m4 = 64, m5 = 740, m6 = 0;
|
||||
int p4 = pInputArray[FIRST_ELEMENT - 1];
|
||||
int p3 = (pInputArray[FIRST_ELEMENT - 1] - pInputArray[FIRST_ELEMENT - 2]) << 1;
|
||||
int p2 = pInputArray[FIRST_ELEMENT - 1] + ((pInputArray[FIRST_ELEMENT - 3] - pInputArray[FIRST_ELEMENT - 2]) << 3);// - pInputArray[3] + pInputArray[2];
|
||||
int *op = &pOutputArray[FIRST_ELEMENT];
|
||||
int *ip = &pInputArray[FIRST_ELEMENT];
|
||||
int IPP2 = ip[-2];
|
||||
int IPP1 = ip[-1];
|
||||
int p7 = 2 * ip[-1] - ip[-2];
|
||||
int opp = op[-1];
|
||||
|
||||
// undo the initial prediction stuff
|
||||
for (int q = 1; q < FIRST_ELEMENT; q++)
|
||||
{
|
||||
pOutputArray[q] += pOutputArray[q - 1];
|
||||
}
|
||||
|
||||
// pump the primary loop
|
||||
for (;op < &pOutputArray[NumberOfElements]; op++, ip++)
|
||||
{
|
||||
|
||||
unsigned int *pip = (unsigned int *) &ip[-FIRST_ELEMENT];
|
||||
int *pbm = &bm[0];
|
||||
int nDotProduct = 0;
|
||||
|
||||
if (*ip > 0)
|
||||
{
|
||||
EXPAND_16_TIMES(nDotProduct += *pip * *pbm; *pbm++ += ((*pip++ >> 30) & 2) - 1;)
|
||||
}
|
||||
else if (*ip < 0)
|
||||
{
|
||||
EXPAND_16_TIMES(nDotProduct += *pip * *pbm; *pbm++ -= ((*pip++ >> 30) & 2) - 1;)
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPAND_16_TIMES(nDotProduct += *pip++ * *pbm++;)
|
||||
}
|
||||
|
||||
*ip -= (nDotProduct >> 9);
|
||||
|
||||
/////////////////////////////////////////////
|
||||
*op = *ip + (((p2 * m2) + (p3 * m3) + (p4 * m4)) >> 11);
|
||||
|
||||
if (*ip > 0)
|
||||
{
|
||||
m2 -= ((p2 >> 30) & 2) - 1;
|
||||
m3 -= ((p3 >> 28) & 8) - 4;
|
||||
m4 -= ((p4 >> 28) & 8) - 4;
|
||||
|
||||
}
|
||||
else if (*ip < 0)
|
||||
{
|
||||
m2 += ((p2 >> 30) & 2) - 1;
|
||||
m3 += ((p3 >> 28) & 8) - 4;
|
||||
m4 += ((p4 >> 28) & 8) - 4;
|
||||
}
|
||||
|
||||
|
||||
p2 = *op + ((IPP2 - p4) << 3);
|
||||
p3 = (*op - p4) << 1;
|
||||
IPP2 = p4;
|
||||
p4 = *op;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
*op += (((p7 * m5) - (opp * m6)) >> 10);
|
||||
|
||||
if (p4 > 0)
|
||||
{
|
||||
m5 -= ((p7 >> 29) & 4) - 2;
|
||||
m6 += ((opp >> 30) & 2) - 1;
|
||||
}
|
||||
else if (p4 < 0)
|
||||
{
|
||||
m5 += ((p7 >> 29) & 4) - 2;
|
||||
m6 -= ((opp >> 30) & 2) - 1;
|
||||
}
|
||||
|
||||
p7 = 2 * *op - opp;
|
||||
opp = *op;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
*op += ((op[-1] * 31) >> 5);
|
||||
}
|
||||
|
||||
#undef FIRST_ELEMENT
|
||||
}
|
||||
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_HIGH
|
||||
|
||||
#endif // #ifdef BACKWARDS_COMPATIBILITY
|
||||
262
MAC_SDK/Source/MACLib/Old/AntiPredictorNormal.cpp
Normal file
262
MAC_SDK/Source/MACLib/Old/AntiPredictorNormal.cpp
Normal file
@@ -0,0 +1,262 @@
|
||||
#include "All.h"
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
#include "Anti-Predictor.h"
|
||||
#ifdef ENABLE_COMPRESSION_MODE_NORMAL
|
||||
|
||||
void CAntiPredictorNormal0000To3320::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
|
||||
{
|
||||
// variable declares
|
||||
int *ip, *op, *op1, *op2;
|
||||
int p, pw;
|
||||
int m;
|
||||
|
||||
// short frame handling
|
||||
if (NumberOfElements < 32)
|
||||
{
|
||||
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// order 3
|
||||
////////////////////////////////////////
|
||||
memcpy(pOutputArray, pInputArray, 32);
|
||||
|
||||
// initialize values
|
||||
m = 300;
|
||||
op = &pOutputArray[8];
|
||||
op1 = &pOutputArray[7];
|
||||
op2 = &pOutputArray[6];
|
||||
|
||||
// make the first prediction
|
||||
p = (pOutputArray[7] * 3) - (pOutputArray[6] * 3) + pOutputArray[5];
|
||||
pw = (p * m) >> 12;
|
||||
|
||||
// loop through the array
|
||||
for (ip = &pInputArray[8]; ip < &pInputArray[NumberOfElements]; ip++, op++, op1++, op2++) {
|
||||
|
||||
// figure the output value
|
||||
*op = *ip + pw;
|
||||
|
||||
// adjust m
|
||||
if (*ip > 0)
|
||||
m += (p > 0) ? 4 : -4;
|
||||
else if (*ip < 0)
|
||||
m += (p > 0) ? -4 : 4;
|
||||
|
||||
// make the next prediction
|
||||
p = (*op * 3) - (*op1 * 3) + *op2;
|
||||
pw = (p * m) >> 12;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// order 2
|
||||
///////////////////////////////////////
|
||||
memcpy(pInputArray, pOutputArray, 32);
|
||||
m = 3000;
|
||||
|
||||
op1 = &pInputArray[7];
|
||||
p = (*op1 * 2) - pInputArray[6];
|
||||
pw = (p * m) >> 12;
|
||||
|
||||
for (op = &pInputArray[8], ip = &pOutputArray[8]; ip < &pOutputArray[NumberOfElements]; ip++, op++, op1++)
|
||||
{
|
||||
*op = *ip + pw;
|
||||
|
||||
// adjust m
|
||||
if (*ip > 0)
|
||||
m += (p > 0) ? 12 : -12;
|
||||
else if (*ip < 0)
|
||||
m += (p > 0) ? -12 : 12;
|
||||
|
||||
p = (*op * 2) - *op1;
|
||||
pw = (p * m) >> 12;
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// order 1
|
||||
///////////////////////////////////////
|
||||
pOutputArray[0] = pInputArray[0];
|
||||
pOutputArray[1] = pInputArray[1] + pOutputArray[0];
|
||||
pOutputArray[2] = pInputArray[2] + pOutputArray[1];
|
||||
pOutputArray[3] = pInputArray[3] + pOutputArray[2];
|
||||
pOutputArray[4] = pInputArray[4] + pOutputArray[3];
|
||||
pOutputArray[5] = pInputArray[5] + pOutputArray[4];
|
||||
pOutputArray[6] = pInputArray[6] + pOutputArray[5];
|
||||
pOutputArray[7] = pInputArray[7] + pOutputArray[6];
|
||||
|
||||
m = 3900;
|
||||
|
||||
p = pOutputArray[7];
|
||||
pw = (p * m) >> 12;
|
||||
|
||||
for (op = &pOutputArray[8], ip = &pInputArray[8]; ip < &pInputArray[NumberOfElements]; ip++, op++) {
|
||||
*op = *ip + pw;
|
||||
|
||||
// adjust m
|
||||
if (*ip > 0)
|
||||
m += (p > 0) ? 1 : -1;
|
||||
else if (*ip < 0)
|
||||
m += (p > 0) ? -1 : 1;
|
||||
|
||||
p = *op;
|
||||
pw = (p * m) >> 12;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CAntiPredictorNormal3320To3800::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
|
||||
{
|
||||
// variable declares
|
||||
int q;
|
||||
|
||||
// short frame handling
|
||||
if (NumberOfElements < 8)
|
||||
{
|
||||
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
// make the first five samples identical in both arrays
|
||||
memcpy(pOutputArray, pInputArray, 20);
|
||||
|
||||
// initialize values
|
||||
int m1 = 0;
|
||||
int m2 = 64;
|
||||
int m3 = 28;
|
||||
int OP0;
|
||||
int OP1 = pOutputArray[4];
|
||||
|
||||
int p3 = (3 * (pOutputArray[4] - pOutputArray[3])) + pOutputArray[2];
|
||||
int p2 = pInputArray[4] + ((pInputArray[2] - pInputArray[3]) << 3) - pInputArray[1] + pInputArray[0];
|
||||
int p1 = pOutputArray[4];
|
||||
|
||||
for (q = 5; q < NumberOfElements; q++)
|
||||
{
|
||||
OP0 = pInputArray[q] + ((p1 * m1) >> 8);
|
||||
(pInputArray[q] ^ p1) > 0 ? m1++ : m1--;
|
||||
p1 = OP0;
|
||||
|
||||
pInputArray[q] = OP0 + ((p2 * m2) >> 11);
|
||||
(OP0 ^ p2) > 0 ? m2++ : m2--;
|
||||
p2 = pInputArray[q] + ((pInputArray[q - 2] - pInputArray[q - 1]) << 3) - pInputArray[q - 3] + pInputArray[q - 4];
|
||||
|
||||
pOutputArray[q] = pInputArray[q] + ((p3 * m3) >> 9);
|
||||
(pInputArray[q] ^ p3) > 0 ? m3++ : m3--;
|
||||
p3 = (3 * (pOutputArray[q] - pOutputArray[q - 1])) + pOutputArray[q - 2];
|
||||
}
|
||||
|
||||
int m4 = 370;
|
||||
int m5 = 3900;
|
||||
|
||||
pOutputArray[1] = pInputArray[1] + pOutputArray[0];
|
||||
pOutputArray[2] = pInputArray[2] + pOutputArray[1];
|
||||
pOutputArray[3] = pInputArray[3] + pOutputArray[2];
|
||||
pOutputArray[4] = pInputArray[4] + pOutputArray[3];
|
||||
|
||||
int p4 = (2 * pInputArray[4]) - pInputArray[3];
|
||||
int p5 = pOutputArray[4];
|
||||
int IP0, IP1;
|
||||
|
||||
IP1 = pInputArray[4];
|
||||
for (q = 5; q < NumberOfElements; q++)
|
||||
{
|
||||
IP0 = pOutputArray[q] + ((p4 * m4) >> 9);
|
||||
(pOutputArray[q] ^ p4) > 0 ? m4++ : m4--;
|
||||
p4 = (2 * IP0) - IP1;
|
||||
|
||||
pOutputArray[q] = IP0 + ((p5 * m5) >> 12);
|
||||
(IP0 ^ p5) > 0 ? m5++ : m5--;
|
||||
p5 = pOutputArray[q];
|
||||
|
||||
IP1 = IP0;
|
||||
}
|
||||
}
|
||||
|
||||
void CAntiPredictorNormal3800ToCurrent::AntiPredict(int *pInputArray, int *pOutputArray, int NumberOfElements)
|
||||
{
|
||||
// the frame to start prediction on
|
||||
#define FIRST_ELEMENT 4
|
||||
|
||||
// short frame handling
|
||||
if (NumberOfElements < 8)
|
||||
{
|
||||
memcpy(pOutputArray, pInputArray, NumberOfElements * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
// make the first five samples identical in both arrays
|
||||
memcpy(pOutputArray, pInputArray, FIRST_ELEMENT * 4);
|
||||
|
||||
// variable declares and initializations
|
||||
int m2 = 64, m3 = 115, m4 = 64, m5 = 740, m6 = 0;
|
||||
int p4 = pInputArray[FIRST_ELEMENT - 1];
|
||||
int p3 = (pInputArray[FIRST_ELEMENT - 1] - pInputArray[FIRST_ELEMENT - 2]) << 1;
|
||||
int p2 = pInputArray[FIRST_ELEMENT - 1] + ((pInputArray[FIRST_ELEMENT - 3] - pInputArray[FIRST_ELEMENT - 2]) << 3);// - pInputArray[3] + pInputArray[2];
|
||||
int *op = &pOutputArray[FIRST_ELEMENT];
|
||||
int *ip = &pInputArray[FIRST_ELEMENT];
|
||||
int IPP2 = ip[-2];
|
||||
int p7 = 2 * ip[-1] - ip[-2];
|
||||
int opp = op[-1];
|
||||
|
||||
// undo the initial prediction stuff
|
||||
for (int q = 1; q < FIRST_ELEMENT; q++) {
|
||||
pOutputArray[q] += pOutputArray[q - 1];
|
||||
}
|
||||
|
||||
// pump the primary loop
|
||||
for (; op < &pOutputArray[NumberOfElements]; op++, ip++) {
|
||||
|
||||
register int o = *op, i = *ip;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
o = i + (((p2 * m2) + (p3 * m3) + (p4 * m4)) >> 11);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
m2 -= ((p2 >> 30) & 2) - 1;
|
||||
m3 -= ((p3 >> 28) & 8) - 4;
|
||||
m4 -= ((p4 >> 28) & 8) - 4;
|
||||
|
||||
}
|
||||
else if (i < 0)
|
||||
{
|
||||
m2 += ((p2 >> 30) & 2) - 1;
|
||||
m3 += ((p3 >> 28) & 8) - 4;
|
||||
m4 += ((p4 >> 28) & 8) - 4;
|
||||
}
|
||||
|
||||
|
||||
p2 = o + ((IPP2 - p4) << 3);
|
||||
p3 = (o - p4) << 1;
|
||||
IPP2 = p4;
|
||||
p4 = o;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
o += (((p7 * m5) - (opp * m6)) >> 10);
|
||||
|
||||
if (p4 > 0)
|
||||
{
|
||||
m5 -= ((p7 >> 29) & 4) - 2;
|
||||
m6 += ((opp >> 30) & 2) - 1;
|
||||
}
|
||||
else if (p4 < 0)
|
||||
{
|
||||
m5 += ((p7 >> 29) & 4) - 2;
|
||||
m6 -= ((opp >> 30) & 2) - 1;
|
||||
}
|
||||
|
||||
p7 = 2 * o - opp;
|
||||
opp = o;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
*op = o + ((op[-1] * 31) >> 5);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef ENABLE_COMPRESSION_MODE_NORMAL
|
||||
|
||||
#endif // #ifdef BACKWARDS_COMPATIBILITY
|
||||
353
MAC_SDK/Source/MACLib/Old/UnBitArrayOld.cpp
Normal file
353
MAC_SDK/Source/MACLib/Old/UnBitArrayOld.cpp
Normal file
@@ -0,0 +1,353 @@
|
||||
#include "All.h"
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
#include "../APEInfo.h"
|
||||
#include "UnBitarrayOld.h"
|
||||
#include "../BitArray.h"
|
||||
|
||||
const uint32 K_SUM_MIN_BOUNDARY_OLD[32] = {0,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,0,0,0,0,0,0};
|
||||
const uint32 K_SUM_MAX_BOUNDARY_OLD[32] = {128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,0,0,0,0,0,0,0};
|
||||
const uint32 Powers_of_Two[32] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648};
|
||||
const uint32 Powers_of_Two_Reversed[32] = {2147483648,1073741824,536870912,268435456,134217728,67108864,33554432,16777216,8388608,4194304,2097152,1048576,524288,262144,131072,65536,32768,16384,8192,4096,2048,1024,512,256,128,64,32,16,8,4,2,1};
|
||||
const uint32 Powers_of_Two_Minus_One[33] = {0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535,131071,262143,524287,1048575,2097151,4194303,8388607,16777215,33554431,67108863,134217727,268435455,536870911,1073741823,2147483647,4294967295};
|
||||
const uint32 Powers_of_Two_Minus_One_Reversed[33] = {4294967295,2147483647,1073741823,536870911,268435455,134217727,67108863,33554431,16777215,8388607,4194303,2097151,1048575,524287,262143,131071,65535,32767,16383,8191,4095,2047,1023,511,255,127,63,31,15,7,3,1,0};
|
||||
|
||||
const uint32 K_SUM_MIN_BOUNDARY[32] = {0,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,0,0,0,0};
|
||||
const uint32 K_SUM_MAX_BOUNDARY[32] = {32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,0,0,0,0,0};
|
||||
|
||||
/***********************************************************************************
|
||||
Construction
|
||||
***********************************************************************************/
|
||||
CUnBitArrayOld::CUnBitArrayOld(IAPEDecompress * pAPEDecompress, int nVersion)
|
||||
{
|
||||
int nBitArrayBytes = 262144;
|
||||
|
||||
// calculate the bytes
|
||||
if (nVersion <= 3880)
|
||||
{
|
||||
int nMaxFrameBytes = (pAPEDecompress->GetInfo(APE_INFO_BLOCKS_PER_FRAME) * 50) / 8;
|
||||
nBitArrayBytes = 65536;
|
||||
while (nBitArrayBytes < nMaxFrameBytes)
|
||||
{
|
||||
nBitArrayBytes <<= 1;
|
||||
}
|
||||
|
||||
nBitArrayBytes = max(nBitArrayBytes, 262144);
|
||||
}
|
||||
else if (nVersion <= 3890)
|
||||
{
|
||||
nBitArrayBytes = 65536;
|
||||
}
|
||||
else
|
||||
{
|
||||
// error
|
||||
}
|
||||
|
||||
CreateHelper(GET_IO(pAPEDecompress), nBitArrayBytes, nVersion);
|
||||
|
||||
// set the refill threshold
|
||||
if (m_nVersion <= 3880)
|
||||
m_nRefillBitThreshold = (m_nBits - (16384 * 8));
|
||||
else
|
||||
m_nRefillBitThreshold = (m_nBits - 512);
|
||||
}
|
||||
|
||||
CUnBitArrayOld::~CUnBitArrayOld()
|
||||
{
|
||||
SAFE_ARRAY_DELETE(m_pBitArray)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Gets the number of m_nBits of data left in the m_nCurrentBitIndex array
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
uint32 CUnBitArrayOld::GetBitsRemaining()
|
||||
{
|
||||
return (m_nElements * 32 - m_nCurrentBitIndex);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Gets a rice value from the array
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
uint32 CUnBitArrayOld::DecodeValueRiceUnsigned(uint32 k)
|
||||
{
|
||||
// variable declares
|
||||
uint32 v;
|
||||
|
||||
// plug through the string of 0's (the overflow)
|
||||
uint32 BitInitial = m_nCurrentBitIndex;
|
||||
while (!(m_pBitArray[m_nCurrentBitIndex >> 5] & Powers_of_Two_Reversed[m_nCurrentBitIndex++ & 31])) {}
|
||||
|
||||
// if k = 0, your done
|
||||
if (k == 0)
|
||||
return (m_nCurrentBitIndex - BitInitial - 1);
|
||||
|
||||
// put the overflow value into v
|
||||
v = (m_nCurrentBitIndex - BitInitial - 1) << k;
|
||||
|
||||
return v | DecodeValueXBits(k);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Get the optimal k for a given value
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
__inline uint32 CUnBitArrayOld::Get_K(uint32 x)
|
||||
{
|
||||
if (x == 0) return 0;
|
||||
|
||||
uint32 k = 0;
|
||||
while (x >= Powers_of_Two[++k]) {}
|
||||
return k;
|
||||
}
|
||||
|
||||
unsigned int CUnBitArrayOld::DecodeValue(DECODE_VALUE_METHOD DecodeMethod, int nParam1, int nParam2)
|
||||
{
|
||||
switch (DecodeMethod)
|
||||
{
|
||||
case DECODE_VALUE_METHOD_UNSIGNED_INT:
|
||||
return DecodeValueXBits(32);
|
||||
case DECODE_VALUE_METHOD_UNSIGNED_RICE:
|
||||
return DecodeValueRiceUnsigned(nParam1);
|
||||
case DECODE_VALUE_METHOD_X_BITS:
|
||||
return DecodeValueXBits(nParam1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Generates an array from the m_nCurrentBitIndexarray
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
void CUnBitArrayOld::GenerateArrayOld(int* Output_Array, uint32 Number_of_Elements, int Minimum_nCurrentBitIndex_Array_Bytes) {
|
||||
|
||||
//variable declarations
|
||||
uint32 K_Sum;
|
||||
uint32 q;
|
||||
uint32 kmin, kmax;
|
||||
uint32 k;
|
||||
uint32 Max;
|
||||
int *p1, *p2;
|
||||
|
||||
// fill bit array if necessary
|
||||
// could use seek information to determine what the max was...
|
||||
uint32 Max_Bits_Needed = Number_of_Elements * 50;
|
||||
|
||||
if (Minimum_nCurrentBitIndex_Array_Bytes > 0)
|
||||
{
|
||||
// this is actually probably double what is really needed
|
||||
// we can only calculate the space needed for both arrays in multichannel
|
||||
Max_Bits_Needed = ((Minimum_nCurrentBitIndex_Array_Bytes + 4) * 8);
|
||||
}
|
||||
|
||||
if (Max_Bits_Needed > GetBitsRemaining())
|
||||
FillBitArray();
|
||||
|
||||
// decode the first 5 elements (all k = 10)
|
||||
Max = (Number_of_Elements < 5) ? Number_of_Elements : 5;
|
||||
for (q = 0; q < Max; q++)
|
||||
{
|
||||
Output_Array[q] = DecodeValueRiceUnsigned(10);
|
||||
}
|
||||
|
||||
// quit if that was all
|
||||
if (Number_of_Elements <= 5)
|
||||
{
|
||||
for (p2 = &Output_Array[0]; p2 < &Output_Array[Number_of_Elements]; p2++)
|
||||
*p2 = (*p2 & 1) ? (*p2 >> 1) + 1 : -(*p2 >> 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// update k and K_Sum
|
||||
K_Sum = Output_Array[0] + Output_Array[1] + Output_Array[2] + Output_Array[3] + Output_Array[4];
|
||||
k = Get_K(K_Sum / 10);
|
||||
|
||||
// work through the rest of the elements before the primary loop
|
||||
Max = (Number_of_Elements < 64) ? Number_of_Elements : 64;
|
||||
for (q = 5; q < Max; q++)
|
||||
{
|
||||
Output_Array[q] = DecodeValueRiceUnsigned(k);
|
||||
K_Sum += Output_Array[q];
|
||||
k = Get_K(K_Sum / (q + 1) / 2);
|
||||
}
|
||||
|
||||
// quit if that was all
|
||||
if (Number_of_Elements <= 64)
|
||||
{
|
||||
for (p2 = &Output_Array[0]; p2 < &Output_Array[Number_of_Elements]; p2++)
|
||||
*p2 = (*p2 & 1) ? (*p2 >> 1) + 1 : -(*p2 >> 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// set all of the variables up for the primary loop
|
||||
uint32 v, Bit_Array_Index;
|
||||
k = Get_K(K_Sum >> 7);
|
||||
kmin = K_SUM_MIN_BOUNDARY_OLD[k];
|
||||
kmax = K_SUM_MAX_BOUNDARY_OLD[k];
|
||||
p1 = &Output_Array[64]; p2 = &Output_Array[0];
|
||||
|
||||
// the primary loop
|
||||
for (p1 = &Output_Array[64], p2 = &Output_Array[0]; p1 < &Output_Array[Number_of_Elements]; p1++, p2++)
|
||||
{
|
||||
// plug through the string of 0's (the overflow)
|
||||
uint32 Bit_Initial = m_nCurrentBitIndex;
|
||||
while (!(m_pBitArray[m_nCurrentBitIndex >> 5] & Powers_of_Two_Reversed[m_nCurrentBitIndex++ & 31])) {}
|
||||
|
||||
// if k = 0, your done
|
||||
if (k == 0)
|
||||
{
|
||||
v = (m_nCurrentBitIndex - Bit_Initial - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// put the overflow value into v
|
||||
v = (m_nCurrentBitIndex - Bit_Initial - 1) << k;
|
||||
|
||||
// store the bit information and incement the bit pointer by 'k'
|
||||
Bit_Array_Index = m_nCurrentBitIndex >> 5;
|
||||
unsigned int Bit_Index = m_nCurrentBitIndex & 31;
|
||||
m_nCurrentBitIndex += k;
|
||||
|
||||
// figure the extra bits on the left and the left value
|
||||
int Left_Extra_Bits = (32 - k) - Bit_Index;
|
||||
unsigned int Left_Value = m_pBitArray[Bit_Array_Index] & Powers_of_Two_Minus_One_Reversed[Bit_Index];
|
||||
|
||||
if (Left_Extra_Bits >= 0)
|
||||
v |= (Left_Value >> Left_Extra_Bits);
|
||||
else
|
||||
v |= (Left_Value << -Left_Extra_Bits) | (m_pBitArray[Bit_Array_Index + 1] >> (32 + Left_Extra_Bits));
|
||||
}
|
||||
|
||||
*p1 = v;
|
||||
K_Sum += *p1 - *p2;
|
||||
|
||||
// convert *p2 to unsigned
|
||||
*p2 = (*p2 % 2) ? (*p2 >> 1) + 1 : -(*p2 >> 1);
|
||||
|
||||
// adjust k if necessary
|
||||
if ((K_Sum < kmin) || (K_Sum >= kmax))
|
||||
{
|
||||
if (K_Sum < kmin)
|
||||
while (K_Sum < K_SUM_MIN_BOUNDARY_OLD[--k]) {}
|
||||
else
|
||||
while (K_Sum >= K_SUM_MAX_BOUNDARY_OLD[++k]) {}
|
||||
|
||||
kmax = K_SUM_MAX_BOUNDARY_OLD[k];
|
||||
kmin = K_SUM_MIN_BOUNDARY_OLD[k];
|
||||
}
|
||||
}
|
||||
|
||||
for (; p2 < &Output_Array[Number_of_Elements]; p2++)
|
||||
*p2 = (*p2 & 1) ? (*p2 >> 1) + 1 : -(*p2 >> 1);
|
||||
}
|
||||
|
||||
void CUnBitArrayOld::GenerateArray(int *pOutputArray, int nElements, int nBytesRequired)
|
||||
{
|
||||
if (m_nVersion < 3860)
|
||||
{
|
||||
GenerateArrayOld(pOutputArray, nElements, nBytesRequired);
|
||||
}
|
||||
else if (m_nVersion <= 3890)
|
||||
{
|
||||
GenerateArrayRice(pOutputArray, nElements, nBytesRequired);
|
||||
}
|
||||
else
|
||||
{
|
||||
// error
|
||||
}
|
||||
}
|
||||
|
||||
void CUnBitArrayOld::GenerateArrayRice(int* Output_Array, uint32 Number_of_Elements, int Minimum_nCurrentBitIndex_Array_Bytes)
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// decode the bit array
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
k = 10;
|
||||
K_Sum = 1024 * 16;
|
||||
|
||||
if (m_nVersion <= 3880)
|
||||
{
|
||||
// the primary loop
|
||||
for (int *p1 = &Output_Array[0]; p1 < &Output_Array[Number_of_Elements]; p1++)
|
||||
{
|
||||
*p1 = DecodeValueNew(FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// the primary loop
|
||||
for (int *p1 = &Output_Array[0]; p1 < &Output_Array[Number_of_Elements]; p1++)
|
||||
{
|
||||
*p1 = DecodeValueNew(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__inline int CUnBitArrayOld::DecodeValueNew(BOOL bCapOverflow)
|
||||
{
|
||||
// make sure there is room for the data
|
||||
// this is a little slower than ensuring a huge block to start with, but it's safer
|
||||
if (m_nCurrentBitIndex > m_nRefillBitThreshold)
|
||||
{
|
||||
FillBitArray();
|
||||
}
|
||||
|
||||
unsigned int v;
|
||||
|
||||
// plug through the string of 0's (the overflow)
|
||||
uint32 Bit_Initial = m_nCurrentBitIndex;
|
||||
while (!(m_pBitArray[m_nCurrentBitIndex >> 5] & Powers_of_Two_Reversed[m_nCurrentBitIndex++ & 31])) {}
|
||||
|
||||
int nOverflow = (m_nCurrentBitIndex - Bit_Initial - 1);
|
||||
|
||||
if (bCapOverflow)
|
||||
{
|
||||
while (nOverflow >= 16)
|
||||
{
|
||||
k += 4;
|
||||
nOverflow -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
// if k = 0, your done
|
||||
if (k != 0)
|
||||
{
|
||||
// put the overflow value into v
|
||||
v = nOverflow << k;
|
||||
|
||||
// store the bit information and incement the bit pointer by 'k'
|
||||
unsigned int Bit_Array_Index = m_nCurrentBitIndex >> 5;
|
||||
unsigned int Bit_Index = m_nCurrentBitIndex & 31;
|
||||
m_nCurrentBitIndex += k;
|
||||
|
||||
// figure the extra bits on the left and the left value
|
||||
int Left_Extra_Bits = (32 - k) - Bit_Index;
|
||||
unsigned int Left_Value = m_pBitArray[Bit_Array_Index] & Powers_of_Two_Minus_One_Reversed[Bit_Index];
|
||||
|
||||
if (Left_Extra_Bits >= 0)
|
||||
{
|
||||
v |= (Left_Value >> Left_Extra_Bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
v |= (Left_Value << -Left_Extra_Bits) | (m_pBitArray[Bit_Array_Index + 1] >> (32 + Left_Extra_Bits));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v = nOverflow;
|
||||
}
|
||||
|
||||
// update K_Sum
|
||||
K_Sum += v - ((K_Sum + 8) >> 4);
|
||||
|
||||
// update k
|
||||
if (K_Sum < K_SUM_MIN_BOUNDARY[k])
|
||||
k--;
|
||||
else if (K_Sum >= K_SUM_MAX_BOUNDARY[k])
|
||||
k++;
|
||||
|
||||
// convert to unsigned and save
|
||||
return (v & 1) ? (v >> 1) + 1 : -(int(v >> 1));
|
||||
}
|
||||
|
||||
#endif // #ifdef BACKWARDS_COMPATIBILITY
|
||||
46
MAC_SDK/Source/MACLib/Old/UnBitArrayOld.h
Normal file
46
MAC_SDK/Source/MACLib/Old/UnBitArrayOld.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef APE_UNBITARRAY_OLD_H
|
||||
#define APE_UNBITARRAY_OLD_H
|
||||
|
||||
#include "All.h"
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
#include "../UnBitArrayBase.h"
|
||||
|
||||
class IAPEDecompress;
|
||||
|
||||
// decodes 0000 up to and including 3890
|
||||
class CUnBitArrayOld : public CUnBitArrayBase
|
||||
{
|
||||
public:
|
||||
|
||||
// construction/destruction
|
||||
CUnBitArrayOld(IAPEDecompress *pAPEDecompress, int nVersion);
|
||||
~CUnBitArrayOld();
|
||||
|
||||
// functions
|
||||
void GenerateArray(int *pOutputArray, int nElements, int nBytesRequired = -1);
|
||||
unsigned int DecodeValue(DECODE_VALUE_METHOD DecodeMethod, int nParam1 = 0, int nParam2 = 0);
|
||||
|
||||
private:
|
||||
|
||||
void GenerateArrayOld(int* pOutputArray, uint32 NumberOfElements, int MinimumBitArrayBytes);
|
||||
void GenerateArrayRice(int* pOutputArray, uint32 NumberOfElements, int MinimumBitArrayBytes);
|
||||
|
||||
uint32 DecodeValueRiceUnsigned(uint32 k);
|
||||
|
||||
// data
|
||||
uint32 k;
|
||||
uint32 K_Sum;
|
||||
uint32 m_nRefillBitThreshold;
|
||||
|
||||
// functions
|
||||
__inline int DecodeValueNew(BOOL bCapOverflow);
|
||||
uint32 GetBitsRemaining();
|
||||
__inline uint32 Get_K(uint32 x);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef APE_UNBITARRAY_OLD_H
|
||||
|
||||
|
||||
261
MAC_SDK/Source/MACLib/Old/UnMAC.cpp
Normal file
261
MAC_SDK/Source/MACLib/Old/UnMAC.cpp
Normal file
@@ -0,0 +1,261 @@
|
||||
/*****************************************************************************************
|
||||
UnMAC.cpp
|
||||
Copyright (C) 2000-2001 by Matthew T. Ashland All Rights Reserved.
|
||||
|
||||
CUnMAC - the main hub for decompression (manages all of the other components)
|
||||
|
||||
Notes:
|
||||
-none
|
||||
*****************************************************************************************/
|
||||
|
||||
/*****************************************************************************************
|
||||
Includes
|
||||
*****************************************************************************************/
|
||||
#include "All.h"
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
#include "../APEInfo.h"
|
||||
#include "UnMAC.h"
|
||||
#include "GlobalFunctions.h"
|
||||
#include "../UnBitArrayBase.h"
|
||||
#include "Anti-Predictor.h"
|
||||
#include "../Prepare.h"
|
||||
#include "../UnBitArray.h"
|
||||
#include "../NewPredictor.h"
|
||||
#include "APEDecompressCore.h"
|
||||
|
||||
/*****************************************************************************************
|
||||
CUnMAC class construction
|
||||
*****************************************************************************************/
|
||||
CUnMAC::CUnMAC()
|
||||
{
|
||||
// initialize member variables
|
||||
m_bInitialized = FALSE;
|
||||
m_LastDecodedFrameIndex = -1;
|
||||
m_pAPEDecompress = NULL;
|
||||
|
||||
m_pAPEDecompressCore = NULL;
|
||||
m_pPrepare = NULL;
|
||||
|
||||
m_nBlocksProcessed = 0;
|
||||
m_nCRC = 0;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
CUnMAC class destruction
|
||||
*****************************************************************************************/
|
||||
CUnMAC::~CUnMAC()
|
||||
{
|
||||
// uninitialize the decoder in case it isn't already
|
||||
Uninitialize();
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Initialize
|
||||
*****************************************************************************************/
|
||||
int CUnMAC::Initialize(IAPEDecompress *pAPEDecompress)
|
||||
{
|
||||
// uninitialize if it is currently initialized
|
||||
if (m_bInitialized)
|
||||
Uninitialize();
|
||||
|
||||
if (pAPEDecompress == NULL)
|
||||
{
|
||||
Uninitialize();
|
||||
return ERROR_INITIALIZING_UNMAC;
|
||||
}
|
||||
|
||||
// set the member pointer to the IAPEDecompress class
|
||||
m_pAPEDecompress = pAPEDecompress;
|
||||
|
||||
// set the last decode frame to -1 so it forces a seek on start
|
||||
m_LastDecodedFrameIndex = -1;
|
||||
|
||||
m_pAPEDecompressCore = new CAPEDecompressCore(GET_IO(pAPEDecompress), pAPEDecompress);
|
||||
m_pPrepare = new CPrepare;
|
||||
|
||||
// set the initialized flag to TRUE
|
||||
m_bInitialized = TRUE;
|
||||
|
||||
m_pAPEDecompress->GetInfo(APE_INFO_WAVEFORMATEX, (int) &m_wfeInput);
|
||||
|
||||
// return a successful value
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Uninitialize
|
||||
*****************************************************************************************/
|
||||
int CUnMAC::Uninitialize()
|
||||
{
|
||||
if (m_bInitialized)
|
||||
{
|
||||
SAFE_DELETE(m_pAPEDecompressCore)
|
||||
SAFE_DELETE(m_pPrepare)
|
||||
|
||||
// clear the APE info pointer
|
||||
m_pAPEDecompress = NULL;
|
||||
|
||||
// set the last decoded frame again
|
||||
m_LastDecodedFrameIndex = -1;
|
||||
|
||||
// set the initialized flag to FALSE
|
||||
m_bInitialized = FALSE;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Decompress frame
|
||||
*****************************************************************************************/
|
||||
int CUnMAC::DecompressFrame(unsigned char *pOutputData, int32 FrameIndex, int CPULoadBalancingFactor)
|
||||
{
|
||||
return DecompressFrameOld(pOutputData, FrameIndex, CPULoadBalancingFactor);
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Seek to the proper frame (if necessary) and do any alignment of the bit array
|
||||
*****************************************************************************************/
|
||||
int CUnMAC::SeekToFrame(int FrameIndex)
|
||||
{
|
||||
if (GET_FRAMES_START_ON_BYTES_BOUNDARIES(m_pAPEDecompress))
|
||||
{
|
||||
if ((m_LastDecodedFrameIndex == -1) || ((FrameIndex - 1) != m_LastDecodedFrameIndex))
|
||||
{
|
||||
int SeekRemainder = (m_pAPEDecompress->GetInfo(APE_INFO_SEEK_BYTE, FrameIndex) - m_pAPEDecompress->GetInfo(APE_INFO_SEEK_BYTE, 0)) % 4;
|
||||
m_pAPEDecompressCore->GetUnBitArrray()->FillAndResetBitArray(m_pAPEDecompress->GetInfo(APE_INFO_SEEK_BYTE, FrameIndex) - SeekRemainder, SeekRemainder * 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pAPEDecompressCore->GetUnBitArrray()->AdvanceToByteBoundary();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((m_LastDecodedFrameIndex == -1) || ((FrameIndex - 1) != m_LastDecodedFrameIndex))
|
||||
{
|
||||
m_pAPEDecompressCore->GetUnBitArrray()->FillAndResetBitArray(m_pAPEDecompress->GetInfo(APE_INFO_SEEK_BYTE, FrameIndex), m_pAPEDecompress->GetInfo(APE_INFO_SEEK_BIT, FrameIndex));
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************************
|
||||
Old code for frame decompression
|
||||
*****************************************************************************************/
|
||||
int CUnMAC::DecompressFrameOld(unsigned char *pOutputData, int32 FrameIndex, int CPULoadBalancingFactor)
|
||||
{
|
||||
// error check the parameters (too high of a frame index, etc.)
|
||||
if (FrameIndex >= m_pAPEDecompress->GetInfo(APE_INFO_TOTAL_FRAMES)) { return ERROR_SUCCESS; }
|
||||
|
||||
// get the number of samples in the frame
|
||||
int nBlocks = 0;
|
||||
nBlocks = ((FrameIndex + 1) >= m_pAPEDecompress->GetInfo(APE_INFO_TOTAL_FRAMES)) ? m_pAPEDecompress->GetInfo(APE_INFO_FINAL_FRAME_BLOCKS) : m_pAPEDecompress->GetInfo(APE_INFO_BLOCKS_PER_FRAME);
|
||||
if (nBlocks == 0)
|
||||
return -1; // nothing to do (file must be zero length) (have to return error)
|
||||
|
||||
// take care of seeking and frame alignment
|
||||
if (SeekToFrame(FrameIndex) != 0) { return -1; }
|
||||
|
||||
// get the checksum
|
||||
unsigned int nSpecialCodes = 0;
|
||||
uint32 nStoredCRC = 0;
|
||||
|
||||
if (GET_USES_CRC(m_pAPEDecompress) == FALSE)
|
||||
{
|
||||
nStoredCRC = m_pAPEDecompressCore->GetUnBitArrray()->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_RICE, 30);
|
||||
if (nStoredCRC == 0)
|
||||
{
|
||||
nSpecialCodes = SPECIAL_FRAME_LEFT_SILENCE | SPECIAL_FRAME_RIGHT_SILENCE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nStoredCRC = m_pAPEDecompressCore->GetUnBitArrray()->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_INT);
|
||||
|
||||
// get any 'special' codes if the file uses them (for silence, FALSE stereo, etc.)
|
||||
nSpecialCodes = 0;
|
||||
if (GET_USES_SPECIAL_FRAMES(m_pAPEDecompress))
|
||||
{
|
||||
if (nStoredCRC & 0x80000000)
|
||||
{
|
||||
nSpecialCodes = m_pAPEDecompressCore->GetUnBitArrray()->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_INT);
|
||||
}
|
||||
nStoredCRC &= 0x7FFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
// the CRC that will be figured during decompression
|
||||
uint32 CRC = 0xFFFFFFFF;
|
||||
|
||||
// decompress and convert from (x,y) -> (l,r)
|
||||
// sort of int and ugly.... sorry
|
||||
if (m_pAPEDecompress->GetInfo(APE_INFO_CHANNELS) == 2)
|
||||
{
|
||||
m_pAPEDecompressCore->GenerateDecodedArrays(nBlocks, nSpecialCodes, FrameIndex, CPULoadBalancingFactor);
|
||||
|
||||
WAVEFORMATEX WaveFormatEx; m_pAPEDecompress->GetInfo(APE_INFO_WAVEFORMATEX, (int) &WaveFormatEx);
|
||||
m_pPrepare->UnprepareOld(m_pAPEDecompressCore->GetDataX(), m_pAPEDecompressCore->GetDataY(), nBlocks, &WaveFormatEx,
|
||||
pOutputData, (unsigned int *) &CRC, (int *) &nSpecialCodes, m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
|
||||
}
|
||||
else if (m_pAPEDecompress->GetInfo(APE_INFO_CHANNELS) == 1)
|
||||
{
|
||||
m_pAPEDecompressCore->GenerateDecodedArrays(nBlocks, nSpecialCodes, FrameIndex, CPULoadBalancingFactor);
|
||||
|
||||
WAVEFORMATEX WaveFormatEx; m_pAPEDecompress->GetInfo(APE_INFO_WAVEFORMATEX, (int) &WaveFormatEx);
|
||||
m_pPrepare->UnprepareOld(m_pAPEDecompressCore->GetDataX(), NULL, nBlocks, &WaveFormatEx,
|
||||
pOutputData, (unsigned int *) &CRC, (int *) &nSpecialCodes, m_pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION));
|
||||
}
|
||||
|
||||
if (GET_USES_SPECIAL_FRAMES(m_pAPEDecompress))
|
||||
{
|
||||
CRC >>= 1;
|
||||
}
|
||||
|
||||
// check the CRC
|
||||
if (GET_USES_CRC(m_pAPEDecompress) == FALSE)
|
||||
{
|
||||
uint32 nChecksum = CalculateOldChecksum(m_pAPEDecompressCore->GetDataX(), m_pAPEDecompressCore->GetDataY(), m_pAPEDecompress->GetInfo(APE_INFO_CHANNELS), nBlocks);
|
||||
if (nChecksum != nStoredCRC)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CRC != nStoredCRC)
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_LastDecodedFrameIndex = FrameIndex;
|
||||
return nBlocks;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************
|
||||
Figures the old checksum using the X,Y data
|
||||
*****************************************************************************************/
|
||||
uint32 CUnMAC::CalculateOldChecksum(int *pDataX, int *pDataY, int nChannels, int nBlocks)
|
||||
{
|
||||
uint32 nChecksum = 0;
|
||||
|
||||
if (nChannels == 2)
|
||||
{
|
||||
for (int z = 0; z < nBlocks; z++)
|
||||
{
|
||||
int R = pDataX[z] - (pDataY[z] / 2);
|
||||
int L = R + pDataY[z];
|
||||
nChecksum += (labs(R) + labs(L));
|
||||
}
|
||||
}
|
||||
else if (nChannels == 1)
|
||||
{
|
||||
for (int z = 0; z < nBlocks; z++)
|
||||
nChecksum += labs(pDataX[z]);
|
||||
}
|
||||
|
||||
return nChecksum;
|
||||
}
|
||||
|
||||
#endif // #ifdef BACKWARDS_COMPATIBILITY
|
||||
69
MAC_SDK/Source/MACLib/Old/UnMAC.h
Normal file
69
MAC_SDK/Source/MACLib/Old/UnMAC.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*****************************************************************************************
|
||||
UnMAC.h
|
||||
Copyright (C) 2000-2001 by Matthew T. Ashland All Rights Reserved.
|
||||
|
||||
Methods for decompressing or verifying APE files
|
||||
|
||||
Notes:
|
||||
-none
|
||||
*****************************************************************************************/
|
||||
|
||||
#ifndef APE_UNMAC_H
|
||||
#define APE_UNMAC_H
|
||||
|
||||
#include "../BitArray.h"
|
||||
#include "../UnBitArrayBase.h"
|
||||
|
||||
class CAntiPredictor;
|
||||
class CPrepare;
|
||||
class CAPEDecompressCore;
|
||||
class CPredictorBase;
|
||||
class IPredictorDecompress;
|
||||
class IAPEDecompress;
|
||||
|
||||
/*****************************************************************************************
|
||||
CUnMAC class... a class that allows decoding on a frame-by-frame basis
|
||||
*****************************************************************************************/
|
||||
class CUnMAC
|
||||
{
|
||||
public:
|
||||
|
||||
// construction/destruction
|
||||
CUnMAC();
|
||||
~CUnMAC();
|
||||
|
||||
// functions
|
||||
int Initialize(IAPEDecompress *pAPEDecompress);
|
||||
int Uninitialize();
|
||||
int DecompressFrame(unsigned char *pOutputData, int32 FrameIndex, int CPULoadBalancingFactor = 0);
|
||||
|
||||
int SeekToFrame(int FrameIndex);
|
||||
|
||||
private:
|
||||
|
||||
// data members
|
||||
BOOL m_bInitialized;
|
||||
int m_LastDecodedFrameIndex;
|
||||
IAPEDecompress * m_pAPEDecompress;
|
||||
CPrepare * m_pPrepare;
|
||||
|
||||
CAPEDecompressCore * m_pAPEDecompressCore;
|
||||
|
||||
// functions
|
||||
void GenerateDecodedArrays(int nBlocks, int nSpecialCodes, int nFrameIndex, int nCPULoadBalancingFactor);
|
||||
void GenerateDecodedArray(int *Input_Array, uint32 Number_of_Elements, int Frame_Index, CAntiPredictor *pAntiPredictor, int CPULoadBalancingFactor = 0);
|
||||
|
||||
int CreateAntiPredictors(int nCompressionLevel, int nVersion);
|
||||
|
||||
int DecompressFrameOld(unsigned char *pOutputData, int32 FrameIndex, int CPULoadBalancingFactor);
|
||||
uint32 CalculateOldChecksum(int *pDataX, int *pDataY, int nChannels, int nBlocks);
|
||||
|
||||
public:
|
||||
|
||||
int m_nBlocksProcessed;
|
||||
unsigned int m_nCRC;
|
||||
unsigned int m_nStoredCRC;
|
||||
WAVEFORMATEX m_wfeInput;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_UNMAC_H
|
||||
30
MAC_SDK/Source/MACLib/Predictor.h
Normal file
30
MAC_SDK/Source/MACLib/Predictor.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef APE_PREDICTOR_H
|
||||
#define APE_PREDICTOR_H
|
||||
|
||||
/*************************************************************************************************
|
||||
IPredictorCompress - the interface for compressing (predicting) data
|
||||
*************************************************************************************************/
|
||||
class IPredictorCompress
|
||||
{
|
||||
public:
|
||||
IPredictorCompress(int nCompressionLevel) {}
|
||||
virtual ~IPredictorCompress() {}
|
||||
|
||||
virtual int CompressValue(int nA, int nB = 0) = 0;
|
||||
virtual int Flush() = 0;
|
||||
};
|
||||
|
||||
/*************************************************************************************************
|
||||
IPredictorDecompress - the interface for decompressing (un-predicting) data
|
||||
*************************************************************************************************/
|
||||
class IPredictorDecompress
|
||||
{
|
||||
public:
|
||||
IPredictorDecompress(int nCompressionLevel, int nVersion) {}
|
||||
virtual ~IPredictorDecompress() {}
|
||||
|
||||
virtual int DecompressValue(int nA, int nB = 0) = 0;
|
||||
virtual int Flush() = 0;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_PREDICTOR_H
|
||||
510
MAC_SDK/Source/MACLib/Prepare.cpp
Normal file
510
MAC_SDK/Source/MACLib/Prepare.cpp
Normal file
@@ -0,0 +1,510 @@
|
||||
#include "All.h"
|
||||
#include "Prepare.h"
|
||||
|
||||
const uint32 CRC32_TABLE[256] = {0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,
|
||||
4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,
|
||||
2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918000,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117};
|
||||
|
||||
int CPrepare::Prepare(const unsigned char * pRawData, int nBytes, const WAVEFORMATEX * pWaveFormatEx, int * pOutputX, int *pOutputY, unsigned int *pCRC, int *pSpecialCodes, int *pPeakLevel)
|
||||
{
|
||||
// error check the parameters
|
||||
if (pRawData == NULL || pWaveFormatEx == NULL)
|
||||
return ERROR_BAD_PARAMETER;
|
||||
|
||||
// initialize the pointers that got passed in
|
||||
*pCRC = 0xFFFFFFFF;
|
||||
*pSpecialCodes = 0;
|
||||
|
||||
// variables
|
||||
uint32 CRC = 0xFFFFFFFF;
|
||||
const int nTotalBlocks = nBytes / pWaveFormatEx->nBlockAlign;
|
||||
int R,L;
|
||||
|
||||
// the prepare code
|
||||
|
||||
if (pWaveFormatEx->wBitsPerSample == 8)
|
||||
{
|
||||
if (pWaveFormatEx->nChannels == 2)
|
||||
{
|
||||
for (int nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++)
|
||||
{
|
||||
R = (int) (*((unsigned char *) pRawData) - 128);
|
||||
L = (int) (*((unsigned char *) (pRawData + 1)) - 128);
|
||||
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
// check the peak
|
||||
if (labs(L) > *pPeakLevel)
|
||||
*pPeakLevel = labs(L);
|
||||
if (labs(R) > *pPeakLevel)
|
||||
*pPeakLevel = labs(R);
|
||||
|
||||
// convert to x,y
|
||||
pOutputY[nBlockIndex] = L - R;
|
||||
pOutputX[nBlockIndex] = R + (pOutputY[nBlockIndex] / 2);
|
||||
}
|
||||
}
|
||||
else if (pWaveFormatEx->nChannels == 1)
|
||||
{
|
||||
for (int nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++)
|
||||
{
|
||||
R = (int) (*((unsigned char *) pRawData) - 128);
|
||||
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
// check the peak
|
||||
if (labs(R) > *pPeakLevel)
|
||||
*pPeakLevel = labs(R);
|
||||
|
||||
// convert to x,y
|
||||
pOutputX[nBlockIndex] = R;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pWaveFormatEx->wBitsPerSample == 24)
|
||||
{
|
||||
if (pWaveFormatEx->nChannels == 2)
|
||||
{
|
||||
for (int nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++)
|
||||
{
|
||||
uint32 nTemp = 0;
|
||||
|
||||
nTemp |= (*pRawData << 0);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
nTemp |= (*pRawData << 8);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
nTemp |= (*pRawData << 16);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
if (nTemp & 0x800000)
|
||||
R = (int) (nTemp & 0x7FFFFF) - 0x800000;
|
||||
else
|
||||
R = (int) (nTemp & 0x7FFFFF);
|
||||
|
||||
nTemp = 0;
|
||||
|
||||
nTemp |= (*pRawData << 0);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
nTemp |= (*pRawData << 8);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
nTemp |= (*pRawData << 16);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
if (nTemp & 0x800000)
|
||||
L = (int) (nTemp & 0x7FFFFF) - 0x800000;
|
||||
else
|
||||
L = (int) (nTemp & 0x7FFFFF);
|
||||
|
||||
// check the peak
|
||||
if (labs(L) > *pPeakLevel)
|
||||
*pPeakLevel = labs(L);
|
||||
if (labs(R) > *pPeakLevel)
|
||||
*pPeakLevel = labs(R);
|
||||
|
||||
// convert to x,y
|
||||
pOutputY[nBlockIndex] = L - R;
|
||||
pOutputX[nBlockIndex] = R + (pOutputY[nBlockIndex] / 2);
|
||||
|
||||
}
|
||||
}
|
||||
else if (pWaveFormatEx->nChannels == 1)
|
||||
{
|
||||
for (int nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++)
|
||||
{
|
||||
uint32 nTemp = 0;
|
||||
|
||||
nTemp |= (*pRawData << 0);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
nTemp |= (*pRawData << 8);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
nTemp |= (*pRawData << 16);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
if (nTemp & 0x800000)
|
||||
R = (int) (nTemp & 0x7FFFFF) - 0x800000;
|
||||
else
|
||||
R = (int) (nTemp & 0x7FFFFF);
|
||||
|
||||
// check the peak
|
||||
if (labs(R) > *pPeakLevel)
|
||||
*pPeakLevel = labs(R);
|
||||
|
||||
// convert to x,y
|
||||
pOutputX[nBlockIndex] = R;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pWaveFormatEx->nChannels == 2)
|
||||
{
|
||||
int LPeak = 0;
|
||||
int RPeak = 0;
|
||||
int nBlockIndex = 0;
|
||||
for (nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++)
|
||||
{
|
||||
|
||||
R = (int) *((int16 *) pRawData);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
L = (int) *((int16 *) pRawData);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
// check the peak
|
||||
if (labs(L) > LPeak)
|
||||
LPeak = labs(L);
|
||||
if (labs(R) > RPeak)
|
||||
RPeak = labs(R);
|
||||
|
||||
// convert to x,y
|
||||
pOutputY[nBlockIndex] = L - R;
|
||||
pOutputX[nBlockIndex] = R + (pOutputY[nBlockIndex] / 2);
|
||||
}
|
||||
|
||||
if (LPeak == 0) { *pSpecialCodes |= SPECIAL_FRAME_LEFT_SILENCE; }
|
||||
if (RPeak == 0) { *pSpecialCodes |= SPECIAL_FRAME_RIGHT_SILENCE; }
|
||||
if (max(LPeak, RPeak) > *pPeakLevel)
|
||||
{
|
||||
*pPeakLevel = max(LPeak, RPeak);
|
||||
}
|
||||
|
||||
// check for pseudo-stereo files
|
||||
nBlockIndex = 0;
|
||||
while (pOutputY[nBlockIndex++] == 0)
|
||||
{
|
||||
if (nBlockIndex == (nBytes / 4))
|
||||
{
|
||||
*pSpecialCodes |= SPECIAL_FRAME_PSEUDO_STEREO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (pWaveFormatEx->nChannels == 1)
|
||||
{
|
||||
int nPeak = 0;
|
||||
for (int nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++)
|
||||
{
|
||||
R = (int) *((int16 *) pRawData);
|
||||
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *pRawData++];
|
||||
|
||||
// check the peak
|
||||
if (labs(R) > nPeak)
|
||||
nPeak = labs(R);
|
||||
|
||||
//convert to x,y
|
||||
pOutputX[nBlockIndex] = R;
|
||||
}
|
||||
|
||||
if (nPeak > *pPeakLevel)
|
||||
*pPeakLevel = nPeak;
|
||||
if (nPeak == 0) { *pSpecialCodes |= SPECIAL_FRAME_MONO_SILENCE; }
|
||||
}
|
||||
}
|
||||
|
||||
CRC = CRC ^ 0xFFFFFFFF;
|
||||
|
||||
// add the special code
|
||||
CRC >>= 1;
|
||||
|
||||
if (*pSpecialCodes != 0)
|
||||
{
|
||||
CRC |= (1 << 31);
|
||||
}
|
||||
|
||||
*pCRC = CRC;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
void CPrepare::Unprepare(int X, int Y, const WAVEFORMATEX * pWaveFormatEx, unsigned char * pOutput, unsigned int * pCRC)
|
||||
{
|
||||
#define CALCULATE_CRC_BYTE *pCRC = (*pCRC >> 8) ^ CRC32_TABLE[(*pCRC & 0xFF) ^ *pOutput++];
|
||||
// decompress and convert from (x,y) -> (l,r)
|
||||
// sort of long and ugly.... sorry
|
||||
|
||||
if (pWaveFormatEx->nChannels == 2)
|
||||
{
|
||||
if (pWaveFormatEx->wBitsPerSample == 16)
|
||||
{
|
||||
// get the right and left values
|
||||
int nR = X - (Y / 2);
|
||||
int nL = nR + Y;
|
||||
|
||||
// error check (for overflows)
|
||||
if ((nR < -32768) || (nR > 32767) || (nL < -32768) || (nL > 32767))
|
||||
{
|
||||
throw(-1);
|
||||
}
|
||||
|
||||
*(int16 *) pOutput = (int16) nR;
|
||||
CALCULATE_CRC_BYTE
|
||||
CALCULATE_CRC_BYTE
|
||||
|
||||
*(int16 *) pOutput = (int16) nL;
|
||||
CALCULATE_CRC_BYTE
|
||||
CALCULATE_CRC_BYTE
|
||||
}
|
||||
else if (pWaveFormatEx->wBitsPerSample == 8)
|
||||
{
|
||||
unsigned char R = (X - (Y / 2) + 128);
|
||||
*pOutput = R;
|
||||
CALCULATE_CRC_BYTE
|
||||
*pOutput = (unsigned char) (R + Y);
|
||||
CALCULATE_CRC_BYTE
|
||||
}
|
||||
else if (pWaveFormatEx->wBitsPerSample == 24)
|
||||
{
|
||||
int32 RV, LV;
|
||||
|
||||
RV = X - (Y / 2);
|
||||
LV = RV + Y;
|
||||
|
||||
uint32 nTemp = 0;
|
||||
if (RV < 0)
|
||||
nTemp = ((uint32) (RV + 0x800000)) | 0x800000;
|
||||
else
|
||||
nTemp = (uint32) RV;
|
||||
|
||||
*pOutput = (unsigned char) ((nTemp >> 0) & 0xFF);
|
||||
CALCULATE_CRC_BYTE
|
||||
*pOutput = (unsigned char) ((nTemp >> 8) & 0xFF);
|
||||
CALCULATE_CRC_BYTE
|
||||
*pOutput = (unsigned char) ((nTemp >> 16) & 0xFF);
|
||||
CALCULATE_CRC_BYTE
|
||||
|
||||
nTemp = 0;
|
||||
if (LV < 0)
|
||||
nTemp = ((uint32) (LV + 0x800000)) | 0x800000;
|
||||
else
|
||||
nTemp = (uint32) LV;
|
||||
|
||||
*pOutput = (unsigned char) ((nTemp >> 0) & 0xFF);
|
||||
CALCULATE_CRC_BYTE
|
||||
|
||||
*pOutput = (unsigned char) ((nTemp >> 8) & 0xFF);
|
||||
CALCULATE_CRC_BYTE
|
||||
|
||||
*pOutput = (unsigned char) ((nTemp >> 16) & 0xFF);
|
||||
CALCULATE_CRC_BYTE
|
||||
}
|
||||
}
|
||||
else if (pWaveFormatEx->nChannels == 1)
|
||||
{
|
||||
if (pWaveFormatEx->wBitsPerSample == 16)
|
||||
{
|
||||
int16 R = X;
|
||||
|
||||
*(int16 *) pOutput = (int16) R;
|
||||
CALCULATE_CRC_BYTE
|
||||
CALCULATE_CRC_BYTE
|
||||
}
|
||||
else if (pWaveFormatEx->wBitsPerSample == 8)
|
||||
{
|
||||
unsigned char R = X + 128;
|
||||
*pOutput = R;
|
||||
CALCULATE_CRC_BYTE
|
||||
}
|
||||
else if (pWaveFormatEx->wBitsPerSample == 24)
|
||||
{
|
||||
int32 RV = X;
|
||||
|
||||
uint32 nTemp = 0;
|
||||
if (RV < 0)
|
||||
nTemp = ((uint32) (RV + 0x800000)) | 0x800000;
|
||||
else
|
||||
nTemp = (uint32) RV;
|
||||
|
||||
*pOutput = (unsigned char) ((nTemp >> 0) & 0xFF);
|
||||
CALCULATE_CRC_BYTE
|
||||
*pOutput = (unsigned char) ((nTemp >> 8) & 0xFF);
|
||||
CALCULATE_CRC_BYTE
|
||||
*pOutput = (unsigned char) ((nTemp >> 16) & 0xFF);
|
||||
CALCULATE_CRC_BYTE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
|
||||
int CPrepare::UnprepareOld(int *pInputX, int *pInputY, int nBlocks, const WAVEFORMATEX *pWaveFormatEx, unsigned char *pRawData, unsigned int *pCRC, int *pSpecialCodes, int nFileVersion)
|
||||
{
|
||||
// the CRC that will be figured during decompression
|
||||
uint32 CRC = 0xFFFFFFFF;
|
||||
|
||||
// decompress and convert from (x,y) -> (l,r)
|
||||
// sort of int and ugly.... sorry
|
||||
if (pWaveFormatEx->nChannels == 2)
|
||||
{
|
||||
// convert the x,y data to raw data
|
||||
if (pWaveFormatEx->wBitsPerSample == 16)
|
||||
{
|
||||
int16 R;
|
||||
unsigned char *Buffer = &pRawData[0];
|
||||
int *pX = pInputX;
|
||||
int *pY = pInputY;
|
||||
|
||||
for (; pX < &pInputX[nBlocks]; pX++, pY++)
|
||||
{
|
||||
R = *pX - (*pY / 2);
|
||||
|
||||
*(int16 *) Buffer = (int16) R;
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
|
||||
*(int16 *) Buffer = (int16) R + *pY;
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
}
|
||||
}
|
||||
else if (pWaveFormatEx->wBitsPerSample == 8)
|
||||
{
|
||||
unsigned char *R = (unsigned char *) &pRawData[0];
|
||||
unsigned char *L = (unsigned char *) &pRawData[1];
|
||||
|
||||
if (nFileVersion > 3830)
|
||||
{
|
||||
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++, L+=2, R+=2)
|
||||
{
|
||||
*R = (unsigned char) (pInputX[SampleIndex] - (pInputY[SampleIndex] / 2) + 128);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *R];
|
||||
*L = (unsigned char) (*R + pInputY[SampleIndex]);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *L];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++, L+=2, R+=2)
|
||||
{
|
||||
*R = (unsigned char) (pInputX[SampleIndex] - (pInputY[SampleIndex] / 2));
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *R];
|
||||
*L = (unsigned char) (*R + pInputY[SampleIndex]);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *L];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pWaveFormatEx->wBitsPerSample == 24)
|
||||
{
|
||||
unsigned char *Buffer = (unsigned char *) &pRawData[0];
|
||||
int32 RV, LV;
|
||||
|
||||
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++)
|
||||
{
|
||||
RV = pInputX[SampleIndex] - (pInputY[SampleIndex] / 2);
|
||||
LV = RV + pInputY[SampleIndex];
|
||||
|
||||
uint32 nTemp = 0;
|
||||
if (RV < 0)
|
||||
nTemp = ((uint32) (RV + 0x800000)) | 0x800000;
|
||||
else
|
||||
nTemp = (uint32) RV;
|
||||
|
||||
*Buffer = (unsigned char) ((nTemp >> 0) & 0xFF);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
|
||||
*Buffer = (unsigned char) ((nTemp >> 8) & 0xFF);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
|
||||
*Buffer = (unsigned char) ((nTemp >> 16) & 0xFF);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
|
||||
nTemp = 0;
|
||||
if (LV < 0)
|
||||
nTemp = ((uint32) (LV + 0x800000)) | 0x800000;
|
||||
else
|
||||
nTemp = (uint32) LV;
|
||||
|
||||
*Buffer = (unsigned char) ((nTemp >> 0) & 0xFF);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
|
||||
*Buffer = (unsigned char) ((nTemp >> 8) & 0xFF);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
|
||||
*Buffer = (unsigned char) ((nTemp >> 16) & 0xFF);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pWaveFormatEx->nChannels == 1)
|
||||
{
|
||||
// convert to raw data
|
||||
if (pWaveFormatEx->wBitsPerSample == 8)
|
||||
{
|
||||
unsigned char *R = (unsigned char *) &pRawData[0];
|
||||
|
||||
if (nFileVersion > 3830)
|
||||
{
|
||||
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++, R++)
|
||||
{
|
||||
*R = pInputX[SampleIndex] + 128;
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *R];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++, R++)
|
||||
{
|
||||
*R = (unsigned char) (pInputX[SampleIndex]);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *R];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (pWaveFormatEx->wBitsPerSample == 24)
|
||||
{
|
||||
|
||||
unsigned char *Buffer = (unsigned char *) &pRawData[0];
|
||||
int32 RV;
|
||||
for (int SampleIndex = 0; SampleIndex<nBlocks; SampleIndex++)
|
||||
{
|
||||
RV = pInputX[SampleIndex];
|
||||
|
||||
uint32 nTemp = 0;
|
||||
if (RV < 0)
|
||||
nTemp = ((uint32) (RV + 0x800000)) | 0x800000;
|
||||
else
|
||||
nTemp = (uint32) RV;
|
||||
|
||||
*Buffer = (unsigned char) ((nTemp >> 0) & 0xFF);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
|
||||
*Buffer = (unsigned char) ((nTemp >> 8) & 0xFF);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
|
||||
*Buffer = (unsigned char) ((nTemp >> 16) & 0xFF);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char *Buffer = &pRawData[0];
|
||||
|
||||
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++)
|
||||
{
|
||||
*(int16 *) Buffer = (int16) (pInputX[SampleIndex]);
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
CRC = (CRC >> 8) ^ CRC32_TABLE[(CRC & 0xFF) ^ *Buffer++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRC = CRC ^ 0xFFFFFFFF;
|
||||
|
||||
*pCRC = CRC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // #ifdef BACKWARDS_COMPATIBILITY
|
||||
38
MAC_SDK/Source/MACLib/Prepare.h
Normal file
38
MAC_SDK/Source/MACLib/Prepare.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef APE_PREPARE_H
|
||||
#define APE_PREPARE_H
|
||||
|
||||
#define SPECIAL_FRAME_MONO_SILENCE 1
|
||||
#define SPECIAL_FRAME_LEFT_SILENCE 1
|
||||
#define SPECIAL_FRAME_RIGHT_SILENCE 2
|
||||
#define SPECIAL_FRAME_PSEUDO_STEREO 4
|
||||
|
||||
/*****************************************************************************
|
||||
Manage the preparation stage of compression and decompression
|
||||
|
||||
Tasks:
|
||||
|
||||
1) convert data to 32-bit
|
||||
2) convert L,R to X,Y
|
||||
3) calculate the CRC
|
||||
4) do simple analysis
|
||||
5) check for the peak value
|
||||
*****************************************************************************/
|
||||
|
||||
class IPredictorDecompress;
|
||||
|
||||
class CPrepare
|
||||
{
|
||||
public:
|
||||
|
||||
int Prepare(const unsigned char * pRawData, int nBytes, const WAVEFORMATEX * pWaveFormatEx, int * pOutputX, int * pOutputY, unsigned int * pCRC, int * pSpecialCodes, int * pPeakLevel);
|
||||
void Unprepare(int X, int Y, const WAVEFORMATEX * pWaveFormatEx, unsigned char * pOutput, unsigned int * pCRC);
|
||||
|
||||
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
int UnprepareOld(int * pInputX, int *pInputY, int nBlocks, const WAVEFORMATEX * pWaveFormatEx, unsigned char * pRawData, unsigned int * pCRC, int * pSpecialCodes, int nFileVersion);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // #ifndef APE_PREPARE_H
|
||||
31
MAC_SDK/Source/MACLib/ScaledFirstOrderFilter.h
Normal file
31
MAC_SDK/Source/MACLib/ScaledFirstOrderFilter.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef APE_SCALEDFIRSTORDERFILTER_H
|
||||
#define APE_SCALEDFIRSTORDERFILTER_H
|
||||
|
||||
template <int MULTIPLY, int SHIFT> class CScaledFirstOrderFilter
|
||||
{
|
||||
public:
|
||||
|
||||
__inline void Flush()
|
||||
{
|
||||
m_nLastValue = 0;
|
||||
}
|
||||
|
||||
__inline int Compress(const int nInput)
|
||||
{
|
||||
int nRetVal = nInput - ((m_nLastValue * MULTIPLY) >> SHIFT);
|
||||
m_nLastValue = nInput;
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
__inline int Decompress(const int nInput)
|
||||
{
|
||||
m_nLastValue = nInput + ((m_nLastValue * MULTIPLY) >> SHIFT);
|
||||
return m_nLastValue;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
int m_nLastValue;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_SCALEDFIRSTORDERFILTER_H
|
||||
178
MAC_SDK/Source/MACLib/StartFilter.h
Normal file
178
MAC_SDK/Source/MACLib/StartFilter.h
Normal file
@@ -0,0 +1,178 @@
|
||||
#ifndef APE_START_FILTER_H
|
||||
#define APE_START_FILTER_H
|
||||
|
||||
class CStartFilter
|
||||
{
|
||||
public:
|
||||
|
||||
CStartFilter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~CStartFilter()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Flush()
|
||||
{
|
||||
m_rbInputA.Flush();
|
||||
m_rbInputB.Flush();
|
||||
|
||||
memset(m_aryMA, 0, sizeof(m_aryMA));
|
||||
memset(m_aryMB, 0, sizeof(m_aryMB));
|
||||
|
||||
m_Stage1FilterA1.Flush();
|
||||
m_Stage1FilterA2.Flush();
|
||||
m_Stage1FilterA3.Flush();
|
||||
|
||||
m_Stage1FilterB1.Flush();
|
||||
m_Stage1FilterB2.Flush();
|
||||
m_Stage1FilterB3.Flush();
|
||||
}
|
||||
|
||||
void Compress(int & nA, int & nB)
|
||||
{
|
||||
/*
|
||||
nA = m_Stage1FilterA1.Compress(nA);
|
||||
nA = m_Stage1FilterA2.Compress(nA);
|
||||
nA = m_Stage1FilterA3.Compress(nA);
|
||||
|
||||
nB = m_Stage1FilterB1.Compress(nB);
|
||||
nB = m_Stage1FilterB2.Compress(nB);
|
||||
nB = m_Stage1FilterB3.Compress(nB);
|
||||
return;
|
||||
//*/
|
||||
|
||||
nA = m_Stage1FilterA1.Compress(nA);
|
||||
nA = m_Stage1FilterA2.Compress(nA);
|
||||
// nA = m_Stage1FilterA3.Compress(nA);
|
||||
|
||||
nB = m_Stage1FilterB1.Compress(nB);
|
||||
nB = m_Stage1FilterB2.Compress(nB);
|
||||
|
||||
//int nTemp = nA; nA = nB; nB = nTemp;
|
||||
// nB = m_Stage1FilterB3.Compress(nB);
|
||||
|
||||
// nA = nA - nB;
|
||||
// nB = nB + (nA / 2);
|
||||
|
||||
|
||||
// return;
|
||||
|
||||
m_rbInputA[0] = nA; m_rbInputB[0] = nB;
|
||||
|
||||
{
|
||||
int nPrediction1 = m_rbInputA[-1];
|
||||
int nPrediction2 = m_rbInputA[-2];
|
||||
int nPrediction3 = m_rbInputA[-1] - m_rbInputA[-2];
|
||||
int nPrediction4 = m_rbInputB[-1];
|
||||
|
||||
int nTotalPrediction = (nPrediction1 * m_aryMA[0]) + (nPrediction2 * m_aryMA[1])
|
||||
+ (nPrediction3 * m_aryMA[2]) + (nPrediction4 * m_aryMA[3]);
|
||||
int nOutput = nA - (nTotalPrediction >> 13);
|
||||
|
||||
if (nOutput > 0)
|
||||
{
|
||||
m_aryMA[0] -= 2*((nPrediction1) ? ((nPrediction1 >> 30) & 2) - 1 : 0);
|
||||
m_aryMA[1] -= (nPrediction2) ? ((nPrediction2 >> 30) & 2) - 1 : 0;
|
||||
m_aryMA[2] -= (nPrediction3) ? ((nPrediction3 >> 30) & 2) - 1 : 0;
|
||||
m_aryMA[3] -= 1*((nPrediction4) ? ((nPrediction4 >> 30) & 2) - 1 : 0);
|
||||
}
|
||||
else if (nOutput < 0)
|
||||
{
|
||||
m_aryMA[0] += 2*((nPrediction1) ? ((nPrediction1 >> 30) & 2) - 1 : 0);
|
||||
m_aryMA[1] += (nPrediction2) ? ((nPrediction2 >> 30) & 2) - 1 : 0;
|
||||
m_aryMA[2] += (nPrediction3) ? ((nPrediction3 >> 30) & 2) - 1 : 0;
|
||||
m_aryMA[3] += 1*((nPrediction4) ? ((nPrediction4 >> 30) & 2) - 1 : 0);
|
||||
}
|
||||
|
||||
nA = nOutput;
|
||||
}
|
||||
{
|
||||
int nPrediction1 = m_rbInputB[-1];
|
||||
int nPrediction2 = m_rbInputB[-2];
|
||||
int nPrediction3 = 0;//m_rbInputB[-1] - m_rbInputB[-2];
|
||||
int nPrediction4 = m_rbInputA[0];
|
||||
|
||||
int nTotalPrediction = (nPrediction1 * m_aryMB[0]) + (nPrediction2 * m_aryMB[1])
|
||||
+ (nPrediction3 * m_aryMB[2]) + (nPrediction4 * m_aryMB[3]);
|
||||
int nOutput = nB - (nTotalPrediction >> 13);
|
||||
|
||||
if (nOutput > 0)
|
||||
{
|
||||
m_aryMB[0] -= 2*((nPrediction1) ? ((nPrediction1 >> 30) & 2) - 1 : 0);
|
||||
m_aryMB[1] -= (nPrediction2) ? ((nPrediction2 >> 30) & 2) - 1 : 0;
|
||||
m_aryMB[2] -= (nPrediction3) ? ((nPrediction3 >> 30) & 2) - 1 : 0;
|
||||
m_aryMB[3] -= 1*((nPrediction4) ? ((nPrediction4 >> 30) & 2) - 1 : 0);
|
||||
}
|
||||
else if (nOutput < 0)
|
||||
{
|
||||
m_aryMB[0] += 2*((nPrediction1) ? ((nPrediction1 >> 30) & 2) - 1 : 0);
|
||||
m_aryMB[1] += (nPrediction2) ? ((nPrediction2 >> 30) & 2) - 1 : 0;
|
||||
m_aryMB[2] += (nPrediction3) ? ((nPrediction3 >> 30) & 2) - 1 : 0;
|
||||
m_aryMB[3] += 1*((nPrediction4) ? ((nPrediction4 >> 30) & 2) - 1 : 0);
|
||||
}
|
||||
|
||||
nB = nOutput;
|
||||
}
|
||||
|
||||
|
||||
m_rbInputA.IncrementSafe();
|
||||
m_rbInputB.IncrementSafe();
|
||||
|
||||
|
||||
/*
|
||||
// nInput = m_Filter1.Compress(nInput);
|
||||
|
||||
m_rbInput[0] = nInput;
|
||||
|
||||
int nPrediction1 = m_rbInput[-1];
|
||||
int nPrediction2 = (2 * m_rbInput[-1]) - m_rbInput[-2];
|
||||
int nPrediction3 = m_rbInput[-1] - m_rbInput[-2];
|
||||
int nPrediction4 = m_nLastOutput;
|
||||
|
||||
int nTotalPrediction = ((nPrediction1) * m_aryM[0]) + (nPrediction2 * m_aryM[1])
|
||||
+ ((nPrediction3 >> 1) * m_aryM[2]) + (nPrediction4 * m_aryM[3]);
|
||||
int nOutput = nInput - (nTotalPrediction >> 13);
|
||||
|
||||
if (nOutput > 0)
|
||||
{
|
||||
m_aryM[0] -= (nPrediction1) ? ((nPrediction1 >> 30) & 2) - 1 : 0;
|
||||
m_aryM[1] -= (nPrediction2) ? ((nPrediction2 >> 30) & 2) - 1 : 0;
|
||||
m_aryM[2] -= (nPrediction3) ? ((nPrediction3 >> 30) & 2) - 1 : 0;
|
||||
m_aryM[3] -= (nPrediction4) ? ((nPrediction4 >> 30) & 2) - 1 : 0;
|
||||
}
|
||||
else if (nOutput < 0)
|
||||
{
|
||||
m_aryM[0] += (nPrediction1) ? ((nPrediction1 >> 30) & 2) - 1 : 0;
|
||||
m_aryM[1] += (nPrediction2) ? ((nPrediction2 >> 30) & 2) - 1 : 0;
|
||||
m_aryM[2] += (nPrediction3) ? ((nPrediction3 >> 30) & 2) - 1 : 0;
|
||||
m_aryM[3] += (nPrediction4) ? ((nPrediction4 >> 30) & 2) - 1 : 0;
|
||||
}
|
||||
|
||||
m_nLastOutput = nOutput;
|
||||
m_rbInput.IncrementSafe();
|
||||
|
||||
return nOutput;
|
||||
//*/
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
CScaledFirstOrderFilter<31, 5> m_Stage1FilterA1;
|
||||
CScaledFirstOrderFilter<24, 5> m_Stage1FilterA2;
|
||||
CScaledFirstOrderFilter<7, 5> m_Stage1FilterA3;
|
||||
|
||||
CScaledFirstOrderFilter<31, 5> m_Stage1FilterB1;
|
||||
CScaledFirstOrderFilter<24, 5> m_Stage1FilterB2;
|
||||
CScaledFirstOrderFilter<7, 5> m_Stage1FilterB3;
|
||||
|
||||
CRollBufferFast<int, 256, 4> m_rbInputA;
|
||||
CRollBufferFast<int, 256, 4> m_rbInputB;
|
||||
int m_aryMA[8]; int m_aryMB[8];
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_START_FILTER_H
|
||||
293
MAC_SDK/Source/MACLib/UnBitArray.cpp
Normal file
293
MAC_SDK/Source/MACLib/UnBitArray.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
#include "All.h"
|
||||
#include "APEInfo.h"
|
||||
#include "UnBitArray.h"
|
||||
#include "BitArray.h"
|
||||
|
||||
const uint32 POWERS_OF_TWO_MINUS_ONE_REVERSED[33] = {4294967295,2147483647,1073741823,536870911,268435455,134217727,67108863,33554431,16777215,8388607,4194303,2097151,1048575,524287,262143,131071,65535,32767,16383,8191,4095,2047,1023,511,255,127,63,31,15,7,3,1,0};
|
||||
|
||||
const uint32 K_SUM_MIN_BOUNDARY[32] = {0,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,0,0,0,0};
|
||||
|
||||
const uint32 RANGE_TOTAL_1[65] = {0,14824,28224,39348,47855,53994,58171,60926,62682,63786,64463,64878,65126,65276,65365,65419,65450,65469,65480,65487,65491,65493,65494,65495,65496,65497,65498,65499,65500,65501,65502,65503,65504,65505,65506,65507,65508,65509,65510,65511,65512,65513,65514,65515,65516,65517,65518,65519,65520,65521,65522,65523,65524,65525,65526,65527,65528,65529,65530,65531,65532,65533,65534,65535,65536};
|
||||
const uint32 RANGE_WIDTH_1[64] = {14824,13400,11124,8507,6139,4177,2755,1756,1104,677,415,248,150,89,54,31,19,11,7,4,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
|
||||
|
||||
const uint32 RANGE_TOTAL_2[65] = {0,19578,36160,48417,56323,60899,63265,64435,64971,65232,65351,65416,65447,65466,65476,65482,65485,65488,65490,65491,65492,65493,65494,65495,65496,65497,65498,65499,65500,65501,65502,65503,65504,65505,65506,65507,65508,65509,65510,65511,65512,65513,65514,65515,65516,65517,65518,65519,65520,65521,65522,65523,65524,65525,65526,65527,65528,65529,65530,65531,65532,65533,65534,65535,65536};
|
||||
const uint32 RANGE_WIDTH_2[64] = {19578,16582,12257,7906,4576,2366,1170,536,261,119,65,31,19,10,6,3,3,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,};
|
||||
|
||||
#define RANGE_OVERFLOW_TOTAL_WIDTH 65536
|
||||
#define RANGE_OVERFLOW_SHIFT 16
|
||||
|
||||
#define CODE_BITS 32
|
||||
#define TOP_VALUE ((unsigned int ) 1 << (CODE_BITS - 1))
|
||||
#define SHIFT_BITS (CODE_BITS - 9)
|
||||
#define EXTRA_BITS ((CODE_BITS - 2) % 8 + 1)
|
||||
#define BOTTOM_VALUE (TOP_VALUE >> 8)
|
||||
|
||||
#define MODEL_ELEMENTS 64
|
||||
|
||||
/***********************************************************************************
|
||||
Construction
|
||||
***********************************************************************************/
|
||||
CUnBitArray::CUnBitArray(CIO * pIO, int nVersion)
|
||||
{
|
||||
CreateHelper(pIO, 16384, nVersion);
|
||||
m_nFlushCounter = 0;
|
||||
m_nFinalizeCounter = 0;
|
||||
}
|
||||
|
||||
CUnBitArray::~CUnBitArray()
|
||||
{
|
||||
SAFE_ARRAY_DELETE(m_pBitArray)
|
||||
}
|
||||
|
||||
unsigned int CUnBitArray::DecodeValue(DECODE_VALUE_METHOD DecodeMethod, int nParam1, int nParam2)
|
||||
{
|
||||
switch (DecodeMethod)
|
||||
{
|
||||
case DECODE_VALUE_METHOD_UNSIGNED_INT:
|
||||
return DecodeValueXBits(32);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CUnBitArray::GenerateArray(int * pOutputArray, int nElements, int nBytesRequired)
|
||||
{
|
||||
GenerateArrayRange(pOutputArray, nElements);
|
||||
}
|
||||
|
||||
__inline unsigned char CUnBitArray::GetC()
|
||||
{
|
||||
unsigned char nValue = (unsigned char) (m_pBitArray[m_nCurrentBitIndex >> 5] >> (24 - (m_nCurrentBitIndex & 31)));
|
||||
m_nCurrentBitIndex += 8;
|
||||
return nValue;
|
||||
}
|
||||
|
||||
__inline int CUnBitArray::RangeDecodeFast(int nShift)
|
||||
{
|
||||
while (m_RangeCoderInfo.range <= BOTTOM_VALUE)
|
||||
{
|
||||
m_RangeCoderInfo.buffer = (m_RangeCoderInfo.buffer << 8) | ((m_pBitArray[m_nCurrentBitIndex >> 5] >> (24 - (m_nCurrentBitIndex & 31))) & 0xFF);
|
||||
m_nCurrentBitIndex += 8;
|
||||
m_RangeCoderInfo.low = (m_RangeCoderInfo.low << 8) | ((m_RangeCoderInfo.buffer >> 1) & 0xFF);
|
||||
m_RangeCoderInfo.range <<= 8;
|
||||
}
|
||||
|
||||
// decode
|
||||
m_RangeCoderInfo.range = m_RangeCoderInfo.range >> nShift;
|
||||
return m_RangeCoderInfo.low / m_RangeCoderInfo.range;
|
||||
}
|
||||
|
||||
__inline int CUnBitArray::RangeDecodeFastWithUpdate(int nShift)
|
||||
{
|
||||
while (m_RangeCoderInfo.range <= BOTTOM_VALUE)
|
||||
{
|
||||
m_RangeCoderInfo.buffer = (m_RangeCoderInfo.buffer << 8) | ((m_pBitArray[m_nCurrentBitIndex >> 5] >> (24 - (m_nCurrentBitIndex & 31))) & 0xFF);
|
||||
m_nCurrentBitIndex += 8;
|
||||
m_RangeCoderInfo.low = (m_RangeCoderInfo.low << 8) | ((m_RangeCoderInfo.buffer >> 1) & 0xFF);
|
||||
m_RangeCoderInfo.range <<= 8;
|
||||
}
|
||||
|
||||
// decode
|
||||
m_RangeCoderInfo.range = m_RangeCoderInfo.range >> nShift;
|
||||
int nRetVal = m_RangeCoderInfo.low / m_RangeCoderInfo.range;
|
||||
m_RangeCoderInfo.low -= m_RangeCoderInfo.range * nRetVal;
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int CUnBitArray::DecodeValueRange(UNBIT_ARRAY_STATE & BitArrayState)
|
||||
{
|
||||
// make sure there is room for the data
|
||||
// this is a little slower than ensuring a huge block to start with, but it's safer
|
||||
if (m_nCurrentBitIndex > m_nRefillBitThreshold)
|
||||
{
|
||||
FillBitArray();
|
||||
}
|
||||
|
||||
int nValue = 0;
|
||||
|
||||
if (m_nVersion >= 3990)
|
||||
{
|
||||
// figure the pivot value
|
||||
int nPivotValue = max(BitArrayState.nKSum / 32, 1);
|
||||
|
||||
// get the overflow
|
||||
int nOverflow = 0;
|
||||
{
|
||||
// decode
|
||||
int nRangeTotal = RangeDecodeFast(RANGE_OVERFLOW_SHIFT);
|
||||
|
||||
// lookup the symbol (must be a faster way than this)
|
||||
while (nRangeTotal >= RANGE_TOTAL_2[nOverflow + 1]) { nOverflow++; }
|
||||
|
||||
// update
|
||||
m_RangeCoderInfo.low -= m_RangeCoderInfo.range * RANGE_TOTAL_2[nOverflow];
|
||||
m_RangeCoderInfo.range = m_RangeCoderInfo.range * RANGE_WIDTH_2[nOverflow];
|
||||
|
||||
// get the working k
|
||||
if (nOverflow == (MODEL_ELEMENTS - 1))
|
||||
{
|
||||
nOverflow = RangeDecodeFastWithUpdate(16);
|
||||
nOverflow <<= 16;
|
||||
nOverflow |= RangeDecodeFastWithUpdate(16);
|
||||
}
|
||||
}
|
||||
|
||||
// get the value
|
||||
int nBase = 0;
|
||||
{
|
||||
int nShift = 0;
|
||||
if (nPivotValue >= (1 << 16))
|
||||
{
|
||||
int nPivotValueBits = 0;
|
||||
while ((nPivotValue >> nPivotValueBits) > 0) { nPivotValueBits++; }
|
||||
int nSplitFactor = 1 << (nPivotValueBits - 16);
|
||||
|
||||
int nPivotValueA = (nPivotValue / nSplitFactor) + 1;
|
||||
int nPivotValueB = nSplitFactor;
|
||||
|
||||
while (m_RangeCoderInfo.range <= BOTTOM_VALUE)
|
||||
{
|
||||
m_RangeCoderInfo.buffer = (m_RangeCoderInfo.buffer << 8) | ((m_pBitArray[m_nCurrentBitIndex >> 5] >> (24 - (m_nCurrentBitIndex & 31))) & 0xFF);
|
||||
m_nCurrentBitIndex += 8;
|
||||
m_RangeCoderInfo.low = (m_RangeCoderInfo.low << 8) | ((m_RangeCoderInfo.buffer >> 1) & 0xFF);
|
||||
m_RangeCoderInfo.range <<= 8;
|
||||
}
|
||||
m_RangeCoderInfo.range = m_RangeCoderInfo.range / nPivotValueA;
|
||||
int nBaseA = m_RangeCoderInfo.low / m_RangeCoderInfo.range;
|
||||
m_RangeCoderInfo.low -= m_RangeCoderInfo.range * nBaseA;
|
||||
|
||||
while (m_RangeCoderInfo.range <= BOTTOM_VALUE)
|
||||
{
|
||||
m_RangeCoderInfo.buffer = (m_RangeCoderInfo.buffer << 8) | ((m_pBitArray[m_nCurrentBitIndex >> 5] >> (24 - (m_nCurrentBitIndex & 31))) & 0xFF);
|
||||
m_nCurrentBitIndex += 8;
|
||||
m_RangeCoderInfo.low = (m_RangeCoderInfo.low << 8) | ((m_RangeCoderInfo.buffer >> 1) & 0xFF);
|
||||
m_RangeCoderInfo.range <<= 8;
|
||||
}
|
||||
m_RangeCoderInfo.range = m_RangeCoderInfo.range / nPivotValueB;
|
||||
int nBaseB = m_RangeCoderInfo.low / m_RangeCoderInfo.range;
|
||||
m_RangeCoderInfo.low -= m_RangeCoderInfo.range * nBaseB;
|
||||
|
||||
nBase = nBaseA * nSplitFactor + nBaseB;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (m_RangeCoderInfo.range <= BOTTOM_VALUE)
|
||||
{
|
||||
m_RangeCoderInfo.buffer = (m_RangeCoderInfo.buffer << 8) | ((m_pBitArray[m_nCurrentBitIndex >> 5] >> (24 - (m_nCurrentBitIndex & 31))) & 0xFF);
|
||||
m_nCurrentBitIndex += 8;
|
||||
m_RangeCoderInfo.low = (m_RangeCoderInfo.low << 8) | ((m_RangeCoderInfo.buffer >> 1) & 0xFF);
|
||||
m_RangeCoderInfo.range <<= 8;
|
||||
}
|
||||
|
||||
// decode
|
||||
m_RangeCoderInfo.range = m_RangeCoderInfo.range / nPivotValue;
|
||||
int nBaseLower = m_RangeCoderInfo.low / m_RangeCoderInfo.range;
|
||||
m_RangeCoderInfo.low -= m_RangeCoderInfo.range * nBaseLower;
|
||||
|
||||
nBase = nBaseLower;
|
||||
}
|
||||
}
|
||||
|
||||
// build the value
|
||||
nValue = nBase + (nOverflow * nPivotValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// decode
|
||||
int nRangeTotal = RangeDecodeFast(RANGE_OVERFLOW_SHIFT);
|
||||
|
||||
// lookup the symbol (must be a faster way than this)
|
||||
int nOverflow = 0;
|
||||
while (nRangeTotal >= RANGE_TOTAL_1[nOverflow + 1]) { nOverflow++; }
|
||||
|
||||
// update
|
||||
m_RangeCoderInfo.low -= m_RangeCoderInfo.range * RANGE_TOTAL_1[nOverflow];
|
||||
m_RangeCoderInfo.range = m_RangeCoderInfo.range * RANGE_WIDTH_1[nOverflow];
|
||||
|
||||
// get the working k
|
||||
int nTempK;
|
||||
if (nOverflow == (MODEL_ELEMENTS - 1))
|
||||
{
|
||||
nTempK = RangeDecodeFastWithUpdate(5);
|
||||
nOverflow = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nTempK = (BitArrayState.k < 1) ? 0 : BitArrayState.k - 1;
|
||||
}
|
||||
|
||||
// figure the extra bits on the left and the left value
|
||||
if (nTempK <= 16 || m_nVersion < 3910)
|
||||
{
|
||||
nValue = RangeDecodeFastWithUpdate(nTempK);
|
||||
}
|
||||
else
|
||||
{
|
||||
int nX1 = RangeDecodeFastWithUpdate(16);
|
||||
int nX2 = RangeDecodeFastWithUpdate(nTempK - 16);
|
||||
nValue = nX1 | (nX2 << 16);
|
||||
}
|
||||
|
||||
// build the value and output it
|
||||
nValue += (nOverflow << nTempK);
|
||||
}
|
||||
|
||||
// update nKSum
|
||||
BitArrayState.nKSum += ((nValue + 1) / 2) - ((BitArrayState.nKSum + 16) >> 5);
|
||||
|
||||
// update k
|
||||
if (BitArrayState.nKSum < K_SUM_MIN_BOUNDARY[BitArrayState.k])
|
||||
BitArrayState.k--;
|
||||
else if (BitArrayState.nKSum >= K_SUM_MIN_BOUNDARY[BitArrayState.k + 1])
|
||||
BitArrayState.k++;
|
||||
|
||||
// output the value (converted to signed)
|
||||
return (nValue & 1) ? (nValue >> 1) + 1 : -(nValue >> 1);
|
||||
}
|
||||
|
||||
void CUnBitArray::FlushState(UNBIT_ARRAY_STATE & BitArrayState)
|
||||
{
|
||||
BitArrayState.k = 10;
|
||||
BitArrayState.nKSum = (1 << BitArrayState.k) * 16;
|
||||
}
|
||||
|
||||
void CUnBitArray::FlushBitArray()
|
||||
{
|
||||
AdvanceToByteBoundary();
|
||||
m_nCurrentBitIndex += 8; // ignore the first byte... (slows compression too much to not output this dummy byte)
|
||||
m_RangeCoderInfo.buffer = GetC();
|
||||
m_RangeCoderInfo.low = m_RangeCoderInfo.buffer >> (8 - EXTRA_BITS);
|
||||
m_RangeCoderInfo.range = (unsigned int) 1 << EXTRA_BITS;
|
||||
|
||||
m_nRefillBitThreshold = (m_nBits - 512);
|
||||
}
|
||||
|
||||
void CUnBitArray::Finalize()
|
||||
{
|
||||
// normalize
|
||||
while (m_RangeCoderInfo.range <= BOTTOM_VALUE)
|
||||
{
|
||||
m_nCurrentBitIndex += 8;
|
||||
m_RangeCoderInfo.range <<= 8;
|
||||
}
|
||||
|
||||
// used to back-pedal the last two bytes out
|
||||
// this should never have been a problem because we've outputted and normalized beforehand
|
||||
// but stopped doing it as of 3.96 in case it accounted for rare decompression failures
|
||||
if (m_nVersion <= 3950)
|
||||
m_nCurrentBitIndex -= 16;
|
||||
}
|
||||
|
||||
void CUnBitArray::GenerateArrayRange(int * pOutputArray, int nElements)
|
||||
{
|
||||
UNBIT_ARRAY_STATE BitArrayState;
|
||||
FlushState(BitArrayState);
|
||||
FlushBitArray();
|
||||
|
||||
for (int z = 0; z < nElements; z++)
|
||||
{
|
||||
pOutputArray[z] = DecodeValueRange(BitArrayState);
|
||||
}
|
||||
|
||||
Finalize();
|
||||
}
|
||||
51
MAC_SDK/Source/MACLib/UnBitArray.h
Normal file
51
MAC_SDK/Source/MACLib/UnBitArray.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef APE_UNBITARRAY_H
|
||||
#define APE_UNBITARRAY_H
|
||||
|
||||
#include "UnBitArrayBase.h"
|
||||
|
||||
class IAPEDecompress;
|
||||
|
||||
struct RANGE_CODER_STRUCT_DECOMPRESS
|
||||
{
|
||||
unsigned int low; // low end of interval
|
||||
unsigned int range; // length of interval
|
||||
unsigned int buffer; // buffer for input/output
|
||||
};
|
||||
|
||||
class CUnBitArray : public CUnBitArrayBase
|
||||
{
|
||||
public:
|
||||
|
||||
// construction/destruction
|
||||
CUnBitArray(CIO * pIO, int nVersion);
|
||||
~CUnBitArray();
|
||||
|
||||
unsigned int DecodeValue(DECODE_VALUE_METHOD DecodeMethod, int nParam1 = 0, int nParam2 = 0);
|
||||
|
||||
void GenerateArray(int * pOutputArray, int nElements, int nBytesRequired = -1);
|
||||
|
||||
int DecodeValueRange(UNBIT_ARRAY_STATE & BitArrayState);
|
||||
|
||||
void FlushState(UNBIT_ARRAY_STATE & BitArrayState);
|
||||
void FlushBitArray();
|
||||
void Finalize();
|
||||
|
||||
private:
|
||||
|
||||
void GenerateArrayRange(int * pOutputArray, int nElements);
|
||||
|
||||
// data
|
||||
int m_nFlushCounter;
|
||||
int m_nFinalizeCounter;
|
||||
|
||||
RANGE_CODER_STRUCT_DECOMPRESS m_RangeCoderInfo;
|
||||
|
||||
uint32 m_nRefillBitThreshold;
|
||||
|
||||
// functions
|
||||
inline int RangeDecodeFast(int nShift);
|
||||
inline int RangeDecodeFastWithUpdate(int nShift);
|
||||
inline unsigned char GetC();
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_UNBITARRAY_H
|
||||
112
MAC_SDK/Source/MACLib/UnBitArrayBase.cpp
Normal file
112
MAC_SDK/Source/MACLib/UnBitArrayBase.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "All.h"
|
||||
#include "UnBitArrayBase.h"
|
||||
#include "APEInfo.h"
|
||||
#include "UnBitArray.h"
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
#include "Old/APEDecompressOld.h"
|
||||
#include "Old/UnBitArrayOld.h"
|
||||
#endif
|
||||
|
||||
const uint32 POWERS_OF_TWO_MINUS_ONE[33] = {0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535,131071,262143,524287,1048575,2097151,4194303,8388607,16777215,33554431,67108863,134217727,268435455,536870911,1073741823,2147483647,4294967295};
|
||||
|
||||
CUnBitArrayBase * CreateUnBitArray(IAPEDecompress * pAPEDecompress, int nVersion)
|
||||
{
|
||||
#ifdef BACKWARDS_COMPATIBILITY
|
||||
if (nVersion >= 3900)
|
||||
return (CUnBitArrayBase * ) new CUnBitArray(GET_IO(pAPEDecompress), nVersion);
|
||||
else
|
||||
return (CUnBitArrayBase * ) new CUnBitArrayOld(pAPEDecompress, nVersion);
|
||||
#else
|
||||
return (CUnBitArrayBase * ) new CUnBitArray(GET_IO(pAPEDecompress), nVersion);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CUnBitArrayBase::AdvanceToByteBoundary()
|
||||
{
|
||||
int nMod = m_nCurrentBitIndex % 8;
|
||||
if (nMod != 0) { m_nCurrentBitIndex += 8 - nMod; }
|
||||
}
|
||||
|
||||
uint32 CUnBitArrayBase::DecodeValueXBits(uint32 nBits)
|
||||
{
|
||||
// get more data if necessary
|
||||
if ((m_nCurrentBitIndex + nBits) >= m_nBits)
|
||||
FillBitArray();
|
||||
|
||||
// variable declares
|
||||
uint32 nLeftBits = 32 - (m_nCurrentBitIndex & 31);
|
||||
uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5;
|
||||
m_nCurrentBitIndex += nBits;
|
||||
|
||||
// if their isn't an overflow to the right value, get the value and exit
|
||||
if (nLeftBits >= nBits)
|
||||
return (m_pBitArray[nBitArrayIndex] & (POWERS_OF_TWO_MINUS_ONE[nLeftBits])) >> (nLeftBits - nBits);
|
||||
|
||||
// must get the "split" value from left and right
|
||||
int nRightBits = nBits - nLeftBits;
|
||||
|
||||
uint32 nLeftValue = ((m_pBitArray[nBitArrayIndex] & POWERS_OF_TWO_MINUS_ONE[nLeftBits]) << nRightBits);
|
||||
uint32 nRightValue = (m_pBitArray[nBitArrayIndex + 1] >> (32 - nRightBits));
|
||||
return (nLeftValue | nRightValue);
|
||||
}
|
||||
|
||||
int CUnBitArrayBase::FillAndResetBitArray(int nFileLocation, int nNewBitIndex)
|
||||
{
|
||||
// reset the bit index
|
||||
m_nCurrentBitIndex = nNewBitIndex;
|
||||
|
||||
// seek if necessary
|
||||
if (nFileLocation != -1)
|
||||
{
|
||||
if (m_pIO->Seek(nFileLocation, FILE_BEGIN) != 0)
|
||||
return ERROR_IO_READ;
|
||||
}
|
||||
|
||||
// read the new data into the bit array
|
||||
unsigned int nBytesRead = 0;
|
||||
if (m_pIO->Read(((unsigned char *) m_pBitArray), m_nBytes, &nBytesRead) != 0)
|
||||
return ERROR_IO_READ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CUnBitArrayBase::FillBitArray()
|
||||
{
|
||||
// get the bit array index
|
||||
uint32 nBitArrayIndex = m_nCurrentBitIndex >> 5;
|
||||
|
||||
// move the remaining data to the front
|
||||
memmove((void *) (m_pBitArray), (const void *) (m_pBitArray + nBitArrayIndex), m_nBytes - (nBitArrayIndex * 4));
|
||||
|
||||
// read the new data
|
||||
int nBytesToRead = nBitArrayIndex * 4;
|
||||
unsigned int nBytesRead = 0;
|
||||
int nRetVal = m_pIO->Read((unsigned char *) (m_pBitArray + m_nElements - nBitArrayIndex), nBytesToRead, &nBytesRead);
|
||||
|
||||
// adjust the m_Bit pointer
|
||||
m_nCurrentBitIndex = m_nCurrentBitIndex & 31;
|
||||
|
||||
// return
|
||||
return (nRetVal == 0) ? 0 : ERROR_IO_READ;
|
||||
}
|
||||
|
||||
int CUnBitArrayBase::CreateHelper(CIO * pIO, int nBytes, int nVersion)
|
||||
{
|
||||
// check the parameters
|
||||
if ((pIO == NULL) || (nBytes <= 0)) { return ERROR_BAD_PARAMETER; }
|
||||
|
||||
// save the size
|
||||
m_nElements = nBytes / 4;
|
||||
m_nBytes = m_nElements * 4;
|
||||
m_nBits = m_nBytes * 8;
|
||||
|
||||
// set the variables
|
||||
m_pIO = pIO;
|
||||
m_nVersion = nVersion;
|
||||
m_nCurrentBitIndex = 0;
|
||||
|
||||
// create the bitarray
|
||||
m_pBitArray = new uint32 [m_nElements];
|
||||
|
||||
return (m_pBitArray != NULL) ? 0 : ERROR_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
59
MAC_SDK/Source/MACLib/UnBitArrayBase.h
Normal file
59
MAC_SDK/Source/MACLib/UnBitArrayBase.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef APE_UNBITARRAYBASE_H
|
||||
#define APE_UNBITARRAYBASE_H
|
||||
|
||||
class IAPEDecompress;
|
||||
class CIO;
|
||||
|
||||
struct UNBIT_ARRAY_STATE
|
||||
{
|
||||
uint32 k;
|
||||
uint32 nKSum;
|
||||
};
|
||||
|
||||
enum DECODE_VALUE_METHOD
|
||||
{
|
||||
DECODE_VALUE_METHOD_UNSIGNED_INT,
|
||||
DECODE_VALUE_METHOD_UNSIGNED_RICE,
|
||||
DECODE_VALUE_METHOD_X_BITS
|
||||
};
|
||||
|
||||
class CUnBitArrayBase
|
||||
{
|
||||
public:
|
||||
|
||||
// virtual destructor
|
||||
virtual ~CUnBitArrayBase() {}
|
||||
|
||||
// functions
|
||||
virtual int FillBitArray();
|
||||
virtual int FillAndResetBitArray(int nFileLocation = -1, int nNewBitIndex = 0);
|
||||
|
||||
virtual void GenerateArray(int * pOutputArray, int nElements, int nBytesRequired = -1) {}
|
||||
virtual unsigned int DecodeValue(DECODE_VALUE_METHOD DecodeMethod, int nParam1 = 0, int nParam2 = 0) { return 0; }
|
||||
|
||||
virtual void AdvanceToByteBoundary();
|
||||
|
||||
virtual int DecodeValueRange(UNBIT_ARRAY_STATE & BitArrayState) { return 0; }
|
||||
virtual void FlushState(UNBIT_ARRAY_STATE & BitArrayState) {}
|
||||
virtual void FlushBitArray() {}
|
||||
virtual void Finalize() {}
|
||||
|
||||
protected:
|
||||
|
||||
virtual int CreateHelper(CIO * pIO, int nBytes, int nVersion);
|
||||
virtual uint32 DecodeValueXBits(uint32 nBits);
|
||||
|
||||
uint32 m_nElements;
|
||||
uint32 m_nBytes;
|
||||
uint32 m_nBits;
|
||||
|
||||
int m_nVersion;
|
||||
CIO * m_pIO;
|
||||
|
||||
uint32 m_nCurrentBitIndex;
|
||||
uint32 * m_pBitArray;
|
||||
};
|
||||
|
||||
CUnBitArrayBase * CreateUnBitArray(IAPEDecompress * pAPEDecompress, int nVersion);
|
||||
|
||||
#endif // #ifndef APE_UNBITARRAYBASE_H
|
||||
279
MAC_SDK/Source/MACLib/WAVInputSource.cpp
Normal file
279
MAC_SDK/Source/MACLib/WAVInputSource.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
#include "All.h"
|
||||
#include "WAVInputSource.h"
|
||||
#include IO_HEADER_FILE
|
||||
#include "MACLib.h"
|
||||
#include "GlobalFunctions.h"
|
||||
|
||||
struct RIFF_HEADER
|
||||
{
|
||||
char cRIFF[4]; // the characters 'RIFF' indicating that it's a RIFF file
|
||||
unsigned long nBytes; // the number of bytes following this header
|
||||
};
|
||||
|
||||
struct DATA_TYPE_ID_HEADER
|
||||
{
|
||||
char cDataTypeID[4]; // should equal 'WAVE' for a WAV file
|
||||
};
|
||||
|
||||
struct WAV_FORMAT_HEADER
|
||||
{
|
||||
unsigned short nFormatTag; // the format of the WAV...should equal 1 for a PCM file
|
||||
unsigned short nChannels; // the number of channels
|
||||
unsigned long nSamplesPerSecond; // the number of samples per second
|
||||
unsigned long nBytesPerSecond; // the bytes per second
|
||||
unsigned short nBlockAlign; // block alignment
|
||||
unsigned short nBitsPerSample; // the number of bits per sample
|
||||
};
|
||||
|
||||
struct RIFF_CHUNK_HEADER
|
||||
{
|
||||
char cChunkLabel[4]; // should equal "data" indicating the data chunk
|
||||
unsigned long nChunkBytes; // the bytes of the chunk
|
||||
};
|
||||
|
||||
|
||||
CInputSource * CreateInputSource(const wchar_t * pSourceName, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode)
|
||||
{
|
||||
// error check the parameters
|
||||
if ((pSourceName == NULL) || (wcslen(pSourceName) == 0))
|
||||
{
|
||||
if (pErrorCode) *pErrorCode = ERROR_BAD_PARAMETER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the extension
|
||||
const wchar_t * pExtension = &pSourceName[wcslen(pSourceName)];
|
||||
while ((pExtension > pSourceName) && (*pExtension != '.'))
|
||||
pExtension--;
|
||||
|
||||
// create the proper input source
|
||||
if (wcsicmp(pExtension, L".wav") == 0)
|
||||
{
|
||||
if (pErrorCode) *pErrorCode = ERROR_SUCCESS;
|
||||
return new CWAVInputSource(pSourceName, pwfeSource, pTotalBlocks, pHeaderBytes, pTerminatingBytes, pErrorCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pErrorCode) *pErrorCode = ERROR_INVALID_INPUT_FILE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CWAVInputSource::CWAVInputSource(CIO * pIO, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode)
|
||||
: CInputSource(pIO, pwfeSource, pTotalBlocks, pHeaderBytes, pTerminatingBytes, pErrorCode)
|
||||
{
|
||||
m_bIsValid = FALSE;
|
||||
|
||||
if (pIO == NULL || pwfeSource == NULL)
|
||||
{
|
||||
if (pErrorCode) *pErrorCode = ERROR_BAD_PARAMETER;
|
||||
return;
|
||||
}
|
||||
|
||||
m_spIO.Assign(pIO, FALSE, FALSE);
|
||||
|
||||
int nRetVal = AnalyzeSource();
|
||||
if (nRetVal == ERROR_SUCCESS)
|
||||
{
|
||||
// fill in the parameters
|
||||
if (pwfeSource) memcpy(pwfeSource, &m_wfeSource, sizeof(WAVEFORMATEX));
|
||||
if (pTotalBlocks) *pTotalBlocks = m_nDataBytes / m_wfeSource.nBlockAlign;
|
||||
if (pHeaderBytes) *pHeaderBytes = m_nHeaderBytes;
|
||||
if (pTerminatingBytes) *pTerminatingBytes = m_nTerminatingBytes;
|
||||
|
||||
m_bIsValid = TRUE;
|
||||
}
|
||||
|
||||
if (pErrorCode) *pErrorCode = nRetVal;
|
||||
}
|
||||
|
||||
CWAVInputSource::CWAVInputSource(const wchar_t * pSourceName, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode)
|
||||
: CInputSource(pSourceName, pwfeSource, pTotalBlocks, pHeaderBytes, pTerminatingBytes, pErrorCode)
|
||||
{
|
||||
m_bIsValid = FALSE;
|
||||
|
||||
if (pSourceName == NULL || pwfeSource == NULL)
|
||||
{
|
||||
if (pErrorCode) *pErrorCode = ERROR_BAD_PARAMETER;
|
||||
return;
|
||||
}
|
||||
|
||||
m_spIO.Assign(new IO_CLASS_NAME);
|
||||
if (m_spIO->Open(pSourceName) != ERROR_SUCCESS)
|
||||
{
|
||||
m_spIO.Delete();
|
||||
if (pErrorCode) *pErrorCode = ERROR_INVALID_INPUT_FILE;
|
||||
return;
|
||||
}
|
||||
|
||||
int nRetVal = AnalyzeSource();
|
||||
if (nRetVal == ERROR_SUCCESS)
|
||||
{
|
||||
// fill in the parameters
|
||||
if (pwfeSource) memcpy(pwfeSource, &m_wfeSource, sizeof(WAVEFORMATEX));
|
||||
if (pTotalBlocks) *pTotalBlocks = m_nDataBytes / m_wfeSource.nBlockAlign;
|
||||
if (pHeaderBytes) *pHeaderBytes = m_nHeaderBytes;
|
||||
if (pTerminatingBytes) *pTerminatingBytes = m_nTerminatingBytes;
|
||||
|
||||
m_bIsValid = TRUE;
|
||||
}
|
||||
|
||||
if (pErrorCode) *pErrorCode = nRetVal;
|
||||
}
|
||||
|
||||
CWAVInputSource::~CWAVInputSource()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
int CWAVInputSource::AnalyzeSource()
|
||||
{
|
||||
// seek to the beginning (just in case)
|
||||
m_spIO->Seek(0, FILE_BEGIN);
|
||||
|
||||
// get the file size
|
||||
m_nFileBytes = m_spIO->GetSize();
|
||||
|
||||
// get the RIFF header
|
||||
RIFF_HEADER RIFFHeader;
|
||||
RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFHeader, sizeof(RIFFHeader)))
|
||||
|
||||
// make sure the RIFF header is valid
|
||||
if (!(RIFFHeader.cRIFF[0] == 'R' && RIFFHeader.cRIFF[1] == 'I' && RIFFHeader.cRIFF[2] == 'F' && RIFFHeader.cRIFF[3] == 'F'))
|
||||
return ERROR_INVALID_INPUT_FILE;
|
||||
|
||||
// read the data type header
|
||||
DATA_TYPE_ID_HEADER DataTypeIDHeader;
|
||||
RETURN_ON_ERROR(ReadSafe(m_spIO, &DataTypeIDHeader, sizeof(DataTypeIDHeader)))
|
||||
|
||||
// make sure it's the right data type
|
||||
if (!(DataTypeIDHeader.cDataTypeID[0] == 'W' && DataTypeIDHeader.cDataTypeID[1] == 'A' && DataTypeIDHeader.cDataTypeID[2] == 'V' && DataTypeIDHeader.cDataTypeID[3] == 'E'))
|
||||
return ERROR_INVALID_INPUT_FILE;
|
||||
|
||||
// find the 'fmt ' chunk
|
||||
RIFF_CHUNK_HEADER RIFFChunkHeader;
|
||||
RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader)))
|
||||
|
||||
while (!(RIFFChunkHeader.cChunkLabel[0] == 'f' && RIFFChunkHeader.cChunkLabel[1] == 'm' && RIFFChunkHeader.cChunkLabel[2] == 't' && RIFFChunkHeader.cChunkLabel[3] == ' '))
|
||||
{
|
||||
// move the file pointer to the end of this chunk
|
||||
m_spIO->Seek(RIFFChunkHeader.nChunkBytes, FILE_CURRENT);
|
||||
|
||||
// check again for the data chunk
|
||||
RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader)))
|
||||
}
|
||||
|
||||
// read the format info
|
||||
WAV_FORMAT_HEADER WAVFormatHeader;
|
||||
RETURN_ON_ERROR(ReadSafe(m_spIO, &WAVFormatHeader, sizeof(WAVFormatHeader)))
|
||||
|
||||
// error check the header to see if we support it
|
||||
if (WAVFormatHeader.nFormatTag != 1)
|
||||
return ERROR_INVALID_INPUT_FILE;
|
||||
|
||||
// copy the format information to the WAVEFORMATEX passed in
|
||||
FillWaveFormatEx(&m_wfeSource, WAVFormatHeader.nSamplesPerSecond, WAVFormatHeader.nBitsPerSample, WAVFormatHeader.nChannels);
|
||||
|
||||
// skip over any extra data in the header
|
||||
int nWAVFormatHeaderExtra = RIFFChunkHeader.nChunkBytes - sizeof(WAVFormatHeader);
|
||||
if (nWAVFormatHeaderExtra < 0)
|
||||
return ERROR_INVALID_INPUT_FILE;
|
||||
else
|
||||
m_spIO->Seek(nWAVFormatHeaderExtra, FILE_CURRENT);
|
||||
|
||||
// find the data chunk
|
||||
RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader)))
|
||||
|
||||
while (!(RIFFChunkHeader.cChunkLabel[0] == 'd' && RIFFChunkHeader.cChunkLabel[1] == 'a' && RIFFChunkHeader.cChunkLabel[2] == 't' && RIFFChunkHeader.cChunkLabel[3] == 'a'))
|
||||
{
|
||||
// move the file pointer to the end of this chunk
|
||||
m_spIO->Seek(RIFFChunkHeader.nChunkBytes, FILE_CURRENT);
|
||||
|
||||
// check again for the data chunk
|
||||
RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader)))
|
||||
}
|
||||
|
||||
// we're at the data block
|
||||
m_nHeaderBytes = m_spIO->GetPosition();
|
||||
m_nDataBytes = RIFFChunkHeader.nChunkBytes;
|
||||
if (m_nDataBytes < 0)
|
||||
m_nDataBytes = m_nFileBytes - m_nHeaderBytes;
|
||||
|
||||
// make sure the data bytes is a whole number of blocks
|
||||
if ((m_nDataBytes % m_wfeSource.nBlockAlign) != 0)
|
||||
return ERROR_INVALID_INPUT_FILE;
|
||||
|
||||
// calculate the terminating byts
|
||||
m_nTerminatingBytes = m_nFileBytes - m_nDataBytes - m_nHeaderBytes;
|
||||
|
||||
// we made it this far, everything must be cool
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CWAVInputSource::GetData(unsigned char * pBuffer, int nBlocks, int * pBlocksRetrieved)
|
||||
{
|
||||
if (!m_bIsValid) return ERROR_UNDEFINED;
|
||||
|
||||
int nBytes = (m_wfeSource.nBlockAlign * nBlocks);
|
||||
unsigned int nBytesRead = 0;
|
||||
|
||||
if (m_spIO->Read(pBuffer, nBytes, &nBytesRead) != ERROR_SUCCESS)
|
||||
return ERROR_IO_READ;
|
||||
|
||||
if (pBlocksRetrieved) *pBlocksRetrieved = (nBytesRead / m_wfeSource.nBlockAlign);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int CWAVInputSource::GetHeaderData(unsigned char * pBuffer)
|
||||
{
|
||||
if (!m_bIsValid) return ERROR_UNDEFINED;
|
||||
|
||||
int nRetVal = ERROR_SUCCESS;
|
||||
|
||||
if (m_nHeaderBytes > 0)
|
||||
{
|
||||
int nOriginalFileLocation = m_spIO->GetPosition();
|
||||
|
||||
m_spIO->Seek(0, FILE_BEGIN);
|
||||
|
||||
unsigned int nBytesRead = 0;
|
||||
int nReadRetVal = m_spIO->Read(pBuffer, m_nHeaderBytes, &nBytesRead);
|
||||
|
||||
if ((nReadRetVal != ERROR_SUCCESS) || (m_nHeaderBytes != int(nBytesRead)))
|
||||
{
|
||||
nRetVal = ERROR_UNDEFINED;
|
||||
}
|
||||
|
||||
m_spIO->Seek(nOriginalFileLocation, FILE_BEGIN);
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int CWAVInputSource::GetTerminatingData(unsigned char * pBuffer)
|
||||
{
|
||||
if (!m_bIsValid) return ERROR_UNDEFINED;
|
||||
|
||||
int nRetVal = ERROR_SUCCESS;
|
||||
|
||||
if (m_nTerminatingBytes > 0)
|
||||
{
|
||||
int nOriginalFileLocation = m_spIO->GetPosition();
|
||||
|
||||
m_spIO->Seek(-m_nTerminatingBytes, FILE_END);
|
||||
|
||||
unsigned int nBytesRead = 0;
|
||||
int nReadRetVal = m_spIO->Read(pBuffer, m_nTerminatingBytes, &nBytesRead);
|
||||
|
||||
if ((nReadRetVal != ERROR_SUCCESS) || (m_nTerminatingBytes != int(nBytesRead)))
|
||||
{
|
||||
nRetVal = ERROR_UNDEFINED;
|
||||
}
|
||||
|
||||
m_spIO->Seek(nOriginalFileLocation, FILE_BEGIN);
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
64
MAC_SDK/Source/MACLib/WAVInputSource.h
Normal file
64
MAC_SDK/Source/MACLib/WAVInputSource.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef APE_WAVINPUTSOURCE_H
|
||||
#define APE_WAVINPUTSOURCE_H
|
||||
|
||||
#include "IO.h"
|
||||
|
||||
/*************************************************************************************
|
||||
CInputSource - base input format class (allows multiple format support)
|
||||
*************************************************************************************/
|
||||
class CInputSource
|
||||
{
|
||||
public:
|
||||
|
||||
// construction / destruction
|
||||
CInputSource(CIO * pIO, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode = NULL) { }
|
||||
CInputSource(const wchar_t * pSourceName, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode = NULL) { }
|
||||
virtual ~CInputSource() { }
|
||||
|
||||
// get data
|
||||
virtual int GetData(unsigned char * pBuffer, int nBlocks, int * pBlocksRetrieved) = 0;
|
||||
|
||||
// get header / terminating data
|
||||
virtual int GetHeaderData(unsigned char * pBuffer) = 0;
|
||||
virtual int GetTerminatingData(unsigned char * pBuffer) = 0;
|
||||
};
|
||||
|
||||
/*************************************************************************************
|
||||
CWAVInputSource - wraps working with WAV files (could be extended to any format)
|
||||
*************************************************************************************/
|
||||
class CWAVInputSource : public CInputSource
|
||||
{
|
||||
public:
|
||||
|
||||
// construction / destruction
|
||||
CWAVInputSource(CIO * pIO, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode = NULL);
|
||||
CWAVInputSource(const wchar_t * pSourceName, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode = NULL);
|
||||
~CWAVInputSource();
|
||||
|
||||
// get data
|
||||
int GetData(unsigned char * pBuffer, int nBlocks, int * pBlocksRetrieved);
|
||||
|
||||
// get header / terminating data
|
||||
int GetHeaderData(unsigned char * pBuffer);
|
||||
int GetTerminatingData(unsigned char * pBuffer);
|
||||
|
||||
private:
|
||||
|
||||
int AnalyzeSource();
|
||||
|
||||
CSmartPtr<CIO> m_spIO;
|
||||
|
||||
WAVEFORMATEX m_wfeSource;
|
||||
int m_nHeaderBytes;
|
||||
int m_nDataBytes;
|
||||
int m_nTerminatingBytes;
|
||||
int m_nFileBytes;
|
||||
BOOL m_bIsValid;
|
||||
};
|
||||
|
||||
/*************************************************************************************
|
||||
Input souce creation
|
||||
*************************************************************************************/
|
||||
CInputSource * CreateInputSource(const wchar_t * pSourceName, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode = NULL);
|
||||
|
||||
#endif // #ifndef APE_WAVINPUTSOURCE_H
|
||||
79
MAC_SDK/Source/MACLib/md5.h
Normal file
79
MAC_SDK/Source/MACLib/md5.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.
|
||||
*
|
||||
* License to copy and use this software is granted provided that it is identified
|
||||
* as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
* mentioning or referencing this software or this function.
|
||||
*
|
||||
* License is also granted to make and use derivative works provided that such
|
||||
* works are identified as "derived from the RSA Data Security, Inc. MD5 Message-
|
||||
* Digest Algorithm" in all material mentioning or referencing the derived work.
|
||||
*
|
||||
* RSA Data Security, Inc. makes no representations concerning either the
|
||||
* merchantability of this software or the suitability of this software for any
|
||||
* particular purpose. It is provided "as is" without express or implied warranty
|
||||
* of any kind. These notices must be retained in any copies of any part of this
|
||||
* documentation and/or software.
|
||||
*/
|
||||
|
||||
#ifndef MD5SUM_MD5_H
|
||||
#define MD5SUM_MD5_H
|
||||
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
/*
|
||||
* Define the MD5 context structure
|
||||
* Please DO NOT change the order or contents of the structure as various assembler files depend on it !!
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint32_t state [ 4]; /* state (ABCD) */
|
||||
uint32_t count [ 2]; /* number of bits, modulo 2^64 (least sig word first) */
|
||||
uint8_t buffer [64]; /* input buffer for incomplete buffer data */
|
||||
} MD5_CTX;
|
||||
|
||||
void MD5Init ( MD5_CTX* ctx );
|
||||
void MD5Update ( MD5_CTX* ctx, const uint8_t* buf, size_t len );
|
||||
void MD5Final ( uint8_t digest [16], MD5_CTX* ctx );
|
||||
|
||||
class CMD5Helper
|
||||
{
|
||||
public:
|
||||
|
||||
CMD5Helper(BOOL bInitialize = TRUE)
|
||||
{
|
||||
if (bInitialize)
|
||||
Initialize();
|
||||
}
|
||||
|
||||
BOOL Initialize()
|
||||
{
|
||||
memset(&m_MD5Context, 0, sizeof(m_MD5Context));
|
||||
MD5Init(&m_MD5Context);
|
||||
m_nTotalBytes = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
inline void AddData(const void * pData, int nBytes)
|
||||
{
|
||||
MD5Update(&m_MD5Context, (const unsigned char *) pData, nBytes);
|
||||
m_nTotalBytes += nBytes;
|
||||
}
|
||||
|
||||
BOOL GetResult(unsigned char cResult[16])
|
||||
{
|
||||
memset(cResult, 0, 16);
|
||||
MD5Final(cResult, &m_MD5Context);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
MD5_CTX m_MD5Context;
|
||||
BOOL m_bStopped;
|
||||
int m_nTotalBytes;
|
||||
};
|
||||
|
||||
|
||||
#endif /* MD5SUM_MD5_H */
|
||||
69
MAC_SDK/Source/Makefile
Normal file
69
MAC_SDK/Source/Makefile
Normal file
@@ -0,0 +1,69 @@
|
||||
#
|
||||
# Simple Makefile
|
||||
#
|
||||
# Frank Klemm
|
||||
#
|
||||
|
||||
TARGET = mac
|
||||
INCLUDES = -IShared -IMACLib -IConsole
|
||||
CPPOPT = -s -O3 -Wall -pedantic -D__GNUC_IA32__
|
||||
COMPILER = gcc
|
||||
|
||||
SOURCEFILES = \
|
||||
Console/Console.cpp \
|
||||
MACLib/APECompress.cpp \
|
||||
MACLib/APECompressCore.cpp \
|
||||
MACLib/APECompressCreate.cpp \
|
||||
MACLib/APEDecompress.cpp \
|
||||
MACLib/APEInfo.cpp \
|
||||
MACLib/APELink.cpp \
|
||||
MACLib/APESimple.cpp \
|
||||
MACLib/APETag.cpp \
|
||||
MACLib/BitArray.cpp \
|
||||
MACLib/MACLib.cpp \
|
||||
MACLib/MACProgressHelper.cpp \
|
||||
MACLib/NNFilter.cpp \
|
||||
MACLib/NewPredictor.cpp \
|
||||
MACLib/Prepare.cpp \
|
||||
MACLib/UnBitArray.cpp \
|
||||
MACLib/UnBitArrayBase.cpp \
|
||||
MACLib/WAVInputSource.cpp \
|
||||
Shared/GlobalFunctions.cpp \
|
||||
Shared/StdLibFileIO.cpp \
|
||||
Shared/WinFileIO.cpp \
|
||||
MACLib/NNFilterAsm.o
|
||||
|
||||
|
||||
|
||||
$(TARGET): $(SOURCEFILES)
|
||||
$(COMPILER) -static $(CPPOPT) $(INCLUDES) -o $(TARGET)-static $(SOURCEFILES)
|
||||
$(COMPILER) $(CPPOPT) $(INCLUDES) -o $(TARGET) $(SOURCEFILES)
|
||||
|
||||
MACLib/NNFilterAsm.o : MACLib/NNFilterAsm.nas
|
||||
nasm -f elf -o MACLib/NNFilterAsm.o MACLib/NNFilterAsm.nas -l MACLib/NNFilterAsm.lst
|
||||
|
||||
APE_Source.tar.bz2:
|
||||
@sh ./MakeSourceBall
|
||||
|
||||
test:
|
||||
@echo e4dd45d9b5ec4cc91f3bd2210a543df6
|
||||
@./$(TARGET) Adagio.ape - -d | md5sum
|
||||
|
||||
speed:
|
||||
@sync
|
||||
@cat Adagio.ape > /dev/null
|
||||
@sync
|
||||
time ./mac Adagio.ape /dev/null -d
|
||||
|
||||
|
||||
# Samual Barber: Adagio for Strings (10:10.84)
|
||||
#
|
||||
# C version 203.01 sec
|
||||
# First ASM version 76.89 sec
|
||||
# 76.85 sec
|
||||
# 77.12 sec
|
||||
# 76.23 sec
|
||||
# 75.67 sec
|
||||
# 76.26 sec
|
||||
# 76.79 sec
|
||||
# 76.70 sec
|
||||
67
MAC_SDK/Source/Readme.htm
Normal file
67
MAC_SDK/Source/Readme.htm
Normal file
@@ -0,0 +1,67 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Monkey</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p align="center"><font size="4" face="Verdana">Monkey's Audio Source Code
|
||||
Readme<br>
|
||||
</font><font face="Verdana" size="2">(last updated July 7, 2002)</font></p>
|
||||
<p><b><font size="2" face="Verdana">Introduction</font></b></p>
|
||||
<p><font size="2" face="Verdana">First off, just to be clear, you have to fully
|
||||
agree with the included license agreement before using / viewing any of the
|
||||
included materials. The big points are that you can't steal code or try to
|
||||
make money with it (without permission) and that you have to submit changes and
|
||||
improvements back to the Monkey's Audio project. With that out of the way,
|
||||
I'm hoping that by releasing the source code, we'll be able to work together to
|
||||
make Monkey's Audio better. Please direct any suggestions or improvements
|
||||
to the Monkey's Audio developer's forum or to me personally when appropriate.
|
||||
(email @ monkeysaudio.com) And thank you for taking the time to help.</font></p>
|
||||
<p><b><font size="2" face="Verdana">Important Note</font></b></p>
|
||||
<p><font size="2" face="Verdana">The Monkey's Audio format is not
|
||||
"finalized". In fact, the compression / decompression engines
|
||||
are continually being improved. This is what makes MAC fun to work on, and
|
||||
it's what makes progress possible. I realize that this can be a pain for
|
||||
3rd party developers, but it's the only way to avoid stagnation. So, you
|
||||
can not hard code Monkey's Audio support and expect it to work with the newest
|
||||
versions of MAC forever. Either use a DLL or else accept that you'll have
|
||||
to re-link to MACLib once in a while.</font></p>
|
||||
<p><b><font size="2" face="Verdana">Things that it'd be great if you worked on</font></b></p>
|
||||
<p><font face="Verdana" size="2">1. It would be nice to have makefiles for gcc
|
||||
or any other compilers that people commonly use.</font></p>
|
||||
<p><font size="2" face="Verdana">2. Pour through the code and look for bone-head
|
||||
maneuvers.</font></p>
|
||||
<p><font size="2" face="Verdana">3. Submit any necessary changes for
|
||||
cross-platform compilation. </font></p>
|
||||
<p><font size="2" face="Verdana">4. XMMS, Lame DLL, PocketPC, etc. plugins /
|
||||
implementations.</font></p>
|
||||
<p><font size="2" face="Verdana">5. A console front-end that doesn't suck. (more
|
||||
options, etc.) Also, don't worry about maintaining compatibility with the
|
||||
current parameter passing scheme -- just use whatever makes sense.</font></p>
|
||||
<p><b><font size="2" face="Verdana">Tips for building MACLib outside of Windows</font></b></p>
|
||||
<p><font face="Verdana" size="2">1. in "Shared/All.h" do this:</font></p>
|
||||
<ul>
|
||||
<li><font size="2" face="Verdana">#define BUILD_CROSS_PLATFORM</font></li>
|
||||
<li><font face="Verdana" size="2">look through "Shared/All.h" and
|
||||
"Shared/NoWindows.h" to make sure all the defines are acceptable</font></li>
|
||||
</ul>
|
||||
<p><font face="Verdana" size="2">2. You need to use NASM to build the assembly
|
||||
if you want it. (helps speed a lot) Check out "MacLib/Assembly/..."
|
||||
for more information.</font></p>
|
||||
<p><b><font size="2" face="Verdana">Known non-Windows problems (help fixing them
|
||||
would be great)</font></b></p>
|
||||
<p><font size="2" face="Verdana">2. The macros PUMP_MESSAGE_LOOP, MESSAGEBOX, and a few others don't work.</font></p>
|
||||
<p> </p>
|
||||
<p align="center" style="margin:0in;margin-bottom:.0001pt;text-align:center"><font face="Verdana" size="2">-
|
||||
All materials and programs copyrighted <20>2000-2002 by Matthew T. Ashland -</font></p>
|
||||
<p align="center" style="margin:0in;margin-bottom:.0001pt;text-align:center"><font face="Verdana" size="2">-
|
||||
All rights reserved. -</font></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
308
MAC_SDK/Source/Shared/APEInfoDialog.cpp
Normal file
308
MAC_SDK/Source/Shared/APEInfoDialog.cpp
Normal file
@@ -0,0 +1,308 @@
|
||||
#include "All.h"
|
||||
#include "APEInfo.h"
|
||||
#include "APEInfoDialog.h"
|
||||
#include "ID3Genres.h"
|
||||
#include "APECompress.h"
|
||||
#include "CharacterHelper.h"
|
||||
|
||||
/***************************************************************************************
|
||||
The dialog component ID's
|
||||
***************************************************************************************/
|
||||
#define FILE_NAME_EDIT 1000
|
||||
|
||||
#define ENCODER_VERSION_STATIC 2000
|
||||
#define COMPRESSION_LEVEL_STATIC 2001
|
||||
#define FORMAT_FLAGS_STATIC 2002
|
||||
#define HAS_TAG_STATIC 2003
|
||||
|
||||
#define SAMPLE_RATE_STATIC 3000
|
||||
#define CHANNELS_STATIC 3001
|
||||
#define BITS_PER_SAMPLE_STATIC 3002
|
||||
#define PEAK_LEVEL_STATIC 3003
|
||||
|
||||
#define TRACK_LENGTH_STATIC 4000
|
||||
#define WAV_SIZE_STATIC 4001
|
||||
#define APE_SIZE_STATIC 4002
|
||||
#define COMPRESSION_RATIO_STATIC 4003
|
||||
|
||||
#define TITLE_EDIT 5000
|
||||
#define ARTIST_EDIT 5001
|
||||
#define ALBUM_EDIT 5002
|
||||
#define COMMENT_EDIT 5003
|
||||
#define YEAR_EDIT 5004
|
||||
#define GENRE_COMBOBOX 5005
|
||||
#define TRACK_EDIT 5006
|
||||
|
||||
#define SAVE_TAG_BUTTON 6000
|
||||
#define REMOVE_TAG_BUTTON 6001
|
||||
#define CANCEL_BUTTON 6002
|
||||
|
||||
/***************************************************************************************
|
||||
Global pointer to this instance
|
||||
***************************************************************************************/
|
||||
CAPEInfoDialog * g_pAPEDecompressDialog = NULL;
|
||||
|
||||
/***************************************************************************************
|
||||
Construction / destruction
|
||||
***************************************************************************************/
|
||||
CAPEInfoDialog::CAPEInfoDialog()
|
||||
{
|
||||
g_pAPEDecompressDialog = NULL;
|
||||
}
|
||||
|
||||
CAPEInfoDialog::~CAPEInfoDialog()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Display the file info dialog
|
||||
***************************************************************************************/
|
||||
int CAPEInfoDialog::ShowAPEInfoDialog(const str_utf16 * pFilename, HINSTANCE hInstance, const str_utf16 * lpszTemplateName, HWND hWndParent)
|
||||
{
|
||||
// only allow one instance at a time
|
||||
if (g_pAPEDecompressDialog != NULL) { return -1; }
|
||||
|
||||
// open the file
|
||||
int nErrorCode = ERROR_SUCCESS;
|
||||
m_pAPEDecompress = CreateIAPEDecompress(pFilename, &nErrorCode);
|
||||
if (m_pAPEDecompress == NULL || nErrorCode != ERROR_SUCCESS)
|
||||
return nErrorCode;
|
||||
|
||||
g_pAPEDecompressDialog = this;
|
||||
|
||||
DialogBoxParam(hInstance, lpszTemplateName, hWndParent, (DLGPROC) DialogProc, 0);
|
||||
|
||||
// clean up
|
||||
SAFE_DELETE(m_pAPEDecompress);
|
||||
g_pAPEDecompressDialog = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Fill the genre combobox
|
||||
***************************************************************************************/
|
||||
int CAPEInfoDialog::FillGenreComboBox(HWND hDlg, int nComboBoxID, char *pSelectedGenre)
|
||||
{
|
||||
// declare the variables
|
||||
int nRetVal;
|
||||
HWND hGenreComboBox = GetDlgItem(hDlg, nComboBoxID);
|
||||
|
||||
// reset the contents of the combobox
|
||||
SendMessage(hGenreComboBox, CB_RESETCONTENT, 0, 0);
|
||||
|
||||
// propagate the combobox (0 to 126 so "Undefined" isn't repeated)
|
||||
for (int z = 0; z < GENRE_COUNT; z++)
|
||||
{
|
||||
//add the genre string
|
||||
nRetVal = SendMessage(hGenreComboBox, CB_ADDSTRING, 0, (LPARAM) g_ID3Genre[z]);
|
||||
if (nRetVal == CB_ERR) { return -1; }
|
||||
}
|
||||
|
||||
// add the 'Undefined' genre
|
||||
nRetVal = SendMessage(hGenreComboBox, CB_ADDSTRING, 0, (LPARAM) "Undefined");
|
||||
if (nRetVal == CB_ERR) { return -1; }
|
||||
|
||||
// set the genre id (if it's specified)
|
||||
if (pSelectedGenre)
|
||||
{
|
||||
if (strlen(pSelectedGenre) > 0)
|
||||
SendMessage(hGenreComboBox, CB_SELECTSTRING, -1, (LPARAM) pSelectedGenre);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
The dialog procedure
|
||||
***************************************************************************************/
|
||||
LRESULT CALLBACK CAPEInfoDialog::DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
// get the class
|
||||
IAPEDecompress * pAPEDecompress = g_pAPEDecompressDialog->m_pAPEDecompress;
|
||||
|
||||
int wmID, wmEvent;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
// variable declares
|
||||
TCHAR cTemp[1024] = { 0 };
|
||||
|
||||
// set info
|
||||
wchar_t cFilename[MAX_PATH + 1] = {0};
|
||||
GET_IO(pAPEDecompress)->GetName(&cFilename[0]);
|
||||
|
||||
SetDlgItemText(hDlg, FILE_NAME_EDIT, cFilename);
|
||||
|
||||
switch (pAPEDecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL))
|
||||
{
|
||||
case COMPRESSION_LEVEL_FAST: _stprintf(cTemp, _T("Mode: Fast")); break;
|
||||
case COMPRESSION_LEVEL_NORMAL: _stprintf(cTemp, _T("Mode: Normal")); break;
|
||||
case COMPRESSION_LEVEL_HIGH: _stprintf(cTemp, _T("Mode: High")); break;
|
||||
case COMPRESSION_LEVEL_EXTRA_HIGH: _stprintf(cTemp, _T("Mode: Extra High")); break;
|
||||
case COMPRESSION_LEVEL_INSANE: _stprintf(cTemp, _T("Mode: Insane")); break;
|
||||
default: _stprintf(cTemp, _T("Mode: Unknown")); break;
|
||||
}
|
||||
SetDlgItemText(hDlg, COMPRESSION_LEVEL_STATIC, cTemp);
|
||||
|
||||
_stprintf(cTemp, _T("Version: %.2f"), float(pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION)) / float(1000));
|
||||
SetDlgItemText(hDlg, ENCODER_VERSION_STATIC, cTemp);
|
||||
|
||||
_stprintf(cTemp, _T("Format Flags: %d"), pAPEDecompress->GetInfo(APE_INFO_FORMAT_FLAGS));
|
||||
SetDlgItemText(hDlg, FORMAT_FLAGS_STATIC, cTemp);
|
||||
|
||||
_stprintf(cTemp, _T("Sample Rate: %d"), pAPEDecompress->GetInfo(APE_INFO_SAMPLE_RATE));
|
||||
SetDlgItemText(hDlg, SAMPLE_RATE_STATIC, cTemp);
|
||||
|
||||
_stprintf(cTemp, _T("Channels: %d"), pAPEDecompress->GetInfo(APE_INFO_CHANNELS));
|
||||
SetDlgItemText(hDlg, CHANNELS_STATIC, cTemp);
|
||||
|
||||
_stprintf(cTemp, _T("Bits Per Sample: %d"), pAPEDecompress->GetInfo(APE_INFO_BITS_PER_SAMPLE));
|
||||
SetDlgItemText(hDlg, BITS_PER_SAMPLE_STATIC, cTemp);
|
||||
|
||||
int nSeconds = pAPEDecompress->GetInfo(APE_INFO_LENGTH_MS) / 1000; int nMinutes = nSeconds / 60; nSeconds = nSeconds % 60; int nHours = nMinutes / 60; nMinutes = nMinutes % 60;
|
||||
if (nHours > 0) _stprintf(cTemp, _T("Length: %d:%02d:%02d"), nHours, nMinutes, nSeconds);
|
||||
else if (nMinutes > 0) _stprintf(cTemp, _T("Length: %d:%02d"), nMinutes, nSeconds);
|
||||
else _stprintf(cTemp, _T("Length: 0:%02d"), nSeconds);
|
||||
SetDlgItemText(hDlg, TRACK_LENGTH_STATIC, cTemp);
|
||||
|
||||
int nPeakLevel = pAPEDecompress->GetInfo(APE_INFO_PEAK_LEVEL);
|
||||
if (nPeakLevel >= 0) _stprintf(cTemp, _T("Peak Level: %d"), nPeakLevel);
|
||||
else _stprintf(cTemp, _T("Peak Level: ?"));
|
||||
SetDlgItemText(hDlg, PEAK_LEVEL_STATIC, cTemp);
|
||||
|
||||
// the file size
|
||||
_stprintf(cTemp, _T("APE: %.2f MB"), float(pAPEDecompress->GetInfo(APE_INFO_APE_TOTAL_BYTES)) / float(1048576));
|
||||
SetDlgItemText(hDlg, APE_SIZE_STATIC, cTemp);
|
||||
|
||||
_stprintf(cTemp, _T("WAV: %.2f MB"), float(pAPEDecompress->GetInfo(APE_INFO_WAV_TOTAL_BYTES)) / float(1048576));
|
||||
SetDlgItemText(hDlg, WAV_SIZE_STATIC, cTemp);
|
||||
|
||||
// the compression ratio
|
||||
_stprintf(cTemp, _T("Compression: %.2f%%"), float(pAPEDecompress->GetInfo(APE_INFO_AVERAGE_BITRATE) * 100) / float(pAPEDecompress->GetInfo(APE_INFO_DECOMPRESSED_BITRATE)));
|
||||
SetDlgItemText(hDlg, COMPRESSION_RATIO_STATIC, cTemp);
|
||||
|
||||
// the has tag
|
||||
BOOL bHasID3Tag = GET_TAG(pAPEDecompress)->GetHasID3Tag();
|
||||
BOOL bHasAPETag = GET_TAG(pAPEDecompress)->GetHasAPETag();
|
||||
|
||||
if (!bHasID3Tag && !bHasAPETag)
|
||||
_stprintf(cTemp, _T("Tag: None"));
|
||||
else if (bHasID3Tag && !bHasAPETag)
|
||||
_stprintf(cTemp, _T("Tag: ID3v1.1"));
|
||||
else if (!bHasID3Tag && bHasAPETag)
|
||||
_stprintf(cTemp, _T("Tag: APE Tag"));
|
||||
else
|
||||
_stprintf(cTemp, _T("Tag: Corrupt"));
|
||||
SetDlgItemText(hDlg, HAS_TAG_STATIC, cTemp);
|
||||
|
||||
wchar_t cBuffer[256];
|
||||
int nBufferBytes = 256;
|
||||
|
||||
nBufferBytes = 256;
|
||||
GET_TAG(pAPEDecompress)->GetFieldString(APE_TAG_FIELD_TITLE, cBuffer, &nBufferBytes);
|
||||
SetDlgItemText(hDlg, TITLE_EDIT, cBuffer);
|
||||
|
||||
nBufferBytes = 256;
|
||||
GET_TAG(pAPEDecompress)->GetFieldString(APE_TAG_FIELD_ARTIST, cBuffer, &nBufferBytes);
|
||||
SetDlgItemText(hDlg, ARTIST_EDIT, cBuffer);
|
||||
|
||||
nBufferBytes = 256;
|
||||
GET_TAG(pAPEDecompress)->GetFieldString(APE_TAG_FIELD_ALBUM, cBuffer, &nBufferBytes);
|
||||
SetDlgItemText(hDlg, ALBUM_EDIT, cBuffer);
|
||||
|
||||
nBufferBytes = 256;
|
||||
GET_TAG(pAPEDecompress)->GetFieldString(APE_TAG_FIELD_COMMENT, cBuffer, &nBufferBytes);
|
||||
SetDlgItemText(hDlg, COMMENT_EDIT, cBuffer);
|
||||
|
||||
nBufferBytes = 256;
|
||||
GET_TAG(pAPEDecompress)->GetFieldString(APE_TAG_FIELD_YEAR, cBuffer, &nBufferBytes);
|
||||
SetDlgItemText(hDlg, YEAR_EDIT, cBuffer);
|
||||
|
||||
nBufferBytes = 256;
|
||||
GET_TAG(pAPEDecompress)->GetFieldString(APE_TAG_FIELD_TRACK, cBuffer, &nBufferBytes);
|
||||
SetDlgItemText(hDlg, TRACK_EDIT, cBuffer);
|
||||
|
||||
g_pAPEDecompressDialog->FillGenreComboBox(hDlg, GENRE_COMBOBOX, NULL);
|
||||
|
||||
nBufferBytes = 256;
|
||||
GET_TAG(pAPEDecompress)->GetFieldString(APE_TAG_FIELD_GENRE, cBuffer, &nBufferBytes);
|
||||
SetDlgItemText(hDlg, GENRE_COMBOBOX, cBuffer);
|
||||
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
case WM_COMMAND:
|
||||
wmID = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
|
||||
switch (wmID)
|
||||
{
|
||||
case IDCANCEL:
|
||||
// traps the [esc] key
|
||||
EndDialog(hDlg, 0);
|
||||
return TRUE;
|
||||
break;
|
||||
case CANCEL_BUTTON:
|
||||
EndDialog(hDlg, 0);
|
||||
return TRUE;
|
||||
break;
|
||||
case REMOVE_TAG_BUTTON:
|
||||
{
|
||||
// make sure you really wanted to
|
||||
int nRetVal = ::MessageBox(hDlg, _T("Are you sure you want to permanently remove the tag?"), _T("Are You Sure?"), MB_YESNO | MB_ICONQUESTION);
|
||||
if (nRetVal == IDYES)
|
||||
{
|
||||
// remove the ID3 tag...
|
||||
if (GET_TAG(pAPEDecompress)->Remove() != 0)
|
||||
{
|
||||
MessageBox(hDlg, _T("Error removing tag. (could the file be read-only?)"), _T("Error Removing Tag"), MB_OK | MB_ICONEXCLAMATION);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
EndDialog(hDlg, 0);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SAVE_TAG_BUTTON:
|
||||
|
||||
// make the id3 tag
|
||||
TCHAR cBuffer[256]; int z;
|
||||
|
||||
#define SAVE_FIELD(ID, Field) \
|
||||
for (z = 0; z < 256; z++) { cBuffer[z] = 0; } \
|
||||
GetDlgItemText(hDlg, ID, cBuffer, 256); \
|
||||
GET_TAG(pAPEDecompress)->SetFieldString(Field, cBuffer);
|
||||
|
||||
SAVE_FIELD(TITLE_EDIT, APE_TAG_FIELD_TITLE)
|
||||
SAVE_FIELD(ARTIST_EDIT, APE_TAG_FIELD_ARTIST)
|
||||
SAVE_FIELD(ALBUM_EDIT, APE_TAG_FIELD_ALBUM)
|
||||
SAVE_FIELD(COMMENT_EDIT, APE_TAG_FIELD_COMMENT)
|
||||
SAVE_FIELD(TRACK_EDIT, APE_TAG_FIELD_TRACK)
|
||||
SAVE_FIELD(YEAR_EDIT, APE_TAG_FIELD_YEAR)
|
||||
SAVE_FIELD(GENRE_COMBOBOX, APE_TAG_FIELD_GENRE)
|
||||
|
||||
if (GET_TAG(pAPEDecompress)->Save() != 0)
|
||||
{
|
||||
MessageBox(hDlg, _T("Error saving tag. (could the file be read-only?)"), _T("Error Saving Tag"), MB_OK | MB_ICONEXCLAMATION);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EndDialog(hDlg, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
EndDialog(hDlg, 0);
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
22
MAC_SDK/Source/Shared/APEInfoDialog.h
Normal file
22
MAC_SDK/Source/Shared/APEInfoDialog.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef APE_APEINFODIALOG_H
|
||||
#define APE_APEINFODIALOG_H
|
||||
|
||||
BOOL CALLBACK FileInfoDialogProcedureA(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
class CAPEInfoDialog
|
||||
{
|
||||
public:
|
||||
|
||||
CAPEInfoDialog();
|
||||
~CAPEInfoDialog();
|
||||
|
||||
int ShowAPEInfoDialog(const str_utf16 * pFilename, HINSTANCE hInstance, const str_utf16 * lpszTemplateName, HWND hWndParent);
|
||||
|
||||
private:
|
||||
|
||||
static LRESULT CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
int FillGenreComboBox(HWND hDlg, int nComboBoxID, char * pSelectedGenre);
|
||||
IAPEDecompress * m_pAPEDecompress;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_APEINFODIALOG_H
|
||||
237
MAC_SDK/Source/Shared/All.h
Normal file
237
MAC_SDK/Source/Shared/All.h
Normal file
@@ -0,0 +1,237 @@
|
||||
#ifndef APE_ALL_H
|
||||
#define APE_ALL_H
|
||||
|
||||
/*****************************************************************************************
|
||||
Cross platform building switch
|
||||
*****************************************************************************************/
|
||||
//#define BUILD_CROSS_PLATFORM
|
||||
|
||||
/*****************************************************************************************
|
||||
Unicode
|
||||
*****************************************************************************************/
|
||||
#ifdef _UNICODE
|
||||
|
||||
#else
|
||||
|
||||
#endif // #ifdef _UNICODE
|
||||
|
||||
|
||||
/*****************************************************************************************
|
||||
Global includes
|
||||
*****************************************************************************************/
|
||||
#ifndef BUILD_CROSS_PLATFORM
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <mmsystem.h>
|
||||
#include <tchar.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "NoWindows.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "SmartPtr.h"
|
||||
|
||||
/*****************************************************************************************
|
||||
Global compiler settings (useful for porting)
|
||||
*****************************************************************************************/
|
||||
#ifndef BUILD_CROSS_PLATFORM
|
||||
#ifndef _WIN64
|
||||
#define ENABLE_ASSEMBLY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BACKWARDS_COMPATIBILITY
|
||||
|
||||
#define ENABLE_COMPRESSION_MODE_FAST
|
||||
#define ENABLE_COMPRESSION_MODE_NORMAL
|
||||
#define ENABLE_COMPRESSION_MODE_HIGH
|
||||
#define ENABLE_COMPRESSION_MODE_EXTRA_HIGH
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef unsigned __int32 uint32;
|
||||
typedef __int32 int32;
|
||||
typedef unsigned __int16 uint16;
|
||||
typedef __int16 int16;
|
||||
typedef unsigned __int8 uint8;
|
||||
typedef __int8 int8;
|
||||
typedef char str_ansi;
|
||||
typedef unsigned char str_utf8;
|
||||
typedef wchar_t str_utf16;
|
||||
|
||||
#define IO_USE_WIN_FILE_IO
|
||||
#define IO_HEADER_FILE "WinFileIO.h"
|
||||
#define IO_CLASS_NAME CWinFileIO
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
#define SLEEP(MILLISECONDS) ::Sleep(MILLISECONDS)
|
||||
#define MESSAGEBOX(PARENT, TEXT, CAPTION, TYPE) ::MessageBox(PARENT, TEXT, CAPTION, TYPE)
|
||||
#define PUMP_MESSAGE_LOOP { MSG Msg; while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) != 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } }
|
||||
#define ODS OutputDebugString
|
||||
#define TICK_COUNT_TYPE unsigned long
|
||||
#define TICK_COUNT_READ(VARIABLE) VARIABLE = GetTickCount()
|
||||
#define TICK_COUNT_FREQ 1000
|
||||
#else
|
||||
#define IO_USE_STD_LIB_FILE_IO
|
||||
#define IO_HEADER_FILE "StdLibFileIO.h"
|
||||
#define IO_CLASS_NAME CStdLibFileIO
|
||||
#define DLLEXPORT
|
||||
#define SLEEP(MILLISECONDS) { struct timespec t; t.tv_sec = (MILLISECONDS) / 1000; t.tv_nsec = (MILLISECONDS) % 1000 * 1000000; nanosleep(&t, NULL); }
|
||||
#define MESSAGEBOX(PARENT, TEXT, CAPTION, TYPE)
|
||||
#define PUMP_MESSAGE_LOOP
|
||||
#define ODS printf
|
||||
#define TICK_COUNT_TYPE unsigned long long
|
||||
#define TICK_COUNT_READ(VARIABLE) { struct timeval t; gettimeofday(&t, NULL); VARIABLE = t.tv_sec * 1000000LLU + t.tv_usec; }
|
||||
#define TICK_COUNT_FREQ 1000000
|
||||
#endif
|
||||
|
||||
/*****************************************************************************************
|
||||
Global defines
|
||||
*****************************************************************************************/
|
||||
#define MAC_VERSION_NUMBER 3990
|
||||
#define MAC_VERSION_STRING _T("3.99")
|
||||
#define MAC_NAME _T("Monkey's Audio 3.99")
|
||||
#define PLUGIN_NAME "Monkey's Audio Player v3.99"
|
||||
#define MJ_PLUGIN_NAME _T("APE Plugin (v3.99)")
|
||||
#define CONSOLE_NAME "--- Monkey's Audio Console Front End (v 3.99) (c) Matthew T. Ashland ---\n"
|
||||
#define PLUGIN_ABOUT _T("Monkey's Audio Player v3.99\nCopyrighted (c) 2000-2004 by Matthew T. Ashland")
|
||||
#define MAC_DLL_INTERFACE_VERSION_NUMBER 1000
|
||||
|
||||
/*****************************************************************************************
|
||||
Byte order
|
||||
*****************************************************************************************/
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BIG_ENDIAN 4321
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
|
||||
/*****************************************************************************************
|
||||
Macros
|
||||
*****************************************************************************************/
|
||||
#define MB(TEST) MESSAGEBOX(NULL, TEST, _T("Information"), MB_OK);
|
||||
#define MBN(NUMBER) { TCHAR cNumber[16]; _stprintf(cNumber, _T("%d"), NUMBER); MESSAGEBOX(NULL, cNumber, _T("Information"), MB_OK); }
|
||||
|
||||
#define SAFE_DELETE(POINTER) if (POINTER) { delete POINTER; POINTER = NULL; }
|
||||
#define SAFE_ARRAY_DELETE(POINTER) if (POINTER) { delete [] POINTER; POINTER = NULL; }
|
||||
#define SAFE_VOID_CLASS_DELETE(POINTER, Class) { Class *pClass = (Class *) POINTER; if (pClass) { delete pClass; POINTER = NULL; } }
|
||||
#define SAFE_FILE_CLOSE(HANDLE) if (HANDLE != INVALID_HANDLE_VALUE) { CloseHandle(HANDLE); HANDLE = INVALID_HANDLE_VALUE; }
|
||||
|
||||
#define ODN(NUMBER) { TCHAR cNumber[16]; _stprintf(cNumber, _T("%d\n"), int(NUMBER)); ODS(cNumber); }
|
||||
|
||||
#define CATCH_ERRORS(CODE) try { CODE } catch(...) { }
|
||||
|
||||
#define RETURN_ON_ERROR(FUNCTION) { int nRetVal = FUNCTION; if (nRetVal != 0) { return nRetVal; } }
|
||||
#define RETURN_VALUE_ON_ERROR(FUNCTION, VALUE) { int nRetVal = FUNCTION; if (nRetVal != 0) { return VALUE; } }
|
||||
#define RETURN_ON_EXCEPTION(CODE, VALUE) { try { CODE } catch(...) { return VALUE; } }
|
||||
|
||||
#define THROW_ON_ERROR(CODE) { int nRetVal = CODE; if (nRetVal != 0) throw(nRetVal); }
|
||||
|
||||
#define EXPAND_1_TIMES(CODE) CODE
|
||||
#define EXPAND_2_TIMES(CODE) CODE CODE
|
||||
#define EXPAND_3_TIMES(CODE) CODE CODE CODE
|
||||
#define EXPAND_4_TIMES(CODE) CODE CODE CODE CODE
|
||||
#define EXPAND_5_TIMES(CODE) CODE CODE CODE CODE CODE
|
||||
#define EXPAND_6_TIMES(CODE) CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_7_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_8_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_9_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_12_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_14_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_15_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_16_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_30_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_31_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_32_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_64_TIMES(CODE) CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE CODE
|
||||
#define EXPAND_N_TIMES(NUMBER, CODE) EXPAND_##NUMBER##_TIMES(CODE)
|
||||
|
||||
#define UNROLL_4_TIMES(MACRO) MACRO(0) MACRO(1) MACRO(2) MACRO(3)
|
||||
#define UNROLL_8_TIMES(MACRO) MACRO(0) MACRO(1) MACRO(2) MACRO(3) MACRO(4) MACRO(5) MACRO(6) MACRO(7)
|
||||
#define UNROLL_15_TIMES(MACRO) MACRO(0) MACRO(1) MACRO(2) MACRO(3) MACRO(4) MACRO(5) MACRO(6) MACRO(7) MACRO(8) MACRO(9) MACRO(10) MACRO(11) MACRO(12) MACRO(13) MACRO(14)
|
||||
#define UNROLL_16_TIMES(MACRO) MACRO(0) MACRO(1) MACRO(2) MACRO(3) MACRO(4) MACRO(5) MACRO(6) MACRO(7) MACRO(8) MACRO(9) MACRO(10) MACRO(11) MACRO(12) MACRO(13) MACRO(14) MACRO(15)
|
||||
#define UNROLL_64_TIMES(MACRO) MACRO(0) MACRO(1) MACRO(2) MACRO(3) MACRO(4) MACRO(5) MACRO(6) MACRO(7) MACRO(8) MACRO(9) MACRO(10) MACRO(11) MACRO(12) MACRO(13) MACRO(14) MACRO(15) MACRO(16) MACRO(17) MACRO(18) MACRO(19) MACRO(20) MACRO(21) MACRO(22) MACRO(23) MACRO(24) MACRO(25) MACRO(26) MACRO(27) MACRO(28) MACRO(29) MACRO(30) MACRO(31) MACRO(32) MACRO(33) MACRO(34) MACRO(35) MACRO(36) MACRO(37) MACRO(38) MACRO(39) MACRO(40) MACRO(41) MACRO(42) MACRO(43) MACRO(44) MACRO(45) MACRO(46) MACRO(47) MACRO(48) MACRO(49) MACRO(50) MACRO(51) MACRO(52) MACRO(53) MACRO(54) MACRO(55) MACRO(56) MACRO(57) MACRO(58) MACRO(59) MACRO(60) MACRO(61) MACRO(62) MACRO(63)
|
||||
#define UNROLL_128_TIMES(MACRO) MACRO(0) MACRO(1) MACRO(2) MACRO(3) MACRO(4) MACRO(5) MACRO(6) MACRO(7) MACRO(8) MACRO(9) MACRO(10) MACRO(11) MACRO(12) MACRO(13) MACRO(14) MACRO(15) MACRO(16) MACRO(17) MACRO(18) MACRO(19) MACRO(20) MACRO(21) MACRO(22) MACRO(23) MACRO(24) MACRO(25) MACRO(26) MACRO(27) MACRO(28) MACRO(29) MACRO(30) MACRO(31) MACRO(32) MACRO(33) MACRO(34) MACRO(35) MACRO(36) MACRO(37) MACRO(38) MACRO(39) MACRO(40) MACRO(41) MACRO(42) MACRO(43) MACRO(44) MACRO(45) MACRO(46) MACRO(47) MACRO(48) MACRO(49) MACRO(50) MACRO(51) MACRO(52) MACRO(53) MACRO(54) MACRO(55) MACRO(56) MACRO(57) MACRO(58) MACRO(59) MACRO(60) MACRO(61) MACRO(62) MACRO(63) MACRO(64) MACRO(65) MACRO(66) MACRO(67) MACRO(68) MACRO(69) MACRO(70) MACRO(71) MACRO(72) MACRO(73) MACRO(74) MACRO(75) MACRO(76) MACRO(77) MACRO(78) MACRO(79) MACRO(80) MACRO(81) MACRO(82) MACRO(83) MACRO(84) MACRO(85) MACRO(86) MACRO(87) MACRO(88) MACRO(89) MACRO(90) MACRO(91) MACRO(92) MACRO(93) MACRO(94) MACRO(95) MACRO(96) MACRO(97) MACRO(98) MACRO(99) MACRO(100) MACRO(101) MACRO(102) MACRO(103) MACRO(104) MACRO(105) MACRO(106) MACRO(107) MACRO(108) MACRO(109) MACRO(110) MACRO(111) MACRO(112) MACRO(113) MACRO(114) MACRO(115) MACRO(116) MACRO(117) MACRO(118) MACRO(119) MACRO(120) MACRO(121) MACRO(122) MACRO(123) MACRO(124) MACRO(125) MACRO(126) MACRO(127)
|
||||
#define UNROLL_256_TIMES(MACRO) MACRO(0) MACRO(1) MACRO(2) MACRO(3) MACRO(4) MACRO(5) MACRO(6) MACRO(7) MACRO(8) MACRO(9) MACRO(10) MACRO(11) MACRO(12) MACRO(13) MACRO(14) MACRO(15) MACRO(16) MACRO(17) MACRO(18) MACRO(19) MACRO(20) MACRO(21) MACRO(22) MACRO(23) MACRO(24) MACRO(25) MACRO(26) MACRO(27) MACRO(28) MACRO(29) MACRO(30) MACRO(31) MACRO(32) MACRO(33) MACRO(34) MACRO(35) MACRO(36) MACRO(37) MACRO(38) MACRO(39) MACRO(40) MACRO(41) MACRO(42) MACRO(43) MACRO(44) MACRO(45) MACRO(46) MACRO(47) MACRO(48) MACRO(49) MACRO(50) MACRO(51) MACRO(52) MACRO(53) MACRO(54) MACRO(55) MACRO(56) MACRO(57) MACRO(58) MACRO(59) MACRO(60) MACRO(61) MACRO(62) MACRO(63) MACRO(64) MACRO(65) MACRO(66) MACRO(67) MACRO(68) MACRO(69) MACRO(70) MACRO(71) MACRO(72) MACRO(73) MACRO(74) MACRO(75) MACRO(76) MACRO(77) MACRO(78) MACRO(79) MACRO(80) MACRO(81) MACRO(82) MACRO(83) MACRO(84) MACRO(85) MACRO(86) MACRO(87) MACRO(88) MACRO(89) MACRO(90) MACRO(91) MACRO(92) MACRO(93) MACRO(94) MACRO(95) MACRO(96) MACRO(97) MACRO(98) MACRO(99) MACRO(100) MACRO(101) MACRO(102) MACRO(103) MACRO(104) MACRO(105) MACRO(106) MACRO(107) MACRO(108) MACRO(109) MACRO(110) MACRO(111) MACRO(112) MACRO(113) MACRO(114) MACRO(115) MACRO(116) MACRO(117) MACRO(118) MACRO(119) MACRO(120) MACRO(121) MACRO(122) MACRO(123) MACRO(124) MACRO(125) MACRO(126) MACRO(127) \
|
||||
MACRO(128) MACRO(129) MACRO(130) MACRO(131) MACRO(132) MACRO(133) MACRO(134) MACRO(135) MACRO(136) MACRO(137) MACRO(138) MACRO(139) MACRO(140) MACRO(141) MACRO(142) MACRO(143) MACRO(144) MACRO(145) MACRO(146) MACRO(147) MACRO(148) MACRO(149) MACRO(150) MACRO(151) MACRO(152) MACRO(153) MACRO(154) MACRO(155) MACRO(156) MACRO(157) MACRO(158) MACRO(159) MACRO(160) MACRO(161) MACRO(162) MACRO(163) MACRO(164) MACRO(165) MACRO(166) MACRO(167) MACRO(168) MACRO(169) MACRO(170) MACRO(171) MACRO(172) MACRO(173) MACRO(174) MACRO(175) MACRO(176) MACRO(177) MACRO(178) MACRO(179) MACRO(180) MACRO(181) MACRO(182) MACRO(183) MACRO(184) MACRO(185) MACRO(186) MACRO(187) MACRO(188) MACRO(189) MACRO(190) MACRO(191) MACRO(192) MACRO(193) MACRO(194) MACRO(195) MACRO(196) MACRO(197) MACRO(198) MACRO(199) MACRO(200) MACRO(201) MACRO(202) MACRO(203) MACRO(204) MACRO(205) MACRO(206) MACRO(207) MACRO(208) MACRO(209) MACRO(210) MACRO(211) MACRO(212) MACRO(213) MACRO(214) MACRO(215) MACRO(216) MACRO(217) MACRO(218) MACRO(219) MACRO(220) MACRO(221) MACRO(222) MACRO(223) MACRO(224) MACRO(225) MACRO(226) MACRO(227) MACRO(228) MACRO(229) MACRO(230) MACRO(231) MACRO(232) MACRO(233) MACRO(234) MACRO(235) MACRO(236) MACRO(237) MACRO(238) MACRO(239) MACRO(240) MACRO(241) MACRO(242) MACRO(243) MACRO(244) MACRO(245) MACRO(246) MACRO(247) MACRO(248) MACRO(249) MACRO(250) MACRO(251) MACRO(252) MACRO(253) MACRO(254) MACRO(255)
|
||||
|
||||
/*****************************************************************************************
|
||||
Error Codes
|
||||
*****************************************************************************************/
|
||||
|
||||
// success
|
||||
#ifndef ERROR_SUCCESS
|
||||
#define ERROR_SUCCESS 0
|
||||
#endif
|
||||
|
||||
// file and i/o errors (1000's)
|
||||
#define ERROR_IO_READ 1000
|
||||
#define ERROR_IO_WRITE 1001
|
||||
#define ERROR_INVALID_INPUT_FILE 1002
|
||||
#define ERROR_INVALID_OUTPUT_FILE 1003
|
||||
#define ERROR_INPUT_FILE_TOO_LARGE 1004
|
||||
#define ERROR_INPUT_FILE_UNSUPPORTED_BIT_DEPTH 1005
|
||||
#define ERROR_INPUT_FILE_UNSUPPORTED_SAMPLE_RATE 1006
|
||||
#define ERROR_INPUT_FILE_UNSUPPORTED_CHANNEL_COUNT 1007
|
||||
#define ERROR_INPUT_FILE_TOO_SMALL 1008
|
||||
#define ERROR_INVALID_CHECKSUM 1009
|
||||
#define ERROR_DECOMPRESSING_FRAME 1010
|
||||
#define ERROR_INITIALIZING_UNMAC 1011
|
||||
#define ERROR_INVALID_FUNCTION_PARAMETER 1012
|
||||
#define ERROR_UNSUPPORTED_FILE_TYPE 1013
|
||||
#define ERROR_UPSUPPORTED_FILE_VERSION 1014
|
||||
|
||||
// memory errors (2000's)
|
||||
#define ERROR_INSUFFICIENT_MEMORY 2000
|
||||
|
||||
// dll errors (3000's)
|
||||
#define ERROR_LOADINGAPE_DLL 3000
|
||||
#define ERROR_LOADINGAPE_INFO_DLL 3001
|
||||
#define ERROR_LOADING_UNMAC_DLL 3002
|
||||
|
||||
// general and misc errors
|
||||
#define ERROR_USER_STOPPED_PROCESSING 4000
|
||||
#define ERROR_SKIPPED 4001
|
||||
|
||||
// programmer errors
|
||||
#define ERROR_BAD_PARAMETER 5000
|
||||
|
||||
// IAPECompress errors
|
||||
#define ERROR_APE_COMPRESS_TOO_MUCH_DATA 6000
|
||||
|
||||
// unknown error
|
||||
#define ERROR_UNDEFINED -1
|
||||
|
||||
#define ERROR_EXPLANATION \
|
||||
{ ERROR_IO_READ , "I/O read error" }, \
|
||||
{ ERROR_IO_WRITE , "I/O write error" }, \
|
||||
{ ERROR_INVALID_INPUT_FILE , "invalid input file" }, \
|
||||
{ ERROR_INVALID_OUTPUT_FILE , "invalid output file" }, \
|
||||
{ ERROR_INPUT_FILE_TOO_LARGE , "input file file too large" }, \
|
||||
{ ERROR_INPUT_FILE_UNSUPPORTED_BIT_DEPTH , "input file unsupported bit depth" }, \
|
||||
{ ERROR_INPUT_FILE_UNSUPPORTED_SAMPLE_RATE , "input file unsupported sample rate" }, \
|
||||
{ ERROR_INPUT_FILE_UNSUPPORTED_CHANNEL_COUNT , "input file unsupported channel count" }, \
|
||||
{ ERROR_INPUT_FILE_TOO_SMALL , "input file too small" }, \
|
||||
{ ERROR_INVALID_CHECKSUM , "invalid checksum" }, \
|
||||
{ ERROR_DECOMPRESSING_FRAME , "decompressing frame" }, \
|
||||
{ ERROR_INITIALIZING_UNMAC , "initializing unmac" }, \
|
||||
{ ERROR_INVALID_FUNCTION_PARAMETER , "invalid function parameter" }, \
|
||||
{ ERROR_UNSUPPORTED_FILE_TYPE , "unsupported file type" }, \
|
||||
{ ERROR_INSUFFICIENT_MEMORY , "insufficient memory" }, \
|
||||
{ ERROR_LOADINGAPE_DLL , "loading MAC.dll" }, \
|
||||
{ ERROR_LOADINGAPE_INFO_DLL , "loading MACinfo.dll" }, \
|
||||
{ ERROR_LOADING_UNMAC_DLL , "loading UnMAC.dll" }, \
|
||||
{ ERROR_USER_STOPPED_PROCESSING , "user stopped processing" }, \
|
||||
{ ERROR_SKIPPED , "skipped" }, \
|
||||
{ ERROR_BAD_PARAMETER , "bad parameter" }, \
|
||||
{ ERROR_APE_COMPRESS_TOO_MUCH_DATA , "APE compress too much data" }, \
|
||||
{ ERROR_UNDEFINED , "undefined" }, \
|
||||
|
||||
#endif // #ifndef APE_ALL_H
|
||||
143
MAC_SDK/Source/Shared/CharacterHelper.cpp
Normal file
143
MAC_SDK/Source/Shared/CharacterHelper.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "All.h"
|
||||
#include "CharacterHelper.h"
|
||||
|
||||
str_ansi * GetANSIFromUTF8(const str_utf8 * pUTF8)
|
||||
{
|
||||
str_utf16 * pUTF16 = GetUTF16FromUTF8(pUTF8);
|
||||
str_ansi * pANSI = GetANSIFromUTF16(pUTF16);
|
||||
delete [] pUTF16;
|
||||
return pANSI;
|
||||
}
|
||||
|
||||
str_ansi * GetANSIFromUTF16(const str_utf16 * pUTF16)
|
||||
{
|
||||
const int nCharacters = pUTF16 ? wcslen(pUTF16) : 0;
|
||||
#ifdef _WIN32
|
||||
int nANSICharacters = (2 * nCharacters);
|
||||
str_ansi * pANSI = new str_ansi [nANSICharacters + 1];
|
||||
memset(pANSI, 0, (nANSICharacters + 1) * sizeof(str_ansi));
|
||||
if (pUTF16)
|
||||
WideCharToMultiByte(CP_ACP, 0, pUTF16, -1, pANSI, nANSICharacters, NULL, NULL);
|
||||
#else
|
||||
str_utf8 * pANSI = new str_utf8 [nCharacters + 1];
|
||||
for (int z = 0; z < nCharacters; z++)
|
||||
pANSI[z] = (pUTF16[z] >= 256) ? '?' : (str_utf8) pUTF16[z];
|
||||
pANSI[nCharacters] = 0;
|
||||
#endif
|
||||
|
||||
return (str_ansi *) pANSI;
|
||||
}
|
||||
|
||||
str_utf16 * GetUTF16FromANSI(const str_ansi * pANSI)
|
||||
{
|
||||
const int nCharacters = pANSI ? strlen(pANSI) : 0;
|
||||
str_utf16 * pUTF16 = new str_utf16 [nCharacters + 1];
|
||||
|
||||
#ifdef _WIN32
|
||||
memset(pUTF16, 0, sizeof(str_utf16) * (nCharacters + 1));
|
||||
if (pANSI)
|
||||
MultiByteToWideChar(CP_ACP, 0, pANSI, -1, pUTF16, nCharacters);
|
||||
#else
|
||||
for (int z = 0; z < nCharacters; z++)
|
||||
pUTF16[z] = (str_utf16) ((str_utf8) pANSI[z]);
|
||||
pUTF16[nCharacters] = 0;
|
||||
#endif
|
||||
|
||||
return pUTF16;
|
||||
}
|
||||
|
||||
str_utf16 * GetUTF16FromUTF8(const str_utf8 * pUTF8)
|
||||
{
|
||||
// get the length
|
||||
int nCharacters = 0; int nIndex = 0;
|
||||
while (pUTF8[nIndex] != 0)
|
||||
{
|
||||
if ((pUTF8[nIndex] & 0x80) == 0)
|
||||
nIndex += 1;
|
||||
else if ((pUTF8[nIndex] & 0xE0) == 0xE0)
|
||||
nIndex += 3;
|
||||
else
|
||||
nIndex += 2;
|
||||
|
||||
nCharacters += 1;
|
||||
}
|
||||
|
||||
// make a UTF-16 string
|
||||
str_utf16 * pUTF16 = new str_utf16 [nCharacters + 1];
|
||||
nIndex = 0; nCharacters = 0;
|
||||
while (pUTF8[nIndex] != 0)
|
||||
{
|
||||
if ((pUTF8[nIndex] & 0x80) == 0)
|
||||
{
|
||||
pUTF16[nCharacters] = pUTF8[nIndex];
|
||||
nIndex += 1;
|
||||
}
|
||||
else if ((pUTF8[nIndex] & 0xE0) == 0xE0)
|
||||
{
|
||||
pUTF16[nCharacters] = ((pUTF8[nIndex] & 0x1F) << 12) | ((pUTF8[nIndex + 1] & 0x3F) << 6) | (pUTF8[nIndex + 2] & 0x3F);
|
||||
nIndex += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
pUTF16[nCharacters] = ((pUTF8[nIndex] & 0x3F) << 6) | (pUTF8[nIndex + 1] & 0x3F);
|
||||
nIndex += 2;
|
||||
}
|
||||
|
||||
nCharacters += 1;
|
||||
}
|
||||
pUTF16[nCharacters] = 0;
|
||||
|
||||
return pUTF16;
|
||||
}
|
||||
|
||||
str_utf8 * GetUTF8FromANSI(const str_ansi * pANSI)
|
||||
{
|
||||
str_utf16 * pUTF16 = GetUTF16FromANSI(pANSI);
|
||||
str_utf8 * pUTF8 = GetUTF8FromUTF16(pUTF16);
|
||||
delete [] pUTF16;
|
||||
return pUTF8;
|
||||
}
|
||||
|
||||
str_utf8 * GetUTF8FromUTF16(const str_utf16 * pUTF16)
|
||||
{
|
||||
// get the size(s)
|
||||
int nCharacters = wcslen(pUTF16);
|
||||
int nUTF8Bytes = 0;
|
||||
for (int z = 0; z < nCharacters; z++)
|
||||
{
|
||||
if (pUTF16[z] < 0x0080)
|
||||
nUTF8Bytes += 1;
|
||||
else if (pUTF16[z] < 0x0800)
|
||||
nUTF8Bytes += 2;
|
||||
else
|
||||
nUTF8Bytes += 3;
|
||||
}
|
||||
|
||||
// allocate a UTF-8 string
|
||||
str_utf8 * pUTF8 = new str_utf8 [nUTF8Bytes + 1];
|
||||
|
||||
// create the UTF-8 string
|
||||
int nUTF8Index = 0;
|
||||
for (int z = 0; z < nCharacters; z++)
|
||||
{
|
||||
if (pUTF16[z] < 0x0080)
|
||||
{
|
||||
pUTF8[nUTF8Index++] = (str_utf8) pUTF16[z];
|
||||
}
|
||||
else if (pUTF16[z] < 0x0800)
|
||||
{
|
||||
pUTF8[nUTF8Index++] = 0xC0 | (pUTF16[z] >> 6);
|
||||
pUTF8[nUTF8Index++] = 0x80 | (pUTF16[z] & 0x3F);
|
||||
}
|
||||
else
|
||||
{
|
||||
pUTF8[nUTF8Index++] = 0xE0 | (pUTF16[z] >> 12);
|
||||
pUTF8[nUTF8Index++] = 0x80 | ((pUTF16[z] >> 6) & 0x3F);
|
||||
pUTF8[nUTF8Index++] = 0x80 | (pUTF16[z] & 0x3F);
|
||||
}
|
||||
}
|
||||
pUTF8[nUTF8Index++] = 0;
|
||||
|
||||
// return the UTF-8 string
|
||||
return pUTF8;
|
||||
}
|
||||
15
MAC_SDK/Source/Shared/CharacterHelper.h
Normal file
15
MAC_SDK/Source/Shared/CharacterHelper.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*******************************************************************************************
|
||||
Character set conversion helpers
|
||||
*******************************************************************************************/
|
||||
|
||||
#ifndef CHARACTER_HELPER_H
|
||||
#define CHARACTER_HELPER_H
|
||||
|
||||
str_ansi * GetANSIFromUTF8(const str_utf8 * pUTF8);
|
||||
str_ansi * GetANSIFromUTF16(const str_utf16 * pUTF16);
|
||||
str_utf16 * GetUTF16FromANSI(const str_ansi * pANSI);
|
||||
str_utf16 * GetUTF16FromUTF8(const str_utf8 * pUTF8);
|
||||
str_utf8 * GetUTF8FromANSI(const str_ansi * pANSI);
|
||||
str_utf8 * GetUTF8FromUTF16(const str_utf16 * pUTF16);
|
||||
|
||||
#endif // #ifndef CHARACTER_HELPER_H
|
||||
89
MAC_SDK/Source/Shared/CircleBuffer.cpp
Normal file
89
MAC_SDK/Source/Shared/CircleBuffer.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "All.h"
|
||||
#include "CircleBuffer.h"
|
||||
|
||||
CCircleBuffer::CCircleBuffer()
|
||||
{
|
||||
m_pBuffer = NULL;
|
||||
m_nTotal = 0;
|
||||
m_nHead = 0;
|
||||
m_nTail = 0;
|
||||
m_nEndCap = 0;
|
||||
m_nMaxDirectWriteBytes = 0;
|
||||
}
|
||||
|
||||
CCircleBuffer::~CCircleBuffer()
|
||||
{
|
||||
SAFE_ARRAY_DELETE(m_pBuffer)
|
||||
}
|
||||
|
||||
void CCircleBuffer::CreateBuffer(int nBytes, int nMaxDirectWriteBytes)
|
||||
{
|
||||
SAFE_ARRAY_DELETE(m_pBuffer)
|
||||
|
||||
m_nMaxDirectWriteBytes = nMaxDirectWriteBytes;
|
||||
m_nTotal = nBytes + 1 + nMaxDirectWriteBytes;
|
||||
m_pBuffer = new unsigned char [m_nTotal];
|
||||
m_nHead = 0;
|
||||
m_nTail = 0;
|
||||
m_nEndCap = m_nTotal;
|
||||
}
|
||||
|
||||
int CCircleBuffer::MaxAdd()
|
||||
{
|
||||
int nMaxAdd = (m_nTail >= m_nHead) ? (m_nTotal - 1 - m_nMaxDirectWriteBytes) - (m_nTail - m_nHead) : m_nHead - m_nTail - 1;
|
||||
return nMaxAdd;
|
||||
}
|
||||
|
||||
int CCircleBuffer::MaxGet()
|
||||
{
|
||||
return (m_nTail >= m_nHead) ? m_nTail - m_nHead : (m_nEndCap - m_nHead) + m_nTail;
|
||||
}
|
||||
|
||||
int CCircleBuffer::Get(unsigned char * pBuffer, int nBytes)
|
||||
{
|
||||
int nTotalGetBytes = 0;
|
||||
|
||||
if (pBuffer != NULL && nBytes > 0)
|
||||
{
|
||||
int nHeadBytes = min(m_nEndCap - m_nHead, nBytes);
|
||||
int nFrontBytes = nBytes - nHeadBytes;
|
||||
|
||||
memcpy(&pBuffer[0], &m_pBuffer[m_nHead], nHeadBytes);
|
||||
nTotalGetBytes = nHeadBytes;
|
||||
|
||||
if (nFrontBytes > 0)
|
||||
{
|
||||
memcpy(&pBuffer[nHeadBytes], &m_pBuffer[0], nFrontBytes);
|
||||
nTotalGetBytes += nFrontBytes;
|
||||
}
|
||||
|
||||
RemoveHead(nBytes);
|
||||
}
|
||||
|
||||
return nTotalGetBytes;
|
||||
}
|
||||
|
||||
void CCircleBuffer::Empty()
|
||||
{
|
||||
m_nHead = 0;
|
||||
m_nTail = 0;
|
||||
m_nEndCap = m_nTotal;
|
||||
}
|
||||
|
||||
int CCircleBuffer::RemoveHead(int nBytes)
|
||||
{
|
||||
nBytes = min(MaxGet(), nBytes);
|
||||
m_nHead += nBytes;
|
||||
if (m_nHead >= m_nEndCap)
|
||||
m_nHead -= m_nEndCap;
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
int CCircleBuffer::RemoveTail(int nBytes)
|
||||
{
|
||||
nBytes = min(MaxGet(), nBytes);
|
||||
m_nTail -= nBytes;
|
||||
if (m_nTail < 0)
|
||||
m_nTail += m_nEndCap;
|
||||
return nBytes;
|
||||
}
|
||||
59
MAC_SDK/Source/Shared/CircleBuffer.h
Normal file
59
MAC_SDK/Source/Shared/CircleBuffer.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef APE_CIRCLEBUFFER_H
|
||||
#define APE_CIRCLEBUFFER_H
|
||||
|
||||
class CCircleBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
// construction / destruction
|
||||
CCircleBuffer();
|
||||
virtual ~CCircleBuffer();
|
||||
|
||||
// create the buffer
|
||||
void CreateBuffer(int nBytes, int nMaxDirectWriteBytes);
|
||||
|
||||
// query
|
||||
int MaxAdd();
|
||||
int MaxGet();
|
||||
|
||||
// direct writing
|
||||
inline unsigned char * CCircleBuffer::GetDirectWritePointer()
|
||||
{
|
||||
// return a pointer to the tail -- note that it will always be safe to write
|
||||
// at least m_nMaxDirectWriteBytes since we use an end cap region
|
||||
return &m_pBuffer[m_nTail];
|
||||
}
|
||||
|
||||
inline void CCircleBuffer::UpdateAfterDirectWrite(int nBytes)
|
||||
{
|
||||
// update the tail
|
||||
m_nTail += nBytes;
|
||||
|
||||
// if the tail enters the "end cap" area, set the end cap and loop around
|
||||
if (m_nTail >= (m_nTotal - m_nMaxDirectWriteBytes))
|
||||
{
|
||||
m_nEndCap = m_nTail;
|
||||
m_nTail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// get data
|
||||
int Get(unsigned char * pBuffer, int nBytes);
|
||||
|
||||
// remove / empty
|
||||
void Empty();
|
||||
int RemoveHead(int nBytes);
|
||||
int RemoveTail(int nBytes);
|
||||
|
||||
private:
|
||||
|
||||
int m_nTotal;
|
||||
int m_nMaxDirectWriteBytes;
|
||||
int m_nEndCap;
|
||||
int m_nHead;
|
||||
int m_nTail;
|
||||
unsigned char * m_pBuffer;
|
||||
};
|
||||
|
||||
|
||||
#endif // #ifndef APE_CIRCLEBUFFER_H
|
||||
100
MAC_SDK/Source/Shared/GlobalFunctions.cpp
Normal file
100
MAC_SDK/Source/Shared/GlobalFunctions.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "All.h"
|
||||
#include "GlobalFunctions.h"
|
||||
#include "IO.h"
|
||||
|
||||
/*
|
||||
#ifndef __GNUC_IA32__
|
||||
|
||||
extern "C" BOOL GetMMXAvailable(void)
|
||||
{
|
||||
#ifdef ENABLE_ASSEMBLY
|
||||
|
||||
unsigned long nRegisterEDX;
|
||||
|
||||
try
|
||||
{
|
||||
__asm mov eax, 1
|
||||
__asm CPUID
|
||||
__asm mov nRegisterEDX, edx
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nRegisterEDX & 0x800000)
|
||||
RETURN_ON_EXCEPTION(__asm emms, FALSE)
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // #ifndef __GNUC_IA32__
|
||||
*/
|
||||
|
||||
int ReadSafe(CIO * pIO, void * pBuffer, int nBytes)
|
||||
{
|
||||
unsigned int nBytesRead = 0;
|
||||
int nRetVal = pIO->Read(pBuffer, nBytes, &nBytesRead);
|
||||
if (nRetVal == ERROR_SUCCESS)
|
||||
{
|
||||
if (nBytes != int(nBytesRead))
|
||||
nRetVal = ERROR_IO_READ;
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
int WriteSafe(CIO * pIO, void * pBuffer, int nBytes)
|
||||
{
|
||||
unsigned int nBytesWritten = 0;
|
||||
int nRetVal = pIO->Write(pBuffer, nBytes, &nBytesWritten);
|
||||
if (nRetVal == ERROR_SUCCESS)
|
||||
{
|
||||
if (nBytes != int(nBytesWritten))
|
||||
nRetVal = ERROR_IO_WRITE;
|
||||
}
|
||||
|
||||
return nRetVal;
|
||||
}
|
||||
|
||||
BOOL FileExists(wchar_t * pFilename)
|
||||
{
|
||||
if (0 == wcscmp(pFilename, L"-") || 0 == wcscmp(pFilename, L"/dev/stdin"))
|
||||
return TRUE;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
BOOL bFound = FALSE;
|
||||
|
||||
WIN32_FIND_DATA WFD;
|
||||
HANDLE hFind = FindFirstFile(pFilename, &WFD);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
bFound = TRUE;
|
||||
CloseHandle(hFind);
|
||||
}
|
||||
|
||||
return bFound;
|
||||
|
||||
#else
|
||||
|
||||
CSmartPtr<char> spANSI(GetANSIFromUTF16(pFilename), TRUE);
|
||||
|
||||
struct stat b;
|
||||
|
||||
if (stat(spANSI, &b) != 0)
|
||||
return FALSE;
|
||||
|
||||
if (!S_ISREG(b.st_mode))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
}
|
||||
21
MAC_SDK/Source/Shared/GlobalFunctions.h
Normal file
21
MAC_SDK/Source/Shared/GlobalFunctions.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef APE_GLOBALFUNCTIONS_H
|
||||
#define APE_GLOBALFUNCTIONS_H
|
||||
|
||||
/*************************************************************************************
|
||||
Definitions
|
||||
*************************************************************************************/
|
||||
class CIO;
|
||||
|
||||
/*************************************************************************************
|
||||
Read / Write from an IO source and return failure if the number of bytes specified
|
||||
isn't read or written
|
||||
*************************************************************************************/
|
||||
int ReadSafe(CIO * pIO, void * pBuffer, int nBytes);
|
||||
int WriteSafe(CIO * pIO, void * pBuffer, int nBytes);
|
||||
|
||||
/*************************************************************************************
|
||||
Checks for the existence of a file
|
||||
*************************************************************************************/
|
||||
BOOL FileExists(wchar_t * pFilename);
|
||||
|
||||
#endif // #ifndef APE_GLOBALFUNCTIONS_H
|
||||
27
MAC_SDK/Source/Shared/ID3Genres.h
Normal file
27
MAC_SDK/Source/Shared/ID3Genres.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef APE_ID3GENRES_H
|
||||
#define APE_ID3GENRES_H
|
||||
|
||||
#define GENRE_UNDEFINED 255
|
||||
#define GENRE_COUNT 148
|
||||
|
||||
const LPCWSTR g_ID3Genre[GENRE_COUNT] =
|
||||
{
|
||||
L"Blues", L"Classic Rock", L"Country", L"Dance", L"Disco", L"Funk", L"Grunge", L"Hip-Hop",
|
||||
L"Jazz", L"Metal", L"New Age", L"Oldies", L"Other", L"Pop", L"R&B", L"Rap", L"Reggae", L"Rock", L"Techno",
|
||||
L"Industrial", L"Alternative", L"Ska", L"Death Metal", L"Pranks", L"Soundtrack", L"Euro-Techno", L"Ambient",
|
||||
L"Trip-Hop", L"Vocal", L"Jazz+Funk", L"Fusion", L"Trance", L"Classical", L"Instrumental", L"Acid", L"House", L"Game",
|
||||
L"Sound Clip", L"Gospel", L"Noise", L"AlternRock", L"Bass", L"Soul", L"Punk", L"Space", L"Meditative", L"Instrumental Pop",
|
||||
L"Instrumental Rock", L"Ethnic", L"Gothic", L"Darkwave", L"Techno-Industrial", L"Electronic", L"Pop-Folk", L"Eurodance",
|
||||
L"Dream", L"Southern Rock", L"Comedy", L"Cult", L"Gangsta", L"Top 40", L"Christian Rap", L"Pop/Funk", L"Jungle",
|
||||
L"Native American", L"Cabaret", L"New Wave", L"Psychadelic", L"Rave", L"Showtunes", L"Trailer", L"Lo-Fi", L"Tribal",
|
||||
L"Acid Punk", L"Acid Jazz", L"Polka", L"Retro", L"Musical", L"Rock & Roll", L"Hard Rock", L"Folk", L"Folk-Rock", L"National Folk",
|
||||
L"Swing", L"Fast Fusion", L"Bebop", L"Latin", L"Revival", L"Celtic", L"Bluegrass", L"Avantgarde", L"Gothic Rock", L"Progressive Rock",
|
||||
L"Psychedelic Rock", L"Symphonic Rock", L"Slow Rock", L"Big Band", L"Chorus", L"Easy Listening", L"Acoustic", L"Humour",
|
||||
L"Speech", L"Chanson", L"Opera", L"Chamber Music", L"Sonata", L"Symphony", L"Booty Bass", L"Primus", L"Porn Groove",
|
||||
L"Satire", L"Slow Jam", L"Club", L"Tango", L"Samba", L"Folklore", L"Ballad", L"Power Ballad", L"Rhythmic Soul", L"Freestyle",
|
||||
L"Duet", L"Punk Rock", L"Drum Solo", L"Acapella", L"Euro-House", L"Dance Hall", L"Goa", L"Drum & Bass", L"Club House", L"Hardcore",
|
||||
L"Terror", L"Indie", L"BritPop", L"Black Punk", L"Polsk Punk", L"Beat", L"Christian Gangsta", L"Heavy Metal", L"Black Metal",
|
||||
L"Crossover", L"Contemporary C", L"Christian Rock", L"Merengue", L"Salsa", L"Thrash Metal", L"Anime", L"JPop", L"SynthPop"
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_ID3GENRES_H
|
||||
49
MAC_SDK/Source/Shared/IO.h
Normal file
49
MAC_SDK/Source/Shared/IO.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef APE_IO_H
|
||||
#define APE_IO_H
|
||||
|
||||
#ifndef FILE_BEGIN
|
||||
#define FILE_BEGIN 0
|
||||
#endif
|
||||
|
||||
#ifndef FILE_CURRENT
|
||||
#define FILE_CURRENT 1
|
||||
#endif
|
||||
|
||||
#ifndef FILE_END
|
||||
#define FILE_END 2
|
||||
#endif
|
||||
|
||||
class CIO
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//construction / destruction
|
||||
CIO() { }
|
||||
virtual ~CIO() { };
|
||||
|
||||
// open / close
|
||||
virtual int Open(const wchar_t * pName) = 0;
|
||||
virtual int Close() = 0;
|
||||
|
||||
// read / write
|
||||
virtual int Read(void * pBuffer, unsigned int nBytesToRead, unsigned int * pBytesRead) = 0;
|
||||
virtual int Write(const void * pBuffer, unsigned int nBytesToWrite, unsigned int * pBytesWritten) = 0;
|
||||
|
||||
// seek
|
||||
virtual int Seek(int nDistance, unsigned int nMoveMode) = 0;
|
||||
|
||||
// creation / destruction
|
||||
virtual int Create(const wchar_t * pName) = 0;
|
||||
virtual int Delete() = 0;
|
||||
|
||||
// other functions
|
||||
virtual int SetEOF() = 0;
|
||||
|
||||
// attributes
|
||||
virtual int GetPosition() = 0;
|
||||
virtual int GetSize() = 0;
|
||||
virtual int GetName(wchar_t * pBuffer) = 0;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_IO_H
|
||||
68
MAC_SDK/Source/Shared/NoWindows.h
Normal file
68
MAC_SDK/Source/Shared/NoWindows.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef _WIN32
|
||||
|
||||
#ifndef APE_NOWINDOWS_H
|
||||
#define APE_NOWINDOWS_H
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define NEAR
|
||||
#define FAR
|
||||
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
typedef unsigned short uint16;
|
||||
typedef short int16;
|
||||
typedef unsigned char uint8;
|
||||
typedef char int8;
|
||||
typedef char str_ansi;
|
||||
typedef unsigned char str_utf8;
|
||||
typedef wchar_t str_utf16;
|
||||
|
||||
typedef unsigned long DWORD;
|
||||
typedef int BOOL;
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef float FLOAT;
|
||||
typedef void * HANDLE;
|
||||
typedef unsigned int UINT;
|
||||
typedef unsigned int WPARAM;
|
||||
typedef long LPARAM;
|
||||
typedef const char * LPCSTR;
|
||||
typedef char * LPSTR;
|
||||
typedef long LRESULT;
|
||||
|
||||
#define ZeroMemory(POINTER, BYTES) memset(POINTER, 0, BYTES);
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define __stdcall
|
||||
#define CALLBACK
|
||||
|
||||
#define _stricmp strcasecmp
|
||||
#define _strnicmp strncasecmp
|
||||
|
||||
#define _FPOSOFF(fp) ((long)(fp).__pos)
|
||||
#define MAX_PATH 260
|
||||
|
||||
#ifndef _WAVEFORMATEX_
|
||||
#define _WAVEFORMATEX_
|
||||
|
||||
typedef struct tWAVEFORMATEX
|
||||
{
|
||||
WORD wFormatTag; /* format type */
|
||||
WORD nChannels; /* number of channels (i.e. mono, stereo...) */
|
||||
DWORD nSamplesPerSec; /* sample rate */
|
||||
DWORD nAvgBytesPerSec; /* for buffer estimation */
|
||||
WORD nBlockAlign; /* block size of data */
|
||||
WORD wBitsPerSample; /* number of bits per sample of mono data */
|
||||
WORD cbSize; /* the count in bytes of the size of */
|
||||
/* extra information (after cbSize) */
|
||||
} WAVEFORMATEX, *PWAVEFORMATEX, NEAR *NPWAVEFORMATEX, FAR *LPWAVEFORMATEX;
|
||||
typedef const WAVEFORMATEX FAR *LPCWAVEFORMATEX;
|
||||
|
||||
#endif // #ifndef _WAVEFORMATEX_
|
||||
|
||||
#endif // #ifndef APE_NOWINDOWS_H
|
||||
|
||||
#endif // #ifndef _WIN32
|
||||
120
MAC_SDK/Source/Shared/RollBuffer.h
Normal file
120
MAC_SDK/Source/Shared/RollBuffer.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#ifndef APE_ROLLBUFFER_H
|
||||
#define APE_ROLLBUFFER_H
|
||||
|
||||
template <class TYPE> class CRollBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
CRollBuffer()
|
||||
{
|
||||
m_pData = NULL;
|
||||
m_pCurrent = NULL;
|
||||
}
|
||||
|
||||
~CRollBuffer()
|
||||
{
|
||||
SAFE_ARRAY_DELETE(m_pData);
|
||||
}
|
||||
|
||||
int Create(int nWindowElements, int nHistoryElements)
|
||||
{
|
||||
SAFE_ARRAY_DELETE(m_pData)
|
||||
m_nWindowElements = nWindowElements;
|
||||
m_nHistoryElements = nHistoryElements;
|
||||
|
||||
m_pData = new TYPE[m_nWindowElements + m_nHistoryElements];
|
||||
if (m_pData == NULL)
|
||||
return ERROR_INSUFFICIENT_MEMORY;
|
||||
|
||||
Flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Flush()
|
||||
{
|
||||
ZeroMemory(m_pData, (m_nHistoryElements + 1) * sizeof(TYPE));
|
||||
m_pCurrent = &m_pData[m_nHistoryElements];
|
||||
}
|
||||
|
||||
void Roll()
|
||||
{
|
||||
memcpy(&m_pData[0], &m_pCurrent[-m_nHistoryElements], m_nHistoryElements * sizeof(TYPE));
|
||||
m_pCurrent = &m_pData[m_nHistoryElements];
|
||||
}
|
||||
|
||||
__inline void IncrementSafe()
|
||||
{
|
||||
m_pCurrent++;
|
||||
if (m_pCurrent == &m_pData[m_nWindowElements + m_nHistoryElements])
|
||||
Roll();
|
||||
}
|
||||
|
||||
__inline void IncrementFast()
|
||||
{
|
||||
m_pCurrent++;
|
||||
}
|
||||
|
||||
__inline TYPE & operator[](const int nIndex) const
|
||||
{
|
||||
return m_pCurrent[nIndex];
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
TYPE * m_pData;
|
||||
TYPE * m_pCurrent;
|
||||
int m_nHistoryElements;
|
||||
int m_nWindowElements;
|
||||
};
|
||||
|
||||
template <class TYPE, int WINDOW_ELEMENTS, int HISTORY_ELEMENTS> class CRollBufferFast
|
||||
{
|
||||
public:
|
||||
|
||||
CRollBufferFast()
|
||||
{
|
||||
m_pData = new TYPE[WINDOW_ELEMENTS + HISTORY_ELEMENTS];
|
||||
Flush();
|
||||
}
|
||||
|
||||
~CRollBufferFast()
|
||||
{
|
||||
SAFE_ARRAY_DELETE(m_pData);
|
||||
}
|
||||
|
||||
void Flush()
|
||||
{
|
||||
ZeroMemory(m_pData, (HISTORY_ELEMENTS + 1) * sizeof(TYPE));
|
||||
m_pCurrent = &m_pData[HISTORY_ELEMENTS];
|
||||
}
|
||||
|
||||
void Roll()
|
||||
{
|
||||
memcpy(&m_pData[0], &m_pCurrent[-HISTORY_ELEMENTS], HISTORY_ELEMENTS * sizeof(TYPE));
|
||||
m_pCurrent = &m_pData[HISTORY_ELEMENTS];
|
||||
}
|
||||
|
||||
__inline void IncrementSafe()
|
||||
{
|
||||
m_pCurrent++;
|
||||
if (m_pCurrent == &m_pData[WINDOW_ELEMENTS + HISTORY_ELEMENTS])
|
||||
Roll();
|
||||
}
|
||||
|
||||
__inline void IncrementFast()
|
||||
{
|
||||
m_pCurrent++;
|
||||
}
|
||||
|
||||
__inline TYPE & operator[](const int nIndex) const
|
||||
{
|
||||
return m_pCurrent[nIndex];
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
TYPE * m_pData;
|
||||
TYPE * m_pCurrent;
|
||||
};
|
||||
|
||||
#endif // #ifndef APE_ROLLBUFFER_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user