Update MAC_SDK to 4.33

This commit is contained in:
Grigory Chudov
2018-03-16 00:12:34 -04:00
parent 06a7c9d1f1
commit a811cfd012
171 changed files with 113 additions and 29321 deletions

8
.gitignore vendored
View File

@@ -12,9 +12,5 @@ Debug/
a32/ a32/
launchSettings.json launchSettings.json
/CUETools/TestResults /CUETools/TestResults
/ThirdParty/x64/libFLAC_dynamic.pdb /ThirdParty/*/libFLAC_dynamic.*
/ThirdParty/x64/libFLAC_dynamic.lib /ThirdParty/*/MACLib.*
/ThirdParty/x64/libFLAC_dynamic.exp
/ThirdParty/Win32/libFLAC_dynamic.pdb
/ThirdParty/Win32/libFLAC_dynamic.lib
/ThirdParty/Win32/libFLAC_dynamic.exp

3
.gitmodules vendored
View File

@@ -4,3 +4,6 @@
[submodule "ThirdParty/flac"] [submodule "ThirdParty/flac"]
path = ThirdParty/flac path = ThirdParty/flac
url = https://github.com/gchudov/flac.git url = https://github.com/gchudov/flac.git
[submodule "ThirdParty/MAC_SDK"]
path = ThirdParty/MAC_SDK
url = git@github.com:gchudov/MAC_SDK.git

View File

