move to new cspot

This commit is contained in:
philippe44
2023-03-25 16:48:41 -07:00
parent c712b78931
commit 008c36facf
2983 changed files with 465270 additions and 13569 deletions

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "alacConvert", "alacConvert.vcproj", "{B9B08911-AF77-447E-A4DD-692AFFA0E346}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Debug|Win32.ActiveCfg = Debug|Win32
{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Debug|Win32.Build.0 = Debug|Win32
{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Release|Win32.ActiveCfg = Release|Win32
{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,379 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="alacConvert"
ProjectGUID="{B9B08911-AF77-447E-A4DD-692AFFA0E346}"
RootNamespace="alacConvert"
Keyword="ManagedCProj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
ManagedExtensions="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\codec;.\"
PreprocessorDefinitions="WIN32;_DEBUG;TARGET_OS_WIN32"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(NoInherit)"
LinkIncremental="2"
GenerateDebugInformation="true"
AssemblyDebug="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
ManagedExtensions="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG"
RuntimeLibrary="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(NoInherit)"
LinkIncremental="1"
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\codec\ag_dec.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\ag_enc.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\ALACBitUtilities.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\ALACDecoder.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\ALACEncoder.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
/>
</FileConfiguration>
</File>
<File
RelativePath="CAFFileALAC.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\dp_dec.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\dp_enc.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\EndianPortable.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="main.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\matrix_dec.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\matrix_enc.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\codec\aglib.h"
>
</File>
<File
RelativePath="..\codec\ALACAudioTypes.h"
>
</File>
<File
RelativePath="..\codec\ALACBitUtilities.h"
>
</File>
<File
RelativePath="..\codec\ALACDecoder.h"
>
</File>
<File
RelativePath="..\codec\ALACEncoder.h"
>
</File>
<File
RelativePath="CAFFileALAC.h"
>
</File>
<File
RelativePath="..\codec\dplib.h"
>
</File>
<File
RelativePath="..\codec\EndianPortable.h"
>
</File>
<File
RelativePath="..\codec\matrixlib.h"
>
</File>
<File
RelativePath=".\stdint.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,362 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 42;
objects = {
/* Begin PBXBuildFile section */
071120831405C91B007FF1B0 /* ALACBitUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 071120811405C91B007FF1B0 /* ALACBitUtilities.c */; };
074B586A1405B97E0060A703 /* ag_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58611405B97E0060A703 /* ag_dec.c */; };
074B586B1405B97E0060A703 /* ag_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58621405B97E0060A703 /* ag_enc.c */; };
074B586D1405B97E0060A703 /* dp_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58641405B97E0060A703 /* dp_dec.c */; };
074B586E1405B97E0060A703 /* dp_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58651405B97E0060A703 /* dp_enc.c */; };
074B58791405B98B0060A703 /* matrix_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58751405B98B0060A703 /* matrix_dec.c */; };
074B587A1405B98B0060A703 /* matrix_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58761405B98B0060A703 /* matrix_enc.c */; };
075CBE1E142184CB0089DFF0 /* CAFFileALAC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 075CBE1D142184CB0089DFF0 /* CAFFileALAC.cpp */; };
07B7F449141999F800035453 /* ALACDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07B7F445141999F800035453 /* ALACDecoder.cpp */; };
07B7F44B141999F800035453 /* ALACEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07B7F447141999F800035453 /* ALACEncoder.cpp */; };
07E06D00142968F2002489A3 /* EndianPortable.c in Sources */ = {isa = PBXBuildFile; fileRef = 07E06CFE142968F2002489A3 /* EndianPortable.c */; };
A98FBFAD06EBB5AB00E7B080 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A98FBFAC06EBB5AB00E7B080 /* main.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
8DD76FAF0486AB0100D96B5E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
071120811405C91B007FF1B0 /* ALACBitUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ALACBitUtilities.c; sourceTree = "<group>"; };
071120821405C91B007FF1B0 /* ALACBitUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACBitUtilities.h; sourceTree = "<group>"; };
074B58611405B97E0060A703 /* ag_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ag_dec.c; sourceTree = "<group>"; };
074B58621405B97E0060A703 /* ag_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ag_enc.c; sourceTree = "<group>"; };
074B58631405B97E0060A703 /* aglib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aglib.h; sourceTree = "<group>"; };
074B58641405B97E0060A703 /* dp_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dp_dec.c; sourceTree = "<group>"; };
074B58651405B97E0060A703 /* dp_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dp_enc.c; sourceTree = "<group>"; };
074B58741405B98B0060A703 /* dplib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dplib.h; sourceTree = "<group>"; };
074B58751405B98B0060A703 /* matrix_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = matrix_dec.c; sourceTree = "<group>"; };
074B58761405B98B0060A703 /* matrix_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = matrix_enc.c; sourceTree = "<group>"; };
074B587B1405B9920060A703 /* matrixlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrixlib.h; sourceTree = "<group>"; };
075CBE12141EC2080089DFF0 /* CAFFileALAC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAFFileALAC.h; sourceTree = "<group>"; };
075CBE1D142184CB0089DFF0 /* CAFFileALAC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CAFFileALAC.cpp; sourceTree = "<group>"; };
075CBE1F142187450089DFF0 /* ALACAudioTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACAudioTypes.h; sourceTree = "<group>"; };
07B7F445141999F800035453 /* ALACDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ALACDecoder.cpp; sourceTree = "<group>"; };
07B7F446141999F800035453 /* ALACDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACDecoder.h; sourceTree = "<group>"; };
07B7F447141999F800035453 /* ALACEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ALACEncoder.cpp; sourceTree = "<group>"; };
07B7F448141999F800035453 /* ALACEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACEncoder.h; sourceTree = "<group>"; };
07E06CFE142968F2002489A3 /* EndianPortable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = EndianPortable.c; sourceTree = "<group>"; };
07E06CFF142968F2002489A3 /* EndianPortable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EndianPortable.h; sourceTree = "<group>"; };
8DD76FB20486AB0100D96B5E /* alacconvert */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = alacconvert; sourceTree = BUILT_PRODUCTS_DIR; };
A98FBFAC06EBB5AB00E7B080 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8DD76FAD0486AB0100D96B5E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
074B58601405B8160060A703 /* codec */ = {
isa = PBXGroup;
children = (
074B58611405B97E0060A703 /* ag_dec.c */,
074B58621405B97E0060A703 /* ag_enc.c */,
074B58631405B97E0060A703 /* aglib.h */,
074B58641405B97E0060A703 /* dp_dec.c */,
074B58651405B97E0060A703 /* dp_enc.c */,
074B58741405B98B0060A703 /* dplib.h */,
074B58751405B98B0060A703 /* matrix_dec.c */,
074B58761405B98B0060A703 /* matrix_enc.c */,
074B587B1405B9920060A703 /* matrixlib.h */,
075CBE1F142187450089DFF0 /* ALACAudioTypes.h */,
071120811405C91B007FF1B0 /* ALACBitUtilities.c */,
071120821405C91B007FF1B0 /* ALACBitUtilities.h */,
07B7F445141999F800035453 /* ALACDecoder.cpp */,
07B7F446141999F800035453 /* ALACDecoder.h */,
07B7F447141999F800035453 /* ALACEncoder.cpp */,
07B7F448141999F800035453 /* ALACEncoder.h */,
07E06CFE142968F2002489A3 /* EndianPortable.c */,
07E06CFF142968F2002489A3 /* EndianPortable.h */,
);
name = codec;
path = ../codec;
sourceTree = SOURCE_ROOT;
};
08FB7794FE84155DC02AAC07 /* ALACconvert */ = {
isa = PBXGroup;
children = (
08FB7795FE84155DC02AAC07 /* Source */,
1AB674ADFE9D54B511CA2CBB /* Products */,
);
name = ALACconvert;
sourceTree = "<group>";
};
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
A98FBFAC06EBB5AB00E7B080 /* main.cpp */,
075CBE12141EC2080089DFF0 /* CAFFileALAC.h */,
075CBE1D142184CB0089DFF0 /* CAFFileALAC.cpp */,
074B58601405B8160060A703 /* codec */,
);
name = Source;
sourceTree = "<group>";
};
1AB674ADFE9D54B511CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
8DD76FB20486AB0100D96B5E /* alacconvert */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
8DD76FAA0486AB0100D96B5E /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
8DD76FA90486AB0100D96B5E /* ALACconvert */ = {
isa = PBXNativeTarget;
buildConfigurationList = A9E1644A087DFBDE006BF7C2 /* Build configuration list for PBXNativeTarget "ALACconvert" */;
buildPhases = (
8DD76FAA0486AB0100D96B5E /* Headers */,
8DD76FAB0486AB0100D96B5E /* Sources */,
8DD76FAD0486AB0100D96B5E /* Frameworks */,
8DD76FAE0486AB0100D96B5E /* Rez */,
8DD76FAF0486AB0100D96B5E /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = ALACconvert;
productInstallPath = "$(HOME)/bin";
productName = ALACconvert;
productReference = 8DD76FB20486AB0100D96B5E /* alacconvert */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = A9E1644E087DFBDE006BF7C2 /* Build configuration list for PBXProject "ALACconvert" */;
compatibilityVersion = "Xcode 2.4";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
en,
);
mainGroup = 08FB7794FE84155DC02AAC07 /* ALACconvert */;
projectDirPath = "";
projectRoot = "";
targets = (
8DD76FA90486AB0100D96B5E /* ALACconvert */,
);
};
/* End PBXProject section */
/* Begin PBXRezBuildPhase section */
8DD76FAE0486AB0100D96B5E /* Rez */ = {
isa = PBXRezBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXRezBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
8DD76FAB0486AB0100D96B5E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A98FBFAD06EBB5AB00E7B080 /* main.cpp in Sources */,
074B586A1405B97E0060A703 /* ag_dec.c in Sources */,
074B586B1405B97E0060A703 /* ag_enc.c in Sources */,
074B586D1405B97E0060A703 /* dp_dec.c in Sources */,
074B586E1405B97E0060A703 /* dp_enc.c in Sources */,
074B58791405B98B0060A703 /* matrix_dec.c in Sources */,
074B587A1405B98B0060A703 /* matrix_enc.c in Sources */,
071120831405C91B007FF1B0 /* ALACBitUtilities.c in Sources */,
07B7F449141999F800035453 /* ALACDecoder.cpp in Sources */,
07B7F44B141999F800035453 /* ALACEncoder.cpp in Sources */,
075CBE1E142184CB0089DFF0 /* CAFFileALAC.cpp in Sources */,
07E06D00142968F2002489A3 /* EndianPortable.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
A9E1644B087DFBDE006BF7C2 /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
COPY_PHASE_STRIP = NO;
DEBUGGING_SYMBOLS = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_ENABLE_TRIGRAPHS = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
GCC_WARN_UNKNOWN_PRAGMAS = NO;
HEADER_SEARCH_PATHS = "";
INSTALL_PATH = "$(HOME)/bin";
LIBRARY_SEARCH_PATHS = "";
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
PRODUCT_NAME = alacconvert;
REZ_EXECUTABLE = YES;
SECTORDER_FLAGS = "";
WARNING_CFLAGS = (
"-Wmost",
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
);
ZERO_LINK = NO;
};
name = Development;
};
A9E1644C087DFBDE006BF7C2 /* Deployment - Fat */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
COPY_PHASE_STRIP = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_ENABLE_TRIGRAPHS = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
GCC_WARN_UNKNOWN_PRAGMAS = NO;
HEADER_SEARCH_PATHS = "";
INSTALL_PATH = "$(HOME)/bin";
LIBRARY_SEARCH_PATHS = "";
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
PRODUCT_NAME = alacconvert;
REZ_EXECUTABLE = YES;
SECTORDER_FLAGS = "";
WARNING_CFLAGS = (
"-Wmost",
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
);
ZERO_LINK = NO;
};
name = "Deployment - Fat";
};
A9E1644D087DFBDE006BF7C2 /* Default */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
FRAMEWORK_SEARCH_PATHS = "";
GCC_ENABLE_TRIGRAPHS = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
GCC_WARN_UNKNOWN_PRAGMAS = NO;
HEADER_SEARCH_PATHS = "";
INSTALL_PATH = "$(HOME)/bin";
LIBRARY_SEARCH_PATHS = "";
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
PRODUCT_NAME = alacconvert;
REZ_EXECUTABLE = YES;
SECTORDER_FLAGS = "";
WARNING_CFLAGS = (
"-Wmost",
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
);
};
name = Default;
};
A9E1644F087DFBDE006BF7C2 /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
HEADER_SEARCH_PATHS = "";
};
name = Development;
};
A9E16450087DFBDE006BF7C2 /* Deployment - Fat */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
HEADER_SEARCH_PATHS = "";
};
name = "Deployment - Fat";
};
A9E16451087DFBDE006BF7C2 /* Default */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
HEADER_SEARCH_PATHS = "";
};
name = Default;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
A9E1644A087DFBDE006BF7C2 /* Build configuration list for PBXNativeTarget "ALACconvert" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A9E1644B087DFBDE006BF7C2 /* Development */,
A9E1644C087DFBDE006BF7C2 /* Deployment - Fat */,
A9E1644D087DFBDE006BF7C2 /* Default */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Default;
};
A9E1644E087DFBDE006BF7C2 /* Build configuration list for PBXProject "ALACconvert" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A9E1644F087DFBDE006BF7C2 /* Development */,
A9E16450087DFBDE006BF7C2 /* Deployment - Fat */,
A9E16451087DFBDE006BF7C2 /* Default */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Default;
};
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}

View File

@@ -0,0 +1,456 @@
/*
Copyright © 2011 Apple Inc. All rights reserved.
IMPORTANT: This Apple software is supplied to you by Apple Inc. (“Apple”) in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the “Apple Software”), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//
// CAFFileALAC.cpp
//
// Copyright 2011 Apple Inc. All rights reserved.
//
#include <stdio.h>
#include "CAFFileALAC.h"
#include "EndianPortable.h"
#define kSizeOfChanAtomPlusChannelLayout 24
int32_t FindCAFFPacketTableStart(FILE * inputFile, int32_t * paktPos, int32_t * paktSize)
{
// returns the absolute position within the file
int32_t currentPosition = ftell(inputFile); // record the current position
uint8_t theReadBuffer[12];
uint32_t chunkType = 0, chunkSize = 0;
bool done = false;
int32_t bytesRead = 8;
fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
while (!done && bytesRead > 0) // no file size here
{
bytesRead = fread(theReadBuffer, 1, 12, inputFile);
chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch(chunkType)
{
case 'pakt':
*paktPos = ftell(inputFile) + kMinCAFFPacketTableHeaderSize;
// big endian size
*paktSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
done = true;
break;
default:
chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
fseek(inputFile, chunkSize, SEEK_CUR);
break;
}
}
fseek(inputFile, currentPosition, SEEK_SET); // start at 0
return 0;
}
void WriteCAFFcaffChunk(FILE * outputFile)
{
uint8_t theReadBuffer[8] = {'c', 'a', 'f', 'f', 0, 1, 0, 0};
fwrite(theReadBuffer, 1, 8, outputFile);
}
void WriteCAFFdescChunk(FILE * outputFile, AudioFormatDescription theOutputFormat)
{
port_CAFAudioDescription theDescription;
uint32_t tempFormatFlags = theOutputFormat.mFormatFlags;
uint8_t theReadBuffer[12] = {'d', 'e', 's', 'c', 0, 0, 0, 0, 0, 0, 0, 0};
if (theOutputFormat.mFormatID == kALACFormatLinearPCM)
{
if (kALACFormatFlagsNativeEndian > 0) // kALACFormatFlagsNativeEndian is 2 on a big endian machine, 0 on little
{
tempFormatFlags = 0;
}
else
{
tempFormatFlags = k_port_CAFLinearPCMFormatFlagIsLittleEndian;
}
}
theDescription.mSampleRate = SwapFloat64NtoB(theOutputFormat.mSampleRate);
theDescription.mFormatID = Swap32NtoB(theOutputFormat.mFormatID);
theDescription.mFormatFlags = Swap32NtoB(tempFormatFlags);
theDescription.mBytesPerPacket = Swap32NtoB(theOutputFormat.mBytesPerPacket);
theDescription.mFramesPerPacket = Swap32NtoB(theOutputFormat.mFramesPerPacket);
theDescription.mChannelsPerFrame = Swap32NtoB(theOutputFormat.mChannelsPerFrame);
theDescription.mBitsPerChannel = Swap32NtoB(theOutputFormat.mBitsPerChannel);
theReadBuffer[11] = sizeof(port_CAFAudioDescription);
fwrite(theReadBuffer, 1, 12, outputFile);
fwrite(&theDescription, 1, sizeof(port_CAFAudioDescription), outputFile);
}
void WriteCAFFdataChunk(FILE * outputFile)
{
uint8_t theReadBuffer[16] = {'d', 'a', 't', 'a', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
fwrite(theReadBuffer, 1, 16, outputFile);
}
void WriteCAFFkukiChunk(FILE * outputFile, void * inCookie, uint32_t inCookieSize)
{
uint8_t thekukiHeaderBuffer[12] = {'k', 'u', 'k', 'i', 0, 0, 0, 0, 0, 0, 0, 0};
thekukiHeaderBuffer[11] = inCookieSize;
fwrite(thekukiHeaderBuffer, 1, 12, outputFile);
fwrite(inCookie, 1, inCookieSize, outputFile);
}
void WriteCAFFChunkSize(FILE * outputFile, int64_t numDataBytes)
{
uint8_t theBuffer[8];
theBuffer[0] = (numDataBytes >> 56) & 0xff;
theBuffer[1] = (numDataBytes >> 48) & 0xff;
theBuffer[2] = (numDataBytes >> 40) & 0xff;
theBuffer[3] = (numDataBytes >> 32) & 0xff;
theBuffer[4] = (numDataBytes >> 24) & 0xff;
theBuffer[5] = (numDataBytes >> 16) & 0xff;
theBuffer[6] = (numDataBytes >> 8) & 0xff;
theBuffer[7] = numDataBytes & 0xff;
fwrite(theBuffer, 1, 8, outputFile);
}
void WriteCAFFchanChunk(FILE * outputFile, uint32_t inChannelTag)
{
uint8_t theBuffer[24] = {'c', 'h', 'a', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
theBuffer[11] = sizeof(ALACAudioChannelLayout);
theBuffer[12] = inChannelTag >> 24;
theBuffer[13] = (inChannelTag >> 16) & 0xff;
theBuffer[14] = (inChannelTag >> 8) & 0xff;
theBuffer[15] = inChannelTag & 0xff;
fwrite(theBuffer, 1, 24, outputFile);
}
void WriteCAFFfreeChunk(FILE * outputFile, uint32_t theSize)
{
uint8_t theBuffer[12] = {'f', 'r', 'e', 'e', 0, 0, 0, 0, 0, 0, 0, 0};
uint32_t i = 0;
uint32_t theAdjustedSize = theSize - sizeof(port_CAFChunkHeader);
if (theSize > theAdjustedSize) // cause we might have wrapped theAdjustedSize
{
theBuffer[8] = theAdjustedSize >> 24;
theBuffer[9] = (theAdjustedSize >> 16) & 0xff;
theBuffer[10] = (theAdjustedSize >> 8) & 0xff;
theBuffer[11] = theAdjustedSize & 0xff;
fwrite(theBuffer, 1, 12, outputFile);
for (i = 0; i < theAdjustedSize; ++i)
{
fwrite(&(theBuffer[4]), 1, 1, outputFile);
}
}
}
void WriteCAFFpaktChunkHeader(FILE * outputFile, port_CAFPacketTableHeader * thePacketTableHeader, uint32_t thePacketTableSize)
{
uint8_t theBuffer[12];
// Endian swap!
thePacketTableHeader->mNumberPackets = Swap64NtoB(thePacketTableHeader->mNumberPackets);
thePacketTableHeader->mNumberValidFrames = Swap64NtoB(thePacketTableHeader->mNumberValidFrames);
thePacketTableHeader->mPrimingFrames = Swap32NtoB(thePacketTableHeader->mPrimingFrames);
thePacketTableHeader->mRemainderFrames = Swap32NtoB(thePacketTableHeader->mRemainderFrames);
// write out the pakt chunk -- big endian!
theBuffer[0] = 'p';
theBuffer[1] = 'a';
theBuffer[2] = 'k';
theBuffer[3] = 't';
theBuffer[4] = 0;
theBuffer[5] = 0;
theBuffer[6] = 0;
theBuffer[7] = 0;
theBuffer[8] = thePacketTableSize >> 24;
theBuffer[9] = (thePacketTableSize >> 16) & 0xff;
theBuffer[10] = (thePacketTableSize >> 8) & 0xff;
theBuffer[11] = thePacketTableSize & 0xff;
fwrite(theBuffer, 1, 12, outputFile);
fwrite(thePacketTableHeader, 1, kMinCAFFPacketTableHeaderSize, outputFile);
}
void GetBERInteger(int32_t theOriginalValue, uint8_t * theBuffer, int32_t * theBERSize)
{
if ((theOriginalValue & 0x7f) == theOriginalValue)
{
*theBERSize = 1;
theBuffer[0] = theOriginalValue;
}
else if ((theOriginalValue & 0x3fff) == theOriginalValue)
{
*theBERSize = 2;
theBuffer[0] = theOriginalValue >> 7;
theBuffer[0] |= 0x80;
theBuffer[1] = theOriginalValue & 0x7f;
}
else if ((theOriginalValue & 0x1fffff) == theOriginalValue)
{
*theBERSize = 3;
theBuffer[0] = theOriginalValue >> 14;
theBuffer[0] |= 0x80;
theBuffer[1] = (theOriginalValue >> 7) & 0x7f;
theBuffer[1] |= 0x80;
theBuffer[2] = theOriginalValue & 0x7f;
}
else if ((theOriginalValue & 0x0fffffff) == theOriginalValue)
{
*theBERSize = 4;
theBuffer[0] = theOriginalValue >> 21;
theBuffer[0] |= 0x80;
theBuffer[1] = (theOriginalValue >> 14) & 0x7f;
theBuffer[1] |= 0x80;
theBuffer[2] = (theOriginalValue >> 7) & 0x7f;
theBuffer[2] |= 0x80;
theBuffer[3] = theOriginalValue & 0x7f;
}
else
{
*theBERSize = 5;
theBuffer[0] = theOriginalValue >> 28;
theBuffer[0] |= 0x80;
theBuffer[1] = (theOriginalValue >> 21) & 0x7f;
theBuffer[1] |= 0x80;
theBuffer[2] = (theOriginalValue >> 14) & 0x7f;
theBuffer[2] |= 0x80;
theBuffer[3] = (theOriginalValue >> 7) & 0x7f;
theBuffer[3] |= 0x80;
theBuffer[4] = theOriginalValue & 0x7f;
}
}
uint32_t ReadBERInteger(uint8_t * theInputBuffer, int32_t * ioNumBytes)
{
uint32_t theAnswer = 0;
uint8_t theData;
int32_t size = 0;
do
{
theData = theInputBuffer[size];
theAnswer = (theAnswer << 7) | (theData & 0x7F);
if (++size > 5)
{
size = 0xFFFFFFFF;
return 0;
}
}
while(((theData & 0x80) != 0) && (size <= *ioNumBytes));
*ioNumBytes = size;
return theAnswer;
}
int32_t BuildBasePacketTable(AudioFormatDescription theInputFormat, int32_t inputDataSize, int32_t * theMaxPacketTableSize, port_CAFPacketTableHeader * thePacketTableHeader)
{
int32_t theMaxPacketSize = 0, theByteSizeTableEntry = 0;
// fill out the header
thePacketTableHeader->mNumberValidFrames = inputDataSize/((theInputFormat.mBitsPerChannel >> 3) * theInputFormat.mChannelsPerFrame);
thePacketTableHeader->mNumberPackets = thePacketTableHeader->mNumberValidFrames/kALACDefaultFramesPerPacket;
thePacketTableHeader->mPrimingFrames = 0;
thePacketTableHeader->mRemainderFrames = thePacketTableHeader->mNumberValidFrames - thePacketTableHeader->mNumberPackets * kALACDefaultFramesPerPacket;
thePacketTableHeader->mRemainderFrames = kALACDefaultFramesPerPacket - thePacketTableHeader->mRemainderFrames;
if (thePacketTableHeader->mRemainderFrames) thePacketTableHeader->mNumberPackets += 1;
// Ok, we have to assume the worst case scenario for packet sizes
theMaxPacketSize = (theInputFormat.mBitsPerChannel >> 3) * theInputFormat.mChannelsPerFrame * kALACDefaultFramesPerPacket + kALACMaxEscapeHeaderBytes;
if (theMaxPacketSize < 16384)
{
theByteSizeTableEntry = 2;
}
else
{
theByteSizeTableEntry = 3;
}
*theMaxPacketTableSize = theByteSizeTableEntry * thePacketTableHeader->mNumberPackets;
return 0;
}
uint32_t GetMagicCookieSizeFromCAFFkuki(FILE * inputFile)
{
// returns to the current absolute position within the file
int32_t currentPosition = ftell(inputFile); // record the current position
uint8_t theReadBuffer[sizeof(ALACSpecificConfig)];
uint32_t chunkType = 0, chunkSize = 0;
bool done = false;
int32_t bytesRead = sizeof(port_CAFFileHeader);
uint32_t theCookieSize = 0;
fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
while (!done && bytesRead > 0) // no file size here
{
bytesRead = fread(theReadBuffer, 1, 12, inputFile);
chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch(chunkType)
{
case 'kuki':
{
theCookieSize = theReadBuffer[11];
done = true;
break;
}
default:
chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
fseek(inputFile, chunkSize, SEEK_CUR);
break;
}
}
fseek(inputFile, currentPosition, SEEK_SET); // start at 0
if (!done) return -1;
return theCookieSize;
}
// gets the kuki chunk from a caff file
int32_t GetMagicCookieFromCAFFkuki(FILE * inputFile, uint8_t * outMagicCookie, uint32_t * ioMagicCookieSize)
{
// returns to the current absolute position within the file
int32_t currentPosition = ftell(inputFile); // record the current position
uint8_t theReadBuffer[12];
uint32_t chunkType = 0, chunkSize = 0;
bool done = false, cookieFound = false;
int32_t bytesRead = sizeof(port_CAFFileHeader);
uint32_t theStoredCookieSize = 0;
fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
while (!done && bytesRead > 0) // no file size here
{
bytesRead = fread(theReadBuffer, 1, 12, inputFile);
chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch(chunkType)
{
case 'kuki':
{
theStoredCookieSize = theReadBuffer[11];
if (*ioMagicCookieSize >= theStoredCookieSize)
{
fread(outMagicCookie, 1, theStoredCookieSize, inputFile);
*ioMagicCookieSize = theStoredCookieSize;
cookieFound = true;
}
else
{
*ioMagicCookieSize = 0;
}
done = true;
break;
}
default:
chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
fseek(inputFile, chunkSize, SEEK_CUR);
break;
}
}
fseek(inputFile, currentPosition, SEEK_SET); // start at 0
if (!done || !cookieFound) return -1;
return 0;
}
bool FindCAFFDataStart(FILE * inputFile, int32_t * dataPos, int32_t * dataSize)
{
bool done = false;
int32_t bytesRead = 8;
uint32_t chunkType = 0, chunkSize = 0;
uint8_t theBuffer[12];
fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
while (!done && bytesRead > 0) // no file size here
{
bytesRead = fread(theBuffer, 1, 12, inputFile);
chunkType = ((int32_t)(theBuffer[0]) << 24) + ((int32_t)(theBuffer[1]) << 16) + ((int32_t)(theBuffer[2]) << 8) + theBuffer[3];
switch(chunkType)
{
case 'data':
*dataPos = ftell(inputFile) + sizeof(uint32_t); // skip the edits
// big endian size
*dataSize = ((int32_t)(theBuffer[8]) << 24) + ((int32_t)(theBuffer[9]) << 16) + ((int32_t)(theBuffer[10]) << 8) + theBuffer[11];
*dataSize -= 4; // the edits are included in the size
done = true;
break;
default:
chunkSize = ((int32_t)(theBuffer[8]) << 24) + ((int32_t)(theBuffer[9]) << 16) + ((int32_t)(theBuffer[10]) << 8) + theBuffer[11];
fseek(inputFile, chunkSize, SEEK_CUR);
break;
}
}
return done;
}
bool GetCAFFdescFormat(FILE * inputFile, AudioFormatDescription * theInputFormat)
{
bool done = false;
uint32_t theChunkSize = 0, theChunkType = 0;
uint8_t theReadBuffer[32];
fseek(inputFile, 4, SEEK_CUR); // skip 4 bytes
while (!done)
{
fread(theReadBuffer, 1, 4, inputFile);
theChunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch (theChunkType)
{
case 'desc':
fseek(inputFile, 8, SEEK_CUR); // skip 8 bytes
fread(theReadBuffer, 1, sizeof(port_CAFAudioDescription), inputFile);
theInputFormat->mFormatID = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFormatID);
theInputFormat->mChannelsPerFrame = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mChannelsPerFrame);
theInputFormat->mSampleRate = SwapFloat64BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mSampleRate);
theInputFormat->mBitsPerChannel = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mBitsPerChannel);
theInputFormat->mFormatFlags = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFormatFlags);
theInputFormat->mBytesPerPacket = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mBytesPerPacket);
if (theInputFormat->mFormatID == kALACFormatAppleLossless)
{
theInputFormat->mBytesPerFrame = 0;
}
else
{
theInputFormat->mBytesPerFrame = theInputFormat->mBytesPerPacket;
if ((theInputFormat->mFormatFlags & 0x02) == 0x02)
{
theInputFormat->mFormatFlags &= 0xfffffffc;
}
else
{
theInputFormat->mFormatFlags |= 0x02;
}
}
theInputFormat->mFramesPerPacket = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFramesPerPacket);
theInputFormat->mReserved = 0;
done = true;
break;
default:
// read the size and skip
fread(theReadBuffer, 1, 8, inputFile);
theChunkSize = ((int32_t)(theReadBuffer[4]) << 24) + ((int32_t)(theReadBuffer[5]) << 16) + ((int32_t)(theReadBuffer[6]) << 8) + theReadBuffer[7];
fseek(inputFile, theChunkSize, SEEK_CUR);
break;
}
}
return done;
}

View File

@@ -0,0 +1,209 @@
/*
Copyright © 2011 Apple Inc. All rights reserved.
IMPORTANT: This Apple software is supplied to you by Apple Inc. (“Apple”) in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the “Apple Software”), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//
// CAFFileALAC.h
// based CAFFile.h in the CoreAudio headers, ALAC specific
//
// Copyright 2011 Apple Inc. All rights reserved.
//
#ifndef _CAFFilePortable_h
#define _CAFFilePortable_h
#if TARGET_OS_WIN32
#define ATTRIBUTE_PACKED
#pragma pack(push, 1)
#else
#define ATTRIBUTE_PACKED __attribute__((__packed__))
#endif
#include "ALACAudioTypes.h"
#define kMinCAFFPacketTableHeaderSize 24
typedef uint32_t CAFFChannelLayoutTag;
// These are subset of the channel layout tags listed in CoreAudioTypes.h
// ALAC and caff both use the same tag values
enum
{
kCAFFChannelLayoutTag_Mono = (100<<16) | 1, // C
kCAFFChannelLayoutTag_Stereo = (101<<16) | 2, // L R
kCAFFChannelLayoutTag_MPEG_3_0_B = (113<<16) | 3, // C L R
kCAFFChannelLayoutTag_MPEG_4_0_B = (116<<16) | 4, // C L R Cs
kCAFFChannelLayoutTag_MPEG_5_0_D = (120<<16) | 5, // C L R Ls Rs
kCAFFChannelLayoutTag_MPEG_5_1_D = (124<<16) | 6, // C L R Ls Rs LFE
kCAFFChannelLayoutTag_AAC_6_1 = (142<<16) | 7, // C L R Ls Rs Cs LFE
kCAFFChannelLayoutTag_MPEG_7_1_B = (127<<16) | 8 // C Lc Rc L R Ls Rs LFE
};
// ALAC currently only utilizes these channels layouts. CAFF supports all those listed in
// CoreAudioTypes.h.
static const CAFFChannelLayoutTag CAFFChannelLayoutTags[kALACMaxChannels] =
{
kCAFFChannelLayoutTag_Mono, // C
kCAFFChannelLayoutTag_Stereo, // L R
kCAFFChannelLayoutTag_MPEG_3_0_B, // C L R
kCAFFChannelLayoutTag_MPEG_4_0_B, // C L R Cs
kCAFFChannelLayoutTag_MPEG_5_0_D, // C L R Ls Rs
kCAFFChannelLayoutTag_MPEG_5_1_D, // C L R Ls Rs LFE
kCAFFChannelLayoutTag_AAC_6_1, // C L R Ls Rs Cs LFE
kCAFFChannelLayoutTag_MPEG_7_1_B // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
};
// In a CAF File all of these types' byte order is big endian.
// When reading or writing these values the program will need to flip byte order to native endian
// CAF File Header
enum {
k_port__port_CAF_FileType = 'caff',
k_port_CAF_FileVersion_Initial = 1
};
// CAF Chunk Types
enum {
k_port_CAF_StreamDescriptionChunkID = 'desc',
k_port_CAF_AudioDataChunkID = 'data',
k_port_CAF_ChannelLayoutChunkID = 'chan',
k_port_CAF_MagicCookieID = 'kuki',
k_port_CAF_PacketTableChunkID = 'pakt',
k_port_CAF_FreeTableChunkID = 'free'
};
struct port_CAFFileHeader
{
uint32_t mFileType; // 'caff'
uint16_t mFileVersion; //initial revision set to 1
uint16_t mFileFlags; //initial revision set to 0
} ATTRIBUTE_PACKED;
typedef struct CAFFileHeader CAFFileHeader;
struct port_CAFChunkHeader
{
uint32_t mChunkType; // four char code
int64_t mChunkSize; // size in bytes of the chunk data (not including this header).
// mChunkSize is int64_t not uint64_t because negative values for
// the data size can have a special meaning
} ATTRIBUTE_PACKED;
typedef struct port_CAFChunkHeader port_CAFChunkHeader;
// Every file MUST have this chunk. It MUST be the first chunk in the file
struct port_CAFAudioDescription
{
double mSampleRate;
uint32_t mFormatID;
uint32_t mFormatFlags;
uint32_t mBytesPerPacket;
uint32_t mFramesPerPacket;
uint32_t mChannelsPerFrame;
uint32_t mBitsPerChannel;
} ATTRIBUTE_PACKED;
typedef struct port_CAFAudioDescription port_CAFAudioDescription;
// these are the flags if the format ID is 'lpcm'
// <CoreAudio/CoreAudioTypes.h> declares some of the format constants
// that can be used as Data Formats in a CAF file
enum
{
k_port_CAFLinearPCMFormatFlagIsFloat = (1L << 0),
k_port_CAFLinearPCMFormatFlagIsLittleEndian = (1L << 1)
};
// 'chan' Optional chunk.
// struct AudioChannelLayout as defined in CoreAudioTypes.h.
// 'free'
// this is a padding chunk for reserving space in the file. content is meaningless.
// 'kuki'
// this is the magic cookie chunk. bag of bytes.
// 'data' Every file MUST have this chunk.
// actual audio data can be any format as described by the 'asbd' chunk.
// if mChunkSize is < 0 then this is the last chunk in the file and the actual length
// should be determined from the file size.
// The motivation for this is to allow writing the files without seeking to update size fields after every
// write in order to keep the file legal.
// The program can put a -1 in the mChunkSize field and
// update it only once at the end of recording.
// If the program were to crash during recording then the file is still well defined.
// 'pakt' Required if either/or mBytesPerPacket or mFramesPerPacket in the Format Description are zero
// For formats that are packetized and have variable sized packets.
// The table is stored as an array of one or two variable length integers.
// (a) size in bytes of the data of a given packet.
// (b) number of frames in a given packet.
// These sizes are encoded as variable length integers
// The packet description entries are either one or two values depending on the format.
// There are three possibilities
// (1)
// If the format has variable bytes per packets (desc.mBytesPerPacket == 0) and constant frames per packet
// (desc.mFramesPerPacket != 0) then the packet table contains single entries representing the bytes in a given packet
// (2)
// If the format is a constant bit rate (desc.mBytesPerPacket != 0) but variable frames per packet
// (desc.mFramesPerPacket == 0) then the packet table entries contains single entries
// representing the number of frames in a given packet
// (3)
// If the format has variable frames per packet (asbd.mFramesPerPacket == 0) and variable bytes per packet
// (desc.mBytesPerPacket == 0) then the packet table entries are a duple of two values. The first value
// is the number of bytes in a given packet, the second value is the number of frames in a given packet
struct port_CAFPacketTableHeader
{
int64_t mNumberPackets;
int64_t mNumberValidFrames;
int32_t mPrimingFrames;
int32_t mRemainderFrames;
uint8_t mPacketDescriptions[1]; // this is a variable length array of mNumberPackets elements
} ATTRIBUTE_PACKED;
typedef struct port_CAFPacketTableHeader port_CAFPacketTableHeader;
struct port_CAFDataChunk
{
uint32_t mEditCount;
uint8_t mData[1]; // this is a variable length data field based off the size of the data chunk
} ATTRIBUTE_PACKED;
typedef struct port_CAFDataChunk port_CAFDataChunk;
// prototypes
int32_t FindCAFFPacketTableStart(FILE * inputFile, int32_t * paktPos, int32_t * paktSize);
void WriteCAFFcaffChunk(FILE * outputFile);
void WriteCAFFdescChunk(FILE * outputFile, AudioFormatDescription theOutputFormat);
void WriteCAFFdataChunk(FILE * outputFile);
void WriteCAFFkukiChunk(FILE * outputFile, void * inCookie, uint32_t inCookieSize);
void WriteCAFFChunkSize(FILE * outputFile, int64_t numDataBytes);
void WriteCAFFchanChunk(FILE * outputFile, uint32_t inChannelTag);
void WriteCAFFfreeChunk(FILE * outputFile, uint32_t theSize);
void WriteCAFFpaktChunkHeader(FILE * outputFile, port_CAFPacketTableHeader * thePacketTableHeader, uint32_t thePacketTableSize);
void GetBERInteger(int32_t theOriginalValue, uint8_t * theBuffer, int32_t * theBERSize);
uint32_t ReadBERInteger(uint8_t * theInputBuffer, int32_t * ioNumBytes);
int32_t BuildBasePacketTable(AudioFormatDescription theInputFormat, int32_t inputDataSize, int32_t * thePacketTableSize, port_CAFPacketTableHeader * thePacketTableHeader);
uint32_t GetMagicCookieSizeFromCAFFkuki(FILE * inputFile);
int32_t GetMagicCookieFromCAFFkuki(FILE * inputFile, uint8_t * outMagicCookie, uint32_t * ioMagicCookieSize);
bool FindCAFFDataStart(FILE * inputFile, int32_t * dataPos, int32_t * dataSize);
bool GetCAFFdescFormat(FILE * inputFile, AudioFormatDescription * theInputFormat);
#if TARGET_OS_WIN32
#pragma pack(pop)
#endif
////////////////////////////////////////////////////////////////////////////////////////////////
#endif

View File

@@ -0,0 +1,784 @@
/*
Copyright © 2011 Apple Inc. All rights reserved.
IMPORTANT: This Apple software is supplied to you by Apple Inc. (“Apple”) in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the “Apple Software”), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* main.cpp
*
* Converts pcm data contained in a .wav or .caf file into Apple Lossless (ALAC) put into a .caf file
* or converts ALAC data from a .caf file into pcm data and put into a .wav or .caf file
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// these are headers for the ALAC encoder and decoder
#include "ALACEncoder.h"
#include "ALACDecoder.h"
#include "ALACBitUtilities.h"
// these are utility headers for this sample code
#include "CAFFileALAC.h"
#include "EndianPortable.h"
#define kMaxBERSize 5
#define kCAFFdataChunkEditsSize 4
#define kWAVERIFFChunkSize 12
#define kWAVEfmtChunkSize 24
#define kWAVEdataChunkHeaderSize 8
#define VERBOSE 0
// Helper functions
int32_t GetInputFormat(FILE * inputFile, AudioFormatDescription * theInputFormat, uint32_t * theFileType);
int32_t SetOutputFormat(AudioFormatDescription theInputFormat, AudioFormatDescription * theOutputFormat);
int32_t FindDataStart(FILE * inputFile, uint32_t inputFileType, int32_t * dataPos, int32_t * dataSize);
int32_t EncodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize);
int32_t DecodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize, uint32_t outputFileType);
void GetOutputFileType(char * outputFileName, uint32_t * outputFileType);
ALACChannelLayoutTag GetALACChannelLayoutTag(uint32_t inChannelsPerFrame);
// Some crude WAVE writing tools
void WriteWAVERIFFChunk(FILE * outputFile);
void WriteWAVEfmtChunk(FILE * outputFile, AudioFormatDescription theOutputFormat);
void WriteWAVEdataChunk(FILE * outputFile);
void WriteWAVEChunkSize(FILE * outputFile, uint32_t numDataBytes);
// Adapted from CoreAudioTypes.h
enum
{
kTestFormatFlag_16BitSourceData = 1,
kTestFormatFlag_20BitSourceData = 2,
kTestFormatFlag_24BitSourceData = 3,
kTestFormatFlag_32BitSourceData = 4
};
int32_t main (int32_t argc, char * argv[])
{
char * inputFileName = argv[1];
char * outputFileName = argv[2];
FILE * inputFile = NULL;
FILE * outputFile = NULL;
bool malformed = argc < 2;
// Parse the commandline and open the necessary files
for (int32_t i = 1; i < argc; ++i)
{
if (strcmp (argv[i], "-h") == 0)
{
malformed = true;
}
else
{
if (argv[i][0] == '-')
{
printf ("unknown option: %s\n", argv[i]);
malformed = true;
}
else
{
if (inputFile == NULL) inputFile = fopen (inputFileName, "rb"); // the b is necessary for Windows -- ignored by Unix
if(inputFile == NULL)
{
fprintf(stderr," Cannot open file \"%s\"\n", inputFileName);
exit (1);
}
if (outputFile == NULL) outputFile = fopen (outputFileName, "w+b"); // the b is necessary for Windows -- ignored by Unix
if(outputFile == NULL)
{
fprintf(stderr," Cannot open file \"%s\"\n", outputFileName);
exit (1);
}
}
}
if (malformed)
{
break;
}
}
if (!malformed)
{
printf("Input file: %s\n", inputFileName);
printf("Output file: %s\n", outputFileName);
// So at this point we have the input and output files open. Need to determine what we're dealing with
int32_t theError = 0;
AudioFormatDescription inputFormat;
AudioFormatDescription outputFormat;
int32_t inputDataPos = 0, inputDataSize = 0;
uint32_t inputFileType = 0; // 'caff' or 'WAVE'
uint32_t outputFileType = 0; // 'caff' or 'WAVE'
theError = GetInputFormat(inputFile, &inputFormat, &inputFileType);
if (theError)
{
fprintf(stderr," Cannot determine what format file \"%s\" is\n", inputFileName);
exit (1);
}
if (inputFileType != 'WAVE' && inputFileType != 'caff')
{
fprintf(stderr," File \"%s\" is of an unsupported type\n", outputFileName);
exit (1);
}
if (inputFormat.mFormatID != kALACFormatAppleLossless && inputFormat.mFormatID != kALACFormatLinearPCM)
{
fprintf(stderr," File \"%s\'s\" data format is of an unsupported type\n", outputFileName);
exit (1);
}
SetOutputFormat(inputFormat, &outputFormat);
if (theError)
{
fprintf(stderr," Cannot determine what format file \"%s\" is\n", outputFileName);
exit (1);
}
FindDataStart(inputFile, inputFileType, &inputDataPos, &inputDataSize);
fseek(inputFile, inputDataPos, SEEK_SET);
// We know where we are and we know what we're doing
if (outputFormat.mFormatID == kALACFormatAppleLossless)
{
// encoding
EncodeALAC(inputFile, outputFile, inputFormat, outputFormat, inputDataSize);
}
else
{
// decoding
GetOutputFileType(outputFileName, &outputFileType);
if (outputFileType == 'WAVE' && outputFormat.mChannelsPerFrame > 2)
{
// we don't support WAVE because we don't want to reinterleave on output
fprintf(stderr," Cannot decode more than two channels to WAVE\n");
exit (1);
}
DecodeALAC(inputFile, outputFile, inputFormat, outputFormat, inputDataSize, outputFileType);
}
}
if (malformed) {
printf ("Usage:\n");
printf ("Encode:\n");
printf (" alacconvert <input wav or caf file> <output caf file>\n");
printf ("Decode:\n");
printf (" alacconvert <input caf file> <output wav or caf file>\n");
printf ("\n");
return 1;
}
if (inputFile) fclose(inputFile);
if (outputFile) fclose(outputFile);
return 0;
}
int32_t GetInputFormat(FILE * inputFile, AudioFormatDescription * theInputFormat, uint32_t * theFileType)
{
// assumes the file is open
uint8_t theReadBuffer[20];
bool done = false;
uint32_t chunkType = 0;
fread(theReadBuffer, 1, 4, inputFile);
if (theReadBuffer[0] == 'c' && theReadBuffer[1] == 'a' && theReadBuffer[2] == 'f' & theReadBuffer[3] == 'f')
{
// It's a caff file!
*theFileType = 'caff';
// We support pcm data for encode and alac data for decode
done = GetCAFFdescFormat(inputFile, theInputFormat);
}
else if (theReadBuffer[0] == 'R' && theReadBuffer[1] == 'I' && theReadBuffer[2] == 'F' & theReadBuffer[3] == 'F')
{
fread(theReadBuffer, 1, 8, inputFile);
if (theReadBuffer[4] == 'W' && theReadBuffer[5] == 'A' && theReadBuffer[6] == 'V' & theReadBuffer[7] == 'E')
{
// It's a WAVE file!
*theFileType = 'WAVE';
// We only support pcm data
while (!done)
{
uint32_t theChunkSize = 0, theSampleRate = 0;
fread(theReadBuffer, 1, 4, inputFile);
chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch (chunkType)
{
case 'fmt ':
fread(theReadBuffer, 1, 20, inputFile);
// Remember campers we're in little endian land
if (theReadBuffer[4] != 1 || theReadBuffer[5] != 0)
{
// we only support PCM
*theFileType = 0; // clear it
return -1;
}
theInputFormat->mFormatID = kALACFormatLinearPCM;
theInputFormat->mChannelsPerFrame = theReadBuffer[6];
theSampleRate = ((int32_t)(theReadBuffer[11]) << 24) + ((int32_t)(theReadBuffer[10]) << 16) + ((int32_t)(theReadBuffer[9]) << 8) + theReadBuffer[8];
theInputFormat->mSampleRate = theSampleRate;
theInputFormat->mBitsPerChannel = theReadBuffer[18];
theInputFormat->mFormatFlags = kALACFormatFlagIsSignedInteger | kALACFormatFlagIsPacked; // always little endian
theInputFormat->mBytesPerPacket = theInputFormat->mBytesPerFrame = (theInputFormat->mBitsPerChannel >> 3) * theInputFormat->mChannelsPerFrame;
theInputFormat->mFramesPerPacket = 1;
theInputFormat->mReserved = 0;
done = true;
break;
default:
// read the size and skip
fread(theReadBuffer, 1, 4, inputFile);
theChunkSize = ((int32_t)(theReadBuffer[3]) << 24) + ((int32_t)(theReadBuffer[2]) << 16) + ((int32_t)(theReadBuffer[1]) << 8) + theReadBuffer[0];
fseek(inputFile, theChunkSize, SEEK_CUR);
break;
}
}
}
else
{
*theFileType = 0; // clear it
return -1;
}
}
else
{
*theFileType = 0; // clear it
return -1;
}
if (!done) return -1;
return 0;
}
int32_t SetOutputFormat(AudioFormatDescription theInputFormat, AudioFormatDescription * theOutputFormat)
{
if (theInputFormat.mFormatID == kALACFormatLinearPCM)
{
// encoding
theOutputFormat->mFormatID = kALACFormatAppleLossless;
theOutputFormat->mSampleRate = theInputFormat.mSampleRate;
switch(theInputFormat.mBitsPerChannel)
{
case 16:
theOutputFormat->mFormatFlags = kTestFormatFlag_16BitSourceData;
break;
case 20:
theOutputFormat->mFormatFlags = kTestFormatFlag_20BitSourceData;
break;
case 24:
theOutputFormat->mFormatFlags = kTestFormatFlag_24BitSourceData;
break;
case 32:
theOutputFormat->mFormatFlags = kTestFormatFlag_32BitSourceData;
break;
default:
return -1;
break;
}
theOutputFormat->mFramesPerPacket = kALACDefaultFramesPerPacket;
theOutputFormat->mChannelsPerFrame = theInputFormat.mChannelsPerFrame;
// mBytesPerPacket == 0 because we are VBR
// mBytesPerFrame and mBitsPerChannel == 0 because there are no discernable bits assigned to a particular sample
// mReserved is always 0
theOutputFormat->mBytesPerPacket = theOutputFormat->mBytesPerFrame = theOutputFormat->mBitsPerChannel = theOutputFormat->mReserved = 0;
}
else
{
// decoding
theOutputFormat->mFormatID = kALACFormatLinearPCM;
theOutputFormat->mSampleRate = theInputFormat.mSampleRate;
switch(theInputFormat.mFormatFlags)
{
case kTestFormatFlag_16BitSourceData:
theOutputFormat->mBitsPerChannel = 16;
break;
case kTestFormatFlag_20BitSourceData:
theOutputFormat->mBitsPerChannel = 20;
break;
case kTestFormatFlag_24BitSourceData:
theOutputFormat->mBitsPerChannel = 24;
break;
case kTestFormatFlag_32BitSourceData:
theOutputFormat->mBitsPerChannel = 32;
break;
default:
return -1;
break;
}
theOutputFormat->mFramesPerPacket = 1;
theOutputFormat->mChannelsPerFrame = theInputFormat.mChannelsPerFrame;
theOutputFormat->mBytesPerPacket = theOutputFormat->mBytesPerFrame = theOutputFormat->mBitsPerChannel != 20 ? theInputFormat.mChannelsPerFrame * ((theOutputFormat->mBitsPerChannel) >> 3) : (int32_t)(theInputFormat.mChannelsPerFrame * 2.5 + .5);
theOutputFormat->mFormatFlags = kALACFormatFlagsNativeEndian;
theOutputFormat->mReserved = 0;
}
return 0;
}
int32_t FindDataStart(FILE * inputFile, uint32_t inputFileType, int32_t * dataPos, int32_t * dataSize)
{
// returns the absolute position within the file
int32_t currentPosition = ftell(inputFile); // record the current position
uint8_t theReadBuffer[12];
uint32_t chunkType = 0, fileSize = 0, chunkSize = 0;
bool done = false;
switch (inputFileType)
{
case 'WAVE':
fseek(inputFile, 0, SEEK_SET); // start at 0
fread(theReadBuffer, 1, 8, inputFile);
fileSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
fseek(inputFile, 12, SEEK_SET); // start at 12!
while (!done && ((uint32_t)(ftell(inputFile)) < fileSize))
{
fread(theReadBuffer, 1, 8, inputFile);
chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch(chunkType)
{
case 'data':
*dataPos = ftell(inputFile);
// little endian size
*dataSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
done = true;
break;
default:
chunkSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
fseek(inputFile, chunkSize, SEEK_CUR);
break;
}
}
break;
case 'caff':
done = FindCAFFDataStart(inputFile, dataPos, dataSize);
break;
}
fseek(inputFile, currentPosition, SEEK_SET); // start at 0
if (!done) return -1;
return 0;
}
int32_t EncodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize)
{
int32_t theInputPacketBytes = theInputFormat.mChannelsPerFrame * (theInputFormat.mBitsPerChannel >> 3) * theOutputFormat.mFramesPerPacket;
int32_t theOutputPacketBytes = theInputPacketBytes + kALACMaxEscapeHeaderBytes;
int32_t thePacketTableSize = 0, packetTablePos = 0, dataPos = 0, dataSizePos = 0, theBERSize = 0, packetTableSizePos;
uint8_t * theReadBuffer = (uint8_t *)calloc(theInputPacketBytes, 1);
uint8_t * theWriteBuffer = (uint8_t *)calloc(theOutputPacketBytes, 1);
int32_t numBytes = 0;
uint32_t packetTableBytesLeft = 0;
int64_t numDataBytes = 0;
port_CAFPacketTableHeader thePacketTableHeader;
int32_t inputDataBytesRemaining = inputDataSize;
uint8_t * theMagicCookie = NULL;
uint32_t theMagicCookieSize = 0;
ALACEncoder * theEncoder = new ALACEncoder;
theEncoder->SetFrameSize(theOutputFormat.mFramesPerPacket);
theEncoder->InitializeEncoder(theOutputFormat);
// we only write out the caff header, the 'desc' chunk. the 'kuki' chunk, the 'pakt' chunk and the 'data' chunk
// write out the caff header
WriteCAFFcaffChunk(outputFile);
// write out the desc chunk
WriteCAFFdescChunk(outputFile, theOutputFormat);
// get the magic cookie
theMagicCookieSize = theEncoder->GetMagicCookieSize(theOutputFormat.mChannelsPerFrame);
theMagicCookie = (uint8_t *)calloc(theMagicCookieSize, 1);
theEncoder->GetMagicCookie(theMagicCookie, &theMagicCookieSize);
// write out the kuki chunk
WriteCAFFkukiChunk(outputFile, theMagicCookie, theMagicCookieSize);
free(theMagicCookie);
// We might be multi channel
if (theOutputFormat.mChannelsPerFrame > 2)
{
WriteCAFFchanChunk(outputFile, GetALACChannelLayoutTag(theOutputFormat.mChannelsPerFrame));
}
// Figure out the maximum size and build the base pakt header
BuildBasePacketTable(theInputFormat, inputDataSize, &thePacketTableSize, &thePacketTableHeader);
packetTableBytesLeft = thePacketTableSize;
// This could be substantially larger than either the read or write buffer, so allocate a block of memory here
// all we're going to do is copy it to the file
uint8_t * thePacketTableEntries = (uint8_t *)calloc (thePacketTableSize, 1);
/* move */
thePacketTableSize += kMinCAFFPacketTableHeaderSize;
WriteCAFFpaktChunkHeader(outputFile, &thePacketTableHeader, thePacketTableSize);
packetTableSizePos = packetTablePos = ftell(outputFile);
packetTableSizePos -= (sizeof(int64_t) + kMinCAFFPacketTableHeaderSize);
thePacketTableSize -= kMinCAFFPacketTableHeaderSize;
fwrite (thePacketTableEntries, 1, thePacketTableSize, outputFile);
free(thePacketTableEntries);
// We'll write out the data chunk next. The 'data' size will start past the 'data' chunk identifier
dataSizePos = ftell(outputFile) + sizeof(uint32_t);
// Finally, write out the data chunk
WriteCAFFdataChunk(outputFile);
dataPos = ftell(outputFile);
while (theInputPacketBytes <= inputDataBytesRemaining)
{
numBytes = fread(theReadBuffer, 1, theInputPacketBytes, inputFile);
#if VERBOSE
printf ("Read %i bytes\n", numBytes);
#endif
inputDataBytesRemaining -= numBytes;
if ((theInputFormat.mFormatFlags & 0x02) != kALACFormatFlagsNativeEndian)
{
#if VERBOSE
printf ("Byte Swapping!\n");
#endif
if (theInputFormat.mBitsPerChannel == 16)
{
uint16_t * theShort = (uint16_t *)theReadBuffer;
for (int32_t i = 0; i < (numBytes >> 1); ++i)
{
Swap16(&(theShort[i]));
}
}
else if (theInputFormat.mBitsPerChannel == 32)
{
uint32_t * theLong = (uint32_t *)theReadBuffer;
for (int32_t i = 0; i < (numBytes >> 2); ++i)
{
Swap32(&(theLong[i]));
}
}
else // covers both 20 and 24
{
for (int32_t i = 0; i < numBytes; i += 3)
{
Swap24(&(theReadBuffer[i]));
}
}
}
theEncoder->Encode(theInputFormat, theInputFormat, theReadBuffer, theWriteBuffer, &numBytes);
GetBERInteger(numBytes, theReadBuffer, &theBERSize);
fseek(outputFile, packetTablePos, SEEK_SET);
fwrite(theReadBuffer, 1, theBERSize, outputFile);
packetTablePos += theBERSize;
packetTableBytesLeft -= theBERSize;
fseek(outputFile, dataPos, SEEK_SET);
fwrite(theWriteBuffer, 1, numBytes, outputFile);
dataPos += numBytes;
numDataBytes += numBytes;
#if VERBOSE
printf ("Writing %i bytes\n", numBytes);
#endif
}
// encode the last partial packet
if (inputDataBytesRemaining)
{
numBytes = fread(theReadBuffer, 1, inputDataBytesRemaining, inputFile);
#if VERBOSE
printf ("Last Packet! Read %i bytes\n", numBytes);
#endif
inputDataBytesRemaining -= numBytes;
if ((theInputFormat.mFormatFlags & 0x02) != kALACFormatFlagsNativeEndian)
{
#if VERBOSE
printf ("Byte Swapping!\n");
#endif
if (theInputFormat.mBitsPerChannel == 16)
{
uint16_t * theShort = (uint16_t *)theReadBuffer;
for (int32_t i = 0; i < (numBytes >> 1); ++i)
{
Swap16(&(theShort[i]));
}
}
else if (theInputFormat.mBitsPerChannel == 32)
{
uint32_t * theLong = (uint32_t *)theReadBuffer;
for (int32_t i = 0; i < (numBytes >> 2); ++i)
{
Swap32(&(theLong[i]));
}
}
else // covers both 20 and 24
{
for (int32_t i = 0; i < numBytes; i += 3)
{
Swap24(&(theReadBuffer[i]));
}
}
}
theEncoder->Encode(theInputFormat, theInputFormat, theReadBuffer, theWriteBuffer, &numBytes);
GetBERInteger(numBytes, theReadBuffer, &theBERSize);
fseek(outputFile, packetTablePos, SEEK_SET);
fwrite(theReadBuffer, 1, theBERSize, outputFile);
packetTablePos += theBERSize;
packetTableBytesLeft -= theBERSize;
fseek(outputFile, dataPos, SEEK_SET);
fwrite(theWriteBuffer, 1, numBytes, outputFile);
dataPos += numBytes;
numDataBytes += numBytes;
#if VERBOSE
printf ("Writing %i bytes\n", numBytes);
#endif
}
// cleanup -- if we have a lot of bytes left over in packet table, write a free chunk
if (packetTableBytesLeft > sizeof(port_CAFChunkHeader)) // min size required to write
{
#if VERBOSE
printf ("Writing %i free bytes\n", packetTableBytesLeft);
#endif
fseek(outputFile, packetTablePos, SEEK_SET);
WriteCAFFfreeChunk(outputFile, packetTableBytesLeft);
fseek(outputFile, packetTableSizePos, SEEK_SET);
WriteCAFFChunkSize(outputFile, thePacketTableSize - packetTableBytesLeft + kMinCAFFPacketTableHeaderSize);
}
// write out the data size
fseek(outputFile, dataSizePos, SEEK_SET);
numDataBytes += kCAFFdataChunkEditsSize;
#if VERBOSE
printf ("numDataBytes == %i bytes\n", numDataBytes);
#endif
WriteCAFFChunkSize(outputFile, numDataBytes);
delete theEncoder;
free(theReadBuffer);
free(theWriteBuffer);
return 0;
}
// There's not a whole lot of difference between encode and decode on this level
int32_t DecodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize, uint32_t outputFileType)
{
int32_t theInputPacketBytes = theInputFormat.mChannelsPerFrame * (theOutputFormat.mBitsPerChannel >> 3) * theInputFormat.mFramesPerPacket + kALACMaxEscapeHeaderBytes;
int32_t theOutputPacketBytes = theInputPacketBytes - kALACMaxEscapeHeaderBytes;
int32_t thePacketTableSize = 0, packetTablePos = 0, outputDataSizePos = 0, inputDataPos = 0;
uint8_t * theReadBuffer = (uint8_t *)calloc(theInputPacketBytes, 1);
uint8_t * theWriteBuffer = (uint8_t *)calloc(theOutputPacketBytes, 1);
int32_t numBytes = 0;
int64_t numDataBytes = 0;
uint32_t numFrames = 0;
BitBuffer theInputBuffer;
uint8_t * theMagicCookie = NULL;
uint32_t theMagicCookieSize = 0;
ALACDecoder * theDecoder = new ALACDecoder;
// We need to get the cookie from the file
theMagicCookieSize = GetMagicCookieSizeFromCAFFkuki(inputFile);
theMagicCookie = (uint8_t *)calloc(theMagicCookieSize, 1);
GetMagicCookieFromCAFFkuki(inputFile, theMagicCookie, &theMagicCookieSize);
// While we don't have a use for this here, if you were using arbitrary channel layouts, you'd need to run the following check:
theDecoder->Init(theMagicCookie, theMagicCookieSize);
free(theMagicCookie);
BitBufferInit(&theInputBuffer, theReadBuffer, theInputPacketBytes);
inputDataPos = ftell(inputFile);
if (outputFileType != 'WAVE')
{
// we only write out the caff header, the 'desc' chunk and the 'data' chunk
// write out the caff header
WriteCAFFcaffChunk(outputFile);
// write out the desc chunk
WriteCAFFdescChunk(outputFile, theOutputFormat);
// We might be multi channel
if (theOutputFormat.mChannelsPerFrame > 2)
{
// we are not rearranging the output data
WriteCAFFchanChunk(outputFile, CAFFChannelLayoutTags[theOutputFormat.mChannelsPerFrame - 1]);
}
// We'll write out the data chunk next. The 'data' size will start past the 'data' chunk identifier
outputDataSizePos = ftell(outputFile) + sizeof(uint32_t);
// Finally, write out the data chunk
WriteCAFFdataChunk(outputFile);
}
else
{
// We're writing a mono or stereo WAVE file
WriteWAVERIFFChunk(outputFile);
WriteWAVEfmtChunk(outputFile, theOutputFormat);
WriteWAVEdataChunk(outputFile);
outputDataSizePos = ftell(outputFile) - sizeof(uint32_t);
}
// We do have to get the packet size from the packet table
FindCAFFPacketTableStart(inputFile, &packetTablePos, &thePacketTableSize);
fseek(inputFile, packetTablePos, SEEK_SET);
numBytes = fread(theReadBuffer, 1, kMaxBERSize, inputFile);
theInputPacketBytes = ReadBERInteger(theReadBuffer, &numBytes);
packetTablePos += numBytes;
fseek(inputFile, inputDataPos, SEEK_SET);
inputDataPos += theInputPacketBytes;
while ((theInputPacketBytes > 0) && ((size_t)theInputPacketBytes == fread(theReadBuffer, 1, theInputPacketBytes, inputFile)))
{
#if VERBOSE
printf ("Read %i bytes\n", theInputPacketBytes);
#endif
theDecoder->Decode(&theInputBuffer, theWriteBuffer, theInputFormat.mFramesPerPacket, theInputFormat.mChannelsPerFrame, &numFrames);
numBytes = numFrames * theOutputFormat.mBytesPerFrame;
#if VERBOSE
printf ("Writing %i bytes\n", numBytes);
#endif
fwrite(theWriteBuffer, 1, numBytes, outputFile);
numDataBytes += numBytes;
fseek(inputFile, packetTablePos, SEEK_SET);
numBytes = fread(theReadBuffer, 1, kMaxBERSize, inputFile);
theInputPacketBytes = ReadBERInteger(theReadBuffer, &numBytes);
#if VERBOSE
printf ("theInputPacketBytes == %i bytes\n", theInputPacketBytes);
#endif
packetTablePos += numBytes;
fseek(inputFile, inputDataPos, SEEK_SET);
inputDataPos += theInputPacketBytes;
BitBufferReset(&theInputBuffer);
}
if (outputFileType != 'WAVE')
{
// cleanup -- write out the data size
fseek(outputFile, outputDataSizePos, SEEK_SET);
numDataBytes += kCAFFdataChunkEditsSize; // add in the edit bytes
#if VERBOSE
printf ("numDataBytes == %i bytes\n", numDataBytes);
#endif
WriteCAFFChunkSize(outputFile, numDataBytes);
}
else
{
// cleanup -- write out the data size
fseek(outputFile, outputDataSizePos, SEEK_SET);
WriteWAVEChunkSize(outputFile, (uint32_t)numDataBytes);
// write out the file size
fseek(outputFile, 4, SEEK_SET);
WriteWAVEChunkSize(outputFile, numDataBytes + sizeof(outputFileType) + kWAVEdataChunkHeaderSize + kWAVEfmtChunkSize); // add in the size for 'WAVE', size of the data' chunk header and the 'fmt ' chunk
}
delete theDecoder;
free(theReadBuffer);
free(theWriteBuffer);
return 0;
}
void GetOutputFileType(char * outputFileName, uint32_t * outputFileType)
{
char * typeStr = strrchr(outputFileName, '.');
*outputFileType = 'caff';
if (typeStr != NULL)
{
if (strlen(typeStr) == 4)
{
if (strcmp(typeStr, ".wav") == 0)
{
*outputFileType = 'WAVE';
}
}
}
}
ALACChannelLayoutTag GetALACChannelLayoutTag(uint32_t inChannelsPerFrame)
{
return ALACChannelLayoutTags[inChannelsPerFrame - 1];
}
void WriteWAVERIFFChunk(FILE * outputFile)
{
uint8_t theReadBuffer[kWAVERIFFChunkSize] = {'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'A', 'V', 'E'};
fwrite(theReadBuffer, 1, kWAVERIFFChunkSize, outputFile);
}
void WriteWAVEfmtChunk(FILE * outputFile, AudioFormatDescription theOutputFormat)
{
// we use a standard 'fmt ' chunk for our pcm data where 16 is the chunk size and 1 is the compression code
uint8_t theBuffer[kWAVEfmtChunkSize] = {'f', 'm', 't', ' ', 16, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint32_t theSampleRate = theOutputFormat.mSampleRate;
uint32_t theAverageBytesPerSecond = theSampleRate * theOutputFormat.mBytesPerFrame;
theBuffer[10] = theOutputFormat.mChannelsPerFrame;
theBuffer[12] = theSampleRate & 0xff;
theBuffer[13] = (theSampleRate >> 8) & 0xff;
theBuffer[14] = (theSampleRate >> 16) & 0xff;
theBuffer[15] = theSampleRate >> 24;
theBuffer[16] = theAverageBytesPerSecond & 0xff;
theBuffer[17] = (theAverageBytesPerSecond >> 8) & 0xff;
theBuffer[18] = (theAverageBytesPerSecond >> 16) & 0xff;
theBuffer[19] = theAverageBytesPerSecond >> 24;
theBuffer[20] = theOutputFormat.mBytesPerFrame;
theBuffer[22] = theOutputFormat.mBitsPerChannel;
fwrite(theBuffer, 1, kWAVEfmtChunkSize, outputFile);
}
void WriteWAVEdataChunk(FILE * outputFile)
{
uint8_t theBuffer[kWAVEdataChunkHeaderSize] = {'d', 'a', 't', 'a', 0, 0, 0, 0};
fwrite(theBuffer, 1, kWAVEdataChunkHeaderSize, outputFile);
}
void WriteWAVEChunkSize(FILE * outputFile, uint32_t numDataBytes)
{
uint8_t theBuffer[4];
theBuffer[0] = numDataBytes & 0xff;
theBuffer[1] = (numDataBytes >> 8) & 0xff;
theBuffer[2] = (numDataBytes >> 16) & 0xff;
theBuffer[3] = (numDataBytes >> 24) & 0xff;
fwrite(theBuffer, 1, 4, outputFile);
}