@@ -7,39 +7,18 @@ using namespace System::Runtime::InteropServices;
using namespace System::IO; using namespace System::IO;
using namespace CUETools::Codecs; using namespace CUETools::Codecs;
#ifndef _WAVEFORMATEX_ #define PLATFORM_WINDOWS
#define _WAVEFORMATEX_ #define PLATFORM_WINDOWS_NO_HEADER
#define EXCLUDE_CIO
#define BOOL int
#define TRUE 1
#define FALSE 0
#define HWND long
/*
* extended waveform format structure used for all non-PCM formats. this
* structure is common to all non-PCM formats.
*/
typedef struct tWAVEFORMATEX
{
Int16 wFormatTag; /* format type */
Int16 nChannels; /* number of channels (i.e. mono, stereo...) */
Int32 nSamplesPerSec; /* sample rate */
Int32 nAvgBytesPerSec; /* for buffer estimation */
Int16 nBlockAlign; /* block size of data */
Int16 wBitsPerSample; /* number of bits per sample of mono data */
Int16 cbSize; /* the count in bytes of the size of */
/* extra information (after cbSize) */
} WAVEFORMATEX, *PWAVEFORMATEX, *NPWAVEFORMATEX, *LPWAVEFORMATEX;
#endif /* _WAVEFORMATEX_ */
#include "All.h" #include "All.h"
#include "MACLib.h" #include "MACLib.h"
#include "IO.h" #include "IO.h"
using namespace ::APE;
namespace CUETools { namespace Codecs { namespace APE { namespace CUETools { namespace Codecs { namespace APE {
class CWinFileIO : public CIO class CWinFileIO : public ::APE::CIO
{ {
public: public:
@@ -54,7 +33,7 @@ namespace CUETools { namespace Codecs { namespace APE {
} }
// open / close // open / close
int Open(const wchar_t * pName) int Open(const wchar_t * pName, bool bOpenReadOnly = false)
{ {
throw gcnew Exception("CIO::Open Unsupported."); throw gcnew Exception("CIO::Open Unsupported.");
} }
@@ -89,7 +68,7 @@ namespace CUETools { namespace Codecs { namespace APE {
// attributes // attributes
int GetPosition(); int GetPosition();
int GetSize(); unsigned int GetSize();
int GetName(wchar_t * pBuffer) int GetName(wchar_t * pBuffer)
{ {
@@ -237,7 +216,7 @@ namespace CUETools { namespace Codecs { namespace APE {
} }
private: private:
IAPEDecompress * pAPEDecompress; ::APE::IAPEDecompress * pAPEDecompress;
Int64 _sampleCount, _sampleOffset; Int64 _sampleCount, _sampleOffset;
AudioPCMConfig^ pcm; AudioPCMConfig^ pcm;
@@ -266,6 +245,14 @@ namespace CUETools { namespace Codecs { namespace APE {
: AudioEncoderSettings("fast normal high extra insane", "high") : AudioEncoderSettings("fast normal high extra insane", "high")
{ {
} }
virtual property String^ Version
{
String^ get()
{
return MAC_VERSION_STRING;
}
}
}; };
[AudioEncoderClass("MAC_SDK", "ape", true, 1, APEWriterSettings::typeid)] [AudioEncoderClass("MAC_SDK", "ape", true, 1, APEWriterSettings::typeid)]
@@ -377,7 +364,7 @@ namespace CUETools { namespace Codecs { namespace APE {
private: private:
IAPECompress * pAPECompress; IAPECompress * pAPECompress;
bool _initialized; bool _initialized;
Int32 _finalSampleCount, _samplesWritten; Int64 _finalSampleCount, _samplesWritten;
APEWriterSettings^ _settings; APEWriterSettings^ _settings;
String^ _path; String^ _path;
Stream^ _IO; Stream^ _IO;
@@ -445,7 +432,7 @@ namespace CUETools { namespace Codecs { namespace APE {
return ((Stream^)_gchIO.Target)->Position; return ((Stream^)_gchIO.Target)->Position;
} }
int CWinFileIO::GetSize() unsigned int CWinFileIO::GetSize()
{ {
return ((Stream^)_gchIO.Target)->Length; return ((Stream^)_gchIO.Target)->Length;
} }

View File

@@ -98,7 +98,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\MAC_SDK\Shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\ThirdParty\MAC_SDK\Source\Shared;..\ThirdParty\MAC_SDK\Source\MACLib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader> <PrecompiledHeader>
@@ -122,7 +122,7 @@
</Midl> </Midl>
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\MAC_SDK\Shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\ThirdParty\MAC_SDK\Source\Shared;..\ThirdParty\MAC_SDK\Source\MACLib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader> <PrecompiledHeader>
@@ -142,7 +142,7 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile> <ClCompile>
<AdditionalIncludeDirectories>..\MAC_SDK\Shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\ThirdParty\MAC_SDK\Source\Shared;..\ThirdParty\MAC_SDK\Source\MACLib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader> <PrecompiledHeader>
@@ -157,6 +157,7 @@
<DataExecutionPrevention> <DataExecutionPrevention>
</DataExecutionPrevention> </DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine> <TargetMachine>MachineX86</TargetMachine>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -164,7 +165,7 @@
<TargetEnvironment>X64</TargetEnvironment> <TargetEnvironment>X64</TargetEnvironment>
</Midl> </Midl>
<ClCompile> <ClCompile>
<AdditionalIncludeDirectories>..\MAC_SDK\Shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\ThirdParty\MAC_SDK\Source\Shared;..\ThirdParty\MAC_SDK\Source\MACLib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader> <PrecompiledHeader>
@@ -179,6 +180,7 @@
<DataExecutionPrevention> <DataExecutionPrevention>
</DataExecutionPrevention> </DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine> <TargetMachine>MachineX64</TargetMachine>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
@@ -225,9 +227,8 @@
<LinkLibraryDependencies>true</LinkLibraryDependencies> <LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs> <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\MAC_SDK\Source\MACLib\MACLib.vcxproj"> <ProjectReference Include="..\ThirdParty\MAC_SDK\Source\Projects\VS2017\MACLib\MACLib.vcxproj">
<Project>{0b9c97d4-61b8-4294-a1df-ba90752a1779}</Project> <Project>{21bf980f-c022-4dcc-9250-7c73528e422b}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@@ -121,55 +121,63 @@ namespace CUETools.eac3to
try try
#endif #endif
{ {
MPLSReader audioSource = null; IAudioSource audioSource = null;
IAudioDest audioDest = null; IAudioDest audioDest = null;
var videos = new List<MPLSStream>();
var audios = new List<MPLSStream>();
List<uint> chapters;
TimeSpan duration;
TagLib.UserDefined.AdditionalFileTypes.Config = config; TagLib.UserDefined.AdditionalFileTypes.Config = config;
try try
{ {
audioSource = new MPLSReader(sourceFile, null); if (true)
Console.ForegroundColor = ConsoleColor.White;
int frameRate = 0;
bool interlaced = false;
var chapters = audioSource.Chapters;
var videos = new List<MPLSStream>();
var audios = new List<MPLSStream>();
audioSource.MPLSHeader.play_item.ForEach(i => i.video.ForEach(v => { if (!videos.Exists(v1 => v1.pid == v.pid)) videos.Add(v); }));
audioSource.MPLSHeader.play_item.ForEach(i => i.audio.ForEach(v => { if (!audios.Exists(v1 => v1.pid == v.pid)) audios.Add(v); }));
videos.ForEach(v => { frameRate = v.FrameRate; interlaced = v.Interlaced; });
Console.Error.WriteLine("M2TS, {0} video track{1}, {2} audio track{3}, {4}, {5}{6}",
videos.Count, videos.Count > 1 ? "s" : "",
audios.Count, audios.Count > 1 ? "s" : "",
CDImageLayout.TimeToString(audioSource.Duration, "{0:0}:{1:00}:{2:00}"), frameRate * (interlaced ? 2 : 1), interlaced ? "i" : "p");
//foreach (var item in audioSource.MPLSHeader.play_item)
//Console.Error.WriteLine("{0}.m2ts", item.clip_id);
{ {
Console.ForegroundColor = ConsoleColor.Gray; var mpls = new MPLSReader(sourceFile, null);
int id = 1; audioSource = mpls;
if (chapters.Count > 1) Console.ForegroundColor = ConsoleColor.White;
int frameRate = 0;
bool interlaced = false;
chapters = mpls.Chapters;
mpls.MPLSHeader.play_item.ForEach(i => i.video.ForEach(v => { if (!videos.Exists(v1 => v1.pid == v.pid)) videos.Add(v); }));
mpls.MPLSHeader.play_item.ForEach(i => i.audio.ForEach(v => { if (!audios.Exists(v1 => v1.pid == v.pid)) audios.Add(v); }));
videos.ForEach(v => { frameRate = v.FrameRate; interlaced = v.Interlaced; });
Console.Error.WriteLine("M2TS, {0} video track{1}, {2} audio track{3}, {4}, {5}{6}",
videos.Count, videos.Count > 1 ? "s" : "",
audios.Count, audios.Count > 1 ? "s" : "",
CDImageLayout.TimeToString(mpls.Duration, "{0:0}:{1:00}:{2:00}"), frameRate * (interlaced ? 2 : 1), interlaced ? "i" : "p");
//foreach (var item in mpls.MPLSHeader.play_item)
//Console.Error.WriteLine("{0}.m2ts", item.clip_id);
{ {
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write(id++);
Console.Error.Write(": ");
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Console.Error.WriteLine("Chapters, {0} chapters", chapters.Count - 1); int id = 1;
} if (chapters.Count > 1)
foreach (var video in videos) {
{ Console.ForegroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.White; Console.Error.Write(id++);
Console.Error.Write(id++); Console.Error.Write(": ");
Console.Error.Write(": "); Console.ForegroundColor = ConsoleColor.Gray;
Console.ForegroundColor = ConsoleColor.Gray; Console.Error.WriteLine("Chapters, {0} chapters", chapters.Count - 1);
Console.Error.WriteLine("{0}, {1}{2}", video.CodecString, video.FormatString, video.FrameRate * (video.Interlaced ? 2 : 1)); }
} foreach (var video in videos)
foreach (var audio in audios) {
{ Console.ForegroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.White; Console.Error.Write(id++);
Console.Error.Write(id++); Console.Error.Write(": ");
Console.Error.Write(": "); Console.ForegroundColor = ConsoleColor.Gray;
Console.ForegroundColor = ConsoleColor.Gray; Console.Error.WriteLine("{0}, {1}{2}", video.CodecString, video.FormatString, video.FrameRate * (video.Interlaced ? 2 : 1));
Console.Error.WriteLine("{0}, {1}, {2}, {3}", audio.CodecString, audio.LanguageString, audio.FormatString, audio.RateString); }
foreach (var audio in audios)
{
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write(id++);
Console.Error.Write(": ");
Console.ForegroundColor = ConsoleColor.Gray;
Console.Error.WriteLine("{0}, {1}, {2}, {3}", audio.CodecString, audio.LanguageString, audio.FormatString, audio.RateString);
}
} }
duration = mpls.Duration;
} }
if (destFile == null) if (destFile == null)
@@ -299,18 +307,21 @@ namespace CUETools.eac3to
throw new Exception("Unknown encoder format: " + destFile); throw new Exception("Unknown encoder format: " + destFile);
} }
if (stream - chapterStreams <= videos.Count) if (audioSource is MPLSReader)
throw new Exception("Video extraction not supported."); {
if (stream - chapterStreams - videos.Count > audios.Count) if (stream - chapterStreams <= videos.Count)
throw new Exception(string.Format("The source file doesn't contain a track with the number {0}.", stream)); throw new Exception("Video extraction not supported.");
ushort pid = audios[stream - chapterStreams - videos.Count - 1].pid; if (stream - chapterStreams - videos.Count > audios.Count)
(audioSource.Settings as BDLPCMReaderSettings).Pid = pid; throw new Exception(string.Format("The source file doesn't contain a track with the number {0}.", stream));
ushort pid = audios[stream - chapterStreams - videos.Count - 1].pid;
(audioSource.Settings as BDLPCMReaderSettings).Pid = pid;
}
} }
AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); AudioBuffer buff = new AudioBuffer(audioSource, 0x10000);
Console.Error.WriteLine("Filename : {0}", sourceFile); Console.Error.WriteLine("Filename : {0}", sourceFile);
Console.Error.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.PCM.SampleRate, audioSource.PCM.ChannelCount, audioSource.PCM.BitsPerSample, Console.Error.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.PCM.SampleRate, audioSource.PCM.ChannelCount, audioSource.PCM.BitsPerSample,
audioSource.Duration); duration);
CUEToolsFormat fmt; CUEToolsFormat fmt;
if (encoderFormat == null) if (encoderFormat == null)
@@ -384,7 +395,7 @@ namespace CUETools.eac3to
TimeSpan elapsed = DateTime.Now - start; TimeSpan elapsed = DateTime.Now - start;
if ((elapsed - lastPrint).TotalMilliseconds > 60) if ((elapsed - lastPrint).TotalMilliseconds > 60)
{ {
long length = (long)(audioSource.Duration.TotalSeconds * audioSource.PCM.SampleRate); long length = (long)(duration.TotalSeconds * audioSource.PCM.SampleRate);
if (length < audioSource.Position) length = audioSource.Position; if (length < audioSource.Position) length = audioSource.Position;
if (length < 1) length = 1; if (length < 1) length = 1;
Console.Error.Write("\rProgress : {0:00}%; {1:0.00}x; {2}/{3}", Console.Error.Write("\rProgress : {0:00}%; {1:0.00}x; {2}/{3}",

View File

@@ -60,8 +60,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.Codecs.APE", "..\C
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.Codecs.WavPack", "..\CUETools.Codecs.WavPack\CUETools.Codecs.WavPack.vcxproj", "{CC2E74B6-534A-43D8-9F16-AC03FE955000}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.Codecs.WavPack", "..\CUETools.Codecs.WavPack\CUETools.Codecs.WavPack.vcxproj", "{CC2E74B6-534A-43D8-9F16-AC03FE955000}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MACLib", "..\MAC_SDK\Source\MACLib\MACLib.vcxproj", "{0B9C97D4-61B8-4294-A1DF-BA90752A1779}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwavpack", "..\wavpack-4.5.0\src\libwavpack.vcxproj", "{5CCCB9CF-0384-458F-BA08-72B73866840F}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwavpack", "..\wavpack-4.5.0\src\libwavpack.vcxproj", "{5CCCB9CF-0384-458F-BA08-72B73866840F}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.ARCUE", "..\CUETools.ARCUE\CUETools.ARCUE.csproj", "{A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.ARCUE", "..\CUETools.ARCUE\CUETools.ARCUE.csproj", "{A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}"
@@ -192,6 +190,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "taglib-sharp", "..\ThirdPar
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libFLAC_dynamic", "..\ThirdParty\flac\src\libFLAC\libFLAC_dynamic.vcxproj", "{4CEFBC83-C215-11DB-8314-0800200C9A66}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libFLAC_dynamic", "..\ThirdParty\flac\src\libFLAC\libFLAC_dynamic.vcxproj", "{4CEFBC83-C215-11DB-8314-0800200C9A66}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MACLib", "..\ThirdParty\MAC_SDK\Source\Projects\VS2017\MACLib\MACLib.vcxproj", "{21BF980F-C022-4DCC-9250-7C73528E422B}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -252,22 +252,6 @@ Global
{CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x64.ActiveCfg = Release|x64 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x64.ActiveCfg = Release|x64
{CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x64.Build.0 = Release|x64 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x64.Build.0 = Release|x64
{CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x86.ActiveCfg = Release|x64 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x86.ActiveCfg = Release|x64
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|Any CPU.ActiveCfg = Debug|x64
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|Mixed Platforms.ActiveCfg = Debug|x64
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|Mixed Platforms.Build.0 = Debug|x64
{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}.Debug|x86.ActiveCfg = Debug|x64
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|Any CPU.ActiveCfg = Release|x64
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|Mixed Platforms.ActiveCfg = Release|x64
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|Mixed Platforms.Build.0 = Release|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
{0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|x86.ActiveCfg = Release|x64
{5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Any CPU.ActiveCfg = Debug|x64 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Any CPU.ActiveCfg = Debug|x64
{5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Mixed Platforms.ActiveCfg = Debug|x64
{5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Mixed Platforms.Build.0 = Debug|x64 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Mixed Platforms.Build.0 = Debug|x64
@@ -1140,6 +1124,24 @@ Global
{4CEFBC83-C215-11DB-8314-0800200C9A66}.Release|x64.Build.0 = Release|x64 {4CEFBC83-C215-11DB-8314-0800200C9A66}.Release|x64.Build.0 = Release|x64
{4CEFBC83-C215-11DB-8314-0800200C9A66}.Release|x86.ActiveCfg = Release|Win32 {4CEFBC83-C215-11DB-8314-0800200C9A66}.Release|x86.ActiveCfg = Release|Win32
{4CEFBC83-C215-11DB-8314-0800200C9A66}.Release|x86.Build.0 = Release|Win32 {4CEFBC83-C215-11DB-8314-0800200C9A66}.Release|x86.Build.0 = Release|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Debug|Any CPU.ActiveCfg = Debug|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Debug|Win32.ActiveCfg = Debug|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Debug|Win32.Build.0 = Debug|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Debug|x64.ActiveCfg = Debug|x64
{21BF980F-C022-4DCC-9250-7C73528E422B}.Debug|x64.Build.0 = Debug|x64
{21BF980F-C022-4DCC-9250-7C73528E422B}.Debug|x86.ActiveCfg = Debug|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Debug|x86.Build.0 = Debug|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Release|Any CPU.ActiveCfg = Release|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Release|Mixed Platforms.Build.0 = Release|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Release|Win32.ActiveCfg = Release|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Release|Win32.Build.0 = Release|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Release|x64.ActiveCfg = Release|x64
{21BF980F-C022-4DCC-9250-7C73528E422B}.Release|x64.Build.0 = Release|x64
{21BF980F-C022-4DCC-9250-7C73528E422B}.Release|x86.ActiveCfg = Release|Win32
{21BF980F-C022-4DCC-9250-7C73528E422B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -1154,7 +1156,6 @@ Global
{0E404B8B-FF82-427F-ADE4-77B54A29219F} = {5D823ABE-D280-4800-824C-2633CBAB2EA9} {0E404B8B-FF82-427F-ADE4-77B54A29219F} = {5D823ABE-D280-4800-824C-2633CBAB2EA9}
{9AE965C4-301E-4C01-B90F-297AF341ACC6} = {39A17A65-E893-44B8-A312-DDCDD990D9D1} {9AE965C4-301E-4C01-B90F-297AF341ACC6} = {39A17A65-E893-44B8-A312-DDCDD990D9D1}
{CC2E74B6-534A-43D8-9F16-AC03FE955000} = {39A17A65-E893-44B8-A312-DDCDD990D9D1} {CC2E74B6-534A-43D8-9F16-AC03FE955000} = {39A17A65-E893-44B8-A312-DDCDD990D9D1}
{0B9C97D4-61B8-4294-A1DF-BA90752A1779} = {8B179853-B7D6-479C-B8B2-6CBCE835D040}
{5CCCB9CF-0384-458F-BA08-72B73866840F} = {8B179853-B7D6-479C-B8B2-6CBCE835D040} {5CCCB9CF-0384-458F-BA08-72B73866840F} = {8B179853-B7D6-479C-B8B2-6CBCE835D040}
{A5A8D8FA-9E32-4010-8AAF-AE580C5AF728} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D} {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D}
{32338A04-5B6B-4C63-8EE7-C6400F73B5D7} = {FD0D49DB-8F02-4A64-A9A3-A5AF54481770} {32338A04-5B6B-4C63-8EE7-C6400F73B5D7} = {FD0D49DB-8F02-4A64-A9A3-A5AF54481770}
@@ -1198,6 +1199,7 @@ Global
{F10AB92C-9AFB-4FC0-94E0-06FCD3CA8155} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D} {F10AB92C-9AFB-4FC0-94E0-06FCD3CA8155} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D}
{1219A514-D3FA-40DB-BBB2-92CE05E35839} = {7E402406-7E51-4F0D-8209-60824C1CD6E8} {1219A514-D3FA-40DB-BBB2-92CE05E35839} = {7E402406-7E51-4F0D-8209-60824C1CD6E8}
{4CEFBC83-C215-11DB-8314-0800200C9A66} = {7E402406-7E51-4F0D-8209-60824C1CD6E8} {4CEFBC83-C215-11DB-8314-0800200C9A66} = {7E402406-7E51-4F0D-8209-60824C1CD6E8}
{21BF980F-C022-4DCC-9250-7C73528E422B} = {8B179853-B7D6-479C-B8B2-6CBCE835D040}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C634D169-5814-4203-94B6-6A11371DDA95} SolutionGuid = {C634D169-5814-4203-94B6-6A11371DDA95}

View File

@@ -1,488 +0,0 @@
{ *************************************************************************** }
{ }
{ Audio Tools Library (Freeware) }
{ Class TAPEtag - for manipulating with APE tags }
{ }
{ Copyright (c) 2001,2002 by Jurgen Faul }
{ E-mail: jfaul@gmx.de }
{ http://jfaul.de/atl }
{ }
{ Version 1.0 (21 April 2002) }
{ - Reading & writing support for APE 1.0 tags }
{ - Reading support for APE 2.0 tags (UTF-8 decoding) }
{ - Tag info: title, artist, album, track, year, genre, comment, copyright }
{ }
{ *************************************************************************** }
unit APEtag;
interface
uses
Classes, SysUtils;
type
{ Class TAPEtag }
TAPEtag = class(TObject)
private
{ Private declarations }
FExists: Boolean;
FVersion: Integer;
FSize: Integer;
FTitle: string;
FArtist: string;
FAlbum: string;
FTrack: Byte;
FYear: string;
FGenre: string;
FComment: string;
FCopyright: string;
procedure FSetTitle(const NewTitle: string);
procedure FSetArtist(const NewArtist: string);
procedure FSetAlbum(const NewAlbum: string);
procedure FSetTrack(const NewTrack: Byte);
procedure FSetYear(const NewYear: string);
procedure FSetGenre(const NewGenre: string);
procedure FSetComment(const NewComment: string);
procedure FSetCopyright(const NewCopyright: string);
public
{ Public declarations }
constructor Create; { Create object }
procedure ResetData; { Reset all data }
function ReadFromFile(const FileName: string): Boolean; { Load tag }
function RemoveFromFile(const FileName: string): Boolean; { Delete tag }
function SaveToFile(const FileName: string): Boolean; { Save tag }
property Exists: Boolean read FExists; { True if tag found }
property Version: Integer read FVersion; { Tag version }
property Size: Integer read FSize; { Total tag size }
property Title: string read FTitle write FSetTitle; { Song title }
property Artist: string read FArtist write FSetArtist; { Artist name }
property Album: string read FAlbum write FSetAlbum; { Album title }
property Track: Byte read FTrack write FSetTrack; { Track number }
property Year: string read FYear write FSetYear; { Release year }
property Genre: string read FGenre write FSetGenre; { Genre name }
property Comment: string read FComment write FSetComment; { Comment }
property Copyright: string read FCopyright write FSetCopyright; { (c) }
end;
implementation
const
{ Tag ID }
ID3V1_ID = 'TAG'; { ID3v1 }
APE_ID = 'APETAGEX'; { APE }
{ Size constants }
ID3V1_TAG_SIZE = 128; { ID3v1 tag }
APE_TAG_FOOTER_SIZE = 32; { APE tag footer }
APE_TAG_HEADER_SIZE = 32; { APE tag header }
{ First version of APE tag }
APE_VERSION_1_0 = 1000;
{ Max. number of supported tag fields }
APE_FIELD_COUNT = 8;
{ Names of supported tag fields }
APE_FIELD: array [1..APE_FIELD_COUNT] of string =
('Title', 'Artist', 'Album', 'Track', 'Year', 'Genre',
'Comment', 'Copyright');
type
{ APE tag data - for internal use }
TagInfo = record
{ Real structure of APE footer }
ID: array [1..8] of Char; { Always "APETAGEX" }
Version: Integer; { Tag version }
Size: Integer; { Tag size including footer }
Fields: Integer; { Number of fields }
Flags: Integer; { Tag flags }
Reserved: array [1..8] of Char; { Reserved for later use }
{ Extended data }
DataShift: Byte; { Used if ID3v1 tag found }
FileSize: Integer; { File size (bytes) }
Field: array [1..APE_FIELD_COUNT] of string; { Information from fields }
end;
{ ********************* Auxiliary functions & procedures ******************** }
function ReadFooter(const FileName: string; var Tag: TagInfo): Boolean;
var
SourceFile: file;
TagID: array [1..3] of Char;
Transferred: Integer;
begin
{ Load footer from file to variable }
try
Result := true;
{ Set read-access and open file }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
Tag.FileSize := FileSize(SourceFile);
{ Check for existing ID3v1 tag }
Seek(SourceFile, Tag.FileSize - ID3V1_TAG_SIZE);
BlockRead(SourceFile, TagID, SizeOf(TagID));
if TagID = ID3V1_ID then Tag.DataShift := ID3V1_TAG_SIZE;
{ Read footer data }
Seek(SourceFile, Tag.FileSize - Tag.DataShift - APE_TAG_FOOTER_SIZE);
BlockRead(SourceFile, Tag, APE_TAG_FOOTER_SIZE, Transferred);
CloseFile(SourceFile);
{ if transfer is not complete }
if Transferred < APE_TAG_FOOTER_SIZE then Result := false;
except
{ Error }
Result := false;
end;
end;
{ --------------------------------------------------------------------------- }
function ConvertFromUTF8(const Source: string): string;
var
Iterator, SourceLength, FChar, NChar: Integer;
begin
{ Convert UTF-8 string to ANSI string }
Result := '';
Iterator := 0;
SourceLength := Length(Source);
while Iterator < SourceLength do
begin
Inc(Iterator);
FChar := Ord(Source[Iterator]);
if FChar >= $80 then
begin
Inc(Iterator);
if Iterator > SourceLength then break;
FChar := FChar and $3F;
if (FChar and $20) <> 0 then
begin
FChar := FChar and $1F;
NChar := Ord(Source[Iterator]);
if (NChar and $C0) <> $80 then break;
FChar := (FChar shl 6) or (NChar and $3F);
Inc(Iterator);
if Iterator > SourceLength then break;
end;
NChar := Ord(Source[Iterator]);
if (NChar and $C0) <> $80 then break;
Result := Result + WideChar((FChar shl 6) or (NChar and $3F));
end
else
Result := Result + WideChar(FChar);
end;
end;
{ --------------------------------------------------------------------------- }
procedure SetTagItem(const FieldName, FieldValue: string; var Tag: TagInfo);
var
Iterator: Byte;
begin
{ Set tag item if supported field found }
for Iterator := 1 to APE_FIELD_COUNT do
if UpperCase(FieldName) = UpperCase(APE_FIELD[Iterator]) then
if Tag.Version > APE_VERSION_1_0 then
Tag.Field[Iterator] := ConvertFromUTF8(FieldValue)
else
Tag.Field[Iterator] := FieldValue;
end;
{ --------------------------------------------------------------------------- }
procedure ReadFields(const FileName: string; var Tag: TagInfo);
var
SourceFile: file;
FieldName: string;
FieldValue: array [1..250] of Char;
NextChar: Char;
Iterator, ValueSize, ValuePosition, FieldFlags: Integer;
begin
try
{ Set read-access, open file }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
Seek(SourceFile, Tag.FileSize - Tag.DataShift - Tag.Size);
{ Read all stored fields }
for Iterator := 1 to Tag.Fields do
begin
FillChar(FieldValue, SizeOf(FieldValue), 0);
BlockRead(SourceFile, ValueSize, SizeOf(ValueSize));
BlockRead(SourceFile, FieldFlags, SizeOf(FieldFlags));
FieldName := '';
repeat
BlockRead(SourceFile, NextChar, SizeOf(NextChar));
FieldName := FieldName + NextChar;
until Ord(NextChar) = 0;
ValuePosition := FilePos(SourceFile);
BlockRead(SourceFile, FieldValue, ValueSize mod SizeOf(FieldValue));
SetTagItem(Trim(FieldName), Trim(FieldValue), Tag);
Seek(SourceFile, ValuePosition + ValueSize);
end;
CloseFile(SourceFile);
except
end;
end;
{ --------------------------------------------------------------------------- }
function GetTrack(const TrackString: string): Byte;
var
Index, Value, Code: Integer;
begin
{ Get track from string }
Index := Pos('/', TrackString);
if Index = 0 then Val(TrackString, Value, Code)
else Val(Copy(TrackString, 1, Index - 1), Value, Code);
if Code = 0 then Result := Value
else Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TruncateFile(const FileName: string; TagSize: Integer): Boolean;
var
SourceFile: file;
begin
try
Result := true;
{ Allow write-access and open file }
FileSetAttr(FileName, 0);
AssignFile(SourceFile, FileName);
FileMode := 2;
Reset(SourceFile, 1);
{ Delete tag }
Seek(SourceFile, FileSize(SourceFile) - TagSize);
Truncate(SourceFile);
CloseFile(SourceFile);
except
{ Error }
Result := false;
end;
end;
{ --------------------------------------------------------------------------- }
procedure BuildFooter(var Tag: TagInfo);
var
Iterator: Integer;
begin
{ Build tag footer }
Tag.ID := APE_ID;
Tag.Version := APE_VERSION_1_0;
Tag.Size := APE_TAG_FOOTER_SIZE;
for Iterator := 1 to APE_FIELD_COUNT do
if Tag.Field[Iterator] <> '' then
begin
Inc(Tag.Size, Length(APE_FIELD[Iterator] + Tag.Field[Iterator]) + 10);
Inc(Tag.Fields);
end;
end;
{ --------------------------------------------------------------------------- }
function AddToFile(const FileName: string; TagData: TStream): Boolean;
var
FileData: TFileStream;
begin
try
{ Add tag data to file }
FileData := TFileStream.Create(FileName, fmOpenWrite or fmShareExclusive);
FileData.Seek(0, soFromEnd);
TagData.Seek(0, soFromBeginning);
FileData.CopyFrom(TagData, TagData.Size);
FileData.Free;
Result := true;
except
{ Error }
Result := false;
end;
end;
{ --------------------------------------------------------------------------- }
function SaveTag(const FileName: string; Tag: TagInfo): Boolean;
var
TagData: TStringStream;
Iterator, ValueSize, Flags: Integer;
begin
{ Build and write tag fields and footer to stream }
TagData := TStringStream.Create('');
for Iterator := 1 to APE_FIELD_COUNT do
if Tag.Field[Iterator] <> '' then
begin
ValueSize := Length(Tag.Field[Iterator]) + 1;
Flags := 0;
TagData.Write(ValueSize, SizeOf(ValueSize));
TagData.Write(Flags, SizeOf(Flags));
TagData.WriteString(APE_FIELD[Iterator] + #0);
TagData.WriteString(Tag.Field[Iterator] + #0);
end;
BuildFooter(Tag);
TagData.Write(Tag, APE_TAG_FOOTER_SIZE);
{ Add created tag to file }
Result := AddToFile(FileName, TagData);
TagData.Free;
end;
{ ********************** Private functions & procedures ********************* }
procedure TAPEtag.FSetTitle(const NewTitle: string);
begin
{ Set song title }
FTitle := Trim(NewTitle);
end;
{ --------------------------------------------------------------------------- }
procedure TAPEtag.FSetArtist(const NewArtist: string);
begin
{ Set artist name }
FArtist := Trim(NewArtist);
end;
{ --------------------------------------------------------------------------- }
procedure TAPEtag.FSetAlbum(const NewAlbum: string);
begin
{ Set album title }
FAlbum := Trim(NewAlbum);
end;
{ --------------------------------------------------------------------------- }
procedure TAPEtag.FSetTrack(const NewTrack: Byte);
begin
{ Set track number }
FTrack := NewTrack;
end;
{ --------------------------------------------------------------------------- }
procedure TAPEtag.FSetYear(const NewYear: string);
begin
{ Set release year }
FYear := Trim(NewYear);
end;
{ --------------------------------------------------------------------------- }
procedure TAPEtag.FSetGenre(const NewGenre: string);
begin
{ Set genre name }
FGenre := Trim(NewGenre);
end;
{ --------------------------------------------------------------------------- }
procedure TAPEtag.FSetComment(const NewComment: string);
begin
{ Set comment }
FComment := Trim(NewComment);
end;
{ --------------------------------------------------------------------------- }
procedure TAPEtag.FSetCopyright(const NewCopyright: string);
begin
{ Set copyright information }
FCopyright := Trim(NewCopyright);
end;
{ ********************** Public functions & procedures ********************** }
constructor TAPEtag.Create;
begin
{ Create object }
inherited;
ResetData;
end;
{ --------------------------------------------------------------------------- }
procedure TAPEtag.ResetData;
begin
{ Reset all variables }
FExists := false;
FVersion := 0;
FSize := 0;
FTitle := '';
FArtist := '';
FAlbum := '';
FTrack := 0;
FYear := '';
FGenre := '';
FComment := '';
FCopyright := '';
end;
{ --------------------------------------------------------------------------- }
function TAPEtag.ReadFromFile(const FileName: string): Boolean;
var
Tag: TagInfo;
begin
{ Reset data and load footer from file to variable }
ResetData;
FillChar(Tag, SizeOf(Tag), 0);
Result := ReadFooter(FileName, Tag);
{ Process data if loaded and footer valid }
if (Result) and (Tag.ID = APE_ID) then
begin
FExists := true;
{ Fill properties with footer data }
FVersion := Tag.Version;
FSize := Tag.Size;
{ Get information from fields }
ReadFields(FileName, Tag);
FTitle := Tag.Field[1];
FArtist := Tag.Field[2];
FAlbum := Tag.Field[3];
FTrack := GetTrack(Tag.Field[4]);
FYear := Tag.Field[5];
FGenre := Tag.Field[6];
FComment := Tag.Field[7];
FCopyright := Tag.Field[8];
end;
end;
{ --------------------------------------------------------------------------- }
function TAPEtag.RemoveFromFile(const FileName: string): Boolean;
var
Tag: TagInfo;
begin
{ Remove tag from file if found }
FillChar(Tag, SizeOf(Tag), 0);
if ReadFooter(FileName, Tag) then
begin
if Tag.ID <> APE_ID then Tag.Size := 0;
if (Tag.Flags shr 31) > 0 then Inc(Tag.Size, APE_TAG_HEADER_SIZE);
Result := TruncateFile(FileName, Tag.DataShift + Tag.Size)
end
else
Result := false;
end;
{ --------------------------------------------------------------------------- }
function TAPEtag.SaveToFile(const FileName: string): Boolean;
var
Tag: TagInfo;
begin
{ Prepare tag data and save to file }
FillChar(Tag, SizeOf(Tag), 0);
Tag.Field[1] := FTitle;
Tag.Field[2] := FArtist;
Tag.Field[3] := FAlbum;
if FTrack > 0 then Tag.Field[4] := IntToStr(FTrack);
Tag.Field[5] := FYear;
Tag.Field[6] := FGenre;
Tag.Field[7] := FComment;
Tag.Field[8] := FCopyright;
{ Delete old tag if exists and write new tag }
Result := (RemoveFromFile(FileName)) and (SaveTag(FileName, Tag));
end;
end.

View File

@@ -1,18 +0,0 @@
APEtag.pas
Tested with Borland Delphi 3,4,5,6
{ *************************************************************************** }
{ }
{ Audio Tools Library (Freeware) }
{ Class TAPEtag - for manipulating with APE tags }
{ }
{ Copyright (c) 2001,2002 by Jurgen Faul }
{ E-mail: jfaul@gmx.de }
{ http://jfaul.de/atl }
{ }
{ Version 1.0 (21 April 2002) }
{ - Reading & writing support for APE 1.0 tags }
{ - Reading support for APE 2.0 tags (UTF-8 decoding) }
{ - Tag info: title, artist, album, track, year, genre, comment, copyright }
{ }
{ *************************************************************************** }

View File

@@ -1,159 +0,0 @@
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, FileCtrl, ExtCtrls, APEtag;
type
TMainForm = class(TForm)
DriveList: TDriveComboBox;
FolderList: TDirectoryListBox;
FileList: TFileListBox;
SaveButton: TButton;
RemoveButton: TButton;
CloseButton: TButton;
InfoBevel: TBevel;
IconImage: TImage;
TagExistsLabel: TLabel;
TagExistsValue: TEdit;
VersionLabel: TLabel;
VersionValue: TEdit;
SizeLabel: TLabel;
SizeValue: TEdit;
TitleLabel: TLabel;
TitleEdit: TEdit;
ArtistLabel: TLabel;
ArtistEdit: TEdit;
AlbumLabel: TLabel;
AlbumEdit: TEdit;
TrackLabel: TLabel;
TrackEdit: TEdit;
YearLabel: TLabel;
YearEdit: TEdit;
GenreLabel: TLabel;
GenreEdit: TEdit;
CommentLabel: TLabel;
CommentEdit: TEdit;
CopyrightLabel: TLabel;
CopyrightEdit: TEdit;
procedure FormCreate(Sender: TObject);
procedure FileListChange(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SaveButtonClick(Sender: TObject);
procedure RemoveButtonClick(Sender: TObject);
procedure CloseButtonClick(Sender: TObject);
private
{ Private declarations }
FileTag: TAPEtag;
procedure ClearAll;
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
procedure TMainForm.ClearAll;
begin
{ Clear all captions }
TagExistsValue.Text := '';
VersionValue.Text := '';
SizeValue.Text := '';
TitleEdit.Text := '';
ArtistEdit.Text := '';
AlbumEdit.Text := '';
TrackEdit.Text := '';
YearEdit.Text := '';
GenreEdit.Text := '';
CommentEdit.Text := '';
CopyrightEdit.Text := '';
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
{ Create object and clear captions }
FileTag := TAPEtag.Create;
ClearAll;
end;
procedure TMainForm.FileListChange(Sender: TObject);
begin
{ Clear captions }
ClearAll;
if FileList.FileName = '' then exit;
if FileExists(FileList.FileName) then
{ Load tag data }
if FileTag.ReadFromFile(FileList.FileName) then
if FileTag.Exists then
begin
{ Fill captions }
TagExistsValue.Text := 'Yes';
VersionValue.Text := FormatFloat('0,000', FileTag.Version);
SizeValue.Text := IntToStr(FileTag.Size) + ' bytes';
TitleEdit.Text := FileTag.Title;
ArtistEdit.Text := FileTag.Artist;
AlbumEdit.Text := FileTag.Album;
if FileTag.Track > 0 then TrackEdit.Text := IntToStr(FileTag.Track);
YearEdit.Text := FileTag.Year;
GenreEdit.Text := FileTag.Genre;
CommentEdit.Text := FileTag.Comment;
CopyrightEdit.Text := FileTag.Copyright;
end
else
{ Tag not found }
TagExistsValue.Text := 'No'
else
{ Read error }
ShowMessage('Can not read tag from the file: ' + FileList.FileName)
else
{ File does not exist }
ShowMessage('The file does not exist: ' + FileList.FileName);
end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{ Free memory }
FileTag.Free;
end;
procedure TMainForm.SaveButtonClick(Sender: TObject);
var
Value, Code: Integer;
begin
{ Prepare tag data }
FileTag.Title := TitleEdit.Text;
FileTag.Artist := ArtistEdit.Text;
FileTag.Album := AlbumEdit.Text;
Val(TrackEdit.Text, Value, Code);
if (Code = 0) and (Value > 0) then FileTag.Track := Value
else FileTag.Track := 0;
FileTag.Year := YearEdit.Text;
FileTag.Genre := GenreEdit.Text;
FileTag.Comment := CommentEdit.Text;
FileTag.Copyright := CopyrightEdit.Text;
{ Save tag data }
if (not FileExists(FileList.FileName)) or
(not FileTag.SaveToFile(FileList.FileName)) then
ShowMessage('Can not save tag to the file: ' + FileList.FileName);
FileListChange(Self);
end;
procedure TMainForm.RemoveButtonClick(Sender: TObject);
begin
{ Delete tag data }
if (FileExists(FileList.FileName)) and
(FileTag.RemoveFromFile(FileList.FileName)) then ClearAll
else ShowMessage('Can not remove tag from the file: ' + FileList.FileName);
end;
procedure TMainForm.CloseButtonClick(Sender: TObject);
begin
{ Exit }
Close;
end;
end.

View File

@@ -1,35 +0,0 @@
-$A8
-$B-
-$C+
-$D+
-$E-
-$F-
-$G+
-$H+
-$I+
-$J-
-$K-
-$L+
-$M-
-$N+
-$O+
-$P+
-$Q-
-$R-
-$S-
-$T-
-$U-
-$V+
-$W-
-$X+
-$YD
-$Z1
-cg
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
-H+
-W+
-M
-$M16384,1048576
-K$00400000
-LE"c:\program files\borland\delphi6\Projects\Bpl"
-LN"c:\program files\borland\delphi6\Projects\Bpl"

View File

@@ -1,96 +0,0 @@
[FileVersion]
Version=6.0
[Compiler]
A=8
B=0
C=1
D=1
E=0
F=0
G=1
H=1
I=1
J=0
K=0
L=1
M=0
N=1
O=1
P=1
Q=0
R=0
S=0
T=0
U=0
V=1
W=0
X=1
Y=1
Z=1
ShowHints=1
ShowWarnings=1
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
[Linker]
MapFile=0
OutputObjs=0
ConsoleApp=1
DebugInfo=0
RemoteSymbols=0
MinStackSize=16384
MaxStackSize=1048576
ImageBase=4194304
ExeDescription=
[Directories]
OutputDir=
UnitOutputDir=
PackageDLLOutputDir=
PackageDCPOutputDir=
SearchPath=
Packages=vcl;rtl;dbrtl;adortl;vcldb;vclx;bdertl;vcldbx;ibxpress;dsnap;cds;bdecds;qrpt;teeui;teedb;tee;dss;teeqr;visualclx;visualdbclx;dsnapcrba;dsnapcon;VclSmp;vclshlctrls;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;inetdb;nmfast;webdsnap;websnap;dbexpress;dbxcds;indy;dclOffice2k
Conditionals=
DebugSourceDirs=
UsePackages=0
[Parameters]
RunParams=
HostApplication=
Launcher=
UseLauncher=0
DebugCWD=
[Language]
ActiveLang=
ProjectLang=
RootDir=
[Version Info]
IncludeVerInfo=0
AutoIncBuild=0
MajorVer=1
MinorVer=0
Release=0
Build=0
Debug=0
PreRelease=0
Special=0
Private=0
DLL=0
Locale=1031
CodePage=1252
[Version Info Keys]
CompanyName=
FileDescription=
FileVersion=1.0.0.0
InternalName=
LegalCopyright=
LegalTrademarks=
OriginalFilename=
ProductName=
ProductVersion=1.0.0.0
Comments=
[HistoryLists\hlUnitAliases]
Count=1
Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
[HistoryLists\hlUnitOutputDirectory]
Count=1
Item0=DCU
[HistoryLists\hlOutputDirectorry]
Count=1
Item0=Data

View File

@@ -1,15 +0,0 @@
program Test;
uses
Forms,
Main in 'Main.pas' {MainForm},
APEtag in 'APEtag.pas';
{$R *.res}
begin
Application.Initialize;
Application.Title := 'APEtag Test';
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.

View File

@@ -1,475 +0,0 @@
{ *************************************************************************** }
{ }
{ Audio Tools Library (Freeware) }
{ Class TID3v1 - for manipulating with ID3v1 tags }
{ }
{ Copyright (c) 2001,2002 by Jurgen Faul }
{ E-mail: jfaul@gmx.de }
{ http://jfaul.de/atl }
{ }
{ Version 1.0 (25 July 2001) }
{ - Reading & writing support for ID3v1.x tags }
{ - Tag info: title, artist, album, track, year, genre, comment }
{ }
{ *************************************************************************** }
unit ID3v1;
interface
uses
Classes, SysUtils;
const
MAX_MUSIC_GENRES = 148; { Max. number of music genres }
DEFAULT_GENRE = 255; { Index for default genre }
{ Used with VersionID property }
TAG_VERSION_1_0 = 1; { Index for ID3v1.0 tag }
TAG_VERSION_1_1 = 2; { Index for ID3v1.1 tag }
var
MusicGenre: array [0..MAX_MUSIC_GENRES - 1] of string; { Genre names }
type
{ Used in TID3v1 class }
String04 = string[4]; { String with max. 4 symbols }
String30 = string[30]; { String with max. 30 symbols }
{ Class TID3v1 }
TID3v1 = class(TObject)
private
{ Private declarations }
FExists: Boolean;
FVersionID: Byte;
FTitle: String30;
FArtist: String30;
FAlbum: String30;
FYear: String04;
FComment: String30;
FTrack: Byte;
FGenreID: Byte;
procedure FSetTitle(const NewTitle: String30);
procedure FSetArtist(const NewArtist: String30);
procedure FSetAlbum(const NewAlbum: String30);
procedure FSetYear(const NewYear: String04);
procedure FSetComment(const NewComment: String30);
procedure FSetTrack(const NewTrack: Byte);
procedure FSetGenreID(const NewGenreID: Byte);
function FGetGenre: string;
public
{ Public declarations }
constructor Create; { Create object }
procedure ResetData; { Reset all data }
function ReadFromFile(const FileName: string): Boolean; { Load tag }
function RemoveFromFile(const FileName: string): Boolean; { Delete tag }
function SaveToFile(const FileName: string): Boolean; { Save tag }
property Exists: Boolean read FExists; { True if tag found }
property VersionID: Byte read FVersionID; { Version code }
property Title: String30 read FTitle write FSetTitle; { Song title }
property Artist: String30 read FArtist write FSetArtist; { Artist name }
property Album: String30 read FAlbum write FSetAlbum; { Album name }
property Year: String04 read FYear write FSetYear; { Year }
property Comment: String30 read FComment write FSetComment; { Comment }
property Track: Byte read FTrack write FSetTrack; { Track number }
property GenreID: Byte read FGenreID write FSetGenreID; { Genre code }
property Genre: string read FGetGenre; { Genre name }
end;
implementation
type
{ Real structure of ID3v1 tag }
TagRecord = record
Header: array [1..3] of Char; { Tag header - must be "TAG" }
Title: array [1..30] of Char; { Title data }
Artist: array [1..30] of Char; { Artist data }
Album: array [1..30] of Char; { Album data }
Year: array [1..4] of Char; { Year data }
Comment: array [1..30] of Char; { Comment data }
Genre: Byte; { Genre data }
end;
{ ********************* Auxiliary functions & procedures ******************** }
function ReadTag(const FileName: string; var TagData: TagRecord): Boolean;
var
SourceFile: file;
begin
try
Result := true;
{ Set read-access and open file }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
{ Read tag }
Seek(SourceFile, FileSize(SourceFile) - 128);
BlockRead(SourceFile, TagData, 128);
CloseFile(SourceFile);
except
{ Error }
Result := false;
end;
end;
{ --------------------------------------------------------------------------- }
function RemoveTag(const FileName: string): Boolean;
var
SourceFile: file;
begin
try
Result := true;
{ Allow write-access and open file }
FileSetAttr(FileName, 0);
AssignFile(SourceFile, FileName);
FileMode := 2;
Reset(SourceFile, 1);
{ Delete tag }
Seek(SourceFile, FileSize(SourceFile) - 128);
Truncate(SourceFile);
CloseFile(SourceFile);
except
{ Error }
Result := false;
end;
end;
{ --------------------------------------------------------------------------- }
function SaveTag(const FileName: string; TagData: TagRecord): Boolean;
var
SourceFile: file;
begin
try
Result := true;
{ Allow write-access and open file }
FileSetAttr(FileName, 0);
AssignFile(SourceFile, FileName);
FileMode := 2;
Reset(SourceFile, 1);
{ Write tag }
Seek(SourceFile, FileSize(SourceFile));
BlockWrite(SourceFile, TagData, SizeOf(TagData));
CloseFile(SourceFile);
except
{ Error }
Result := false;
end;
end;
{ --------------------------------------------------------------------------- }
function GetTagVersion(const TagData: TagRecord): Byte;
begin
Result := TAG_VERSION_1_0;
{ Terms for ID3v1.1 }
if ((TagData.Comment[29] = #0) and (TagData.Comment[30] <> #0)) or
((TagData.Comment[29] = #32) and (TagData.Comment[30] <> #32)) then
Result := TAG_VERSION_1_1;
end;
{ ********************** Private functions & procedures ********************* }
procedure TID3v1.FSetTitle(const NewTitle: String30);
begin
FTitle := TrimRight(NewTitle);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetArtist(const NewArtist: String30);
begin
FArtist := TrimRight(NewArtist);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetAlbum(const NewAlbum: String30);
begin
FAlbum := TrimRight(NewAlbum);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetYear(const NewYear: String04);
begin
FYear := TrimRight(NewYear);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetComment(const NewComment: String30);
begin
FComment := TrimRight(NewComment);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetTrack(const NewTrack: Byte);
begin
FTrack := NewTrack;
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetGenreID(const NewGenreID: Byte);
begin
FGenreID := NewGenreID;
end;
{ --------------------------------------------------------------------------- }
function TID3v1.FGetGenre: string;
begin
Result := '';
{ Return an empty string if the current GenreID is not valid }
if FGenreID in [0..MAX_MUSIC_GENRES - 1] then Result := MusicGenre[FGenreID];
end;
{ ********************** Public functions & procedures ********************** }
constructor TID3v1.Create;
begin
inherited;
ResetData;
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.ResetData;
begin
FExists := false;
FVersionID := TAG_VERSION_1_0;
FTitle := '';
FArtist := '';
FAlbum := '';
FYear := '';
FComment := '';
FTrack := 0;
FGenreID := DEFAULT_GENRE;
end;
{ --------------------------------------------------------------------------- }
function TID3v1.ReadFromFile(const FileName: string): Boolean;
var
TagData: TagRecord;
begin
{ Reset and load tag data from file to variable }
ResetData;
Result := ReadTag(FileName, TagData);
{ Process data if loaded and tag header OK }
if (Result) and (TagData.Header = 'TAG') then
begin
FExists := true;
FVersionID := GetTagVersion(TagData);
{ Fill properties with tag data }
FTitle := TrimRight(TagData.Title);
FArtist := TrimRight(TagData.Artist);
FAlbum := TrimRight(TagData.Album);
FYear := TrimRight(TagData.Year);
if FVersionID = TAG_VERSION_1_0 then
FComment := TrimRight(TagData.Comment)
else
begin
FComment := TrimRight(Copy(TagData.Comment, 1, 28));
FTrack := Ord(TagData.Comment[30]);
end;
FGenreID := TagData.Genre;
end;
end;
{ --------------------------------------------------------------------------- }
function TID3v1.RemoveFromFile(const FileName: string): Boolean;
var
TagData: TagRecord;
begin
{ Find tag }
Result := ReadTag(FileName, TagData);
{ Delete tag if loaded and tag header OK }
if (Result) and (TagData.Header = 'TAG') then Result := RemoveTag(FileName);
end;
{ --------------------------------------------------------------------------- }
function TID3v1.SaveToFile(const FileName: string): Boolean;
var
TagData: TagRecord;
begin
{ Prepare tag record }
FillChar(TagData, SizeOf(TagData), 0);
TagData.Header := 'TAG';
Move(FTitle[1], TagData.Title, Length(FTitle));
Move(FArtist[1], TagData.Artist, Length(FArtist));
Move(FAlbum[1], TagData.Album, Length(FAlbum));
Move(FYear[1], TagData.Year, Length(FYear));
Move(FComment[1], TagData.Comment, Length(FComment));
if FTrack > 0 then
begin
TagData.Comment[29] := #0;
TagData.Comment[30] := Chr(FTrack);
end;
TagData.Genre := FGenreID;
{ Delete old tag and write new tag }
Result := (RemoveFromFile(FileName)) and (SaveTag(FileName, TagData));
end;
{ ************************** Initialize music genres ************************ }
initialization
begin
{ Standard genres }
MusicGenre[0] := 'Blues';
MusicGenre[1] := 'Classic Rock';
MusicGenre[2] := 'Country';
MusicGenre[3] := 'Dance';
MusicGenre[4] := 'Disco';
MusicGenre[5] := 'Funk';
MusicGenre[6] := 'Grunge';
MusicGenre[7] := 'Hip-Hop';
MusicGenre[8] := 'Jazz';
MusicGenre[9] := 'Metal';
MusicGenre[10] := 'New Age';
MusicGenre[11] := 'Oldies';
MusicGenre[12] := 'Other';
MusicGenre[13] := 'Pop';
MusicGenre[14] := 'R&B';
MusicGenre[15] := 'Rap';
MusicGenre[16] := 'Reggae';
MusicGenre[17] := 'Rock';
MusicGenre[18] := 'Techno';
MusicGenre[19] := 'Industrial';
MusicGenre[20] := 'Alternative';
MusicGenre[21] := 'Ska';
MusicGenre[22] := 'Death Metal';
MusicGenre[23] := 'Pranks';
MusicGenre[24] := 'Soundtrack';
MusicGenre[25] := 'Euro-Techno';
MusicGenre[26] := 'Ambient';
MusicGenre[27] := 'Trip-Hop';
MusicGenre[28] := 'Vocal';
MusicGenre[29] := 'Jazz+Funk';
MusicGenre[30] := 'Fusion';
MusicGenre[31] := 'Trance';
MusicGenre[32] := 'Classical';
MusicGenre[33] := 'Instrumental';
MusicGenre[34] := 'Acid';
MusicGenre[35] := 'House';
MusicGenre[36] := 'Game';
MusicGenre[37] := 'Sound Clip';
MusicGenre[38] := 'Gospel';
MusicGenre[39] := 'Noise';
MusicGenre[40] := 'AlternRock';
MusicGenre[41] := 'Bass';
MusicGenre[42] := 'Soul';
MusicGenre[43] := 'Punk';
MusicGenre[44] := 'Space';
MusicGenre[45] := 'Meditative';
MusicGenre[46] := 'Instrumental Pop';
MusicGenre[47] := 'Instrumental Rock';
MusicGenre[48] := 'Ethnic';
MusicGenre[49] := 'Gothic';
MusicGenre[50] := 'Darkwave';
MusicGenre[51] := 'Techno-Industrial';
MusicGenre[52] := 'Electronic';
MusicGenre[53] := 'Pop-Folk';
MusicGenre[54] := 'Eurodance';
MusicGenre[55] := 'Dream';
MusicGenre[56] := 'Southern Rock';
MusicGenre[57] := 'Comedy';
MusicGenre[58] := 'Cult';
MusicGenre[59] := 'Gangsta';
MusicGenre[60] := 'Top 40';
MusicGenre[61] := 'Christian Rap';
MusicGenre[62] := 'Pop/Funk';
MusicGenre[63] := 'Jungle';
MusicGenre[64] := 'Native American';
MusicGenre[65] := 'Cabaret';
MusicGenre[66] := 'New Wave';
MusicGenre[67] := 'Psychadelic';
MusicGenre[68] := 'Rave';
MusicGenre[69] := 'Showtunes';
MusicGenre[70] := 'Trailer';
MusicGenre[71] := 'Lo-Fi';
MusicGenre[72] := 'Tribal';
MusicGenre[73] := 'Acid Punk';
MusicGenre[74] := 'Acid Jazz';
MusicGenre[75] := 'Polka';
MusicGenre[76] := 'Retro';
MusicGenre[77] := 'Musical';
MusicGenre[78] := 'Rock & Roll';
MusicGenre[79] := 'Hard Rock';
{ Extended genres }
MusicGenre[80] := 'Folk';
MusicGenre[81] := 'Folk-Rock';
MusicGenre[82] := 'National Folk';
MusicGenre[83] := 'Swing';
MusicGenre[84] := 'Fast Fusion';
MusicGenre[85] := 'Bebob';
MusicGenre[86] := 'Latin';
MusicGenre[87] := 'Revival';
MusicGenre[88] := 'Celtic';
MusicGenre[89] := 'Bluegrass';
MusicGenre[90] := 'Avantgarde';
MusicGenre[91] := 'Gothic Rock';
MusicGenre[92] := 'Progessive Rock';
MusicGenre[93] := 'Psychedelic Rock';
MusicGenre[94] := 'Symphonic Rock';
MusicGenre[95] := 'Slow Rock';
MusicGenre[96] := 'Big Band';
MusicGenre[97] := 'Chorus';
MusicGenre[98] := 'Easy Listening';
MusicGenre[99] := 'Acoustic';
MusicGenre[100]:= 'Humour';
MusicGenre[101]:= 'Speech';
MusicGenre[102]:= 'Chanson';
MusicGenre[103]:= 'Opera';
MusicGenre[104]:= 'Chamber Music';
MusicGenre[105]:= 'Sonata';
MusicGenre[106]:= 'Symphony';
MusicGenre[107]:= 'Booty Bass';
MusicGenre[108]:= 'Primus';
MusicGenre[109]:= 'Porn Groove';
MusicGenre[110]:= 'Satire';
MusicGenre[111]:= 'Slow Jam';
MusicGenre[112]:= 'Club';
MusicGenre[113]:= 'Tango';
MusicGenre[114]:= 'Samba';
MusicGenre[115]:= 'Folklore';
MusicGenre[116]:= 'Ballad';
MusicGenre[117]:= 'Power Ballad';
MusicGenre[118]:= 'Rhythmic Soul';
MusicGenre[119]:= 'Freestyle';
MusicGenre[120]:= 'Duet';
MusicGenre[121]:= 'Punk Rock';
MusicGenre[122]:= 'Drum Solo';
MusicGenre[123]:= 'A capella';
MusicGenre[124]:= 'Euro-House';
MusicGenre[125]:= 'Dance Hall';
MusicGenre[126]:= 'Goa';
MusicGenre[127]:= 'Drum & Bass';
MusicGenre[128]:= 'Club-House';
MusicGenre[129]:= 'Hardcore';
MusicGenre[130]:= 'Terror';
MusicGenre[131]:= 'Indie';
MusicGenre[132]:= 'BritPop';
MusicGenre[133]:= 'Negerpunk';
MusicGenre[134]:= 'Polsk Punk';
MusicGenre[135]:= 'Beat';
MusicGenre[136]:= 'Christian Gangsta Rap';
MusicGenre[137]:= 'Heavy Metal';
MusicGenre[138]:= 'Black Metal';
MusicGenre[139]:= 'Crossover';
MusicGenre[140]:= 'Contemporary Christian';
MusicGenre[141]:= 'Christian Rock';
MusicGenre[142]:= 'Merengue';
MusicGenre[143]:= 'Salsa';
MusicGenre[144]:= 'Trash Metal';
MusicGenre[145]:= 'Anime';
MusicGenre[146]:= 'JPop';
MusicGenre[147]:= 'Synthpop';
end;
end.

View File

@@ -1,17 +0,0 @@
ID3v1.pas
Tested with Borland Delphi 3,4,5,6
{ *************************************************************************** }
{ }
{ Audio Tools Library (Freeware) }
{ Class TID3v1 - for manipulating with ID3v1 tags }
{ }
{ Copyright (c) 2001,2002 by Jurgen Faul }
{ E-mail: jfaul@gmx.de }
{ http://jfaul.de/atl }
{ }
{ Version 1.0 (25 July 2001) }
{ - Reading & writing support for ID3v1.x tags }
{ - Tag info: title, artist, album, track, year, genre, comment }
{ }
{ *************************************************************************** }

View File

@@ -1,162 +0,0 @@
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, FileCtrl, ExtCtrls, ID3v1;
type
TMainForm = class(TForm)
DriveList: TDriveComboBox;
FolderList: TDirectoryListBox;
FileList: TFileListBox;
CloseButton: TButton;
RemoveButton: TButton;
SaveButton: TButton;
InfoBevel: TBevel;
IconImage: TImage;
TagExistsLabel: TLabel;
TagVersionLabel: TLabel;
TitleLabel: TLabel;
ArtistLabel: TLabel;
AlbumLabel: TLabel;
YearLabel: TLabel;
CommentLabel: TLabel;
TrackLabel: TLabel;
GenreLabel: TLabel;
TitleEdit: TEdit;
ArtistEdit: TEdit;
AlbumEdit: TEdit;
TrackEdit: TEdit;
YearEdit: TEdit;
CommentEdit: TEdit;
GenreComboBox: TComboBox;
TagExistsValue: TEdit;
TagVersionValue: TEdit;
procedure CloseButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FileListChange(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SaveButtonClick(Sender: TObject);
procedure RemoveButtonClick(Sender: TObject);
private
{ Private declarations }
FileTag: TID3v1;
procedure ClearAll;
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
procedure TMainForm.ClearAll;
begin
{ Clear all captions }
TagExistsValue.Text := '';
TagVersionValue.Text := '';
TitleEdit.Text := '';
ArtistEdit.Text := '';
AlbumEdit.Text := '';
TrackEdit.Text := '';
YearEdit.Text := '';
GenreComboBox.ItemIndex := 0;
CommentEdit.Text := '';
end;
procedure TMainForm.CloseButtonClick(Sender: TObject);
begin
{ Exit }
Close;
end;
procedure TMainForm.FormCreate(Sender: TObject);
var
Iterator: Integer;
begin
{ Create object }
FileTag := TID3v1.Create;
{ Fill and initialize genres }
GenreComboBox.Items.Add('');
for Iterator := 0 to MAX_MUSIC_GENRES - 1 do
GenreComboBox.Items.Add(MusicGenre[Iterator]);
{ Reset }
ClearAll;
end;
procedure TMainForm.FileListChange(Sender: TObject);
begin
{ Clear captions }
ClearAll;
if FileList.FileName = '' then exit;
if FileExists(FileList.FileName) then
{ Load tag data }
if FileTag.ReadFromFile(FileList.FileName) then
if FileTag.Exists then
begin
{ Fill captions }
TagExistsValue.Text := 'Yes';
if FileTag.VersionID = TAG_VERSION_1_0 then
TagVersionValue.Text := '1.0'
else
TagVersionValue.Text := '1.1';
TitleEdit.Text := FileTag.Title;
ArtistEdit.Text := FileTag.Artist;
AlbumEdit.Text := FileTag.Album;
TrackEdit.Text := IntToStr(FileTag.Track);
YearEdit.Text := FileTag.Year;
if FileTag.GenreID < MAX_MUSIC_GENRES then
GenreComboBox.ItemIndex := FileTag.GenreID + 1;
CommentEdit.Text := FileTag.Comment;
end
else
{ Tag not found }
TagExistsValue.Text := 'No'
else
{ Read error }
ShowMessage('Can not read tag from the file: ' + FileList.FileName)
else
{ File does not exist }
ShowMessage('The file does not exist: ' + FileList.FileName);
end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{ Free memory }
FileTag.Free;
end;
procedure TMainForm.SaveButtonClick(Sender: TObject);
var
Value, Code: Integer;
begin
{ Prepare tag data }
FileTag.Title := TitleEdit.Text;
FileTag.Artist := ArtistEdit.Text;
FileTag.Album := AlbumEdit.Text;
FileTag.Year := YearEdit.Text;
Val(TrackEdit.Text, Value, Code);
if (Code = 0) and (Value > 0) then FileTag.Track := Value
else FileTag.Track := 0;
if GenreComboBox.ItemIndex = 0 then FileTag.GenreID := DEFAULT_GENRE
else FileTag.GenreID := GenreComboBox.ItemIndex - 1;
FileTag.Comment := CommentEdit.Text;
{ Save tag data }
if (not FileExists(FileList.FileName)) or
(not FileTag.SaveToFile(FileList.FileName)) then
ShowMessage('Can not save tag to the file: ' + FileList.FileName);
FileListChange(Self);
end;
procedure TMainForm.RemoveButtonClick(Sender: TObject);
begin
{ Delete tag data }
if (FileExists(FileList.FileName)) and
(FileTag.RemoveFromFile(FileList.FileName)) then ClearAll
else ShowMessage('Can not remove tag from the file: ' + FileList.FileName);
end;
end.

View File

@@ -1,35 +0,0 @@
-$A8
-$B-
-$C+
-$D+
-$E-
-$F-
-$G+
-$H+
-$I+
-$J-
-$K-
-$L+
-$M-
-$N+
-$O+
-$P+
-$Q-
-$R-
-$S-
-$T-
-$U-
-$V+
-$W-
-$X+
-$YD
-$Z1
-cg
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
-H+
-W+
-M
-$M16384,1048576
-K$00400000
-LE"c:\program files\borland\delphi6\Projects\Bpl"
-LN"c:\program files\borland\delphi6\Projects\Bpl"

View File

@@ -1,96 +0,0 @@
[FileVersion]
Version=6.0
[Compiler]
A=8
B=0
C=1
D=1
E=0
F=0
G=1
H=1
I=1
J=0
K=0
L=1
M=0
N=1
O=1
P=1
Q=0
R=0
S=0
T=0
U=0
V=1
W=0
X=1
Y=1
Z=1
ShowHints=1
ShowWarnings=1
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
[Linker]
MapFile=0
OutputObjs=0
ConsoleApp=1
DebugInfo=0
RemoteSymbols=0
MinStackSize=16384
MaxStackSize=1048576
ImageBase=4194304
ExeDescription=
[Directories]
OutputDir=
UnitOutputDir=
PackageDLLOutputDir=
PackageDCPOutputDir=
SearchPath=
Packages=vcl;rtl;dbrtl;adortl;vcldb;vclx;bdertl;vcldbx;ibxpress;dsnap;cds;bdecds;qrpt;teeui;teedb;tee;dss;teeqr;visualclx;visualdbclx;dsnapcrba;dsnapcon;VclSmp;vclshlctrls;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;inetdb;nmfast;webdsnap;websnap;dbexpress;dbxcds;indy;dclOffice2k
Conditionals=
DebugSourceDirs=
UsePackages=0
[Parameters]
RunParams=
HostApplication=
Launcher=
UseLauncher=0
DebugCWD=
[Language]
ActiveLang=
ProjectLang=
RootDir=
[Version Info]
IncludeVerInfo=0
AutoIncBuild=0
MajorVer=1
MinorVer=0
Release=0
Build=0
Debug=0
PreRelease=0
Special=0
Private=0
DLL=0
Locale=1031
CodePage=1252
[Version Info Keys]
CompanyName=
FileDescription=
FileVersion=1.0.0.0
InternalName=
LegalCopyright=
LegalTrademarks=
OriginalFilename=
ProductName=
ProductVersion=1.0.0.0
Comments=
[HistoryLists\hlUnitAliases]
Count=1
Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
[HistoryLists\hlUnitOutputDirectory]
Count=1
Item0=DCU
[HistoryLists\hlOutputDirectorry]
Count=1
Item0=Data

View File

@@ -1,15 +0,0 @@
program Test;
uses
Forms,
Main in 'Main.pas' {MainForm},
ID3v1 in 'ID3v1.pas';
{$R *.res}
begin
Application.Initialize;
Application.Title := 'ID3v1 Test';
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.

View File

@@ -1,631 +0,0 @@
{ *************************************************************************** }
{ }
{ Audio Tools Library (Freeware) }
{ Class TID3v2 - for manipulating with ID3v2 tags }
{ }
{ Copyright (c) 2001,2002 by Jurgen Faul }
{ E-mail: jfaul@gmx.de }
{ http://jfaul.de/atl }
{ }
{ Version 1.4 (24 March 2002) }
{ - Reading support for ID3v2.2.x & ID3v2.4.x tags }
{ }
{ Version 1.3 (16 February 2002) }
{ - Fixed bug with property Comment }
{ - Added info: composer, encoder, copyright, language, link }
{ }
{ Version 1.2 (17 October 2001) }
{ - Writing support for ID3v2.3.x tags }
{ - Fixed bug with track number detection }
{ - Fixed bug with tag reading }
{ }
{ Version 1.1 (31 August 2001) }
{ - Added public procedure ResetData }
{ }
{ Version 1.0 (14 August 2001) }
{ - Reading support for ID3v2.3.x tags }
{ - Tag info: title, artist, album, track, year, genre, comment }
{ }
{ *************************************************************************** }
unit ID3v2;
interface
uses
Classes, SysUtils;
const
TAG_VERSION_2_2 = 2; { Code for ID3v2.2.x tag }
TAG_VERSION_2_3 = 3; { Code for ID3v2.3.x tag }
TAG_VERSION_2_4 = 4; { Code for ID3v2.4.x tag }
type
{ Class TID3v2 }
TID3v2 = class(TObject)
private
{ Private declarations }
FExists: Boolean;
FVersionID: Byte;
FSize: Integer;
FTitle: string;
FArtist: string;
FAlbum: string;
FTrack: Byte;
FYear: string;
FGenre: string;
FComment: string;
FComposer: string;
FEncoder: string;
FCopyright: string;
FLanguage: string;
FLink: string;
procedure FSetTitle(const NewTitle: string);
procedure FSetArtist(const NewArtist: string);
procedure FSetAlbum(const NewAlbum: string);
procedure FSetTrack(const NewTrack: Byte);
procedure FSetYear(const NewYear: string);
procedure FSetGenre(const NewGenre: string);
procedure FSetComment(const NewComment: string);
procedure FSetComposer(const NewComposer: string);
procedure FSetEncoder(const NewEncoder: string);
procedure FSetCopyright(const NewCopyright: string);
procedure FSetLanguage(const NewLanguage: string);
procedure FSetLink(const NewLink: string);
public
{ Public declarations }
constructor Create; { Create object }
procedure ResetData; { Reset all data }
function ReadFromFile(const FileName: string): Boolean; { Load tag }
function SaveToFile(const FileName: string): Boolean; { Save tag }
function RemoveFromFile(const FileName: string): Boolean; { Delete tag }
property Exists: Boolean read FExists; { True if tag found }
property VersionID: Byte read FVersionID; { Version code }
property Size: Integer read FSize; { Total tag size }
property Title: string read FTitle write FSetTitle; { Song title }
property Artist: string read FArtist write FSetArtist; { Artist name }
property Album: string read FAlbum write FSetAlbum; { Album title }
property Track: Byte read FTrack write FSetTrack; { Track number }
property Year: string read FYear write FSetYear; { Release year }
property Genre: string read FGenre write FSetGenre; { Genre name }
property Comment: string read FComment write FSetComment; { Comment }
property Composer: string read FComposer write FSetComposer; { Composer }
property Encoder: string read FEncoder write FSetEncoder; { Encoder }
property Copyright: string read FCopyright write FSetCopyright; { (c) }
property Language: string read FLanguage write FSetLanguage; { Language }
property Link: string read FLink write FSetLink; { URL link }
end;
implementation
const
{ ID3v2 tag ID }
ID3V2_ID = 'ID3';
{ Max. number of supported tag frames }
ID3V2_FRAME_COUNT = 16;
{ Names of supported tag frames (ID3v2.3.x & ID3v2.4.x) }
ID3V2_FRAME_NEW: array [1..ID3V2_FRAME_COUNT] of string =
('TIT2', 'TPE1', 'TALB', 'TRCK', 'TYER', 'TCON', 'COMM', 'TCOM', 'TENC',
'TCOP', 'TLAN', 'WXXX', 'TDRC', 'TOPE', 'TIT1', 'TOAL');
{ Names of supported tag frames (ID3v2.2.x) }
ID3V2_FRAME_OLD: array [1..ID3V2_FRAME_COUNT] of string =
('TT2', 'TP1', 'TAL', 'TRK', 'TYE', 'TCO', 'COM', 'TCM', 'TEN',
'TCR', 'TLA', 'WXX', 'TOR', 'TOA', 'TT1', 'TOT');
type
{ Frame header (ID3v2.3.x & ID3v2.4.x) }
FrameHeaderNew = record
ID: array [1..4] of Char; { Frame ID }
Size: Integer; { Size excluding header }
Flags: Word; { Flags }
end;
{ Frame header (ID3v2.2.x) }
FrameHeaderOld = record
ID: array [1..3] of Char; { Frame ID }
Size: array [1..3] of Byte; { Size excluding header }
end;
{ ID3v2 header data - for internal use }
TagInfo = record
{ Real structure of ID3v2 header }
ID: array [1..3] of Char; { Always "ID3" }
Version: Byte; { Version number }
Revision: Byte; { Revision number }
Flags: Byte; { Flags of tag }
Size: array [1..4] of Byte; { Tag size excluding header }
{ Extended data }
FileSize: Integer; { File size (bytes) }
Frame: array [1..ID3V2_FRAME_COUNT] of string; { Information from frames }
end;
{ ********************* Auxiliary functions & procedures ******************** }
function ReadHeader(const FileName: string; var Tag: TagInfo): Boolean;
var
SourceFile: file;
Transferred: Integer;
begin
try
Result := true;
{ Set read-access and open file }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
{ Read header and get file size }
BlockRead(SourceFile, Tag, 10, Transferred);
Tag.FileSize := FileSize(SourceFile);
CloseFile(SourceFile);
{ if transfer is not complete }
if Transferred < 10 then Result := false;
except
{ Error }
Result := false;
end;
end;
{ --------------------------------------------------------------------------- }
function GetTagSize(const Tag: TagInfo): Integer;
begin
{ Get total tag size }
Result :=
Tag.Size[1] * $200000 +
Tag.Size[2] * $4000 +
Tag.Size[3] * $80 +
Tag.Size[4] + 10;
if Tag.Flags and $10 > 0 then Inc(Result, 10);
if Result > Tag.FileSize then Result := 0;
end;
{ --------------------------------------------------------------------------- }
procedure SetTagItem(const ID, Data: string; var Tag: TagInfo);
var
Iterator: Byte;
FrameID: string;
begin
{ Set tag item if supported frame found }
for Iterator := 1 to ID3V2_FRAME_COUNT do
begin
if Tag.Version > TAG_VERSION_2_2 then FrameID := ID3V2_FRAME_NEW[Iterator]
else FrameID := ID3V2_FRAME_OLD[Iterator];
if FrameID = ID then Tag.Frame[Iterator] := Data;
end;
end;
{ --------------------------------------------------------------------------- }
function Swap32(const Figure: Integer): Integer;
var
ByteArray: array [1..4] of Byte absolute Figure;
begin
{ Swap 4 bytes }
Result :=
ByteArray[1] * $1000000 +
ByteArray[2] * $10000 +
ByteArray[3] * $100 +
ByteArray[4];
end;
{ --------------------------------------------------------------------------- }
procedure ReadFramesNew(const FileName: string; var Tag: TagInfo);
var
SourceFile: file;
Frame: FrameHeaderNew;
Data: array [1..250] of Char;
DataPosition, DataSize: Integer;
begin
{ Get information from frames (ID3v2.3.x & ID3v2.4.x) }
try
{ Set read-access, open file }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
Seek(SourceFile, 10);
while (FilePos(SourceFile) < GetTagSize(Tag)) and (not EOF(SourceFile)) do
begin
FillChar(Data, SizeOf(Data), 0);
{ Read frame header and check frame ID }
BlockRead(SourceFile, Frame, 10);
if not (Frame.ID[1] in ['A'..'Z']) then break;
{ Note data position and determine significant data size }
DataPosition := FilePos(SourceFile);
if Swap32(Frame.Size) > SizeOf(Data) then DataSize := SizeOf(Data)
else DataSize := Swap32(Frame.Size);
{ Read frame data and set tag item if frame supported }
BlockRead(SourceFile, Data, DataSize);
SetTagItem(Frame.ID, Data, Tag);
Seek(SourceFile, DataPosition + Swap32(Frame.Size));
end;
CloseFile(SourceFile);
except
end;
end;
{ --------------------------------------------------------------------------- }
procedure ReadFramesOld(const FileName: string; var Tag: TagInfo);
var
SourceFile: file;
Frame: FrameHeaderOld;
Data: array [1..250] of Char;
DataPosition, FrameSize, DataSize: Integer;
begin
{ Get information from frames (ID3v2.2.x) }
try
{ Set read-access, open file }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
Seek(SourceFile, 10);
while (FilePos(SourceFile) < GetTagSize(Tag)) and (not EOF(SourceFile)) do
begin
FillChar(Data, SizeOf(Data), 0);
{ Read frame header and check frame ID }
BlockRead(SourceFile, Frame, 6);
if not (Frame.ID[1] in ['A'..'Z']) then break;
{ Note data position and determine significant data size }
DataPosition := FilePos(SourceFile);
FrameSize := Frame.Size[1] shl 16 + Frame.Size[2] shl 8 + Frame.Size[3];
if FrameSize > SizeOf(Data) then DataSize := SizeOf(Data)
else DataSize := FrameSize;
{ Read frame data and set tag item if frame supported }
BlockRead(SourceFile, Data, DataSize);
SetTagItem(Frame.ID, Data, Tag);
Seek(SourceFile, DataPosition + FrameSize);
end;
CloseFile(SourceFile);
except
end;
end;
{ --------------------------------------------------------------------------- }
function GetContent(const Content1, Content2: string): string;
begin
{ Get content preferring the first content }
Result := Trim(Content1);
if Result = '' then Result := Trim(Content2);
end;
{ --------------------------------------------------------------------------- }
function ExtractTrack(const TrackString: string): Byte;
var
Index, Value, Code: Integer;
begin
{ Extract track from string }
Index := Pos('/', Trim(TrackString));
if Index = 0 then Val(Trim(TrackString), Value, Code)
else Val(Copy(Trim(TrackString), 1, Index - 1), Value, Code);
if Code = 0 then Result := Value
else Result := 0;
end;
{ --------------------------------------------------------------------------- }
function ExtractYear(const YearString, DateString: string): string;
begin
{ Extract year from strings }
Result := Trim(YearString);
if Result = '' then Result := Copy(Trim(DateString), 1, 4);
end;
{ --------------------------------------------------------------------------- }
function ExtractGenre(const GenreString: string): string;
begin
{ Extract genre from string }
Result := Trim(GenreString);
if Pos(')', Result) > 0 then Delete(Result, 1, LastDelimiter(')', Result));
end;
{ --------------------------------------------------------------------------- }
function ExtractComment(const CommentString: string): string;
var
Comment: string;
begin
{ Extract comment from string }
Comment := CommentString;
Delete(Comment, 1, 4);
Delete(Comment, 1, Pos(#0, Comment));
Result := Trim(Comment);
end;
{ --------------------------------------------------------------------------- }
function ExtractLink(const LinkString: string): string;
var
Link: string;
begin
{ Extract URL link from string }
Link := LinkString;
Delete(Link, 1, 1);
Delete(Link, 1, Pos(#0, Link));
Result := Trim(Link);
end;
{ --------------------------------------------------------------------------- }
procedure BuildHeader(var Tag: TagInfo);
var
Iterator, TagSize: Integer;
begin
{ Build tag header }
Tag.ID := ID3V2_ID;
Tag.Version := TAG_VERSION_2_3;
Tag.Revision := 0;
Tag.Flags := 0;
TagSize := 0;
for Iterator := 1 to ID3V2_FRAME_COUNT do
if Tag.Frame[Iterator] <> '' then
Inc(TagSize, Length(Tag.Frame[Iterator]) + 11);
{ Convert tag size }
Tag.Size[1] := TagSize div $200000;
Tag.Size[2] := TagSize div $4000;
Tag.Size[3] := TagSize div $80;
Tag.Size[4] := TagSize mod $80;
end;
{ --------------------------------------------------------------------------- }
function RebuildFile(const FileName: string; TagData: TStream): Boolean;
var
Tag: TagInfo;
Source, Destination: TFileStream;
BufferName: string;
begin
{ Rebuild file with old file data and new tag data (optional) }
Result := false;
if (not FileExists(FileName)) or (FileSetAttr(FileName, 0) <> 0) then exit;
if not ReadHeader(FileName, Tag) then exit;
if (TagData = nil) and (Tag.ID <> ID3V2_ID) then exit;
try
{ Create file streams }
BufferName := FileName + '~';
Source := TFileStream.Create(FileName, fmOpenRead or fmShareExclusive);
Destination := TFileStream.Create(BufferName, fmCreate);
{ Copy data blocks }
if Tag.ID = ID3V2_ID then Source.Seek(GetTagSize(Tag), soFromBeginning);
if TagData <> nil then Destination.CopyFrom(TagData, 0);
Destination.CopyFrom(Source, Source.Size - Source.Position);
{ Free resources }
Source.Free;
Destination.Free;
{ Replace old file and delete temporary file }
if (DeleteFile(FileName)) and (RenameFile(BufferName, FileName)) then
Result := true
else
raise Exception.Create('');
except
{ Access error }
if FileExists(BufferName) then DeleteFile(BufferName);
end;
end;
{ --------------------------------------------------------------------------- }
function SaveTag(const FileName: string; Tag: TagInfo): Boolean;
var
TagData: TStringStream;
Iterator, FrameSize: Integer;
begin
{ Build and write tag header and frames to stream }
TagData := TStringStream.Create('');
BuildHeader(Tag);
TagData.Write(Tag, 10);
for Iterator := 1 to ID3V2_FRAME_COUNT do
if Tag.Frame[Iterator] <> '' then
begin
TagData.WriteString(ID3V2_FRAME_NEW[Iterator]);
FrameSize := Swap32(Length(Tag.Frame[Iterator]) + 1);
TagData.Write(FrameSize, SizeOf(FrameSize));
TagData.WriteString(#0#0#0 + Tag.Frame[Iterator]);
end;
{ Rebuild file with new tag data }
Result := RebuildFile(FileName, TagData);
TagData.Free;
end;
{ ********************** Private functions & procedures ********************* }
procedure TID3v2.FSetTitle(const NewTitle: string);
begin
{ Set song title }
FTitle := Trim(NewTitle);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetArtist(const NewArtist: string);
begin
{ Set artist name }
FArtist := Trim(NewArtist);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetAlbum(const NewAlbum: string);
begin
{ Set album title }
FAlbum := Trim(NewAlbum);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetTrack(const NewTrack: Byte);
begin
{ Set track number }
FTrack := NewTrack;
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetYear(const NewYear: string);
begin
{ Set release year }
FYear := Trim(NewYear);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetGenre(const NewGenre: string);
begin
{ Set genre name }
FGenre := Trim(NewGenre);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetComment(const NewComment: string);
begin
{ Set comment }
FComment := Trim(NewComment);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetComposer(const NewComposer: string);
begin
{ Set composer name }
FComposer := Trim(NewComposer);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetEncoder(const NewEncoder: string);
begin
{ Set encoder name }
FEncoder := Trim(NewEncoder);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetCopyright(const NewCopyright: string);
begin
{ Set copyright information }
FCopyright := Trim(NewCopyright);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetLanguage(const NewLanguage: string);
begin
{ Set language }
FLanguage := Trim(NewLanguage);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetLink(const NewLink: string);
begin
{ Set URL link }
FLink := Trim(NewLink);
end;
{ ********************** Public functions & procedures ********************** }
constructor TID3v2.Create;
begin
{ Create object }
inherited;
ResetData;
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.ResetData;
begin
{ Reset all variables }
FExists := false;
FVersionID := 0;
FSize := 0;
FTitle := '';
FArtist := '';
FAlbum := '';
FTrack := 0;
FYear := '';
FGenre := '';
FComment := '';
FComposer := '';
FEncoder := '';
FCopyright := '';
FLanguage := '';
FLink := '';
end;
{ --------------------------------------------------------------------------- }
function TID3v2.ReadFromFile(const FileName: string): Boolean;
var
Tag: TagInfo;
begin
{ Reset data and load header from file to variable }
ResetData;
Result := ReadHeader(FileName, Tag);
{ Process data if loaded and header valid }
if (Result) and (Tag.ID = ID3V2_ID) then
begin
FExists := true;
{ Fill properties with header data }
FVersionID := Tag.Version;
FSize := GetTagSize(Tag);
{ Get information from frames if version supported }
if (FVersionID in [TAG_VERSION_2_2..TAG_VERSION_2_4]) and (FSize > 0) then
begin
if FVersionID > TAG_VERSION_2_2 then ReadFramesNew(FileName, Tag)
else ReadFramesOld(FileName, Tag);
FTitle := GetContent(Tag.Frame[1], Tag.Frame[15]);
FArtist := GetContent(Tag.Frame[2], Tag.Frame[14]);
FAlbum := GetContent(Tag.Frame[3], Tag.Frame[16]);
FTrack := ExtractTrack(Tag.Frame[4]);
FYear := ExtractYear(Tag.Frame[5], Tag.Frame[13]);
FGenre := ExtractGenre(Tag.Frame[6]);
FComment := ExtractComment(Tag.Frame[7]);
FComposer := Trim(Tag.Frame[8]);
FEncoder := Trim(Tag.Frame[9]);
FCopyright := Trim(Tag.Frame[10]);
FLanguage := Trim(Tag.Frame[11]);
FLink := ExtractLink(Tag.Frame[12]);
end;
end;
end;
{ --------------------------------------------------------------------------- }
function TID3v2.SaveToFile(const FileName: string): Boolean;
var
Tag: TagInfo;
begin
{ Prepare tag data and save to file }
FillChar(Tag, SizeOf(Tag), 0);
Tag.Frame[1] := FTitle;
Tag.Frame[2] := FArtist;
Tag.Frame[3] := FAlbum;
if FTrack > 0 then Tag.Frame[4] := IntToStr(FTrack);
Tag.Frame[5] := FYear;
Tag.Frame[6] := FGenre;
if FComment <> '' then Tag.Frame[7] := 'eng' + #0 + FComment;
Tag.Frame[8] := FComposer;
Tag.Frame[9] := FEncoder;
Tag.Frame[10] := FCopyright;
Tag.Frame[11] := FLanguage;
if FLink <> '' then Tag.Frame[12] := #0 + FLink;
Result := SaveTag(FileName, Tag);
end;
{ --------------------------------------------------------------------------- }
function TID3v2.RemoveFromFile(const FileName: string): Boolean;
begin
{ Remove tag from file }
Result := RebuildFile(FileName, nil);
end;
end.

View File

@@ -1,32 +0,0 @@
ID3v2.pas
Tested with Borland Delphi 3,4,5,6
{ *************************************************************************** }
{ }
{ Audio Tools Library (Freeware) }
{ Class TID3v2 - for manipulating with ID3v2 tags }
{ }
{ Copyright (c) 2001,2002 by Jurgen Faul }
{ E-mail: jfaul@gmx.de }
{ http://jfaul.de/atl }
{ }
{ Version 1.4 (24 March 2002) }
{ - Reading support for ID3v2.2.x & ID3v2.4.x tags }
{ }
{ Version 1.3 (16 February 2002) }
{ - Fixed bug with property Comment }
{ - Added info: composer, encoder, copyright, language, link }
{ }
{ Version 1.2 (17 October 2001) }
{ - Writing support for ID3v2.3.x tags }
{ - Fixed bug with track number detection }
{ - Fixed bug with tag reading }
{ }
{ Version 1.1 (31 August 2001) }
{ - Added public procedure ResetData }
{ }
{ Version 1.0 (14 August 2001) }
{ - Reading support for ID3v2.3.x tags }
{ - Tag info: title, artist, album, track, year, genre, comment }
{ }
{ *************************************************************************** }

View File

@@ -1,179 +0,0 @@
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, FileCtrl, ExtCtrls, ID3v2;
type
TMainForm = class(TForm)
DriveList: TDriveComboBox;
FolderList: TDirectoryListBox;
FileList: TFileListBox;
SaveButton: TButton;
RemoveButton: TButton;
CloseButton: TButton;
InfoBevel: TBevel;
IconImage: TImage;
TagExistsLabel: TLabel;
TagExistsValue: TEdit;
VersionLabel: TLabel;
VersionValue: TEdit;
SizeLabel: TLabel;
SizeValue: TEdit;
TitleLabel: TLabel;
TitleEdit: TEdit;
ArtistLabel: TLabel;
ArtistEdit: TEdit;
AlbumLabel: TLabel;
AlbumEdit: TEdit;
TrackLabel: TLabel;
TrackEdit: TEdit;
YearLabel: TLabel;
YearEdit: TEdit;
GenreLabel: TLabel;
GenreEdit: TEdit;
CommentLabel: TLabel;
CommentEdit: TEdit;
ComposerLabel: TLabel;
ComposerEdit: TEdit;
EncoderLabel: TLabel;
EncoderEdit: TEdit;
CopyrightLabel: TLabel;
CopyrightEdit: TEdit;
LanguageLabel: TLabel;
LanguageEdit: TEdit;
LinkLabel: TLabel;
LinkEdit: TEdit;
procedure FormCreate(Sender: TObject);
procedure FileListChange(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SaveButtonClick(Sender: TObject);
procedure RemoveButtonClick(Sender: TObject);
procedure CloseButtonClick(Sender: TObject);
private
{ Private declarations }
FileTag: TID3v2;
procedure ClearAll;
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
procedure TMainForm.ClearAll;
begin
{ Clear all captions }
TagExistsValue.Text := '';
VersionValue.Text := '';
SizeValue.Text := '';
TitleEdit.Text := '';
ArtistEdit.Text := '';
AlbumEdit.Text := '';
TrackEdit.Text := '';
YearEdit.Text := '';
GenreEdit.Text := '';
CommentEdit.Text := '';
ComposerEdit.Text := '';
EncoderEdit.Text := '';
CopyrightEdit.Text := '';
LanguageEdit.Text := '';
LinkEdit.Text := '';
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
{ Create object and clear captions }
FileTag := TID3v2.Create;
ClearAll;
end;
procedure TMainForm.FileListChange(Sender: TObject);
begin
{ Clear captions }
ClearAll;
if FileList.FileName = '' then exit;
if FileExists(FileList.FileName) then
{ Load tag data }
if FileTag.ReadFromFile(FileList.FileName) then
if FileTag.Exists then
begin
{ Fill captions }
TagExistsValue.Text := 'Yes';
VersionValue.Text := '2.' + IntToStr(FileTag.VersionID);
SizeValue.Text := IntToStr(FileTag.Size) + ' bytes';
TitleEdit.Text := FileTag.Title;
ArtistEdit.Text := FileTag.Artist;
AlbumEdit.Text := FileTag.Album;
if FileTag.Track > 0 then TrackEdit.Text := IntToStr(FileTag.Track);
YearEdit.Text := FileTag.Year;
GenreEdit.Text := FileTag.Genre;
CommentEdit.Text := FileTag.Comment;
ComposerEdit.Text := FileTag.Composer;
EncoderEdit.Text := FileTag.Encoder;
CopyrightEdit.Text := FileTag.Copyright;
LanguageEdit.Text := FileTag.Language;
LinkEdit.Text := FileTag.Link;
end
else
{ Tag not found }
TagExistsValue.Text := 'No'
else
{ Read error }
ShowMessage('Can not read tag from the file: ' + FileList.FileName)
else
{ File does not exist }
ShowMessage('The file does not exist: ' + FileList.FileName);
end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{ Free memory }
FileTag.Free;
end;
procedure TMainForm.SaveButtonClick(Sender: TObject);
var
Value, Code: Integer;
begin
{ Prepare tag data }
FileTag.Title := TitleEdit.Text;
FileTag.Artist := ArtistEdit.Text;
FileTag.Album := AlbumEdit.Text;
Val(TrackEdit.Text, Value, Code);
if (Code = 0) and (Value > 0) then FileTag.Track := Value
else FileTag.Track := 0;
FileTag.Year := YearEdit.Text;
FileTag.Genre := GenreEdit.Text;
FileTag.Comment := CommentEdit.Text;
FileTag.Composer := ComposerEdit.Text;
FileTag.Encoder := EncoderEdit.Text;
FileTag.Copyright := CopyrightEdit.Text;
FileTag.Language := LanguageEdit.Text;
FileTag.Link := LinkEdit.Text;
{ Save tag data }
if (not FileExists(FileList.FileName)) or
(not FileTag.SaveToFile(FileList.FileName)) then
ShowMessage('Can not save tag to the file: ' + FileList.FileName);
FileListChange(Self);
end;
procedure TMainForm.RemoveButtonClick(Sender: TObject);
begin
{ Delete tag data }
if (FileExists(FileList.FileName)) and
(FileTag.RemoveFromFile(FileList.FileName)) then ClearAll
else ShowMessage('Can not remove tag from the file: ' + FileList.FileName);
end;
procedure TMainForm.CloseButtonClick(Sender: TObject);
begin
{ Exit }
Close;
end;
end.

View File

@@ -1,35 +0,0 @@
-$A8
-$B-
-$C+
-$D+
-$E-
-$F-
-$G+
-$H+
-$I+
-$J-
-$K-
-$L+
-$M-
-$N+
-$O+
-$P+
-$Q-
-$R-
-$S-
-$T-
-$U-
-$V+
-$W-
-$X+
-$YD
-$Z1
-cg
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
-H+
-W+
-M
-$M16384,1048576
-K$00400000
-LE"c:\program files\borland\delphi6\Projects\Bpl"
-LN"c:\program files\borland\delphi6\Projects\Bpl"

View File

@@ -1,96 +0,0 @@
[FileVersion]
Version=6.0
[Compiler]
A=8
B=0
C=1
D=1
E=0
F=0
G=1
H=1
I=1
J=0
K=0
L=1
M=0
N=1
O=1
P=1
Q=0
R=0
S=0
T=0
U=0
V=1
W=0
X=1
Y=1
Z=1
ShowHints=1
ShowWarnings=1
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
[Linker]
MapFile=0
OutputObjs=0
ConsoleApp=1
DebugInfo=0
RemoteSymbols=0
MinStackSize=16384
MaxStackSize=1048576
ImageBase=4194304
ExeDescription=
[Directories]
OutputDir=
UnitOutputDir=
PackageDLLOutputDir=
PackageDCPOutputDir=
SearchPath=
Packages=vcl;rtl;dbrtl;adortl;vcldb;vclx;bdertl;vcldbx;ibxpress;dsnap;cds;bdecds;qrpt;teeui;teedb;tee;dss;teeqr;visualclx;visualdbclx;dsnapcrba;dsnapcon;VclSmp;vclshlctrls;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;inetdb;nmfast;webdsnap;websnap;dbexpress;dbxcds;indy;dclOffice2k
Conditionals=
DebugSourceDirs=
UsePackages=0
[Parameters]
RunParams=
HostApplication=
Launcher=
UseLauncher=0
DebugCWD=
[Language]
ActiveLang=
ProjectLang=
RootDir=
[Version Info]
IncludeVerInfo=0
AutoIncBuild=0
MajorVer=1
MinorVer=0
Release=0
Build=0
Debug=0
PreRelease=0
Special=0
Private=0
DLL=0
Locale=1031
CodePage=1252
[Version Info Keys]
CompanyName=
FileDescription=
FileVersion=1.0.0.0
InternalName=
LegalCopyright=
LegalTrademarks=
OriginalFilename=
ProductName=
ProductVersion=1.0.0.0
Comments=
[HistoryLists\hlUnitAliases]
Count=1
Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
[HistoryLists\hlUnitOutputDirectory]
Count=1
Item0=DCU
[HistoryLists\hlOutputDirectorry]
Count=1
Item0=Data

View File

@@ -1,15 +0,0 @@
program Test;
uses
Forms,
Main in 'Main.pas' {MainForm},
ID3v2 in 'ID3v2.pas';
{$R *.res}
begin
Application.Initialize;
Application.Title := 'ID3v2 Test';
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.

View File

@@ -1,30 +0,0 @@
Monkey.pas (ID3v1.pas, ID3v2.pas, APEtag.pas needed)
Tested with Borland Delphi 3,4,5,6
{ *************************************************************************** }
{ }
{ Audio Tools Library (Freeware) }
{ Class TMonkey - for manipulating with Monkey's Audio file information }
{ }
{ Uses: }
{ - Class TID3v1 }
{ - Class TID3v2 }
{ - Class TAPEtag }
{ }
{ Copyright (c) 2001,2002 by Jurgen Faul }
{ E-mail: jfaul@gmx.de }
{ http://jfaul.de/atl }
{ }
{ Version 1.2 (21 April 2002) }
{ - Class TID3v2: support for ID3v2 tags }
{ - Class TAPEtag: support for APE tags }
{ }
{ Version 1.1 (11 September 2001) }
{ - Added property Samples }
{ - Removed WAV header information }
{ }
{ Version 1.0 (7 September 2001) }
{ - Support for Monkey's Audio files }
{ - Class TID3v1: reading & writing support for ID3v1.x tags }
{ }
{ *************************************************************************** }

View File

@@ -1,131 +0,0 @@
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, FileCtrl, ExtCtrls, Monkey;
type
TMainForm = class(TForm)
DriveList: TDriveComboBox;
FolderList: TDirectoryListBox;
FileList: TFileListBox;
CloseButton: TButton;
InfoBevel: TBevel;
IconImage: TImage;
ValidHeaderLabel: TLabel;
FileLengthLabel: TLabel;
ValidHeaderValue: TEdit;
ChannelModeValue: TEdit;
ChannelModeLabel: TLabel;
SampleRateLabel: TLabel;
BitsPerSampleLabel: TLabel;
DurationLabel: TLabel;
SampleRateValue: TEdit;
BitsPerSampleValue: TEdit;
DurationValue: TEdit;
FileLengthValue: TEdit;
CompressionLabel: TLabel;
CompressionValue: TEdit;
PeakLevelLabel: TLabel;
PeakLevelValue: TEdit;
FramesLabel: TLabel;
FramesValue: TEdit;
FlagsLabel: TLabel;
FlagsValue: TEdit;
SeekElementsLabel: TLabel;
SeekElementsValue: TEdit;
TotalSamplesLabel: TLabel;
TotalSamplesValue: TEdit;
procedure CloseButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FileListChange(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
Monkey: TMonkey;
procedure ClearAll;
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
procedure TMainForm.ClearAll;
begin
{ Clear all captions }
ValidHeaderValue.Text := '';
FileLengthValue.Text := '';
ChannelModeValue.Text := '';
SampleRateValue.Text := '';
BitsPerSampleValue.Text := '';
DurationValue.Text := '';
FlagsValue.Text := '';
FramesValue.Text := '';
TotalSamplesValue.Text := '';
PeakLevelValue.Text := '';
SeekElementsValue.Text := '';
CompressionValue.Text := '';
end;
procedure TMainForm.CloseButtonClick(Sender: TObject);
begin
{ Exit }
Close;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
{ Create object and reset captions }
Monkey := TMonkey.Create;
ClearAll;
end;
procedure TMainForm.FileListChange(Sender: TObject);
begin
{ Clear captions }
ClearAll;
if FileList.FileName = '' then exit;
if FileExists(FileList.FileName) then
{ Load Monkey's Audio data }
if Monkey.ReadFromFile(FileList.FileName) then
if Monkey.Valid then
begin
{ Fill captions }
ValidHeaderValue.Text := 'Yes, version ' + Monkey.Version;
FileLengthValue.Text := IntToStr(Monkey.FileLength) + ' bytes';
ChannelModeValue.Text := Monkey.ChannelMode;
SampleRateValue.Text := IntToStr(Monkey.Header.SampleRate) + ' hz';
BitsPerSampleValue.Text := IntToStr(Monkey.Bits) + ' bit';
DurationValue.Text := FormatFloat('.000', Monkey.Duration) + ' sec.';
FlagsValue.Text := IntToStr(Monkey.Header.Flags);
FramesValue.Text := IntToStr(Monkey.Header.Frames);
TotalSamplesValue.Text := IntToStr(Monkey.Samples);
PeakLevelValue.Text := FormatFloat('00.00', Monkey.Peak) + '% - ' +
IntToStr(Monkey.Header.PeakLevel);
SeekElementsValue.Text := IntToStr(Monkey.Header.SeekElements);
CompressionValue.Text := FormatFloat('00.00', Monkey.Ratio) + '% - ' +
Monkey.Compression;
end
else
{ Header not found }
ValidHeaderValue.Text := 'No'
else
{ Read error }
ShowMessage('Can not read header in the file: ' + FileList.FileName)
else
{ File does not exist }
ShowMessage('The file does not exist: ' + FileList.FileName);
end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{ Free memory }
Monkey.Free;
end;
end.

View File

@@ -1,300 +0,0 @@
{ *************************************************************************** }
{ }
{ Audio Tools Library (Freeware) }
{ Class TMonkey - for manipulating with Monkey's Audio file information }
{ }
{ Uses: }
{ - Class TID3v1 }
{ - Class TID3v2 }
{ - Class TAPEtag }
{ }
{ Copyright (c) 2001,2002 by Jurgen Faul }
{ E-mail: jfaul@gmx.de }
{ http://jfaul.de/atl }
{ }
{ Version 1.2 (21 April 2002) }
{ - Class TID3v2: support for ID3v2 tags }
{ - Class TAPEtag: support for APE tags }
{ }
{ Version 1.1 (11 September 2001) }
{ - Added property Samples }
{ - Removed WAV header information }
{ }
{ Version 1.0 (7 September 2001) }
{ - Support for Monkey's Audio files }
{ - Class TID3v1: reading & writing support for ID3v1.x tags }
{ }
{ *************************************************************************** }
unit Monkey;
interface
uses
Classes, SysUtils, ID3v1, ID3v2, APEtag;
const
{ Compression level codes }
MONKEY_COMPRESSION_FAST = 1000; { Fast (poor) }
MONKEY_COMPRESSION_NORMAL = 2000; { Normal (good) }
MONKEY_COMPRESSION_HIGH = 3000; { High (very good) }
MONKEY_COMPRESSION_EXTRA_HIGH = 4000; { Extra high (best) }
{ Compression level names }
MONKEY_COMPRESSION: array [0..4] of string =
('Unknown', 'Fast', 'Normal', 'High', 'Extra High');
{ Format flags }
MONKEY_FLAG_8_BIT = 1; { Audio 8-bit }
MONKEY_FLAG_CRC = 2; { New CRC32 error detection }
MONKEY_FLAG_PEAK_LEVEL = 4; { Peak level stored }
MONKEY_FLAG_24_BIT = 8; { Audio 24-bit }
MONKEY_FLAG_SEEK_ELEMENTS = 16; { Number of seek elements stored }
MONKEY_FLAG_WAV_NOT_STORED = 32; { WAV header not stored }
{ Channel mode names }
MONKEY_MODE: array [0..2] of string =
('Unknown', 'Mono', 'Stereo');
type
{ Real structure of Monkey's Audio header }
MonkeyHeader = record
ID: array [1..4] of Char; { Always "MAC " }
VersionID: Word; { Version number * 1000 (3.91 = 3910) }
CompressionID: Word; { Compression level code }
Flags: Word; { Any format flags }
Channels: Word; { Number of channels }
SampleRate: Integer; { Sample rate (hz) }
HeaderBytes: Integer; { Header length (without header ID) }
TerminatingBytes: Integer; { Extended data }
Frames: Integer; { Number of frames in the file }
FinalSamples: Integer; { Number of samples in the final frame }
PeakLevel: Integer; { Peak level (if stored) }
SeekElements: Integer; { Number of seek elements (if stored) }
end;
{ Class TMonkey }
TMonkey = class(TObject)
private
{ Private declarations }
FFileLength: Integer;
FHeader: MonkeyHeader;
FID3v1: TID3v1;
FID3v2: TID3v2;
FAPEtag: TAPEtag;
procedure FResetData;
function FGetValid: Boolean;
function FGetVersion: string;
function FGetCompression: string;
function FGetBits: Byte;
function FGetChannelMode: string;
function FGetPeak: Double;
function FGetSamplesPerFrame: Integer;
function FGetSamples: Integer;
function FGetDuration: Double;
function FGetRatio: Double;
public
{ Public declarations }
constructor Create; { Create object }
destructor Destroy; override; { Destroy object }
function ReadFromFile(const FileName: string): Boolean; { Load header }
property FileLength: Integer read FFileLength; { File length (bytes) }
property Header: MonkeyHeader read FHeader; { Monkey's Audio header }
property ID3v1: TID3v1 read FID3v1; { ID3v1 tag data }
property ID3v2: TID3v2 read FID3v2; { ID3v2 tag data }
property APEtag: TAPEtag read FAPEtag; { APE tag data }
property Valid: Boolean read FGetValid; { True if header valid }
property Version: string read FGetVersion; { Encoder version }
property Compression: string read FGetCompression; { Compression level }
property Bits: Byte read FGetBits; { Bits per sample }
property ChannelMode: string read FGetChannelMode; { Channel mode }
property Peak: Double read FGetPeak; { Peak level ratio (%) }
property Samples: Integer read FGetSamples; { Number of samples }
property Duration: Double read FGetDuration; { Duration (seconds) }
property Ratio: Double read FGetRatio; { Compression ratio (%) }
end;
implementation
{ ********************** Private functions & procedures ********************* }
procedure TMonkey.FResetData;
begin
{ Reset data }
FFileLength := 0;
FillChar(FHeader, SizeOf(FHeader), 0);
FID3v1.ResetData;
FID3v2.ResetData;
FAPEtag.ResetData;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetValid: Boolean;
begin
{ Check for right Monkey's Audio file data }
Result :=
(FHeader.ID = 'MAC ') and
(FHeader.SampleRate > 0) and
(FHeader.Channels > 0);
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetVersion: string;
begin
{ Get encoder version }
if FHeader.VersionID = 0 then Result := ''
else Str(FHeader.VersionID / 1000 : 4 : 2, Result);
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetCompression: string;
begin
{ Get compression level }
Result := MONKEY_COMPRESSION[FHeader.CompressionID div 1000];
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetBits: Byte;
begin
{ Get number of bits per sample }
if FGetValid then
begin
Result := 16;
if FHeader.Flags and MONKEY_FLAG_8_BIT > 0 then Result := 8;
if FHeader.Flags and MONKEY_FLAG_24_BIT > 0 then Result := 24;
end
else
Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetChannelMode: string;
begin
{ Get channel mode }
Result := MONKEY_MODE[FHeader.Channels];
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetPeak: Double;
begin
{ Get peak level ratio }
if (FGetValid) and (FHeader.Flags and MONKEY_FLAG_PEAK_LEVEL > 0) then
case FGetBits of
16: Result := FHeader.PeakLevel / 32768 * 100;
24: Result := FHeader.PeakLevel / 8388608 * 100;
else Result := FHeader.PeakLevel / 128 * 100;
end
else
Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetSamplesPerFrame: Integer;
begin
{ Get number of samples in a frame }
if FGetValid then
if (FHeader.VersionID >= 3900) or
((FHeader.VersionID >= 3800) and
(FHeader.CompressionID = MONKEY_COMPRESSION_EXTRA_HIGH)) then
Result := 73728
else
Result := 9216
else
Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetSamples: Integer;
begin
{ Get number of samples }
if FGetValid then
Result := (FHeader.Frames - 1) * FGetSamplesPerFrame + FHeader.FinalSamples
else
Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetDuration: Double;
begin
{ Get song duration }
if FGetValid then Result := FGetSamples / FHeader.SampleRate
else Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetRatio: Double;
begin
{ Get compression ratio }
if FGetValid then
Result := FFileLength /
(FGetSamples * FHeader.Channels * FGetBits / 8 + 44) * 100
else
Result := 0;
end;
{ ********************** Public functions & procedures ********************** }
constructor TMonkey.Create;
begin
{ Create object }
inherited;
FID3v1 := TID3v1.Create;
FID3v2 := TID3v2.Create;
FAPEtag := TAPEtag.Create;
FResetData;
end;
{ --------------------------------------------------------------------------- }
destructor TMonkey.Destroy;
begin
{ Destroy object }
FID3v1.Free;
FID3v2.Free;
FAPEtag.Free;
inherited;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.ReadFromFile(const FileName: string): Boolean;
var
SourceFile: file;
begin
try
{ Reset data and search for file tag }
FResetData;
if (not FID3v1.ReadFromFile(FileName)) or
(not FID3v2.ReadFromFile(FileName)) or
(not FAPEtag.ReadFromFile(FileName)) then raise Exception.Create('');
{ Set read-access, open file and get file length }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
FFileLength := FileSize(SourceFile);
{ Read Monkey's Audio header data }
Seek(SourceFile, ID3v2.Size);
BlockRead(SourceFile, FHeader, SizeOf(FHeader));
if FHeader.Flags and MONKEY_FLAG_PEAK_LEVEL = 0 then
FHeader.PeakLevel := 0;
if FHeader.Flags and MONKEY_FLAG_SEEK_ELEMENTS = 0 then
FHeader.SeekElements := 0;
CloseFile(SourceFile);
Result := true;
except
FResetData;
Result := false;
end;
end;
end.

View File

@@ -1,35 +0,0 @@
-$A8
-$B-
-$C+
-$D+
-$E-
-$F-
-$G+
-$H+
-$I+
-$J-
-$K-
-$L+
-$M-
-$N+
-$O+
-$P+
-$Q-
-$R-
-$S-
-$T-
-$U-
-$V+
-$W-
-$X+
-$YD
-$Z1
-cg
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
-H+
-W+
-M
-$M16384,1048576
-K$00400000
-LE"c:\program files\borland\delphi6\Projects\Bpl"
-LN"c:\program files\borland\delphi6\Projects\Bpl"

View File

@@ -1,96 +0,0 @@
[FileVersion]
Version=6.0
[Compiler]
A=8
B=0
C=1
D=1
E=0
F=0
G=1
H=1
I=1
J=0
K=0
L=1
M=0
N=1
O=1
P=1
Q=0
R=0
S=0
T=0
U=0
V=1
W=0
X=1
Y=1
Z=1
ShowHints=1
ShowWarnings=1
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
[Linker]
MapFile=0
OutputObjs=0
ConsoleApp=1
DebugInfo=0
RemoteSymbols=0
MinStackSize=16384
MaxStackSize=1048576
ImageBase=4194304
ExeDescription=
[Directories]
OutputDir=
UnitOutputDir=
PackageDLLOutputDir=
PackageDCPOutputDir=
SearchPath=
Packages=vcl;rtl;dbrtl;adortl;vcldb;vclx;bdertl;vcldbx;ibxpress;dsnap;cds;bdecds;qrpt;teeui;teedb;tee;dss;teeqr;visualclx;visualdbclx;dsnapcrba;dsnapcon;VclSmp;vclshlctrls;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;inetdb;nmfast;webdsnap;websnap;dbexpress;dbxcds;indy;dclOffice2k
Conditionals=
DebugSourceDirs=
UsePackages=0
[Parameters]
RunParams=
HostApplication=
Launcher=
UseLauncher=0
DebugCWD=
[Language]
ActiveLang=
ProjectLang=
RootDir=
[Version Info]
IncludeVerInfo=0
AutoIncBuild=0
MajorVer=1
MinorVer=0
Release=0
Build=0
Debug=0
PreRelease=0
Special=0
Private=0
DLL=0
Locale=1031
CodePage=1252
[Version Info Keys]
CompanyName=
FileDescription=
FileVersion=1.0.0.0
InternalName=
LegalCopyright=
LegalTrademarks=
OriginalFilename=
ProductName=
ProductVersion=1.0.0.0
Comments=
[HistoryLists\hlUnitAliases]
Count=1
Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
[HistoryLists\hlUnitOutputDirectory]
Count=1
Item0=DCU
[HistoryLists\hlOutputDirectorry]
Count=1
Item0=Data

View File

@@ -1,18 +0,0 @@
program Test;
uses
Forms,
Main in 'Main.pas' {MainForm},
Monkey in 'Monkey.pas',
ID3v1 in '..\ID3v1\ID3v1.pas',
ID3v2 in '..\ID3v2\ID3v2.pas',
APEtag in '..\APEtag\APEtag.pas';
{$R *.res}
begin
Application.Initialize;
Application.Title := 'Monkey Test';
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.

View File

@@ -1,5 +0,0 @@
TMonkey Delphi Class for analyzing APE files
Sumbitted by Jurgen Faul ( jfaul@gmx.de )
(note: this does not directly use the MAC SDK, so it is not guaranteed to work with future APE files)

View File

@@ -1,127 +0,0 @@
/***************************************************************************************
Analyze - Sample 1
Copyright (C) 2000-2001 by Matthew T. Ashland All Rights Reserved.
Feel free to use this code in any way that you like.
This example opens an APE file and displays some basic information about it. To use it,
just type Sample 1.exe followed by a file name and it'll display information about that
file.
Notes for use in a new project:
-you need to include "MACLib.lib" in the included libraries list
-life will be easier if you set the [MAC SDK]\\Shared directory as an include
directory and an additional library input path in the project settings
-set the runtime library to "Mutlithreaded"
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.
***************************************************************************************/
// includes
#include "all.h"
#include "stdio.h"
#include "maclib.h"
#include "apetag.h"
int main(int argc, char* argv[])
{
///////////////////////////////////////////////////////////////////////////////
// error check the command line parameters
///////////////////////////////////////////////////////////////////////////////
if (argc != 2)
{
printf("~~~Improper Usage~~~\r\n\r\n");
printf("Usage Example: Sample 1.exe 'c:\\1.ape'\r\n\r\n");
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// variable declares
///////////////////////////////////////////////////////////////////////////////
int nRetVal = 0; // generic holder for return values
char cTempBuffer[256]; ZeroMemory(&cTempBuffer[0], 256); // generic buffer for string stuff
char * pFilename = argv[1]; // the file to open
IAPEDecompress * pAPEDecompress = NULL; // APE interface
///////////////////////////////////////////////////////////////////////////////
// open the file and error check
///////////////////////////////////////////////////////////////////////////////
pAPEDecompress = CreateIAPEDecompress(pFilename, &nRetVal);
if (pAPEDecompress == NULL)
{
printf("Error opening APE file. (error code %d)\r\n\r\n", nRetVal);
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// display some information about the file
///////////////////////////////////////////////////////////////////////////////
printf("Displaying information about '%s':\r\n\r\n", pFilename);
// file format information
printf("File Format:\r\n");
printf("\tVersion: %.2f\r\n", float(pAPEDecompress->GetInfo(APE_INFO_FILE_VERSION)) / float(1000));
switch (pAPEDecompress->GetInfo(APE_INFO_COMPRESSION_LEVEL))
{
case COMPRESSION_LEVEL_FAST: printf("\tCompression level: Fast\r\n\r\n"); break;
case COMPRESSION_LEVEL_NORMAL: printf("\tCompression level: Normal\r\n\r\n"); break;
case COMPRESSION_LEVEL_HIGH: printf("\tCompression level: High\r\n\r\n"); break;
case COMPRESSION_LEVEL_EXTRA_HIGH: printf("\tCompression level: Extra High\r\n\r\n"); break;
}
// audio format information
printf("Audio Format:\r\n");
printf("\tSamples per second: %d\r\n", pAPEDecompress->GetInfo(APE_INFO_SAMPLE_RATE));
printf("\tBits per sample: %d\r\n", pAPEDecompress->GetInfo(APE_INFO_BITS_PER_SAMPLE));
printf("\tNumber of channels: %d\r\n", pAPEDecompress->GetInfo(APE_INFO_CHANNELS));
printf("\tPeak level: %d\r\n\r\n", pAPEDecompress->GetInfo(APE_INFO_PEAK_LEVEL));
// size and duration information
printf("Size and Duration:\r\n");
printf("\tLength of file (s): %d\r\n", pAPEDecompress->GetInfo(APE_INFO_LENGTH_MS) / 1000);
printf("\tFile Size (kb): %d\r\n\r\n", pAPEDecompress->GetInfo(APE_INFO_APE_TOTAL_BYTES) / 1024);
// tag information
printf("Tag Information:\r\n");
CAPETag * pAPETag = (CAPETag *) pAPEDecompress->GetInfo(APE_INFO_TAG);
BOOL bHasID3Tag = pAPETag->GetHasID3Tag();
BOOL bHasAPETag = pAPETag->GetHasAPETag();
if (bHasID3Tag || bHasAPETag)
{
// iterate through all the tag fields
BOOL bFirst = TRUE;
CAPETagField * pTagField;
while (pAPETag->GetNextTagField(bFirst, &pTagField))
{
bFirst = FALSE;
// output the tag field properties (don't output huge fields like images, etc.)
if (pTagField->GetFieldValueSize() > 128)
{
printf("\t%s: --- too much data to display ---\r\n", pTagField->GetFieldName());
}
else
{
printf("\t%s: %s\r\n", pTagField->GetFieldName(), pTagField->GetFieldValue());
}
}
}
else
{
printf("\tNot tagged\r\n\r\n");
}
///////////////////////////////////////////////////////////////////////////////
// cleanup (just delete the object
///////////////////////////////////////////////////////////////////////////////
delete pAPEDecompress;
///////////////////////////////////////////////////////////////////////////////
// quit
///////////////////////////////////////////////////////////////////////////////
return 0;
}

View File

@@ -1,102 +0,0 @@
# Microsoft Developer Studio Project File - Name="Sample 1" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=Sample 1 - 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 "Sample 1.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 "Sample 1.mak" CFG="Sample 1 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Sample 1 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "Sample 1 - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Sample 1 - 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 "..\..\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 /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib maclib.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Shared"
!ELSEIF "$(CFG)" == "Sample 1 - 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 "..\..\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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib maclib.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Shared"
!ENDIF
# Begin Target
# Name "Sample 1 - Win32 Release"
# Name "Sample 1 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=".\Sample 1.cpp"
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\Shared\APEInfo.h
# End Source File
# End Group
# End Target
# End Project

View File

@@ -1,121 +0,0 @@
/***************************************************************************************
Compress - Sample 1
Copyright (C) 2000-2001 by Matthew T. Ashland All Rights Reserved.
Feel free to use this code in any way that you like.
This example illustrates using MACLib.lib to create an APE file by encoding some
random data.
The IAPECompress interface fully supports on-the-fly encoding. To use on-
the-fly encoding, be sure to tell the encoder to create the proper WAV header on
decompression. Also, you need to specify the absolute maximum audio bytes that will
get encoded. (trying to encode more than the limit set on Start() will cause failure)
This maximum is used to allocates space in the seek table at the front of the file. Currently,
it takes around 8k per hour of CD music, so it isn't a big deal to allocate more than
needed. You can also specify MAX_AUDIO_BYTES_UNKNOWN to allocate as much space as possible. (2 GB)
Notes for use in a new project:
-you need to include "MACLib.lib" in the included libraries list
-life will be easier if you set the [MAC SDK]\\Shared directory as an include
directory and an additional library input path in the project settings
-set the runtime library to "Mutlithreaded"
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
***************************************************************************************/
// includes
#include <windows.h>
#include <mmreg.h>
#include "stdio.h"
#include "all.h"
#include "MACLib.h"
/***************************************************************************************
Main (the main function)
***************************************************************************************/
int main(int argc, char* argv[])
{
///////////////////////////////////////////////////////////////////////////////
// variable declares
///////////////////////////////////////////////////////////////////////////////
int nAudioBytes = 1048576*10;
const char cOutputFile[MAX_PATH] = "c:\\Noise.ape";
printf("Creating file: %s\n", cOutputFile);
///////////////////////////////////////////////////////////////////////////////
// create and start the encoder
///////////////////////////////////////////////////////////////////////////////
// set the input WAV format
WAVEFORMATEX wfeAudioFormat; FillWaveFormatEx(&wfeAudioFormat, 44100, 16, 2);
// create the encoder interface
IAPECompress * pAPECompress = CreateIAPECompress();
// start the encoder
int nRetVal = pAPECompress->Start(cOutputFile, &wfeAudioFormat, nAudioBytes,
COMPRESSION_LEVEL_HIGH, NULL, CREATE_WAV_HEADER_ON_DECOMPRESSION);
if (nRetVal != 0)
{
SAFE_DELETE(pAPECompress)
printf("Error starting encoder.\n");
return -1;
}
///////////////////////////////////////////////////////////////////////////////
// pump through and feed the encoder audio data (white noise for the sample)
///////////////////////////////////////////////////////////////////////////////
int nAudioBytesLeft = nAudioBytes;
while (nAudioBytesLeft > 0)
{
///////////////////////////////////////////////////////////////////////////////
// NOTE: we're locking the buffer used internally by MAC and copying the data
// directly into it... however, you could also use the AddData(...) command
// to avoid the added complexity of locking and unlocking
// the buffer (but it may be a little slower )
///////////////////////////////////////////////////////////////////////////////
// lock the compression buffer
int nBufferBytesAvailable = 0;
unsigned char * pBuffer = pAPECompress->LockBuffer(&nBufferBytesAvailable);
// fill the buffer with white noise
int nNoiseBytes = min(nBufferBytesAvailable, nAudioBytesLeft);
for (int z = 0; z < nNoiseBytes; z++)
{
pBuffer[z] = rand() % 255;
}
// unlock the buffer and let it get processed
int nRetVal = pAPECompress->UnlockBuffer(nNoiseBytes, TRUE);
if (nRetVal != 0)
{
printf("Error Encoding Frame (error: %d)\n", nRetVal);
break;
}
// update the audio bytes left
nAudioBytesLeft -= nNoiseBytes;
}
///////////////////////////////////////////////////////////////////////////////
// finalize the file (could append a tag, or WAV terminating data)
///////////////////////////////////////////////////////////////////////////////
if (pAPECompress->Finish(NULL, 0, 0) != 0)
{
printf("Error finishing encoder.\n");
}
///////////////////////////////////////////////////////////////////////////////
// clean up and quit
///////////////////////////////////////////////////////////////////////////////
SAFE_DELETE(pAPECompress)
printf("Done.\n");
return 0;
}

View File

@@ -1,106 +0,0 @@
# Microsoft Developer Studio Project File - Name="Sample 1" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=Sample 1 - 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 "Sample 1.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 "Sample 1.mak" CFG="Sample 1 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Sample 1 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "Sample 1 - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Sample 1 - 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 "..\..\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 /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib maclib.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Shared"
!ELSEIF "$(CFG)" == "Sample 1 - 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 "..\..\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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib maclib.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Shared"
!ENDIF
# Begin Target
# Name "Sample 1 - Win32 Release"
# Name "Sample 1 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=".\Sample 1.cpp"
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\Shared\All.h
# End Source File
# Begin Source File
SOURCE=..\..\Shared\MAC.h
# End Source File
# End Group
# End Target
# End Project

View File

@@ -1,217 +0,0 @@
/***************************************************************************************
Compress - Sample 2
Copyright (C) 2000-2002 by Matthew T. Ashland All Rights Reserved.
Feel free to use this code in any way that you like.
This example illustrates dynamic linkage to MACDll.dll to create an APE file using
on-the-fly encoding.
The IAPECompress interface fully supports on-the-fly encoding. To use on-
the-fly encoding, be sure to tell the encoder to create the proper WAV header on
decompression. Also, you need to specify the absolute maximum audio bytes that will
get encoded. (trying to encode more than the limit set on Start() will cause failure)
This maximum is used to allocates space in the seek table at the front of the file. Currently,
it takes around 8k per hour of CD music, so it isn't a big deal to allocate more than
needed. You can also specify MAX_AUDIO_BYTES_UNKNOWN to allocate as much space as possible. (2 GB)
Notes for use in a new project:
-life will be easier if you set the [MAC SDK]\\Shared directory as an include
directory and an additional library input path in the project settings
-set the runtime library to "Mutlithreaded"
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
***************************************************************************************/
// includes
#include <windows.h>
#include <mmreg.h>
#include "stdio.h"
#include "all.h"
#include "MACDll.h"
/***************************************************************************************
MAC_DLL structure (holds function pointers)
***************************************************************************************/
struct MAC_COMPRESS_DLL
{
// APECompress functions
proc_APECompress_Create Create;
proc_APECompress_Destroy Destroy;
proc_APECompress_Start Start;
proc_APECompress_AddData AddData;
proc_APECompress_Finish Finish;
};
/***************************************************************************************
GetFunctions - helper that gets the function addresses for the functions we need
***************************************************************************************/
int GetFunctions(HMODULE hMACDll, MAC_COMPRESS_DLL * pMACDll)
{
// clear
memset(pMACDll, 0, sizeof(MAC_COMPRESS_DLL));
// load the functions
if (hMACDll != NULL)
{
pMACDll->Create = (proc_APECompress_Create) GetProcAddress(hMACDll, "c_APECompress_Create");
pMACDll->Destroy = (proc_APECompress_Destroy) GetProcAddress(hMACDll, "c_APECompress_Destroy");
pMACDll->Start = (proc_APECompress_Start) GetProcAddress(hMACDll, "c_APECompress_Start");
pMACDll->AddData = (proc_APECompress_AddData) GetProcAddress(hMACDll, "c_APECompress_AddData");
pMACDll->Finish = (proc_APECompress_Finish) GetProcAddress(hMACDll, "c_APECompress_Finish");
}
// error check
if ((pMACDll->Create == NULL) ||
(pMACDll->Destroy == NULL) ||
(pMACDll->Start == NULL) ||
(pMACDll->AddData == NULL) ||
(pMACDll->Finish == NULL))
{
return -1;
}
return 0;
}
/***************************************************************************************
Version checks the dll / interface
***************************************************************************************/
int VersionCheckInterface(HMODULE hMACDll)
{
int nRetVal = -1;
proc_GetInterfaceCompatibility GetInterfaceCompatibility = (proc_GetInterfaceCompatibility) GetProcAddress(hMACDll, "GetInterfaceCompatibility");
if (GetInterfaceCompatibility)
{
nRetVal = GetInterfaceCompatibility(MAC_VERSION_NUMBER, TRUE, NULL);
}
return nRetVal;
}
/***************************************************************************************
Fill a WAVEFORMATEX structure
***************************************************************************************/
int FillWaveFormatExStructure(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 0;
}
/***************************************************************************************
Main (the main function)
***************************************************************************************/
int main(int argc, char* argv[])
{
///////////////////////////////////////////////////////////////////////////////
// variable declares
///////////////////////////////////////////////////////////////////////////////
int nTotalAudioBytes = 1048576;
const char cOutputFile[MAX_PATH] = "c:\\Noise.ape";
int nRetVal;
printf("Creating file: %s\n", cOutputFile);
///////////////////////////////////////////////////////////////////////////////
// load MACDll.dll and get the functions
///////////////////////////////////////////////////////////////////////////////
// load the DLL
HMODULE hMACDll = LoadLibrary("MACDll.dll");
if (hMACDll == NULL)
return -1;
// always check the interface version (so we don't crash if something changed)
if (VersionCheckInterface(hMACDll) != 0)
{
FreeLibrary(hMACDll);
return -1;
}
// get the functions
MAC_COMPRESS_DLL MACDll;
if (GetFunctions(hMACDll, &MACDll) != 0)
{
FreeLibrary(hMACDll);
return -1;
}
///////////////////////////////////////////////////////////////////////////////
// create and start the encoder
///////////////////////////////////////////////////////////////////////////////
// set the input WAV format
WAVEFORMATEX wfeAudioFormat; FillWaveFormatExStructure(&wfeAudioFormat, 44100, 16, 2);
// create the encoder interface
APE_COMPRESS_HANDLE hAPECompress = MACDll.Create(&nRetVal);
if (hAPECompress == NULL)
{
printf("Error creating encoder (error code: %d)\r\n", nRetVal);
FreeLibrary(hMACDll);
return -1;
}
// start the encoder
nRetVal = MACDll.Start(hAPECompress, cOutputFile, &wfeAudioFormat, nTotalAudioBytes,
COMPRESSION_LEVEL_HIGH, NULL, CREATE_WAV_HEADER_ON_DECOMPRESSION);
if (nRetVal != 0)
{
printf("Error starting encoder.\n");
MACDll.Destroy(hAPECompress);
FreeLibrary(hMACDll);
return -1;
}
///////////////////////////////////////////////////////////////////////////////
// pump through and feed the encoder audio data (white noise for the sample)
///////////////////////////////////////////////////////////////////////////////
int nAudioBytesLeft = nTotalAudioBytes;
unsigned char cBuffer[1024];
while (nAudioBytesLeft > 0)
{
// fill the buffer with white noise
for (int z = 0; z < 1024; z++)
cBuffer[z] = rand() % 255;
// give the data to MAC
// (we can safely add any amount, but of course larger chunks take longer to process)
int nBytesToAdd = min(1024, nAudioBytesLeft);
nRetVal = MACDll.AddData(hAPECompress, &cBuffer[0], nBytesToAdd);
if (nRetVal != ERROR_SUCCESS)
printf("Encoding error (error code: %d)\r\n", nRetVal);
// update the audio bytes left
nAudioBytesLeft -= nBytesToAdd;
}
///////////////////////////////////////////////////////////////////////////////
// finalize the file (could append a tag, or WAV terminating data)
///////////////////////////////////////////////////////////////////////////////
if (MACDll.Finish(hAPECompress, NULL, 0, 0) != 0)
{
printf("Error finishing encoder.\n");
}
///////////////////////////////////////////////////////////////////////////////
// clean up and quit
///////////////////////////////////////////////////////////////////////////////
MACDll.Destroy(hAPECompress);
FreeLibrary(hMACDll);
printf("Done.\n");
return 0;
}

View File

@@ -1,100 +0,0 @@
# Microsoft Developer Studio Project File - Name="Sample 2" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=Sample 2 - 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 "Sample 2.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 "Sample 2.mak" CFG="Sample 2 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Sample 2 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "Sample 2 - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Sample 2 - 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 "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /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 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
!ELSEIF "$(CFG)" == "Sample 2 - 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 "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /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 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
!ENDIF
# Begin Target
# Name "Sample 2 - Win32 Release"
# Name "Sample 2 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=".\Sample 2.cpp"
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -1,92 +0,0 @@
/***************************************************************************************
Decompress - Sample 1
Copyright (C) 2000-2001 by Matthew T. Ashland All Rights Reserved.
Feel free to use this code in any way that you like.
This example illustrates using MACDLib.lib and the simple IAPESimple class to verify
or decompress a file. (verify and decompress work the same, except that verify doesn't
have an output file) Also, shows how to use a callback to display the progress.
General Notes:
-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.
Notes for use in a new project:
-you need to include "MACLib.lib" in the included libraries list
-life will be easier if you set the [MAC SDK]\\Shared directory as an include
directory and an additional library input path in the project settings
-set the runtime library to "Mutlithreaded"
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.
***************************************************************************************/
// includes
#include <windows.h>
#include "stdio.h"
#include "all.h"
#include "maclib.h"
// global variables (evil... but alright for a simple sample)
unsigned __int32 g_nInitialTickCount;
/***************************************************************************************
Progress callback
***************************************************************************************/
void CALLBACK ProgressCallback(int nPercentageDone)
{
double dProgress = double(nPercentageDone) / 1000;
double dElapsedMS = (GetTickCount() - g_nInitialTickCount);
double dSecondsRemaining = (((dElapsedMS * 100) / dProgress) - dElapsedMS) / 1000;
printf("Progress: %.1f%% (%.1f seconds remaining) \r", dProgress, dSecondsRemaining);
}
/***************************************************************************************
Main (the main function)
***************************************************************************************/
int main(int argc, char* argv[])
{
///////////////////////////////////////////////////////////////////////////////
// error check the command line parameters
///////////////////////////////////////////////////////////////////////////////
if (argc != 2)
{
printf("~~~Improper Usage~~~\n\n");
printf("Usage Example: Sample 1.exe \"c:\\1.ape\"\n\n");
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// variable declares
///////////////////////////////////////////////////////////////////////////////
int nPercentageDone = 0; //the percentage done... continually updated by the decoder
int nKillFlag = 0; //the kill flag for controlling the decoder
int nRetVal = 0; //generic holder for return values
char * pFilename = argv[1]; //the file to open
///////////////////////////////////////////////////////////////////////////////
// attempt to verify the file
///////////////////////////////////////////////////////////////////////////////
// set the start time and display the starting message
g_nInitialTickCount = GetTickCount();
printf("Verifying '%s'...\n", pFilename);
// do the verify (call unmac.dll)
nRetVal = VerifyFile(pFilename, &nPercentageDone, ProgressCallback, &nKillFlag);
// process the return value
if (nRetVal == 0)
printf("\nPassed...\n");
else
printf("\nFailed (error: %d)\n", nRetVal);
///////////////////////////////////////////////////////////////////////////////
// quit
///////////////////////////////////////////////////////////////////////////////
return 0;
}

View File

@@ -1,110 +0,0 @@
# Microsoft Developer Studio Project File - Name="Sample 1" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=Sample 1 - 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 "Sample 1.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 "Sample 1.mak" CFG="Sample 1 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Sample 1 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "Sample 1 - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Sample 1 - 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 "..\..\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 /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib maclib.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Shared"
!ELSEIF "$(CFG)" == "Sample 1 - 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 "..\..\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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib maclib.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Shared"
!ENDIF
# Begin Target
# Name "Sample 1 - Win32 Release"
# Name "Sample 1 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=".\Sample 1.cpp"
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\Shared\All.h
# End Source File
# Begin Source File
SOURCE=..\..\Shared\APEInfo.h
# End Source File
# Begin Source File
SOURCE=..\..\Shared\UnMAC.h
# End Source File
# End Group
# End Target
# End Project

View File

@@ -1,460 +0,0 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="Sample 1"
ProjectGUID="{E0AFAD4C-5628-44F3-A2B6-46BA966DC595}"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/Sample 1.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\Shared"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release/Sample 1.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="maclib.lib"
OutputFile=".\Release/Sample 1.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\Shared"
ProgramDatabaseFile=".\Release/Sample 1.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/Sample 1.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Debug/Sample 1.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\Shared"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\Debug/Sample 1.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="maclib.lib"
OutputFile=".\Debug/Sample 1.exe"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\Shared"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/Sample 1.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/Sample 1.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
TypeLibraryName=".\Release/Sample 1.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\Shared"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release/Sample 1.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="maclib.lib"
OutputFile=".\Release/Sample 1.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\Shared"
ProgramDatabaseFile=".\Release/Sample 1.pdb"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/Sample 1.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
TypeLibraryName=".\Debug/Sample 1.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\Shared"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\Debug/Sample 1.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="maclib.lib"
OutputFile=".\Debug/Sample 1.exe"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\Source\MacLib\x64\Debug"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/Sample 1.pdb"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/Sample 1.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="Sample 1.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="..\..\Shared\All.h"
>
</File>
<File
RelativePath="..\..\Shared\APEInfo.h"
>
</File>
<File
RelativePath="..\..\Shared\UnMAC.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,117 +0,0 @@
/***************************************************************************************
Decompress - Sample 2
Copyright (C) 2000-2001 by Matthew T. Ashland All Rights Reserved.
Feel free to use this code in any way that you like.
This example illustrates using MACLib.lib to do decoding and seeking of an APE file.
The library manages all seeking and buffering, so you simply seek
to a location and ask for the amount of data required. (Seek() and GetData())
GetData will return the amount requested unless you're at the end of the file. (in
which case it returns everything up to the end) It's typically a good idea to check
the return value of each decode. A value other than ERROR_SUCCESS (0) means errors
were encountered. In these cases, the decoder will do the best job it can to keep
returning valid data. (corrupt data will be converted to silence)
General Notes:
-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.
Notes for use in a new project:
-you need to include "MACLib.lib" in the included libraries list
-life will be easier if you set the [MAC SDK]\\Shared directory as an include
directory and an additional library input path in the project settings
-set the runtime library to "Mutlithreaded"
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
***************************************************************************************/
// includes
#include <windows.h>
#include "stdio.h"
#include "all.h"
#include "maclib.h"
/***************************************************************************************
Main (the main function)
***************************************************************************************/
int main(int argc, char* argv[])
{
///////////////////////////////////////////////////////////////////////////////
// error check the command line parameters
///////////////////////////////////////////////////////////////////////////////
if (argc != 2)
{
printf("~~~Improper Usage~~~\r\n\r\n");
printf("Usage Example: Sample 2.exe \"c:\\1.ape\"\r\n\r\n");
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// variable declares
///////////////////////////////////////////////////////////////////////////////
int nPercentageDone = 0; // the percentage done... continually updated by the decoder
int nKillFlag = 0; // the kill flag for controlling the decoder
int nRetVal = 0; // generic holder for return values
char * pFilename = argv[1]; // the file to open
///////////////////////////////////////////////////////////////////////////////
// open the APE file
///////////////////////////////////////////////////////////////////////////////
IAPEDecompress * pAPEDecompress = CreateIAPEDecompress(L"E:\\Music\\Steve Hackett\\Steve Hackett - Wild Orchids (2006)\\Steve Hackett - Wild Orchids (2006).ape" , &nRetVal);
if (pAPEDecompress == NULL)
{
printf("Error opening APE file (error code: %d)\r\n", nRetVal);
return -1;
}
///////////////////////////////////////////////////////////////////////////////
// allocate space for the raw decompressed data
///////////////////////////////////////////////////////////////////////////////
char * pRawData = new char [1024 * pAPEDecompress->GetInfo(APE_INFO_BLOCK_ALIGN)];
if (pRawData == NULL) { return -1; }
///////////////////////////////////////////////////////////////////////////////
// ask for data at a a few random locations and display the sum of 1024 blocks
///////////////////////////////////////////////////////////////////////////////
for (int z = 0; z < 160; z++)
{
// figure a random location in the file and seek to it
int nRandomBlock = rand() % (pAPEDecompress->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS) - 1024);
nRetVal = pAPEDecompress->Seek(nRandomBlock);
if (nRetVal != 0) {
printf("Seek error (%d)\r\n", nRetVal);
return -1;
}
// decompress 1024 blocks from that location
int nBlocksRetrieved;
nRetVal = pAPEDecompress->GetData(pRawData, 1024, &nBlocksRetrieved);
if (nRetVal != ERROR_SUCCESS)
{
printf("Decoding error (%d)\r\n", nRetVal);
}
// figure the sum of the decoded data
int nBytesRetrieved = nBlocksRetrieved * pAPEDecompress->GetInfo(APE_INFO_BLOCK_ALIGN);
int nSum = 0;
for (int x = 0; x < nBytesRetrieved; x++)
{
nSum += pRawData[x];
}
// display the sum
printf("Block / Sum = %.4d / %d\r\n", nRandomBlock, nSum);
}
///////////////////////////////////////////////////////////////////////////////
// clean-up and quit
///////////////////////////////////////////////////////////////////////////////
delete pAPEDecompress;
return 0;
}

View File

@@ -1,114 +0,0 @@
# Microsoft Developer Studio Project File - Name="Sample 2" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=Sample 2 - 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 "Sample 2.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 "Sample 2.mak" CFG="Sample 2 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Sample 2 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "Sample 2 - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Sample 2 - 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 "..\..\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 /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib maclib.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\Shared"
!ELSEIF "$(CFG)" == "Sample 2 - 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 "..\..\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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib maclib.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Shared"
!ENDIF
# Begin Target
# Name "Sample 2 - Win32 Release"
# Name "Sample 2 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=".\Sample 2.cpp"
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\Shared\All.h
# End Source File
# Begin Source File
SOURCE=..\..\Shared\APEInfo.h
# End Source File
# Begin Source File
SOURCE=..\..\Shared\MACDll.h
# End Source File
# Begin Source File
SOURCE=..\..\Shared\UnMAC.h
# End Source File
# End Group
# End Target
# End Project

View File

@@ -1,461 +0,0 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="Sample 2"
ProjectGUID="{E7B72EF2-1C5A-45EF-BA35-6094BCF560B1}"
RootNamespace="Sample 2"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Debug/Sample 2.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\Shared"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="2"
PrecompiledHeaderFile=".\Debug/Sample 2.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="maclib.lib"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/Sample 2.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/Sample 2.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
TypeLibraryName=".\Debug/Sample 2.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\Shared"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\Debug/Sample 2.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="maclib.lib"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/Sample 2.pdb"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/Sample 2.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/Sample 2.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\Shared"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release/Sample 2.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="maclib.lib"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
ProgramDatabaseFile=".\Release/Sample 2.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/Sample 2.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
TypeLibraryName=".\Release/Sample 2.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\Shared"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release/Sample 2.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="maclib.lib"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\..\bin\$(PlatformName)\$(ConfigurationName)"
ProgramDatabaseFile=".\Release/Sample 2.pdb"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/Sample 2.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="Sample 2.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="..\..\Shared\All.h"
>
</File>
<File
RelativePath="..\..\Shared\APEInfo.h"
>
</File>
<File
RelativePath="..\..\Shared\MACDll.h"
>
</File>
<File
RelativePath="..\..\Shared\UnMAC.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,190 +0,0 @@
/***************************************************************************************
Decompress - Sample 3
Copyright (C) 2000-2001 by Matthew T. Ashland All Rights Reserved.
Feel free to use this code in any way that you like.
This example illustrates dynamic linkage to MACDll.dll to decompress a whole file
and display a simple checksum. (see Sample 1 and Sample 2 for more info)
General Notes:
-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.
Notes for use in a new project:
-life will be easier if you set the [MAC SDK]\\Shared directory as an include
directory and an additional library input path in the project settings
-set the runtime library to "Mutlithreaded"
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
***************************************************************************************/
// includes
#include <windows.h>
#include "stdio.h"
#include "MACDll.h"
/***************************************************************************************
MAC_DLL structure (holds function pointers)
***************************************************************************************/
struct MAC_DLL
{
// APEDecompress functions
proc_APEDecompress_Create Create;
proc_APEDecompress_Destroy Destroy;
proc_APEDecompress_GetData GetData;
proc_APEDecompress_Seek Seek;
proc_APEDecompress_GetInfo GetInfo;
};
/***************************************************************************************
GetFunctions - helper that gets the function addresses for the functions we need
***************************************************************************************/
int GetFunctions(HMODULE hMACDll, MAC_DLL * pMACDll)
{
// clear
memset(pMACDll, 0, sizeof(MAC_DLL));
// load the functions
if (hMACDll != NULL)
{
pMACDll->Create = (proc_APEDecompress_Create) GetProcAddress(hMACDll, "c_APEDecompress_Create");
pMACDll->Destroy = (proc_APEDecompress_Destroy) GetProcAddress(hMACDll, "c_APEDecompress_Destroy");
pMACDll->GetData = (proc_APEDecompress_GetData) GetProcAddress(hMACDll, "c_APEDecompress_GetData");
pMACDll->Seek = (proc_APEDecompress_Seek) GetProcAddress(hMACDll, "c_APEDecompress_Seek");
pMACDll->GetInfo = (proc_APEDecompress_GetInfo) GetProcAddress(hMACDll, "c_APEDecompress_GetInfo");
}
// error check
if ((pMACDll->Create == NULL) ||
(pMACDll->Destroy == NULL) ||
(pMACDll->GetData == NULL) ||
(pMACDll->Seek == NULL) ||
(pMACDll->GetInfo == NULL))
{
return -1;
}
return 0;
}
/***************************************************************************************
Version checks the dll / interface
***************************************************************************************/
int VersionCheckInterface(HMODULE hMACDll)
{
int nRetVal = -1;
proc_GetInterfaceCompatibility GetInterfaceCompatibility = (proc_GetInterfaceCompatibility) GetProcAddress(hMACDll, "GetInterfaceCompatibility");
if (GetInterfaceCompatibility)
{
nRetVal = GetInterfaceCompatibility(MAC_VERSION_NUMBER, TRUE, NULL);
}
return nRetVal;
}
/***************************************************************************************
Main (the main function)
***************************************************************************************/
int main(int argc, char* argv[])
{
///////////////////////////////////////////////////////////////////////////////
// error check the command line parameters
///////////////////////////////////////////////////////////////////////////////
if (argc != 2)
{
printf("~~~Improper Usage~~~\r\n\r\n");
printf("Usage Example: Sample 3.exe \"c:\\1.ape\"\r\n\r\n");
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// variable declares
///////////////////////////////////////////////////////////////////////////////
int nRetVal = 0; // generic holder for return values
char * pFilename = argv[1]; // the file to open
///////////////////////////////////////////////////////////////////////////////
// load MACDll.dll and get the functions
///////////////////////////////////////////////////////////////////////////////
// load the DLL
HMODULE hMACDll = LoadLibrary("MACDll.dll");
if (hMACDll == NULL)
return -1;
// always check the interface version (so we don't crash if something changed)
if (VersionCheckInterface(hMACDll) != 0)
{
FreeLibrary(hMACDll);
return -1;
}
// get the functions
MAC_DLL MACDll;
if (GetFunctions(hMACDll, &MACDll) != 0)
{
FreeLibrary(hMACDll);
return -1;
}
///////////////////////////////////////////////////////////////////////////////
// create the APEDecompress object for the file
///////////////////////////////////////////////////////////////////////////////
APE_DECOMPRESS_HANDLE hAPEDecompress = MACDll.Create(pFilename, &nRetVal);
if (hAPEDecompress == NULL)
{
printf("Error opening APE file (error code: %d)\r\n", nRetVal);
FreeLibrary(hMACDll);
return -1;
}
///////////////////////////////////////////////////////////////////////////////
// calculate a byte-level checksum of the whole file
///////////////////////////////////////////////////////////////////////////////
// make a buffer to hold 1024 blocks of audio data
int nBlockAlign = MACDll.GetInfo(hAPEDecompress, APE_INFO_BLOCK_ALIGN, 0, 0);
unsigned char * pBuffer = new unsigned char [1024 * nBlockAlign];
// loop through the whole file
int nTotalBlocks = MACDll.GetInfo(hAPEDecompress, APE_DECOMPRESS_TOTAL_BLOCKS, 0, 0);
int nBlocksRetrieved = 1;
int nTotalBlocksRetrieved = 0;
unsigned int nChecksum = 0;
while (nBlocksRetrieved > 0)
{
// try to decompress 1024 blocks
nRetVal = MACDll.GetData(hAPEDecompress, (char *) pBuffer, 1024, &nBlocksRetrieved);
if (nRetVal != 0)
printf("Decompression error (continuing with checksum, but file is probably corrupt)\r\n");
// calculate the sum (byte-by-byte)
for (int z = 0; z < (nBlockAlign * nBlocksRetrieved); z++)
{
nChecksum += abs(int(pBuffer[z]));
}
nTotalBlocksRetrieved += nBlocksRetrieved;
// output the progress
printf("Progress: %.1f%% \r", (float(nTotalBlocksRetrieved) * float(100)) / float(max(nTotalBlocks, 1.0)));
}
delete [] pBuffer;
// output the result
printf("Progress: done. \r\n");
printf("Stupid-style Checksum: 0x%X\r\n", nChecksum);
///////////////////////////////////////////////////////////////////////////////
// clean-up and quit
///////////////////////////////////////////////////////////////////////////////
MACDll.Destroy(hAPEDecompress);
FreeLibrary(hMACDll);
return 0;
}

View File

@@ -1,115 +0,0 @@
# Microsoft Developer Studio Project File - Name="Sample 3" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=Sample 3 - 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 "Sample 3.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 "Sample 3.mak" CFG="Sample 3 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Sample 3 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "Sample 3 - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Sample 3 - 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" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\Shared\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX /Yc /Yu
# 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 /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "Sample 3 - 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" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\Shared\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
# SUBTRACT CPP /YX /Yc /Yu
# 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 kernel32.lib user32.lib gdi32.lib maclib.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\Shared\\"
!ENDIF
# Begin Target
# Name "Sample 3 - Win32 Release"
# Name "Sample 3 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=".\Sample 3.cpp"
!IF "$(CFG)" == "Sample 3 - Win32 Release"
# ADD CPP /MT
!ELSEIF "$(CFG)" == "Sample 3 - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -1,451 +0,0 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="Sample 3"
ProjectGUID="{9D410FD0-DFBB-4AA1-9E80-3DA181F88AC4}"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Debug/Sample 3.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\Shared\"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\Debug/Sample 3.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="maclib.lib"
OutputFile=".\Debug/Sample 3.exe"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\Shared\"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/Sample 3.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/Sample 3.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/Sample 3.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\Shared\"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release/Sample 3.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib"
OutputFile=".\Release/Sample 3.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
ProgramDatabaseFile=".\Release/Sample 3.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/Sample 3.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
TypeLibraryName=".\Debug/Sample 3.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\Shared\"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\Debug/Sample 3.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="maclib.lib"
OutputFile=".\Debug/Sample 3.exe"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\Source\MacLib\X64\Debug"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/Sample 3.pdb"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/Sample 3.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
TypeLibraryName=".\Release/Sample 3.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\Shared\"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release/Sample 3.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib"
OutputFile=".\Release/Sample 3.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
ProgramDatabaseFile=".\Release/Sample 3.pdb"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/Sample 3.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="Sample 3.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,293 +0,0 @@
#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

View File

@@ -1,235 +0,0 @@
#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
#define ENABLE_ASSEMBLY
#endif
#define NO_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 NO_IO_HEADER_FILE "WinFileIO.h"
#define NO_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

View File

@@ -1,49 +0,0 @@
#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

View File

@@ -1,99 +0,0 @@
/*****************************************************************************************
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

View File

@@ -1,452 +0,0 @@
/*****************************************************************************************
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)
//////////////////////////////////////////////////////////////////////////////////////////////
#ifdef IO_CLASS_NAME
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;
#endif
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

View File

@@ -1,89 +0,0 @@
#ifndef APE_SMARTPTR_H
#define APE_SMARTPTR_H
// disable the operator -> on UDT warning
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4284)
#endif
/*************************************************************************************************
CSmartPtr - a simple smart pointer class that can automatically initialize and free memory
note: (doesn't do garbage collection / reference counting because of the many pitfalls)
*************************************************************************************************/
template <class TYPE> class CSmartPtr
{
public:
TYPE * m_pObject;
BOOL m_bArray;
BOOL m_bDelete;
CSmartPtr()
{
m_bDelete = TRUE;
m_pObject = NULL;
}
CSmartPtr(TYPE * a_pObject, BOOL a_bArray = FALSE, BOOL a_bDelete = TRUE)
{
m_bDelete = TRUE;
m_pObject = NULL;
Assign(a_pObject, a_bArray, a_bDelete);
}
~CSmartPtr()
{
Delete();
}
void Assign(TYPE * a_pObject, BOOL a_bArray = FALSE, BOOL a_bDelete = TRUE)
{
Delete();
m_bDelete = a_bDelete;
m_bArray = a_bArray;
m_pObject = a_pObject;
}
void Delete()
{
if (m_bDelete && m_pObject)
{
if (m_bArray)
delete [] m_pObject;
else
delete m_pObject;
m_pObject = NULL;
}
}
void SetDelete(const BOOL a_bDelete)
{
m_bDelete = a_bDelete;
}
__inline TYPE * GetPtr() const
{
return m_pObject;
}
__inline operator TYPE * () const
{
return m_pObject;
}
__inline TYPE * operator ->() const
{
return m_pObject;
}
// declare assignment, but don't implement (compiler error if we try to use)
// that way we can't carelessly mix smart pointers and regular pointers
__inline void * operator =(void *) const;
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif _MSC_VER
#endif // #ifndef APE_SMARTPTR_H

View File

@@ -1,190 +0,0 @@
/***************************************************************************************
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;
}

View File

@@ -1,114 +0,0 @@
# 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

View File

@@ -1,185 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="Console"
ProjectGUID="{CC3FC224-9557-45F3-9B8F-C29AE1DBCE82}"
SccProjectName="&quot;$/Monkey&apos;s Audio/Console&quot;, 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>

View File

@@ -1,103 +0,0 @@
// 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

View File

@@ -1,15 +0,0 @@
//{{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

View File

@@ -1,25 +0,0 @@
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

View File

@@ -1,79 +0,0 @@
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.

View File

@@ -1,48 +0,0 @@
<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.&nbsp;</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>&nbsp;</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.&nbsp; 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.&nbsp; 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">&nbsp;</p>
<p align="center" style="margin:0in;margin-bottom:.0001pt;text-align:center">&nbsp;</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">&nbsp;</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>

View File

@@ -1,233 +0,0 @@
#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();
}

View File

@@ -1,38 +0,0 @@
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

View File

@@ -1,160 +0,0 @@
# 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

View File

@@ -1,99 +0,0 @@
/*****************************************************************************************
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

View File

@@ -1,261 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="MACDll"
ProjectGUID="{F7EE0746-C0AD-4045-B8B9-1CB2AFDFCB96}"
SccProjectName="&quot;$/Monkey&apos;s Audio/MACDll&quot;, 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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,226 +0,0 @@
// 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

View File

@@ -1,20 +0,0 @@
//{{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

View File

@@ -1,250 +0,0 @@
#include "All.h"
#include "APECompress.h"
#ifdef IO_CLASS_NAME
#include IO_HEADER_FILE
#endif
#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)
}
}
#ifdef IO_CLASS_NAME
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;
}
#endif
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;
}

View File

@@ -1,58 +0,0 @@
#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
#ifdef IO_CLASS_NAME
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);
#endif
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

View File

@@ -1,126 +0,0 @@
#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;
}

View File

@@ -1,41 +0,0 @@
#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

View File

@@ -1,218 +0,0 @@
#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;
}

View File

@@ -1,43 +0,0 @@
#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

View File

@@ -1,479 +0,0 @@
#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;
}

View File

@@ -1,72 +0,0 @@
#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

View File

@@ -1,280 +0,0 @@
#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;
}

View File

@@ -1,57 +0,0 @@
#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

View File

@@ -1,374 +0,0 @@
/*****************************************************************************************
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
*****************************************************************************************/
#ifdef IO_CLASS_NAME
CAPEInfo::CAPEInfo(int * pErrorCode, const wchar_t * pFilename, CAPETag * pTag, bool fReadOnly)
{
*pErrorCode = ERROR_SUCCESS;
CloseFile();
// open the file
m_spIO.Assign(new IO_CLASS_NAME);
if (m_spIO->Open(pFilename, fReadOnly) != 0)
{
CloseFile();
*pErrorCode = ERROR_INVALID_INPUT_FILE;
return;
}
// get the file information
if (GetFileInformation(TRUE) != 0)
{
CloseFile();
*pErrorCode = ERROR_INVALID_INPUT_FILE;
return;
}
#ifndef NO_TAG
// 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);
}
#endif
}
#endif
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;
}
#ifndef NO_TAG
// 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, FALSE));
else
m_spAPETag.Assign(pTag);
#endif
}
/*****************************************************************************************
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();
#ifndef NO_TAG
m_spAPETag.Delete();
#endif
// 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;
}
#ifndef NO_TAG
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;
}
#endif
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;
#ifndef NO_TAG
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;
}
#endif
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;
}
#ifndef NO_TAG
case APE_INFO_TAG:
nRetVal = (int) m_spAPETag.GetPtr();
break;
#endif
case APE_INTERNAL_INFO:
nRetVal = (int) &m_APEFileInfo;
break;
}
return nRetVal;
}

View File

@@ -1,106 +0,0 @@
/*****************************************************************************************
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"
#ifndef NO_TAG
#include "APETag.h"
#else
#define CAPETag void
#endif
#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, bool fReadOnly = 0);
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;
#ifndef NO_TAG
CSmartPtr<CAPETag> m_spAPETag;
#endif
APE_FILE_INFO m_APEFileInfo;
};
#endif // #ifndef APE_APEINFO_H

View File

@@ -1,120 +0,0 @@
#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;
}

View File

@@ -1,30 +0,0 @@
#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

View File

@@ -1,430 +0,0 @@
#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
#ifndef NO_TAG
int nTagBytes = GET_TAG(spAPEDecompress)->GetTagBytes();
#else
int nTagBytes = 0;
#endif
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;
}

View File

@@ -1,745 +0,0 @@
#include "All.h"
#include "ID3Genres.h"
#ifndef NO_TAG
#include "APETag.h"
#endif
#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());
}

View File

@@ -1,293 +0,0 @@
#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

View File

@@ -1,12 +0,0 @@
#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

View File

@@ -1,181 +0,0 @@
%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

View File

@@ -1,194 +0,0 @@
%include "Tools64.inc"
segment_code
%imacro AdaptAddAligned 1
AdaptAddLoop0%1:
movdqa xmm0, [rcx]
movdqa xmm1, [rdx]
%1 xmm0, xmm1
movdqa [rcx], xmm0
movdqa xmm2, [rcx + 16]
movdqa xmm3, [rdx + 16]
%1 xmm2, xmm3
movdqa [rcx + 16], xmm2
add rcx, byte 32
add rdx, byte 32
dec r9d
jnz AdaptAddLoop0%1
emms
ret
%endmacro
%imacro AdaptAddUnaligned 1
mov r8d, r9d
and r8d, 1
shr r9d, 1
cmp r9d, byte 0
je short AdaptAddLoopULast%1
AdaptAddLoopU%1:
movdqa xmm0, [rcx]
lddqu xmm1, [rdx]
%1 xmm0, xmm1
movdqa [rcx], xmm0
movdqa xmm2, [rcx + 16]
lddqu xmm3, [rdx + 16]
%1 xmm2, xmm3
movdqa [rcx + 16], xmm2
movdqa xmm4, [rcx+32]
lddqu xmm5, [rdx+32]
%1 xmm4, xmm5
movdqa [rcx+32], xmm4
movdqa xmm6, [rcx + 48]
lddqu xmm7, [rdx + 48]
%1 xmm6, xmm7
movdqa [rcx + 48], xmm6
add rcx, byte 64
add rdx, byte 64
dec r9d
jnz AdaptAddLoopU%1
AdaptAddLoopULast%1:
cmp r8d, byte 0
je short AdaptAddLoopUEnd%1
movdqa xmm0, [rcx]
lddqu xmm1, [rdx]
%1 xmm0, xmm1
movdqa [rcx], xmm0
movdqa xmm2, [rcx + 16]
lddqu xmm3, [rdx + 16]
%1 xmm2, xmm3
movdqa [rcx + 16], xmm2
AdaptAddLoopUEnd%1:
emms
ret
%endmacro
;
; 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
nop
nop
nop
nop
nop
proc Adapt
shr r9d, 4
cmp r8d, byte 0 ; nDirection
jle AdaptSub1
AdaptAddUnaligned paddw
align 16
nop
nop
nop
nop
nop
nop
nop
AdaptSub1: je AdaptDone1
AdaptAddUnaligned psubw
AdaptDone1:
endproc
;
; int CalculateDotProduct ( const short* pA, const short* pB, int nOrder )
;
align 16
nop
nop
nop
nop
nop
proc CalculateDotProduct
shr r8d, 4
pxor xmm7, xmm7
mov r9d, r8d
and r9d, 1
shr r8d, 1
cmp r8d, byte 0
je DotNonEven
LoopDotEven:
lddqu xmm0, [rcx] ;pA
pmaddwd xmm0, [rdx] ;pB
paddd xmm7, xmm0
lddqu xmm1, [rcx + 16]
pmaddwd xmm1, [rdx + 16]
paddd xmm7, xmm1
lddqu xmm2, [rcx + 32]
pmaddwd xmm2, [rdx + 32]
paddd xmm7, xmm2
lddqu xmm3, [rcx + 48]
pmaddwd xmm3, [rdx + 48]
add rcx, byte 64
add rdx, byte 64
paddd xmm7, xmm3
dec r8d
jnz short LoopDotEven
DotNonEven:
cmp r9d, byte 0
je DotFinal
lddqu xmm0, [rcx] ;pA
pmaddwd xmm0, [rdx] ;pB
paddd xmm7, xmm0
lddqu xmm1, [rcx + 16]
pmaddwd xmm1, [rdx + 16]
paddd xmm7, xmm1
DotFinal:
movdqa xmm6, xmm7
psrldq xmm6, 8
paddd xmm7, xmm6
movshdup xmm6, xmm7
paddd xmm7, xmm6
movd eax, xmm7
emms
endproc
;
; BOOL GetMMXAvailable ( void );
;
proc GetMMXAvailable
push rbx
push rcx
push rdx
mov eax,1
CPUID
test ecx, 1 ; actually, testing for SSE3
setnz al
and eax, byte 1
pop rdx
pop rcx
pop rbx
endproc

View File

@@ -1,117 +0,0 @@
;
; (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

Some files were not shown because too many files have changed in this diff Show More