diff --git a/.gitmodules b/.gitmodules index aae0054cf..7b55ef621 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "Frameworks/libsidplay/sidplay-residfp-code"] path = Frameworks/libsidplay/sidplay-residfp-code url = https://bitbucket.org/losnoco/sidplay-residfp.git +[submodule "Frameworks/libatrac9/libatrac9"] + path = Frameworks/libatrac9/libatrac9 + url = https://github.com/Thealexbarney/LibAtrac9.git diff --git a/Cog.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Cog.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/Cog.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/Frameworks/AdPlug/libAdPlug.xcodeproj/project.pbxproj b/Frameworks/AdPlug/libAdPlug.xcodeproj/project.pbxproj index c841c0b55..e9919ebb7 100644 --- a/Frameworks/AdPlug/libAdPlug.xcodeproj/project.pbxproj +++ b/Frameworks/AdPlug/libAdPlug.xcodeproj/project.pbxproj @@ -566,7 +566,7 @@ TargetAttributes = { 83D3C4D3201C654F005564CB = { CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; + ProvisioningStyle = Manual; }; }; }; @@ -808,9 +808,9 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; @@ -828,6 +828,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = net.kode54.AdPlug; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; }; name = Debug; @@ -836,9 +837,9 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; @@ -852,6 +853,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = net.kode54.AdPlug; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; }; name = Release; diff --git a/Frameworks/Ogg/macosx/Ogg.xcodeproj/project.pbxproj b/Frameworks/Ogg/macosx/Ogg.xcodeproj/project.pbxproj index 315ba102f..ae3e66d44 100644 --- a/Frameworks/Ogg/macosx/Ogg.xcodeproj/project.pbxproj +++ b/Frameworks/Ogg/macosx/Ogg.xcodeproj/project.pbxproj @@ -259,8 +259,11 @@ 730F235509181A3A00AB638C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = N6E749HJ2X; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; @@ -273,6 +276,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.8; PRODUCT_BUNDLE_IDENTIFIER = org.xiph.ogg; PRODUCT_NAME = Ogg; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = macosx; WRAPPER_EXTENSION = framework; ZERO_LINK = YES; @@ -282,8 +286,11 @@ 730F235609181A3A00AB638C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; + DEVELOPMENT_TEAM = N6E749HJ2X; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; @@ -295,6 +302,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.8; PRODUCT_BUNDLE_IDENTIFIER = org.xiph.ogg; PRODUCT_NAME = Ogg; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = macosx; WRAPPER_EXTENSION = framework; ZERO_LINK = NO; diff --git a/Frameworks/OpenMPT/libOpenMPT.xcodeproj/project.pbxproj b/Frameworks/OpenMPT/libOpenMPT.xcodeproj/project.pbxproj index dbeed8cc5..0ae5bff98 100644 --- a/Frameworks/OpenMPT/libOpenMPT.xcodeproj/project.pbxproj +++ b/Frameworks/OpenMPT/libOpenMPT.xcodeproj/project.pbxproj @@ -1141,7 +1141,7 @@ TargetAttributes = { 83E5EFBC1FFEF7CC00659F0F = { CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; + ProvisioningStyle = Manual; }; }; }; @@ -1456,9 +1456,9 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; @@ -1471,6 +1471,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = net.kode54.libOpenMPT; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; }; name = Debug; @@ -1479,9 +1480,9 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; @@ -1494,6 +1495,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = net.kode54.libOpenMPT; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; }; name = Release; diff --git a/Frameworks/Vorbis/macosx/Vorbis.xcodeproj/project.pbxproj b/Frameworks/Vorbis/macosx/Vorbis.xcodeproj/project.pbxproj index 7d4b89c9d..66f184906 100644 --- a/Frameworks/Vorbis/macosx/Vorbis.xcodeproj/project.pbxproj +++ b/Frameworks/Vorbis/macosx/Vorbis.xcodeproj/project.pbxproj @@ -578,6 +578,7 @@ LastUpgradeCheck = 1130; TargetAttributes = { 730F23A1091827B100AB638C = { + DevelopmentTeam = N6E749HJ2X; ProvisioningStyle = Manual; }; 738835E30B18F870005C7A69 = { @@ -756,11 +757,11 @@ 730F23ED091827B100AB638C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = N6E749HJ2X; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; @@ -791,11 +792,11 @@ 730F23EE091827B100AB638C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = N6E749HJ2X; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; diff --git a/Frameworks/g719/g719.xcodeproj/project.pbxproj b/Frameworks/g719/g719.xcodeproj/project.pbxproj index 2d4b379a7..ba8b15b16 100644 --- a/Frameworks/g719/g719.xcodeproj/project.pbxproj +++ b/Frameworks/g719/g719.xcodeproj/project.pbxproj @@ -234,6 +234,7 @@ TargetAttributes = { 83D7311B1A74968900CA1366 = { CreatedOnToolsVersion = 6.1.1; + DevelopmentTeam = N6E749HJ2X; }; }; }; @@ -348,7 +349,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; + MACOSX_DEPLOYMENT_TARGET = 10.8; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -398,7 +399,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; + MACOSX_DEPLOYMENT_TARGET = 10.8; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; VERSIONING_SYSTEM = "apple-generic"; @@ -409,8 +410,10 @@ 83D731331A74968900CA1366 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = N6E749HJ2X; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@loader_path/Frameworks"; @@ -436,9 +439,10 @@ 83D731341A74968900CA1366 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = N6E749HJ2X; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@loader_path/Frameworks"; diff --git a/Frameworks/g7221/g7221.xcodeproj/project.pbxproj b/Frameworks/g7221/g7221.xcodeproj/project.pbxproj deleted file mode 100644 index 5d6d7b72d..000000000 --- a/Frameworks/g7221/g7221.xcodeproj/project.pbxproj +++ /dev/null @@ -1,374 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 83D730FF1A738F4E00CA1366 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 83D730F21A738F4E00CA1366 /* common.c */; }; - 83D731001A738F4E00CA1366 /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D730F31A738F4E00CA1366 /* common.h */; }; - 83D731011A738F4E00CA1366 /* dct4.c in Sources */ = {isa = PBXBuildFile; fileRef = 83D730F41A738F4E00CA1366 /* dct4.c */; }; - 83D731021A738F4E00CA1366 /* dct4.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D730F51A738F4E00CA1366 /* dct4.h */; }; - 83D731031A738F4E00CA1366 /* decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83D730F61A738F4E00CA1366 /* decoder.c */; }; - 83D731041A738F4E00CA1366 /* decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D730F71A738F4E00CA1366 /* decoder.h */; }; - 83D731051A738F4E00CA1366 /* huffman.c in Sources */ = {isa = PBXBuildFile; fileRef = 83D730F81A738F4E00CA1366 /* huffman.c */; }; - 83D731061A738F4E00CA1366 /* huffman.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D730F91A738F4E00CA1366 /* huffman.h */; }; - 83D731071A738F4E00CA1366 /* huffman_consts.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D730FA1A738F4E00CA1366 /* huffman_consts.h */; }; - 83D731081A738F4E00CA1366 /* rmlt.c in Sources */ = {isa = PBXBuildFile; fileRef = 83D730FB1A738F4E00CA1366 /* rmlt.c */; }; - 83D731091A738F4E00CA1366 /* rmlt.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D730FC1A738F4E00CA1366 /* rmlt.h */; }; - 83D7310A1A738F4E00CA1366 /* siren7.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D730FD1A738F4E00CA1366 /* siren7.h */; }; - 83D7310B1A738F4E00CA1366 /* g7221.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D730FE1A738F4E00CA1366 /* g7221.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 83D7310D1A738F8500CA1366 /* g7221.c in Sources */ = {isa = PBXBuildFile; fileRef = 83D7310C1A738F8500CA1366 /* g7221.c */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 83D730C91A738EB200CA1366 /* g7221.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = g7221.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 83D730CD1A738EB200CA1366 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 83D730F21A738F4E00CA1366 /* common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = common.c; sourceTree = ""; }; - 83D730F31A738F4E00CA1366 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; - 83D730F41A738F4E00CA1366 /* dct4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dct4.c; sourceTree = ""; }; - 83D730F51A738F4E00CA1366 /* dct4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dct4.h; sourceTree = ""; }; - 83D730F61A738F4E00CA1366 /* decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = decoder.c; sourceTree = ""; }; - 83D730F71A738F4E00CA1366 /* decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = decoder.h; sourceTree = ""; }; - 83D730F81A738F4E00CA1366 /* huffman.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = huffman.c; sourceTree = ""; }; - 83D730F91A738F4E00CA1366 /* huffman.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = huffman.h; sourceTree = ""; }; - 83D730FA1A738F4E00CA1366 /* huffman_consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = huffman_consts.h; sourceTree = ""; }; - 83D730FB1A738F4E00CA1366 /* rmlt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rmlt.c; sourceTree = ""; }; - 83D730FC1A738F4E00CA1366 /* rmlt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rmlt.h; sourceTree = ""; }; - 83D730FD1A738F4E00CA1366 /* siren7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = siren7.h; sourceTree = ""; }; - 83D730FE1A738F4E00CA1366 /* g7221.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g7221.h; sourceTree = ""; }; - 83D7310C1A738F8500CA1366 /* g7221.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g7221.c; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 83D730C51A738EB200CA1366 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 83D730BF1A738EB200CA1366 = { - isa = PBXGroup; - children = ( - 83D730CB1A738EB200CA1366 /* g7221 */, - 83D730CA1A738EB200CA1366 /* Products */, - ); - sourceTree = ""; - }; - 83D730CA1A738EB200CA1366 /* Products */ = { - isa = PBXGroup; - children = ( - 83D730C91A738EB200CA1366 /* g7221.framework */, - ); - name = Products; - sourceTree = ""; - }; - 83D730CB1A738EB200CA1366 /* g7221 */ = { - isa = PBXGroup; - children = ( - 83D730F11A738F4E00CA1366 /* libsiren */, - 83D730FE1A738F4E00CA1366 /* g7221.h */, - 83D730CC1A738EB200CA1366 /* Supporting Files */, - 83D7310C1A738F8500CA1366 /* g7221.c */, - ); - path = g7221; - sourceTree = ""; - }; - 83D730CC1A738EB200CA1366 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 83D730CD1A738EB200CA1366 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 83D730F11A738F4E00CA1366 /* libsiren */ = { - isa = PBXGroup; - children = ( - 83D730F21A738F4E00CA1366 /* common.c */, - 83D730F31A738F4E00CA1366 /* common.h */, - 83D730F41A738F4E00CA1366 /* dct4.c */, - 83D730F51A738F4E00CA1366 /* dct4.h */, - 83D730F61A738F4E00CA1366 /* decoder.c */, - 83D730F71A738F4E00CA1366 /* decoder.h */, - 83D730F81A738F4E00CA1366 /* huffman.c */, - 83D730F91A738F4E00CA1366 /* huffman.h */, - 83D730FA1A738F4E00CA1366 /* huffman_consts.h */, - 83D730FB1A738F4E00CA1366 /* rmlt.c */, - 83D730FC1A738F4E00CA1366 /* rmlt.h */, - 83D730FD1A738F4E00CA1366 /* siren7.h */, - ); - path = libsiren; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 83D730C61A738EB200CA1366 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 83D7310B1A738F4E00CA1366 /* g7221.h in Headers */, - 83D731061A738F4E00CA1366 /* huffman.h in Headers */, - 83D7310A1A738F4E00CA1366 /* siren7.h in Headers */, - 83D731071A738F4E00CA1366 /* huffman_consts.h in Headers */, - 83D731001A738F4E00CA1366 /* common.h in Headers */, - 83D731041A738F4E00CA1366 /* decoder.h in Headers */, - 83D731021A738F4E00CA1366 /* dct4.h in Headers */, - 83D731091A738F4E00CA1366 /* rmlt.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 83D730C81A738EB200CA1366 /* g7221 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 83D730DF1A738EB200CA1366 /* Build configuration list for PBXNativeTarget "g7221" */; - buildPhases = ( - 83D730C41A738EB200CA1366 /* Sources */, - 83D730C51A738EB200CA1366 /* Frameworks */, - 83D730C61A738EB200CA1366 /* Headers */, - 83D730C71A738EB200CA1366 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = g7221; - productName = g7221; - productReference = 83D730C91A738EB200CA1366 /* g7221.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 83D730C01A738EB200CA1366 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1020; - ORGANIZATIONNAME = "Christopher Snowhill"; - TargetAttributes = { - 83D730C81A738EB200CA1366 = { - CreatedOnToolsVersion = 6.1.1; - }; - }; - }; - buildConfigurationList = 83D730C31A738EB200CA1366 /* Build configuration list for PBXProject "g7221" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 83D730BF1A738EB200CA1366; - productRefGroup = 83D730CA1A738EB200CA1366 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 83D730C81A738EB200CA1366 /* g7221 */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 83D730C71A738EB200CA1366 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 83D730C41A738EB200CA1366 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 83D731081A738F4E00CA1366 /* rmlt.c in Sources */, - 83D731011A738F4E00CA1366 /* dct4.c in Sources */, - 83D731031A738F4E00CA1366 /* decoder.c in Sources */, - 83D7310D1A738F8500CA1366 /* g7221.c in Sources */, - 83D730FF1A738F4E00CA1366 /* common.c in Sources */, - 83D731051A738F4E00CA1366 /* huffman.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 83D730DD1A738EB200CA1366 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 83D730DE1A738EB200CA1366 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 83D730E01A738EB200CA1366 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@loader_path/Frameworks"; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = g7221/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cogx.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 83D730E11A738EB200CA1366 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - COMBINE_HIDPI_IMAGES = YES; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@loader_path/Frameworks"; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = g7221/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cogx.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 83D730C31A738EB200CA1366 /* Build configuration list for PBXProject "g7221" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 83D730DD1A738EB200CA1366 /* Debug */, - 83D730DE1A738EB200CA1366 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 83D730DF1A738EB200CA1366 /* Build configuration list for PBXNativeTarget "g7221" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 83D730E01A738EB200CA1366 /* Debug */, - 83D730E11A738EB200CA1366 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 83D730C01A738EB200CA1366 /* Project object */; -} diff --git a/Frameworks/g7221/g7221.xcodeproj/xcshareddata/xcschemes/g7221.xcscheme b/Frameworks/g7221/g7221.xcodeproj/xcshareddata/xcschemes/g7221.xcscheme deleted file mode 100644 index 11a2495f3..000000000 --- a/Frameworks/g7221/g7221.xcodeproj/xcshareddata/xcschemes/g7221.xcscheme +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Frameworks/libatrac9/libatrac9 b/Frameworks/libatrac9/libatrac9 new file mode 160000 index 000000000..6a9e00f6c --- /dev/null +++ b/Frameworks/libatrac9/libatrac9 @@ -0,0 +1 @@ +Subproject commit 6a9e00f6c7abd74d037fd210b6670d3cdb313049 diff --git a/Frameworks/libatrac9/libatrac9/Info.plist b/Frameworks/libatrac9/libatrac9-Info.plist similarity index 84% rename from Frameworks/libatrac9/libatrac9/Info.plist rename to Frameworks/libatrac9/libatrac9-Info.plist index a351796f3..6a8539a5d 100644 --- a/Frameworks/libatrac9/libatrac9/Info.plist +++ b/Frameworks/libatrac9/libatrac9-Info.plist @@ -13,14 +13,12 @@ CFBundleName $(PRODUCT_NAME) CFBundlePackageType - FMWK + $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString 1.0 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSHumanReadableCopyright - Copyright © 2018 Christopher Snowhill. All rights reserved. - NSPrincipalClass - + Copyright © 2020 Christopher Snowhill. All rights reserved. diff --git a/Frameworks/libatrac9/libatrac9.xcodeproj/project.pbxproj b/Frameworks/libatrac9/libatrac9.xcodeproj/project.pbxproj index e10d6edf2..2ae39e266 100644 --- a/Frameworks/libatrac9/libatrac9.xcodeproj/project.pbxproj +++ b/Frameworks/libatrac9/libatrac9.xcodeproj/project.pbxproj @@ -3,75 +3,76 @@ archiveVersion = 1; classes = { }; - objectVersion = 48; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ - 830EBDF020045FF80023AA10 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDB920045FF80023AA10 /* tables.c */; }; - 830EBDF120045FF80023AA10 /* libatrac9.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDBA20045FF80023AA10 /* libatrac9.c */; }; - 830EBDF220045FF80023AA10 /* huffCodes.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDBB20045FF80023AA10 /* huffCodes.c */; }; - 830EBDF320045FF80023AA10 /* imdct.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDBC20045FF80023AA10 /* imdct.c */; }; - 830EBDF420045FF80023AA10 /* scale_factors.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDBD20045FF80023AA10 /* scale_factors.h */; }; - 830EBDF520045FF80023AA10 /* utility.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDBE20045FF80023AA10 /* utility.c */; }; - 830EBDF620045FF80023AA10 /* quantization.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDBF20045FF80023AA10 /* quantization.h */; }; - 830EBDF720045FF80023AA10 /* band_extension.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDC020045FF80023AA10 /* band_extension.c */; }; - 830EBDF820045FF80023AA10 /* unpack.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDC120045FF80023AA10 /* unpack.c */; }; - 830EBDF920045FF80023AA10 /* bit_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDC220045FF80023AA10 /* bit_reader.h */; }; - 830EBDFA20045FF80023AA10 /* decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDC320045FF80023AA10 /* decoder.h */; }; - 830EBDFB20045FF80023AA10 /* decinit.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDC420045FF80023AA10 /* decinit.c */; }; - 830EBDFC20045FF80023AA10 /* bit_allocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDC520045FF80023AA10 /* bit_allocation.h */; }; - 830EBDFE20045FF80023AA10 /* libatrac9.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDC720045FF80023AA10 /* libatrac9.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 830EBDFF20045FF80023AA10 /* tables.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDC820045FF80023AA10 /* tables.h */; }; - 830EBE0020045FF80023AA10 /* scale_factors.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDC920045FF80023AA10 /* scale_factors.c */; }; - 830EBE0120045FF80023AA10 /* error_codes.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDCA20045FF80023AA10 /* error_codes.h */; }; - 830EBE0220045FF80023AA10 /* imdct.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDCB20045FF80023AA10 /* imdct.h */; }; - 830EBE0420045FF80023AA10 /* huffCodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDCD20045FF80023AA10 /* huffCodes.h */; }; - 830EBE0520045FF80023AA10 /* decinit.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDCE20045FF80023AA10 /* decinit.h */; }; - 830EBE0620045FF80023AA10 /* decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDCF20045FF80023AA10 /* decoder.c */; }; - 830EBE0720045FF80023AA10 /* bit_reader.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDD020045FF80023AA10 /* bit_reader.c */; }; - 830EBE0820045FF80023AA10 /* unpack.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDD120045FF80023AA10 /* unpack.h */; }; - 830EBE0A20045FF80023AA10 /* quantization.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDD320045FF80023AA10 /* quantization.c */; }; - 830EBE0B20045FF80023AA10 /* utility.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDD420045FF80023AA10 /* utility.h */; }; - 830EBE0C20045FF80023AA10 /* band_extension.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDD520045FF80023AA10 /* band_extension.h */; }; - 830EBE0D20045FF80023AA10 /* bit_allocation.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBDD620045FF80023AA10 /* bit_allocation.c */; }; - 830EBE0E20045FF80023AA10 /* structures.h in Headers */ = {isa = PBXBuildFile; fileRef = 830EBDD720045FF80023AA10 /* structures.h */; }; + 835FC6E523F62B0F006960FA /* structures.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6C923F62B0E006960FA /* structures.h */; }; + 835FC6E623F62B0F006960FA /* bit_reader.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6CA23F62B0E006960FA /* bit_reader.c */; }; + 835FC6E723F62B0F006960FA /* quantization.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6CB23F62B0E006960FA /* quantization.c */; }; + 835FC6E823F62B0F006960FA /* decinit.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6CC23F62B0E006960FA /* decinit.c */; }; + 835FC6E923F62B0F006960FA /* libatrac9.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6CD23F62B0E006960FA /* libatrac9.c */; }; + 835FC6EA23F62B0F006960FA /* imdct.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6CE23F62B0E006960FA /* imdct.c */; }; + 835FC6EB23F62B0F006960FA /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6CF23F62B0E006960FA /* tables.c */; }; + 835FC6EC23F62B0F006960FA /* decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6D023F62B0E006960FA /* decoder.h */; }; + 835FC6ED23F62B0F006960FA /* scale_factors.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6D123F62B0E006960FA /* scale_factors.h */; }; + 835FC6EE23F62B0F006960FA /* libatrac9.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6D223F62B0E006960FA /* libatrac9.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 835FC6EF23F62B0F006960FA /* scale_factors.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6D323F62B0E006960FA /* scale_factors.c */; }; + 835FC6F023F62B0F006960FA /* decinit.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6D423F62B0F006960FA /* decinit.h */; }; + 835FC6F123F62B0F006960FA /* imdct.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6D523F62B0F006960FA /* imdct.h */; }; + 835FC6F223F62B0F006960FA /* bit_allocation.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6D623F62B0F006960FA /* bit_allocation.c */; }; + 835FC6F323F62B0F006960FA /* utility.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6D723F62B0F006960FA /* utility.h */; }; + 835FC6F423F62B0F006960FA /* unpack.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6D823F62B0F006960FA /* unpack.h */; }; + 835FC6F523F62B0F006960FA /* huffCodes.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6D923F62B0F006960FA /* huffCodes.c */; }; + 835FC6F623F62B0F006960FA /* quantization.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6DA23F62B0F006960FA /* quantization.h */; }; + 835FC6F723F62B0F006960FA /* decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6DB23F62B0F006960FA /* decoder.c */; }; + 835FC6F823F62B0F006960FA /* band_extension.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6DC23F62B0F006960FA /* band_extension.h */; }; + 835FC6F923F62B0F006960FA /* band_extension.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6DD23F62B0F006960FA /* band_extension.c */; }; + 835FC6FA23F62B0F006960FA /* unpack.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6DE23F62B0F006960FA /* unpack.c */; }; + 835FC6FB23F62B0F006960FA /* bit_allocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6DF23F62B0F006960FA /* bit_allocation.h */; }; + 835FC6FC23F62B0F006960FA /* tables.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6E023F62B0F006960FA /* tables.h */; }; + 835FC6FD23F62B0F006960FA /* utility.c in Sources */ = {isa = PBXBuildFile; fileRef = 835FC6E123F62B0F006960FA /* utility.c */; }; + 835FC6FE23F62B0F006960FA /* bit_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6E223F62B0F006960FA /* bit_reader.h */; }; + 835FC6FF23F62B0F006960FA /* error_codes.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6E323F62B0F006960FA /* error_codes.h */; }; + 835FC70023F62B0F006960FA /* huffCodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 835FC6E423F62B0F006960FA /* huffCodes.h */; }; + 836C052423F62E9300FA07C7 /* libatrac9-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 836C052323F62E9200FA07C7 /* libatrac9-Info.plist */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 830EBD8720045F190023AA10 /* libatrac9.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libatrac9.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 830EBD8B20045F190023AA10 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 830EBDB920045FF80023AA10 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tables.c; sourceTree = ""; }; - 830EBDBA20045FF80023AA10 /* libatrac9.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libatrac9.c; sourceTree = ""; }; - 830EBDBB20045FF80023AA10 /* huffCodes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = huffCodes.c; sourceTree = ""; }; - 830EBDBC20045FF80023AA10 /* imdct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = imdct.c; sourceTree = ""; }; - 830EBDBD20045FF80023AA10 /* scale_factors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scale_factors.h; sourceTree = ""; }; - 830EBDBE20045FF80023AA10 /* utility.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utility.c; sourceTree = ""; }; - 830EBDBF20045FF80023AA10 /* quantization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = quantization.h; sourceTree = ""; }; - 830EBDC020045FF80023AA10 /* band_extension.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = band_extension.c; sourceTree = ""; }; - 830EBDC120045FF80023AA10 /* unpack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unpack.c; sourceTree = ""; }; - 830EBDC220045FF80023AA10 /* bit_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bit_reader.h; sourceTree = ""; }; - 830EBDC320045FF80023AA10 /* decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = decoder.h; sourceTree = ""; }; - 830EBDC420045FF80023AA10 /* decinit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = decinit.c; sourceTree = ""; }; - 830EBDC520045FF80023AA10 /* bit_allocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bit_allocation.h; sourceTree = ""; }; - 830EBDC720045FF80023AA10 /* libatrac9.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libatrac9.h; sourceTree = ""; }; - 830EBDC820045FF80023AA10 /* tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tables.h; sourceTree = ""; }; - 830EBDC920045FF80023AA10 /* scale_factors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scale_factors.c; sourceTree = ""; }; - 830EBDCA20045FF80023AA10 /* error_codes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error_codes.h; sourceTree = ""; }; - 830EBDCB20045FF80023AA10 /* imdct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imdct.h; sourceTree = ""; }; - 830EBDCD20045FF80023AA10 /* huffCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = huffCodes.h; sourceTree = ""; }; - 830EBDCE20045FF80023AA10 /* decinit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = decinit.h; sourceTree = ""; }; - 830EBDCF20045FF80023AA10 /* decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = decoder.c; sourceTree = ""; }; - 830EBDD020045FF80023AA10 /* bit_reader.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bit_reader.c; sourceTree = ""; }; - 830EBDD120045FF80023AA10 /* unpack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unpack.h; sourceTree = ""; }; - 830EBDD320045FF80023AA10 /* quantization.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = quantization.c; sourceTree = ""; }; - 830EBDD420045FF80023AA10 /* utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utility.h; sourceTree = ""; }; - 830EBDD520045FF80023AA10 /* band_extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = band_extension.h; sourceTree = ""; }; - 830EBDD620045FF80023AA10 /* bit_allocation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bit_allocation.c; sourceTree = ""; }; - 830EBDD720045FF80023AA10 /* structures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = structures.h; sourceTree = ""; }; + 835FC6B023F61BF0006960FA /* libatrac9.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libatrac9.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 835FC6C923F62B0E006960FA /* structures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = structures.h; path = C/src/structures.h; sourceTree = ""; }; + 835FC6CA23F62B0E006960FA /* bit_reader.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bit_reader.c; path = C/src/bit_reader.c; sourceTree = ""; }; + 835FC6CB23F62B0E006960FA /* quantization.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = quantization.c; path = C/src/quantization.c; sourceTree = ""; }; + 835FC6CC23F62B0E006960FA /* decinit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = decinit.c; path = C/src/decinit.c; sourceTree = ""; }; + 835FC6CD23F62B0E006960FA /* libatrac9.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = libatrac9.c; path = C/src/libatrac9.c; sourceTree = ""; }; + 835FC6CE23F62B0E006960FA /* imdct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = imdct.c; path = C/src/imdct.c; sourceTree = ""; }; + 835FC6CF23F62B0E006960FA /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tables.c; path = C/src/tables.c; sourceTree = ""; }; + 835FC6D023F62B0E006960FA /* decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = decoder.h; path = C/src/decoder.h; sourceTree = ""; }; + 835FC6D123F62B0E006960FA /* scale_factors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scale_factors.h; path = C/src/scale_factors.h; sourceTree = ""; }; + 835FC6D223F62B0E006960FA /* libatrac9.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = libatrac9.h; path = C/src/libatrac9.h; sourceTree = ""; }; + 835FC6D323F62B0E006960FA /* scale_factors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scale_factors.c; path = C/src/scale_factors.c; sourceTree = ""; }; + 835FC6D423F62B0F006960FA /* decinit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = decinit.h; path = C/src/decinit.h; sourceTree = ""; }; + 835FC6D523F62B0F006960FA /* imdct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imdct.h; path = C/src/imdct.h; sourceTree = ""; }; + 835FC6D623F62B0F006960FA /* bit_allocation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bit_allocation.c; path = C/src/bit_allocation.c; sourceTree = ""; }; + 835FC6D723F62B0F006960FA /* utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utility.h; path = C/src/utility.h; sourceTree = ""; }; + 835FC6D823F62B0F006960FA /* unpack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unpack.h; path = C/src/unpack.h; sourceTree = ""; }; + 835FC6D923F62B0F006960FA /* huffCodes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = huffCodes.c; path = C/src/huffCodes.c; sourceTree = ""; }; + 835FC6DA23F62B0F006960FA /* quantization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = quantization.h; path = C/src/quantization.h; sourceTree = ""; }; + 835FC6DB23F62B0F006960FA /* decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = decoder.c; path = C/src/decoder.c; sourceTree = ""; }; + 835FC6DC23F62B0F006960FA /* band_extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = band_extension.h; path = C/src/band_extension.h; sourceTree = ""; }; + 835FC6DD23F62B0F006960FA /* band_extension.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = band_extension.c; path = C/src/band_extension.c; sourceTree = ""; }; + 835FC6DE23F62B0F006960FA /* unpack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = unpack.c; path = C/src/unpack.c; sourceTree = ""; }; + 835FC6DF23F62B0F006960FA /* bit_allocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bit_allocation.h; path = C/src/bit_allocation.h; sourceTree = ""; }; + 835FC6E023F62B0F006960FA /* tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tables.h; path = C/src/tables.h; sourceTree = ""; }; + 835FC6E123F62B0F006960FA /* utility.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = utility.c; path = C/src/utility.c; sourceTree = ""; }; + 835FC6E223F62B0F006960FA /* bit_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bit_reader.h; path = C/src/bit_reader.h; sourceTree = ""; }; + 835FC6E323F62B0F006960FA /* error_codes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = error_codes.h; path = C/src/error_codes.h; sourceTree = ""; }; + 835FC6E423F62B0F006960FA /* huffCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = huffCodes.h; path = C/src/huffCodes.h; sourceTree = ""; }; + 836C052323F62E9200FA07C7 /* libatrac9-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "libatrac9-Info.plist"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 830EBD8320045F190023AA10 /* Frameworks */ = { + 835FC6AD23F61BF0006960FA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -81,110 +82,94 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 830EBD7D20045F190023AA10 = { + 835FC6A623F61BF0006960FA = { isa = PBXGroup; children = ( - 830EBD8920045F190023AA10 /* libatrac9 */, - 830EBD8820045F190023AA10 /* Products */, + 836C052323F62E9200FA07C7 /* libatrac9-Info.plist */, + 835FC6B223F61BF0006960FA /* libatrac9 */, + 835FC6B123F61BF0006960FA /* Products */, ); sourceTree = ""; }; - 830EBD8820045F190023AA10 /* Products */ = { + 835FC6B123F61BF0006960FA /* Products */ = { isa = PBXGroup; children = ( - 830EBD8720045F190023AA10 /* libatrac9.framework */, + 835FC6B023F61BF0006960FA /* libatrac9.framework */, ); name = Products; sourceTree = ""; }; - 830EBD8920045F190023AA10 /* libatrac9 */ = { + 835FC6B223F61BF0006960FA /* libatrac9 */ = { isa = PBXGroup; children = ( - 830EBD9C20045FF80023AA10 /* LibAtrac9 */, - 830EBD8B20045F190023AA10 /* Info.plist */, + 835FC6DD23F62B0F006960FA /* band_extension.c */, + 835FC6DC23F62B0F006960FA /* band_extension.h */, + 835FC6D623F62B0F006960FA /* bit_allocation.c */, + 835FC6DF23F62B0F006960FA /* bit_allocation.h */, + 835FC6CA23F62B0E006960FA /* bit_reader.c */, + 835FC6E223F62B0F006960FA /* bit_reader.h */, + 835FC6CC23F62B0E006960FA /* decinit.c */, + 835FC6D423F62B0F006960FA /* decinit.h */, + 835FC6DB23F62B0F006960FA /* decoder.c */, + 835FC6D023F62B0E006960FA /* decoder.h */, + 835FC6E323F62B0F006960FA /* error_codes.h */, + 835FC6D923F62B0F006960FA /* huffCodes.c */, + 835FC6E423F62B0F006960FA /* huffCodes.h */, + 835FC6CE23F62B0E006960FA /* imdct.c */, + 835FC6D523F62B0F006960FA /* imdct.h */, + 835FC6CD23F62B0E006960FA /* libatrac9.c */, + 835FC6D223F62B0E006960FA /* libatrac9.h */, + 835FC6CB23F62B0E006960FA /* quantization.c */, + 835FC6DA23F62B0F006960FA /* quantization.h */, + 835FC6D323F62B0E006960FA /* scale_factors.c */, + 835FC6D123F62B0E006960FA /* scale_factors.h */, + 835FC6C923F62B0E006960FA /* structures.h */, + 835FC6CF23F62B0E006960FA /* tables.c */, + 835FC6E023F62B0F006960FA /* tables.h */, + 835FC6DE23F62B0F006960FA /* unpack.c */, + 835FC6D823F62B0F006960FA /* unpack.h */, + 835FC6E123F62B0F006960FA /* utility.c */, + 835FC6D723F62B0F006960FA /* utility.h */, ); path = libatrac9; sourceTree = ""; }; - 830EBD9C20045FF80023AA10 /* LibAtrac9 */ = { - isa = PBXGroup; - children = ( - 830EBDB820045FF80023AA10 /* C */, - ); - path = LibAtrac9; - sourceTree = ""; - }; - 830EBDB820045FF80023AA10 /* C */ = { - isa = PBXGroup; - children = ( - 830EBDC020045FF80023AA10 /* band_extension.c */, - 830EBDD520045FF80023AA10 /* band_extension.h */, - 830EBDD620045FF80023AA10 /* bit_allocation.c */, - 830EBDC520045FF80023AA10 /* bit_allocation.h */, - 830EBDD020045FF80023AA10 /* bit_reader.c */, - 830EBDC220045FF80023AA10 /* bit_reader.h */, - 830EBDC420045FF80023AA10 /* decinit.c */, - 830EBDCE20045FF80023AA10 /* decinit.h */, - 830EBDCF20045FF80023AA10 /* decoder.c */, - 830EBDC320045FF80023AA10 /* decoder.h */, - 830EBDCA20045FF80023AA10 /* error_codes.h */, - 830EBDBB20045FF80023AA10 /* huffCodes.c */, - 830EBDCD20045FF80023AA10 /* huffCodes.h */, - 830EBDBC20045FF80023AA10 /* imdct.c */, - 830EBDCB20045FF80023AA10 /* imdct.h */, - 830EBDBA20045FF80023AA10 /* libatrac9.c */, - 830EBDC720045FF80023AA10 /* libatrac9.h */, - 830EBDD320045FF80023AA10 /* quantization.c */, - 830EBDBF20045FF80023AA10 /* quantization.h */, - 830EBDC920045FF80023AA10 /* scale_factors.c */, - 830EBDBD20045FF80023AA10 /* scale_factors.h */, - 830EBDD720045FF80023AA10 /* structures.h */, - 830EBDB920045FF80023AA10 /* tables.c */, - 830EBDC820045FF80023AA10 /* tables.h */, - 830EBDC120045FF80023AA10 /* unpack.c */, - 830EBDD120045FF80023AA10 /* unpack.h */, - 830EBDBE20045FF80023AA10 /* utility.c */, - 830EBDD420045FF80023AA10 /* utility.h */, - ); - path = C; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 830EBD8420045F190023AA10 /* Headers */ = { + 835FC6AB23F61BF0006960FA /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 830EBDFE20045FF80023AA10 /* libatrac9.h in Headers */, - 830EBE0220045FF80023AA10 /* imdct.h in Headers */, - 830EBE0520045FF80023AA10 /* decinit.h in Headers */, - 830EBE0420045FF80023AA10 /* huffCodes.h in Headers */, - 830EBE0B20045FF80023AA10 /* utility.h in Headers */, - 830EBE0820045FF80023AA10 /* unpack.h in Headers */, - 830EBDF420045FF80023AA10 /* scale_factors.h in Headers */, - 830EBE0C20045FF80023AA10 /* band_extension.h in Headers */, - 830EBE0120045FF80023AA10 /* error_codes.h in Headers */, - 830EBDFA20045FF80023AA10 /* decoder.h in Headers */, - 830EBDFF20045FF80023AA10 /* tables.h in Headers */, - 830EBDF920045FF80023AA10 /* bit_reader.h in Headers */, - 830EBE0E20045FF80023AA10 /* structures.h in Headers */, - 830EBDFC20045FF80023AA10 /* bit_allocation.h in Headers */, - 830EBDF620045FF80023AA10 /* quantization.h in Headers */, + 835FC6EE23F62B0F006960FA /* libatrac9.h in Headers */, + 835FC6F423F62B0F006960FA /* unpack.h in Headers */, + 835FC6FC23F62B0F006960FA /* tables.h in Headers */, + 835FC6F823F62B0F006960FA /* band_extension.h in Headers */, + 835FC6F123F62B0F006960FA /* imdct.h in Headers */, + 835FC6FB23F62B0F006960FA /* bit_allocation.h in Headers */, + 835FC6FE23F62B0F006960FA /* bit_reader.h in Headers */, + 835FC6F023F62B0F006960FA /* decinit.h in Headers */, + 835FC70023F62B0F006960FA /* huffCodes.h in Headers */, + 835FC6E523F62B0F006960FA /* structures.h in Headers */, + 835FC6ED23F62B0F006960FA /* scale_factors.h in Headers */, + 835FC6FF23F62B0F006960FA /* error_codes.h in Headers */, + 835FC6F323F62B0F006960FA /* utility.h in Headers */, + 835FC6F623F62B0F006960FA /* quantization.h in Headers */, + 835FC6EC23F62B0F006960FA /* decoder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 830EBD8620045F190023AA10 /* libatrac9 */ = { + 835FC6AF23F61BF0006960FA /* libatrac9 */ = { isa = PBXNativeTarget; - buildConfigurationList = 830EBD8F20045F190023AA10 /* Build configuration list for PBXNativeTarget "libatrac9" */; + buildConfigurationList = 835FC6B823F61BF0006960FA /* Build configuration list for PBXNativeTarget "libatrac9" */; buildPhases = ( - 830EBD8220045F190023AA10 /* Sources */, - 830EBD8320045F190023AA10 /* Frameworks */, - 830EBD8420045F190023AA10 /* Headers */, - 830EBD8520045F190023AA10 /* Resources */, + 835FC6AB23F61BF0006960FA /* Headers */, + 835FC6AC23F61BF0006960FA /* Sources */, + 835FC6AD23F61BF0006960FA /* Frameworks */, + 835FC6AE23F61BF0006960FA /* Resources */, ); buildRules = ( ); @@ -192,77 +177,77 @@ ); name = libatrac9; productName = libatrac9; - productReference = 830EBD8720045F190023AA10 /* libatrac9.framework */; + productReference = 835FC6B023F61BF0006960FA /* libatrac9.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 830EBD7E20045F190023AA10 /* Project object */ = { + 835FC6A723F61BF0006960FA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0940; + LastUpgradeCheck = 1130; ORGANIZATIONNAME = "Christopher Snowhill"; TargetAttributes = { - 830EBD8620045F190023AA10 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; + 835FC6AF23F61BF0006960FA = { + CreatedOnToolsVersion = 11.3.1; }; }; }; - buildConfigurationList = 830EBD8120045F190023AA10 /* Build configuration list for PBXProject "libatrac9" */; - compatibilityVersion = "Xcode 8.0"; + buildConfigurationList = 835FC6AA23F61BF0006960FA /* Build configuration list for PBXProject "libatrac9" */; + compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); - mainGroup = 830EBD7D20045F190023AA10; - productRefGroup = 830EBD8820045F190023AA10 /* Products */; + mainGroup = 835FC6A623F61BF0006960FA; + productRefGroup = 835FC6B123F61BF0006960FA /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 830EBD8620045F190023AA10 /* libatrac9 */, + 835FC6AF23F61BF0006960FA /* libatrac9 */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 830EBD8520045F190023AA10 /* Resources */ = { + 835FC6AE23F61BF0006960FA /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 836C052423F62E9300FA07C7 /* libatrac9-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 830EBD8220045F190023AA10 /* Sources */ = { + 835FC6AC23F61BF0006960FA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 830EBE0620045FF80023AA10 /* decoder.c in Sources */, - 830EBDF720045FF80023AA10 /* band_extension.c in Sources */, - 830EBE0020045FF80023AA10 /* scale_factors.c in Sources */, - 830EBDF520045FF80023AA10 /* utility.c in Sources */, - 830EBDFB20045FF80023AA10 /* decinit.c in Sources */, - 830EBE0720045FF80023AA10 /* bit_reader.c in Sources */, - 830EBE0A20045FF80023AA10 /* quantization.c in Sources */, - 830EBDF820045FF80023AA10 /* unpack.c in Sources */, - 830EBDF020045FF80023AA10 /* tables.c in Sources */, - 830EBDF320045FF80023AA10 /* imdct.c in Sources */, - 830EBDF220045FF80023AA10 /* huffCodes.c in Sources */, - 830EBDF120045FF80023AA10 /* libatrac9.c in Sources */, - 830EBE0D20045FF80023AA10 /* bit_allocation.c in Sources */, + 835FC6FD23F62B0F006960FA /* utility.c in Sources */, + 835FC6F723F62B0F006960FA /* decoder.c in Sources */, + 835FC6EB23F62B0F006960FA /* tables.c in Sources */, + 835FC6EA23F62B0F006960FA /* imdct.c in Sources */, + 835FC6FA23F62B0F006960FA /* unpack.c in Sources */, + 835FC6E723F62B0F006960FA /* quantization.c in Sources */, + 835FC6EF23F62B0F006960FA /* scale_factors.c in Sources */, + 835FC6E823F62B0F006960FA /* decinit.c in Sources */, + 835FC6F223F62B0F006960FA /* bit_allocation.c in Sources */, + 835FC6E623F62B0F006960FA /* bit_reader.c in Sources */, + 835FC6F923F62B0F006960FA /* band_extension.c in Sources */, + 835FC6F523F62B0F006960FA /* huffCodes.c in Sources */, + 835FC6E923F62B0F006960FA /* libatrac9.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ - 830EBD8D20045F190023AA10 /* Debug */ = { + 835FC6B623F61BF0006960FA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -272,6 +257,7 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; @@ -293,7 +279,6 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Mac Developer"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; @@ -313,9 +298,9 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INSTALL_PATH = "@loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; VERSIONING_SYSTEM = "apple-generic"; @@ -323,7 +308,7 @@ }; name = Debug; }; - 830EBD8E20045F190023AA10 /* Release */ = { + 835FC6B723F61BF0006960FA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -333,6 +318,7 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; @@ -354,7 +340,6 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Mac Developer"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -368,53 +353,59 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INSTALL_PATH = "@loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; + MACOSX_DEPLOYMENT_TARGET = 10.8; MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; SDKROOT = macosx; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; - 830EBD9020045F190023AA10 /* Debug */ = { + 835FC6B923F61BF0006960FA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; - FRAMEWORK_VERSION = A; - HEADER_SEARCH_PATHS = libatrac9/LibAtrac9/C; - INFOPLIST_FILE = libatrac9/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.7; - PRODUCT_BUNDLE_IDENTIFIER = net.kode54.libatrac9; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = libatrac9-Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.losno.libatrac9; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; }; name = Debug; }; - 830EBD9120045F190023AA10 /* Release */ = { + 835FC6BA23F61BF0006960FA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; - FRAMEWORK_VERSION = A; - HEADER_SEARCH_PATHS = libatrac9/LibAtrac9/C; - INFOPLIST_FILE = libatrac9/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.7; - PRODUCT_BUNDLE_IDENTIFIER = net.kode54.libatrac9; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = libatrac9-Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.losno.libatrac9; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; }; name = Release; @@ -422,25 +413,25 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 830EBD8120045F190023AA10 /* Build configuration list for PBXProject "libatrac9" */ = { + 835FC6AA23F61BF0006960FA /* Build configuration list for PBXProject "libatrac9" */ = { isa = XCConfigurationList; buildConfigurations = ( - 830EBD8D20045F190023AA10 /* Debug */, - 830EBD8E20045F190023AA10 /* Release */, + 835FC6B623F61BF0006960FA /* Debug */, + 835FC6B723F61BF0006960FA /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 830EBD8F20045F190023AA10 /* Build configuration list for PBXNativeTarget "libatrac9" */ = { + 835FC6B823F61BF0006960FA /* Build configuration list for PBXNativeTarget "libatrac9" */ = { isa = XCConfigurationList; buildConfigurations = ( - 830EBD9020045F190023AA10 /* Debug */, - 830EBD9120045F190023AA10 /* Release */, + 835FC6B923F61BF0006960FA /* Debug */, + 835FC6BA23F61BF0006960FA /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 830EBD7E20045F190023AA10 /* Project object */; + rootObject = 835FC6A723F61BF0006960FA /* Project object */; } diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/.gitattributes b/Frameworks/libatrac9/libatrac9/LibAtrac9/.gitattributes deleted file mode 100644 index 1ff0c4230..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/.gitattributes +++ /dev/null @@ -1,63 +0,0 @@ -############################################################################### -# Set default behavior to automatically normalize line endings. -############################################################################### -* text=auto - -############################################################################### -# Set default behavior for command prompt diff. -# -# This is need for earlier builds of msysgit that does not have it on by -# default for csharp files. -# Note: This is only used by command line -############################################################################### -#*.cs diff=csharp - -############################################################################### -# Set the merge driver for project and solution files -# -# Merging from the command prompt will add diff markers to the files if there -# are conflicts (Merging from VS is not affected by the settings below, in VS -# the diff markers are never inserted). Diff markers may cause the following -# file extensions to fail to load in VS. An alternative would be to treat -# these files as binary and thus will always conflict and require user -# intervention with every merge. To do so, just uncomment the entries below -############################################################################### -#*.sln merge=binary -#*.csproj merge=binary -#*.vbproj merge=binary -#*.vcxproj merge=binary -#*.vcproj merge=binary -#*.dbproj merge=binary -#*.fsproj merge=binary -#*.lsproj merge=binary -#*.wixproj merge=binary -#*.modelproj merge=binary -#*.sqlproj merge=binary -#*.wwaproj merge=binary - -############################################################################### -# behavior for image files -# -# image files are treated as binary by default. -############################################################################### -#*.jpg binary -#*.png binary -#*.gif binary - -############################################################################### -# diff behavior for common document formats -# -# Convert binary document formats to text before diffing them. This feature -# is only available from the command line. Turn it on by uncommenting the -# entries below. -############################################################################### -#*.doc diff=astextplain -#*.DOC diff=astextplain -#*.docx diff=astextplain -#*.DOCX diff=astextplain -#*.dot diff=astextplain -#*.DOT diff=astextplain -#*.pdf diff=astextplain -#*.PDF diff=astextplain -#*.rtf diff=astextplain -#*.RTF diff=astextplain diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/.gitignore b/Frameworks/libatrac9/libatrac9/LibAtrac9/.gitignore deleted file mode 100644 index 3c4efe206..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/.gitignore +++ /dev/null @@ -1,261 +0,0 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# DNX -project.lock.json -project.fragment.lock.json -artifacts/ - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -#*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/packages/repositories.config -# NuGet v3's project.json files produces more ignoreable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -node_modules/ -orleans.codegen.cs - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush -.cr/ - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/band_extension.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/band_extension.c deleted file mode 100644 index 912c58848..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/band_extension.c +++ /dev/null @@ -1,191 +0,0 @@ -#include "band_extension.h" -#include "tables.h" -#include "utility.h" -#include - -void ApplyBandExtension(block* block) -{ - if (!block->BandExtensionEnabled || !block->HasExtensionData) return; - - for (int i = 0; i < block->ChannelCount; i++) - { - ApplyBandExtensionChannel(&block->Channels[i]); - } -} - -void ApplyBandExtensionChannel(channel* channel) -{ - const int groupAUnit = channel->Block->QuantizationUnitCount; - int* scaleFactors = channel->ScaleFactors; - double* spectra = channel->Spectra; - double scales[6]; - int* values = channel->BexValues; - - const bex_group* bex_info = &BexGroupInfo[channel->Block->QuantizationUnitCount - 13]; - const int bandCount = bex_info->band_count; - const int groupBUnit = bex_info->group_b_unit; - const int groupCUnit = bex_info->group_c_unit; - - const int totalUnits = max(groupCUnit, 22); - const int bexQuantUnits = totalUnits - groupAUnit; - - const int groupABin = QuantUnitToCoeffIndex[groupAUnit]; - const int groupBBin = QuantUnitToCoeffIndex[groupBUnit]; - const int groupCBin = QuantUnitToCoeffIndex[groupCUnit]; - const int totalBins = QuantUnitToCoeffIndex[totalUnits]; - - FillHighFrequencies(spectra, groupABin, groupBBin, groupCBin, totalBins); - - double groupAScale, groupBScale, groupCScale; - double rate, scale, mult; - - switch (channel->BexMode) - { - case 0: - switch (bandCount) - { - case 3: - scales[0] = BexMode0Bands3[0][values[0]]; - scales[1] = BexMode0Bands3[1][values[0]]; - scales[2] = BexMode0Bands3[2][values[1]]; - scales[3] = BexMode0Bands3[3][values[2]]; - scales[4] = BexMode0Bands3[4][values[3]]; - break; - case 4: - scales[0] = BexMode0Bands4[0][values[0]]; - scales[1] = BexMode0Bands4[1][values[0]]; - scales[2] = BexMode0Bands4[2][values[1]]; - scales[3] = BexMode0Bands4[3][values[2]]; - scales[4] = BexMode0Bands4[4][values[3]]; - break; - case 5: - scales[0] = BexMode0Bands5[0][values[0]]; - scales[1] = BexMode0Bands5[1][values[1]]; - scales[2] = BexMode0Bands5[2][values[1]]; - break; - } - - scales[bexQuantUnits - 1] = SpectrumScale[scaleFactors[groupAUnit]]; - - AddNoiseToSpectrum(channel, QuantUnitToCoeffIndex[totalUnits - 1], - QuantUnitToCoeffCount[totalUnits - 1]); - ScaleBexQuantUnits(spectra, scales, groupAUnit, totalUnits); - break; - case 1: - for (int i = groupAUnit; i < totalUnits; i++) - { - scales[i - groupAUnit] = SpectrumScale[scaleFactors[i]]; - } - - AddNoiseToSpectrum(channel, groupABin, totalBins - groupABin); - ScaleBexQuantUnits(spectra, scales, groupAUnit, totalUnits); - break; - case 2: - groupAScale = BexMode2Scale[values[0]]; - groupBScale = BexMode2Scale[values[1]]; - - for (int i = groupABin; i < groupBBin; i++) - { - spectra[i] *= groupAScale; - } - - for (int i = groupBBin; i < groupCBin; i++) - { - spectra[i] *= groupBScale; - } - return; - case 3: - rate = pow(2, BexMode3Rate[values[1]]); - scale = BexMode3Initial[values[0]]; - for (int i = groupABin; i < totalBins; i++) - { - scale *= rate; - spectra[i] *= scale; - } - return; - case 4: - mult = BexMode4Multiplier[values[0]]; - groupAScale = 0.7079468 * mult; - groupBScale = 0.5011902 * mult; - groupCScale = 0.3548279 * mult; - - for (int i = groupABin; i < groupBBin; i++) - { - spectra[i] *= groupAScale; - } - - for (int i = groupBBin; i < groupCBin; i++) - { - spectra[i] *= groupBScale; - } - - for (int i = groupCBin; i < totalBins; i++) - { - spectra[i] *= groupCScale; - } - } -} - -void ScaleBexQuantUnits(double* spectra, double* scales, int startUnit, int totalUnits) -{ - for (int i = startUnit; i < totalUnits; i++) - { - for (int k = QuantUnitToCoeffIndex[i]; k < QuantUnitToCoeffIndex[i + 1]; k++) - { - spectra[k] *= scales[i - startUnit]; - } - } -} - -void FillHighFrequencies(double* spectra, int groupABin, int groupBBin, int groupCBin, int totalBins) -{ - for (int i = 0; i < groupBBin - groupABin; i++) - { - spectra[groupABin + i] = spectra[groupABin - i - 1]; - } - - for (int i = 0; i < groupCBin - groupBBin; i++) - { - spectra[groupBBin + i] = spectra[groupBBin - i - 1]; - } - - for (int i = 0; i < totalBins - groupCBin; i++) - { - spectra[groupCBin + i] = spectra[groupCBin - i - 1]; - } -} - -void AddNoiseToSpectrum(channel* channel, int index, int count) -{ - if (!channel->rng.initialized) - { - int* sf = channel->ScaleFactors; - const unsigned short seed = (unsigned short)(543 * (sf[8] + sf[12] + sf[15] + 1)); - rng_init(&channel->rng, seed); - } - for (int i = 0; i < count; i++) - { - channel->Spectra[i + index] = rng_next(&channel->rng) / 65535.0 * 2.0 - 1.0; - } -} - -void rng_init(rng_cxt* rng, unsigned short seed) -{ - const int startValue = 0x4D93 * (seed ^ (seed >> 14)); - - rng->stateA = (unsigned short)(3 - startValue); - rng->stateB = (unsigned short)(2 - startValue); - rng->stateC = (unsigned short)(1 - startValue); - rng->stateD = (unsigned short)(0 - startValue); - rng->initialized = TRUE; -} - -unsigned short rng_next(rng_cxt* rng) -{ - const unsigned short t = (unsigned short)(rng->stateD ^ (rng->stateD << 5)); - rng->stateD = rng->stateC; - rng->stateC = rng->stateB; - rng->stateB = rng->stateA; - rng->stateA = (unsigned short)(t ^ rng->stateA ^ ((t ^ (rng->stateA >> 5)) >> 4)); - return rng->stateA; -} \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/band_extension.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/band_extension.h deleted file mode 100644 index c0b6a902e..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/band_extension.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "structures.h" - -void ApplyBandExtension(block* block); -void ApplyBandExtensionChannel(channel* channel); - -void ScaleBexQuantUnits(double* spectra, double* scales, int startUnit, int totalUnits); -void FillHighFrequencies(double* spectra, int groupABin, int groupBBin, int groupCBin, int totalBins); -void AddNoiseToSpectrum(channel* channel, int index, int count); - -void rng_init(rng_cxt* rng, unsigned short seed); -unsigned short rng_next(rng_cxt* rng); \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_allocation.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_allocation.c deleted file mode 100644 index 2977efc37..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_allocation.c +++ /dev/null @@ -1,119 +0,0 @@ -#include "bit_allocation.h" -#include "tables.h" -#include "utility.h" -#include - -at9_status CreateGradient(block* block) -{ - int valueCount = block->GradientEndValue - block->GradientStartValue; - int unitCount = block->GradientEndUnit - block->GradientStartUnit; - - for (int i = 0; i < block->GradientEndUnit; i++) - { - block->Gradient[i] = block->GradientStartValue; - } - - for (int i = block->GradientEndUnit; i <= block->QuantizationUnitCount; i++) - { - block->Gradient[i] = block->GradientEndValue; - } - if (unitCount <= 0) return ERR_SUCCESS; - if (valueCount == 0) return ERR_SUCCESS; - - const unsigned char* curve = GradientCurves[unitCount - 1]; - if (valueCount <= 0) - { - double scale = (-valueCount - 1) / 31.0; - int baseVal = block->GradientStartValue - 1; - for (int i = block->GradientStartUnit; i < block->GradientEndUnit; i++) - { - block->Gradient[i] = baseVal - (int)(curve[i - block->GradientStartUnit] * scale); - } - } - else - { - double scale = (valueCount - 1) / 31.0; - int baseVal = block->GradientStartValue + 1; - for (int i = block->GradientStartUnit; i < block->GradientEndUnit; i++) - { - block->Gradient[i] = baseVal + (int)(curve[i - block->GradientStartUnit] * scale); - } - } - - return ERR_SUCCESS; -} - -void CalculateMask(channel* channel) -{ - memset(channel->PrecisionMask, 0, sizeof(channel->PrecisionMask)); - for (int i = 1; i < channel->Block->QuantizationUnitCount; i++) - { - const int delta = channel->ScaleFactors[i] - channel->ScaleFactors[i - 1]; - if (delta > 1) - { - channel->PrecisionMask[i] += min(delta - 1, 5); - } - else if (delta < -1) - { - channel->PrecisionMask[i - 1] += min(delta * -1 - 1, 5); - } - } -} - -void CalculatePrecisions(channel* channel) -{ - block* block = channel->Block; - - if (block->GradientMode != 0) - { - for (int i = 0; i < block->QuantizationUnitCount; i++) - { - channel->Precisions[i] = channel->ScaleFactors[i] + channel->PrecisionMask[i] - block->Gradient[i]; - if (channel->Precisions[i] > 0) - { - switch (block->GradientMode) - { - case 1: - channel->Precisions[i] /= 2; - break; - case 2: - channel->Precisions[i] = 3 * channel->Precisions[i] / 8; - break; - case 3: - channel->Precisions[i] /= 4; - break; - } - } - } - } - else - { - for (int i = 0; i < block->QuantizationUnitCount; i++) - { - channel->Precisions[i] = channel->ScaleFactors[i] - block->Gradient[i]; - } - } - - for (int i = 0; i < block->QuantizationUnitCount; i++) - { - if (channel->Precisions[i] < 1) - { - channel->Precisions[i] = 1; - } - } - - for (int i = 0; i < block->GradientBoundary; i++) - { - channel->Precisions[i]++; - } - - for (int i = 0; i < block->QuantizationUnitCount; i++) - { - channel->PrecisionsFine[i] = 0; - if (channel->Precisions[i] > 15) - { - channel->PrecisionsFine[i] = channel->Precisions[i] - 15; - channel->Precisions[i] = 15; - } - } -} \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_allocation.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_allocation.h deleted file mode 100644 index 8ab8ba208..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_allocation.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "unpack.h" - -at9_status CreateGradient(block* block); -void CalculateMask(channel* channel); -void CalculatePrecisions(channel* channel); diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_reader.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_reader.c deleted file mode 100644 index f38530562..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_reader.c +++ /dev/null @@ -1,110 +0,0 @@ -#include "bit_reader.h" -#include "utility.h" - -static int peek_int_fallback(bit_reader_cxt* br, int bit_count); - -void init_bit_reader_cxt(bit_reader_cxt* br, const void * buffer) -{ - br->buffer = buffer; - br->position = 0; -} - -int read_int(bit_reader_cxt* br, const int bits) -{ - const int value = peek_int(br, bits); - br->position += bits; - return value; -} - -int read_signed_int(bit_reader_cxt* br, const int bits) -{ - const int value = peek_int(br, bits); - br->position += bits; - return SignExtend32(value, bits); -} - -int read_offset_binary(bit_reader_cxt* br, const int bits) -{ - const int offset = 1 << (bits - 1); - const int value = peek_int(br, bits) - offset; - br->position += bits; - return value; -} - -int peek_int(bit_reader_cxt* br, const int bits) -{ - const int byte_index = br->position / 8; - const int bit_index = br->position % 8; - const unsigned char* buffer = br->buffer; - - if (bits <= 9) - { - int value = buffer[byte_index] << 8 | buffer[byte_index + 1]; - value &= 0xFFFF >> bit_index; - value >>= 16 - bits - bit_index; - return value; - } - - if (bits <= 17) - { - int value = buffer[byte_index] << 16 | buffer[byte_index + 1] << 8 | buffer[byte_index + 2]; - value &= 0xFFFFFF >> bit_index; - value >>= 24 - bits - bit_index; - return value; - } - - if (bits <= 25) - { - int value = buffer[byte_index] << 24 - | buffer[byte_index + 1] << 16 - | buffer[byte_index + 2] << 8 - | buffer[byte_index + 3]; - - value &= (int)(0xFFFFFFFF >> bit_index); - value >>= 32 - bits - bit_index; - return value; - } - return peek_int_fallback(br, bits); -} - -void align_position(bit_reader_cxt* br, const unsigned int multiple) -{ - const int position = br->position; - if (position % multiple == 0) - { - return; - } - - br->position = position + multiple - position % multiple; -} - -static int peek_int_fallback(bit_reader_cxt* br, int bit_count) -{ - int value = 0; - int byte_index = br->position / 8; - int bit_index = br->position % 8; - const unsigned char* buffer = br->buffer; - - while (bit_count > 0) - { - if (bit_index >= 8) - { - bit_index = 0; - byte_index++; - } - - int bits_to_read = bit_count; - if (bits_to_read > 8 - bit_index) - { - bits_to_read = 8 - bit_index; - } - - const int mask = 0xFF >> bit_index; - const int current_byte = (mask & buffer[byte_index]) >> (8 - bit_index - bits_to_read); - - value = (value << bits_to_read) | current_byte; - bit_index += bits_to_read; - bit_count -= bits_to_read; - } - return value; -} \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_reader.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_reader.h deleted file mode 100644 index bcec9d40f..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/bit_reader.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -typedef struct { - const unsigned char * buffer; - int position; -} bit_reader_cxt; - -void init_bit_reader_cxt(bit_reader_cxt* br, const void * buffer); -int peek_int(bit_reader_cxt* br, const int bits); -int read_int(bit_reader_cxt* br, const int bits); -int read_signed_int(bit_reader_cxt* br, const int bits); -int read_offset_binary(bit_reader_cxt* br, const int bits); -void align_position(bit_reader_cxt* br, const unsigned int multiple); \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decinit.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decinit.c deleted file mode 100644 index c8a1945e0..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decinit.c +++ /dev/null @@ -1,188 +0,0 @@ -#include "bit_reader.h" -#include "decinit.h" -#include "error_codes.h" -#include "structures.h" -#include "tables.h" -#include -#include -#include "utility.h" - -static int BlockTypeToChannelCount(BlockType block_type); - -at9_status init_decoder(atrac9_handle* handle, unsigned char* config_data, int wlength) -{ - ERROR_CHECK(init_config_data(&handle->config, config_data)); - ERROR_CHECK(init_frame(handle)); - init_mdct_tables(handle->config.FrameSamplesPower); - init_huffman_codebooks(); - handle->wlength = wlength; - handle->initialized = 1; - return ERR_SUCCESS; -} - -at9_status init_config_data(ConfigData* config, unsigned char* config_data) -{ - memcpy(config->ConfigData, config_data, CONFIG_DATA_SIZE); - ERROR_CHECK(read_config_data(config)); - - config->FramesPerSuperframe = 1 << config->SuperframeIndex; - config->SuperframeBytes = config->FrameBytes << config->SuperframeIndex; - - config->ChannelConfig = ChannelConfigs[config->ChannelConfigIndex]; - config->ChannelCount = config->ChannelConfig.ChannelCount; - config->SampleRate = SampleRates[config->SampleRateIndex]; - config->HighSampleRate = config->SampleRateIndex > 7; - config->FrameSamplesPower = SamplingRateIndexToFrameSamplesPower[config->SampleRateIndex]; - config->FrameSamples = 1 << config->FrameSamplesPower; - config->SuperframeSamples = config->FrameSamples * config->FramesPerSuperframe; - - return ERR_SUCCESS; -} - -at9_status read_config_data(ConfigData* config) -{ - bit_reader_cxt br; - init_bit_reader_cxt(&br, &config->ConfigData); - - const int header = read_int(&br, 8); - config->SampleRateIndex = read_int(&br, 4); - config->ChannelConfigIndex = read_int(&br, 3); - const int validation_bit = read_int(&br, 1); - config->FrameBytes = read_int(&br, 11) + 1; - config->SuperframeIndex = read_int(&br, 2); - - if (header != 0xFE || validation_bit != 0) - { - return ERR_BAD_CONFIG_DATA; - } - - return ERR_SUCCESS; -} - -at9_status init_frame(atrac9_handle* handle) -{ - const int block_count = handle->config.ChannelConfig.BlockCount; - handle->frame.config = &handle->config; - - for (int i = 0; i < block_count; i++) - { - ERROR_CHECK(init_block(&handle->frame.Blocks[i], &handle->frame, i)); - } - - return ERR_SUCCESS; -} - -at9_status init_block(block* block, frame* parent_frame, int block_index) -{ - block->Frame = parent_frame; - block->BlockIndex = block_index; - block->config = parent_frame->config; - block->BlockType = block->config->ChannelConfig.Types[block_index]; - block->ChannelCount = BlockTypeToChannelCount(block->BlockType); - - for (int i = 0; i < block->ChannelCount; i++) - { - ERROR_CHECK(init_channel(&block->Channels[i], block, i)); - } - - return ERR_SUCCESS; -} - -at9_status init_channel(channel* channel, block* parent_block, int channel_index) -{ - channel->Block = parent_block; - channel->Frame = parent_block->Frame; - channel->config = parent_block->config; - channel->ChannelIndex = channel_index; - channel->mdct.bits = parent_block->config->FrameSamplesPower; - return ERR_SUCCESS; -} - -void init_huffman_codebooks() -{ - init_huffman_set(HuffmanScaleFactorsUnsigned, sizeof(HuffmanScaleFactorsUnsigned) / sizeof(HuffmanCodebook)); - init_huffman_set(HuffmanScaleFactorsSigned, sizeof(HuffmanScaleFactorsSigned) / sizeof(HuffmanCodebook)); - init_huffman_set(HuffmanSpectrum, sizeof(HuffmanSpectrum) / sizeof(HuffmanCodebook)); -} - -void init_huffman_set(const HuffmanCodebook* codebooks, int count) -{ - for (int i = 0; i < count; i++) - { - InitHuffmanCodebook(&codebooks[i]); - } -} - -void init_mdct_tables(int frameSizePower) -{ - for (int i = 0; i < 9; i++) - { - GenerateTrigTables(i); - GenerateShuffleTable(i); - } - GenerateMdctWindow(frameSizePower); - GenerateImdctWindow(frameSizePower); -} - -void GenerateTrigTables(int sizeBits) -{ - const int size = 1 << sizeBits; - double* sinTab = SinTables[sizeBits]; - double* cosTab = CosTables[sizeBits]; - - for (int i = 0; i < size; i++) - { - const double value = M_PI * (4 * i + 1) / (4 * size); - sinTab[i] = sin(value); - cosTab[i] = cos(value); - } -} - -void GenerateShuffleTable(int sizeBits) -{ - const int size = 1 << sizeBits; - int* table = ShuffleTables[sizeBits]; - - for (int i = 0; i < size; i++) - { - table[i] = BitReverse32(i ^ (i / 2), sizeBits); - } -} - -void GenerateMdctWindow(int frameSizePower) -{ - const int frameSize = 1 << frameSizePower; - double* mdct = MdctWindow[frameSizePower - 6]; - - for (int i = 0; i < frameSize; i++) - { - mdct[i] = (sin(((i + 0.5) / frameSize - 0.5) * M_PI) + 1.0) * 0.5; - } -} - -void GenerateImdctWindow(int frameSizePower) -{ - const int frameSize = 1 << frameSizePower; - double* imdct = ImdctWindow[frameSizePower - 6]; - double* mdct = MdctWindow[frameSizePower - 6]; - - for (int i = 0; i < frameSize; i++) - { - imdct[i] = mdct[i] / (mdct[frameSize - 1 - i] * mdct[frameSize - 1 - i] + mdct[i] * mdct[i]); - } -} - -static int BlockTypeToChannelCount(BlockType block_type) -{ - switch (block_type) - { - case Mono: - return 1; - case Stereo: - return 2; - case LFE: - return 1; - default: - return 0; - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decinit.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decinit.h deleted file mode 100644 index 3871e4fb2..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decinit.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "error_codes.h" -#include "structures.h" -#include "huffCodes.h" - -at9_status init_decoder(atrac9_handle* handle, unsigned char * config_data, int wlength); -at9_status init_config_data(ConfigData* config, unsigned char * config_data); -at9_status read_config_data(ConfigData* config); -at9_status init_frame(atrac9_handle* handle); -at9_status init_block(block* block, frame* parent_frame, int block_index); -at9_status init_channel(channel* channel, block* parent_block, int channel_index); -void init_huffman_codebooks(); -void init_huffman_set(const HuffmanCodebook* codebooks, int count); -void GenerateTrigTables(int sizeBits); -void GenerateShuffleTable(int sizeBits); -void init_mdct_tables(int frameSizePower); -void GenerateMdctWindow(int frameSizePower); -void GenerateImdctWindow(int frameSizePower); diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decoder.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decoder.c deleted file mode 100644 index 4b63cc02d..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decoder.c +++ /dev/null @@ -1,114 +0,0 @@ -#include -#include "decoder.h" -#include "unpack.h" -#include "quantization.h" -#include "tables.h" -#include "imdct.h" -#include -#include "utility.h" -#include "band_extension.h" - -at9_status Decode(atrac9_handle* handle, const unsigned char* audio, unsigned char* pcm, int* bytesUsed) -{ - handle->frame.frameNum++; - bit_reader_cxt br; - init_bit_reader_cxt(&br, audio); - ERROR_CHECK(DecodeFrame(&handle->frame, &br)); - - PcmFloatToShort(&handle->frame, (short*)pcm); - - *bytesUsed = br.position / 8; - return ERR_SUCCESS; -} - -at9_status DecodeFrame(frame* frame, bit_reader_cxt* br) -{ - ERROR_CHECK(UnpackFrame(frame, br)); - - for (int i = 0; i < frame->config->ChannelConfig.BlockCount; i++) - { - block* block = &frame->Blocks[i]; - - DequantizeSpectra(block); - ApplyIntensityStereo(block); - ScaleSpectrumBlock(block); - ApplyBandExtension(block); - ImdctBlock(block); - } - - return ERR_SUCCESS; -} - -void PcmFloatToShort(frame* frame, short* pcmOut) -{ - const int endSample = frame->config->FrameSamples; - short* dest = pcmOut; - for (int d = 0, s = 0; s < endSample; d++, s++) - { - for (int i = 0; i < frame->config->ChannelConfig.BlockCount; i++) - { - block* block = &frame->Blocks[i]; - - for (int j = 0; j < block->ChannelCount; j++) - { - channel* channel = &block->Channels[j]; - double* pcmSrc = channel->Pcm; - - const double sample = pcmSrc[d]; - const int roundedSample = (int)floor(sample + 0.5); - *dest++ = Clamp16(roundedSample); - } - } - } -} - -void ImdctBlock(block* block) -{ - for (int i = 0; i < block->ChannelCount; i++) - { - channel* channel = &block->Channels[i]; - - RunImdct(&channel->mdct, channel->Spectra, channel->Pcm); - } -} - -void ApplyIntensityStereo(block* block) -{ - if (block->BlockType != Stereo) return; - - const int totalUnits = block->QuantizationUnitCount; - const int stereoUnits = block->StereoQuantizationUnit; - if (stereoUnits >= totalUnits) return; - - channel* source = &block->Channels[block->PrimaryChannelIndex == 0 ? 0 : 1]; - channel* dest = &block->Channels[block->PrimaryChannelIndex == 0 ? 1 : 0]; - - for (int i = stereoUnits; i < totalUnits; i++) - { - const int sign = block->JointStereoSigns[i]; - for (int sb = QuantUnitToCoeffIndex[i]; sb < QuantUnitToCoeffIndex[i + 1]; sb++) - { - if (sign > 0) - { - dest->Spectra[sb] = -source->Spectra[sb]; - } - else - { - dest->Spectra[sb] = source->Spectra[sb]; - } - } - } -} - -int GetCodecInfo(atrac9_handle* handle, CodecInfo * pCodecInfo) -{ - pCodecInfo->channels = handle->config.ChannelCount; - pCodecInfo->channelConfigIndex = handle->config.ChannelConfigIndex; - pCodecInfo->samplingRate = handle->config.SampleRate; - pCodecInfo->superframeSize = handle->config.SuperframeBytes; - pCodecInfo->framesInSuperframe = handle->config.FramesPerSuperframe; - pCodecInfo->frameSamples = handle->config.FrameSamples; - pCodecInfo->wlength = handle->wlength; - memcpy(pCodecInfo->configData, handle->config.ConfigData, CONFIG_DATA_SIZE); - return ERR_SUCCESS; -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decoder.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decoder.h deleted file mode 100644 index 62bf7cb76..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/decoder.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include "bit_reader.h" -#include "error_codes.h" -#include "structures.h" - -at9_status Decode(atrac9_handle* handle, const unsigned char* audio, unsigned char* pcm, int* bytesUsed); -at9_status DecodeFrame(frame* frame, bit_reader_cxt* br); -void ImdctBlock(block* block); -void ApplyIntensityStereo(block* block); -void PcmFloatToShort(frame* frame, short* pcmOut); -int GetCodecInfo(atrac9_handle* handle, CodecInfo* pCodecInfo); diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/error_codes.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/error_codes.h deleted file mode 100644 index d40847d1c..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/error_codes.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -typedef enum at9_status -{ - ERR_SUCCESS = 0, - - ERR_NOT_IMPLEMENTED = 0x80000000, - - ERR_BAD_CONFIG_DATA = 0x81000000, - - ERR_UNPACK_SUPERFRAME_FLAG_INVALID = 0x82000000, - ERR_UNPACK_REUSE_BAND_PARAMS_INVALID, - ERR_UNPACK_BAND_PARAMS_INVALID, - - ERR_UNPACK_GRAD_BOUNDARY_INVALID = 0x82100000, - ERR_UNPACK_GRAD_START_UNIT_OOB, - ERR_UNPACK_GRAD_END_UNIT_OOB, - ERR_UNPACK_GRAD_START_VALUE_OOB, - ERR_UNPACK_GRAD_END_VALUE_OOB, - ERR_UNPACK_GRAD_END_UNIT_INVALID, // start_unit > end_unit - - ERR_UNPACK_SCALE_FACTOR_MODE_INVALID, - ERR_UNPACK_SCALE_FACTOR_OOB, - - ERR_UNPACK_EXTENSION_DATA_INVALID -} at9_status; - -#define ERROR_CHECK(x) do { \ - at9_status status = (x); \ - if (status != ERR_SUCCESS) { \ - return status; \ - } \ -} while (0) \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/huffCodes.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/huffCodes.c deleted file mode 100644 index 2ee97e0d4..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/huffCodes.c +++ /dev/null @@ -1,152 +0,0 @@ -#include "huffCodes.h" -#include "utility.h" - -int ReadHuffmanValue(const HuffmanCodebook* huff, bit_reader_cxt* br, int is_signed) -{ - const int code = peek_int(br, huff->MaxBitSize); - const unsigned char value = huff->Lookup[code]; - const int bits = huff->Bits[value]; - br->position += bits; - return is_signed ? SignExtend32(value, huff->ValueBits) : value; -} - -void DecodeHuffmanValues(int* spectrum, int index, int bandCount, const HuffmanCodebook* huff, const int* values) -{ - const int valueCount = bandCount >> huff->ValueCountPower; - const int mask = (1 << huff->ValueBits) - 1; - - for (int i = 0; i < valueCount; i++) - { - int value = values[i]; - for (int j = 0; j < huff->ValueCount; j++) - { - spectrum[index++] = SignExtend32(value & mask, huff->ValueBits); - value >>= huff->ValueBits; - } - } -} - -void InitHuffmanCodebook(const HuffmanCodebook* codebook) -{ - const int huffLength = codebook->Length; - if (huffLength == 0) return; - - unsigned char* dest = codebook->Lookup; - - for (int i = 0; i < huffLength; i++) - { - if (codebook->Bits[i] == 0) continue; - const int unusedBits = codebook->MaxBitSize - codebook->Bits[i]; - - const int start = codebook->Codes[i] << unusedBits; - const int length = 1 << unusedBits; - const int end = start + length; - - for (int j = start; j < end; j++) - { - dest[j] = i; - } - } -} - -HuffmanCodebook HuffmanScaleFactorsUnsigned[7] = { - {0}, - {ScaleFactorsA1Bits, ScaleFactorsA1Codes, ScaleFactorsA1Lookup, 2, 1, 0, 1, 2, 1}, - {ScaleFactorsA2Bits, ScaleFactorsA2Codes, ScaleFactorsA2Lookup, 4, 1, 0, 2, 4, 3}, - {ScaleFactorsA3Bits, ScaleFactorsA3Codes, ScaleFactorsA3Lookup, 8, 1, 0, 3, 8, 6}, - {ScaleFactorsA4Bits, ScaleFactorsA4Codes, ScaleFactorsA4Lookup, 16, 1, 0, 4, 16, 8}, - {ScaleFactorsA5Bits, ScaleFactorsA5Codes, ScaleFactorsA5Lookup, 32, 1, 0, 5, 32, 8}, - {ScaleFactorsA6Bits, ScaleFactorsA6Codes, ScaleFactorsA6Lookup, 64, 1, 0, 6, 64, 8}, -}; - -HuffmanCodebook HuffmanScaleFactorsSigned[6] = { - {0}, - {0}, - {ScaleFactorsB2Bits, ScaleFactorsB2Codes, ScaleFactorsB2Lookup, 4, 1, 0, 2, 4, 2}, - {ScaleFactorsB3Bits, ScaleFactorsB3Codes, ScaleFactorsB3Lookup, 8, 1, 0, 3, 8, 6}, - {ScaleFactorsB4Bits, ScaleFactorsB4Codes, ScaleFactorsB4Lookup, 16, 1, 0, 4, 16, 8}, - {ScaleFactorsB5Bits, ScaleFactorsB5Codes, ScaleFactorsB5Lookup, 32, 1, 0, 5, 32, 8}, -}; - -HuffmanCodebook HuffmanSpectrum[2][8][4] = { - { - {0}, - {0}, - { - {SpectrumA21Bits, SpectrumA21Codes, SpectrumA21Lookup, 16, 2, 1, 2, 4, 3}, - {SpectrumA22Bits, SpectrumA22Codes, SpectrumA22Lookup, 256, 4, 2, 2, 4, 8}, - {SpectrumA23Bits, SpectrumA23Codes, SpectrumA23Lookup, 256, 4, 2, 2, 4, 9}, - {SpectrumA24Bits, SpectrumA24Codes, SpectrumA24Lookup, 256, 4, 2, 2, 4, 10} - }, - { - {SpectrumA31Bits, SpectrumA31Codes, SpectrumA31Lookup, 64, 2, 1, 3, 8, 7}, - {SpectrumA32Bits, SpectrumA32Codes, SpectrumA32Lookup, 64, 2, 1, 3, 8, 7}, - {SpectrumA33Bits, SpectrumA33Codes, SpectrumA33Lookup, 64, 2, 1, 3, 8, 8}, - {SpectrumA34Bits, SpectrumA34Codes, SpectrumA34Lookup, 64, 2, 1, 3, 8, 10} - }, - { - {SpectrumA41Bits, SpectrumA41Codes, SpectrumA41Lookup, 256, 2, 1, 4, 16, 9}, - {SpectrumA42Bits, SpectrumA42Codes, SpectrumA42Lookup, 256, 2, 1, 4, 16, 10}, - {SpectrumA43Bits, SpectrumA43Codes, SpectrumA43Lookup, 256, 2, 1, 4, 16, 10}, - {SpectrumA44Bits, SpectrumA44Codes, SpectrumA44Lookup, 256, 2, 1, 4, 16, 10} - }, - { - {SpectrumA51Bits, SpectrumA51Codes, SpectrumA51Lookup, 32, 1, 0, 5, 32, 6}, - {SpectrumA52Bits, SpectrumA52Codes, SpectrumA52Lookup, 32, 1, 0, 5, 32, 6}, - {SpectrumA53Bits, SpectrumA53Codes, SpectrumA53Lookup, 32, 1, 0, 5, 32, 7}, - {SpectrumA54Bits, SpectrumA54Codes, SpectrumA54Lookup, 32, 1, 0, 5, 32, 8} - }, - { - {SpectrumA61Bits, SpectrumA61Codes, SpectrumA61Lookup, 64, 1, 0, 6, 64, 7}, - {SpectrumA62Bits, SpectrumA62Codes, SpectrumA62Lookup, 64, 1, 0, 6, 64, 7}, - {SpectrumA63Bits, SpectrumA63Codes, SpectrumA63Lookup, 64, 1, 0, 6, 64, 8}, - {SpectrumA64Bits, SpectrumA64Codes, SpectrumA64Lookup, 64, 1, 0, 6, 64, 9} - }, - { - {SpectrumA71Bits, SpectrumA71Codes, SpectrumA71Lookup, 128, 1, 0, 7, 128, 8}, - {SpectrumA72Bits, SpectrumA72Codes, SpectrumA72Lookup, 128, 1, 0, 7, 128, 8}, - {SpectrumA73Bits, SpectrumA73Codes, SpectrumA73Lookup, 128, 1, 0, 7, 128, 9}, - {SpectrumA74Bits, SpectrumA74Codes, SpectrumA74Lookup, 128, 1, 0, 7, 128, 10} - } - }, - { - {0}, - {0}, - { - {0}, - {SpectrumB22Bits, SpectrumB22Codes, SpectrumB22Lookup, 256, 4, 2, 2, 4, 10}, - {SpectrumB23Bits, SpectrumB23Codes, SpectrumB23Lookup, 256, 4, 2, 2, 4, 10}, - {SpectrumB24Bits, SpectrumB24Codes, SpectrumB24Lookup, 256, 4, 2, 2, 4, 10} - }, - { - {0}, - {SpectrumB32Bits, SpectrumB32Codes, SpectrumB32Lookup, 64, 2, 1, 3, 8, 9}, - {SpectrumB33Bits, SpectrumB33Codes, SpectrumB33Lookup, 64, 2, 1, 3, 8, 10}, - {SpectrumB34Bits, SpectrumB34Codes, SpectrumB34Lookup, 64, 2, 1, 3, 8, 10} - }, - { - {0}, - {SpectrumB42Bits, SpectrumB42Codes, SpectrumB42Lookup, 256, 2, 1, 4, 16, 10}, - {SpectrumB43Bits, SpectrumB43Codes, SpectrumB43Lookup, 256, 2, 1, 4, 16, 10}, - {SpectrumB44Bits, SpectrumB44Codes, SpectrumB44Lookup, 256, 2, 1, 4, 16, 10} - }, - { - {0}, - {SpectrumB52Bits, SpectrumB52Codes, SpectrumB52Lookup, 32, 1, 0, 5, 32, 7}, - {SpectrumB53Bits, SpectrumB53Codes, SpectrumB53Lookup, 32, 1, 0, 5, 32, 8}, - {SpectrumB54Bits, SpectrumB54Codes, SpectrumB54Lookup, 32, 1, 0, 5, 32, 9} - }, - { - {0}, - {SpectrumB62Bits, SpectrumB62Codes, SpectrumB62Lookup, 64, 1, 0, 6, 64, 8}, - {SpectrumB63Bits, SpectrumB63Codes, SpectrumB63Lookup, 64, 1, 0, 6, 64, 9}, - {SpectrumB64Bits, SpectrumB64Codes, SpectrumB64Lookup, 64, 1, 0, 6, 64, 10} - }, - { - {0}, - {SpectrumB72Bits, SpectrumB72Codes, SpectrumB72Lookup, 128, 1, 0, 7, 128, 9}, - {SpectrumB73Bits, SpectrumB73Codes, SpectrumB73Lookup, 128, 1, 0, 7, 128, 10}, - {SpectrumB74Bits, SpectrumB74Codes, SpectrumB74Lookup, 128, 1, 0, 7, 128, 10} - } - } -}; diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/huffCodes.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/huffCodes.h deleted file mode 100644 index a2fef16c2..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/huffCodes.h +++ /dev/null @@ -1,1295 +0,0 @@ -#pragma once -#include -#include "bit_reader.h" - -typedef struct -{ - const unsigned char* Bits; - const short* Codes; - unsigned char* Lookup; - const int Length; - const int ValueCount; - const int ValueCountPower; - const int ValueBits; - const int ValueMax; - const int MaxBitSize; -} HuffmanCodebook; - -int ReadHuffmanValue(const HuffmanCodebook* huff, bit_reader_cxt* br, int is_signed); -void DecodeHuffmanValues(int* spectrum, int index, int bandCount, const HuffmanCodebook* huff, const int* values); -void InitHuffmanCodebook(const HuffmanCodebook* codebook); - -extern HuffmanCodebook HuffmanScaleFactorsUnsigned[7]; -extern HuffmanCodebook HuffmanScaleFactorsSigned[6]; -extern HuffmanCodebook HuffmanSpectrum[2][8][4]; - -static const uint8_t ScaleFactorsA1Bits[2] = -{ - 1, 1 -}; - -static const uint16_t ScaleFactorsA1Codes[2] = -{ - 0x00, 0x01 -}; - -static const uint8_t ScaleFactorsA2Bits[4] = -{ - 1, 3, 3, 2 -}; - -static const uint16_t ScaleFactorsA2Codes[4] = -{ - 0x00, 0x06, 0x07, 0x02 -}; - -static const uint8_t ScaleFactorsA3Bits[8] = -{ - 2, 2, 4, 6, 6, 5, 3, 2 -}; - -static const uint16_t ScaleFactorsA3Codes[8] = -{ - 0x00, 0x01, 0x0E, 0x3E, 0x3F, 0x1E, 0x06, 0x02 -}; - -static const uint8_t ScaleFactorsA4Bits[16] = -{ - 2, 2, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 6, 5, 4, 2 -}; - -static const uint16_t ScaleFactorsA4Codes[16] = -{ - 0x01, 0x02, 0x00, 0x06, 0x0F, 0x13, 0x23, 0x24, 0x25, 0x22, 0x21, 0x20, 0x0E, 0x05, 0x01, 0x03 -}; - -static const uint8_t ScaleFactorsA5Bits[32] = -{ - 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 6, 5, 5, 4, 3 -}; - -static const uint16_t ScaleFactorsA5Codes[32] = -{ - 0x02, 0x01, 0x07, 0x0D, 0x0C, 0x18, 0x1B, 0x21, 0x3F, 0x6A, 0x6B, 0x68, 0x73, 0x79, 0x7C, 0x7D, - 0x7A, 0x7B, 0x78, 0x72, 0x44, 0x45, 0x47, 0x46, 0x69, 0x38, 0x20, 0x1D, 0x19, 0x09, 0x05, 0x00 -}; - -static const uint8_t ScaleFactorsA6Bits[64] = -{ - 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 4, 4, 4 -}; - -static const uint16_t ScaleFactorsA6Codes[64] = -{ - 0x00, 0x01, 0x04, 0x05, 0x12, 0x13, 0x2E, 0x2F, 0x30, 0x66, 0x67, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, - 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, - 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, - 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x68, 0x69, 0x6A, 0x31, 0x32, 0x14, 0x15, 0x16, 0x06, 0x07, 0x08 -}; - -static const uint8_t ScaleFactorsB2Bits[4] = -{ - 1, 2, 0, 2 -}; - -static const uint16_t ScaleFactorsB2Codes[4] = -{ - 0x00, 0x03, 0x00, 0x02 -}; - -static const uint8_t ScaleFactorsB3Bits[8] = -{ - 1, 3, 5, 6, 0, 6, 4, 2 -}; - -static const uint16_t ScaleFactorsB3Codes[8] = -{ - 0x01, 0x00, 0x04, 0x0B, 0x00, 0x0A, 0x03, 0x01 -}; - -static const uint8_t ScaleFactorsB4Bits[16] = -{ - 1, 3, 4, 5, 5, 7, 8, 8, 0, 8, 8, 7, 6, 6, 4, 3 -}; - -static const uint16_t ScaleFactorsB4Codes[16] = -{ - 0x01, 0x01, 0x04, 0x0E, 0x0F, 0x2C, 0x5A, 0x5D, 0x00, 0x5C, 0x5B, 0x2F, 0x15, 0x14, 0x06, 0x00 -}; - -static const uint8_t ScaleFactorsB5Bits[32] = -{ - 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 7, 7, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 3 -}; - -static const uint16_t ScaleFactorsB5Codes[32] = -{ - 0x00, 0x05, 0x07, 0x0C, 0x04, 0x02, 0x03, 0x05, 0x09, 0x10, 0x23, 0x33, 0x36, 0x6E, 0x60, 0x65, - 0x62, 0x61, 0x63, 0x64, 0x6F, 0x6D, 0x6C, 0x6B, 0x6A, 0x68, 0x69, 0x45, 0x44, 0x37, 0x1A, 0x07 -}; - -static const uint8_t SpectrumA21Bits[16] = -{ - 0, 3, 0, 3, 3, 3, 0, 3, 0, 0, 0, 0, 3, 3, 0, 3 -}; - -static const uint16_t SpectrumA21Codes[16] = -{ - 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x06 -}; - -static const uint8_t SpectrumA22Bits[256] = -{ - 0, 4, 0, 4, 5, 6, 0, 6, 0, 0, 0, 0, 5, 6, 0, 6, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 6, 7, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 6, 7, 0, 7, - 5, 6, 0, 6, 7, 7, 0, 7, 0, 0, 0, 0, 6, 7, 0, 7, - 6, 7, 0, 7, 7, 8, 0, 8, 0, 0, 0, 0, 7, 8, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 7, 0, 7, 7, 8, 0, 8, 0, 0, 0, 0, 7, 7, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 7, 7, 0, 7, - 6, 7, 0, 7, 7, 8, 0, 7, 0, 0, 0, 0, 7, 8, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 7, 0, 7, 7, 7, 0, 8, 0, 0, 0, 0, 7, 8, 0, 8 -}; - -static const uint16_t SpectrumA22Codes[256] = -{ - 0x00, 0x02, 0x00, 0x03, 0x10, 0x3C, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x11, 0x3E, 0x00, 0x3D, - 0x0E, 0x00, 0x00, 0x39, 0x18, 0x26, 0x00, 0x75, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x24, 0x00, 0x6D, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x38, 0x00, 0x01, 0x1A, 0x6C, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x19, 0x74, 0x00, 0x27, - 0x16, 0x14, 0x00, 0x17, 0x76, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x35, 0x64, 0x00, 0x6F, - 0x26, 0x04, 0x00, 0x63, 0x22, 0xA2, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x67, 0xA0, 0x00, 0x0D, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2B, 0x52, 0x00, 0x0B, 0x20, 0x92, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x00, 0x95, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x17, 0x16, 0x00, 0x15, 0x34, 0x6E, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x77, 0x08, 0x00, 0x07, - 0x2A, 0x0A, 0x00, 0x53, 0x60, 0x94, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x21, 0x90, 0x00, 0x93, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x27, 0x62, 0x00, 0x05, 0x66, 0x0C, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x23, 0x96, 0x00, 0xA3 -}; - -static const uint8_t SpectrumA23Bits[256] = -{ - 3, 4, 0, 4, 5, 6, 0, 6, 0, 0, 0, 0, 5, 6, 0, 6, - 5, 7, 0, 6, 6, 8, 0, 7, 0, 0, 0, 0, 6, 8, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 7, 6, 7, 0, 8, 0, 0, 0, 0, 6, 7, 0, 8, - 5, 6, 0, 6, 7, 8, 0, 8, 0, 0, 0, 0, 6, 7, 0, 7, - 6, 8, 0, 7, 8, 9, 0, 9, 0, 0, 0, 0, 7, 9, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 8, 0, 8, 8, 9, 0, 9, 0, 0, 0, 0, 7, 8, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 7, 8, 0, 8, - 6, 8, 0, 8, 7, 9, 0, 8, 0, 0, 0, 0, 8, 9, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 7, 0, 8, 7, 8, 0, 9, 0, 0, 0, 0, 8, 9, 0, 9 -}; - -static const uint16_t SpectrumA23Codes[256] = -{ - 0x006, 0x002, 0x000, 0x003, 0x016, 0x01E, 0x000, 0x021, 0x000, 0x000, 0x000, 0x000, - 0x017, 0x020, 0x000, 0x01F, 0x01C, 0x054, 0x000, 0x027, 0x010, 0x0A6, 0x000, 0x027, - 0x000, 0x000, 0x000, 0x000, 0x015, 0x0A4, 0x000, 0x02D, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01D, 0x026, 0x000, 0x055, 0x014, 0x02C, 0x000, 0x0A5, 0x000, 0x000, 0x000, 0x000, - 0x011, 0x026, 0x000, 0x0A7, 0x01E, 0x000, 0x000, 0x003, 0x04A, 0x074, 0x000, 0x071, - 0x000, 0x000, 0x000, 0x000, 0x023, 0x00A, 0x000, 0x009, 0x018, 0x072, 0x000, 0x00D, - 0x0A2, 0x15A, 0x000, 0x123, 0x000, 0x000, 0x000, 0x000, 0x00F, 0x158, 0x000, 0x05D, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x01B, 0x0AE, 0x000, 0x077, 0x092, 0x140, 0x000, 0x121, - 0x000, 0x000, 0x000, 0x000, 0x025, 0x05E, 0x000, 0x143, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01F, 0x002, 0x000, 0x001, 0x022, 0x008, 0x000, 0x00B, 0x000, 0x000, 0x000, 0x000, - 0x04B, 0x070, 0x000, 0x075, 0x01A, 0x076, 0x000, 0x0AF, 0x024, 0x142, 0x000, 0x05F, - 0x000, 0x000, 0x000, 0x000, 0x093, 0x120, 0x000, 0x141, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x019, 0x00C, 0x000, 0x073, 0x00E, 0x05C, 0x000, 0x159, 0x000, 0x000, 0x000, 0x000, - 0x0A3, 0x122, 0x000, 0x15B -}; - -static const uint8_t SpectrumA24Bits[256] = -{ - 2, 4, 0, 4, 5, 6, 0, 6, 0, 0, 0, 0, 5, 6, 0, 6, - 5, 7, 0, 6, 6, 8, 0, 8, 0, 0, 0, 0, 6, 8, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 7, 6, 8, 0, 8, 0, 0, 0, 0, 6, 8, 0, 8, - 5, 7, 0, 7, 7, 9, 0, 9, 0, 0, 0, 0, 6, 8, 0, 8, - 6, 9, 0, 8, 8, 10, 0, 10, 0, 0, 0, 0, 8, 10, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 8, 0, 9, 9, 10, 0, 10, 0, 0, 0, 0, 8, 9, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 7, 0, 7, 6, 8, 0, 8, 0, 0, 0, 0, 7, 9, 0, 9, - 6, 9, 0, 8, 8, 10, 0, 9, 0, 0, 0, 0, 9, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 8, 0, 9, 8, 9, 0, 10, 0, 0, 0, 0, 8, 10, 0, 10 -}; - -static const uint16_t SpectrumA24Codes[256] = -{ - 0x002, 0x002, 0x000, 0x003, 0x01E, 0x010, 0x000, 0x013, 0x000, 0x000, 0x000, 0x000, - 0x01F, 0x012, 0x000, 0x011, 0x01A, 0x030, 0x000, 0x01B, 0x000, 0x064, 0x000, 0x0C1, - 0x000, 0x000, 0x000, 0x000, 0x003, 0x052, 0x000, 0x07D, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01B, 0x01A, 0x000, 0x031, 0x002, 0x07C, 0x000, 0x053, 0x000, 0x000, 0x000, 0x000, - 0x001, 0x0C0, 0x000, 0x065, 0x01C, 0x062, 0x000, 0x065, 0x02A, 0x198, 0x000, 0x19B, - 0x000, 0x000, 0x000, 0x000, 0x017, 0x078, 0x000, 0x07B, 0x004, 0x0FE, 0x000, 0x077, - 0x050, 0x33A, 0x000, 0x1F9, 0x000, 0x000, 0x000, 0x000, 0x073, 0x338, 0x000, 0x0E1, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x007, 0x066, 0x000, 0x187, 0x19E, 0x308, 0x000, 0x30B, - 0x000, 0x000, 0x000, 0x000, 0x075, 0x0E2, 0x000, 0x1FB, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01D, 0x064, 0x000, 0x063, 0x016, 0x07A, 0x000, 0x079, 0x000, 0x000, 0x000, 0x000, - 0x02B, 0x19A, 0x000, 0x199, 0x006, 0x186, 0x000, 0x067, 0x074, 0x1FA, 0x000, 0x0E3, - 0x000, 0x000, 0x000, 0x000, 0x19F, 0x30A, 0x000, 0x309, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x005, 0x076, 0x000, 0x0FF, 0x072, 0x0E0, 0x000, 0x339, 0x000, 0x000, 0x000, 0x000, - 0x051, 0x1F8, 0x000, 0x33B -}; - -static const uint8_t SpectrumA31Bits[64] = -{ - 0, 0, 4, 5, 0, 5, 4, 0, 0, 0, 5, 5, 0, 5, 5, 0, - 5, 5, 6, 6, 0, 6, 5, 5, 5, 6, 6, 7, 0, 7, 6, 6, - 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 6, 7, 0, 7, 6, 6, - 5, 5, 5, 6, 0, 6, 6, 5, 0, 0, 5, 5, 0, 5, 5, 0 -}; - -static const uint16_t SpectrumA31Codes[64] = -{ - 0x00, 0x00, 0x02, 0x18, 0x00, 0x19, 0x03, 0x00, 0x00, 0x00, 0x12, 0x02, 0x00, 0x09, 0x15, 0x00, - 0x1A, 0x0A, 0x3E, 0x2C, 0x00, 0x2F, 0x01, 0x0D, 0x0E, 0x38, 0x20, 0x78, 0x00, 0x7B, 0x23, 0x3B, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x3A, 0x22, 0x7A, 0x00, 0x79, 0x21, 0x39, - 0x1B, 0x0C, 0x00, 0x2E, 0x00, 0x2D, 0x3F, 0x0B, 0x00, 0x00, 0x14, 0x08, 0x00, 0x03, 0x13, 0x00 -}; - -static const uint8_t SpectrumA32Bits[64] = -{ - 4, 5, 5, 6, 0, 6, 5, 5, 5, 6, 5, 6, 0, 6, 5, 5, - 5, 5, 6, 7, 0, 7, 6, 5, 6, 6, 7, 7, 0, 7, 7, 6, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 7, 0, 7, 7, 6, - 5, 5, 6, 7, 0, 7, 6, 5, 5, 5, 5, 6, 0, 6, 5, 6 -}; - -static const uint16_t SpectrumA32Codes[64] = -{ - 0x0D, 0x18, 0x16, 0x3A, 0x00, 0x3B, 0x17, 0x19, 0x12, 0x3E, 0x08, 0x1C, 0x00, 0x1B, 0x07, 0x01, - 0x10, 0x02, 0x28, 0x78, 0x00, 0x7B, 0x1F, 0x05, 0x2A, 0x16, 0x72, 0x2A, 0x00, 0x29, 0x71, 0x19, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x18, 0x70, 0x28, 0x00, 0x2B, 0x73, 0x17, - 0x11, 0x04, 0x1E, 0x7A, 0x00, 0x79, 0x29, 0x03, 0x13, 0x00, 0x06, 0x1A, 0x00, 0x1D, 0x09, 0x3F -}; - -static const uint8_t SpectrumA33Bits[64] = -{ - 3, 4, 5, 6, 0, 6, 5, 4, 4, 5, 6, 7, 0, 7, 6, 5, - 5, 6, 6, 7, 0, 7, 6, 6, 6, 7, 8, 8, 0, 8, 8, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 8, 0, 8, 8, 7, - 5, 6, 6, 7, 0, 7, 6, 6, 4, 5, 6, 7, 0, 7, 6, 5 -}; - -static const uint16_t SpectrumA33Codes[64] = -{ - 0x05, 0x06, 0x10, 0x08, 0x00, 0x09, 0x11, 0x07, 0x04, 0x12, 0x3E, 0x6A, 0x00, 0x6D, 0x3D, 0x19, - 0x06, 0x3A, 0x06, 0x02, 0x00, 0x01, 0x05, 0x39, 0x02, 0x16, 0xDC, 0x2A, 0x00, 0x29, 0xDF, 0x69, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x68, 0xDE, 0x28, 0x00, 0x2B, 0xDD, 0x17, - 0x07, 0x38, 0x04, 0x00, 0x00, 0x03, 0x07, 0x3B, 0x05, 0x18, 0x3C, 0x6C, 0x00, 0x6B, 0x3F, 0x13 -}; - -static const uint8_t SpectrumA34Bits[64] = -{ - 2, 4, 5, 7, 0, 7, 5, 4, 4, 5, 6, 8, 0, 8, 6, 5, - 5, 6, 7, 8, 0, 8, 7, 6, 7, 8, 8, 10, 0, 10, 9, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 0, 10, 8, 8, - 5, 6, 7, 8, 0, 8, 7, 6, 4, 5, 6, 8, 0, 8, 6, 5 -}; - -static const uint16_t SpectrumA34Codes[64] = -{ - 0x000, 0x00A, 0x00A, 0x034, 0x000, 0x035, 0x00B, 0x00B, 0x008, 0x01C, 0x032, 0x0DA, - 0x000, 0x0DD, 0x035, 0x01F, 0x008, 0x01E, 0x03A, 0x06C, 0x000, 0x063, 0x039, 0x031, - 0x032, 0x06E, 0x060, 0x37A, 0x000, 0x379, 0x1BF, 0x0D9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x033, 0x0D8, 0x1BE, 0x378, 0x000, 0x37B, 0x061, 0x06F, - 0x009, 0x030, 0x038, 0x062, 0x000, 0x06D, 0x03B, 0x01F, 0x009, 0x01E, 0x034, 0x0DC, - 0x000, 0x0DB, 0x033, 0x01D -}; - -static const uint8_t SpectrumA41Bits[256] = -{ - 0, 0, 0, 0, 6, 6, 7, 7, 0, 7, 7, 6, 6, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 7, 7, 0, 7, 7, 7, 6, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 7, 8, 0, 8, 7, 7, 7, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 8, 8, 0, 8, 8, 7, 7, 0, 0, 0, - 7, 7, 7, 8, 7, 8, 8, 8, 0, 8, 8, 8, 7, 8, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 9, 0, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 8, 8, 8, 8, 9, 9, 0, 9, 8, 8, 8, 8, 8, 7, - 8, 8, 8, 8, 8, 9, 9, 9, 0, 9, 9, 9, 8, 8, 8, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 8, 8, 8, 8, 9, 9, 9, 0, 9, 9, 9, 8, 8, 8, 8, - 7, 7, 8, 8, 8, 8, 8, 9, 0, 9, 9, 8, 8, 8, 8, 7, - 7, 7, 7, 7, 8, 8, 8, 8, 0, 9, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 8, 7, 8, 8, 8, 0, 8, 8, 8, 7, 8, 7, 7, - 0, 0, 0, 0, 7, 7, 8, 8, 0, 8, 8, 7, 7, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 7, 8, 0, 8, 7, 7, 7, 0, 0, 0, - 0, 0, 0, 0, 6, 7, 7, 7, 0, 7, 7, 7, 7, 0, 0, 0 -}; - -static const uint16_t SpectrumA41Codes[256] = -{ - 0x000, 0x000, 0x000, 0x000, 0x018, 0x00E, 0x05E, 0x028, 0x000, 0x029, 0x05F, 0x00F, - 0x019, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x076, 0x06E, 0x03E, 0x004, - 0x000, 0x017, 0x045, 0x07B, 0x013, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x04A, 0x048, 0x010, 0x0CE, 0x000, 0x0E1, 0x023, 0x055, 0x053, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x008, 0x018, 0x0D6, 0x09E, 0x000, 0x09D, 0x0E5, 0x02B, - 0x01B, 0x000, 0x000, 0x000, 0x07C, 0x05C, 0x038, 0x0FC, 0x002, 0x0D2, 0x09A, 0x05C, - 0x000, 0x06B, 0x0A3, 0x0D9, 0x00F, 0x0FF, 0x03D, 0x061, 0x074, 0x056, 0x036, 0x000, - 0x0CC, 0x08C, 0x058, 0x1E2, 0x000, 0x00F, 0x05F, 0x0A1, 0x0D5, 0x00D, 0x03B, 0x059, - 0x040, 0x014, 0x0DA, 0x0B6, 0x084, 0x040, 0x1E0, 0x196, 0x000, 0x1A1, 0x00D, 0x043, - 0x087, 0x0C7, 0x0E3, 0x00B, 0x0F2, 0x0C4, 0x08E, 0x05A, 0x024, 0x1CC, 0x194, 0x168, - 0x000, 0x16B, 0x1A3, 0x1CF, 0x027, 0x069, 0x099, 0x0C9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x0F3, 0x0C8, 0x098, 0x068, 0x026, 0x1CE, 0x1A2, 0x16A, 0x000, 0x169, 0x195, 0x1CD, - 0x025, 0x05B, 0x08F, 0x0C5, 0x041, 0x00A, 0x0E2, 0x0C6, 0x086, 0x042, 0x00C, 0x1A0, - 0x000, 0x197, 0x1E1, 0x041, 0x085, 0x0B7, 0x0DB, 0x015, 0x075, 0x058, 0x03A, 0x00C, - 0x0D4, 0x0A0, 0x05E, 0x00E, 0x000, 0x1E3, 0x059, 0x08D, 0x0CD, 0x001, 0x037, 0x057, - 0x07D, 0x060, 0x03C, 0x0FE, 0x00E, 0x0D8, 0x0A2, 0x06A, 0x000, 0x05D, 0x09B, 0x0D3, - 0x003, 0x0FD, 0x039, 0x05D, 0x000, 0x000, 0x000, 0x000, 0x01A, 0x02A, 0x0E4, 0x09C, - 0x000, 0x09F, 0x0D7, 0x019, 0x009, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x052, 0x054, 0x022, 0x0E0, 0x000, 0x0CF, 0x011, 0x049, 0x04B, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x012, 0x07A, 0x044, 0x016, 0x000, 0x005, 0x03F, 0x06F, - 0x077, 0x000, 0x000, 0x000 -}; - -static const uint8_t SpectrumA42Bits[256] = -{ - 5, 6, 7, 7, 7, 7, 8, 8, 0, 8, 8, 7, 7, 7, 7, 6, - 6, 7, 7, 8, 7, 7, 8, 8, 0, 8, 8, 7, 7, 8, 7, 7, - 7, 7, 8, 8, 7, 8, 8, 9, 0, 9, 8, 8, 7, 8, 8, 7, - 8, 8, 8, 8, 8, 8, 8, 9, 0, 9, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 8, 8, 8, 9, 9, 0, 9, 9, 8, 8, 8, 7, 7, - 7, 7, 8, 8, 8, 9, 9, 9, 0, 9, 9, 9, 8, 8, 8, 7, - 8, 8, 8, 8, 9, 9, 9, 10, 0, 10, 9, 9, 9, 8, 8, 8, - 8, 8, 9, 9, 9, 9, 10, 10, 0, 10, 10, 9, 9, 9, 9, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 9, 9, 9, 9, 9, 10, 10, 0, 10, 10, 9, 9, 9, 9, 8, - 8, 8, 8, 8, 9, 9, 9, 10, 0, 10, 9, 9, 9, 8, 8, 8, - 7, 7, 8, 8, 8, 9, 9, 9, 0, 9, 9, 9, 8, 8, 8, 7, - 7, 7, 7, 8, 8, 8, 9, 9, 0, 9, 9, 8, 8, 8, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 9, 0, 9, 8, 8, 8, 8, 8, 8, - 7, 7, 8, 8, 7, 8, 8, 9, 0, 9, 8, 8, 7, 8, 8, 7, - 6, 7, 7, 8, 7, 7, 8, 8, 0, 8, 8, 7, 7, 8, 7, 7 -}; - -static const uint16_t SpectrumA42Codes[256] = -{ - 0x003, 0x018, 0x058, 0x000, 0x066, 0x03C, 0x0D6, 0x07C, 0x000, 0x07D, 0x0D7, 0x03D, - 0x067, 0x001, 0x059, 0x019, 0x002, 0x064, 0x036, 0x0DA, 0x04C, 0x01C, 0x0BE, 0x02C, - 0x000, 0x037, 0x0C5, 0x029, 0x04B, 0x0E7, 0x03B, 0x069, 0x044, 0x02E, 0x0FA, 0x092, - 0x020, 0x0F8, 0x086, 0x1FC, 0x000, 0x1E7, 0x07F, 0x0F5, 0x023, 0x0AD, 0x0FD, 0x02D, - 0x0F6, 0x0DC, 0x09C, 0x03E, 0x0F0, 0x0B6, 0x026, 0x186, 0x000, 0x18D, 0x02F, 0x0B5, - 0x0E1, 0x03D, 0x0AF, 0x0D9, 0x054, 0x040, 0x014, 0x0EC, 0x0BC, 0x054, 0x1C6, 0x108, - 0x000, 0x10B, 0x1C5, 0x069, 0x0B9, 0x0DF, 0x019, 0x047, 0x026, 0x008, 0x0E4, 0x0A2, - 0x056, 0x1DC, 0x142, 0x06A, 0x000, 0x091, 0x123, 0x1DF, 0x04B, 0x0A7, 0x0EB, 0x00B, - 0x0C0, 0x09E, 0x06A, 0x022, 0x1AA, 0x140, 0x092, 0x3CA, 0x000, 0x3A7, 0x04B, 0x121, - 0x18F, 0x007, 0x071, 0x0A5, 0x020, 0x004, 0x1A8, 0x174, 0x0E4, 0x068, 0x3A4, 0x2EE, - 0x000, 0x2ED, 0x3C9, 0x049, 0x0E7, 0x185, 0x1D1, 0x1FF, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x021, 0x1FE, 0x1D0, 0x184, 0x0E6, 0x048, 0x3C8, 0x2EC, 0x000, 0x2EF, 0x3A5, 0x069, - 0x0E5, 0x175, 0x1A9, 0x005, 0x0C1, 0x0A4, 0x070, 0x006, 0x18E, 0x120, 0x04A, 0x3A6, - 0x000, 0x3CB, 0x093, 0x141, 0x1AB, 0x023, 0x06B, 0x09F, 0x027, 0x00A, 0x0EA, 0x0A6, - 0x04A, 0x1DE, 0x122, 0x090, 0x000, 0x06B, 0x143, 0x1DD, 0x057, 0x0A3, 0x0E5, 0x009, - 0x055, 0x046, 0x018, 0x0DE, 0x0B8, 0x068, 0x1C4, 0x10A, 0x000, 0x109, 0x1C7, 0x055, - 0x0BD, 0x0ED, 0x015, 0x041, 0x0F7, 0x0D8, 0x0AE, 0x03C, 0x0E0, 0x0B4, 0x02E, 0x18C, - 0x000, 0x187, 0x027, 0x0B7, 0x0F1, 0x03F, 0x09D, 0x0DD, 0x045, 0x02C, 0x0FC, 0x0AC, - 0x022, 0x0F4, 0x07E, 0x1E6, 0x000, 0x1FD, 0x087, 0x0F9, 0x021, 0x093, 0x0FB, 0x02F, - 0x003, 0x068, 0x03A, 0x0E6, 0x04A, 0x028, 0x0C4, 0x036, 0x000, 0x02D, 0x0BF, 0x01D, - 0x04D, 0x0DB, 0x037, 0x065 -}; - -static const uint8_t SpectrumA43Bits[256] = -{ - 4, 6, 6, 7, 7, 8, 8, 9, 0, 9, 8, 8, 7, 7, 6, 6, - 5, 6, 7, 7, 7, 8, 8, 9, 0, 9, 8, 8, 7, 7, 7, 6, - 6, 7, 7, 7, 8, 8, 9, 9, 0, 9, 9, 8, 8, 7, 7, 7, - 7, 7, 7, 8, 8, 8, 9, 10, 0, 10, 9, 9, 8, 8, 7, 7, - 7, 7, 8, 8, 8, 9, 10, 10, 0, 10, 10, 9, 8, 8, 8, 7, - 8, 8, 8, 9, 9, 9, 10, 10, 0, 10, 10, 9, 9, 9, 8, 8, - 8, 9, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 9, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 8, 9, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 9, - 8, 8, 8, 9, 9, 9, 10, 10, 0, 10, 10, 9, 9, 9, 8, 8, - 7, 7, 8, 8, 8, 9, 10, 10, 0, 10, 10, 9, 8, 8, 8, 7, - 7, 7, 7, 8, 8, 9, 9, 10, 0, 10, 9, 8, 8, 8, 7, 7, - 6, 7, 7, 7, 8, 8, 9, 9, 0, 9, 9, 8, 8, 7, 7, 7, - 5, 6, 7, 7, 7, 8, 8, 9, 0, 9, 8, 8, 7, 7, 7, 6 -}; - -static const uint16_t SpectrumA43Codes[256] = -{ - 0x002, 0x03E, 0x016, 0x060, 0x04E, 0x0DC, 0x04A, 0x130, 0x000, 0x131, 0x04B, 0x0DD, - 0x04F, 0x061, 0x017, 0x03F, 0x002, 0x02C, 0x076, 0x042, 0x034, 0x0CE, 0x002, 0x0E8, - 0x000, 0x0CF, 0x001, 0x0D1, 0x037, 0x045, 0x07B, 0x02F, 0x014, 0x072, 0x052, 0x01A, - 0x0E0, 0x080, 0x198, 0x01E, 0x000, 0x01D, 0x19B, 0x083, 0x0DF, 0x019, 0x055, 0x079, - 0x050, 0x03C, 0x004, 0x0C4, 0x096, 0x00C, 0x0EA, 0x34A, 0x000, 0x34F, 0x0ED, 0x1D7, - 0x095, 0x0AF, 0x003, 0x03F, 0x046, 0x026, 0x0D6, 0x092, 0x046, 0x15A, 0x3A8, 0x108, - 0x000, 0x10F, 0x3A3, 0x135, 0x039, 0x091, 0x0D9, 0x031, 0x0D4, 0x0CA, 0x072, 0x1C6, - 0x136, 0x090, 0x2B2, 0x104, 0x000, 0x103, 0x111, 0x08B, 0x133, 0x1D3, 0x071, 0x0C9, - 0x03E, 0x1B4, 0x18C, 0x0CC, 0x38A, 0x2B0, 0x106, 0x0F2, 0x000, 0x0EF, 0x101, 0x113, - 0x3A1, 0x0CB, 0x18F, 0x1B7, 0x0EE, 0x092, 0x388, 0x348, 0x10A, 0x0F4, 0x0F0, 0x0EA, - 0x000, 0x0E9, 0x0ED, 0x0F7, 0x10D, 0x34D, 0x3AB, 0x0C9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x0EF, 0x0C8, 0x3AA, 0x34C, 0x10C, 0x0F6, 0x0EC, 0x0E8, 0x000, 0x0EB, 0x0F1, 0x0F5, - 0x10B, 0x349, 0x389, 0x093, 0x03F, 0x1B6, 0x18E, 0x0CA, 0x3A0, 0x112, 0x100, 0x0EE, - 0x000, 0x0F3, 0x107, 0x2B1, 0x38B, 0x0CD, 0x18D, 0x1B5, 0x0D5, 0x0C8, 0x070, 0x1D2, - 0x132, 0x08A, 0x110, 0x102, 0x000, 0x105, 0x2B3, 0x091, 0x137, 0x1C7, 0x073, 0x0CB, - 0x047, 0x030, 0x0D8, 0x090, 0x038, 0x134, 0x3A2, 0x10E, 0x000, 0x109, 0x3A9, 0x15B, - 0x047, 0x093, 0x0D7, 0x027, 0x051, 0x03E, 0x002, 0x0AE, 0x094, 0x1D6, 0x0EC, 0x34E, - 0x000, 0x34B, 0x0EB, 0x00D, 0x097, 0x0C5, 0x005, 0x03D, 0x015, 0x078, 0x054, 0x018, - 0x0DE, 0x082, 0x19A, 0x01C, 0x000, 0x01F, 0x199, 0x081, 0x0E1, 0x01B, 0x053, 0x073, - 0x003, 0x02E, 0x07A, 0x044, 0x036, 0x0D0, 0x000, 0x0CE, 0x000, 0x0E9, 0x003, 0x0CF, - 0x035, 0x043, 0x077, 0x02D -}; - -static const uint8_t SpectrumA44Bits[256] = -{ - 4, 5, 6, 7, 7, 8, 9, 10, 0, 10, 9, 8, 7, 7, 6, 5, - 5, 6, 6, 7, 7, 8, 9, 10, 0, 10, 9, 8, 7, 7, 6, 6, - 6, 6, 7, 7, 8, 9, 10, 10, 0, 10, 10, 9, 8, 7, 7, 6, - 7, 7, 7, 8, 8, 9, 10, 10, 0, 10, 10, 9, 8, 8, 7, 7, - 7, 8, 8, 8, 9, 10, 10, 10, 0, 10, 10, 10, 9, 8, 8, 7, - 8, 8, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 8, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 8, 8, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 8, - 7, 7, 8, 8, 9, 10, 10, 10, 0, 10, 10, 10, 9, 8, 8, 8, - 7, 7, 7, 8, 8, 9, 10, 10, 0, 10, 10, 9, 8, 8, 7, 7, - 6, 6, 7, 7, 8, 9, 10, 10, 0, 10, 10, 9, 8, 7, 7, 6, - 5, 6, 6, 7, 7, 8, 9, 10, 0, 10, 9, 8, 7, 7, 6, 6 -}; - -static const uint16_t SpectrumA44Codes[256] = -{ - 0x00A, 0x012, 0x030, 0x06E, 0x024, 0x074, 0x0EC, 0x07E, 0x000, 0x07F, 0x0ED, 0x075, - 0x025, 0x06F, 0x031, 0x013, 0x010, 0x03C, 0x018, 0x05A, 0x002, 0x046, 0x09E, 0x07C, - 0x000, 0x079, 0x0E5, 0x04D, 0x007, 0x065, 0x01B, 0x03F, 0x02E, 0x016, 0x072, 0x01A, - 0x0D6, 0x1C6, 0x3B4, 0x066, 0x000, 0x06B, 0x3B7, 0x1D9, 0x0D5, 0x021, 0x075, 0x015, - 0x06C, 0x03E, 0x01E, 0x0CC, 0x044, 0x0F2, 0x082, 0x05C, 0x000, 0x05F, 0x087, 0x0F5, - 0x031, 0x0CF, 0x017, 0x059, 0x01C, 0x0EE, 0x0D0, 0x024, 0x1C0, 0x08E, 0x06E, 0x048, - 0x000, 0x04D, 0x06D, 0x089, 0x0F7, 0x033, 0x0D3, 0x001, 0x070, 0x028, 0x1C2, 0x0F0, - 0x08A, 0x074, 0x054, 0x040, 0x000, 0x043, 0x053, 0x073, 0x099, 0x0EF, 0x1C5, 0x02B, - 0x0E6, 0x04E, 0x08C, 0x080, 0x068, 0x058, 0x046, 0x02A, 0x000, 0x029, 0x045, 0x051, - 0x065, 0x085, 0x09B, 0x09D, 0x07A, 0x076, 0x060, 0x056, 0x04E, 0x02C, 0x024, 0x022, - 0x000, 0x021, 0x027, 0x02F, 0x04B, 0x05B, 0x063, 0x071, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x07B, 0x070, 0x062, 0x05A, 0x04A, 0x02E, 0x026, 0x020, 0x000, 0x023, 0x025, 0x02D, - 0x04F, 0x057, 0x061, 0x077, 0x0E7, 0x09C, 0x09A, 0x084, 0x064, 0x050, 0x044, 0x028, - 0x000, 0x02B, 0x047, 0x059, 0x069, 0x081, 0x08D, 0x04F, 0x071, 0x02A, 0x1C4, 0x0EE, - 0x098, 0x072, 0x052, 0x042, 0x000, 0x041, 0x055, 0x075, 0x08B, 0x0F1, 0x1C3, 0x029, - 0x01D, 0x000, 0x0D2, 0x032, 0x0F6, 0x088, 0x06C, 0x04C, 0x000, 0x049, 0x06F, 0x08F, - 0x1C1, 0x025, 0x0D1, 0x0EF, 0x06D, 0x058, 0x016, 0x0CE, 0x030, 0x0F4, 0x086, 0x05E, - 0x000, 0x05D, 0x083, 0x0F3, 0x045, 0x0CD, 0x01F, 0x03F, 0x02F, 0x014, 0x074, 0x020, - 0x0D4, 0x1D8, 0x3B6, 0x06A, 0x000, 0x067, 0x3B5, 0x1C7, 0x0D7, 0x01B, 0x073, 0x017, - 0x011, 0x03E, 0x01A, 0x064, 0x006, 0x04C, 0x0E4, 0x078, 0x000, 0x07D, 0x09F, 0x047, - 0x003, 0x05B, 0x019, 0x03D -}; - -static const uint8_t SpectrumA51Bits[32] = -{ - 5, 5, 5, 5, 5, 6, 6, 6, 4, 4, 5, 5, 5, 5, 5, 5, - 0, 5, 5, 5, 5, 5, 5, 4, 4, 6, 6, 6, 5, 5, 5, 5 -}; - -static const uint16_t SpectrumA51Codes[32] = -{ - 0x19, 0x16, 0x12, 0x0E, 0x06, 0x3A, 0x38, 0x30, 0x00, 0x04, 0x1E, 0x1A, 0x14, 0x10, 0x0C, 0x04, - 0x00, 0x05, 0x0D, 0x11, 0x15, 0x1B, 0x1F, 0x05, 0x01, 0x31, 0x39, 0x3B, 0x07, 0x0F, 0x13, 0x17 -}; - -static const uint8_t SpectrumA52Bits[32] = -{ - 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, - 0, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4 -}; - -static const uint16_t SpectrumA52Codes[32] = -{ - 0x09, 0x04, 0x00, 0x1E, 0x1A, 0x14, 0x0C, 0x06, 0x18, 0x16, 0x0E, 0x04, 0x3A, 0x38, 0x22, 0x20, - 0x00, 0x21, 0x23, 0x39, 0x3B, 0x05, 0x0F, 0x17, 0x19, 0x07, 0x0D, 0x15, 0x1B, 0x1F, 0x01, 0x05 -}; - -static const uint8_t SpectrumA53Bits[32] = -{ - 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 7, - 0, 7, 7, 7, 7, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4 -}; - -static const uint16_t SpectrumA53Codes[32] = -{ - 0x00, 0x0C, 0x08, 0x04, 0x1E, 0x16, 0x14, 0x06, 0x0C, 0x04, 0x38, 0x1E, 0x76, 0x74, 0x3A, 0x38, - 0x00, 0x39, 0x3B, 0x75, 0x77, 0x1F, 0x39, 0x05, 0x0D, 0x07, 0x15, 0x17, 0x1F, 0x05, 0x09, 0x0D -}; - -static const uint8_t SpectrumA54Bits[32] = -{ - 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, - 0, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4 -}; - -static const uint16_t SpectrumA54Codes[32] = -{ - 0x02, 0x0E, 0x0A, 0x08, 0x02, 0x1A, 0x0E, 0x02, 0x00, 0x30, 0x18, 0x66, 0x36, 0x34, 0xCA, 0xC8, - 0x00, 0xC9, 0xCB, 0x35, 0x37, 0x67, 0x19, 0x31, 0x01, 0x03, 0x0F, 0x1B, 0x03, 0x09, 0x0B, 0x0F -}; - -static const uint8_t SpectrumA61Bits[64] = -{ - 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, - 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, - 5, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6 -}; - -static const uint16_t SpectrumA61Codes[64] = -{ - 0x35, 0x30, 0x2A, 0x28, 0x24, 0x20, 0x18, 0x0E, 0x0C, 0x7E, 0x7C, 0x72, 0x70, 0x68, 0x5E, 0x5C, - 0x04, 0x0E, 0x08, 0x00, 0x3C, 0x3A, 0x36, 0x32, 0x2C, 0x26, 0x22, 0x1A, 0x16, 0x14, 0x06, 0x04, - 0x00, 0x05, 0x07, 0x15, 0x17, 0x1B, 0x23, 0x27, 0x2D, 0x33, 0x37, 0x3B, 0x3D, 0x01, 0x09, 0x0F, - 0x05, 0x5D, 0x5F, 0x69, 0x71, 0x73, 0x7D, 0x7F, 0x0D, 0x0F, 0x19, 0x21, 0x25, 0x29, 0x2B, 0x31 -}; - -static const uint8_t SpectrumA62Bits[64] = -{ - 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, - 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 -}; - -static const uint16_t SpectrumA62Codes[64] = -{ - 0x14, 0x0E, 0x08, 0x04, 0x02, 0x3E, 0x3C, 0x38, 0x34, 0x30, 0x2A, 0x24, 0x1A, 0x18, 0x0E, 0x02, - 0x32, 0x36, 0x2C, 0x26, 0x20, 0x16, 0x0C, 0x00, 0x76, 0x74, 0x5E, 0x5C, 0x46, 0x44, 0x2A, 0x28, - 0x00, 0x29, 0x2B, 0x45, 0x47, 0x5D, 0x5F, 0x75, 0x77, 0x01, 0x0D, 0x17, 0x21, 0x27, 0x2D, 0x37, - 0x33, 0x03, 0x0F, 0x19, 0x1B, 0x25, 0x2B, 0x31, 0x35, 0x39, 0x3D, 0x3F, 0x03, 0x05, 0x09, 0x0F -}; - -static const uint8_t SpectrumA63Bits[64] = -{ - 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, - 0, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5 -}; - -static const uint16_t SpectrumA63Codes[64] = -{ - 0x00, 0x1C, 0x18, 0x14, 0x10, 0x0A, 0x08, 0x02, 0x3E, 0x36, 0x2E, 0x2C, 0x24, 0x1C, 0x0E, 0x08, - 0x1E, 0x1A, 0x0C, 0x7A, 0x6A, 0x68, 0x4C, 0x32, 0x16, 0x14, 0xF2, 0xF0, 0x9E, 0x9C, 0x62, 0x60, - 0x00, 0x61, 0x63, 0x9D, 0x9F, 0xF1, 0xF3, 0x15, 0x17, 0x33, 0x4D, 0x69, 0x6B, 0x7B, 0x0D, 0x1B, - 0x1F, 0x09, 0x0F, 0x1D, 0x25, 0x2D, 0x2F, 0x37, 0x3F, 0x03, 0x09, 0x0B, 0x11, 0x15, 0x19, 0x1D -}; - -static const uint8_t SpectrumA64Bits[64] = -{ - 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, - 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, - 6, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4 -}; - -static const uint16_t SpectrumA64Codes[64] = -{ - 0x006, 0x002, 0x01C, 0x01A, 0x016, 0x012, 0x00E, 0x00A, 0x002, 0x03E, 0x032, 0x02A, - 0x022, 0x020, 0x010, 0x07A, 0x000, 0x078, 0x060, 0x050, 0x024, 0x006, 0x0C6, 0x0C4, - 0x0A4, 0x04E, 0x00A, 0x008, 0x14E, 0x14C, 0x09A, 0x098, 0x000, 0x099, 0x09B, 0x14D, - 0x14F, 0x009, 0x00B, 0x04F, 0x0A5, 0x0C5, 0x0C7, 0x007, 0x025, 0x051, 0x061, 0x079, - 0x001, 0x07B, 0x011, 0x021, 0x023, 0x02B, 0x033, 0x03F, 0x003, 0x00B, 0x00F, 0x013, - 0x017, 0x01B, 0x01D, 0x003 -}; - -static const uint8_t SpectrumA71Bits[128] = -{ - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, - 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 -}; - -static const uint16_t SpectrumA71Codes[128] = -{ - 0x6C, 0x66, 0x62, 0x5C, 0x56, 0x50, 0x52, 0x4E, 0x48, 0x3E, 0x36, 0x34, 0x2A, 0x26, 0x1E, 0x16, - 0x0E, 0x08, 0x00, 0xF6, 0xF4, 0xEE, 0xEC, 0xE2, 0xE0, 0xDA, 0xD2, 0xD0, 0xBE, 0xBC, 0xB2, 0xB0, - 0x0C, 0x20, 0x1C, 0x16, 0x10, 0x08, 0x02, 0x7E, 0x7C, 0x78, 0x74, 0x72, 0x6E, 0x6A, 0x64, 0x60, - 0x5A, 0x54, 0x4C, 0x4A, 0x46, 0x44, 0x3C, 0x32, 0x30, 0x28, 0x24, 0x1C, 0x14, 0x0C, 0x0A, 0x02, - 0x00, 0x03, 0x0B, 0x0D, 0x15, 0x1D, 0x25, 0x29, 0x31, 0x33, 0x3D, 0x45, 0x47, 0x4B, 0x4D, 0x55, - 0x5B, 0x61, 0x65, 0x6B, 0x6F, 0x73, 0x75, 0x79, 0x7D, 0x7F, 0x03, 0x09, 0x11, 0x17, 0x1D, 0x21, - 0x0D, 0xB1, 0xB3, 0xBD, 0xBF, 0xD1, 0xD3, 0xDB, 0xE1, 0xE3, 0xED, 0xEF, 0xF5, 0xF7, 0x01, 0x09, - 0x0F, 0x17, 0x1F, 0x27, 0x2B, 0x35, 0x37, 0x3F, 0x49, 0x4F, 0x53, 0x51, 0x57, 0x5D, 0x63, 0x67 -}; - -static const uint8_t SpectrumA72Bits[128] = -{ - 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6 -}; - -static const uint16_t SpectrumA72Codes[128] = -{ - 0x2A, 0x24, 0x1C, 0x18, 0x12, 0x0E, 0x0A, 0x06, 0x02, 0x7E, 0x7C, 0x7A, 0x76, 0x72, 0x70, 0x6A, - 0x68, 0x62, 0x5C, 0x5A, 0x52, 0x4E, 0x46, 0x42, 0x3C, 0x34, 0x2A, 0x28, 0x20, 0x12, 0x10, 0x08, - 0x66, 0x74, 0x6C, 0x64, 0x5E, 0x58, 0x50, 0x44, 0x40, 0x36, 0x2C, 0x22, 0x1A, 0x0A, 0x02, 0x00, - 0xF2, 0xF0, 0xDE, 0xDC, 0xC2, 0xC0, 0xAE, 0xAC, 0x9A, 0x98, 0x7E, 0x7C, 0x5E, 0x5C, 0x32, 0x30, - 0x00, 0x31, 0x33, 0x5D, 0x5F, 0x7D, 0x7F, 0x99, 0x9B, 0xAD, 0xAF, 0xC1, 0xC3, 0xDD, 0xDF, 0xF1, - 0xF3, 0x01, 0x03, 0x0B, 0x1B, 0x23, 0x2D, 0x37, 0x41, 0x45, 0x51, 0x59, 0x5F, 0x65, 0x6D, 0x75, - 0x67, 0x09, 0x11, 0x13, 0x21, 0x29, 0x2B, 0x35, 0x3D, 0x43, 0x47, 0x4F, 0x53, 0x5B, 0x5D, 0x63, - 0x69, 0x6B, 0x71, 0x73, 0x77, 0x7B, 0x7D, 0x7F, 0x03, 0x07, 0x0B, 0x0F, 0x13, 0x19, 0x1D, 0x25 -}; - -static const uint8_t SpectrumA73Bits[128] = -{ - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 -}; - -static const uint16_t SpectrumA73Codes[128] = -{ - 0x003, 0x03E, 0x038, 0x034, 0x030, 0x02C, 0x028, 0x024, 0x020, 0x01C, 0x016, 0x014, - 0x00E, 0x00A, 0x004, 0x000, 0x07A, 0x076, 0x06E, 0x06C, 0x064, 0x05E, 0x056, 0x04E, - 0x04C, 0x044, 0x036, 0x030, 0x022, 0x018, 0x012, 0x004, 0x03C, 0x03E, 0x032, 0x024, - 0x020, 0x010, 0x0F2, 0x0F0, 0x0E8, 0x0CE, 0x0BA, 0x0B8, 0x0A8, 0x08C, 0x06A, 0x04E, - 0x04C, 0x034, 0x00E, 0x00C, 0x1D6, 0x1D4, 0x19A, 0x198, 0x156, 0x154, 0x11E, 0x11C, - 0x0D2, 0x0D0, 0x06E, 0x06C, 0x000, 0x06D, 0x06F, 0x0D1, 0x0D3, 0x11D, 0x11F, 0x155, - 0x157, 0x199, 0x19B, 0x1D5, 0x1D7, 0x00D, 0x00F, 0x035, 0x04D, 0x04F, 0x06B, 0x08D, - 0x0A9, 0x0B9, 0x0BB, 0x0CF, 0x0E9, 0x0F1, 0x0F3, 0x011, 0x021, 0x025, 0x033, 0x03F, - 0x03D, 0x005, 0x013, 0x019, 0x023, 0x031, 0x037, 0x045, 0x04D, 0x04F, 0x057, 0x05F, - 0x065, 0x06D, 0x06F, 0x077, 0x07B, 0x001, 0x005, 0x00B, 0x00F, 0x015, 0x017, 0x01D, - 0x021, 0x025, 0x029, 0x02D, 0x031, 0x035, 0x039, 0x03F -}; - -static const uint8_t SpectrumA74Bits[128] = -{ - 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5 -}; - -static const uint16_t SpectrumA74Codes[128] = -{ - 0x00D, 0x00A, 0x004, 0x000, 0x03A, 0x036, 0x032, 0x030, 0x02C, 0x028, 0x026, 0x022, - 0x01E, 0x018, 0x012, 0x00E, 0x006, 0x07E, 0x07A, 0x070, 0x06A, 0x05E, 0x056, 0x054, - 0x048, 0x040, 0x038, 0x022, 0x01A, 0x00A, 0x0F8, 0x0E6, 0x008, 0x0FA, 0x0F0, 0x0D2, - 0x0BA, 0x0B8, 0x094, 0x084, 0x074, 0x042, 0x032, 0x1E6, 0x1CA, 0x1C8, 0x1A2, 0x12E, - 0x10E, 0x10C, 0x0EC, 0x082, 0x062, 0x060, 0x3CA, 0x3C8, 0x342, 0x340, 0x25A, 0x258, - 0x1DE, 0x1DC, 0x102, 0x100, 0x000, 0x101, 0x103, 0x1DD, 0x1DF, 0x259, 0x25B, 0x341, - 0x343, 0x3C9, 0x3CB, 0x061, 0x063, 0x083, 0x0ED, 0x10D, 0x10F, 0x12F, 0x1A3, 0x1C9, - 0x1CB, 0x1E7, 0x033, 0x043, 0x075, 0x085, 0x095, 0x0B9, 0x0BB, 0x0D3, 0x0F1, 0x0FB, - 0x009, 0x0E7, 0x0F9, 0x00B, 0x01B, 0x023, 0x039, 0x041, 0x049, 0x055, 0x057, 0x05F, - 0x06B, 0x071, 0x07B, 0x07F, 0x007, 0x00F, 0x013, 0x019, 0x01F, 0x023, 0x027, 0x029, - 0x02D, 0x031, 0x033, 0x037, 0x03B, 0x001, 0x005, 0x00B -}; - -static const uint8_t SpectrumB22Bits[256] = -{ - 0, 4, 0, 4, 4, 5, 0, 5, 0, 0, 0, 0, 4, 5, 0, 5, - 4, 7, 0, 6, 6, 9, 0, 7, 0, 0, 0, 0, 6, 9, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 6, 0, 7, 6, 7, 0, 9, 0, 0, 0, 0, 6, 7, 0, 9, - 4, 8, 0, 8, 8, 10, 0, 10, 0, 0, 0, 0, 6, 9, 0, 9, - 5, 10, 0, 9, 9, 10, 0, 10, 0, 0, 0, 0, 7, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 9, 0, 10, 9, 10, 0, 10, 0, 0, 0, 0, 7, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 8, 0, 8, 6, 9, 0, 9, 0, 0, 0, 0, 8, 10, 0, 10, - 6, 10, 0, 9, 7, 10, 0, 10, 0, 0, 0, 0, 9, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 9, 0, 10, 7, 10, 0, 10, 0, 0, 0, 0, 9, 10, 0, 10 -}; - -static const uint16_t SpectrumB22Codes[256] = -{ - 0x000, 0x00E, 0x000, 0x00F, 0x008, 0x006, 0x000, 0x00B, 0x000, 0x000, 0x000, 0x000, - 0x009, 0x00A, 0x000, 0x007, 0x006, 0x00A, 0x000, 0x029, 0x006, 0x158, 0x000, 0x023, - 0x000, 0x000, 0x000, 0x000, 0x013, 0x174, 0x000, 0x021, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x007, 0x028, 0x000, 0x00B, 0x012, 0x020, 0x000, 0x175, 0x000, 0x000, 0x000, 0x000, - 0x007, 0x022, 0x000, 0x159, 0x00C, 0x0BC, 0x000, 0x0BF, 0x022, 0x2B8, 0x000, 0x2BB, - 0x000, 0x000, 0x000, 0x000, 0x00B, 0x170, 0x000, 0x15B, 0x000, 0x04E, 0x000, 0x15F, - 0x042, 0x04A, 0x000, 0x041, 0x000, 0x000, 0x000, 0x000, 0x055, 0x044, 0x000, 0x04D, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x02D, 0x172, 0x000, 0x2ED, 0x040, 0x042, 0x000, 0x047, - 0x000, 0x000, 0x000, 0x000, 0x013, 0x2EE, 0x000, 0x049, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x00D, 0x0BE, 0x000, 0x0BD, 0x00A, 0x15A, 0x000, 0x171, 0x000, 0x000, 0x000, 0x000, - 0x023, 0x2BA, 0x000, 0x2B9, 0x02C, 0x2EC, 0x000, 0x173, 0x012, 0x048, 0x000, 0x2EF, - 0x000, 0x000, 0x000, 0x000, 0x041, 0x046, 0x000, 0x043, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x001, 0x15E, 0x000, 0x04F, 0x054, 0x04C, 0x000, 0x045, 0x000, 0x000, 0x000, 0x000, - 0x043, 0x040, 0x000, 0x04B -}; - -static const uint8_t SpectrumB23Bits[256] = -{ - 2, 4, 0, 4, 4, 6, 0, 6, 0, 0, 0, 0, 4, 6, 0, 6, - 4, 9, 0, 7, 7, 9, 0, 8, 0, 0, 0, 0, 7, 9, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 7, 0, 9, 7, 8, 0, 9, 0, 0, 0, 0, 7, 8, 0, 9, - 4, 8, 0, 8, 9, 10, 0, 10, 0, 0, 0, 0, 7, 10, 0, 10, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 9, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 8, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 8, 0, 8, 7, 10, 0, 10, 0, 0, 0, 0, 9, 10, 0, 10, - 7, 10, 0, 10, 8, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 10, 0, 10, 9, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10 -}; - -static const uint16_t SpectrumB23Codes[256] = -{ - 0x003, 0x008, 0x000, 0x009, 0x002, 0x018, 0x000, 0x01B, 0x000, 0x000, 0x000, 0x000, - 0x003, 0x01A, 0x000, 0x019, 0x000, 0x17C, 0x000, 0x055, 0x056, 0x0E8, 0x000, 0x07D, - 0x000, 0x000, 0x000, 0x000, 0x059, 0x0F6, 0x000, 0x07F, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x001, 0x054, 0x000, 0x17D, 0x058, 0x07E, 0x000, 0x0F7, 0x000, 0x000, 0x000, 0x000, - 0x057, 0x07C, 0x000, 0x0E9, 0x004, 0x0A2, 0x000, 0x0A1, 0x17A, 0x1DA, 0x000, 0x1D9, - 0x000, 0x000, 0x000, 0x000, 0x053, 0x1E8, 0x000, 0x2F3, 0x05C, 0x1D6, 0x000, 0x1E7, - 0x1EA, 0x1E2, 0x000, 0x1CF, 0x000, 0x000, 0x000, 0x000, 0x17F, 0x1CA, 0x000, 0x1DD, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x05B, 0x2F0, 0x000, 0x1DF, 0x1E4, 0x1CC, 0x000, 0x1D5, - 0x000, 0x000, 0x000, 0x000, 0x071, 0x1E0, 0x000, 0x1C9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x005, 0x0A0, 0x000, 0x0A3, 0x052, 0x2F2, 0x000, 0x1E9, 0x000, 0x000, 0x000, 0x000, - 0x17B, 0x1D8, 0x000, 0x1DB, 0x05A, 0x1DE, 0x000, 0x2F1, 0x070, 0x1C8, 0x000, 0x1E1, - 0x000, 0x000, 0x000, 0x000, 0x1E5, 0x1D4, 0x000, 0x1CD, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x05D, 0x1E6, 0x000, 0x1D7, 0x17E, 0x1DC, 0x000, 0x1CB, 0x000, 0x000, 0x000, 0x000, - 0x1EB, 0x1CE, 0x000, 0x1E3 -}; - -static const uint8_t SpectrumB24Bits[256] = -{ - 1, 4, 0, 4, 5, 7, 0, 7, 0, 0, 0, 0, 5, 7, 0, 7, - 5, 9, 0, 7, 8, 10, 0, 9, 0, 0, 0, 0, 7, 10, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 7, 0, 9, 7, 9, 0, 10, 0, 0, 0, 0, 8, 9, 0, 10, - 5, 9, 0, 8, 9, 10, 0, 10, 0, 0, 0, 0, 7, 10, 0, 10, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 8, 0, 9, 7, 10, 0, 10, 0, 0, 0, 0, 9, 10, 0, 10, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10 -}; - -static const uint16_t SpectrumB24Codes[256] = -{ - 0x001, 0x000, 0x000, 0x001, 0x00A, 0x01C, 0x000, 0x033, 0x000, 0x000, 0x000, 0x000, - 0x00B, 0x032, 0x000, 0x01D, 0x008, 0x0D8, 0x000, 0x031, 0x06E, 0x0FA, 0x000, 0x0D7, - 0x000, 0x000, 0x000, 0x000, 0x011, 0x0F4, 0x000, 0x0D5, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x009, 0x030, 0x000, 0x0D9, 0x010, 0x0D4, 0x000, 0x0F5, 0x000, 0x000, 0x000, 0x000, - 0x06F, 0x0D6, 0x000, 0x0FB, 0x00E, 0x0DA, 0x000, 0x025, 0x0D2, 0x0D4, 0x000, 0x0DB, - 0x000, 0x000, 0x000, 0x000, 0x017, 0x0FE, 0x000, 0x0FD, 0x014, 0x0DC, 0x000, 0x0F9, - 0x0F2, 0x0D6, 0x000, 0x09B, 0x000, 0x000, 0x000, 0x000, 0x1A3, 0x09C, 0x000, 0x0D3, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x019, 0x0F6, 0x000, 0x0D9, 0x0F0, 0x09E, 0x000, 0x0D1, - 0x000, 0x000, 0x000, 0x000, 0x1A1, 0x0DE, 0x000, 0x099, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x00F, 0x024, 0x000, 0x0DB, 0x016, 0x0FC, 0x000, 0x0FF, 0x000, 0x000, 0x000, 0x000, - 0x0D3, 0x0DA, 0x000, 0x0D5, 0x018, 0x0D8, 0x000, 0x0F7, 0x1A0, 0x098, 0x000, 0x0DF, - 0x000, 0x000, 0x000, 0x000, 0x0F1, 0x0D0, 0x000, 0x09F, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x015, 0x0F8, 0x000, 0x0DD, 0x1A2, 0x0D2, 0x000, 0x09D, 0x000, 0x000, 0x000, 0x000, - 0x0F3, 0x09A, 0x000, 0x0D7 -}; - -static const uint8_t SpectrumB32Bits[64] = -{ - 2, 4, 5, 6, 0, 6, 5, 4, 5, 6, 6, 7, 0, 6, 5, 6, - 5, 6, 7, 7, 0, 8, 7, 6, 6, 7, 8, 9, 0, 9, 8, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 0, 9, 8, 7, - 5, 6, 7, 8, 0, 7, 7, 6, 5, 6, 5, 6, 0, 7, 6, 6 -}; - -static const uint16_t SpectrumB32Codes[64] = -{ - 0x001, 0x002, 0x01E, 0x02A, 0x000, 0x02B, 0x01F, 0x003, 0x016, 0x020, 0x03A, 0x064, - 0x000, 0x005, 0x001, 0x023, 0x01A, 0x026, 0x070, 0x00C, 0x000, 0x0CF, 0x073, 0x031, - 0x024, 0x00E, 0x0CC, 0x146, 0x000, 0x145, 0x0A1, 0x053, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x025, 0x052, 0x0A0, 0x144, 0x000, 0x147, 0x0CD, 0x00F, - 0x01B, 0x030, 0x072, 0x0CE, 0x000, 0x00D, 0x071, 0x027, 0x017, 0x022, 0x000, 0x004, - 0x000, 0x065, 0x03B, 0x021 -}; - -static const uint8_t SpectrumB33Bits[64] = -{ - 2, 4, 5, 7, 0, 7, 5, 4, 4, 5, 6, 8, 0, 7, 6, 5, - 5, 6, 7, 9, 0, 8, 7, 6, 7, 8, 9, 10, 0, 10, 9, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 0, 10, 9, 8, - 5, 6, 7, 8, 0, 9, 7, 6, 4, 5, 6, 7, 0, 8, 6, 5 -}; - -static const uint16_t SpectrumB33Codes[64] = -{ - 0x003, 0x008, 0x014, 0x05E, 0x000, 0x05F, 0x015, 0x009, 0x004, 0x002, 0x01C, 0x0BA, - 0x000, 0x011, 0x01F, 0x001, 0x00C, 0x00C, 0x014, 0x166, 0x000, 0x02D, 0x013, 0x00F, - 0x05A, 0x0B0, 0x05E, 0x0B8, 0x000, 0x0BB, 0x165, 0x0B9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x05B, 0x0B8, 0x164, 0x0BA, 0x000, 0x0B9, 0x05F, 0x0B1, - 0x00D, 0x00E, 0x012, 0x02C, 0x000, 0x167, 0x015, 0x00D, 0x005, 0x000, 0x01E, 0x010, - 0x000, 0x0BB, 0x01D, 0x003 -}; - -static const uint8_t SpectrumB34Bits[64] = -{ - 1, 4, 6, 8, 0, 8, 6, 4, 4, 6, 7, 9, 0, 8, 7, 6, - 6, 7, 8, 10, 0, 10, 8, 7, 8, 9, 10, 10, 0, 10, 10, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10, 10, 0, 10, 10, 9, - 6, 7, 8, 10, 0, 10, 8, 7, 4, 6, 7, 8, 0, 9, 7, 6 -}; - -static const uint16_t SpectrumB34Codes[64] = -{ - 0x000, 0x00A, 0x038, 0x0EE, 0x000, 0x0EF, 0x039, 0x00B, 0x008, 0x03C, 0x06E, 0x1D8, - 0x000, 0x0C1, 0x075, 0x03F, 0x032, 0x068, 0x0C4, 0x358, 0x000, 0x30F, 0x0C7, 0x06D, - 0x0D4, 0x1AE, 0x30C, 0x308, 0x000, 0x30B, 0x35B, 0x1DB, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x0D5, 0x1DA, 0x35A, 0x30A, 0x000, 0x309, 0x30D, 0x1AF, - 0x033, 0x06C, 0x0C6, 0x30E, 0x000, 0x359, 0x0C5, 0x069, 0x009, 0x03E, 0x074, 0x0C0, - 0x000, 0x1D9, 0x06F, 0x03D -}; - -static const uint8_t SpectrumB42Bits[256] = -{ - 4, 5, 6, 8, 6, 7, 8, 8, 0, 8, 8, 7, 6, 8, 6, 5, - 5, 6, 7, 8, 7, 7, 8, 9, 0, 8, 8, 7, 7, 8, 7, 6, - 7, 7, 8, 9, 7, 8, 9, 9, 0, 9, 9, 8, 7, 9, 8, 7, - 8, 9, 9, 10, 8, 8, 9, 10, 0, 10, 9, 8, 8, 10, 9, 8, - 6, 7, 8, 8, 9, 9, 10, 10, 0, 10, 10, 9, 9, 8, 8, 7, - 7, 7, 8, 9, 9, 10, 10, 10, 0, 10, 10, 10, 9, 9, 8, 7, - 8, 8, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 8, - 8, 9, 9, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 9, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 9, 9, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 9, 9, - 8, 8, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 8, - 7, 7, 8, 9, 9, 10, 10, 10, 0, 10, 10, 10, 9, 9, 8, 7, - 6, 7, 8, 8, 9, 9, 10, 10, 0, 10, 10, 9, 9, 8, 8, 7, - 8, 8, 9, 10, 8, 8, 9, 10, 0, 10, 9, 8, 8, 10, 9, 9, - 7, 7, 8, 9, 7, 8, 9, 9, 0, 9, 9, 8, 7, 9, 8, 7, - 5, 6, 7, 8, 7, 7, 8, 8, 0, 9, 8, 7, 7, 8, 7, 6 -}; - -static const uint16_t SpectrumB42Codes[256] = -{ - 0x00E, 0x018, 0x010, 0x0F0, 0x024, 0x05A, 0x0F6, 0x078, 0x000, 0x079, 0x0F7, 0x05B, - 0x025, 0x0F1, 0x011, 0x019, 0x00C, 0x014, 0x01C, 0x036, 0x05C, 0x012, 0x09E, 0x1E4, - 0x000, 0x00B, 0x0A9, 0x03B, 0x05F, 0x071, 0x019, 0x017, 0x06E, 0x000, 0x03E, 0x114, - 0x002, 0x0B0, 0x1AA, 0x07A, 0x000, 0x099, 0x1E7, 0x0B3, 0x00B, 0x131, 0x07F, 0x00D, - 0x0D8, 0x1FE, 0x112, 0x22E, 0x086, 0x010, 0x134, 0x35C, 0x000, 0x35F, 0x133, 0x013, - 0x081, 0x22D, 0x119, 0x07B, 0x00A, 0x050, 0x0F8, 0x04E, 0x1B4, 0x154, 0x3EC, 0x0D2, - 0x000, 0x0D7, 0x3D7, 0x137, 0x1FD, 0x073, 0x0FD, 0x057, 0x052, 0x010, 0x08E, 0x1E8, - 0x11A, 0x3EE, 0x0F2, 0x03C, 0x000, 0x03F, 0x0F1, 0x3D5, 0x111, 0x1F5, 0x09D, 0x025, - 0x0D2, 0x082, 0x1A0, 0x0F8, 0x36E, 0x0D4, 0x072, 0x03A, 0x000, 0x027, 0x071, 0x07D, - 0x36D, 0x0FB, 0x1AD, 0x085, 0x00C, 0x1A8, 0x03C, 0x346, 0x0D0, 0x076, 0x024, 0x020, - 0x000, 0x023, 0x039, 0x075, 0x07F, 0x345, 0x09B, 0x157, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x00D, 0x156, 0x09A, 0x344, 0x07E, 0x074, 0x038, 0x022, 0x000, 0x021, 0x025, 0x077, - 0x0D1, 0x347, 0x03D, 0x1A9, 0x0D3, 0x084, 0x1AC, 0x0FA, 0x36C, 0x07C, 0x070, 0x026, - 0x000, 0x03B, 0x073, 0x0D5, 0x36F, 0x0F9, 0x1A1, 0x083, 0x053, 0x024, 0x09C, 0x1F4, - 0x110, 0x3D4, 0x0F0, 0x03E, 0x000, 0x03D, 0x0F3, 0x3EF, 0x11B, 0x1E9, 0x08F, 0x011, - 0x00B, 0x056, 0x0FC, 0x072, 0x1FC, 0x136, 0x3D6, 0x0D6, 0x000, 0x0D3, 0x3ED, 0x155, - 0x1B5, 0x04F, 0x0F9, 0x051, 0x0D9, 0x07A, 0x118, 0x22C, 0x080, 0x012, 0x132, 0x35E, - 0x000, 0x35D, 0x135, 0x011, 0x087, 0x22F, 0x113, 0x1FF, 0x06F, 0x00C, 0x07E, 0x130, - 0x00A, 0x0B2, 0x1E6, 0x098, 0x000, 0x07B, 0x1AB, 0x0B1, 0x003, 0x115, 0x03F, 0x001, - 0x00D, 0x016, 0x018, 0x070, 0x05E, 0x03A, 0x0A8, 0x00A, 0x000, 0x1E5, 0x09F, 0x013, - 0x05D, 0x037, 0x01D, 0x015 -}; - -static const uint8_t SpectrumB43Bits[256] = -{ - 2, 5, 6, 7, 7, 8, 8, 9, 0, 9, 8, 8, 7, 7, 6, 5, - 5, 6, 7, 8, 7, 8, 9, 10, 0, 10, 9, 8, 7, 8, 7, 6, - 6, 7, 8, 9, 8, 9, 10, 10, 0, 10, 10, 9, 8, 9, 8, 7, - 7, 8, 9, 10, 9, 9, 10, 10, 0, 10, 10, 10, 9, 10, 9, 8, - 7, 8, 8, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 8, 7, - 8, 8, 9, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 9, 8, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 8, 8, 9, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 9, 8, - 7, 7, 8, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 8, 8, - 7, 8, 9, 10, 9, 10, 10, 10, 0, 10, 10, 9, 9, 10, 9, 8, - 6, 7, 8, 9, 8, 9, 10, 10, 0, 10, 10, 9, 8, 9, 8, 7, - 5, 6, 7, 8, 7, 8, 9, 10, 0, 10, 9, 8, 7, 8, 7, 6 -}; - -static const uint16_t SpectrumB43Codes[256] = -{ - 0x001, 0x01E, 0x022, 0x018, 0x064, 0x0EC, 0x008, 0x100, 0x000, 0x101, 0x009, 0x0ED, - 0x065, 0x019, 0x023, 0x01F, 0x01A, 0x030, 0x056, 0x09A, 0x00A, 0x090, 0x12C, 0x0A6, - 0x000, 0x0A9, 0x12F, 0x093, 0x00F, 0x09F, 0x059, 0x039, 0x00E, 0x054, 0x0BC, 0x19E, - 0x082, 0x176, 0x0AC, 0x088, 0x000, 0x08B, 0x0AF, 0x19D, 0x095, 0x1D1, 0x0BF, 0x051, - 0x002, 0x098, 0x1D4, 0x0B8, 0x170, 0x046, 0x090, 0x060, 0x000, 0x067, 0x095, 0x0BD, - 0x173, 0x0B5, 0x1D3, 0x09D, 0x052, 0x0EE, 0x034, 0x174, 0x0BA, 0x09C, 0x080, 0x044, - 0x000, 0x047, 0x06D, 0x099, 0x0BF, 0x16F, 0x085, 0x001, 0x0CC, 0x036, 0x16C, 0x0B0, - 0x09A, 0x084, 0x04E, 0x03E, 0x000, 0x037, 0x04B, 0x06B, 0x0A1, 0x0B3, 0x16B, 0x087, - 0x1D6, 0x102, 0x0A4, 0x092, 0x068, 0x04C, 0x034, 0x030, 0x000, 0x02D, 0x03D, 0x049, - 0x083, 0x097, 0x0AB, 0x169, 0x0B6, 0x09E, 0x06E, 0x064, 0x040, 0x038, 0x02E, 0x02A, - 0x000, 0x029, 0x033, 0x03B, 0x043, 0x063, 0x087, 0x0A3, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x0B7, 0x0A2, 0x086, 0x062, 0x042, 0x03A, 0x032, 0x028, 0x000, 0x02B, 0x02F, 0x039, - 0x041, 0x065, 0x06F, 0x09F, 0x1D7, 0x168, 0x0AA, 0x096, 0x082, 0x048, 0x03C, 0x02C, - 0x000, 0x031, 0x035, 0x04D, 0x069, 0x093, 0x0A5, 0x103, 0x0CD, 0x086, 0x16A, 0x0B2, - 0x0A0, 0x06A, 0x04A, 0x036, 0x000, 0x03F, 0x04F, 0x085, 0x09B, 0x0B1, 0x16D, 0x037, - 0x053, 0x000, 0x084, 0x16E, 0x0BE, 0x098, 0x06C, 0x046, 0x000, 0x045, 0x081, 0x09D, - 0x0BB, 0x175, 0x035, 0x0EF, 0x003, 0x09C, 0x1D2, 0x0B4, 0x172, 0x0BC, 0x094, 0x066, - 0x000, 0x061, 0x091, 0x047, 0x171, 0x0B9, 0x1D5, 0x099, 0x00F, 0x050, 0x0BE, 0x1D0, - 0x094, 0x19C, 0x0AE, 0x08A, 0x000, 0x089, 0x0AD, 0x177, 0x083, 0x19F, 0x0BD, 0x055, - 0x01B, 0x038, 0x058, 0x09E, 0x00E, 0x092, 0x12E, 0x0A8, 0x000, 0x0A7, 0x12D, 0x091, - 0x00B, 0x09B, 0x057, 0x031 -}; - -static const uint8_t SpectrumB44Bits[256] = -{ - 2, 4, 6, 7, 7, 8, 10, 10, 0, 10, 10, 8, 7, 7, 6, 4, - 5, 5, 7, 8, 8, 10, 10, 10, 0, 10, 10, 10, 8, 8, 7, 5, - 6, 7, 8, 9, 9, 10, 10, 10, 0, 10, 10, 10, 10, 9, 8, 7, - 8, 8, 9, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 8, - 8, 8, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 8, - 9, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 9, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 8, - 8, 8, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 9, 8, - 6, 7, 8, 9, 10, 10, 10, 10, 0, 10, 10, 10, 9, 9, 8, 7, - 5, 5, 7, 8, 8, 10, 10, 10, 0, 10, 10, 10, 8, 8, 7, 5 -}; - -static const uint16_t SpectrumB44Codes[256] = -{ - 0x002, 0x002, 0x030, 0x000, 0x002, 0x00C, 0x1D2, 0x1AE, 0x000, 0x1AF, 0x1D3, 0x00D, - 0x003, 0x001, 0x031, 0x003, 0x01E, 0x002, 0x070, 0x0C8, 0x07E, 0x1E8, 0x1C0, 0x176, - 0x000, 0x17F, 0x1C3, 0x1EB, 0x0CF, 0x0D3, 0x073, 0x009, 0x018, 0x06A, 0x0EC, 0x1DE, - 0x1A2, 0x1CA, 0x1AA, 0x164, 0x000, 0x16D, 0x1AD, 0x1D1, 0x1EF, 0x1DD, 0x0EB, 0x06D, - 0x0E8, 0x0CA, 0x1BE, 0x1CE, 0x1DA, 0x1B6, 0x170, 0x154, 0x000, 0x153, 0x173, 0x1B1, - 0x1D7, 0x1D5, 0x343, 0x0CD, 0x0DC, 0x078, 0x340, 0x1CC, 0x1BA, 0x1A8, 0x156, 0x148, - 0x000, 0x145, 0x15F, 0x1A1, 0x1BD, 0x1D9, 0x1ED, 0x07D, 0x1BC, 0x1DC, 0x1C4, 0x1B2, - 0x17C, 0x15A, 0x14A, 0x03A, 0x000, 0x039, 0x147, 0x16B, 0x17B, 0x1B5, 0x1C9, 0x1DF, - 0x1C6, 0x1B8, 0x1A2, 0x168, 0x160, 0x14C, 0x02E, 0x024, 0x000, 0x027, 0x03D, 0x151, - 0x15D, 0x16F, 0x1A7, 0x1BF, 0x1A4, 0x174, 0x162, 0x14E, 0x140, 0x02C, 0x02A, 0x022, - 0x000, 0x021, 0x029, 0x03F, 0x143, 0x159, 0x167, 0x179, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x1A5, 0x178, 0x166, 0x158, 0x142, 0x03E, 0x028, 0x020, 0x000, 0x023, 0x02B, 0x02D, - 0x141, 0x14F, 0x163, 0x175, 0x1C7, 0x1BE, 0x1A6, 0x16E, 0x15C, 0x150, 0x03C, 0x026, - 0x000, 0x025, 0x02F, 0x14D, 0x161, 0x169, 0x1A3, 0x1B9, 0x1BD, 0x1DE, 0x1C8, 0x1B4, - 0x17A, 0x16A, 0x146, 0x038, 0x000, 0x03B, 0x14B, 0x15B, 0x17D, 0x1B3, 0x1C5, 0x1DD, - 0x0DD, 0x07C, 0x1EC, 0x1D8, 0x1BC, 0x1A0, 0x15E, 0x144, 0x000, 0x149, 0x157, 0x1A9, - 0x1BB, 0x1CD, 0x341, 0x079, 0x0E9, 0x0CC, 0x342, 0x1D4, 0x1D6, 0x1B0, 0x172, 0x152, - 0x000, 0x155, 0x171, 0x1B7, 0x1DB, 0x1CF, 0x1BF, 0x0CB, 0x019, 0x06C, 0x0EA, 0x1DC, - 0x1EE, 0x1D0, 0x1AC, 0x16C, 0x000, 0x165, 0x1AB, 0x1CB, 0x1A3, 0x1DF, 0x0ED, 0x06B, - 0x01F, 0x008, 0x072, 0x0D2, 0x0CE, 0x1EA, 0x1C2, 0x17E, 0x000, 0x177, 0x1C1, 0x1E9, - 0x07F, 0x0C9, 0x071, 0x003 -}; - -static const uint8_t SpectrumB52Bits[32] = -{ - 3, 4, 4, 4, 5, 5, 6, 6, 5, 5, 5, 6, 6, 6, 7, 7, - 0, 7, 7, 6, 6, 6, 5, 5, 5, 6, 6, 5, 5, 4, 4, 4 -}; - -static const uint16_t SpectrumB52Codes[32] = -{ - 0x06, 0x0E, 0x06, 0x00, 0x0A, 0x04, 0x2C, 0x12, 0x14, 0x10, 0x06, 0x2E, 0x24, 0x10, 0x4E, 0x4C, - 0x00, 0x4D, 0x4F, 0x11, 0x25, 0x2F, 0x07, 0x11, 0x15, 0x13, 0x2D, 0x05, 0x0B, 0x01, 0x07, 0x0F -}; - -static const uint8_t SpectrumB53Bits[32] = -{ - 2, 3, 4, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 8, 8, - 0, 8, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 4, 3 -}; - -static const uint16_t SpectrumB53Codes[32] = -{ - 0x02, 0x00, 0x06, 0x1C, 0x18, 0x3E, 0x16, 0x10, 0x3C, 0x36, 0x14, 0x6A, 0x26, 0x24, 0xD2, 0xD0, - 0x00, 0xD1, 0xD3, 0x25, 0x27, 0x6B, 0x15, 0x37, 0x3D, 0x11, 0x17, 0x3F, 0x19, 0x1D, 0x07, 0x01 -}; - -static const uint8_t SpectrumB54Bits[32] = -{ - 2, 3, 4, 4, 5, 6, 6, 7, 6, 6, 7, 8, 8, 8, 9, 9, - 0, 9, 9, 8, 8, 8, 7, 6, 6, 7, 6, 6, 5, 4, 4, 3 -}; - -static const uint16_t SpectrumB54Codes[32] = -{ - 0x003, 0x002, 0x008, 0x000, 0x014, 0x02E, 0x00E, 0x05A, 0x00A, 0x008, 0x01A, 0x0B2, - 0x032, 0x030, 0x162, 0x160, 0x000, 0x161, 0x163, 0x031, 0x033, 0x0B3, 0x01B, 0x009, - 0x00B, 0x05B, 0x00F, 0x02F, 0x015, 0x001, 0x009, 0x003 -}; - -static const uint8_t SpectrumB62Bits[64] = -{ - 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, - 0, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, - 6, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4 -}; - -static const uint16_t SpectrumB62Codes[64] = -{ - 0x0D, 0x06, 0x1C, 0x14, 0x0A, 0x04, 0x3E, 0x2E, 0x22, 0x0E, 0x06, 0x00, 0x5A, 0x4E, 0x40, 0x20, - 0x30, 0x32, 0x24, 0x12, 0x0C, 0x02, 0x78, 0x58, 0x42, 0x22, 0x0A, 0x08, 0xF6, 0xF4, 0x9A, 0x98, - 0x00, 0x99, 0x9B, 0xF5, 0xF7, 0x09, 0x0B, 0x23, 0x43, 0x59, 0x79, 0x03, 0x0D, 0x13, 0x25, 0x33, - 0x31, 0x21, 0x41, 0x4F, 0x5B, 0x01, 0x07, 0x0F, 0x23, 0x2F, 0x3F, 0x05, 0x0B, 0x15, 0x1D, 0x07 -}; - -static const uint8_t SpectrumB63Bits[64] = -{ - 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, - 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, - 6, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4 -}; - -static const uint16_t SpectrumB63Codes[64] = -{ - 0x006, 0x00E, 0x004, 0x014, 0x010, 0x006, 0x000, 0x026, 0x01C, 0x018, 0x004, 0x05C, - 0x04A, 0x03C, 0x016, 0x0BC, 0x006, 0x008, 0x058, 0x03E, 0x036, 0x014, 0x0B6, 0x0B4, - 0x090, 0x068, 0x17E, 0x17C, 0x126, 0x124, 0x0D6, 0x0D4, 0x000, 0x0D5, 0x0D7, 0x125, - 0x127, 0x17D, 0x17F, 0x069, 0x091, 0x0B5, 0x0B7, 0x015, 0x037, 0x03F, 0x059, 0x009, - 0x007, 0x0BD, 0x017, 0x03D, 0x04B, 0x05D, 0x005, 0x019, 0x01D, 0x027, 0x001, 0x007, - 0x011, 0x015, 0x005, 0x00F -}; - -static const uint8_t SpectrumB64Bits[64] = -{ - 3, 3, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, - 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, - 0, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, 8, 7, 7, - 7, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 3 -}; - -static const uint16_t SpectrumB64Codes[64] = -{ - 0x007, 0x000, 0x008, 0x01A, 0x014, 0x00C, 0x032, 0x02E, 0x01E, 0x014, 0x062, 0x05A, - 0x03A, 0x026, 0x020, 0x0B2, 0x038, 0x02C, 0x022, 0x0C0, 0x05E, 0x04A, 0x186, 0x184, - 0x160, 0x0BA, 0x092, 0x090, 0x2C6, 0x2C4, 0x172, 0x170, 0x000, 0x171, 0x173, 0x2C5, - 0x2C7, 0x091, 0x093, 0x0BB, 0x161, 0x185, 0x187, 0x04B, 0x05F, 0x0C1, 0x023, 0x02D, - 0x039, 0x0B3, 0x021, 0x027, 0x03B, 0x05B, 0x063, 0x015, 0x01F, 0x02F, 0x033, 0x00D, - 0x015, 0x01B, 0x009, 0x001 -}; - -static const uint8_t SpectrumB72Bits[128] = -{ - 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5 -}; - -static const uint16_t SpectrumB72Codes[128] = -{ - 0x01E, 0x016, 0x00C, 0x000, 0x038, 0x032, 0x028, 0x022, 0x01C, 0x012, 0x00E, 0x006, - 0x076, 0x06C, 0x060, 0x04E, 0x03E, 0x02A, 0x022, 0x01A, 0x012, 0x00A, 0x0FC, 0x0DC, - 0x0C6, 0x0A8, 0x094, 0x086, 0x058, 0x042, 0x040, 0x02A, 0x068, 0x07C, 0x06A, 0x056, - 0x048, 0x040, 0x02E, 0x028, 0x016, 0x010, 0x008, 0x0EA, 0x0DE, 0x0AA, 0x09A, 0x096, - 0x07A, 0x078, 0x05A, 0x032, 0x030, 0x028, 0x1FE, 0x1FC, 0x1D2, 0x1D0, 0x18A, 0x188, - 0x132, 0x130, 0x10A, 0x108, 0x000, 0x109, 0x10B, 0x131, 0x133, 0x189, 0x18B, 0x1D1, - 0x1D3, 0x1FD, 0x1FF, 0x029, 0x031, 0x033, 0x05B, 0x079, 0x07B, 0x097, 0x09B, 0x0AB, - 0x0DF, 0x0EB, 0x009, 0x011, 0x017, 0x029, 0x02F, 0x041, 0x049, 0x057, 0x06B, 0x07D, - 0x069, 0x02B, 0x041, 0x043, 0x059, 0x087, 0x095, 0x0A9, 0x0C7, 0x0DD, 0x0FD, 0x00B, - 0x013, 0x01B, 0x023, 0x02B, 0x03F, 0x04F, 0x061, 0x06D, 0x077, 0x007, 0x00F, 0x013, - 0x01D, 0x023, 0x029, 0x033, 0x039, 0x001, 0x00D, 0x017 -}; - -static const uint8_t SpectrumB73Bits[128] = -{ - 3, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, - 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 7, - 8, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 4 -}; - -static const uint16_t SpectrumB73Codes[128] = -{ - 0x000, 0x006, 0x018, 0x010, 0x004, 0x03A, 0x034, 0x02A, 0x026, 0x014, 0x010, 0x07E, - 0x072, 0x06E, 0x05C, 0x052, 0x04A, 0x02C, 0x024, 0x018, 0x0F4, 0x0E0, 0x0DA, 0x0B6, - 0x0B2, 0x0A0, 0x05E, 0x04E, 0x038, 0x034, 0x1E6, 0x1B2, 0x0FA, 0x01E, 0x0F8, 0x0F0, - 0x0BE, 0x0B4, 0x0A2, 0x090, 0x04C, 0x03A, 0x1EE, 0x1E4, 0x1C6, 0x1B0, 0x178, 0x162, - 0x126, 0x124, 0x0B8, 0x06C, 0x3DA, 0x3D8, 0x38A, 0x388, 0x2F6, 0x2F4, 0x2C2, 0x2C0, - 0x176, 0x174, 0x0DC, 0x0DE, 0x000, 0x0DF, 0x0DD, 0x175, 0x177, 0x2C1, 0x2C3, 0x2F5, - 0x2F7, 0x389, 0x38B, 0x3D9, 0x3DB, 0x06D, 0x0B9, 0x125, 0x127, 0x163, 0x179, 0x1B1, - 0x1C7, 0x1E5, 0x1EF, 0x03B, 0x04D, 0x091, 0x0A3, 0x0B5, 0x0BF, 0x0F1, 0x0F9, 0x01F, - 0x0FB, 0x1B3, 0x1E7, 0x035, 0x039, 0x04F, 0x05F, 0x0A1, 0x0B3, 0x0B7, 0x0DB, 0x0E1, - 0x0F5, 0x019, 0x025, 0x02D, 0x04B, 0x053, 0x05D, 0x06F, 0x073, 0x07F, 0x011, 0x015, - 0x027, 0x02B, 0x035, 0x03B, 0x005, 0x011, 0x019, 0x007 -}; - -static const uint8_t SpectrumB74Bits[128] = -{ - 3, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, - 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, - 8, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4 -}; - -static const uint16_t SpectrumB74Codes[128] = -{ - 0x001, 0x008, 0x01E, 0x018, 0x00C, 0x002, 0x03A, 0x034, 0x02C, 0x01E, 0x016, 0x012, - 0x072, 0x06E, 0x05E, 0x056, 0x050, 0x038, 0x022, 0x004, 0x0E2, 0x0DA, 0x0BA, 0x0A8, - 0x076, 0x054, 0x050, 0x002, 0x000, 0x1C0, 0x1B0, 0x156, 0x0A4, 0x0A6, 0x074, 0x052, - 0x004, 0x1C2, 0x1B2, 0x170, 0x154, 0x0AE, 0x0AC, 0x086, 0x2E6, 0x2E4, 0x10A, 0x108, - 0x106, 0x104, 0x102, 0x100, 0x03E, 0x03A, 0x03C, 0x038, 0x036, 0x034, 0x032, 0x030, - 0x01E, 0x01A, 0x01C, 0x018, 0x000, 0x019, 0x01D, 0x01B, 0x01F, 0x031, 0x033, 0x035, - 0x037, 0x039, 0x03D, 0x03B, 0x03F, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x2E5, - 0x2E7, 0x087, 0x0AD, 0x0AF, 0x155, 0x171, 0x1B3, 0x1C3, 0x005, 0x053, 0x075, 0x0A7, - 0x0A5, 0x157, 0x1B1, 0x1C1, 0x001, 0x003, 0x051, 0x055, 0x077, 0x0A9, 0x0BB, 0x0DB, - 0x0E3, 0x005, 0x023, 0x039, 0x051, 0x057, 0x05F, 0x06F, 0x073, 0x013, 0x017, 0x01F, - 0x02D, 0x035, 0x03B, 0x003, 0x00D, 0x019, 0x01F, 0x009 -}; - -static uint8_t ScaleFactorsA1Lookup[2]; -static uint8_t ScaleFactorsA2Lookup[8]; -static uint8_t ScaleFactorsA3Lookup[64]; -static uint8_t ScaleFactorsA4Lookup[256]; -static uint8_t ScaleFactorsA5Lookup[256]; -static uint8_t ScaleFactorsA6Lookup[256]; -static uint8_t ScaleFactorsB2Lookup[4]; -static uint8_t ScaleFactorsB3Lookup[64]; -static uint8_t ScaleFactorsB4Lookup[256]; -static uint8_t ScaleFactorsB5Lookup[256]; -static uint8_t SpectrumA21Lookup[8]; -static uint8_t SpectrumA22Lookup[256]; -static uint8_t SpectrumA23Lookup[512]; -static uint8_t SpectrumA24Lookup[1024]; -static uint8_t SpectrumA31Lookup[128]; -static uint8_t SpectrumA32Lookup[128]; -static uint8_t SpectrumA33Lookup[256]; -static uint8_t SpectrumA34Lookup[1024]; -static uint8_t SpectrumA41Lookup[512]; -static uint8_t SpectrumA42Lookup[1024]; -static uint8_t SpectrumA43Lookup[1024]; -static uint8_t SpectrumA44Lookup[1024]; -static uint8_t SpectrumA51Lookup[64]; -static uint8_t SpectrumA52Lookup[64]; -static uint8_t SpectrumA53Lookup[128]; -static uint8_t SpectrumA54Lookup[256]; -static uint8_t SpectrumA61Lookup[128]; -static uint8_t SpectrumA62Lookup[128]; -static uint8_t SpectrumA63Lookup[256]; -static uint8_t SpectrumA64Lookup[512]; -static uint8_t SpectrumA71Lookup[256]; -static uint8_t SpectrumA72Lookup[256]; -static uint8_t SpectrumA73Lookup[512]; -static uint8_t SpectrumA74Lookup[1024]; -static uint8_t SpectrumB22Lookup[1024]; -static uint8_t SpectrumB23Lookup[1024]; -static uint8_t SpectrumB24Lookup[1024]; -static uint8_t SpectrumB32Lookup[512]; -static uint8_t SpectrumB33Lookup[1024]; -static uint8_t SpectrumB34Lookup[1024]; -static uint8_t SpectrumB42Lookup[1024]; -static uint8_t SpectrumB43Lookup[1024]; -static uint8_t SpectrumB44Lookup[1024]; -static uint8_t SpectrumB52Lookup[128]; -static uint8_t SpectrumB53Lookup[256]; -static uint8_t SpectrumB54Lookup[512]; -static uint8_t SpectrumB62Lookup[256]; -static uint8_t SpectrumB63Lookup[512]; -static uint8_t SpectrumB64Lookup[1024]; -static uint8_t SpectrumB72Lookup[512]; -static uint8_t SpectrumB73Lookup[1024]; -static uint8_t SpectrumB74Lookup[1024]; diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/imdct.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/imdct.c deleted file mode 100644 index 29bf3dfd7..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/imdct.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "imdct.h" -#include "tables.h" - -void RunImdct(mdct* mdct, double* input, double* output) -{ - const int size = 1 << mdct->bits; - const int half = size / 2; - double dctOut[MAX_FRAME_SAMPLES]; - const double* window = ImdctWindow[mdct->bits - 6]; - double* previous = mdct->_imdctPrevious; - - Dct4(mdct, input, dctOut); - - for (int i = 0; i < half; i++) - { - output[i] = window[i] * dctOut[i + half] + previous[i]; - output[i + half] = window[i + half] * -dctOut[size - 1 - i] - previous[i + half]; - previous[i] = window[size - 1 - i] * -dctOut[half - i - 1]; - previous[i + half] = window[half - i - 1] * dctOut[i]; - } -} - -void Dct4(mdct* mdct, double* input, double* output) -{ - int MdctBits = mdct->bits; - int MdctSize = 1 << MdctBits; - const int* shuffleTable = ShuffleTables[MdctBits]; - const double* sinTable = SinTables[MdctBits]; - const double* cosTable = CosTables[MdctBits]; - double dctTemp[MAX_FRAME_SAMPLES]; - - int size = MdctSize; - int lastIndex = size - 1; - int halfSize = size / 2; - - for (int i = 0; i < halfSize; i++) - { - int i2 = i * 2; - double a = input[i2]; - double b = input[lastIndex - i2]; - double sin = sinTable[i]; - double cos = cosTable[i]; - dctTemp[i2] = a * cos + b * sin; - dctTemp[i2 + 1] = a * sin - b * cos; - } - int stageCount = MdctBits - 1; - - for (int stage = 0; stage < stageCount; stage++) - { - int blockCount = 1 << stage; - int blockSizeBits = stageCount - stage; - int blockHalfSizeBits = blockSizeBits - 1; - int blockSize = 1 << blockSizeBits; - int blockHalfSize = 1 << blockHalfSizeBits; - sinTable = SinTables[blockHalfSizeBits]; - cosTable = CosTables[blockHalfSizeBits]; - - for (int block = 0; block < blockCount; block++) - { - for (int i = 0; i < blockHalfSize; i++) - { - int frontPos = (block * blockSize + i) * 2; - int backPos = frontPos + blockSize; - double a = dctTemp[frontPos] - dctTemp[backPos]; - double b = dctTemp[frontPos + 1] - dctTemp[backPos + 1]; - double sin = sinTable[i]; - double cos = cosTable[i]; - dctTemp[frontPos] += dctTemp[backPos]; - dctTemp[frontPos + 1] += dctTemp[backPos + 1]; - dctTemp[backPos] = a * cos + b * sin; - dctTemp[backPos + 1] = a * sin - b * cos; - } - } - } - - for (int i = 0; i < MdctSize; i++) - { - output[i] = dctTemp[shuffleTable[i]]; - } -} \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/imdct.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/imdct.h deleted file mode 100644 index e8c3bf3c6..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/imdct.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "structures.h" - -void RunImdct(mdct* mdct, double* input, double* output); -void Dct4(mdct* mdct, double* input, double* output); \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.c deleted file mode 100644 index 2dbe1cd7e..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "libatrac9.h" -#include "structures.h" -#include -#include -#include "decinit.h" -#include "decoder.h" - -void* Atrac9GetHandle() -{ - struct atrac9_handle* handle = malloc(sizeof(atrac9_handle)); - memset(handle, 0, sizeof(atrac9_handle)); - return handle; -} - -void Atrac9ReleaseHandle(void* handle) -{ - free(handle); -} - -int Atrac9InitDecoder(void* handle, unsigned char * pConfigData) -{ - return init_decoder(handle, pConfigData, 16); -} - -int Atrac9Decode(void* handle, const unsigned char *pAtrac9Buffer, short *pPcmBuffer, int *pNBytesUsed) -{ - return Decode(handle, pAtrac9Buffer, (unsigned char*)pPcmBuffer, pNBytesUsed); -} - -int Atrac9GetCodecInfo(void* handle, Atrac9CodecInfo * pCodecInfo) -{ - return GetCodecInfo(handle, (CodecInfo*)pCodecInfo); -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.h deleted file mode 100644 index 977f80444..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif - -#define ATRAC9_CONFIG_DATA_SIZE 4 - -typedef struct { - int channels; - int channelConfigIndex; - int samplingRate; - int superframeSize; - int framesInSuperframe; - int frameSamples; - int wlength; - unsigned char configData[ATRAC9_CONFIG_DATA_SIZE]; - - double MdctWindow[3][256]; - double ImdctWindow[3][256]; -} Atrac9CodecInfo; - -void* Atrac9GetHandle(void); -void Atrac9ReleaseHandle(void* handle); - -int Atrac9InitDecoder(void* handle, unsigned char *pConfigData); -int Atrac9Decode(void* handle, const unsigned char *pAtrac9Buffer, short *pPcmBuffer, int *pNBytesUsed); - -int Atrac9GetCodecInfo(void* handle, Atrac9CodecInfo *pCodecInfo); - -#ifdef __cplusplus -} -#endif diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.sln b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.sln deleted file mode 100644 index 8c7c6bfdf..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2010 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libatrac9", "libatrac9.vcxproj", "{2425F2CC-BB1B-4069-BC10-1C7F535EF8E8}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2425F2CC-BB1B-4069-BC10-1C7F535EF8E8}.Debug|x64.ActiveCfg = Debug|x64 - {2425F2CC-BB1B-4069-BC10-1C7F535EF8E8}.Debug|x64.Build.0 = Debug|x64 - {2425F2CC-BB1B-4069-BC10-1C7F535EF8E8}.Debug|x86.ActiveCfg = Debug|Win32 - {2425F2CC-BB1B-4069-BC10-1C7F535EF8E8}.Debug|x86.Build.0 = Debug|Win32 - {2425F2CC-BB1B-4069-BC10-1C7F535EF8E8}.Release|x64.ActiveCfg = Release|x64 - {2425F2CC-BB1B-4069-BC10-1C7F535EF8E8}.Release|x64.Build.0 = Release|x64 - {2425F2CC-BB1B-4069-BC10-1C7F535EF8E8}.Release|x86.ActiveCfg = Release|Win32 - {2425F2CC-BB1B-4069-BC10-1C7F535EF8E8}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {BB003D83-77D8-4E7B-896D-7C9ADA458F73} - EndGlobalSection -EndGlobal diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.vcxproj b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.vcxproj deleted file mode 100644 index 8830bda95..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {2425F2CC-BB1B-4069-BC10-1C7F535EF8E8} - libatrac9 - 10.0.16299.0 - libatrac9 - - - - DynamicLibrary - true - v141 - MultiByte - - - DynamicLibrary - false - v141 - true - MultiByte - - - DynamicLibrary - true - v141 - MultiByte - - - DynamicLibrary - false - v141 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - true - true - _WINDLL;COMPILING_DLL;%(PreprocessorDefinitions) - CompileAsC - - - - - Level3 - Disabled - true - true - CompileAsC - _WINDLL;COMPILING_DLL;%(PreprocessorDefinitions) - - - - - Level3 - MaxSpeed - true - true - true - true - CompileAsC - _WINDLL;COMPILING_DLL;%(PreprocessorDefinitions) - Sync - - - true - true - - - - - Level3 - MaxSpeed - true - true - true - true - CompileAsC - _WINDLL;COMPILING_DLL;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.vcxproj.filters b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.vcxproj.filters deleted file mode 100644 index 24c4233a8..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/libatrac9.vcxproj.filters +++ /dev/null @@ -1,105 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/quantization.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/quantization.c deleted file mode 100644 index 6d95e62ab..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/quantization.c +++ /dev/null @@ -1,54 +0,0 @@ -#include "quantization.h" -#include -#include "tables.h" - -void DequantizeSpectra(block* block) -{ - for (int i = 0; i < block->ChannelCount; i++) - { - channel* channel = &block->Channels[i]; - memset(channel->Spectra, 0, sizeof(channel->Spectra)); - - for (int j = 0; j < channel->CodedQuantUnits; j++) - { - DequantizeQuantUnit(channel, j); - } - } -} - - void DequantizeQuantUnit(channel* channel, int band) -{ - const int subBandIndex = QuantUnitToCoeffIndex[band]; - const int subBandCount = QuantUnitToCoeffCount[band]; - const double stepSize = QuantizerStepSize[channel->Precisions[band]]; - const double stepSizeFine = QuantizerFineStepSize[channel->PrecisionsFine[band]]; - - for (int sb = 0; sb < subBandCount; sb++) - { - const double coarse = channel->QuantizedSpectra[subBandIndex + sb] * stepSize; - const double fine = channel->QuantizedSpectraFine[subBandIndex + sb] * stepSizeFine; - channel->Spectra[subBandIndex + sb] = coarse + fine; - } -} - -void ScaleSpectrumBlock(block* block) - { - for (int i = 0; i < block->ChannelCount; i++) - { - ScaleSpectrumChannel(&block->Channels[i]); - } - } - -void ScaleSpectrumChannel(channel* channel) -{ - const int quantUnitCount = channel->Block->QuantizationUnitCount; - double* spectra = channel->Spectra; - - for (int i = 0; i < quantUnitCount; i++) - { - for (int sb = QuantUnitToCoeffIndex[i]; sb < QuantUnitToCoeffIndex[i + 1]; sb++) - { - spectra[sb] *= SpectrumScale[channel->ScaleFactors[i]]; - } - } - } \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/quantization.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/quantization.h deleted file mode 100644 index d9de74a3e..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/quantization.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "structures.h" - -void DequantizeSpectra(block* block); -void DequantizeQuantUnit(channel* channel, int band); -void ScaleSpectrumBlock(block* block); -void ScaleSpectrumChannel(channel* channel); \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/scale_factors.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/scale_factors.c deleted file mode 100644 index ee812414a..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/scale_factors.c +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include "huffCodes.h" -#include "scale_factors.h" -#include "tables.h" -#include "utility.h" - -at9_status read_scale_factors(channel * channel, bit_reader_cxt * br) -{ - memset(channel->ScaleFactors, 0, sizeof(channel->ScaleFactors)); - - channel->ScaleFactorCodingMode = read_int(br, 2); - if (channel->ChannelIndex == 0) - { - switch (channel->ScaleFactorCodingMode) - { - case 0: - ReadVlcDeltaOffset(channel, br); - break; - case 1: - ReadClcOffset(channel, br); - break; - case 2: - if (channel->Block->FirstInSuperframe) return ERR_UNPACK_SCALE_FACTOR_MODE_INVALID; - ReadVlcDistanceToBaseline(channel, br, channel->ScaleFactorsPrev, channel->Block->QuantizationUnitsPrev); - break; - case 3: - if (channel->Block->FirstInSuperframe) return ERR_UNPACK_SCALE_FACTOR_MODE_INVALID; - ReadVlcDeltaOffsetWithBaseline(channel, br, channel->ScaleFactorsPrev, channel->Block->QuantizationUnitsPrev); - break; - } - } - else - { - switch (channel->ScaleFactorCodingMode) - { - case 0: - ReadVlcDeltaOffset(channel, br); - break; - case 1: - ReadVlcDistanceToBaseline(channel, br, channel->Block->Channels[0].ScaleFactors, channel->Block->ExtensionUnit); - break; - case 2: - ReadVlcDeltaOffsetWithBaseline(channel, br, channel->Block->Channels[0].ScaleFactors, channel->Block->ExtensionUnit); - break; - case 3: - if (channel->Block->FirstInSuperframe) return ERR_UNPACK_SCALE_FACTOR_MODE_INVALID; - ReadVlcDistanceToBaseline(channel, br, channel->ScaleFactorsPrev, channel->Block->QuantizationUnitsPrev); - break; - } - } - - for (int i = 0; i < channel->Block->ExtensionUnit; i++) - { - if (channel->ScaleFactors[i] < 0 || channel->ScaleFactors[i] > 31) - { - return ERR_UNPACK_SCALE_FACTOR_OOB; - } - } - - memcpy(channel->ScaleFactorsPrev, channel->ScaleFactors, sizeof(channel->ScaleFactors)); - - return ERR_SUCCESS; -} - -void ReadClcOffset(channel* channel, bit_reader_cxt* br) -{ - const int maxBits = 5; - int* sf = channel->ScaleFactors; - const int bitLength = read_int(br, 2) + 2; - const int baseValue = bitLength < maxBits ? read_int(br, maxBits) : 0; - - for (int i = 0; i < channel->Block->ExtensionUnit; i++) - { - sf[i] = read_int(br, bitLength) + baseValue; - } -} - -void ReadVlcDeltaOffset(channel* channel, bit_reader_cxt* br) -{ - const int weightIndex = read_int(br, 3); - const unsigned char* weights = ScaleFactorWeights[weightIndex]; - - int* sf = channel->ScaleFactors; - const int baseValue = read_int(br, 5); - const int bitLength = read_int(br, 2) + 3; - const HuffmanCodebook* codebook = &HuffmanScaleFactorsUnsigned[bitLength]; - - sf[0] = read_int(br, bitLength); - - for (int i = 1; i < channel->Block->ExtensionUnit; i++) - { - const int delta = ReadHuffmanValue(codebook, br, 0); - sf[i] = (sf[i - 1] + delta) & (codebook->ValueMax - 1); - } - - for (int i = 0; i < channel->Block->ExtensionUnit; i++) - { - sf[i] += baseValue - weights[i]; - } -} - -void ReadVlcDistanceToBaseline(channel* channel, bit_reader_cxt* br, int* baseline, int baselineLength) -{ - int* sf = channel->ScaleFactors; - const int bit_length = read_int(br, 2) + 2; - const HuffmanCodebook* codebook = &HuffmanScaleFactorsSigned[bit_length]; - const int unitCount = min(channel->Block->ExtensionUnit, baselineLength); - - for (int i = 0; i < unitCount; i++) - { - const int distance = ReadHuffmanValue(codebook, br, TRUE); - sf[i] = (baseline[i] + distance) & 31; - } - - for (int i = unitCount; i < channel->Block->ExtensionUnit; i++) - { - sf[i] = read_int(br, 5); - } -} - -void ReadVlcDeltaOffsetWithBaseline(channel* channel, bit_reader_cxt* br, int* baseline, int baselineLength) -{ - int* sf = channel->ScaleFactors; - const int baseValue = read_offset_binary(br, 5); - const int bitLength = read_int(br, 2) + 1; - const HuffmanCodebook* codebook = &HuffmanScaleFactorsUnsigned[bitLength]; - const int unitCount = min(channel->Block->ExtensionUnit, baselineLength); - - sf[0] = read_int(br, bitLength); - - for (int i = 1; i < unitCount; i++) - { - const int delta = ReadHuffmanValue(codebook, br, FALSE); - sf[i] = (sf[i - 1] + delta) & (codebook->ValueMax - 1); - } - - for (int i = 0; i < unitCount; i++) - { - sf[i] += baseValue + baseline[i]; - } - - for (int i = unitCount; i < channel->Block->ExtensionUnit; i++) - { - sf[i] = read_int(br, 5); - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/scale_factors.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/scale_factors.h deleted file mode 100644 index 557c83436..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/scale_factors.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "bit_allocation.h" - -at9_status read_scale_factors(channel* channel, bit_reader_cxt* br); -void ReadClcOffset(channel* channel, bit_reader_cxt* br); -void ReadVlcDeltaOffset(channel* channel, bit_reader_cxt* br); -void ReadVlcDistanceToBaseline(channel* channel, bit_reader_cxt* br, int* baseline, int baselineLength); -void ReadVlcDeltaOffsetWithBaseline(channel* channel, bit_reader_cxt* br, int* baseline, int baselineLength); diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/structures.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/structures.h deleted file mode 100644 index 05a9b3049..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/structures.h +++ /dev/null @@ -1,160 +0,0 @@ -#pragma once - -#define CONFIG_DATA_SIZE 4 -#define MAX_BLOCK_COUNT 5 -#define MAX_BLOCK_CHANNEL_COUNT 2 -#define MAX_FRAME_SAMPLES 256 -#define MAX_BEX_VALUES 4 - -#define MAX_QUANT_UNITS 30 - -typedef struct frame frame; -typedef struct block block; - -typedef enum BlockType { - Mono = 0, - Stereo = 1, - LFE = 2 -} BlockType; - -typedef struct { - int BlockCount; - int ChannelCount; - enum BlockType Types[MAX_BLOCK_COUNT]; -} ChannelConfig; - -typedef struct { - unsigned char ConfigData[CONFIG_DATA_SIZE]; - int SampleRateIndex; - int ChannelConfigIndex; - int FrameBytes; - int SuperframeIndex; - - ChannelConfig ChannelConfig; - int ChannelCount; - int SampleRate; - int HighSampleRate; - int FramesPerSuperframe; - int FrameSamplesPower; - int FrameSamples; - int SuperframeBytes; - int SuperframeSamples; -} ConfigData; - -typedef struct { - int initialized; - unsigned short stateA; - unsigned short stateB; - unsigned short stateC; - unsigned short stateD; -} rng_cxt; - -typedef struct { - int bits; - int size; - double scale; - double _imdctPrevious[MAX_FRAME_SAMPLES]; - double* window; - double* sinTable; - double* cosTable; -} mdct; - -typedef struct { - frame* Frame; - block* Block; - ConfigData* config; - int ChannelIndex; - - mdct mdct; - - double Pcm[MAX_FRAME_SAMPLES]; - double Spectra[MAX_FRAME_SAMPLES]; - - int CodedQuantUnits; - int ScaleFactorCodingMode; - - int ScaleFactors[31]; - int ScaleFactorsPrev[31]; - - int Precisions[MAX_QUANT_UNITS]; - int PrecisionsFine[MAX_QUANT_UNITS]; - int PrecisionMask[MAX_QUANT_UNITS]; - - int CodebookSet[MAX_QUANT_UNITS]; - - int QuantizedSpectra[MAX_FRAME_SAMPLES]; - int QuantizedSpectraFine[MAX_FRAME_SAMPLES]; - - int BexMode; - int BexValueCount; - int BexValues[MAX_BEX_VALUES]; - - rng_cxt rng; -} channel; - -struct block { - frame* Frame; - ConfigData* config; - enum BlockType BlockType; - int BlockIndex; - channel Channels[MAX_BLOCK_CHANNEL_COUNT]; - int ChannelCount; - int FirstInSuperframe; - int ReuseBandParams; - - int BandCount; - int StereoBand; - int ExtensionBand; - int QuantizationUnitCount; - int StereoQuantizationUnit; - int ExtensionUnit; - int QuantizationUnitsPrev; - - int Gradient[31]; - int GradientMode; - int GradientStartUnit; - int GradientStartValue; - int GradientEndUnit; - int GradientEndValue; - int GradientBoundary; - - int PrimaryChannelIndex; - int HasJointStereoSigns; - int JointStereoSigns[MAX_QUANT_UNITS]; - - int BandExtensionEnabled; - int HasExtensionData; - int BexDataLength; - int BexMode; -}; - -struct frame { - ConfigData* config; - int FrameIndex; - block Blocks[MAX_BLOCK_COUNT]; - int frameNum; -}; - -typedef struct { - int initialized; - int wlength; - ConfigData config; - frame frame; -} atrac9_handle; - -typedef struct { - int group_b_unit; - int group_c_unit; - int band_count; -} bex_group; - -typedef struct { - int channels; - int channelConfigIndex; - int samplingRate; - int superframeSize; - int framesInSuperframe; - int frameSamples; - int wlength; - unsigned char configData[CONFIG_DATA_SIZE]; -} CodecInfo; diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/tables.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/tables.c deleted file mode 100644 index 35d9ad6ee..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/tables.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "tables.h" - -double MdctWindow[3][256]; -double ImdctWindow[3][256]; -double SinTables[9][256]; -double CosTables[9][256]; -int ShuffleTables[9][256]; diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/tables.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/tables.h deleted file mode 100644 index 7be2ebf05..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/tables.h +++ /dev/null @@ -1,389 +0,0 @@ -#pragma once - -#include "structures.h" - -static const ChannelConfig ChannelConfigs[6] = -{ - {1, 1, Mono}, - {2, 2, Mono, Mono}, - {1, 2, Stereo}, - {4, 6, Stereo, Mono, LFE, Stereo}, - {5, 8, Stereo, Mono, LFE, Stereo, Stereo}, - {2, 4, Stereo, Stereo}, -}; - -static const int MaxHuffPrecision[2] = { 7, 1 }; -static const int MinBandCount[2] = { 3, 1 }; -static const int MaxExtensionBand[2] = { 18, 16 }; - -static const int SamplingRateIndexToFrameSamplesPower[16] = -{ 6, 6, 7, 7, 7, 8, 8, 8, 6, 6, 7, 7, 7, 8, 8, 8 }; - -static const int MaxBandCount[16] = -{ 8, 8, 12, 12, 12, 18, 18, 18, 8, 8, 12, 12, 12, 16, 16, 16 }; - -static const int BandToQuantUnitCount[19] = -{ 0, 4, 8, 10, 12, 13, 14, 15, 16, 18, 20, 21, 22, 23, 24, 25, 26, 28, 30 }; - -static const int QuantUnitToCoeffCount[30] = -{ - 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 8, 8, 8, - 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 -}; - -static const int QuantUnitToCoeffIndex[31] = -{ - 0, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, - 64, 72, 80, 88, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256 -}; - -static const int QuantUnitToCodebookIndex[30] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 -}; - -static const int SampleRates[16] = -{ - 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, - 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 -}; - -static const unsigned char GradientCurves[48][48] = { - { 1 }, - { 1, 16 }, - { 1, 7, 25 }, - { 1, 4, 16, 27 }, - { 1, 3, 10, 21, 28 }, - { 1, 3, 7, 16, 25, 29 }, - { 1, 2, 5, 11, 20, 26, 29 }, - { 1, 2, 4, 9, 16, 23, 27, 29 }, - { 1, 2, 3, 7, 12, 19, 25, 28, 29 }, - { 1, 2, 3, 5, 10, 16, 21, 26, 28, 29 }, - { 1, 2, 3, 5, 8, 12, 19, 23, 26, 28, 29 }, - { 1, 2, 3, 4, 7, 11, 16, 21, 25, 27, 29, 30 }, - { 1, 1, 2, 4, 5, 9, 13, 18, 22, 26, 27, 29, 30 }, - { 1, 1, 2, 3, 5, 8, 11, 16, 20, 23, 26, 28, 29, 30 }, - { 1, 1, 2, 3, 4, 7, 10, 13, 18, 21, 25, 27, 28, 29, 30 }, - { 1, 1, 2, 3, 4, 6, 9, 12, 16, 20, 23, 26, 27, 28, 29, 30 }, - { 1, 1, 2, 3, 4, 5, 7, 10, 13, 18, 21, 24, 26, 27, 28, 29, 30 }, - { 1, 1, 2, 3, 3, 5, 7, 9, 12, 16, 19, 22, 25, 26, 28, 29, 29, 30 }, - { 1, 1, 2, 2, 3, 4, 6, 8, 11, 13, 18, 20, 23, 25, 27, 28, 29, 29, 30 }, - { 1, 1, 2, 2, 3, 4, 5, 7, 10, 12, 16, 19, 21, 24, 26, 27, 28, 29, 29, 30 }, - { 1, 1, 2, 2, 3, 4, 5, 7, 9, 11, 13, 18, 20, 22, 25, 26, 27, 28, 29, 29, 30 }, - { 1, 1, 2, 2, 3, 3, 5, 6, 8, 10, 12, 16, 19, 21, 23, 25, 26, 28, 28, 29, 29, - 30 }, - { 1, 1, 2, 2, 3, 3, 4, 5, 7, 9, 11, 13, 18, 20, 22, 24, 26, 27, 28, 28, 29, - 29, 30 }, - { 1, 1, 2, 2, 3, 3, 4, 5, 7, 9, 11, 13, 16, 19, 21, 23, 25, 26, 27, 28, 29, - 29, 30, 30 }, - { 1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 15, 16, 19, 21, 23, 25, 26, 27, 28, - 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 26, 27, 27, - 28, 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 3, 3, 4, 5, 7, 8, 10, 12, 15, 16, 19, 21, 23, 25, 26, 27, - 28, 28, 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 3, 3, 4, 5, 6, 8, 9, 11, 13, 16, 18, 20, 22, 23, 25, 26, 27, - 28, 28, 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 7, 9, 10, 12, 15, 16, 19, 21, 22, 24, 26, 26, - 27, 28, 28, 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 10, 11, 13, 16, 18, 20, 21, 23, 25, 26, - 27, 27, 28, 29, 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 8, 9, 11, 12, 15, 16, 19, 20, 22, 23, 25, - 26, 27, 28, 28, 29, 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 13, 16, 18, 20, 21, 23, 24, - 26, 26, 27, 28, 28, 29, 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 7, 8, 9, 11, 12, 15, 16, 19, 20, 22, 23, - 25, 26, 26, 27, 28, 28, 29, 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6, 7, 9, 10, 12, 13, 16, 18, 19, 21, 22, - 24, 25, 26, 27, 27, 28, 28, 29, 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 19, 20, 21, - 23, 24, 25, 26, 27, 28, 28, 28, 29, 29, 29, 30, 30 }, - { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 7, 8, 9, 11, 12, 13, 16, 18, 19, 21, - 22, 23, 25, 26, 26, 27, 28, 28, 29, 29, 29, 30, 30, 30 }, - { 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6, 7, 9, 10, 11, 13, 15, 16, 18, 20, - 21, 22, 24, 25, 26, 27, 27, 28, 28, 29, 29, 29, 30, 30, 30 }, - { 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 11, 12, 13, 16, 18, 19, 20, - 22, 23, 24, 25, 26, 27, 27, 28, 28, 29, 29, 29, 30, 30, 30 }, - { 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 7, 8, 9, 10, 11, 13, 15, 16, 18, 20, - 21, 22, 23, 25, 26, 26, 27, 27, 28, 28, 29, 29, 29, 30, 30, 30 }, - { 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 13, 16, 18, 19, - 20, 21, 23, 24, 25, 26, 26, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30 }, - { 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16, 18, - 19, 21, 22, 23, 24, 25, 26, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30 }, - { 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 7, 8, 9, 10, 11, 12, 13, 16, 18, - 19, 20, 21, 22, 23, 25, 26, 26, 27, 27, 28, 28, 29, 29, 29, 29, 30, 30, - 30 }, - { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, - 18, 19, 20, 22, 23, 24, 25, 26, 26, 27, 27, 28, 28, 29, 29, 29, 29, 30, 30, - 30 }, - { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 28, 28, 29, 29, 29, 29, 30, - 30, 30 }, - { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 7, 8, 9, 10, 11, 12, 13, 15, - 16, 18, 19, 20, 21, 22, 23, 25, 26, 26, 27, 27, 28, 28, 28, 29, 29, 29, 29, - 30, 30, 30 }, - { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 27, 28, 28, 28, 29, 29, 29, - 29, 30, 30, 30 }, - { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 27, 28, 28, 28, 29, 29, - 29, 29, 30, 30, 30 }, - { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 27, 28, 28, 28, 29, 29, - 29, 29, 30, 30, 30, 30 } -}; - -static const unsigned char ScaleFactorWeights[8][32] = { - { 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 10, 12, 12, 12 }, - { 3, 2, 2, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 2, 3, - 3, 4, 5, 7, 10, 10, 10 }, - { 0, 2, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, - 7, 7, 8, 9, 12, 12, 12 }, - { 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 8, 8, 10, - 11, 11, 12, 13, 13, 13, 13 }, - { 0, 2, 2, 3, 3, 4, 4, 5, 4, 5, 5, 5, 5, 6, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, - 11, 12, 12, 13, 13, 14, 14, 14 }, - { 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, - 6, 7, 7, 9, 11, 11, 11 }, - { 0, 5, 8, 10, 11, 11, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 12, 12, 12, 12, 13, 15, 15, 15 }, - { 0, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 11, - 11, 12, 12, 12, 12, 13, 13, 15, 15, 15 } -}; - -static const double SpectrumScale[32] = -{ - 3.0517578125e-5, 6.1035156250e-5, 1.2207031250e-4, 2.4414062500e-4, - 4.8828125000e-4, 9.7656250000e-4, 1.9531250000e-3, 3.9062500000e-3, - 7.8125000000e-3, 1.5625000000e-2, 3.1250000000e-2, 6.2500000000e-2, - 1.2500000000e-1, 2.5000000000e-1, 5.0000000000e-1, 1.0000000000e+0, - 2.0000000000e+0, 4.0000000000e+0, 8.0000000000e+0, 1.6000000000e+1, - 3.2000000000e+1, 6.4000000000e+1, 1.2800000000e+2, 2.5600000000e+2, - 5.1200000000e+2, 1.0240000000e+3, 2.0480000000e+3, 4.0960000000e+3, - 8.1920000000e+3, 1.6384000000e+4, 3.2768000000e+4, 6.5536000000e+4 -}; - -static const double QuantizerInverseStepSize[16] = -{ - 0.5, 1.5, 3.5, 7.5, 15.5, 31.5, 63.5, 127.5, - 255.5, 511.5, 1023.5, 2047.5, 4095.5, 8191.5, 16383.5, 32767.5 -}; - -static const double QuantizerStepSize[16] = -{ - 2.0000000000000000e+0, 6.6666666666666663e-1, 2.8571428571428570e-1, 1.3333333333333333e-1, - 6.4516129032258063e-2, 3.1746031746031744e-2, 1.5748031496062992e-2, 7.8431372549019607e-3, - 3.9138943248532287e-3, 1.9550342130987292e-3, 9.7703957010258913e-4, 4.8840048840048840e-4, - 2.4417043096081065e-4, 1.2207776353537203e-4, 6.1037018951994385e-5, 3.0518043793392844e-5 -}; - -static const double QuantizerFineStepSize[16] = -{ - 3.0518043793392844e-05, 1.0172681264464281e-05, 4.3597205419132631e-06, 2.0345362528928561e-06, - 9.8445302559331759e-07, 4.8441339354591809e-07, 2.4029955742829012e-07, 1.1967860311134448e-07, - 5.9722199204291275e-08, 2.9831909866464167e-08, 1.4908668194134265e-08, 7.4525137468602791e-09, - 3.7258019525568114e-09, 1.8627872668859698e-09, 9.3136520869755679e-10, 4.6567549848772173e-10 -}; - -static const bex_group BexGroupInfo[8] = -{ - { 16, 21, 0 }, - { 18, 22, 1 }, - { 20, 22, 2 }, - { 21, 22, 3 }, - { 21, 22, 3 }, - { 23, 24, 4 }, - { 23, 24, 4 }, - { 24, 24, 5 } -}; - -static const int BexEncodedValueCounts[5][6] = -{ - {0, 0, 0, 4, 4, 2}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 2, 2, 1}, - {0, 0, 0, 2, 2, 2}, - {1, 1, 1, 0, 0, 0} -}; - -// [mode][bands][valueIndex] -static const int BexDataLengths[5][6][4] = -{ - { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {5, 4, 3, 3}, - {4, 4, 3, 4}, - {4, 5, 0, 0} - }, { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0} - }, { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {6, 6, 0, 0}, - {6, 6, 0, 0}, - {6, 0, 0, 0} - }, { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {4, 4, 0, 0}, - {4, 4, 0, 0}, - {4, 4, 0, 0} - }, { - {3, 0, 0, 0}, - {3, 0, 0, 0}, - {3, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0} - } -}; - -static const double BexMode0Bands3[5][32] = -{ - { - 0.000000e+0, 1.988220e-1, 2.514343e-1, 2.960510e-1, - 3.263550e-1, 3.771362e-1, 3.786926e-1, 4.540405e-1, - 4.877625e-1, 5.262451e-1, 5.447083e-1, 5.737000e-1, - 6.212158e-1, 6.222839e-1, 6.560974e-1, 6.896667e-1, - 7.555542e-1, 7.677917e-1, 7.918091e-1, 7.971497e-1, - 8.188171e-1, 8.446045e-1, 9.790649e-1, 9.822083e-1, - 9.846191e-1, 9.859314e-1, 9.863586e-1, 9.863892e-1, - 9.873352e-1, 9.881287e-1, 9.898682e-1, 9.913330e-1 - }, { - 0.000000e+0, 9.982910e-1, 7.592773e-2, 7.179565e-1, - 9.851379e-1, 5.340271e-1, 9.013672e-1, 6.349182e-1, - 7.226257e-1, 1.948547e-1, 7.628174e-1, 9.873657e-1, - 8.112183e-1, 2.715454e-1, 9.734192e-1, 1.443787e-1, - 4.640198e-1, 3.249207e-1, 3.790894e-1, 8.276367e-2, - 5.954590e-1, 2.864380e-1, 9.806824e-1, 7.929077e-1, - 6.292114e-1, 4.887085e-1, 2.905273e-1, 1.301880e-1, - 3.140869e-1, 5.482483e-1, 4.210815e-1, 1.182861e-1 - }, { - 0.000000e+0, 3.155518e-2, 8.581543e-2, 1.364746e-1, - 1.858826e-1, 2.368469e-1, 2.888184e-1, 3.432617e-1, - 4.012451e-1, 4.623108e-1, 5.271301e-1, 5.954895e-1, - 6.681213e-1, 7.448425e-1, 8.245239e-1, 9.097290e-1 - }, { - 0.000000e+0, 4.418945e-2, 1.303711e-1, 2.273560e-1, - 3.395996e-1, 4.735718e-1, 6.267090e-1, 8.003845e-1 - }, { - 0.000000e+0, 2.804565e-2, 9.683228e-2, 1.849976e-1, - 3.005981e-1, 4.470520e-1, 6.168518e-1, 8.007813e-1 - } -}; - -static const double BexMode0Bands4[5][16] = -{ - { - 0.000000e+0, 2.708740e-1, 3.479614e-1, 3.578186e-1, - 5.083618e-1, 5.299072e-1, 5.819092e-1, 6.381836e-1, - 7.276917e-1, 7.595520e-1, 7.878723e-1, 9.707336e-1, - 9.713135e-1, 9.736023e-1, 9.759827e-1, 9.832458e-1 - }, { - 0.000000e+0, 2.330627e-1, 5.891418e-1, 7.170410e-1, - 2.036438e-1, 1.613464e-1, 6.668701e-1, 9.481201e-1, - 9.769897e-1, 5.111694e-1, 3.522644e-1, 8.209534e-1, - 2.933960e-1, 9.757690e-1, 5.289917e-1, 4.372253e-1 - }, { - 0.000000e+0, 4.360962e-2, 1.056519e-1, 1.590576e-1, - 2.078857e-1, 2.572937e-1, 3.082581e-1, 3.616028e-1, - 4.191589e-1, 4.792175e-1, 5.438538e-1, 6.125183e-1, - 6.841125e-1, 7.589417e-1, 8.365173e-1, 9.148254e-1 - }, { - 0.000000e+0, 4.074097e-2, 1.164551e-1, 2.077026e-1, - 3.184509e-1, 4.532166e-1, 6.124268e-1, 7.932129e-1 - }, { - 0.000000e+0, 8.880615e-3, 2.932739e-2, 5.593872e-2, - 8.825684e-2, 1.259155e-1, 1.721497e-1, 2.270813e-1, - 2.901611e-1, 3.579712e-1, 4.334106e-1, 5.147095e-1, - 6.023254e-1, 6.956177e-1, 7.952881e-1, 8.977356e-1 - } -}; - -static const double BexMode0Bands5[3][32] = -{ - { - 0.000000e+0, 7.379150e-2, 1.806335e-1, 2.687073e-1, - 3.407898e-1, 4.047546e-1, 4.621887e-1, 5.168762e-1, - 5.703125e-1, 6.237488e-1, 6.763611e-1, 7.288208e-1, - 7.808533e-1, 8.337708e-1, 8.874512e-1, 9.418030e-1 - }, { - 0.000000e+0, 7.980347e-2, 1.615295e-1, 1.665649e-1, - 1.822205e-1, 2.185669e-1, 2.292175e-1, 2.456665e-1, - 2.666321e-1, 3.306580e-1, 3.330688e-1, 3.765259e-1, - 4.085083e-1, 4.400024e-1, 4.407654e-1, 4.817505e-1, - 4.924011e-1, 5.320740e-1, 5.893860e-1, 6.131287e-1, - 6.212463e-1, 6.278076e-1, 6.308899e-1, 7.660828e-1, - 7.850647e-1, 7.910461e-1, 7.929382e-1, 8.038330e-1, - 9.834900e-1, 9.846191e-1, 9.852295e-1, 9.862671e-1 - }, { - 0.000000e+0, 6.084290e-1, 3.672791e-1, 3.151855e-1, - 1.488953e-1, 2.571716e-1, 5.103455e-1, 3.311157e-1, - 5.426025e-2, 4.254456e-1, 7.998352e-1, 7.873230e-1, - 5.418701e-1, 2.925110e-1, 8.468628e-2, 1.410522e-1, - 9.819641e-1, 9.609070e-1, 3.530884e-2, 9.729004e-2, - 5.758362e-1, 9.941711e-1, 7.215576e-1, 7.183228e-1, - 2.028809e-1, 9.588623e-2, 2.032166e-1, 1.338806e-1, - 5.003357e-1, 1.874390e-1, 9.804993e-1, 1.107788e-1 - } -}; - -static const double BexMode2Scale[64] = -{ - 4.272461e-4, 1.312256e-3, 2.441406e-3, 3.692627e-3, - 4.913330e-3, 6.134033e-3, 7.507324e-3, 8.972168e-3, - 1.049805e-2, 1.223755e-2, 1.406860e-2, 1.599121e-2, - 1.800537e-2, 2.026367e-2, 2.264404e-2, 2.517700e-2, - 2.792358e-2, 3.073120e-2, 3.344727e-2, 3.631592e-2, - 3.952026e-2, 4.275513e-2, 4.608154e-2, 4.968262e-2, - 5.355835e-2, 5.783081e-2, 6.195068e-2, 6.677246e-2, - 7.196045e-2, 7.745361e-2, 8.319092e-2, 8.993530e-2, - 9.759521e-2, 1.056213e-1, 1.138916e-1, 1.236267e-1, - 1.348267e-1, 1.470337e-1, 1.603394e-1, 1.755676e-1, - 1.905823e-1, 2.071228e-1, 2.245178e-1, 2.444153e-1, - 2.658997e-1, 2.897644e-1, 3.146057e-1, 3.450012e-1, - 3.766174e-1, 4.122620e-1, 4.505615e-1, 4.893799e-1, - 5.305481e-1, 5.731201e-1, 6.157837e-1, 6.580811e-1, - 6.985168e-1, 7.435303e-1, 7.865906e-1, 8.302612e-1, - 8.718567e-1, 9.125671e-1, 9.575806e-1, 9.996643e-1 -}; - -static const double BexMode3Initial[16] = -{ - 3.491211e-1, 5.371094e-1, 6.782227e-1, 7.910156e-1, - 9.057617e-1, 1.024902e+0, 1.156250e+0, 1.290527e+0, - 1.458984e+0, 1.664551e+0, 1.929688e+0, 2.278320e+0, - 2.831543e+0, 3.659180e+0, 5.257813e+0, 8.373047e+0 -}; - -static const double BexMode3Rate[16] = -{ - -2.913818e-1, -2.541504e-1, -1.664429e-1, -1.476440e-1, - -1.342163e-1, -1.220703e-1, -1.117554e-1, -1.026611e-1, - -9.436035e-2, -8.483887e-2, -7.476807e-2, -6.304932e-2, - -4.492188e-2, -2.447510e-2, +1.831055e-4, +4.174805e-2 -}; - -static const double BexMode4Multiplier[8] = -{ - 3.610229e-2, 1.260681e-1, 2.227478e-1, 3.338318e-1, - 4.662170e-1, 6.221313e-1, 7.989197e-1, 9.939575e-1 -}; - -extern double MdctWindow[3][256]; -extern double ImdctWindow[3][256]; -extern double SinTables[9][256]; -extern double CosTables[9][256]; -extern int ShuffleTables[9][256]; - diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/unpack.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/unpack.c deleted file mode 100644 index d65cab9c2..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/unpack.c +++ /dev/null @@ -1,423 +0,0 @@ -#include "tables.h" -#include "unpack.h" -#include "bit_allocation.h" -#include -#include "scale_factors.h" -#include "utility.h" -#include "huffCodes.h" - -at9_status UnpackFrame(frame* frame, bit_reader_cxt* br) -{ - const int block_count = frame->config->ChannelConfig.BlockCount; - - for (int i = 0; i < block_count; i++) - { - ERROR_CHECK(UnpackBlock(&frame->Blocks[i], br)); - } - return ERR_SUCCESS; -} - -at9_status UnpackBlock(block* block, bit_reader_cxt* br) -{ - ERROR_CHECK(ReadBlockHeader(block, br)); - - if (block->BlockType == LFE) - { - ERROR_CHECK(UnpackLfeBlock(block, br)); - } - else - { - ERROR_CHECK(UnpackStandardBlock(block, br)); - } - - align_position(br, 8); - return ERR_SUCCESS; -} - -at9_status ReadBlockHeader(block* block, bit_reader_cxt* br) -{ - int firstInSuperframe = block->Frame->FrameIndex == 0; - block->FirstInSuperframe = !read_int(br, 1); - block->ReuseBandParams = read_int(br, 1); - - if (block->FirstInSuperframe && block->ReuseBandParams && block->BlockType != LFE) - { - return ERR_UNPACK_REUSE_BAND_PARAMS_INVALID; - } - - return ERR_SUCCESS; -} - -at9_status UnpackStandardBlock(block* block, bit_reader_cxt* br) -{ - if (!block->ReuseBandParams) - { - ERROR_CHECK(ReadBandParams(block, br)); - } - - ERROR_CHECK(ReadGradientParams(block, br)); - ERROR_CHECK(CreateGradient(block)); - ERROR_CHECK(ReadStereoParams(block, br)); - ERROR_CHECK(ReadExtensionParams(block, br)); - - for (int i = 0; i < block->ChannelCount; i++) - { - channel* channel = &block->Channels[i]; - UpdateCodedUnits(channel); - - ERROR_CHECK(read_scale_factors(channel, br)); - CalculateMask(channel); - CalculatePrecisions(channel); - CalculateSpectrumCodebookIndex(channel); - - ERROR_CHECK(ReadSpectra(channel, br)); - ERROR_CHECK(ReadSpectraFine(channel, br)); - } - - block->QuantizationUnitsPrev = block->BandExtensionEnabled ? block->ExtensionUnit : block->QuantizationUnitCount; - return ERR_SUCCESS; -} - -at9_status ReadBandParams(block* block, bit_reader_cxt* br) -{ - const int minBandCount = MinBandCount[block->config->HighSampleRate]; - const int maxExtensionBand = MaxExtensionBand[block->config->HighSampleRate]; - block->BandCount = read_int(br, 4) + minBandCount; - block->QuantizationUnitCount = BandToQuantUnitCount[block->BandCount]; - - if (block->BandCount < minBandCount || block->BandCount > - MaxBandCount[block->config->SampleRateIndex]) - { - return ERR_SUCCESS; - } - - if (block->BlockType == Stereo) - { - block->StereoBand = read_int(br, 4); - block->StereoBand += minBandCount; - block->StereoQuantizationUnit = BandToQuantUnitCount[block->StereoBand]; - } - else - { - block->StereoBand = block->BandCount; - } - - block->BandExtensionEnabled = read_int(br, 1); - if (block->BandExtensionEnabled) - { - block->ExtensionBand = read_int(br, 4); - block->ExtensionBand += minBandCount; - - if (block->ExtensionBand < block->BandCount || block->ExtensionBand > maxExtensionBand) - { - return ERR_UNPACK_BAND_PARAMS_INVALID; - } - - block->ExtensionUnit = BandToQuantUnitCount[block->ExtensionBand]; - } - else - { - block->ExtensionBand = block->BandCount; - block->ExtensionUnit = block->QuantizationUnitCount; - } - - return ERR_SUCCESS; -} - -at9_status ReadGradientParams(block* block, bit_reader_cxt* br) -{ - block->GradientMode = read_int(br, 2); - if (block->GradientMode > 0) - { - block->GradientEndUnit = 31; - block->GradientEndValue = 31; - block->GradientStartUnit = read_int(br, 5); - block->GradientStartValue = read_int(br, 5); - } - else - { - block->GradientStartUnit = read_int(br, 6); - block->GradientEndUnit = read_int(br, 6) + 1; - block->GradientStartValue = read_int(br, 5); - block->GradientEndValue = read_int(br, 5); - } - block->GradientBoundary = read_int(br, 4); - - if (block->GradientBoundary > block->QuantizationUnitCount) - { - return ERR_UNPACK_GRAD_BOUNDARY_INVALID; - } - if (block->GradientStartUnit < 1 || block->GradientStartUnit >= 48) - { - return ERR_UNPACK_GRAD_START_UNIT_OOB; - } - if (block->GradientEndUnit < 1 || block->GradientEndUnit >= 48) - { - return ERR_UNPACK_GRAD_END_UNIT_OOB; - } - if (block->GradientStartUnit > block->GradientEndUnit) - { - return ERR_UNPACK_GRAD_END_UNIT_INVALID; - } - if (block->GradientStartValue < 0 || block->GradientStartValue >= 32) - { - return ERR_UNPACK_GRAD_START_VALUE_OOB; - } - if (block->GradientEndValue < 0 || block->GradientEndValue >= 32) - { - return ERR_UNPACK_GRAD_END_VALUE_OOB; - } - - return ERR_SUCCESS; -} - -at9_status ReadStereoParams(block* block, bit_reader_cxt* br) -{ - if (block->BlockType != Stereo) return ERR_SUCCESS; - - block->PrimaryChannelIndex = read_int(br, 1); - block->HasJointStereoSigns = read_int(br, 1); - if (block->HasJointStereoSigns) - { - for (int i = block->StereoQuantizationUnit; i < block->QuantizationUnitCount; i++) - { - block->JointStereoSigns[i] = read_int(br, 1); - } - } - else - { - memset(block->JointStereoSigns, 0, sizeof(block->JointStereoSigns)); - } - - return ERR_SUCCESS; -} - -void BexReadHeader(channel* channel, bit_reader_cxt* br, int bexBand) -{ - const int bexMode = read_int(br, 2); - channel->BexMode = bexBand > 2 ? bexMode : 4; - channel->BexValueCount = BexEncodedValueCounts[channel->BexMode][bexBand]; -} - -void BexReadData(channel* channel, bit_reader_cxt* br, int bexBand) -{ - for (int i = 0; i < channel->BexValueCount; i++) - { - const int dataLength = BexDataLengths[channel->BexMode][bexBand][i]; - channel->BexValues[i] = read_int(br, dataLength); - } -} - -at9_status ReadExtensionParams(block* block, bit_reader_cxt* br) -{ - int bexBand = 0; - if (block->BandExtensionEnabled) - { - bexBand = BexGroupInfo[block->QuantizationUnitCount - 13].band_count; - if (block->BlockType == Stereo) - { - BexReadHeader(&block->Channels[1], br, bexBand); - } - else - { - br->position += 1; - } - } - block->HasExtensionData = read_int(br, 1); - - if (!block->HasExtensionData) return ERR_SUCCESS; - if (!block->BandExtensionEnabled) - { - block->BexMode = read_int(br, 2); - block->BexDataLength = read_int(br, 5); - br->position += block->BexDataLength; - return ERR_SUCCESS; - } - - BexReadHeader(&block->Channels[0], br, bexBand); - - block->BexDataLength = read_int(br, 5); - if (block->BexDataLength <= 0) return ERR_SUCCESS; - const int bexDataEnd = br->position + block->BexDataLength; - - BexReadData(&block->Channels[0], br, bexBand); - - if (block->BlockType == Stereo) - { - BexReadData(&block->Channels[1], br, bexBand); - } - - // Make sure we didn't read too many bits - if (br->position > bexDataEnd) - { - return ERR_UNPACK_EXTENSION_DATA_INVALID; - } - - return ERR_SUCCESS; -} - -void UpdateCodedUnits(channel* channel) -{ - if (channel->Block->PrimaryChannelIndex == channel->ChannelIndex) - { - channel->CodedQuantUnits = channel->Block->QuantizationUnitCount; - } - else - { - channel->CodedQuantUnits = channel->Block->StereoQuantizationUnit; - } -} - -void CalculateSpectrumCodebookIndex(channel* channel) -{ - memset(channel->CodebookSet, 0, sizeof(channel->CodebookSet)); - const int quantUnits = channel->CodedQuantUnits; - int* sf = channel->ScaleFactors; - - if (quantUnits <= 1) return; - if (channel->config->HighSampleRate) return; - - // Temporarily setting this value allows for simpler code by - // making the last value a non-special case. - const int originalScaleTmp = sf[quantUnits]; - sf[quantUnits] = sf[quantUnits - 1]; - - int avg = 0; - if (quantUnits > 12) - { - for (int i = 0; i < 12; i++) - { - avg += sf[i]; - } - avg = (avg + 6) / 12; - } - - for (int i = 8; i < quantUnits; i++) - { - const int prevSf = sf[i - 1]; - const int nextSf = sf[i + 1]; - const int minSf = min(prevSf, nextSf); - if (sf[i] - minSf >= 3 || sf[i] - prevSf + sf[i] - nextSf >= 3) - { - channel->CodebookSet[i] = 1; - } - } - - for (int i = 12; i < quantUnits; i++) - { - if (channel->CodebookSet[i] == 0) - { - const int minSf = min(sf[i - 1], sf[i + 1]); - if (sf[i] - minSf >= 2 && sf[i] >= avg - (QuantUnitToCoeffCount[i] == 16 ? 1 : 0)) - { - channel->CodebookSet[i] = 1; - } - } - } - - sf[quantUnits] = originalScaleTmp; -} - -at9_status ReadSpectra(channel* channel, bit_reader_cxt* br) -{ - int values[16]; - memset(channel->QuantizedSpectra, 0, sizeof(channel->QuantizedSpectra)); - const int maxHuffPrecision = MaxHuffPrecision[channel->config->HighSampleRate]; - - for (int i = 0; i < channel->CodedQuantUnits; i++) - { - const int subbandCount = QuantUnitToCoeffCount[i]; - const int precision = channel->Precisions[i] + 1; - if (precision <= maxHuffPrecision) - { - const HuffmanCodebook* huff = &HuffmanSpectrum[channel->CodebookSet[i]][precision][QuantUnitToCodebookIndex[i]]; - const int groupCount = subbandCount >> huff->ValueCountPower; - for (int j = 0; j < groupCount; j++) - { - values[j] = ReadHuffmanValue(huff, br, FALSE); - } - - DecodeHuffmanValues(channel->QuantizedSpectra, QuantUnitToCoeffIndex[i], subbandCount, huff, values); - } - else - { - const int subbandIndex = QuantUnitToCoeffIndex[i]; - for (int j = subbandIndex; j < QuantUnitToCoeffIndex[i + 1]; j++) - { - channel->QuantizedSpectra[j] = read_signed_int(br, precision); - } - } - } - - return ERR_SUCCESS; -} - -at9_status ReadSpectraFine(channel* channel, bit_reader_cxt* br) -{ - memset(channel->QuantizedSpectraFine, 0, sizeof(channel->QuantizedSpectraFine)); - - for (int i = 0; i < channel->CodedQuantUnits; i++) - { - if (channel->PrecisionsFine[i] > 0) - { - const int overflowBits = channel->PrecisionsFine[i] + 1; - const int startSubband = QuantUnitToCoeffIndex[i]; - const int endSubband = QuantUnitToCoeffIndex[i + 1]; - - for (int j = startSubband; j < endSubband; j++) - { - channel->QuantizedSpectraFine[j] = read_signed_int(br, overflowBits); - } - } - } - return ERR_SUCCESS; -} - -at9_status UnpackLfeBlock(block* block, bit_reader_cxt* br) -{ - channel* channel = &block->Channels[0]; - block->QuantizationUnitCount = 2; - - DecodeLfeScaleFactors(channel, br); - CalculateLfePrecision(channel); - channel->CodedQuantUnits = block->QuantizationUnitCount; - ReadLfeSpectra(channel, br); - - return ERR_SUCCESS; -} - -void DecodeLfeScaleFactors(channel* channel, bit_reader_cxt* br) -{ - memset(channel->ScaleFactors, 0, sizeof(channel->ScaleFactors)); - for (int i = 0; i < channel->Block->QuantizationUnitCount; i++) - { - channel->ScaleFactors[i] = read_int(br, 5); - } -} - -void CalculateLfePrecision(channel* channel) -{ - block* block = channel->Block; - const int precision = block->ReuseBandParams ? 8 : 4; - for (int i = 0; i < block->QuantizationUnitCount; i++) - { - channel->Precisions[i] = precision; - channel->PrecisionsFine[i] = 0; - } -} - -void ReadLfeSpectra(channel* channel, bit_reader_cxt* br) -{ - memset(channel->QuantizedSpectra, 0, sizeof(channel->QuantizedSpectra)); - - for (int i = 0; i < channel->CodedQuantUnits; i++) - { - if (channel->Precisions[i] <= 0) continue; - - const int precision = channel->Precisions[i] + 1; - for (int j = QuantUnitToCoeffIndex[i]; j < QuantUnitToCoeffIndex[i + 1]; j++) - { - channel->QuantizedSpectra[j] = read_signed_int(br, precision); - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/unpack.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/unpack.h deleted file mode 100644 index 53a4c2b3d..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/unpack.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "bit_reader.h" -#include "error_codes.h" -#include "structures.h" - -at9_status UnpackFrame(frame* frame, bit_reader_cxt* br); -at9_status UnpackBlock(block* block, bit_reader_cxt* br); -at9_status ReadBlockHeader(block* block, bit_reader_cxt* br); -at9_status UnpackStandardBlock(block* block, bit_reader_cxt* br); -at9_status ReadBandParams(block* block, bit_reader_cxt* br); -at9_status ReadGradientParams(block* block, bit_reader_cxt* br); -at9_status ReadStereoParams(block* block, bit_reader_cxt* br); -at9_status ReadExtensionParams(block* block, bit_reader_cxt* br); -void UpdateCodedUnits(channel* channel); -void CalculateSpectrumCodebookIndex(channel* channel); - -at9_status ReadSpectra(channel* channel, bit_reader_cxt* br); -at9_status ReadSpectraFine(channel* channel, bit_reader_cxt* br); - -at9_status UnpackLfeBlock(block* block, bit_reader_cxt* br); -void DecodeLfeScaleFactors(channel* channel, bit_reader_cxt* br); -void CalculateLfePrecision(channel* channel); -void ReadLfeSpectra(channel* channel, bit_reader_cxt* br); diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/utility.c b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/utility.c deleted file mode 100644 index b440ce126..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/utility.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "utility.h" -#include - -int max(int a, int b) { return a > b ? a : b; } -int min(int a, int b) { return a > b ? b : a; } - -unsigned int BitReverse32(unsigned int value, int bitCount) -{ - value = ((value & 0xaaaaaaaa) >> 1) | ((value & 0x55555555) << 1); - value = ((value & 0xcccccccc) >> 2) | ((value & 0x33333333) << 2); - value = ((value & 0xf0f0f0f0) >> 4) | ((value & 0x0f0f0f0f) << 4); - value = ((value & 0xff00ff00) >> 8) | ((value & 0x00ff00ff) << 8); - value = (value >> 16) | (value << 16); - return value >> (32 - bitCount); -} - -int SignExtend32(int value, int bits) -{ - const int shift = 8 * sizeof(int) - bits; - return (value << shift) >> shift; -} - -short Clamp16(int value) -{ - if (value > SHRT_MAX) - return SHRT_MAX; - if (value < SHRT_MIN) - return SHRT_MIN; - return (short)value; -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/utility.h b/Frameworks/libatrac9/libatrac9/LibAtrac9/C/utility.h deleted file mode 100644 index 489b54da4..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/C/utility.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#define FALSE 0 -#define TRUE 1 -#define NULL 0 - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -int max(int a, int b); -int min(int a, int b); -unsigned int BitReverse32(unsigned int value, int bitCount); -int SignExtend32(int value, int bits); -short Clamp16(int value); diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9.sln b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9.sln deleted file mode 100644 index 5310f9132..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9.sln +++ /dev/null @@ -1,42 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2003 -MinimumVisualStudioVersion = 15.0.26124.0 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibAtrac9", "LibAtrac9\LibAtrac9.csproj", "{2414DAA9-779C-4E7E-A97F-4DE09B22B88F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|ARM = Debug|ARM - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|ARM = Release|ARM - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Debug|ARM.ActiveCfg = Debug|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Debug|ARM.Build.0 = Debug|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Debug|x64.ActiveCfg = Debug|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Debug|x64.Build.0 = Debug|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Debug|x86.ActiveCfg = Debug|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Debug|x86.Build.0 = Debug|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Release|Any CPU.Build.0 = Release|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Release|ARM.ActiveCfg = Release|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Release|ARM.Build.0 = Release|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Release|x64.ActiveCfg = Release|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Release|x64.Build.0 = Release|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Release|x86.ActiveCfg = Release|Any CPU - {2414DAA9-779C-4E7E-A97F-4DE09B22B88F}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {2AFD09F0-D995-47ED-AA86-FFA93824A514} - EndGlobalSection -EndGlobal diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Atrac9Config.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Atrac9Config.cs deleted file mode 100644 index 8d1e4357d..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Atrac9Config.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System.IO; -using LibAtrac9.Utilities; - -namespace LibAtrac9 -{ - /// - /// Stores the configuration data needed to decode or encode an ATRAC9 stream. - /// - public class Atrac9Config - { - /// - /// The 4-byte ATRAC9 configuration data. - /// - public byte[] ConfigData { get; } - - /// - /// A 4-bit value specifying one of 16 sample rates. - /// - public int SampleRateIndex { get; } - /// - /// A 3-bit value specifying one of 6 substream channel mappings. - /// - public int ChannelConfigIndex { get; } - /// - /// An 11-bit value containing the average size of a single frame. - /// - public int FrameBytes { get; } - /// - /// A 2-bit value indicating how many frames are in each superframe. - /// - public int SuperframeIndex { get; } - - /// - /// The channel mapping used by the ATRAC9 stream. - /// - public ChannelConfig ChannelConfig { get; } - /// - /// The total number of channels in the ATRAC9 stream. - /// - public int ChannelCount { get; } - /// - /// The sample rate of the ATRAC9 stream. - /// - public int SampleRate { get; } - /// - /// Indicates whether the ATRAC9 stream has a of 8 or above. - /// - public bool HighSampleRate { get; } - - /// - /// The number of frames in each superframe. - /// - public int FramesPerSuperframe { get; } - /// - /// The number of samples in one frame as an exponent of 2. - /// = 2^. - /// - public int FrameSamplesPower { get; } - /// - /// The number of samples in one frame. - /// - public int FrameSamples { get; } - /// - /// The number of bytes in one superframe. - /// - public int SuperframeBytes { get; } - /// - /// The number of samples in one superframe. - /// - public int SuperframeSamples { get; } - - /// - /// Reads ATRAC9 configuration data and calculates the stream parameters from it. - /// - /// The processed ATRAC9 configuration. - public Atrac9Config(byte[] configData) - { - if (configData == null || configData.Length != 4) - { - throw new InvalidDataException("Config data must be 4 bytes long"); - } - - ReadConfigData(configData, out int a, out int b, out int c, out int d); - SampleRateIndex = a; - ChannelConfigIndex = b; - FrameBytes = c; - SuperframeIndex = d; - ConfigData = configData; - - FramesPerSuperframe = 1 << SuperframeIndex; - SuperframeBytes = FrameBytes << SuperframeIndex; - ChannelConfig = Tables.ChannelConfig[ChannelConfigIndex]; - - ChannelCount = ChannelConfig.ChannelCount; - SampleRate = Tables.SampleRates[SampleRateIndex]; - HighSampleRate = SampleRateIndex > 7; - FrameSamplesPower = Tables.SamplingRateIndexToFrameSamplesPower[SampleRateIndex]; - FrameSamples = 1 << FrameSamplesPower; - SuperframeSamples = FrameSamples * FramesPerSuperframe; - } - - private static void ReadConfigData(byte[] configData, out int sampleRateIndex, out int channelConfigIndex, out int frameBytes, out int superframeIndex) - { - var reader = new BitReader(configData); - - int header = reader.ReadInt(8); - sampleRateIndex = reader.ReadInt(4); - channelConfigIndex = reader.ReadInt(3); - int validationBit = reader.ReadInt(1); - frameBytes = reader.ReadInt(11) + 1; - superframeIndex = reader.ReadInt(2); - - if (header != 0xFE || validationBit != 0) - { - throw new InvalidDataException("ATRAC9 Config Data is invalid"); - } - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Atrac9Decoder.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Atrac9Decoder.cs deleted file mode 100644 index fb2fb344b..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Atrac9Decoder.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using LibAtrac9.Utilities; - -namespace LibAtrac9 -{ - /// - /// Decodes an ATRAC9 stream into 16-bit PCM. - /// - public class Atrac9Decoder - { - /// - /// The config data for the current ATRAC9 stream. - /// - public Atrac9Config Config { get; private set; } - - private Frame Frame { get; set; } - private BitReader Reader { get; set; } - private bool _initialized; - - /// - /// Sets up the decoder to decode an ATRAC9 stream based on the information in . - /// - /// A 4-byte value containing information about the ATRAC9 stream. - public void Initialize(byte[] configData) - { - Config = new Atrac9Config(configData); - Frame = new Frame(Config); - Reader = new BitReader(null); - _initialized = true; - } - - /// - /// Decodes one superframe of ATRAC9 data. - /// - /// The ATRAC9 data to decode. The array must be at least - /// . bytes long. - /// A buffer that the decoded PCM data will be placed in. - /// The array must have dimensions of at least [.] - /// [.]. - public void Decode(byte[] atrac9Data, short[][] pcmOut) - { - if (!_initialized) throw new InvalidOperationException("Decoder must be initialized before decoding."); - - ValidateDecodeBuffers(atrac9Data, pcmOut); - Reader.SetBuffer(atrac9Data); - DecodeSuperFrame(pcmOut); - } - - private void ValidateDecodeBuffers(byte[] atrac9Buffer, short[][] pcmBuffer) - { - if (atrac9Buffer == null) throw new ArgumentNullException(nameof(atrac9Buffer)); - if (pcmBuffer == null) throw new ArgumentNullException(nameof(pcmBuffer)); - - if (atrac9Buffer.Length < Config.SuperframeBytes) - { - throw new ArgumentException("ATRAC9 buffer is too small"); - } - - if (pcmBuffer.Length < Config.ChannelCount) - { - throw new ArgumentException("PCM buffer is too small"); - } - - for (int i = 0; i < Config.ChannelCount; i++) - { - if (pcmBuffer[i]?.Length < Config.SuperframeSamples) - { - throw new ArgumentException("PCM buffer is too small"); - } - } - } - - private void DecodeSuperFrame(short[][] pcmOut) - { - for (int i = 0; i < Config.FramesPerSuperframe; i++) - { - Frame.FrameIndex = i; - DecodeFrame(Reader, Frame); - PcmFloatToShort(pcmOut, i * Config.FrameSamples); - Reader.AlignPosition(8); - } - } - - private void PcmFloatToShort(short[][] pcmOut, int start) - { - int endSample = start + Config.FrameSamples; - int channelNum = 0; - foreach (Block block in Frame.Blocks) - { - foreach (Channel channel in block.Channels) - { - double[] pcmSrc = channel.Pcm; - short[] pcmDest = pcmOut[channelNum++]; - for (int d = 0, s = start; s < endSample; d++, s++) - { - double sample = pcmSrc[d]; - // Not using Math.Round because it's ~20x slower on 64-bit - int roundedSample = (int)Math.Floor(sample + 0.5); - pcmDest[s] = Helpers.Clamp16(roundedSample); - } - } - } - } - - private static void DecodeFrame(BitReader reader, Frame frame) - { - Unpack.UnpackFrame(reader, frame); - - foreach (Block block in frame.Blocks) - { - Quantization.DequantizeSpectra(block); - Stereo.ApplyIntensityStereo(block); - Quantization.ScaleSpectrum(block); - BandExtension.ApplyBandExtension(block); - ImdctBlock(block); - } - } - - private static void ImdctBlock(Block block) - { - foreach (Channel channel in block.Channels) - { - channel.Mdct.RunImdct(channel.Spectra, channel.Pcm); - } - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Atrac9Rng.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Atrac9Rng.cs deleted file mode 100644 index 072a61391..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Atrac9Rng.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace LibAtrac9 -{ - /// - /// An Xorshift RNG used by the ATRAC9 codec - /// - internal class Atrac9Rng - { - private ushort _stateA; - private ushort _stateB; - private ushort _stateC; - private ushort _stateD; - - public Atrac9Rng(ushort seed) - { - int startValue = 0x4D93 * (seed ^ (seed >> 14)); - - _stateA = (ushort)(3 - startValue); - _stateB = (ushort)(2 - startValue); - _stateC = (ushort)(1 - startValue); - _stateD = (ushort)(0 - startValue); - } - - public ushort Next() - { - ushort t = (ushort)(_stateD ^ (_stateD << 5)); - _stateD = _stateC; - _stateC = _stateB; - _stateB = _stateA; - _stateA = (ushort)(t ^ _stateA ^ ((t ^ (_stateA >> 5)) >> 4)); - return _stateA; - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/BandExtension.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/BandExtension.cs deleted file mode 100644 index 297c79bfa..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/BandExtension.cs +++ /dev/null @@ -1,372 +0,0 @@ -using System; - -namespace LibAtrac9 -{ - internal static class BandExtension - { - public static void ApplyBandExtension(Block block) - { - if (!block.BandExtensionEnabled || !block.HasExtensionData) return; - - foreach (Channel channel in block.Channels) - { - ApplyBandExtensionChannel(channel); - } - } - - private static void ApplyBandExtensionChannel(Channel channel) - { - int groupAUnit = channel.Block.QuantizationUnitCount; - int[] scaleFactors = channel.ScaleFactors; - double[] spectra = channel.Spectra; - double[] scales = channel.BexScales; - int[] values = channel.BexValues; - - GetBexBandInfo(out int bandCount, out int groupBUnit, out int groupCUnit, groupAUnit); - int totalUnits = Math.Max(groupCUnit, 22); - - int groupABin = Tables.QuantUnitToCoeffIndex[groupAUnit]; - int groupBBin = Tables.QuantUnitToCoeffIndex[groupBUnit]; - int groupCBin = Tables.QuantUnitToCoeffIndex[groupCUnit]; - int totalBins = Tables.QuantUnitToCoeffIndex[totalUnits]; - - FillHighFrequencies(spectra, groupABin, groupBBin, groupCBin, totalBins); - - switch (channel.BexMode) - { - case 0: - int bexQuantUnits = totalUnits - groupAUnit; - - switch (bandCount) - { - case 3: - scales[0] = BexMode0Bands3[0][values[0]]; - scales[1] = BexMode0Bands3[1][values[0]]; - scales[2] = BexMode0Bands3[2][values[1]]; - scales[3] = BexMode0Bands3[3][values[2]]; - scales[4] = BexMode0Bands3[4][values[3]]; - break; - case 4: - scales[0] = BexMode0Bands4[0][values[0]]; - scales[1] = BexMode0Bands4[1][values[0]]; - scales[2] = BexMode0Bands4[2][values[1]]; - scales[3] = BexMode0Bands4[3][values[2]]; - scales[4] = BexMode0Bands4[4][values[3]]; - break; - case 5: - scales[0] = BexMode0Bands5[0][values[0]]; - scales[1] = BexMode0Bands5[1][values[1]]; - scales[2] = BexMode0Bands5[2][values[1]]; - break; - } - - scales[bexQuantUnits - 1] = Tables.SpectrumScale[scaleFactors[groupAUnit]]; - - AddNoiseToSpectrum(channel, Tables.QuantUnitToCoeffIndex[totalUnits - 1], - Tables.QuantUnitToCoeffCount[totalUnits - 1]); - ScaleBexQuantUnits(spectra, scales, groupAUnit, totalUnits); - break; - case 1: - for (int i = groupAUnit; i < totalUnits; i++) - { - scales[i - groupAUnit] = Tables.SpectrumScale[scaleFactors[i]]; - } - - AddNoiseToSpectrum(channel, groupABin, totalBins - groupABin); - ScaleBexQuantUnits(spectra, scales, groupAUnit, totalUnits); - break; - case 2: - double groupAScale2 = BexMode2Scale[values[0]]; - double groupBScale2 = BexMode2Scale[values[1]]; - - for (int i = groupABin; i < groupBBin; i++) - { - spectra[i] *= groupAScale2; - } - - for (int i = groupBBin; i < groupCBin; i++) - { - spectra[i] *= groupBScale2; - } - return; - case 3: - double rate = Math.Pow(2, BexMode3Rate[values[1]]); - double scale = BexMode3Initial[values[0]]; - for (int i = groupABin; i < totalBins; i++) - { - scale *= rate; - spectra[i] *= scale; - } - return; - case 4: - double mult = BexMode4Multiplier[values[0]]; - double groupAScale4 = 0.7079468 * mult; - double groupBScale4 = 0.5011902 * mult; - double groupCScale4 = 0.3548279 * mult; - - for (int i = groupABin; i < groupBBin; i++) - { - spectra[i] *= groupAScale4; - } - - for (int i = groupBBin; i < groupCBin; i++) - { - spectra[i] *= groupBScale4; - } - - for (int i = groupCBin; i < totalBins; i++) - { - spectra[i] *= groupCScale4; - } - return; - } - } - - private static void ScaleBexQuantUnits(double[] spectra, double[] scales, int startUnit, int totalUnits) - { - for (int i = startUnit; i < totalUnits; i++) - { - for (int k = Tables.QuantUnitToCoeffIndex[i]; k < Tables.QuantUnitToCoeffIndex[i + 1]; k++) - { - spectra[k] *= scales[i - startUnit]; - } - } - } - - private static void FillHighFrequencies(double[] spectra, int groupABin, int groupBBin, int groupCBin, int totalBins) - { - for (int i = 0; i < groupBBin - groupABin; i++) - { - spectra[groupABin + i] = spectra[groupABin - i - 1]; - } - - for (int i = 0; i < groupCBin - groupBBin; i++) - { - spectra[groupBBin + i] = spectra[groupBBin - i - 1]; - } - - for (int i = 0; i < totalBins - groupCBin; i++) - { - spectra[groupCBin + i] = spectra[groupCBin - i - 1]; - } - } - - private static void AddNoiseToSpectrum(Channel channel, int index, int count) - { - if (channel.Rng == null) - { - int[] sf = channel.ScaleFactors; - ushort seed = (ushort)(543 * (sf[8] + sf[12] + sf[15] + 1)); - channel.Rng = new Atrac9Rng(seed); - } - for (int i = 0; i < count; i++) - { - channel.Spectra[i + index] = channel.Rng.Next() / 65535.0 * 2.0 - 1.0; - } - } - - public static void GetBexBandInfo(out int bandCount, out int groupAUnit, out int groupBUnit, int quantUnits) - { - groupAUnit = BexGroupInfo[quantUnits - 13][0]; - groupBUnit = BexGroupInfo[quantUnits - 13][1]; - bandCount = BexGroupInfo[quantUnits - 13][2]; - } - - public static readonly byte[][] BexGroupInfo = - { - new byte[] {16, 21, 0}, - new byte[] {18, 22, 1}, - new byte[] {20, 22, 2}, - new byte[] {21, 22, 3}, - new byte[] {21, 22, 3}, - new byte[] {23, 24, 4}, - new byte[] {23, 24, 4}, - new byte[] {24, 24, 5} - }; - - // [mode][bands] - - public static readonly byte[][] BexEncodedValueCounts = - { - new byte[] {0, 0, 0, 4, 4, 2}, - new byte[] {0, 0, 0, 0, 0, 0}, - new byte[] {0, 0, 0, 2, 2, 1}, - new byte[] {0, 0, 0, 2, 2, 2}, - new byte[] {1, 1, 1, 0, 0, 0} - }; - - // [mode][bands][valueIndex] - - public static readonly byte[][][] BexDataLengths = - { - new[] { - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {5, 4, 3, 3}, - new byte[] {4, 4, 3, 4}, - new byte[] {4, 5, 0, 0} - }, new[] { - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0} - }, new[] { - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {6, 6, 0, 0}, - new byte[] {6, 6, 0, 0}, - new byte[] {6, 0, 0, 0} - }, new[] { - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {4, 4, 0, 0}, - new byte[] {4, 4, 0, 0}, - new byte[] {4, 4, 0, 0} - }, new[] { - new byte[] {3, 0, 0, 0}, - new byte[] {3, 0, 0, 0}, - new byte[] {3, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0} - } - }; - - public static readonly double[][] BexMode0Bands3 = - { - new[] { - 0.000000e+0, 1.988220e-1, 2.514343e-1, 2.960510e-1, - 3.263550e-1, 3.771362e-1, 3.786926e-1, 4.540405e-1, - 4.877625e-1, 5.262451e-1, 5.447083e-1, 5.737000e-1, - 6.212158e-1, 6.222839e-1, 6.560974e-1, 6.896667e-1, - 7.555542e-1, 7.677917e-1, 7.918091e-1, 7.971497e-1, - 8.188171e-1, 8.446045e-1, 9.790649e-1, 9.822083e-1, - 9.846191e-1, 9.859314e-1, 9.863586e-1, 9.863892e-1, - 9.873352e-1, 9.881287e-1, 9.898682e-1, 9.913330e-1 - }, new[] { - 0.000000e+0, 9.982910e-1, 7.592773e-2, 7.179565e-1, - 9.851379e-1, 5.340271e-1, 9.013672e-1, 6.349182e-1, - 7.226257e-1, 1.948547e-1, 7.628174e-1, 9.873657e-1, - 8.112183e-1, 2.715454e-1, 9.734192e-1, 1.443787e-1, - 4.640198e-1, 3.249207e-1, 3.790894e-1, 8.276367e-2, - 5.954590e-1, 2.864380e-1, 9.806824e-1, 7.929077e-1, - 6.292114e-1, 4.887085e-1, 2.905273e-1, 1.301880e-1, - 3.140869e-1, 5.482483e-1, 4.210815e-1, 1.182861e-1 - }, new[] { - 0.000000e+0, 3.155518e-2, 8.581543e-2, 1.364746e-1, - 1.858826e-1, 2.368469e-1, 2.888184e-1, 3.432617e-1, - 4.012451e-1, 4.623108e-1, 5.271301e-1, 5.954895e-1, - 6.681213e-1, 7.448425e-1, 8.245239e-1, 9.097290e-1 - }, new[] { - 0.000000e+0, 4.418945e-2, 1.303711e-1, 2.273560e-1, - 3.395996e-1, 4.735718e-1, 6.267090e-1, 8.003845e-1 - }, new[] { - 0.000000e+0, 2.804565e-2, 9.683228e-2, 1.849976e-1, - 3.005981e-1, 4.470520e-1, 6.168518e-1, 8.007813e-1 - } - }; - - public static readonly double[][] BexMode0Bands4 = - { - new[] { - 0.000000e+0, 2.708740e-1, 3.479614e-1, 3.578186e-1, - 5.083618e-1, 5.299072e-1, 5.819092e-1, 6.381836e-1, - 7.276917e-1, 7.595520e-1, 7.878723e-1, 9.707336e-1, - 9.713135e-1, 9.736023e-1, 9.759827e-1, 9.832458e-1 - }, new[] { - 0.000000e+0, 2.330627e-1, 5.891418e-1, 7.170410e-1, - 2.036438e-1, 1.613464e-1, 6.668701e-1, 9.481201e-1, - 9.769897e-1, 5.111694e-1, 3.522644e-1, 8.209534e-1, - 2.933960e-1, 9.757690e-1, 5.289917e-1, 4.372253e-1 - }, new[] { - 0.000000e+0, 4.360962e-2, 1.056519e-1, 1.590576e-1, - 2.078857e-1, 2.572937e-1, 3.082581e-1, 3.616028e-1, - 4.191589e-1, 4.792175e-1, 5.438538e-1, 6.125183e-1, - 6.841125e-1, 7.589417e-1, 8.365173e-1, 9.148254e-1 - }, new[] { - 0.000000e+0, 4.074097e-2, 1.164551e-1, 2.077026e-1, - 3.184509e-1, 4.532166e-1, 6.124268e-1, 7.932129e-1 - }, new[] { - 0.000000e+0, 8.880615e-3, 2.932739e-2, 5.593872e-2, - 8.825684e-2, 1.259155e-1, 1.721497e-1, 2.270813e-1, - 2.901611e-1, 3.579712e-1, 4.334106e-1, 5.147095e-1, - 6.023254e-1, 6.956177e-1, 7.952881e-1, 8.977356e-1 - } - }; - - public static readonly double[][] BexMode0Bands5 = - { - new[] { - 0.000000e+0, 7.379150e-2, 1.806335e-1, 2.687073e-1, - 3.407898e-1, 4.047546e-1, 4.621887e-1, 5.168762e-1, - 5.703125e-1, 6.237488e-1, 6.763611e-1, 7.288208e-1, - 7.808533e-1, 8.337708e-1, 8.874512e-1, 9.418030e-1 - }, new[] { - 0.000000e+0, 7.980347e-2, 1.615295e-1, 1.665649e-1, - 1.822205e-1, 2.185669e-1, 2.292175e-1, 2.456665e-1, - 2.666321e-1, 3.306580e-1, 3.330688e-1, 3.765259e-1, - 4.085083e-1, 4.400024e-1, 4.407654e-1, 4.817505e-1, - 4.924011e-1, 5.320740e-1, 5.893860e-1, 6.131287e-1, - 6.212463e-1, 6.278076e-1, 6.308899e-1, 7.660828e-1, - 7.850647e-1, 7.910461e-1, 7.929382e-1, 8.038330e-1, - 9.834900e-1, 9.846191e-1, 9.852295e-1, 9.862671e-1 - }, new[] { - 0.000000e+0, 6.084290e-1, 3.672791e-1, 3.151855e-1, - 1.488953e-1, 2.571716e-1, 5.103455e-1, 3.311157e-1, - 5.426025e-2, 4.254456e-1, 7.998352e-1, 7.873230e-1, - 5.418701e-1, 2.925110e-1, 8.468628e-2, 1.410522e-1, - 9.819641e-1, 9.609070e-1, 3.530884e-2, 9.729004e-2, - 5.758362e-1, 9.941711e-1, 7.215576e-1, 7.183228e-1, - 2.028809e-1, 9.588623e-2, 2.032166e-1, 1.338806e-1, - 5.003357e-1, 1.874390e-1, 9.804993e-1, 1.107788e-1 - } - }; - - public static readonly double[] BexMode2Scale = - { - 4.272461e-4, 1.312256e-3, 2.441406e-3, 3.692627e-3, - 4.913330e-3, 6.134033e-3, 7.507324e-3, 8.972168e-3, - 1.049805e-2, 1.223755e-2, 1.406860e-2, 1.599121e-2, - 1.800537e-2, 2.026367e-2, 2.264404e-2, 2.517700e-2, - 2.792358e-2, 3.073120e-2, 3.344727e-2, 3.631592e-2, - 3.952026e-2, 4.275513e-2, 4.608154e-2, 4.968262e-2, - 5.355835e-2, 5.783081e-2, 6.195068e-2, 6.677246e-2, - 7.196045e-2, 7.745361e-2, 8.319092e-2, 8.993530e-2, - 9.759521e-2, 1.056213e-1, 1.138916e-1, 1.236267e-1, - 1.348267e-1, 1.470337e-1, 1.603394e-1, 1.755676e-1, - 1.905823e-1, 2.071228e-1, 2.245178e-1, 2.444153e-1, - 2.658997e-1, 2.897644e-1, 3.146057e-1, 3.450012e-1, - 3.766174e-1, 4.122620e-1, 4.505615e-1, 4.893799e-1, - 5.305481e-1, 5.731201e-1, 6.157837e-1, 6.580811e-1, - 6.985168e-1, 7.435303e-1, 7.865906e-1, 8.302612e-1, - 8.718567e-1, 9.125671e-1, 9.575806e-1, 9.996643e-1 - }; - - public static readonly double[] BexMode3Initial = - { - 3.491211e-1, 5.371094e-1, 6.782227e-1, 7.910156e-1, - 9.057617e-1, 1.024902e+0, 1.156250e+0, 1.290527e+0, - 1.458984e+0, 1.664551e+0, 1.929688e+0, 2.278320e+0, - 2.831543e+0, 3.659180e+0, 5.257813e+0, 8.373047e+0 - }; - - public static readonly double[] BexMode3Rate = - { - -2.913818e-1, -2.541504e-1, -1.664429e-1, -1.476440e-1, - -1.342163e-1, -1.220703e-1, -1.117554e-1, -1.026611e-1, - -9.436035e-2, -8.483887e-2, -7.476807e-2, -6.304932e-2, - -4.492188e-2, -2.447510e-2, +1.831055e-4, +4.174805e-2 - }; - - public static readonly double[] BexMode4Multiplier = - { - 3.610229e-2, 1.260681e-1, 2.227478e-1, 3.338318e-1, - 4.662170e-1, 6.221313e-1, 7.989197e-1, 9.939575e-1 - }; - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/BitAllocation.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/BitAllocation.cs deleted file mode 100644 index 1775b32d5..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/BitAllocation.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; - -namespace LibAtrac9 -{ - internal static class BitAllocation - { - public static void CreateGradient(Block block) - { - int valueCount = block.GradientEndValue - block.GradientStartValue; - int unitCount = block.GradientEndUnit - block.GradientStartUnit; - - for (int i = 0; i < block.GradientEndUnit; i++) - { - block.Gradient[i] = block.GradientStartValue; - } - - for (int i = block.GradientEndUnit; i <= block.QuantizationUnitCount; i++) - { - block.Gradient[i] = block.GradientEndValue; - } - if (unitCount <= 0) return; - if (valueCount == 0) return; - - byte[] curve = Tables.GradientCurves[unitCount - 1]; - if (valueCount <= 0) - { - double scale = (-valueCount - 1) / 31.0; - int baseVal = block.GradientStartValue - 1; - for (int i = block.GradientStartUnit; i < block.GradientEndUnit; i++) - { - block.Gradient[i] = baseVal - (int)(curve[i - block.GradientStartUnit] * scale); - } - } - else - { - double scale = (valueCount - 1) / 31.0; - int baseVal = block.GradientStartValue + 1; - for (int i = block.GradientStartUnit; i < block.GradientEndUnit; i++) - { - block.Gradient[i] = baseVal + (int)(curve[i - block.GradientStartUnit] * scale); - } - } - } - - public static void CalculateMask(Channel channel) - { - Array.Clear(channel.PrecisionMask, 0, channel.PrecisionMask.Length); - for (int i = 1; i < channel.Block.QuantizationUnitCount; i++) - { - int delta = channel.ScaleFactors[i] - channel.ScaleFactors[i - 1]; - if (delta > 1) - { - channel.PrecisionMask[i] += Math.Min(delta - 1, 5); - } - else if (delta < -1) - { - channel.PrecisionMask[i - 1] += Math.Min(delta * -1 - 1, 5); - } - } - } - - public static void CalculatePrecisions(Channel channel) - { - Block block = channel.Block; - - if (block.GradientMode != 0) - { - for (int i = 0; i < block.QuantizationUnitCount; i++) - { - channel.Precisions[i] = channel.ScaleFactors[i] + channel.PrecisionMask[i] - block.Gradient[i]; - if (channel.Precisions[i] > 0) - { - switch (block.GradientMode) - { - case 1: - channel.Precisions[i] /= 2; - break; - case 2: - channel.Precisions[i] = 3 * channel.Precisions[i] / 8; - break; - case 3: - channel.Precisions[i] /= 4; - break; - } - } - } - } - else - { - for (int i = 0; i < block.QuantizationUnitCount; i++) - { - channel.Precisions[i] = channel.ScaleFactors[i] - block.Gradient[i]; - } - } - - for (int i = 0; i < block.QuantizationUnitCount; i++) - { - if (channel.Precisions[i] < 1) - { - channel.Precisions[i] = 1; - } - } - - for (int i = 0; i < block.GradientBoundary; i++) - { - channel.Precisions[i]++; - } - - for (int i = 0; i < block.QuantizationUnitCount; i++) - { - channel.PrecisionsFine[i] = 0; - if (channel.Precisions[i] > 15) - { - channel.PrecisionsFine[i] = channel.Precisions[i] - 15; - channel.Precisions[i] = 15; - } - } - } - - public static byte[][] GenerateGradientCurves() - { - byte[] main = - { - 01, 01, 01, 01, 02, 02, 02, 02, 03, 03, 03, 04, 04, 05, 05, 06, 07, 08, 09, 10, 11, 12, 13, 15, - 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 27, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30 - }; - var curves = new byte[main.Length][]; - - for (int length = 1; length <= main.Length; length++) - { - curves[length - 1] = new byte[length]; - for (int i = 0; i < length; i++) - { - curves[length - 1][i] = main[i * main.Length / length]; - } - } - return curves; - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Block.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Block.cs deleted file mode 100644 index fc5d0db24..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Block.cs +++ /dev/null @@ -1,91 +0,0 @@ -namespace LibAtrac9 -{ - internal class Block - { - public Atrac9Config Config { get; } - public BlockType BlockType { get; } - public int BlockIndex { get; } - public Frame Frame { get; } - - public Channel[] Channels { get; } - public int ChannelCount { get; } - - public bool FirstInSuperframe { get; set; } - public bool ReuseBandParams { get; set; } - - public int BandCount { get; set; } - public int StereoBand { get; set; } - public int ExtensionBand { get; set; } - public int QuantizationUnitCount { get; set; } - public int StereoQuantizationUnit { get; set; } - public int ExtensionUnit { get; set; } - public int QuantizationUnitsPrev { get; set; } - - public int[] Gradient { get; } = new int[31]; - public int GradientMode { get; set; } - public int GradientStartUnit { get; set; } - public int GradientStartValue { get; set; } - public int GradientEndUnit { get; set; } - public int GradientEndValue { get; set; } - public int GradientBoundary { get; set; } - - public int PrimaryChannelIndex { get; set; } - public int[] JointStereoSigns { get; } = new int[30]; - public bool HasJointStereoSigns { get; set; } - public Channel PrimaryChannel => Channels[PrimaryChannelIndex == 0 ? 0 : 1]; - public Channel SecondaryChannel => Channels[PrimaryChannelIndex == 0 ? 1 : 0]; - - public bool BandExtensionEnabled { get; set; } - public bool HasExtensionData { get; set; } - public int BexDataLength { get; set; } - public int BexMode { get; set; } - - public Block(Frame parentFrame, int blockIndex) - { - Frame = parentFrame; - BlockIndex = blockIndex; - Config = parentFrame.Config; - BlockType = Config.ChannelConfig.BlockTypes[blockIndex]; - ChannelCount = BlockTypeToChannelCount(BlockType); - Channels = new Channel[ChannelCount]; - for (int i = 0; i < ChannelCount; i++) - { - Channels[i] = new Channel(this, i); - } - } - - public static int BlockTypeToChannelCount(BlockType blockType) - { - switch (blockType) - { - case BlockType.Mono: - return 1; - case BlockType.Stereo: - return 2; - case BlockType.LFE: - return 1; - default: - return 0; - } - } - } - - /// - /// An ATRAC9 block (substream) type - /// - public enum BlockType - { - /// - /// Mono ATRAC9 block - /// - Mono = 0, - /// - /// Stereo ATRAC9 block - /// - Stereo = 1, - /// - /// Low-frequency effects ATRAC9 block - /// - LFE = 2 - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Channel.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Channel.cs deleted file mode 100644 index 4b77f6a98..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Channel.cs +++ /dev/null @@ -1,48 +0,0 @@ -using LibAtrac9.Utilities; - -namespace LibAtrac9 -{ - internal class Channel - { - public Atrac9Config Config { get; } - public int ChannelIndex { get; } - public bool IsPrimary => Block.PrimaryChannelIndex == ChannelIndex; - public Block Block { get; } - public Mdct Mdct { get; } - - public double[] Pcm { get; } = new double[256]; - public double[] Spectra { get; } = new double[256]; - - public int CodedQuantUnits { get; set; } - public int ScaleFactorCodingMode { get; set; } - public int[] ScaleFactors { get; } = new int[31]; - public int[] ScaleFactorsPrev { get; } = new int[31]; - - public int[] Precisions { get; } = new int[30]; - public int[] PrecisionsFine { get; } = new int[30]; - public int[] PrecisionMask { get; } = new int[30]; - - public int[] SpectraValuesBuffer { get; } = new int[16]; - public int[] CodebookSet { get; } = new int[30]; - - public int[] QuantizedSpectra { get; } = new int[256]; - public int[] QuantizedSpectraFine { get; } = new int[256]; - - public int BexMode { get; set; } - public int BexValueCount { get; set; } - public int[] BexValues { get; } = new int[4]; - public double[] BexScales { get; } = new double[6]; - public Atrac9Rng Rng { get; set; } - - public Channel(Block parentBlock, int channelIndex) - { - Block = parentBlock; - ChannelIndex = channelIndex; - Config = parentBlock.Config; - Mdct = new Mdct(Config.FrameSamplesPower, Tables.ImdctWindow[Config.FrameSamplesPower - 6]); - } - - public void UpdateCodedUnits() => - CodedQuantUnits = IsPrimary ? Block.QuantizationUnitCount : Block.StereoQuantizationUnit; - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/ChannelConfig.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/ChannelConfig.cs deleted file mode 100644 index 6854c7fee..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/ChannelConfig.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace LibAtrac9 -{ - /// - /// Describes the channel mapping for an ATRAC9 stream - /// - public class ChannelConfig - { - internal ChannelConfig(params BlockType[] blockTypes) - { - BlockCount = blockTypes.Length; - BlockTypes = blockTypes; - foreach (BlockType type in blockTypes) - { - ChannelCount += Block.BlockTypeToChannelCount(type); - } - } - - /// - /// The number of blocks or substreams in the ATRAC9 stream - /// - public int BlockCount { get; } - - /// - /// The type of each block or substream in the ATRAC9 stream - /// - public BlockType[] BlockTypes { get; } - - /// - /// The number of channels in the ATRAC9 stream - /// - public int ChannelCount { get; } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Frame.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Frame.cs deleted file mode 100644 index 46feb1bbb..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Frame.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace LibAtrac9 -{ - internal class Frame - { - public Atrac9Config Config { get; } - public int FrameIndex { get; set; } - public Block[] Blocks { get; } - - public Frame(Atrac9Config config) - { - Config = config; - Blocks = new Block[config.ChannelConfig.BlockCount]; - - for (int i = 0; i < config.ChannelConfig.BlockCount; i++) - { - Blocks[i] = new Block(this, i); - } - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/HuffmanCodebook.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/HuffmanCodebook.cs deleted file mode 100644 index 8a900b54c..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/HuffmanCodebook.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using LibAtrac9.Utilities; - -namespace LibAtrac9 -{ - internal class HuffmanCodebook - { - public HuffmanCodebook(short[] codes, byte[] bits, byte valueCountPower) - { - Codes = codes; - Bits = bits; - if (Codes == null || Bits == null) return; - - ValueCount = 1 << valueCountPower; - ValueCountPower = valueCountPower; - ValueBits = Helpers.Log2(codes.Length) >> valueCountPower; - ValueMax = 1 << ValueBits; - - int max = 0; - foreach (byte bitSize in bits) - { - max = Math.Max(max, bitSize); - } - - MaxBitSize = max; - Lookup = CreateLookupTable(); - } - - private byte[] CreateLookupTable() - { - if (Codes == null || Bits == null) return null; - - int tableSize = 1 << MaxBitSize; - var dest = new byte[tableSize]; - - for (int i = 0; i < Bits.Length; i++) - { - if (Bits[i] == 0) continue; - int unusedBits = MaxBitSize - Bits[i]; - - int start = Codes[i] << unusedBits; - int length = 1 << unusedBits; - int end = start + length; - - for (int j = start; j < end; j++) - { - dest[j] = (byte)i; - } - } - return dest; - } - - public short[] Codes { get; } - public byte[] Bits { get; } - public byte[] Lookup { get; } - public int ValueCount { get; } - public int ValueCountPower { get; } - public int ValueBits { get; } - public int ValueMax { get; } - public int MaxBitSize { get; } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/HuffmanCodebooks.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/HuffmanCodebooks.cs deleted file mode 100644 index 8c350d098..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/HuffmanCodebooks.cs +++ /dev/null @@ -1,1352 +0,0 @@ -namespace LibAtrac9 -{ - internal static class HuffmanCodebooks - { - public static HuffmanCodebook[][] GenerateHuffmanCodebooks(short[][][] codes, byte[][][] bits, byte[][] groupCounts) - { - var tables = new HuffmanCodebook[bits.Length][]; - for (int i = 0; i < tables.Length; i++) - { - if (codes[i] != null) - { - tables[i] = GenerateHuffmanCodebooks(codes[i], bits[i], groupCounts[i]); - } - } - return tables; - } - - public static HuffmanCodebook[] GenerateHuffmanCodebooks(short[][] codes, byte[][] bits, byte[] groupCounts) - { - var tables = new HuffmanCodebook[bits.Length]; - for (int i = 0; i < tables.Length; i++) - { - if (codes[i] != null) - { - tables[i] = new HuffmanCodebook(codes[i], bits[i], groupCounts[i]); - } - } - return tables; - } - - // For scale factor table names, {letter}{number} correspond to the signedness and word length - private static readonly byte[] ScaleFactorsA1Bits = - { - 1, 1 - }; - - private static readonly short[] ScaleFactorsA1Codes = - { - 0x00, 0x01 - }; - - private static readonly byte[] ScaleFactorsA2Bits = - { - 1, 3, 3, 2 - }; - - private static readonly short[] ScaleFactorsA2Codes = - { - 0x00, 0x06, 0x07, 0x02 - }; - - private static readonly byte[] ScaleFactorsA3Bits = - { - 2, 2, 4, 6, 6, 5, 3, 2 - }; - - private static readonly short[] ScaleFactorsA3Codes = - { - 0x00, 0x01, 0x0E, 0x3E, 0x3F, 0x1E, 0x06, 0x02 - }; - - private static readonly byte[] ScaleFactorsA4Bits = - { - 2, 2, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 6, 5, 4, 2 - }; - - private static readonly short[] ScaleFactorsA4Codes = - { - 0x01, 0x02, 0x00, 0x06, 0x0F, 0x13, 0x23, 0x24, 0x25, 0x22, 0x21, 0x20, 0x0E, 0x05, 0x01, 0x03 - }; - - private static readonly byte[] ScaleFactorsA5Bits = - { - 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 6, 5, 5, 4, 3 - }; - - private static readonly short[] ScaleFactorsA5Codes = - { - 0x02, 0x01, 0x07, 0x0D, 0x0C, 0x18, 0x1B, 0x21, 0x3F, 0x6A, 0x6B, 0x68, 0x73, 0x79, 0x7C, 0x7D, - 0x7A, 0x7B, 0x78, 0x72, 0x44, 0x45, 0x47, 0x46, 0x69, 0x38, 0x20, 0x1D, 0x19, 0x09, 0x05, 0x00 - }; - - private static readonly byte[] ScaleFactorsA6Bits = - { - 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 4, 4, 4 - }; - - private static readonly short[] ScaleFactorsA6Codes = - { - 0x00, 0x01, 0x04, 0x05, 0x12, 0x13, 0x2E, 0x2F, 0x30, 0x66, 0x67, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, - 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, - 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, - 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x68, 0x69, 0x6A, 0x31, 0x32, 0x14, 0x15, 0x16, 0x06, 0x07, 0x08 - }; - - private static readonly byte[] ScaleFactorsB2Bits = - { - 1, 2, 0, 2 - }; - - private static readonly short[] ScaleFactorsB2Codes = - { - 0x00, 0x03, 0x00, 0x02 - }; - - private static readonly byte[] ScaleFactorsB3Bits = - { - 1, 3, 5, 6, 0, 6, 4, 2 - }; - - private static readonly short[] ScaleFactorsB3Codes = - { - 0x01, 0x00, 0x04, 0x0B, 0x00, 0x0A, 0x03, 0x01 - }; - - private static readonly byte[] ScaleFactorsB4Bits = - { - 1, 3, 4, 5, 5, 7, 8, 8, 0, 8, 8, 7, 6, 6, 4, 3 - }; - - private static readonly short[] ScaleFactorsB4Codes = - { - 0x01, 0x01, 0x04, 0x0E, 0x0F, 0x2C, 0x5A, 0x5D, 0x00, 0x5C, 0x5B, 0x2F, 0x15, 0x14, 0x06, 0x00 - }; - - private static readonly byte[] ScaleFactorsB5Bits = - { - 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 7, 7, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 3 - }; - - private static readonly short[] ScaleFactorsB5Codes = - { - 0x00, 0x05, 0x07, 0x0C, 0x04, 0x02, 0x03, 0x05, 0x09, 0x10, 0x23, 0x33, 0x36, 0x6E, 0x60, 0x65, - 0x62, 0x61, 0x63, 0x64, 0x6F, 0x6D, 0x6C, 0x6B, 0x6A, 0x68, 0x69, 0x45, 0x44, 0x37, 0x1A, 0x07 - }; - - // For spectrum table names, {letter}{number}{number} correspond to the - // codebook set, word length, and band group - private static readonly byte[] SpectrumA21Bits = - { - 0, 3, 0, 3, 3, 3, 0, 3, 0, 0, 0, 0, 3, 3, 0, 3 - }; - - private static readonly short[] SpectrumA21Codes = - { - 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x06 - }; - - private static readonly byte[] SpectrumA22Bits = - { - 0, 4, 0, 4, 5, 6, 0, 6, 0, 0, 0, 0, 5, 6, 0, 6, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 6, 7, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 6, 7, 0, 7, - 5, 6, 0, 6, 7, 7, 0, 7, 0, 0, 0, 0, 6, 7, 0, 7, - 6, 7, 0, 7, 7, 8, 0, 8, 0, 0, 0, 0, 7, 8, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 7, 0, 7, 7, 8, 0, 8, 0, 0, 0, 0, 7, 7, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 7, 7, 0, 7, - 6, 7, 0, 7, 7, 8, 0, 7, 0, 0, 0, 0, 7, 8, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 7, 0, 7, 7, 7, 0, 8, 0, 0, 0, 0, 7, 8, 0, 8 - }; - - private static readonly short[] SpectrumA22Codes = - { - 0x00, 0x02, 0x00, 0x03, 0x10, 0x3C, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x11, 0x3E, 0x00, 0x3D, - 0x0E, 0x00, 0x00, 0x39, 0x18, 0x26, 0x00, 0x75, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x24, 0x00, 0x6D, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x38, 0x00, 0x01, 0x1A, 0x6C, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x19, 0x74, 0x00, 0x27, - 0x16, 0x14, 0x00, 0x17, 0x76, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x35, 0x64, 0x00, 0x6F, - 0x26, 0x04, 0x00, 0x63, 0x22, 0xA2, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x67, 0xA0, 0x00, 0x0D, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2B, 0x52, 0x00, 0x0B, 0x20, 0x92, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x00, 0x95, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x17, 0x16, 0x00, 0x15, 0x34, 0x6E, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x77, 0x08, 0x00, 0x07, - 0x2A, 0x0A, 0x00, 0x53, 0x60, 0x94, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x21, 0x90, 0x00, 0x93, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x27, 0x62, 0x00, 0x05, 0x66, 0x0C, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x23, 0x96, 0x00, 0xA3 - }; - - private static readonly byte[] SpectrumA23Bits = - { - 3, 4, 0, 4, 5, 6, 0, 6, 0, 0, 0, 0, 5, 6, 0, 6, - 5, 7, 0, 6, 6, 8, 0, 7, 0, 0, 0, 0, 6, 8, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 7, 6, 7, 0, 8, 0, 0, 0, 0, 6, 7, 0, 8, - 5, 6, 0, 6, 7, 8, 0, 8, 0, 0, 0, 0, 6, 7, 0, 7, - 6, 8, 0, 7, 8, 9, 0, 9, 0, 0, 0, 0, 7, 9, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 8, 0, 8, 8, 9, 0, 9, 0, 0, 0, 0, 7, 8, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 7, 8, 0, 8, - 6, 8, 0, 8, 7, 9, 0, 8, 0, 0, 0, 0, 8, 9, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 7, 0, 8, 7, 8, 0, 9, 0, 0, 0, 0, 8, 9, 0, 9 - }; - - private static readonly short[] SpectrumA23Codes = - { - 0x006, 0x002, 0x000, 0x003, 0x016, 0x01E, 0x000, 0x021, 0x000, 0x000, 0x000, 0x000, - 0x017, 0x020, 0x000, 0x01F, 0x01C, 0x054, 0x000, 0x027, 0x010, 0x0A6, 0x000, 0x027, - 0x000, 0x000, 0x000, 0x000, 0x015, 0x0A4, 0x000, 0x02D, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01D, 0x026, 0x000, 0x055, 0x014, 0x02C, 0x000, 0x0A5, 0x000, 0x000, 0x000, 0x000, - 0x011, 0x026, 0x000, 0x0A7, 0x01E, 0x000, 0x000, 0x003, 0x04A, 0x074, 0x000, 0x071, - 0x000, 0x000, 0x000, 0x000, 0x023, 0x00A, 0x000, 0x009, 0x018, 0x072, 0x000, 0x00D, - 0x0A2, 0x15A, 0x000, 0x123, 0x000, 0x000, 0x000, 0x000, 0x00F, 0x158, 0x000, 0x05D, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x01B, 0x0AE, 0x000, 0x077, 0x092, 0x140, 0x000, 0x121, - 0x000, 0x000, 0x000, 0x000, 0x025, 0x05E, 0x000, 0x143, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01F, 0x002, 0x000, 0x001, 0x022, 0x008, 0x000, 0x00B, 0x000, 0x000, 0x000, 0x000, - 0x04B, 0x070, 0x000, 0x075, 0x01A, 0x076, 0x000, 0x0AF, 0x024, 0x142, 0x000, 0x05F, - 0x000, 0x000, 0x000, 0x000, 0x093, 0x120, 0x000, 0x141, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x019, 0x00C, 0x000, 0x073, 0x00E, 0x05C, 0x000, 0x159, 0x000, 0x000, 0x000, 0x000, - 0x0A3, 0x122, 0x000, 0x15B - }; - - private static readonly byte[] SpectrumA24Bits = - { - 02, 04, 00, 04, 05, 06, 00, 06, 00, 00, 00, 00, 05, 06, 00, 06, - 05, 07, 00, 06, 06, 08, 00, 08, 00, 00, 00, 00, 06, 08, 00, 08, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 05, 06, 00, 07, 06, 08, 00, 08, 00, 00, 00, 00, 06, 08, 00, 08, - 05, 07, 00, 07, 07, 09, 00, 09, 00, 00, 00, 00, 06, 08, 00, 08, - 06, 09, 00, 08, 08, 10, 00, 10, 00, 00, 00, 00, 08, 10, 00, 09, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 06, 08, 00, 09, 09, 10, 00, 10, 00, 00, 00, 00, 08, 09, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 05, 07, 00, 07, 06, 08, 00, 08, 00, 00, 00, 00, 07, 09, 00, 09, - 06, 09, 00, 08, 08, 10, 00, 09, 00, 00, 00, 00, 09, 10, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 06, 08, 00, 09, 08, 09, 00, 10, 00, 00, 00, 00, 08, 10, 00, 10 - }; - - private static readonly short[] SpectrumA24Codes = - { - 0x002, 0x002, 0x000, 0x003, 0x01E, 0x010, 0x000, 0x013, 0x000, 0x000, 0x000, 0x000, - 0x01F, 0x012, 0x000, 0x011, 0x01A, 0x030, 0x000, 0x01B, 0x000, 0x064, 0x000, 0x0C1, - 0x000, 0x000, 0x000, 0x000, 0x003, 0x052, 0x000, 0x07D, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01B, 0x01A, 0x000, 0x031, 0x002, 0x07C, 0x000, 0x053, 0x000, 0x000, 0x000, 0x000, - 0x001, 0x0C0, 0x000, 0x065, 0x01C, 0x062, 0x000, 0x065, 0x02A, 0x198, 0x000, 0x19B, - 0x000, 0x000, 0x000, 0x000, 0x017, 0x078, 0x000, 0x07B, 0x004, 0x0FE, 0x000, 0x077, - 0x050, 0x33A, 0x000, 0x1F9, 0x000, 0x000, 0x000, 0x000, 0x073, 0x338, 0x000, 0x0E1, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x007, 0x066, 0x000, 0x187, 0x19E, 0x308, 0x000, 0x30B, - 0x000, 0x000, 0x000, 0x000, 0x075, 0x0E2, 0x000, 0x1FB, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01D, 0x064, 0x000, 0x063, 0x016, 0x07A, 0x000, 0x079, 0x000, 0x000, 0x000, 0x000, - 0x02B, 0x19A, 0x000, 0x199, 0x006, 0x186, 0x000, 0x067, 0x074, 0x1FA, 0x000, 0x0E3, - 0x000, 0x000, 0x000, 0x000, 0x19F, 0x30A, 0x000, 0x309, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x005, 0x076, 0x000, 0x0FF, 0x072, 0x0E0, 0x000, 0x339, 0x000, 0x000, 0x000, 0x000, - 0x051, 0x1F8, 0x000, 0x33B - }; - - private static readonly byte[] SpectrumA31Bits = - { - 0, 0, 4, 5, 0, 5, 4, 0, 0, 0, 5, 5, 0, 5, 5, 0, - 5, 5, 6, 6, 0, 6, 5, 5, 5, 6, 6, 7, 0, 7, 6, 6, - 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 6, 7, 0, 7, 6, 6, - 5, 5, 5, 6, 0, 6, 6, 5, 0, 0, 5, 5, 0, 5, 5, 0 - }; - - private static readonly short[] SpectrumA31Codes = - { - 0x00, 0x00, 0x02, 0x18, 0x00, 0x19, 0x03, 0x00, 0x00, 0x00, 0x12, 0x02, 0x00, 0x09, 0x15, 0x00, - 0x1A, 0x0A, 0x3E, 0x2C, 0x00, 0x2F, 0x01, 0x0D, 0x0E, 0x38, 0x20, 0x78, 0x00, 0x7B, 0x23, 0x3B, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x3A, 0x22, 0x7A, 0x00, 0x79, 0x21, 0x39, - 0x1B, 0x0C, 0x00, 0x2E, 0x00, 0x2D, 0x3F, 0x0B, 0x00, 0x00, 0x14, 0x08, 0x00, 0x03, 0x13, 0x00 - }; - - private static readonly byte[] SpectrumA32Bits = - { - 4, 5, 5, 6, 0, 6, 5, 5, 5, 6, 5, 6, 0, 6, 5, 5, - 5, 5, 6, 7, 0, 7, 6, 5, 6, 6, 7, 7, 0, 7, 7, 6, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 7, 0, 7, 7, 6, - 5, 5, 6, 7, 0, 7, 6, 5, 5, 5, 5, 6, 0, 6, 5, 6 - }; - - private static readonly short[] SpectrumA32Codes = - { - 0x0D, 0x18, 0x16, 0x3A, 0x00, 0x3B, 0x17, 0x19, 0x12, 0x3E, 0x08, 0x1C, 0x00, 0x1B, 0x07, 0x01, - 0x10, 0x02, 0x28, 0x78, 0x00, 0x7B, 0x1F, 0x05, 0x2A, 0x16, 0x72, 0x2A, 0x00, 0x29, 0x71, 0x19, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x18, 0x70, 0x28, 0x00, 0x2B, 0x73, 0x17, - 0x11, 0x04, 0x1E, 0x7A, 0x00, 0x79, 0x29, 0x03, 0x13, 0x00, 0x06, 0x1A, 0x00, 0x1D, 0x09, 0x3F - }; - - private static readonly byte[] SpectrumA33Bits = - { - 3, 4, 5, 6, 0, 6, 5, 4, 4, 5, 6, 7, 0, 7, 6, 5, - 5, 6, 6, 7, 0, 7, 6, 6, 6, 7, 8, 8, 0, 8, 8, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 8, 0, 8, 8, 7, - 5, 6, 6, 7, 0, 7, 6, 6, 4, 5, 6, 7, 0, 7, 6, 5 - }; - - private static readonly short[] SpectrumA33Codes = - { - 0x05, 0x06, 0x10, 0x08, 0x00, 0x09, 0x11, 0x07, 0x04, 0x12, 0x3E, 0x6A, 0x00, 0x6D, 0x3D, 0x19, - 0x06, 0x3A, 0x06, 0x02, 0x00, 0x01, 0x05, 0x39, 0x02, 0x16, 0xDC, 0x2A, 0x00, 0x29, 0xDF, 0x69, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x68, 0xDE, 0x28, 0x00, 0x2B, 0xDD, 0x17, - 0x07, 0x38, 0x04, 0x00, 0x00, 0x03, 0x07, 0x3B, 0x05, 0x18, 0x3C, 0x6C, 0x00, 0x6B, 0x3F, 0x13 - }; - - private static readonly byte[] SpectrumA34Bits = - { - 02, 04, 05, 07, 00, 07, 05, 04, 04, 05, 06, 08, 00, 08, 06, 05, - 05, 06, 07, 08, 00, 08, 07, 06, 07, 08, 08, 10, 00, 10, 09, 08, - 00, 00, 00, 00, 00, 00, 00, 00, 07, 08, 09, 10, 00, 10, 08, 08, - 05, 06, 07, 08, 00, 08, 07, 06, 04, 05, 06, 08, 00, 08, 06, 05 - }; - - private static readonly short[] SpectrumA34Codes = - { - 0x000, 0x00A, 0x00A, 0x034, 0x000, 0x035, 0x00B, 0x00B, 0x008, 0x01C, 0x032, 0x0DA, - 0x000, 0x0DD, 0x035, 0x01F, 0x008, 0x01E, 0x03A, 0x06C, 0x000, 0x063, 0x039, 0x031, - 0x032, 0x06E, 0x060, 0x37A, 0x000, 0x379, 0x1BF, 0x0D9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x033, 0x0D8, 0x1BE, 0x378, 0x000, 0x37B, 0x061, 0x06F, - 0x009, 0x030, 0x038, 0x062, 0x000, 0x06D, 0x03B, 0x01F, 0x009, 0x01E, 0x034, 0x0DC, - 0x000, 0x0DB, 0x033, 0x01D - }; - - private static readonly byte[] SpectrumA41Bits = - { - 0, 0, 0, 0, 6, 6, 7, 7, 0, 7, 7, 6, 6, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 7, 7, 0, 7, 7, 7, 6, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 7, 8, 0, 8, 7, 7, 7, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 8, 8, 0, 8, 8, 7, 7, 0, 0, 0, - 7, 7, 7, 8, 7, 8, 8, 8, 0, 8, 8, 8, 7, 8, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 9, 0, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 8, 8, 8, 8, 9, 9, 0, 9, 8, 8, 8, 8, 8, 7, - 8, 8, 8, 8, 8, 9, 9, 9, 0, 9, 9, 9, 8, 8, 8, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 8, 8, 8, 8, 9, 9, 9, 0, 9, 9, 9, 8, 8, 8, 8, - 7, 7, 8, 8, 8, 8, 8, 9, 0, 9, 9, 8, 8, 8, 8, 7, - 7, 7, 7, 7, 8, 8, 8, 8, 0, 9, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 8, 7, 8, 8, 8, 0, 8, 8, 8, 7, 8, 7, 7, - 0, 0, 0, 0, 7, 7, 8, 8, 0, 8, 8, 7, 7, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 7, 8, 0, 8, 7, 7, 7, 0, 0, 0, - 0, 0, 0, 0, 6, 7, 7, 7, 0, 7, 7, 7, 7, 0, 0, 0 - }; - - private static readonly short[] SpectrumA41Codes = - { - 0x000, 0x000, 0x000, 0x000, 0x018, 0x00E, 0x05E, 0x028, 0x000, 0x029, 0x05F, 0x00F, - 0x019, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x076, 0x06E, 0x03E, 0x004, - 0x000, 0x017, 0x045, 0x07B, 0x013, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x04A, 0x048, 0x010, 0x0CE, 0x000, 0x0E1, 0x023, 0x055, 0x053, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x008, 0x018, 0x0D6, 0x09E, 0x000, 0x09D, 0x0E5, 0x02B, - 0x01B, 0x000, 0x000, 0x000, 0x07C, 0x05C, 0x038, 0x0FC, 0x002, 0x0D2, 0x09A, 0x05C, - 0x000, 0x06B, 0x0A3, 0x0D9, 0x00F, 0x0FF, 0x03D, 0x061, 0x074, 0x056, 0x036, 0x000, - 0x0CC, 0x08C, 0x058, 0x1E2, 0x000, 0x00F, 0x05F, 0x0A1, 0x0D5, 0x00D, 0x03B, 0x059, - 0x040, 0x014, 0x0DA, 0x0B6, 0x084, 0x040, 0x1E0, 0x196, 0x000, 0x1A1, 0x00D, 0x043, - 0x087, 0x0C7, 0x0E3, 0x00B, 0x0F2, 0x0C4, 0x08E, 0x05A, 0x024, 0x1CC, 0x194, 0x168, - 0x000, 0x16B, 0x1A3, 0x1CF, 0x027, 0x069, 0x099, 0x0C9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x0F3, 0x0C8, 0x098, 0x068, 0x026, 0x1CE, 0x1A2, 0x16A, 0x000, 0x169, 0x195, 0x1CD, - 0x025, 0x05B, 0x08F, 0x0C5, 0x041, 0x00A, 0x0E2, 0x0C6, 0x086, 0x042, 0x00C, 0x1A0, - 0x000, 0x197, 0x1E1, 0x041, 0x085, 0x0B7, 0x0DB, 0x015, 0x075, 0x058, 0x03A, 0x00C, - 0x0D4, 0x0A0, 0x05E, 0x00E, 0x000, 0x1E3, 0x059, 0x08D, 0x0CD, 0x001, 0x037, 0x057, - 0x07D, 0x060, 0x03C, 0x0FE, 0x00E, 0x0D8, 0x0A2, 0x06A, 0x000, 0x05D, 0x09B, 0x0D3, - 0x003, 0x0FD, 0x039, 0x05D, 0x000, 0x000, 0x000, 0x000, 0x01A, 0x02A, 0x0E4, 0x09C, - 0x000, 0x09F, 0x0D7, 0x019, 0x009, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x052, 0x054, 0x022, 0x0E0, 0x000, 0x0CF, 0x011, 0x049, 0x04B, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x012, 0x07A, 0x044, 0x016, 0x000, 0x005, 0x03F, 0x06F, - 0x077, 0x000, 0x000, 0x000 - }; - - private static readonly byte[] SpectrumA42Bits = - { - 05, 06, 07, 07, 07, 07, 08, 08, 00, 08, 08, 07, 07, 07, 07, 06, - 06, 07, 07, 08, 07, 07, 08, 08, 00, 08, 08, 07, 07, 08, 07, 07, - 07, 07, 08, 08, 07, 08, 08, 09, 00, 09, 08, 08, 07, 08, 08, 07, - 08, 08, 08, 08, 08, 08, 08, 09, 00, 09, 08, 08, 08, 08, 08, 08, - 07, 07, 07, 08, 08, 08, 09, 09, 00, 09, 09, 08, 08, 08, 07, 07, - 07, 07, 08, 08, 08, 09, 09, 09, 00, 09, 09, 09, 08, 08, 08, 07, - 08, 08, 08, 08, 09, 09, 09, 10, 00, 10, 09, 09, 09, 08, 08, 08, - 08, 08, 09, 09, 09, 09, 10, 10, 00, 10, 10, 09, 09, 09, 09, 09, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 08, 09, 09, 09, 09, 09, 10, 10, 00, 10, 10, 09, 09, 09, 09, 08, - 08, 08, 08, 08, 09, 09, 09, 10, 00, 10, 09, 09, 09, 08, 08, 08, - 07, 07, 08, 08, 08, 09, 09, 09, 00, 09, 09, 09, 08, 08, 08, 07, - 07, 07, 07, 08, 08, 08, 09, 09, 00, 09, 09, 08, 08, 08, 07, 07, - 08, 08, 08, 08, 08, 08, 08, 09, 00, 09, 08, 08, 08, 08, 08, 08, - 07, 07, 08, 08, 07, 08, 08, 09, 00, 09, 08, 08, 07, 08, 08, 07, - 06, 07, 07, 08, 07, 07, 08, 08, 00, 08, 08, 07, 07, 08, 07, 07 - }; - - private static readonly short[] SpectrumA42Codes = - { - 0x003, 0x018, 0x058, 0x000, 0x066, 0x03C, 0x0D6, 0x07C, 0x000, 0x07D, 0x0D7, 0x03D, - 0x067, 0x001, 0x059, 0x019, 0x002, 0x064, 0x036, 0x0DA, 0x04C, 0x01C, 0x0BE, 0x02C, - 0x000, 0x037, 0x0C5, 0x029, 0x04B, 0x0E7, 0x03B, 0x069, 0x044, 0x02E, 0x0FA, 0x092, - 0x020, 0x0F8, 0x086, 0x1FC, 0x000, 0x1E7, 0x07F, 0x0F5, 0x023, 0x0AD, 0x0FD, 0x02D, - 0x0F6, 0x0DC, 0x09C, 0x03E, 0x0F0, 0x0B6, 0x026, 0x186, 0x000, 0x18D, 0x02F, 0x0B5, - 0x0E1, 0x03D, 0x0AF, 0x0D9, 0x054, 0x040, 0x014, 0x0EC, 0x0BC, 0x054, 0x1C6, 0x108, - 0x000, 0x10B, 0x1C5, 0x069, 0x0B9, 0x0DF, 0x019, 0x047, 0x026, 0x008, 0x0E4, 0x0A2, - 0x056, 0x1DC, 0x142, 0x06A, 0x000, 0x091, 0x123, 0x1DF, 0x04B, 0x0A7, 0x0EB, 0x00B, - 0x0C0, 0x09E, 0x06A, 0x022, 0x1AA, 0x140, 0x092, 0x3CA, 0x000, 0x3A7, 0x04B, 0x121, - 0x18F, 0x007, 0x071, 0x0A5, 0x020, 0x004, 0x1A8, 0x174, 0x0E4, 0x068, 0x3A4, 0x2EE, - 0x000, 0x2ED, 0x3C9, 0x049, 0x0E7, 0x185, 0x1D1, 0x1FF, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x021, 0x1FE, 0x1D0, 0x184, 0x0E6, 0x048, 0x3C8, 0x2EC, 0x000, 0x2EF, 0x3A5, 0x069, - 0x0E5, 0x175, 0x1A9, 0x005, 0x0C1, 0x0A4, 0x070, 0x006, 0x18E, 0x120, 0x04A, 0x3A6, - 0x000, 0x3CB, 0x093, 0x141, 0x1AB, 0x023, 0x06B, 0x09F, 0x027, 0x00A, 0x0EA, 0x0A6, - 0x04A, 0x1DE, 0x122, 0x090, 0x000, 0x06B, 0x143, 0x1DD, 0x057, 0x0A3, 0x0E5, 0x009, - 0x055, 0x046, 0x018, 0x0DE, 0x0B8, 0x068, 0x1C4, 0x10A, 0x000, 0x109, 0x1C7, 0x055, - 0x0BD, 0x0ED, 0x015, 0x041, 0x0F7, 0x0D8, 0x0AE, 0x03C, 0x0E0, 0x0B4, 0x02E, 0x18C, - 0x000, 0x187, 0x027, 0x0B7, 0x0F1, 0x03F, 0x09D, 0x0DD, 0x045, 0x02C, 0x0FC, 0x0AC, - 0x022, 0x0F4, 0x07E, 0x1E6, 0x000, 0x1FD, 0x087, 0x0F9, 0x021, 0x093, 0x0FB, 0x02F, - 0x003, 0x068, 0x03A, 0x0E6, 0x04A, 0x028, 0x0C4, 0x036, 0x000, 0x02D, 0x0BF, 0x01D, - 0x04D, 0x0DB, 0x037, 0x065 - }; - - private static readonly byte[] SpectrumA43Bits = - { - 04, 06, 06, 07, 07, 08, 08, 09, 00, 09, 08, 08, 07, 07, 06, 06, - 05, 06, 07, 07, 07, 08, 08, 09, 00, 09, 08, 08, 07, 07, 07, 06, - 06, 07, 07, 07, 08, 08, 09, 09, 00, 09, 09, 08, 08, 07, 07, 07, - 07, 07, 07, 08, 08, 08, 09, 10, 00, 10, 09, 09, 08, 08, 07, 07, - 07, 07, 08, 08, 08, 09, 10, 10, 00, 10, 10, 09, 08, 08, 08, 07, - 08, 08, 08, 09, 09, 09, 10, 10, 00, 10, 10, 09, 09, 09, 08, 08, - 08, 09, 09, 09, 10, 10, 10, 10, 00, 10, 10, 10, 10, 09, 09, 09, - 09, 09, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 09, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 09, 09, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 09, - 08, 09, 09, 09, 10, 10, 10, 10, 00, 10, 10, 10, 10, 09, 09, 09, - 08, 08, 08, 09, 09, 09, 10, 10, 00, 10, 10, 09, 09, 09, 08, 08, - 07, 07, 08, 08, 08, 09, 10, 10, 00, 10, 10, 09, 08, 08, 08, 07, - 07, 07, 07, 08, 08, 09, 09, 10, 00, 10, 09, 08, 08, 08, 07, 07, - 06, 07, 07, 07, 08, 08, 09, 09, 00, 09, 09, 08, 08, 07, 07, 07, - 05, 06, 07, 07, 07, 08, 08, 09, 00, 09, 08, 08, 07, 07, 07, 06 - }; - - private static readonly short[] SpectrumA43Codes = - { - 0x002, 0x03E, 0x016, 0x060, 0x04E, 0x0DC, 0x04A, 0x130, 0x000, 0x131, 0x04B, 0x0DD, - 0x04F, 0x061, 0x017, 0x03F, 0x002, 0x02C, 0x076, 0x042, 0x034, 0x0CE, 0x002, 0x0E8, - 0x000, 0x0CF, 0x001, 0x0D1, 0x037, 0x045, 0x07B, 0x02F, 0x014, 0x072, 0x052, 0x01A, - 0x0E0, 0x080, 0x198, 0x01E, 0x000, 0x01D, 0x19B, 0x083, 0x0DF, 0x019, 0x055, 0x079, - 0x050, 0x03C, 0x004, 0x0C4, 0x096, 0x00C, 0x0EA, 0x34A, 0x000, 0x34F, 0x0ED, 0x1D7, - 0x095, 0x0AF, 0x003, 0x03F, 0x046, 0x026, 0x0D6, 0x092, 0x046, 0x15A, 0x3A8, 0x108, - 0x000, 0x10F, 0x3A3, 0x135, 0x039, 0x091, 0x0D9, 0x031, 0x0D4, 0x0CA, 0x072, 0x1C6, - 0x136, 0x090, 0x2B2, 0x104, 0x000, 0x103, 0x111, 0x08B, 0x133, 0x1D3, 0x071, 0x0C9, - 0x03E, 0x1B4, 0x18C, 0x0CC, 0x38A, 0x2B0, 0x106, 0x0F2, 0x000, 0x0EF, 0x101, 0x113, - 0x3A1, 0x0CB, 0x18F, 0x1B7, 0x0EE, 0x092, 0x388, 0x348, 0x10A, 0x0F4, 0x0F0, 0x0EA, - 0x000, 0x0E9, 0x0ED, 0x0F7, 0x10D, 0x34D, 0x3AB, 0x0C9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x0EF, 0x0C8, 0x3AA, 0x34C, 0x10C, 0x0F6, 0x0EC, 0x0E8, 0x000, 0x0EB, 0x0F1, 0x0F5, - 0x10B, 0x349, 0x389, 0x093, 0x03F, 0x1B6, 0x18E, 0x0CA, 0x3A0, 0x112, 0x100, 0x0EE, - 0x000, 0x0F3, 0x107, 0x2B1, 0x38B, 0x0CD, 0x18D, 0x1B5, 0x0D5, 0x0C8, 0x070, 0x1D2, - 0x132, 0x08A, 0x110, 0x102, 0x000, 0x105, 0x2B3, 0x091, 0x137, 0x1C7, 0x073, 0x0CB, - 0x047, 0x030, 0x0D8, 0x090, 0x038, 0x134, 0x3A2, 0x10E, 0x000, 0x109, 0x3A9, 0x15B, - 0x047, 0x093, 0x0D7, 0x027, 0x051, 0x03E, 0x002, 0x0AE, 0x094, 0x1D6, 0x0EC, 0x34E, - 0x000, 0x34B, 0x0EB, 0x00D, 0x097, 0x0C5, 0x005, 0x03D, 0x015, 0x078, 0x054, 0x018, - 0x0DE, 0x082, 0x19A, 0x01C, 0x000, 0x01F, 0x199, 0x081, 0x0E1, 0x01B, 0x053, 0x073, - 0x003, 0x02E, 0x07A, 0x044, 0x036, 0x0D0, 0x000, 0x0CE, 0x000, 0x0E9, 0x003, 0x0CF, - 0x035, 0x043, 0x077, 0x02D - }; - - private static readonly byte[] SpectrumA44Bits = - { - 04, 05, 06, 07, 07, 08, 09, 10, 00, 10, 09, 08, 07, 07, 06, 05, - 05, 06, 06, 07, 07, 08, 09, 10, 00, 10, 09, 08, 07, 07, 06, 06, - 06, 06, 07, 07, 08, 09, 10, 10, 00, 10, 10, 09, 08, 07, 07, 06, - 07, 07, 07, 08, 08, 09, 10, 10, 00, 10, 10, 09, 08, 08, 07, 07, - 07, 08, 08, 08, 09, 10, 10, 10, 00, 10, 10, 10, 09, 08, 08, 07, - 08, 08, 09, 09, 10, 10, 10, 10, 00, 10, 10, 10, 10, 09, 09, 08, - 09, 09, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 09, - 10, 10, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 10, 10, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 10, - 09, 09, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 09, - 08, 08, 09, 09, 10, 10, 10, 10, 00, 10, 10, 10, 10, 09, 09, 08, - 07, 07, 08, 08, 09, 10, 10, 10, 00, 10, 10, 10, 09, 08, 08, 08, - 07, 07, 07, 08, 08, 09, 10, 10, 00, 10, 10, 09, 08, 08, 07, 07, - 06, 06, 07, 07, 08, 09, 10, 10, 00, 10, 10, 09, 08, 07, 07, 06, - 05, 06, 06, 07, 07, 08, 09, 10, 00, 10, 09, 08, 07, 07, 06, 06 - }; - - private static readonly short[] SpectrumA44Codes = - { - 0x00A, 0x012, 0x030, 0x06E, 0x024, 0x074, 0x0EC, 0x07E, 0x000, 0x07F, 0x0ED, 0x075, - 0x025, 0x06F, 0x031, 0x013, 0x010, 0x03C, 0x018, 0x05A, 0x002, 0x046, 0x09E, 0x07C, - 0x000, 0x079, 0x0E5, 0x04D, 0x007, 0x065, 0x01B, 0x03F, 0x02E, 0x016, 0x072, 0x01A, - 0x0D6, 0x1C6, 0x3B4, 0x066, 0x000, 0x06B, 0x3B7, 0x1D9, 0x0D5, 0x021, 0x075, 0x015, - 0x06C, 0x03E, 0x01E, 0x0CC, 0x044, 0x0F2, 0x082, 0x05C, 0x000, 0x05F, 0x087, 0x0F5, - 0x031, 0x0CF, 0x017, 0x059, 0x01C, 0x0EE, 0x0D0, 0x024, 0x1C0, 0x08E, 0x06E, 0x048, - 0x000, 0x04D, 0x06D, 0x089, 0x0F7, 0x033, 0x0D3, 0x001, 0x070, 0x028, 0x1C2, 0x0F0, - 0x08A, 0x074, 0x054, 0x040, 0x000, 0x043, 0x053, 0x073, 0x099, 0x0EF, 0x1C5, 0x02B, - 0x0E6, 0x04E, 0x08C, 0x080, 0x068, 0x058, 0x046, 0x02A, 0x000, 0x029, 0x045, 0x051, - 0x065, 0x085, 0x09B, 0x09D, 0x07A, 0x076, 0x060, 0x056, 0x04E, 0x02C, 0x024, 0x022, - 0x000, 0x021, 0x027, 0x02F, 0x04B, 0x05B, 0x063, 0x071, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x07B, 0x070, 0x062, 0x05A, 0x04A, 0x02E, 0x026, 0x020, 0x000, 0x023, 0x025, 0x02D, - 0x04F, 0x057, 0x061, 0x077, 0x0E7, 0x09C, 0x09A, 0x084, 0x064, 0x050, 0x044, 0x028, - 0x000, 0x02B, 0x047, 0x059, 0x069, 0x081, 0x08D, 0x04F, 0x071, 0x02A, 0x1C4, 0x0EE, - 0x098, 0x072, 0x052, 0x042, 0x000, 0x041, 0x055, 0x075, 0x08B, 0x0F1, 0x1C3, 0x029, - 0x01D, 0x000, 0x0D2, 0x032, 0x0F6, 0x088, 0x06C, 0x04C, 0x000, 0x049, 0x06F, 0x08F, - 0x1C1, 0x025, 0x0D1, 0x0EF, 0x06D, 0x058, 0x016, 0x0CE, 0x030, 0x0F4, 0x086, 0x05E, - 0x000, 0x05D, 0x083, 0x0F3, 0x045, 0x0CD, 0x01F, 0x03F, 0x02F, 0x014, 0x074, 0x020, - 0x0D4, 0x1D8, 0x3B6, 0x06A, 0x000, 0x067, 0x3B5, 0x1C7, 0x0D7, 0x01B, 0x073, 0x017, - 0x011, 0x03E, 0x01A, 0x064, 0x006, 0x04C, 0x0E4, 0x078, 0x000, 0x07D, 0x09F, 0x047, - 0x003, 0x05B, 0x019, 0x03D - }; - - private static readonly byte[] SpectrumA51Bits = - { - 5, 5, 5, 5, 5, 6, 6, 6, 4, 4, 5, 5, 5, 5, 5, 5, - 0, 5, 5, 5, 5, 5, 5, 4, 4, 6, 6, 6, 5, 5, 5, 5 - }; - - private static readonly short[] SpectrumA51Codes = - { - 0x19, 0x16, 0x12, 0x0E, 0x06, 0x3A, 0x38, 0x30, 0x00, 0x04, 0x1E, 0x1A, 0x14, 0x10, 0x0C, 0x04, - 0x00, 0x05, 0x0D, 0x11, 0x15, 0x1B, 0x1F, 0x05, 0x01, 0x31, 0x39, 0x3B, 0x07, 0x0F, 0x13, 0x17 - }; - - private static readonly byte[] SpectrumA52Bits = - { - 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, - 0, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4 - }; - - private static readonly short[] SpectrumA52Codes = - { - 0x09, 0x04, 0x00, 0x1E, 0x1A, 0x14, 0x0C, 0x06, 0x18, 0x16, 0x0E, 0x04, 0x3A, 0x38, 0x22, 0x20, - 0x00, 0x21, 0x23, 0x39, 0x3B, 0x05, 0x0F, 0x17, 0x19, 0x07, 0x0D, 0x15, 0x1B, 0x1F, 0x01, 0x05 - }; - - private static readonly byte[] SpectrumA53Bits = - { - 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 7, - 0, 7, 7, 7, 7, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4 - }; - - private static readonly short[] SpectrumA53Codes = - { - 0x00, 0x0C, 0x08, 0x04, 0x1E, 0x16, 0x14, 0x06, 0x0C, 0x04, 0x38, 0x1E, 0x76, 0x74, 0x3A, 0x38, - 0x00, 0x39, 0x3B, 0x75, 0x77, 0x1F, 0x39, 0x05, 0x0D, 0x07, 0x15, 0x17, 0x1F, 0x05, 0x09, 0x0D - }; - - private static readonly byte[] SpectrumA54Bits = - { - 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, - 0, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4 - }; - - private static readonly short[] SpectrumA54Codes = - { - 0x02, 0x0E, 0x0A, 0x08, 0x02, 0x1A, 0x0E, 0x02, 0x00, 0x30, 0x18, 0x66, 0x36, 0x34, 0xCA, 0xC8, - 0x00, 0xC9, 0xCB, 0x35, 0x37, 0x67, 0x19, 0x31, 0x01, 0x03, 0x0F, 0x1B, 0x03, 0x09, 0x0B, 0x0F - }; - - private static readonly byte[] SpectrumA61Bits = - { - 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, - 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, - 5, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6 - }; - - private static readonly short[] SpectrumA61Codes = - { - 0x35, 0x30, 0x2A, 0x28, 0x24, 0x20, 0x18, 0x0E, 0x0C, 0x7E, 0x7C, 0x72, 0x70, 0x68, 0x5E, 0x5C, - 0x04, 0x0E, 0x08, 0x00, 0x3C, 0x3A, 0x36, 0x32, 0x2C, 0x26, 0x22, 0x1A, 0x16, 0x14, 0x06, 0x04, - 0x00, 0x05, 0x07, 0x15, 0x17, 0x1B, 0x23, 0x27, 0x2D, 0x33, 0x37, 0x3B, 0x3D, 0x01, 0x09, 0x0F, - 0x05, 0x5D, 0x5F, 0x69, 0x71, 0x73, 0x7D, 0x7F, 0x0D, 0x0F, 0x19, 0x21, 0x25, 0x29, 0x2B, 0x31 - }; - - private static readonly byte[] SpectrumA62Bits = - { - 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, - 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 - }; - - private static readonly short[] SpectrumA62Codes = - { - 0x14, 0x0E, 0x08, 0x04, 0x02, 0x3E, 0x3C, 0x38, 0x34, 0x30, 0x2A, 0x24, 0x1A, 0x18, 0x0E, 0x02, - 0x32, 0x36, 0x2C, 0x26, 0x20, 0x16, 0x0C, 0x00, 0x76, 0x74, 0x5E, 0x5C, 0x46, 0x44, 0x2A, 0x28, - 0x00, 0x29, 0x2B, 0x45, 0x47, 0x5D, 0x5F, 0x75, 0x77, 0x01, 0x0D, 0x17, 0x21, 0x27, 0x2D, 0x37, - 0x33, 0x03, 0x0F, 0x19, 0x1B, 0x25, 0x2B, 0x31, 0x35, 0x39, 0x3D, 0x3F, 0x03, 0x05, 0x09, 0x0F - }; - - private static readonly byte[] SpectrumA63Bits = - { - 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, - 0, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5 - }; - - private static readonly short[] SpectrumA63Codes = - { - 0x00, 0x1C, 0x18, 0x14, 0x10, 0x0A, 0x08, 0x02, 0x3E, 0x36, 0x2E, 0x2C, 0x24, 0x1C, 0x0E, 0x08, - 0x1E, 0x1A, 0x0C, 0x7A, 0x6A, 0x68, 0x4C, 0x32, 0x16, 0x14, 0xF2, 0xF0, 0x9E, 0x9C, 0x62, 0x60, - 0x00, 0x61, 0x63, 0x9D, 0x9F, 0xF1, 0xF3, 0x15, 0x17, 0x33, 0x4D, 0x69, 0x6B, 0x7B, 0x0D, 0x1B, - 0x1F, 0x09, 0x0F, 0x1D, 0x25, 0x2D, 0x2F, 0x37, 0x3F, 0x03, 0x09, 0x0B, 0x11, 0x15, 0x19, 0x1D - }; - - private static readonly byte[] SpectrumA64Bits = - { - 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, - 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, - 6, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4 - }; - - private static readonly short[] SpectrumA64Codes = - { - 0x006, 0x002, 0x01C, 0x01A, 0x016, 0x012, 0x00E, 0x00A, 0x002, 0x03E, 0x032, 0x02A, - 0x022, 0x020, 0x010, 0x07A, 0x000, 0x078, 0x060, 0x050, 0x024, 0x006, 0x0C6, 0x0C4, - 0x0A4, 0x04E, 0x00A, 0x008, 0x14E, 0x14C, 0x09A, 0x098, 0x000, 0x099, 0x09B, 0x14D, - 0x14F, 0x009, 0x00B, 0x04F, 0x0A5, 0x0C5, 0x0C7, 0x007, 0x025, 0x051, 0x061, 0x079, - 0x001, 0x07B, 0x011, 0x021, 0x023, 0x02B, 0x033, 0x03F, 0x003, 0x00B, 0x00F, 0x013, - 0x017, 0x01B, 0x01D, 0x003 - }; - - private static readonly byte[] SpectrumA71Bits = - { - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, - 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - }; - - private static readonly short[] SpectrumA71Codes = - { - 0x6C, 0x66, 0x62, 0x5C, 0x56, 0x50, 0x52, 0x4E, 0x48, 0x3E, 0x36, 0x34, 0x2A, 0x26, 0x1E, 0x16, - 0x0E, 0x08, 0x00, 0xF6, 0xF4, 0xEE, 0xEC, 0xE2, 0xE0, 0xDA, 0xD2, 0xD0, 0xBE, 0xBC, 0xB2, 0xB0, - 0x0C, 0x20, 0x1C, 0x16, 0x10, 0x08, 0x02, 0x7E, 0x7C, 0x78, 0x74, 0x72, 0x6E, 0x6A, 0x64, 0x60, - 0x5A, 0x54, 0x4C, 0x4A, 0x46, 0x44, 0x3C, 0x32, 0x30, 0x28, 0x24, 0x1C, 0x14, 0x0C, 0x0A, 0x02, - 0x00, 0x03, 0x0B, 0x0D, 0x15, 0x1D, 0x25, 0x29, 0x31, 0x33, 0x3D, 0x45, 0x47, 0x4B, 0x4D, 0x55, - 0x5B, 0x61, 0x65, 0x6B, 0x6F, 0x73, 0x75, 0x79, 0x7D, 0x7F, 0x03, 0x09, 0x11, 0x17, 0x1D, 0x21, - 0x0D, 0xB1, 0xB3, 0xBD, 0xBF, 0xD1, 0xD3, 0xDB, 0xE1, 0xE3, 0xED, 0xEF, 0xF5, 0xF7, 0x01, 0x09, - 0x0F, 0x17, 0x1F, 0x27, 0x2B, 0x35, 0x37, 0x3F, 0x49, 0x4F, 0x53, 0x51, 0x57, 0x5D, 0x63, 0x67 - }; - - private static readonly byte[] SpectrumA72Bits = - { - 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6 - }; - - private static readonly short[] SpectrumA72Codes = - { - 0x2A, 0x24, 0x1C, 0x18, 0x12, 0x0E, 0x0A, 0x06, 0x02, 0x7E, 0x7C, 0x7A, 0x76, 0x72, 0x70, 0x6A, - 0x68, 0x62, 0x5C, 0x5A, 0x52, 0x4E, 0x46, 0x42, 0x3C, 0x34, 0x2A, 0x28, 0x20, 0x12, 0x10, 0x08, - 0x66, 0x74, 0x6C, 0x64, 0x5E, 0x58, 0x50, 0x44, 0x40, 0x36, 0x2C, 0x22, 0x1A, 0x0A, 0x02, 0x00, - 0xF2, 0xF0, 0xDE, 0xDC, 0xC2, 0xC0, 0xAE, 0xAC, 0x9A, 0x98, 0x7E, 0x7C, 0x5E, 0x5C, 0x32, 0x30, - 0x00, 0x31, 0x33, 0x5D, 0x5F, 0x7D, 0x7F, 0x99, 0x9B, 0xAD, 0xAF, 0xC1, 0xC3, 0xDD, 0xDF, 0xF1, - 0xF3, 0x01, 0x03, 0x0B, 0x1B, 0x23, 0x2D, 0x37, 0x41, 0x45, 0x51, 0x59, 0x5F, 0x65, 0x6D, 0x75, - 0x67, 0x09, 0x11, 0x13, 0x21, 0x29, 0x2B, 0x35, 0x3D, 0x43, 0x47, 0x4F, 0x53, 0x5B, 0x5D, 0x63, - 0x69, 0x6B, 0x71, 0x73, 0x77, 0x7B, 0x7D, 0x7F, 0x03, 0x07, 0x0B, 0x0F, 0x13, 0x19, 0x1D, 0x25 - }; - - private static readonly byte[] SpectrumA73Bits = - { - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 - }; - - private static readonly short[] SpectrumA73Codes = - { - 0x003, 0x03E, 0x038, 0x034, 0x030, 0x02C, 0x028, 0x024, 0x020, 0x01C, 0x016, 0x014, - 0x00E, 0x00A, 0x004, 0x000, 0x07A, 0x076, 0x06E, 0x06C, 0x064, 0x05E, 0x056, 0x04E, - 0x04C, 0x044, 0x036, 0x030, 0x022, 0x018, 0x012, 0x004, 0x03C, 0x03E, 0x032, 0x024, - 0x020, 0x010, 0x0F2, 0x0F0, 0x0E8, 0x0CE, 0x0BA, 0x0B8, 0x0A8, 0x08C, 0x06A, 0x04E, - 0x04C, 0x034, 0x00E, 0x00C, 0x1D6, 0x1D4, 0x19A, 0x198, 0x156, 0x154, 0x11E, 0x11C, - 0x0D2, 0x0D0, 0x06E, 0x06C, 0x000, 0x06D, 0x06F, 0x0D1, 0x0D3, 0x11D, 0x11F, 0x155, - 0x157, 0x199, 0x19B, 0x1D5, 0x1D7, 0x00D, 0x00F, 0x035, 0x04D, 0x04F, 0x06B, 0x08D, - 0x0A9, 0x0B9, 0x0BB, 0x0CF, 0x0E9, 0x0F1, 0x0F3, 0x011, 0x021, 0x025, 0x033, 0x03F, - 0x03D, 0x005, 0x013, 0x019, 0x023, 0x031, 0x037, 0x045, 0x04D, 0x04F, 0x057, 0x05F, - 0x065, 0x06D, 0x06F, 0x077, 0x07B, 0x001, 0x005, 0x00B, 0x00F, 0x015, 0x017, 0x01D, - 0x021, 0x025, 0x029, 0x02D, 0x031, 0x035, 0x039, 0x03F - }; - - private static readonly byte[] SpectrumA74Bits = - { - 05, 05, 05, 05, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, - 06, 07, 07, 07, 07, 07, 07, 07, 07, 07, 07, 07, 07, 07, 08, 08, - 07, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 09, 09, 09, 09, 09, - 09, 09, 09, 09, 09, 09, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 00, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 09, 09, 09, 09, 09, - 09, 09, 09, 09, 09, 09, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, - 07, 08, 08, 07, 07, 07, 07, 07, 07, 07, 07, 07, 07, 07, 07, 07, - 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 05, 05, 05 - }; - - private static readonly short[] SpectrumA74Codes = - { - 0x00D, 0x00A, 0x004, 0x000, 0x03A, 0x036, 0x032, 0x030, 0x02C, 0x028, 0x026, 0x022, - 0x01E, 0x018, 0x012, 0x00E, 0x006, 0x07E, 0x07A, 0x070, 0x06A, 0x05E, 0x056, 0x054, - 0x048, 0x040, 0x038, 0x022, 0x01A, 0x00A, 0x0F8, 0x0E6, 0x008, 0x0FA, 0x0F0, 0x0D2, - 0x0BA, 0x0B8, 0x094, 0x084, 0x074, 0x042, 0x032, 0x1E6, 0x1CA, 0x1C8, 0x1A2, 0x12E, - 0x10E, 0x10C, 0x0EC, 0x082, 0x062, 0x060, 0x3CA, 0x3C8, 0x342, 0x340, 0x25A, 0x258, - 0x1DE, 0x1DC, 0x102, 0x100, 0x000, 0x101, 0x103, 0x1DD, 0x1DF, 0x259, 0x25B, 0x341, - 0x343, 0x3C9, 0x3CB, 0x061, 0x063, 0x083, 0x0ED, 0x10D, 0x10F, 0x12F, 0x1A3, 0x1C9, - 0x1CB, 0x1E7, 0x033, 0x043, 0x075, 0x085, 0x095, 0x0B9, 0x0BB, 0x0D3, 0x0F1, 0x0FB, - 0x009, 0x0E7, 0x0F9, 0x00B, 0x01B, 0x023, 0x039, 0x041, 0x049, 0x055, 0x057, 0x05F, - 0x06B, 0x071, 0x07B, 0x07F, 0x007, 0x00F, 0x013, 0x019, 0x01F, 0x023, 0x027, 0x029, - 0x02D, 0x031, 0x033, 0x037, 0x03B, 0x001, 0x005, 0x00B - }; - - private static readonly byte[] SpectrumB22Bits = - { - 00, 04, 00, 04, 04, 05, 00, 05, 00, 00, 00, 00, 04, 05, 00, 05, - 04, 07, 00, 06, 06, 09, 00, 07, 00, 00, 00, 00, 06, 09, 00, 07, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 04, 06, 00, 07, 06, 07, 00, 09, 00, 00, 00, 00, 06, 07, 00, 09, - 04, 08, 00, 08, 08, 10, 00, 10, 00, 00, 00, 00, 06, 09, 00, 09, - 05, 10, 00, 09, 09, 10, 00, 10, 00, 00, 00, 00, 07, 10, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 06, 09, 00, 10, 09, 10, 00, 10, 00, 00, 00, 00, 07, 10, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 04, 08, 00, 08, 06, 09, 00, 09, 00, 00, 00, 00, 08, 10, 00, 10, - 06, 10, 00, 09, 07, 10, 00, 10, 00, 00, 00, 00, 09, 10, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 05, 09, 00, 10, 07, 10, 00, 10, 00, 00, 00, 00, 09, 10, 00, 10 - }; - - private static readonly short[] SpectrumB22Codes = - { - 0x000, 0x00E, 0x000, 0x00F, 0x008, 0x006, 0x000, 0x00B, 0x000, 0x000, 0x000, 0x000, - 0x009, 0x00A, 0x000, 0x007, 0x006, 0x00A, 0x000, 0x029, 0x006, 0x158, 0x000, 0x023, - 0x000, 0x000, 0x000, 0x000, 0x013, 0x174, 0x000, 0x021, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x007, 0x028, 0x000, 0x00B, 0x012, 0x020, 0x000, 0x175, 0x000, 0x000, 0x000, 0x000, - 0x007, 0x022, 0x000, 0x159, 0x00C, 0x0BC, 0x000, 0x0BF, 0x022, 0x2B8, 0x000, 0x2BB, - 0x000, 0x000, 0x000, 0x000, 0x00B, 0x170, 0x000, 0x15B, 0x000, 0x04E, 0x000, 0x15F, - 0x042, 0x04A, 0x000, 0x041, 0x000, 0x000, 0x000, 0x000, 0x055, 0x044, 0x000, 0x04D, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x02D, 0x172, 0x000, 0x2ED, 0x040, 0x042, 0x000, 0x047, - 0x000, 0x000, 0x000, 0x000, 0x013, 0x2EE, 0x000, 0x049, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x00D, 0x0BE, 0x000, 0x0BD, 0x00A, 0x15A, 0x000, 0x171, 0x000, 0x000, 0x000, 0x000, - 0x023, 0x2BA, 0x000, 0x2B9, 0x02C, 0x2EC, 0x000, 0x173, 0x012, 0x048, 0x000, 0x2EF, - 0x000, 0x000, 0x000, 0x000, 0x041, 0x046, 0x000, 0x043, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x001, 0x15E, 0x000, 0x04F, 0x054, 0x04C, 0x000, 0x045, 0x000, 0x000, 0x000, 0x000, - 0x043, 0x040, 0x000, 0x04B - }; - - private static readonly byte[] SpectrumB23Bits = - { - 02, 04, 00, 04, 04, 06, 00, 06, 00, 00, 00, 00, 04, 06, 00, 06, - 04, 09, 00, 07, 07, 09, 00, 08, 00, 00, 00, 00, 07, 09, 00, 08, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 04, 07, 00, 09, 07, 08, 00, 09, 00, 00, 00, 00, 07, 08, 00, 09, - 04, 08, 00, 08, 09, 10, 00, 10, 00, 00, 00, 00, 07, 10, 00, 10, - 07, 10, 00, 10, 10, 10, 00, 10, 00, 00, 00, 00, 09, 10, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 07, 10, 00, 10, 10, 10, 00, 10, 00, 00, 00, 00, 08, 10, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 04, 08, 00, 08, 07, 10, 00, 10, 00, 00, 00, 00, 09, 10, 00, 10, - 07, 10, 00, 10, 08, 10, 00, 10, 00, 00, 00, 00, 10, 10, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 07, 10, 00, 10, 09, 10, 00, 10, 00, 00, 00, 00, 10, 10, 00, 10 - }; - - private static readonly short[] SpectrumB23Codes = - { - 0x003, 0x008, 0x000, 0x009, 0x002, 0x018, 0x000, 0x01B, 0x000, 0x000, 0x000, 0x000, - 0x003, 0x01A, 0x000, 0x019, 0x000, 0x17C, 0x000, 0x055, 0x056, 0x0E8, 0x000, 0x07D, - 0x000, 0x000, 0x000, 0x000, 0x059, 0x0F6, 0x000, 0x07F, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x001, 0x054, 0x000, 0x17D, 0x058, 0x07E, 0x000, 0x0F7, 0x000, 0x000, 0x000, 0x000, - 0x057, 0x07C, 0x000, 0x0E9, 0x004, 0x0A2, 0x000, 0x0A1, 0x17A, 0x1DA, 0x000, 0x1D9, - 0x000, 0x000, 0x000, 0x000, 0x053, 0x1E8, 0x000, 0x2F3, 0x05C, 0x1D6, 0x000, 0x1E7, - 0x1EA, 0x1E2, 0x000, 0x1CF, 0x000, 0x000, 0x000, 0x000, 0x17F, 0x1CA, 0x000, 0x1DD, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x05B, 0x2F0, 0x000, 0x1DF, 0x1E4, 0x1CC, 0x000, 0x1D5, - 0x000, 0x000, 0x000, 0x000, 0x071, 0x1E0, 0x000, 0x1C9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x005, 0x0A0, 0x000, 0x0A3, 0x052, 0x2F2, 0x000, 0x1E9, 0x000, 0x000, 0x000, 0x000, - 0x17B, 0x1D8, 0x000, 0x1DB, 0x05A, 0x1DE, 0x000, 0x2F1, 0x070, 0x1C8, 0x000, 0x1E1, - 0x000, 0x000, 0x000, 0x000, 0x1E5, 0x1D4, 0x000, 0x1CD, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x05D, 0x1E6, 0x000, 0x1D7, 0x17E, 0x1DC, 0x000, 0x1CB, 0x000, 0x000, 0x000, 0x000, - 0x1EB, 0x1CE, 0x000, 0x1E3 - }; - - private static readonly byte[] SpectrumB24Bits = - { - 01, 04, 00, 04, 05, 07, 00, 07, 00, 00, 00, 00, 05, 07, 00, 07, - 05, 09, 00, 07, 08, 10, 00, 09, 00, 00, 00, 00, 07, 10, 00, 09, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 05, 07, 00, 09, 07, 09, 00, 10, 00, 00, 00, 00, 08, 09, 00, 10, - 05, 09, 00, 08, 09, 10, 00, 10, 00, 00, 00, 00, 07, 10, 00, 10, - 07, 10, 00, 10, 10, 10, 00, 10, 00, 00, 00, 00, 10, 10, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 07, 10, 00, 10, 10, 10, 00, 10, 00, 00, 00, 00, 10, 10, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 05, 08, 00, 09, 07, 10, 00, 10, 00, 00, 00, 00, 09, 10, 00, 10, - 07, 10, 00, 10, 10, 10, 00, 10, 00, 00, 00, 00, 10, 10, 00, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 07, 10, 00, 10, 10, 10, 00, 10, 00, 00, 00, 00, 10, 10, 00, 10 - }; - - private static readonly short[] SpectrumB24Codes = - { - 0x001, 0x000, 0x000, 0x001, 0x00A, 0x01C, 0x000, 0x033, 0x000, 0x000, 0x000, 0x000, - 0x00B, 0x032, 0x000, 0x01D, 0x008, 0x0D8, 0x000, 0x031, 0x06E, 0x0FA, 0x000, 0x0D7, - 0x000, 0x000, 0x000, 0x000, 0x011, 0x0F4, 0x000, 0x0D5, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x009, 0x030, 0x000, 0x0D9, 0x010, 0x0D4, 0x000, 0x0F5, 0x000, 0x000, 0x000, 0x000, - 0x06F, 0x0D6, 0x000, 0x0FB, 0x00E, 0x0DA, 0x000, 0x025, 0x0D2, 0x0D4, 0x000, 0x0DB, - 0x000, 0x000, 0x000, 0x000, 0x017, 0x0FE, 0x000, 0x0FD, 0x014, 0x0DC, 0x000, 0x0F9, - 0x0F2, 0x0D6, 0x000, 0x09B, 0x000, 0x000, 0x000, 0x000, 0x1A3, 0x09C, 0x000, 0x0D3, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x019, 0x0F6, 0x000, 0x0D9, 0x0F0, 0x09E, 0x000, 0x0D1, - 0x000, 0x000, 0x000, 0x000, 0x1A1, 0x0DE, 0x000, 0x099, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x00F, 0x024, 0x000, 0x0DB, 0x016, 0x0FC, 0x000, 0x0FF, 0x000, 0x000, 0x000, 0x000, - 0x0D3, 0x0DA, 0x000, 0x0D5, 0x018, 0x0D8, 0x000, 0x0F7, 0x1A0, 0x098, 0x000, 0x0DF, - 0x000, 0x000, 0x000, 0x000, 0x0F1, 0x0D0, 0x000, 0x09F, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x015, 0x0F8, 0x000, 0x0DD, 0x1A2, 0x0D2, 0x000, 0x09D, 0x000, 0x000, 0x000, 0x000, - 0x0F3, 0x09A, 0x000, 0x0D7 - }; - - private static readonly byte[] SpectrumB32Bits = - { - 2, 4, 5, 6, 0, 6, 5, 4, 5, 6, 6, 7, 0, 6, 5, 6, - 5, 6, 7, 7, 0, 8, 7, 6, 6, 7, 8, 9, 0, 9, 8, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 0, 9, 8, 7, - 5, 6, 7, 8, 0, 7, 7, 6, 5, 6, 5, 6, 0, 7, 6, 6 - }; - - private static readonly short[] SpectrumB32Codes = - { - 0x001, 0x002, 0x01E, 0x02A, 0x000, 0x02B, 0x01F, 0x003, 0x016, 0x020, 0x03A, 0x064, - 0x000, 0x005, 0x001, 0x023, 0x01A, 0x026, 0x070, 0x00C, 0x000, 0x0CF, 0x073, 0x031, - 0x024, 0x00E, 0x0CC, 0x146, 0x000, 0x145, 0x0A1, 0x053, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x025, 0x052, 0x0A0, 0x144, 0x000, 0x147, 0x0CD, 0x00F, - 0x01B, 0x030, 0x072, 0x0CE, 0x000, 0x00D, 0x071, 0x027, 0x017, 0x022, 0x000, 0x004, - 0x000, 0x065, 0x03B, 0x021 - }; - - private static readonly byte[] SpectrumB33Bits = - { - 02, 04, 05, 07, 00, 07, 05, 04, 04, 05, 06, 08, 00, 07, 06, 05, - 05, 06, 07, 09, 00, 08, 07, 06, 07, 08, 09, 10, 00, 10, 09, 08, - 00, 00, 00, 00, 00, 00, 00, 00, 07, 08, 09, 10, 00, 10, 09, 08, - 05, 06, 07, 08, 00, 09, 07, 06, 04, 05, 06, 07, 00, 08, 06, 05 - }; - - private static readonly short[] SpectrumB33Codes = - { - 0x003, 0x008, 0x014, 0x05E, 0x000, 0x05F, 0x015, 0x009, 0x004, 0x002, 0x01C, 0x0BA, - 0x000, 0x011, 0x01F, 0x001, 0x00C, 0x00C, 0x014, 0x166, 0x000, 0x02D, 0x013, 0x00F, - 0x05A, 0x0B0, 0x05E, 0x0B8, 0x000, 0x0BB, 0x165, 0x0B9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x05B, 0x0B8, 0x164, 0x0BA, 0x000, 0x0B9, 0x05F, 0x0B1, - 0x00D, 0x00E, 0x012, 0x02C, 0x000, 0x167, 0x015, 0x00D, 0x005, 0x000, 0x01E, 0x010, - 0x000, 0x0BB, 0x01D, 0x003 - }; - - private static readonly byte[] SpectrumB34Bits = - { - 01, 04, 06, 08, 00, 08, 06, 04, 04, 06, 07, 09, 00, 08, 07, 06, - 06, 07, 08, 10, 00, 10, 08, 07, 08, 09, 10, 10, 00, 10, 10, 09, - 00, 00, 00, 00, 00, 00, 00, 00, 08, 09, 10, 10, 00, 10, 10, 09, - 06, 07, 08, 10, 00, 10, 08, 07, 04, 06, 07, 08, 00, 09, 07, 06 - }; - - private static readonly short[] SpectrumB34Codes = - { - 0x000, 0x00A, 0x038, 0x0EE, 0x000, 0x0EF, 0x039, 0x00B, 0x008, 0x03C, 0x06E, 0x1D8, - 0x000, 0x0C1, 0x075, 0x03F, 0x032, 0x068, 0x0C4, 0x358, 0x000, 0x30F, 0x0C7, 0x06D, - 0x0D4, 0x1AE, 0x30C, 0x308, 0x000, 0x30B, 0x35B, 0x1DB, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x0D5, 0x1DA, 0x35A, 0x30A, 0x000, 0x309, 0x30D, 0x1AF, - 0x033, 0x06C, 0x0C6, 0x30E, 0x000, 0x359, 0x0C5, 0x069, 0x009, 0x03E, 0x074, 0x0C0, - 0x000, 0x1D9, 0x06F, 0x03D - }; - - private static readonly byte[] SpectrumB42Bits = - { - 04, 05, 06, 08, 06, 07, 08, 08, 00, 08, 08, 07, 06, 08, 06, 05, - 05, 06, 07, 08, 07, 07, 08, 09, 00, 08, 08, 07, 07, 08, 07, 06, - 07, 07, 08, 09, 07, 08, 09, 09, 00, 09, 09, 08, 07, 09, 08, 07, - 08, 09, 09, 10, 08, 08, 09, 10, 00, 10, 09, 08, 08, 10, 09, 08, - 06, 07, 08, 08, 09, 09, 10, 10, 00, 10, 10, 09, 09, 08, 08, 07, - 07, 07, 08, 09, 09, 10, 10, 10, 00, 10, 10, 10, 09, 09, 08, 07, - 08, 08, 09, 09, 10, 10, 10, 10, 00, 10, 10, 10, 10, 09, 09, 08, - 08, 09, 09, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 09, 09, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 08, 09, 09, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 09, 09, - 08, 08, 09, 09, 10, 10, 10, 10, 00, 10, 10, 10, 10, 09, 09, 08, - 07, 07, 08, 09, 09, 10, 10, 10, 00, 10, 10, 10, 09, 09, 08, 07, - 06, 07, 08, 08, 09, 09, 10, 10, 00, 10, 10, 09, 09, 08, 08, 07, - 08, 08, 09, 10, 08, 08, 09, 10, 00, 10, 09, 08, 08, 10, 09, 09, - 07, 07, 08, 09, 07, 08, 09, 09, 00, 09, 09, 08, 07, 09, 08, 07, - 05, 06, 07, 08, 07, 07, 08, 08, 00, 09, 08, 07, 07, 08, 07, 06 - }; - - private static readonly short[] SpectrumB42Codes = - { - 0x00E, 0x018, 0x010, 0x0F0, 0x024, 0x05A, 0x0F6, 0x078, 0x000, 0x079, 0x0F7, 0x05B, - 0x025, 0x0F1, 0x011, 0x019, 0x00C, 0x014, 0x01C, 0x036, 0x05C, 0x012, 0x09E, 0x1E4, - 0x000, 0x00B, 0x0A9, 0x03B, 0x05F, 0x071, 0x019, 0x017, 0x06E, 0x000, 0x03E, 0x114, - 0x002, 0x0B0, 0x1AA, 0x07A, 0x000, 0x099, 0x1E7, 0x0B3, 0x00B, 0x131, 0x07F, 0x00D, - 0x0D8, 0x1FE, 0x112, 0x22E, 0x086, 0x010, 0x134, 0x35C, 0x000, 0x35F, 0x133, 0x013, - 0x081, 0x22D, 0x119, 0x07B, 0x00A, 0x050, 0x0F8, 0x04E, 0x1B4, 0x154, 0x3EC, 0x0D2, - 0x000, 0x0D7, 0x3D7, 0x137, 0x1FD, 0x073, 0x0FD, 0x057, 0x052, 0x010, 0x08E, 0x1E8, - 0x11A, 0x3EE, 0x0F2, 0x03C, 0x000, 0x03F, 0x0F1, 0x3D5, 0x111, 0x1F5, 0x09D, 0x025, - 0x0D2, 0x082, 0x1A0, 0x0F8, 0x36E, 0x0D4, 0x072, 0x03A, 0x000, 0x027, 0x071, 0x07D, - 0x36D, 0x0FB, 0x1AD, 0x085, 0x00C, 0x1A8, 0x03C, 0x346, 0x0D0, 0x076, 0x024, 0x020, - 0x000, 0x023, 0x039, 0x075, 0x07F, 0x345, 0x09B, 0x157, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x00D, 0x156, 0x09A, 0x344, 0x07E, 0x074, 0x038, 0x022, 0x000, 0x021, 0x025, 0x077, - 0x0D1, 0x347, 0x03D, 0x1A9, 0x0D3, 0x084, 0x1AC, 0x0FA, 0x36C, 0x07C, 0x070, 0x026, - 0x000, 0x03B, 0x073, 0x0D5, 0x36F, 0x0F9, 0x1A1, 0x083, 0x053, 0x024, 0x09C, 0x1F4, - 0x110, 0x3D4, 0x0F0, 0x03E, 0x000, 0x03D, 0x0F3, 0x3EF, 0x11B, 0x1E9, 0x08F, 0x011, - 0x00B, 0x056, 0x0FC, 0x072, 0x1FC, 0x136, 0x3D6, 0x0D6, 0x000, 0x0D3, 0x3ED, 0x155, - 0x1B5, 0x04F, 0x0F9, 0x051, 0x0D9, 0x07A, 0x118, 0x22C, 0x080, 0x012, 0x132, 0x35E, - 0x000, 0x35D, 0x135, 0x011, 0x087, 0x22F, 0x113, 0x1FF, 0x06F, 0x00C, 0x07E, 0x130, - 0x00A, 0x0B2, 0x1E6, 0x098, 0x000, 0x07B, 0x1AB, 0x0B1, 0x003, 0x115, 0x03F, 0x001, - 0x00D, 0x016, 0x018, 0x070, 0x05E, 0x03A, 0x0A8, 0x00A, 0x000, 0x1E5, 0x09F, 0x013, - 0x05D, 0x037, 0x01D, 0x015 - }; - - private static readonly byte[] SpectrumB43Bits = - { - 02, 05, 06, 07, 07, 08, 08, 09, 00, 09, 08, 08, 07, 07, 06, 05, - 05, 06, 07, 08, 07, 08, 09, 10, 00, 10, 09, 08, 07, 08, 07, 06, - 06, 07, 08, 09, 08, 09, 10, 10, 00, 10, 10, 09, 08, 09, 08, 07, - 07, 08, 09, 10, 09, 09, 10, 10, 00, 10, 10, 10, 09, 10, 09, 08, - 07, 08, 08, 09, 10, 10, 10, 10, 00, 10, 10, 10, 10, 09, 08, 07, - 08, 08, 09, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 09, 08, - 09, 09, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 09, - 10, 10, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 10, 10, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 10, - 09, 09, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 09, - 08, 08, 09, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 09, 08, - 07, 07, 08, 09, 10, 10, 10, 10, 00, 10, 10, 10, 10, 09, 08, 08, - 07, 08, 09, 10, 09, 10, 10, 10, 00, 10, 10, 09, 09, 10, 09, 08, - 06, 07, 08, 09, 08, 09, 10, 10, 00, 10, 10, 09, 08, 09, 08, 07, - 05, 06, 07, 08, 07, 08, 09, 10, 00, 10, 09, 08, 07, 08, 07, 06 - }; - - private static readonly short[] SpectrumB43Codes = - { - 0x001, 0x01E, 0x022, 0x018, 0x064, 0x0EC, 0x008, 0x100, 0x000, 0x101, 0x009, 0x0ED, - 0x065, 0x019, 0x023, 0x01F, 0x01A, 0x030, 0x056, 0x09A, 0x00A, 0x090, 0x12C, 0x0A6, - 0x000, 0x0A9, 0x12F, 0x093, 0x00F, 0x09F, 0x059, 0x039, 0x00E, 0x054, 0x0BC, 0x19E, - 0x082, 0x176, 0x0AC, 0x088, 0x000, 0x08B, 0x0AF, 0x19D, 0x095, 0x1D1, 0x0BF, 0x051, - 0x002, 0x098, 0x1D4, 0x0B8, 0x170, 0x046, 0x090, 0x060, 0x000, 0x067, 0x095, 0x0BD, - 0x173, 0x0B5, 0x1D3, 0x09D, 0x052, 0x0EE, 0x034, 0x174, 0x0BA, 0x09C, 0x080, 0x044, - 0x000, 0x047, 0x06D, 0x099, 0x0BF, 0x16F, 0x085, 0x001, 0x0CC, 0x036, 0x16C, 0x0B0, - 0x09A, 0x084, 0x04E, 0x03E, 0x000, 0x037, 0x04B, 0x06B, 0x0A1, 0x0B3, 0x16B, 0x087, - 0x1D6, 0x102, 0x0A4, 0x092, 0x068, 0x04C, 0x034, 0x030, 0x000, 0x02D, 0x03D, 0x049, - 0x083, 0x097, 0x0AB, 0x169, 0x0B6, 0x09E, 0x06E, 0x064, 0x040, 0x038, 0x02E, 0x02A, - 0x000, 0x029, 0x033, 0x03B, 0x043, 0x063, 0x087, 0x0A3, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x0B7, 0x0A2, 0x086, 0x062, 0x042, 0x03A, 0x032, 0x028, 0x000, 0x02B, 0x02F, 0x039, - 0x041, 0x065, 0x06F, 0x09F, 0x1D7, 0x168, 0x0AA, 0x096, 0x082, 0x048, 0x03C, 0x02C, - 0x000, 0x031, 0x035, 0x04D, 0x069, 0x093, 0x0A5, 0x103, 0x0CD, 0x086, 0x16A, 0x0B2, - 0x0A0, 0x06A, 0x04A, 0x036, 0x000, 0x03F, 0x04F, 0x085, 0x09B, 0x0B1, 0x16D, 0x037, - 0x053, 0x000, 0x084, 0x16E, 0x0BE, 0x098, 0x06C, 0x046, 0x000, 0x045, 0x081, 0x09D, - 0x0BB, 0x175, 0x035, 0x0EF, 0x003, 0x09C, 0x1D2, 0x0B4, 0x172, 0x0BC, 0x094, 0x066, - 0x000, 0x061, 0x091, 0x047, 0x171, 0x0B9, 0x1D5, 0x099, 0x00F, 0x050, 0x0BE, 0x1D0, - 0x094, 0x19C, 0x0AE, 0x08A, 0x000, 0x089, 0x0AD, 0x177, 0x083, 0x19F, 0x0BD, 0x055, - 0x01B, 0x038, 0x058, 0x09E, 0x00E, 0x092, 0x12E, 0x0A8, 0x000, 0x0A7, 0x12D, 0x091, - 0x00B, 0x09B, 0x057, 0x031 - }; - - private static readonly byte[] SpectrumB44Bits = - { - 02, 04, 06, 07, 07, 08, 10, 10, 00, 10, 10, 08, 07, 07, 06, 04, - 05, 05, 07, 08, 08, 10, 10, 10, 00, 10, 10, 10, 08, 08, 07, 05, - 06, 07, 08, 09, 09, 10, 10, 10, 00, 10, 10, 10, 10, 09, 08, 07, - 08, 08, 09, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 08, - 08, 08, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 08, - 09, 10, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 10, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, - 10, 10, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 10, - 09, 10, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 10, - 08, 08, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 10, 08, - 08, 08, 10, 10, 10, 10, 10, 10, 00, 10, 10, 10, 10, 10, 09, 08, - 06, 07, 08, 09, 10, 10, 10, 10, 00, 10, 10, 10, 09, 09, 08, 07, - 05, 05, 07, 08, 08, 10, 10, 10, 00, 10, 10, 10, 08, 08, 07, 05 - }; - - private static readonly short[] SpectrumB44Codes = - { - 0x002, 0x002, 0x030, 0x000, 0x002, 0x00C, 0x1D2, 0x1AE, 0x000, 0x1AF, 0x1D3, 0x00D, - 0x003, 0x001, 0x031, 0x003, 0x01E, 0x002, 0x070, 0x0C8, 0x07E, 0x1E8, 0x1C0, 0x176, - 0x000, 0x17F, 0x1C3, 0x1EB, 0x0CF, 0x0D3, 0x073, 0x009, 0x018, 0x06A, 0x0EC, 0x1DE, - 0x1A2, 0x1CA, 0x1AA, 0x164, 0x000, 0x16D, 0x1AD, 0x1D1, 0x1EF, 0x1DD, 0x0EB, 0x06D, - 0x0E8, 0x0CA, 0x1BE, 0x1CE, 0x1DA, 0x1B6, 0x170, 0x154, 0x000, 0x153, 0x173, 0x1B1, - 0x1D7, 0x1D5, 0x343, 0x0CD, 0x0DC, 0x078, 0x340, 0x1CC, 0x1BA, 0x1A8, 0x156, 0x148, - 0x000, 0x145, 0x15F, 0x1A1, 0x1BD, 0x1D9, 0x1ED, 0x07D, 0x1BC, 0x1DC, 0x1C4, 0x1B2, - 0x17C, 0x15A, 0x14A, 0x03A, 0x000, 0x039, 0x147, 0x16B, 0x17B, 0x1B5, 0x1C9, 0x1DF, - 0x1C6, 0x1B8, 0x1A2, 0x168, 0x160, 0x14C, 0x02E, 0x024, 0x000, 0x027, 0x03D, 0x151, - 0x15D, 0x16F, 0x1A7, 0x1BF, 0x1A4, 0x174, 0x162, 0x14E, 0x140, 0x02C, 0x02A, 0x022, - 0x000, 0x021, 0x029, 0x03F, 0x143, 0x159, 0x167, 0x179, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x1A5, 0x178, 0x166, 0x158, 0x142, 0x03E, 0x028, 0x020, 0x000, 0x023, 0x02B, 0x02D, - 0x141, 0x14F, 0x163, 0x175, 0x1C7, 0x1BE, 0x1A6, 0x16E, 0x15C, 0x150, 0x03C, 0x026, - 0x000, 0x025, 0x02F, 0x14D, 0x161, 0x169, 0x1A3, 0x1B9, 0x1BD, 0x1DE, 0x1C8, 0x1B4, - 0x17A, 0x16A, 0x146, 0x038, 0x000, 0x03B, 0x14B, 0x15B, 0x17D, 0x1B3, 0x1C5, 0x1DD, - 0x0DD, 0x07C, 0x1EC, 0x1D8, 0x1BC, 0x1A0, 0x15E, 0x144, 0x000, 0x149, 0x157, 0x1A9, - 0x1BB, 0x1CD, 0x341, 0x079, 0x0E9, 0x0CC, 0x342, 0x1D4, 0x1D6, 0x1B0, 0x172, 0x152, - 0x000, 0x155, 0x171, 0x1B7, 0x1DB, 0x1CF, 0x1BF, 0x0CB, 0x019, 0x06C, 0x0EA, 0x1DC, - 0x1EE, 0x1D0, 0x1AC, 0x16C, 0x000, 0x165, 0x1AB, 0x1CB, 0x1A3, 0x1DF, 0x0ED, 0x06B, - 0x01F, 0x008, 0x072, 0x0D2, 0x0CE, 0x1EA, 0x1C2, 0x17E, 0x000, 0x177, 0x1C1, 0x1E9, - 0x07F, 0x0C9, 0x071, 0x003 - }; - - private static readonly byte[] SpectrumB52Bits = - { - 3, 4, 4, 4, 5, 5, 6, 6, 5, 5, 5, 6, 6, 6, 7, 7, - 0, 7, 7, 6, 6, 6, 5, 5, 5, 6, 6, 5, 5, 4, 4, 4 - }; - - private static readonly short[] SpectrumB52Codes = - { - 0x06, 0x0E, 0x06, 0x00, 0x0A, 0x04, 0x2C, 0x12, 0x14, 0x10, 0x06, 0x2E, 0x24, 0x10, 0x4E, 0x4C, - 0x00, 0x4D, 0x4F, 0x11, 0x25, 0x2F, 0x07, 0x11, 0x15, 0x13, 0x2D, 0x05, 0x0B, 0x01, 0x07, 0x0F - }; - - private static readonly byte[] SpectrumB53Bits = - { - 2, 3, 4, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 8, 8, - 0, 8, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 4, 3 - }; - - private static readonly short[] SpectrumB53Codes = - { - 0x02, 0x00, 0x06, 0x1C, 0x18, 0x3E, 0x16, 0x10, 0x3C, 0x36, 0x14, 0x6A, 0x26, 0x24, 0xD2, 0xD0, - 0x00, 0xD1, 0xD3, 0x25, 0x27, 0x6B, 0x15, 0x37, 0x3D, 0x11, 0x17, 0x3F, 0x19, 0x1D, 0x07, 0x01 - }; - - private static readonly byte[] SpectrumB54Bits = - { - 2, 3, 4, 4, 5, 6, 6, 7, 6, 6, 7, 8, 8, 8, 9, 9, - 0, 9, 9, 8, 8, 8, 7, 6, 6, 7, 6, 6, 5, 4, 4, 3 - }; - - private static readonly short[] SpectrumB54Codes = - { - 0x003, 0x002, 0x008, 0x000, 0x014, 0x02E, 0x00E, 0x05A, 0x00A, 0x008, 0x01A, 0x0B2, - 0x032, 0x030, 0x162, 0x160, 0x000, 0x161, 0x163, 0x031, 0x033, 0x0B3, 0x01B, 0x009, - 0x00B, 0x05B, 0x00F, 0x02F, 0x015, 0x001, 0x009, 0x003 - }; - - private static readonly byte[] SpectrumB62Bits = - { - 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, - 0, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, - 6, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4 - }; - - private static readonly short[] SpectrumB62Codes = - { - 0x0D, 0x06, 0x1C, 0x14, 0x0A, 0x04, 0x3E, 0x2E, 0x22, 0x0E, 0x06, 0x00, 0x5A, 0x4E, 0x40, 0x20, - 0x30, 0x32, 0x24, 0x12, 0x0C, 0x02, 0x78, 0x58, 0x42, 0x22, 0x0A, 0x08, 0xF6, 0xF4, 0x9A, 0x98, - 0x00, 0x99, 0x9B, 0xF5, 0xF7, 0x09, 0x0B, 0x23, 0x43, 0x59, 0x79, 0x03, 0x0D, 0x13, 0x25, 0x33, - 0x31, 0x21, 0x41, 0x4F, 0x5B, 0x01, 0x07, 0x0F, 0x23, 0x2F, 0x3F, 0x05, 0x0B, 0x15, 0x1D, 0x07 - }; - - private static readonly byte[] SpectrumB63Bits = - { - 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, - 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, - 6, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4 - }; - - private static readonly short[] SpectrumB63Codes = - { - 0x006, 0x00E, 0x004, 0x014, 0x010, 0x006, 0x000, 0x026, 0x01C, 0x018, 0x004, 0x05C, - 0x04A, 0x03C, 0x016, 0x0BC, 0x006, 0x008, 0x058, 0x03E, 0x036, 0x014, 0x0B6, 0x0B4, - 0x090, 0x068, 0x17E, 0x17C, 0x126, 0x124, 0x0D6, 0x0D4, 0x000, 0x0D5, 0x0D7, 0x125, - 0x127, 0x17D, 0x17F, 0x069, 0x091, 0x0B5, 0x0B7, 0x015, 0x037, 0x03F, 0x059, 0x009, - 0x007, 0x0BD, 0x017, 0x03D, 0x04B, 0x05D, 0x005, 0x019, 0x01D, 0x027, 0x001, 0x007, - 0x011, 0x015, 0x005, 0x00F - }; - - private static readonly byte[] SpectrumB64Bits = - { - 03, 03, 04, 05, 05, 05, 06, 06, 06, 06, 07, 07, 07, 07, 07, 08, - 07, 07, 07, 08, 08, 08, 09, 09, 09, 09, 09, 09, 10, 10, 10, 10, - 00, 10, 10, 10, 10, 09, 09, 09, 09, 09, 09, 08, 08, 08, 07, 07, - 07, 08, 07, 07, 07, 07, 07, 06, 06, 06, 06, 05, 05, 05, 04, 03 - }; - - private static readonly short[] SpectrumB64Codes = - { - 0x007, 0x000, 0x008, 0x01A, 0x014, 0x00C, 0x032, 0x02E, 0x01E, 0x014, 0x062, 0x05A, - 0x03A, 0x026, 0x020, 0x0B2, 0x038, 0x02C, 0x022, 0x0C0, 0x05E, 0x04A, 0x186, 0x184, - 0x160, 0x0BA, 0x092, 0x090, 0x2C6, 0x2C4, 0x172, 0x170, 0x000, 0x171, 0x173, 0x2C5, - 0x2C7, 0x091, 0x093, 0x0BB, 0x161, 0x185, 0x187, 0x04B, 0x05F, 0x0C1, 0x023, 0x02D, - 0x039, 0x0B3, 0x021, 0x027, 0x03B, 0x05B, 0x063, 0x015, 0x01F, 0x02F, 0x033, 0x00D, - 0x015, 0x01B, 0x009, 0x001 - }; - - private static readonly byte[] SpectrumB72Bits = - { - 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5 - }; - - private static readonly short[] SpectrumB72Codes = - { - 0x01E, 0x016, 0x00C, 0x000, 0x038, 0x032, 0x028, 0x022, 0x01C, 0x012, 0x00E, 0x006, - 0x076, 0x06C, 0x060, 0x04E, 0x03E, 0x02A, 0x022, 0x01A, 0x012, 0x00A, 0x0FC, 0x0DC, - 0x0C6, 0x0A8, 0x094, 0x086, 0x058, 0x042, 0x040, 0x02A, 0x068, 0x07C, 0x06A, 0x056, - 0x048, 0x040, 0x02E, 0x028, 0x016, 0x010, 0x008, 0x0EA, 0x0DE, 0x0AA, 0x09A, 0x096, - 0x07A, 0x078, 0x05A, 0x032, 0x030, 0x028, 0x1FE, 0x1FC, 0x1D2, 0x1D0, 0x18A, 0x188, - 0x132, 0x130, 0x10A, 0x108, 0x000, 0x109, 0x10B, 0x131, 0x133, 0x189, 0x18B, 0x1D1, - 0x1D3, 0x1FD, 0x1FF, 0x029, 0x031, 0x033, 0x05B, 0x079, 0x07B, 0x097, 0x09B, 0x0AB, - 0x0DF, 0x0EB, 0x009, 0x011, 0x017, 0x029, 0x02F, 0x041, 0x049, 0x057, 0x06B, 0x07D, - 0x069, 0x02B, 0x041, 0x043, 0x059, 0x087, 0x095, 0x0A9, 0x0C7, 0x0DD, 0x0FD, 0x00B, - 0x013, 0x01B, 0x023, 0x02B, 0x03F, 0x04F, 0x061, 0x06D, 0x077, 0x007, 0x00F, 0x013, - 0x01D, 0x023, 0x029, 0x033, 0x039, 0x001, 0x00D, 0x017 - }; - - private static readonly byte[] SpectrumB73Bits = - { - 03, 04, 05, 05, 05, 06, 06, 06, 06, 06, 06, 07, 07, 07, 07, 07, - 07, 07, 07, 07, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 09, 09, - 08, 07, 08, 08, 08, 08, 08, 08, 08, 08, 09, 09, 09, 09, 09, 09, - 09, 09, 09, 09, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 00, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 09, 09, 09, - 09, 09, 09, 09, 09, 09, 09, 08, 08, 08, 08, 08, 08, 08, 08, 07, - 08, 09, 09, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 07, 07, 07, - 07, 07, 07, 07, 07, 07, 06, 06, 06, 06, 06, 06, 05, 05, 05, 04 - }; - - private static readonly short[] SpectrumB73Codes = - { - 0x000, 0x006, 0x018, 0x010, 0x004, 0x03A, 0x034, 0x02A, 0x026, 0x014, 0x010, 0x07E, - 0x072, 0x06E, 0x05C, 0x052, 0x04A, 0x02C, 0x024, 0x018, 0x0F4, 0x0E0, 0x0DA, 0x0B6, - 0x0B2, 0x0A0, 0x05E, 0x04E, 0x038, 0x034, 0x1E6, 0x1B2, 0x0FA, 0x01E, 0x0F8, 0x0F0, - 0x0BE, 0x0B4, 0x0A2, 0x090, 0x04C, 0x03A, 0x1EE, 0x1E4, 0x1C6, 0x1B0, 0x178, 0x162, - 0x126, 0x124, 0x0B8, 0x06C, 0x3DA, 0x3D8, 0x38A, 0x388, 0x2F6, 0x2F4, 0x2C2, 0x2C0, - 0x176, 0x174, 0x0DC, 0x0DE, 0x000, 0x0DF, 0x0DD, 0x175, 0x177, 0x2C1, 0x2C3, 0x2F5, - 0x2F7, 0x389, 0x38B, 0x3D9, 0x3DB, 0x06D, 0x0B9, 0x125, 0x127, 0x163, 0x179, 0x1B1, - 0x1C7, 0x1E5, 0x1EF, 0x03B, 0x04D, 0x091, 0x0A3, 0x0B5, 0x0BF, 0x0F1, 0x0F9, 0x01F, - 0x0FB, 0x1B3, 0x1E7, 0x035, 0x039, 0x04F, 0x05F, 0x0A1, 0x0B3, 0x0B7, 0x0DB, 0x0E1, - 0x0F5, 0x019, 0x025, 0x02D, 0x04B, 0x053, 0x05D, 0x06F, 0x073, 0x07F, 0x011, 0x015, - 0x027, 0x02B, 0x035, 0x03B, 0x005, 0x011, 0x019, 0x007 - }; - - private static readonly byte[] SpectrumB74Bits = - { - 03, 04, 05, 05, 05, 05, 06, 06, 06, 06, 06, 06, 07, 07, 07, 07, - 07, 07, 07, 07, 08, 08, 08, 08, 08, 08, 08, 08, 08, 09, 09, 09, - 08, 08, 08, 08, 08, 09, 09, 09, 09, 09, 09, 09, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 00, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 09, 09, 09, 09, 09, 09, 09, 08, 08, 08, 08, - 08, 09, 09, 09, 08, 08, 08, 08, 08, 08, 08, 08, 08, 07, 07, 07, - 07, 07, 07, 07, 07, 06, 06, 06, 06, 06, 06, 05, 05, 05, 05, 04 - }; - - private static readonly short[] SpectrumB74Codes = - { - 0x001, 0x008, 0x01E, 0x018, 0x00C, 0x002, 0x03A, 0x034, 0x02C, 0x01E, 0x016, 0x012, - 0x072, 0x06E, 0x05E, 0x056, 0x050, 0x038, 0x022, 0x004, 0x0E2, 0x0DA, 0x0BA, 0x0A8, - 0x076, 0x054, 0x050, 0x002, 0x000, 0x1C0, 0x1B0, 0x156, 0x0A4, 0x0A6, 0x074, 0x052, - 0x004, 0x1C2, 0x1B2, 0x170, 0x154, 0x0AE, 0x0AC, 0x086, 0x2E6, 0x2E4, 0x10A, 0x108, - 0x106, 0x104, 0x102, 0x100, 0x03E, 0x03A, 0x03C, 0x038, 0x036, 0x034, 0x032, 0x030, - 0x01E, 0x01A, 0x01C, 0x018, 0x000, 0x019, 0x01D, 0x01B, 0x01F, 0x031, 0x033, 0x035, - 0x037, 0x039, 0x03D, 0x03B, 0x03F, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x2E5, - 0x2E7, 0x087, 0x0AD, 0x0AF, 0x155, 0x171, 0x1B3, 0x1C3, 0x005, 0x053, 0x075, 0x0A7, - 0x0A5, 0x157, 0x1B1, 0x1C1, 0x001, 0x003, 0x051, 0x055, 0x077, 0x0A9, 0x0BB, 0x0DB, - 0x0E3, 0x005, 0x023, 0x039, 0x051, 0x057, 0x05F, 0x06F, 0x073, 0x013, 0x017, 0x01F, - 0x02D, 0x035, 0x03B, 0x003, 0x00D, 0x019, 0x01F, 0x009 - }; - - public static readonly byte[][] HuffmanScaleFactorsABits = - { - null, - ScaleFactorsA1Bits, ScaleFactorsA2Bits, ScaleFactorsA3Bits, - ScaleFactorsA4Bits, ScaleFactorsA5Bits, ScaleFactorsA6Bits - }; - - public static readonly short[][] HuffmanScaleFactorsACodes = - { - null, - ScaleFactorsA1Codes, ScaleFactorsA2Codes, ScaleFactorsA3Codes, - ScaleFactorsA4Codes, ScaleFactorsA5Codes, ScaleFactorsA6Codes - }; - - public static readonly byte[][] HuffmanScaleFactorsBBits = - { - null, null, - ScaleFactorsB2Bits, ScaleFactorsB3Bits, ScaleFactorsB4Bits, ScaleFactorsB5Bits - }; - - public static readonly short[][] HuffmanScaleFactorsBCodes = - { - null, null, - ScaleFactorsB2Codes, ScaleFactorsB3Codes, ScaleFactorsB4Codes, ScaleFactorsB5Codes - }; - - public static readonly byte[] HuffmanScaleFactorsGroupSizes = { 0, 0, 0, 0, 0, 0, 0 }; - - public static readonly byte[][][] HuffmanSpectrumABits = - { - null, - null, - new[] {SpectrumA21Bits, SpectrumA22Bits, SpectrumA23Bits, SpectrumA24Bits}, - new[] {SpectrumA31Bits, SpectrumA32Bits, SpectrumA33Bits, SpectrumA34Bits}, - new[] {SpectrumA41Bits, SpectrumA42Bits, SpectrumA43Bits, SpectrumA44Bits}, - new[] {SpectrumA51Bits, SpectrumA52Bits, SpectrumA53Bits, SpectrumA54Bits}, - new[] {SpectrumA61Bits, SpectrumA62Bits, SpectrumA63Bits, SpectrumA64Bits}, - new[] {SpectrumA71Bits, SpectrumA72Bits, SpectrumA73Bits, SpectrumA74Bits} - }; - - public static readonly short[][][] HuffmanSpectrumACodes = - { - null, - null, - new[] {SpectrumA21Codes, SpectrumA22Codes, SpectrumA23Codes, SpectrumA24Codes}, - new[] {SpectrumA31Codes, SpectrumA32Codes, SpectrumA33Codes, SpectrumA34Codes}, - new[] {SpectrumA41Codes, SpectrumA42Codes, SpectrumA43Codes, SpectrumA44Codes}, - new[] {SpectrumA51Codes, SpectrumA52Codes, SpectrumA53Codes, SpectrumA54Codes}, - new[] {SpectrumA61Codes, SpectrumA62Codes, SpectrumA63Codes, SpectrumA64Codes}, - new[] {SpectrumA71Codes, SpectrumA72Codes, SpectrumA73Codes, SpectrumA74Codes} - }; - - public static readonly byte[][] HuffmanSpectrumAGroupSizes = - { - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {1, 2, 2, 2}, - new byte[] {1, 1, 1, 1}, - new byte[] {1, 1, 1, 1}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0} - }; - - public static readonly byte[][][] HuffmanSpectrumBBits = - { - null, - null, - new[] {null, SpectrumB22Bits, SpectrumB23Bits, SpectrumB24Bits}, - new[] {null, SpectrumB32Bits, SpectrumB33Bits, SpectrumB34Bits}, - new[] {null, SpectrumB42Bits, SpectrumB43Bits, SpectrumB44Bits}, - new[] {null, SpectrumB52Bits, SpectrumB53Bits, SpectrumB54Bits}, - new[] {null, SpectrumB62Bits, SpectrumB63Bits, SpectrumB64Bits}, - new[] {null, SpectrumB72Bits, SpectrumB73Bits, SpectrumB74Bits} - }; - - public static readonly short[][][] HuffmanSpectrumBCodes = - { - null, - null, - new[] {null, SpectrumB22Codes, SpectrumB23Codes, SpectrumB24Codes}, - new[] {null, SpectrumB32Codes, SpectrumB33Codes, SpectrumB34Codes}, - new[] {null, SpectrumB42Codes, SpectrumB43Codes, SpectrumB44Codes}, - new[] {null, SpectrumB52Codes, SpectrumB53Codes, SpectrumB54Codes}, - new[] {null, SpectrumB62Codes, SpectrumB63Codes, SpectrumB64Codes}, - new[] {null, SpectrumB72Codes, SpectrumB73Codes, SpectrumB74Codes} - }; - - public static readonly byte[][] HuffmanSpectrumBGroupSizes = - { - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 2, 2, 2}, - new byte[] {0, 1, 1, 1}, - new byte[] {0, 1, 1, 1}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0}, - new byte[] {0, 0, 0, 0} - }; - } -} \ No newline at end of file diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/LibAtrac9.csproj b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/LibAtrac9.csproj deleted file mode 100644 index 39fc3c8d4..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/LibAtrac9.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - netstandard1.0 - true - - - diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Quantization.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Quantization.cs deleted file mode 100644 index beb3d7d82..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Quantization.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; - -namespace LibAtrac9 -{ - internal static class Quantization - { - public static void DequantizeSpectra(Block block) - { - foreach (Channel channel in block.Channels) - { - Array.Clear(channel.Spectra, 0, channel.Spectra.Length); - - for (int i = 0; i < channel.CodedQuantUnits; i++) - { - DequantizeQuantUnit(channel, i); - } - } - } - - private static void DequantizeQuantUnit(Channel channel, int band) - { - int subBandIndex = Tables.QuantUnitToCoeffIndex[band]; - int subBandCount = Tables.QuantUnitToCoeffCount[band]; - double stepSize = Tables.QuantizerStepSize[channel.Precisions[band]]; - double stepSizeFine = Tables.QuantizerFineStepSize[channel.PrecisionsFine[band]]; - - for (int sb = 0; sb < subBandCount; sb++) - { - double coarse = channel.QuantizedSpectra[subBandIndex + sb] * stepSize; - double fine = channel.QuantizedSpectraFine[subBandIndex + sb] * stepSizeFine; - channel.Spectra[subBandIndex + sb] = coarse + fine; - } - } - - public static void ScaleSpectrum(Block block) - { - foreach (Channel channel in block.Channels) - { - ScaleSpectrum(channel); - } - } - - private static void ScaleSpectrum(Channel channel) - { - int quantUnitCount = channel.Block.QuantizationUnitCount; - double[] spectra = channel.Spectra; - - for (int i = 0; i < quantUnitCount; i++) - { - for (int sb = Tables.QuantUnitToCoeffIndex[i]; sb < Tables.QuantUnitToCoeffIndex[i + 1]; sb++) - { - spectra[sb] *= Tables.SpectrumScale[channel.ScaleFactors[i]]; - } - } - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/ScaleFactors.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/ScaleFactors.cs deleted file mode 100644 index 55634a993..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/ScaleFactors.cs +++ /dev/null @@ -1,171 +0,0 @@ -using System; -using System.IO; -using LibAtrac9.Utilities; - -namespace LibAtrac9 -{ - internal static class ScaleFactors - { - public static void Read(BitReader reader, Channel channel) - { - Array.Clear(channel.ScaleFactors, 0, channel.ScaleFactors.Length); - - channel.ScaleFactorCodingMode = reader.ReadInt(2); - if (channel.ChannelIndex == 0) - { - switch (channel.ScaleFactorCodingMode) - { - case 0: - ReadVlcDeltaOffset(reader, channel); - break; - case 1: - ReadClcOffset(reader, channel); - break; - case 2: - if (channel.Block.FirstInSuperframe) throw new InvalidDataException(); - ReadVlcDistanceToBaseline(reader, channel, channel.ScaleFactorsPrev, channel.Block.QuantizationUnitsPrev); - break; - case 3: - if (channel.Block.FirstInSuperframe) throw new InvalidDataException(); - ReadVlcDeltaOffsetWithBaseline(reader, channel, channel.ScaleFactorsPrev, channel.Block.QuantizationUnitsPrev); - break; - } - } - else - { - switch (channel.ScaleFactorCodingMode) - { - case 0: - ReadVlcDeltaOffset(reader, channel); - break; - case 1: - ReadVlcDistanceToBaseline(reader, channel, channel.Block.Channels[0].ScaleFactors, channel.Block.ExtensionUnit); - break; - case 2: - ReadVlcDeltaOffsetWithBaseline(reader, channel, channel.Block.Channels[0].ScaleFactors, channel.Block.ExtensionUnit); - break; - case 3: - if (channel.Block.FirstInSuperframe) throw new InvalidDataException(); - ReadVlcDistanceToBaseline(reader, channel, channel.ScaleFactorsPrev, channel.Block.QuantizationUnitsPrev); - break; - } - } - - for (int i = 0; i < channel.Block.ExtensionUnit; i++) - { - if (channel.ScaleFactors[i] < 0 || channel.ScaleFactors[i] > 31) - { - throw new InvalidDataException("Scale factor values are out of range."); - } - } - - Array.Copy(channel.ScaleFactors, channel.ScaleFactorsPrev, channel.ScaleFactors.Length); - } - - private static void ReadClcOffset(BitReader reader, Channel channel) - { - const int maxBits = 5; - int[] sf = channel.ScaleFactors; - int bitLength = reader.ReadInt(2) + 2; - int baseValue = bitLength < maxBits ? reader.ReadInt(maxBits) : 0; - - for (int i = 0; i < channel.Block.ExtensionUnit; i++) - { - sf[i] = reader.ReadInt(bitLength) + baseValue; - } - } - - private static void ReadVlcDeltaOffset(BitReader reader, Channel channel) - { - int weightIndex = reader.ReadInt(3); - byte[] weights = ScaleFactorWeights[weightIndex]; - - int[] sf = channel.ScaleFactors; - int baseValue = reader.ReadInt(5); - int bitLength = reader.ReadInt(2) + 3; - HuffmanCodebook codebook = Tables.HuffmanScaleFactorsUnsigned[bitLength]; - - sf[0] = reader.ReadInt(bitLength); - - for (int i = 1; i < channel.Block.ExtensionUnit; i++) - { - int delta = Unpack.ReadHuffmanValue(codebook, reader); - sf[i] = (sf[i - 1] + delta) & (codebook.ValueMax - 1); - } - - for (int i = 0; i < channel.Block.ExtensionUnit; i++) - { - sf[i] += baseValue - weights[i]; - } - } - - private static void ReadVlcDistanceToBaseline(BitReader reader, Channel channel, int[] baseline, int baselineLength) - { - int[] sf = channel.ScaleFactors; - int bitLength = reader.ReadInt(2) + 2; - HuffmanCodebook codebook = Tables.HuffmanScaleFactorsSigned[bitLength]; - int unitCount = Math.Min(channel.Block.ExtensionUnit, baselineLength); - - for (int i = 0; i < unitCount; i++) - { - int distance = Unpack.ReadHuffmanValue(codebook, reader, true); - sf[i] = (baseline[i] + distance) & 31; - } - - for (int i = unitCount; i < channel.Block.ExtensionUnit; i++) - { - sf[i] = reader.ReadInt(5); - } - } - - private static void ReadVlcDeltaOffsetWithBaseline(BitReader reader, Channel channel, int[] baseline, int baselineLength) - { - int[] sf = channel.ScaleFactors; - int baseValue = reader.ReadOffsetBinary(5, BitReader.OffsetBias.Negative); - int bitLength = reader.ReadInt(2) + 1; - HuffmanCodebook codebook = Tables.HuffmanScaleFactorsUnsigned[bitLength]; - int unitCount = Math.Min(channel.Block.ExtensionUnit, baselineLength); - - sf[0] = reader.ReadInt(bitLength); - - for (int i = 1; i < unitCount; i++) - { - int delta = Unpack.ReadHuffmanValue(codebook, reader); - sf[i] = (sf[i - 1] + delta) & (codebook.ValueMax - 1); - } - - for (int i = 0; i < unitCount; i++) - { - sf[i] += baseValue + baseline[i]; - } - - for (int i = unitCount; i < channel.Block.ExtensionUnit; i++) - { - sf[i] = reader.ReadInt(5); - } - } - - public static readonly byte[][] ScaleFactorWeights = - { - new byte[] { - 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 10, 12, 12, 12 - }, new byte[] { - 3, 2, 2, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 5, 7, 10, 10, 10 - }, new byte[] { - 0, 2, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 9, 12, 12, 12 - }, new byte[] { - 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 8, 8, 10, 11, 11, 12, 13, 13, 13, 13 - }, new byte[] { - 0, 2, 2, 3, 3, 4, 4, 5, 4, 5, 5, 5, 5, 6, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 11, 12, 12, 13, 13, 14, 14, 14 - }, new byte[] { - 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 7, 7, 9, 11, 11, 11 - }, new byte[] { - 0, 5, 8, 10, 11, 11, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, - 12, 13, 15, 15, 15 - }, new byte[] { - 0, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, - 15, 15, 15 - } - }; - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Stereo.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Stereo.cs deleted file mode 100644 index a7ebdaf67..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Stereo.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace LibAtrac9 -{ - internal static class Stereo - { - public static void ApplyIntensityStereo(Block block) - { - if (block.BlockType != BlockType.Stereo) return; - - int totalUnits = block.QuantizationUnitCount; - int stereoUnits = block.StereoQuantizationUnit; - if (stereoUnits >= totalUnits) return; - - Channel source = block.PrimaryChannel; - Channel dest = block.SecondaryChannel; - - for (int i = stereoUnits; i < totalUnits; i++) - { - int sign = block.JointStereoSigns[i]; - for (int sb = Tables.QuantUnitToCoeffIndex[i]; sb < Tables.QuantUnitToCoeffIndex[i + 1]; sb++) - { - if (sign > 0) - { - dest.Spectra[sb] = -source.Spectra[sb]; - } - else - { - dest.Spectra[sb] = source.Spectra[sb]; - } - } - } - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Tables.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Tables.cs deleted file mode 100644 index 150759c02..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Tables.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using static LibAtrac9.HuffmanCodebooks; - -namespace LibAtrac9 -{ - internal static class Tables - { - public static int MaxHuffPrecision(bool highSampleRate) => highSampleRate ? 1 : 7; - public static int MinBandCount(bool highSampleRate) => highSampleRate ? 1 : 3; - public static int MaxExtensionBand(bool highSampleRate) => highSampleRate ? 16 : 18; - - public static readonly int[] SampleRates = - { - 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, - 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 - }; - - public static readonly byte[] SamplingRateIndexToFrameSamplesPower = { 6, 6, 7, 7, 7, 8, 8, 8, 6, 6, 7, 7, 7, 8, 8, 8 }; - - // From sampling rate index - public static readonly byte[] MaxBandCount = { 8, 8, 12, 12, 12, 18, 18, 18, 8, 8, 12, 12, 12, 16, 16, 16 }; - public static readonly byte[] BandToQuantUnitCount = { 0, 4, 8, 10, 12, 13, 14, 15, 16, 18, 20, 21, 22, 23, 24, 25, 26, 28, 30 }; - - public static readonly byte[] QuantUnitToCoeffCount = - { - 02, 02, 02, 02, 02, 02, 02, 02, 04, 04, 04, 04, 08, 08, 08, - 08, 08, 08, 08, 08, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 - }; - - public static readonly short[] QuantUnitToCoeffIndex = - { - 0, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, - 64, 72, 80, 88, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256 - }; - - public static readonly byte[] QuantUnitToCodebookIndex = - { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 - }; - - public static readonly ChannelConfig[] ChannelConfig = - { - new ChannelConfig(BlockType.Mono), - new ChannelConfig(BlockType.Mono, BlockType.Mono), - new ChannelConfig(BlockType.Stereo), - new ChannelConfig(BlockType.Stereo, BlockType.Mono, BlockType.LFE, BlockType.Stereo), - new ChannelConfig(BlockType.Stereo, BlockType.Mono, BlockType.LFE, BlockType.Stereo, BlockType.Stereo), - new ChannelConfig(BlockType.Stereo, BlockType.Stereo) - }; - - public static readonly HuffmanCodebook[] HuffmanScaleFactorsUnsigned = - GenerateHuffmanCodebooks(HuffmanScaleFactorsACodes, HuffmanScaleFactorsABits, HuffmanScaleFactorsGroupSizes); - - public static readonly HuffmanCodebook[] HuffmanScaleFactorsSigned = - GenerateHuffmanCodebooks(HuffmanScaleFactorsBCodes, HuffmanScaleFactorsBBits, HuffmanScaleFactorsGroupSizes); - - public static readonly HuffmanCodebook[][][] HuffmanSpectrum = - { - GenerateHuffmanCodebooks(HuffmanSpectrumACodes, HuffmanSpectrumABits, HuffmanSpectrumAGroupSizes), - GenerateHuffmanCodebooks(HuffmanSpectrumBCodes, HuffmanSpectrumBBits, HuffmanSpectrumBGroupSizes) - }; - - public static readonly double[][] ImdctWindow = { GenerateImdctWindow(6), GenerateImdctWindow(7), GenerateImdctWindow(8) }; - - public static readonly double[] SpectrumScale = Generate(32, SpectrumScaleFunction); - public static readonly double[] QuantizerStepSize = Generate(16, QuantizerStepSizeFunction); - public static readonly double[] QuantizerFineStepSize = Generate(16, QuantizerFineStepSizeFunction); - - public static readonly byte[][] GradientCurves = BitAllocation.GenerateGradientCurves(); - - private static double QuantizerStepSizeFunction(int x) => 2.0 / ((1 << (x + 1)) - 1); - private static double QuantizerFineStepSizeFunction(int x) => QuantizerStepSizeFunction(x) / ushort.MaxValue; - private static double SpectrumScaleFunction(int x) => Math.Pow(2, x - 15); - - private static double[] GenerateImdctWindow(int frameSizePower) - { - int frameSize = 1 << frameSizePower; - var output = new double[frameSize]; - - double[] a1 = GenerateMdctWindow(frameSizePower); - - for (int i = 0; i < frameSize; i++) - { - output[i] = a1[i] / (a1[frameSize - 1 - i] * a1[frameSize - 1 - i] + a1[i] * a1[i]); - } - return output; - } - - private static double[] GenerateMdctWindow(int frameSizePower) - { - int frameSize = 1 << frameSizePower; - var output = new double[frameSize]; - - for (int i = 0; i < frameSize; i++) - { - output[i] = (Math.Sin(((i + 0.5) / frameSize - 0.5) * Math.PI) + 1.0) * 0.5; - } - - return output; - } - - private static T[] Generate(int count, Func elementGenerator) - { - var table = new T[count]; - for (int i = 0; i < count; i++) - { - table[i] = elementGenerator(i); - } - return table; - } - - - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Unpack.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Unpack.cs deleted file mode 100644 index 29c25fe0c..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Unpack.cs +++ /dev/null @@ -1,425 +0,0 @@ -using System; -using System.IO; -using LibAtrac9.Utilities; - -namespace LibAtrac9 -{ - internal static class Unpack - { - public static void UnpackFrame(BitReader reader, Frame frame) - { - foreach (Block block in frame.Blocks) - { - UnpackBlock(reader, block); - } - } - - private static void UnpackBlock(BitReader reader, Block block) - { - ReadBlockHeader(reader, block); - - if (block.BlockType == BlockType.LFE) - { - UnpackLfeBlock(reader, block); - } - else - { - UnpackStandardBlock(reader, block); - } - - reader.AlignPosition(8); - } - - private static void ReadBlockHeader(BitReader reader, Block block) - { - bool firstInSuperframe = block.Frame.FrameIndex == 0; - block.FirstInSuperframe = !reader.ReadBool(); - block.ReuseBandParams = reader.ReadBool(); - - if (block.FirstInSuperframe != firstInSuperframe) - { - throw new InvalidDataException(); - } - - if (firstInSuperframe && block.ReuseBandParams && block.BlockType != BlockType.LFE) - { - throw new InvalidDataException(); - } - } - - private static void UnpackStandardBlock(BitReader reader, Block block) - { - Channel[] channels = block.Channels; - - if (!block.ReuseBandParams) - { - ReadBandParams(reader, block); - } - - ReadGradientParams(reader, block); - BitAllocation.CreateGradient(block); - ReadStereoParams(reader, block); - ReadExtensionParams(reader, block); - - foreach (Channel channel in channels) - { - channel.UpdateCodedUnits(); - - ScaleFactors.Read(reader, channel); - BitAllocation.CalculateMask(channel); - BitAllocation.CalculatePrecisions(channel); - CalculateSpectrumCodebookIndex(channel); - - ReadSpectra(reader, channel); - ReadSpectraFine(reader, channel); - } - - block.QuantizationUnitsPrev = block.BandExtensionEnabled ? block.ExtensionUnit : block.QuantizationUnitCount; - } - - private static void ReadBandParams(BitReader reader, Block block) - { - int minBandCount = Tables.MinBandCount(block.Config.HighSampleRate); - int maxExtensionBand = Tables.MaxExtensionBand(block.Config.HighSampleRate); - block.BandCount = reader.ReadInt(4); - block.BandCount += minBandCount; - block.QuantizationUnitCount = Tables.BandToQuantUnitCount[block.BandCount]; - if (block.BandCount < minBandCount || block.BandCount > - Tables.MaxBandCount[block.Config.SampleRateIndex]) - { - return; - } - - if (block.BlockType == BlockType.Stereo) - { - block.StereoBand = reader.ReadInt(4); - block.StereoBand += minBandCount; - block.StereoQuantizationUnit = Tables.BandToQuantUnitCount[block.StereoBand]; - } - else - { - block.StereoBand = block.BandCount; - } - - block.BandExtensionEnabled = reader.ReadBool(); - if (block.BandExtensionEnabled) - { - block.ExtensionBand = reader.ReadInt(4); - block.ExtensionBand += minBandCount; - - if (block.ExtensionBand < block.BandCount || block.ExtensionBand > maxExtensionBand) - { - throw new InvalidDataException(); - } - - block.ExtensionUnit = Tables.BandToQuantUnitCount[block.ExtensionBand]; - } - else - { - block.ExtensionBand = block.BandCount; - block.ExtensionUnit = block.QuantizationUnitCount; - } - } - - private static void ReadGradientParams(BitReader reader, Block block) - { - block.GradientMode = reader.ReadInt(2); - if (block.GradientMode > 0) - { - block.GradientEndUnit = 31; - block.GradientEndValue = 31; - block.GradientStartUnit = reader.ReadInt(5); - block.GradientStartValue = reader.ReadInt(5); - } - else - { - block.GradientStartUnit = reader.ReadInt(6); - block.GradientEndUnit = reader.ReadInt(6) + 1; - block.GradientStartValue = reader.ReadInt(5); - block.GradientEndValue = reader.ReadInt(5); - } - block.GradientBoundary = reader.ReadInt(4); - - if (block.GradientBoundary > block.QuantizationUnitCount) - { - throw new InvalidDataException(); - } - if (block.GradientStartUnit < 1 || block.GradientStartUnit >= 48) - { - throw new InvalidDataException(); - } - if (block.GradientEndUnit < 1 || block.GradientEndUnit >= 48) - { - throw new InvalidDataException(); - } - if (block.GradientStartUnit > block.GradientEndUnit) - { - throw new InvalidDataException(); - } - if (block.GradientStartValue < 0 || block.GradientStartValue >= 32) - { - throw new InvalidDataException(); - } - if (block.GradientEndValue < 0 || block.GradientEndValue >= 32) - { - throw new InvalidDataException(); - } - } - - private static void ReadStereoParams(BitReader reader, Block block) - { - if (block.BlockType != BlockType.Stereo) return; - - block.PrimaryChannelIndex = reader.ReadInt(1); - block.HasJointStereoSigns = reader.ReadBool(); - if (block.HasJointStereoSigns) - { - for (int i = block.StereoQuantizationUnit; i < block.QuantizationUnitCount; i++) - { - block.JointStereoSigns[i] = reader.ReadInt(1); - } - } - else - { - Array.Clear(block.JointStereoSigns, 0, block.JointStereoSigns.Length); - } - } - - private static void ReadExtensionParams(BitReader reader, Block block) - { - // ReSharper disable once RedundantAssignment - int bexBand = 0; - if (block.BandExtensionEnabled) - { - BandExtension.GetBexBandInfo(out bexBand, out _, out _, block.QuantizationUnitCount); - if (block.BlockType == BlockType.Stereo) - { - ReadHeader(block.Channels[1]); - } - else - { - reader.Position += 1; - } - } - block.HasExtensionData = reader.ReadBool(); - - if (!block.HasExtensionData) return; - if (!block.BandExtensionEnabled) - { - block.BexMode = reader.ReadInt(2); - block.BexDataLength = reader.ReadInt(5); - reader.Position += block.BexDataLength; - return; - } - - ReadHeader(block.Channels[0]); - - block.BexDataLength = reader.ReadInt(5); - if (block.BexDataLength <= 0) return; - int bexDataEnd = reader.Position + block.BexDataLength; - - ReadData(block.Channels[0]); - - if (block.BlockType == BlockType.Stereo) - { - ReadData(block.Channels[1]); - } - - // Make sure we didn't read too many bits - if (reader.Position > bexDataEnd) - { - throw new InvalidDataException(); - } - - void ReadHeader(Channel channel) - { - int bexMode = reader.ReadInt(2); - channel.BexMode = bexBand > 2 ? bexMode : 4; - channel.BexValueCount = BandExtension.BexEncodedValueCounts[channel.BexMode][bexBand]; - } - - void ReadData(Channel channel) - { - for (int i = 0; i < channel.BexValueCount; i++) - { - int dataLength = BandExtension.BexDataLengths[channel.BexMode][bexBand][i]; - channel.BexValues[i] = reader.ReadInt(dataLength); - } - } - } - - private static void CalculateSpectrumCodebookIndex(Channel channel) - { - Array.Clear(channel.CodebookSet, 0, channel.CodebookSet.Length); - int quantUnits = channel.CodedQuantUnits; - int[] sf = channel.ScaleFactors; - - if (quantUnits <= 1) return; - if (channel.Config.HighSampleRate) return; - - // Temporarily setting this value allows for simpler code by - // making the last value a non-special case. - int originalScaleTmp = sf[quantUnits]; - sf[quantUnits] = sf[quantUnits - 1]; - - int avg = 0; - if (quantUnits > 12) - { - for (int i = 0; i < 12; i++) - { - avg += sf[i]; - } - avg = (avg + 6) / 12; - } - - for (int i = 8; i < quantUnits; i++) - { - int prevSf = sf[i - 1]; - int nextSf = sf[i + 1]; - int minSf = Math.Min(prevSf, nextSf); - if (sf[i] - minSf >= 3 || sf[i] - prevSf + sf[i] - nextSf >= 3) - { - channel.CodebookSet[i] = 1; - } - } - - for (int i = 12; i < quantUnits; i++) - { - if (channel.CodebookSet[i] == 0) - { - int minSf = Math.Min(sf[i - 1], sf[i + 1]); - if (sf[i] - minSf >= 2 && sf[i] >= avg - (Tables.QuantUnitToCoeffCount[i] == 16 ? 1 : 0)) - { - channel.CodebookSet[i] = 1; - } - } - } - - sf[quantUnits] = originalScaleTmp; - } - - private static void ReadSpectra(BitReader reader, Channel channel) - { - int[] values = channel.SpectraValuesBuffer; - Array.Clear(channel.QuantizedSpectra, 0, channel.QuantizedSpectra.Length); - int maxHuffPrecision = Tables.MaxHuffPrecision(channel.Config.HighSampleRate); - - for (int i = 0; i < channel.CodedQuantUnits; i++) - { - int subbandCount = Tables.QuantUnitToCoeffCount[i]; - int precision = channel.Precisions[i] + 1; - if (precision <= maxHuffPrecision) - { - HuffmanCodebook huff = Tables.HuffmanSpectrum[channel.CodebookSet[i]][precision][Tables.QuantUnitToCodebookIndex[i]]; - int groupCount = subbandCount >> huff.ValueCountPower; - for (int j = 0; j < groupCount; j++) - { - values[j] = ReadHuffmanValue(huff, reader); - } - - DecodeHuffmanValues(channel.QuantizedSpectra, Tables.QuantUnitToCoeffIndex[i], subbandCount, huff, values); - } - else - { - int subbandIndex = Tables.QuantUnitToCoeffIndex[i]; - for (int j = subbandIndex; j < Tables.QuantUnitToCoeffIndex[i + 1]; j++) - { - channel.QuantizedSpectra[j] = reader.ReadSignedInt(precision); - } - } - } - } - - private static void ReadSpectraFine(BitReader reader, Channel channel) - { - Array.Clear(channel.QuantizedSpectraFine, 0, channel.QuantizedSpectraFine.Length); - - for (int i = 0; i < channel.CodedQuantUnits; i++) - { - if (channel.PrecisionsFine[i] > 0) - { - int overflowBits = channel.PrecisionsFine[i] + 1; - int startSubband = Tables.QuantUnitToCoeffIndex[i]; - int endSubband = Tables.QuantUnitToCoeffIndex[i + 1]; - - for (int j = startSubband; j < endSubband; j++) - { - channel.QuantizedSpectraFine[j] = reader.ReadSignedInt(overflowBits); - } - } - } - } - - private static void DecodeHuffmanValues(int[] spectrum, int index, int bandCount, HuffmanCodebook huff, int[] values) - { - int valueCount = bandCount >> huff.ValueCountPower; - int mask = (1 << huff.ValueBits) - 1; - - for (int i = 0; i < valueCount; i++) - { - int value = values[i]; - for (int j = 0; j < huff.ValueCount; j++) - { - spectrum[index++] = Bit.SignExtend32(value & mask, huff.ValueBits); - value >>= huff.ValueBits; - } - } - } - - public static int ReadHuffmanValue(HuffmanCodebook huff, BitReader reader, bool signed = false) - { - int code = reader.PeekInt(huff.MaxBitSize); - byte value = huff.Lookup[code]; - int bits = huff.Bits[value]; - reader.Position += bits; - return signed ? Bit.SignExtend32(value, huff.ValueBits) : value; - } - - private static void UnpackLfeBlock(BitReader reader, Block block) - { - Channel channel = block.Channels[0]; - block.QuantizationUnitCount = 2; - - DecodeLfeScaleFactors(reader, channel); - CalculateLfePrecision(channel); - channel.CodedQuantUnits = block.QuantizationUnitCount; - ReadLfeSpectra(reader, channel); - } - - private static void DecodeLfeScaleFactors(BitReader reader, Channel channel) - { - Array.Clear(channel.ScaleFactors, 0, channel.ScaleFactors.Length); - for (int i = 0; i < channel.Block.QuantizationUnitCount; i++) - { - channel.ScaleFactors[i] = reader.ReadInt(5); - } - } - - private static void CalculateLfePrecision(Channel channel) - { - Block block = channel.Block; - int precision = block.ReuseBandParams ? 8 : 4; - for (int i = 0; i < block.QuantizationUnitCount; i++) - { - channel.Precisions[i] = precision; - channel.PrecisionsFine[i] = 0; - } - } - - private static void ReadLfeSpectra(BitReader reader, Channel channel) - { - Array.Clear(channel.QuantizedSpectra, 0, channel.QuantizedSpectra.Length); - - for (int i = 0; i < channel.CodedQuantUnits; i++) - { - if (channel.Precisions[i] <= 0) continue; - - int precision = channel.Precisions[i] + 1; - for (int j = Tables.QuantUnitToCoeffIndex[i]; j < Tables.QuantUnitToCoeffIndex[i + 1]; j++) - { - channel.QuantizedSpectra[j] = reader.ReadSignedInt(precision); - } - } - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/Bit.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/Bit.cs deleted file mode 100644 index f8ff07946..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/Bit.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace LibAtrac9.Utilities -{ - internal static class Bit - { - private static uint BitReverse32(uint value) - { - value = ((value & 0xaaaaaaaa) >> 1) | ((value & 0x55555555) << 1); - value = ((value & 0xcccccccc) >> 2) | ((value & 0x33333333) << 2); - value = ((value & 0xf0f0f0f0) >> 4) | ((value & 0x0f0f0f0f) << 4); - value = ((value & 0xff00ff00) >> 8) | ((value & 0x00ff00ff) << 8); - return (value >> 16) | (value << 16); - } - private static uint BitReverse32(uint value, int bitCount) => BitReverse32(value) >> (32 - bitCount); - public static int BitReverse32(int value, int bitCount) => (int) BitReverse32((uint) value, bitCount); - - public static int SignExtend32(int value, int bits) - { - int shift = 8 * sizeof(int) - bits; - return (value << shift) >> shift; - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/BitReader.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/BitReader.cs deleted file mode 100644 index b89d9d765..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/BitReader.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Diagnostics; - -namespace LibAtrac9.Utilities -{ - internal class BitReader - { - private byte[] Buffer { get; set; } - private int LengthBits { get; set; } - public int Position { get; set; } - private int Remaining => LengthBits - Position; - - public BitReader(byte[] buffer) => SetBuffer(buffer); - - public void SetBuffer(byte[] buffer) - { - Buffer = buffer; - LengthBits = Buffer?.Length * 8 ?? 0; - Position = 0; - } - - public int ReadInt(int bitCount) - { - int value = PeekInt(bitCount); - Position += bitCount; - return value; - } - - public int ReadSignedInt(int bitCount) - { - int value = PeekInt(bitCount); - Position += bitCount; - return Bit.SignExtend32(value, bitCount); - } - - public bool ReadBool() => ReadInt(1) == 1; - - public int ReadOffsetBinary(int bitCount, OffsetBias bias) - { - int offset = (1 << (bitCount - 1)) - (int)bias; - int value = PeekInt(bitCount) - offset; - Position += bitCount; - return value; - } - - public void AlignPosition(int multiple) - { - Position = Helpers.GetNextMultiple(Position, multiple); - } - - public int PeekInt(int bitCount) - { - Debug.Assert(bitCount >= 0 && bitCount <= 32); - - if (bitCount > Remaining) - { - if (Position >= LengthBits) return 0; - - int extraBits = bitCount - Remaining; - return PeekIntFallback(Remaining) << extraBits; - } - - int byteIndex = Position / 8; - int bitIndex = Position % 8; - - if (bitCount <= 9 && Remaining >= 16) - { - int value = Buffer[byteIndex] << 8 | Buffer[byteIndex + 1]; - value &= 0xFFFF >> bitIndex; - value >>= 16 - bitCount - bitIndex; - return value; - } - - if (bitCount <= 17 && Remaining >= 24) - { - int value = Buffer[byteIndex] << 16 | Buffer[byteIndex + 1] << 8 | Buffer[byteIndex + 2]; - value &= 0xFFFFFF >> bitIndex; - value >>= 24 - bitCount - bitIndex; - return value; - } - - if (bitCount <= 25 && Remaining >= 32) - { - int value = Buffer[byteIndex] << 24 | Buffer[byteIndex + 1] << 16 | Buffer[byteIndex + 2] << 8 | Buffer[byteIndex + 3]; - value &= (int)(0xFFFFFFFF >> bitIndex); - value >>= 32 - bitCount - bitIndex; - return value; - } - return PeekIntFallback(bitCount); - } - - private int PeekIntFallback(int bitCount) - { - int value = 0; - int byteIndex = Position / 8; - int bitIndex = Position % 8; - - while (bitCount > 0) - { - if (bitIndex >= 8) - { - bitIndex = 0; - byteIndex++; - } - - int bitsToRead = Math.Min(bitCount, 8 - bitIndex); - int mask = 0xFF >> bitIndex; - int currentByte = (mask & Buffer[byteIndex]) >> (8 - bitIndex - bitsToRead); - - value = (value << bitsToRead) | currentByte; - bitIndex += bitsToRead; - bitCount -= bitsToRead; - } - return value; - } - - /// - /// Specifies the bias of an offset binary value. A positive bias can represent one more - /// positive value than negative value, and a negative bias can represent one more - /// negative value than positive value. - /// - /// Example: - /// A 4-bit offset binary value with a positive bias can store - /// the values 8 through -7 inclusive. - /// A 4-bit offset binary value with a positive bias can store - /// the values 7 through -8 inclusive. - public enum OffsetBias - { - Negative = 0 - } - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/Helpers.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/Helpers.cs deleted file mode 100644 index 24f615ace..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/Helpers.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace LibAtrac9.Utilities -{ - internal static class Helpers - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static short Clamp16(int value) - { - if (value > short.MaxValue) - return short.MaxValue; - if (value < short.MinValue) - return short.MinValue; - return (short)value; - } - - public static int GetNextMultiple(int value, int multiple) - { - if (multiple <= 0) - return value; - - if (value % multiple == 0) - return value; - - return value + multiple - value % multiple; - } - - /// - /// Returns the floor of the base 2 logarithm of a specified number. - /// - /// The number whose logarithm is to be found. - /// The floor of the base 2 logarithm of . - public static int Log2(int value) - { - value |= value >> 1; - value |= value >> 2; - value |= value >> 4; - value |= value >> 8; - value |= value >> 16; - - return MultiplyDeBruijnBitPosition[(uint)(value * 0x07C4ACDDU) >> 27]; - } - - private static readonly int[] MultiplyDeBruijnBitPosition = - { - 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, - 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 - }; - } -} diff --git a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/Mdct.cs b/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/Mdct.cs deleted file mode 100644 index dfc4c1b41..000000000 --- a/Frameworks/libatrac9/libatrac9/LibAtrac9/CSharp/LibAtrac9/Utilities/Mdct.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibAtrac9.Utilities -{ - internal class Mdct - { - private int MdctBits { get; } - private int MdctSize { get; } - private double Scale { get; } - - private static readonly object TableLock = new object(); - private static int _tableBits = -1; - private static readonly List SinTables = new List(); - private static readonly List CosTables = new List(); - private static readonly List ShuffleTables = new List(); - - private readonly double[] _imdctPrevious; - private readonly double[] _imdctWindow; - - private readonly double[] _scratchMdct; - private readonly double[] _scratchDct; - - public Mdct(int mdctBits, double[] window, double scale = 1) - { - SetTables(mdctBits); - - MdctBits = mdctBits; - MdctSize = 1 << mdctBits; - Scale = scale; - - if (window.Length < MdctSize) - { - throw new ArgumentException("Window must be as long as the MDCT size.", nameof(window)); - } - - _imdctPrevious = new double[MdctSize]; - _scratchMdct = new double[MdctSize]; - _scratchDct = new double[MdctSize]; - _imdctWindow = window; - } - - private static void SetTables(int maxBits) - { - lock (TableLock) - { - if (maxBits > _tableBits) - { - for (int i = _tableBits + 1; i <= maxBits; i++) - { - GenerateTrigTables(i, out double[] sin, out double[] cos); - SinTables.Add(sin); - CosTables.Add(cos); - ShuffleTables.Add(GenerateShuffleTable(i)); - } - _tableBits = maxBits; - } - } - } - - public void RunImdct(double[] input, double[] output) - { - if (input.Length < MdctSize) - { - throw new ArgumentException("Input must be as long as the MDCT size.", nameof(input)); - } - - if (output.Length < MdctSize) - { - throw new ArgumentException("Output must be as long as the MDCT size.", nameof(output)); - } - - int size = MdctSize; - int half = size / 2; - double[] dctOut = _scratchMdct; - - Dct4(input, dctOut); - - for (int i = 0; i < half; i++) - { - output[i] = _imdctWindow[i] * dctOut[i + half] + _imdctPrevious[i]; - output[i + half] = _imdctWindow[i + half] * -dctOut[size - 1 - i] - _imdctPrevious[i + half]; - _imdctPrevious[i] = _imdctWindow[size - 1 - i] * -dctOut[half - i - 1]; - _imdctPrevious[i + half] = _imdctWindow[half - i - 1] * dctOut[i]; - } - } - - /// - /// Does a Type-4 DCT. - /// - /// The input array containing the time or frequency-domain samples - /// The output array that will contain the transformed time or frequency-domain samples - private void Dct4(double[] input, double[] output) - { - int[] shuffleTable = ShuffleTables[MdctBits]; - double[] sinTable = SinTables[MdctBits]; - double[] cosTable = CosTables[MdctBits]; - double[] dctTemp = _scratchDct; - - int size = MdctSize; - int lastIndex = size - 1; - int halfSize = size / 2; - - for (int i = 0; i < halfSize; i++) - { - int i2 = i * 2; - double a = input[i2]; - double b = input[lastIndex - i2]; - double sin = sinTable[i]; - double cos = cosTable[i]; - dctTemp[i2] = a * cos + b * sin; - dctTemp[i2 + 1] = a * sin - b * cos; - } - int stageCount = MdctBits - 1; - - for (int stage = 0; stage < stageCount; stage++) - { - int blockCount = 1 << stage; - int blockSizeBits = stageCount - stage; - int blockHalfSizeBits = blockSizeBits - 1; - int blockSize = 1 << blockSizeBits; - int blockHalfSize = 1 << blockHalfSizeBits; - sinTable = SinTables[blockHalfSizeBits]; - cosTable = CosTables[blockHalfSizeBits]; - - for (int block = 0; block < blockCount; block++) - { - for (int i = 0; i < blockHalfSize; i++) - { - int frontPos = (block * blockSize + i) * 2; - int backPos = frontPos + blockSize; - double a = dctTemp[frontPos] - dctTemp[backPos]; - double b = dctTemp[frontPos + 1] - dctTemp[backPos + 1]; - double sin = sinTable[i]; - double cos = cosTable[i]; - dctTemp[frontPos] += dctTemp[backPos]; - dctTemp[frontPos + 1] += dctTemp[backPos + 1]; - dctTemp[backPos] = a * cos + b * sin; - dctTemp[backPos + 1] = a * sin - b * cos; - } - } - } - - for (int i = 0; i < MdctSize; i++) - { - output[i] = dctTemp[shuffleTable[i]] * Scale; - } - } - - internal static void GenerateTrigTables(int sizeBits, out double[] sin, out double[] cos) - { - int size = 1 << sizeBits; - sin = new double[size]; - cos = new double[size]; - - for (int i = 0; i < size; i++) - { - double value = Math.PI * (4 * i + 1) / (4 * size); - sin[i] = Math.Sin(value); - cos[i] = Math.Cos(value); - } - } - - internal static int[] GenerateShuffleTable(int sizeBits) - { - int size = 1 << sizeBits; - var table = new int[size]; - - for (int i = 0; i < size; i++) - { - table[i] = Bit.BitReverse32(i ^ (i / 2), sizeBits); - } - - return table; - } - } -} diff --git a/Frameworks/libbinio/libbinio.xcodeproj/project.pbxproj b/Frameworks/libbinio/libbinio.xcodeproj/project.pbxproj index 6bf0e1a29..6aac3540c 100644 --- a/Frameworks/libbinio/libbinio.xcodeproj/project.pbxproj +++ b/Frameworks/libbinio/libbinio.xcodeproj/project.pbxproj @@ -119,7 +119,7 @@ TargetAttributes = { 83D3C67A201D37D8005564CB = { CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; + ProvisioningStyle = Manual; }; }; }; @@ -283,9 +283,9 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -296,6 +296,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_BUNDLE_IDENTIFIER = net.kode54.libbinio; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; }; name = Debug; @@ -304,9 +305,9 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -317,6 +318,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_BUNDLE_IDENTIFIER = net.kode54.libbinio; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; }; name = Release; diff --git a/Frameworks/mpg123/mpg123.xcodeproj/project.pbxproj b/Frameworks/mpg123/mpg123.xcodeproj/project.pbxproj index 74d1055ed..6ee223b58 100644 --- a/Frameworks/mpg123/mpg123.xcodeproj/project.pbxproj +++ b/Frameworks/mpg123/mpg123.xcodeproj/project.pbxproj @@ -320,6 +320,12 @@ attributes = { LastUpgradeCheck = 0940; ORGANIZATIONNAME = "Christopher Snowhill"; + TargetAttributes = { + 8313E30E1901FBDC00B4B6F1 = { + DevelopmentTeam = N6E749HJ2X; + ProvisioningStyle = Manual; + }; + }; }; buildConfigurationList = 8313E3091901FBDC00B4B6F1 /* Build configuration list for PBXProject "mpg123" */; compatibilityVersion = "Xcode 3.2"; @@ -446,7 +452,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = "@loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.7; + MACOSX_DEPLOYMENT_TARGET = 10.8; ONLY_ACTIVE_ARCH = YES; SKIP_INSTALL = YES; }; @@ -494,7 +500,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = "@loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.7; + MACOSX_DEPLOYMENT_TARGET = 10.8; SKIP_INSTALL = YES; }; name = Release; @@ -502,13 +508,17 @@ 8313E3381901FBDC00B4B6F1 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = N6E749HJ2X; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; INFOPLIST_FILE = "mpg123/mpg123-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "NoWork-Inc.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; WRAPPER_EXTENSION = framework; }; name = Debug; @@ -516,8 +526,9 @@ 8313E3391901FBDC00B4B6F1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = N6E749HJ2X; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index e79dcd016..90cc56df3 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj @@ -68,8 +68,6 @@ 830EBE102004655D0023AA10 /* atrac9_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBE0F2004655D0023AA10 /* atrac9_decoder.c */; }; 830EBE132004656E0023AA10 /* xnb.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBE112004656E0023AA10 /* xnb.c */; }; 830EBE142004656E0023AA10 /* ktss.c in Sources */ = {isa = PBXBuildFile; fileRef = 830EBE122004656E0023AA10 /* ktss.c */; }; - 830EBE19200465B00023AA10 /* libatrac9.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 830EBD9720045F1B0023AA10 /* libatrac9.framework */; }; - 830EBE1A200465C00023AA10 /* libatrac9.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 830EBD9720045F1B0023AA10 /* libatrac9.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 8313E3E61902020400B4B6F1 /* mpg123.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313E3431901FBDD00B4B6F1 /* mpg123.framework */; }; 8313E3E71902021800B4B6F1 /* mpg123.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8313E3431901FBDD00B4B6F1 /* mpg123.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 8315958720FEC832007002F0 /* asf_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8315958320FEC831007002F0 /* asf_decoder.c */; }; @@ -214,6 +212,8 @@ 8351F32F2212B57000A606E4 /* dsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8351F32C2212B57000A606E4 /* dsf.c */; }; 835C883622CC17BE001B4B3F /* bwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 835C883122CC17BD001B4B3F /* bwav.c */; }; 835C883722CC17BE001B4B3F /* ogg_vorbis_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 835C883522CC17BE001B4B3F /* ogg_vorbis_streamfile.h */; }; + 836C052B23F62F1A00FA07C7 /* libatrac9.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 835FC6C623F62AEF006960FA /* libatrac9.framework */; }; + 836C052C23F62F3100FA07C7 /* libatrac9.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 835FC6C623F62AEF006960FA /* libatrac9.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 836F6B4718BDB8880095E648 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 836F6B4518BDB8880095E648 /* InfoPlist.strings */; }; 836F6F1E18BDC2190095E648 /* acm_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE018BDC2180095E648 /* acm_decoder.c */; }; 836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE218BDC2180095E648 /* adx_decoder.c */; }; @@ -437,6 +437,23 @@ 83709E091ECBC1A4005C03D3 /* ta_aac.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E031ECBC1A4005C03D3 /* ta_aac.c */; }; 83709E0D1ECBC1C3005C03D3 /* mc3_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */; }; 83709E0E1ECBC1C3005C03D3 /* psv_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */; }; + 8373341623F60C7B00DE14DC /* g7221_decoder_aes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8373340E23F60C7A00DE14DC /* g7221_decoder_aes.h */; }; + 8373341723F60C7B00DE14DC /* g7221_decoder_aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373340F23F60C7A00DE14DC /* g7221_decoder_aes.c */; }; + 8373341823F60C7B00DE14DC /* tgcadpcm_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373341023F60C7A00DE14DC /* tgcadpcm_decoder.c */; }; + 8373341923F60C7B00DE14DC /* g7221_decoder_lib_data.h in Headers */ = {isa = PBXBuildFile; fileRef = 8373341123F60C7A00DE14DC /* g7221_decoder_lib_data.h */; }; + 8373341A23F60C7B00DE14DC /* relic_decoder_mixfft.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373341223F60C7B00DE14DC /* relic_decoder_mixfft.c */; }; + 8373341B23F60C7B00DE14DC /* g7221_decoder_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373341323F60C7B00DE14DC /* g7221_decoder_lib.c */; }; + 8373341C23F60C7B00DE14DC /* relic_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373341423F60C7B00DE14DC /* relic_decoder.c */; }; + 8373341D23F60C7B00DE14DC /* g7221_decoder_lib.h in Headers */ = {isa = PBXBuildFile; fileRef = 8373341523F60C7B00DE14DC /* g7221_decoder_lib.h */; }; + 8373342623F60CDC00DE14DC /* deblock_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8373341E23F60CDB00DE14DC /* deblock_streamfile.h */; }; + 8373342723F60CDC00DE14DC /* lrmd_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8373341F23F60CDB00DE14DC /* lrmd_streamfile.h */; }; + 8373342823F60CDC00DE14DC /* fda.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373342023F60CDB00DE14DC /* fda.c */; }; + 8373342923F60CDC00DE14DC /* deblock_streamfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373342123F60CDB00DE14DC /* deblock_streamfile.c */; }; + 8373342A23F60CDC00DE14DC /* lrmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373342223F60CDB00DE14DC /* lrmd.c */; }; + 8373342B23F60CDC00DE14DC /* fwse.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373342323F60CDB00DE14DC /* fwse.c */; }; + 8373342C23F60CDC00DE14DC /* kwb.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373342423F60CDB00DE14DC /* kwb.c */; }; + 8373342D23F60CDC00DE14DC /* bnsf_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 8373342523F60CDC00DE14DC /* bnsf_keys.h */; }; + 8373342F23F60D4100DE14DC /* tgc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8373342E23F60D4100DE14DC /* tgc.c */; }; 8375737321F9507D00F01AF5 /* oki_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8375737221F9507D00F01AF5 /* oki_decoder.c */; }; 8375737621F950ED00F01AF5 /* gin.c in Sources */ = {isa = PBXBuildFile; fileRef = 8375737421F950EC00F01AF5 /* gin.c */; }; 8375737721F950ED00F01AF5 /* ubi_sb_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8375737521F950EC00F01AF5 /* ubi_sb_streamfile.h */; }; @@ -444,7 +461,6 @@ 837CEA7923487E2500E62A4A /* ubi_adpcm_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEA7623487E2400E62A4A /* ubi_adpcm_decoder.c */; }; 837CEA7A23487E2500E62A4A /* ffmpeg_decoder_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEA7723487E2400E62A4A /* ffmpeg_decoder_utils.c */; }; 837CEAD823487E8300E62A4A /* bmp_konami.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAD423487E8300E62A4A /* bmp_konami.c */; }; - 837CEAD923487E8300E62A4A /* acb_utf.h in Headers */ = {isa = PBXBuildFile; fileRef = 837CEAD523487E8300E62A4A /* acb_utf.h */; }; 837CEADA23487E8300E62A4A /* acb.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAD623487E8300E62A4A /* acb.c */; }; 837CEADB23487E8300E62A4A /* bgw_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 837CEAD723487E8300E62A4A /* bgw_streamfile.h */; }; 837CEAF123487F2C00E62A4A /* xvas.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEADC23487F2900E62A4A /* xvas.c */; }; @@ -550,8 +566,6 @@ 83C7282A22BC8C1500678B4A /* plugins.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C7282622BC8C1400678B4A /* plugins.c */; }; 83CD428A1F787879000F77BE /* libswresample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 83CD42851F787878000F77BE /* libswresample.a */; }; 83D2F58E2356B266007646ED /* libopus.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 83D2F58A2356B266007646ED /* libopus.a */; }; - 83D731101A7394BF00CA1366 /* g7221.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83D730EB1A738EB300CA1366 /* g7221.framework */; }; - 83D731111A7394D300CA1366 /* g7221.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83D730EB1A738EB300CA1366 /* g7221.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 83D731891A749D1500CA1366 /* g719.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83D7313E1A74968A00CA1366 /* g719.framework */; }; 83D7318A1A749D2200CA1366 /* g719.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83D7313E1A74968A00CA1366 /* g719.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 83D7318C1A749EEE00CA1366 /* g719_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83D7318B1A749EEE00CA1366 /* g719_decoder.c */; }; @@ -588,20 +602,6 @@ /* End PBXBuildRule section */ /* Begin PBXContainerItemProxy section */ - 830EBD9620045F1B0023AA10 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 830EBD9220045F190023AA10 /* libatrac9.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 830EBD8720045F190023AA10; - remoteInfo = libatrac9; - }; - 830EBE152004659B0023AA10 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 830EBD9220045F190023AA10 /* libatrac9.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 830EBD8620045F190023AA10; - remoteInfo = libatrac9; - }; 8313E3421901FBDD00B4B6F1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 8313E33D1901FBDC00B4B6F1 /* mpg123.xcodeproj */; @@ -623,19 +623,19 @@ remoteGlobalIDString = 730F23A1091827B100AB638C; remoteInfo = Vorbis; }; - 83D730EA1A738EB300CA1366 /* PBXContainerItemProxy */ = { + 835FC6C523F62AEF006960FA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 83D730E51A738EB200CA1366 /* g7221.xcodeproj */; + containerPortal = 835FC6C123F62AEE006960FA /* libatrac9.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 83D730C91A738EB200CA1366; - remoteInfo = g7221; + remoteGlobalIDString = 835FC6B023F61BF0006960FA; + remoteInfo = libatrac9; }; - 83D7310E1A7394B500CA1366 /* PBXContainerItemProxy */ = { + 836C052523F62F0000FA07C7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 83D730E51A738EB200CA1366 /* g7221.xcodeproj */; + containerPortal = 835FC6C123F62AEE006960FA /* libatrac9.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 83D730C81A738EB200CA1366; - remoteInfo = g7221; + remoteGlobalIDString = 835FC6AF23F61BF0006960FA; + remoteInfo = libatrac9; }; 83D7313D1A74968A00CA1366 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -688,10 +688,9 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 830EBE1A200465C00023AA10 /* libatrac9.framework in CopyFiles */, + 836C052C23F62F3100FA07C7 /* libatrac9.framework in CopyFiles */, 832C70BF1E9335E400BD7B4E /* Vorbis.framework in CopyFiles */, 83D7318A1A749D2200CA1366 /* g719.framework in CopyFiles */, - 83D731111A7394D300CA1366 /* g7221.framework in CopyFiles */, 8313E3E71902021800B4B6F1 /* mpg123.framework in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; @@ -757,7 +756,6 @@ 8306B0D520984590000302D4 /* atsl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = atsl.c; sourceTree = ""; }; 8306B0D620984590000302D4 /* ppst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ppst.c; sourceTree = ""; }; 8306B0D720984590000302D4 /* ubi_jade.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_jade.c; sourceTree = ""; }; - 830EBD9220045F190023AA10 /* libatrac9.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libatrac9.xcodeproj; path = ../libatrac9/libatrac9.xcodeproj; sourceTree = ""; }; 830EBE0F2004655D0023AA10 /* atrac9_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = atrac9_decoder.c; sourceTree = ""; }; 830EBE112004656E0023AA10 /* xnb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xnb.c; sourceTree = ""; }; 830EBE122004656E0023AA10 /* ktss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ktss.c; sourceTree = ""; }; @@ -903,6 +901,7 @@ 8351F32C2212B57000A606E4 /* dsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsf.c; sourceTree = ""; }; 835C883122CC17BD001B4B3F /* bwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bwav.c; sourceTree = ""; }; 835C883522CC17BE001B4B3F /* ogg_vorbis_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ogg_vorbis_streamfile.h; sourceTree = ""; }; + 835FC6C123F62AEE006960FA /* libatrac9.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libatrac9.xcodeproj; path = ../libatrac9/libatrac9.xcodeproj; sourceTree = ""; }; 836F6B3918BDB8880095E648 /* libvgmstream.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libvgmstream.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 836F6B4418BDB8880095E648 /* libvgmstream-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "libvgmstream-Info.plist"; sourceTree = ""; }; 836F6B4618BDB8880095E648 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -1128,6 +1127,23 @@ 83709E031ECBC1A4005C03D3 /* ta_aac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ta_aac.c; sourceTree = ""; }; 83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc3_decoder.c; sourceTree = ""; }; 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psv_decoder.c; sourceTree = ""; }; + 8373340E23F60C7A00DE14DC /* g7221_decoder_aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g7221_decoder_aes.h; sourceTree = ""; }; + 8373340F23F60C7A00DE14DC /* g7221_decoder_aes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g7221_decoder_aes.c; sourceTree = ""; }; + 8373341023F60C7A00DE14DC /* tgcadpcm_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tgcadpcm_decoder.c; sourceTree = ""; }; + 8373341123F60C7A00DE14DC /* g7221_decoder_lib_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g7221_decoder_lib_data.h; sourceTree = ""; }; + 8373341223F60C7B00DE14DC /* relic_decoder_mixfft.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = relic_decoder_mixfft.c; sourceTree = ""; }; + 8373341323F60C7B00DE14DC /* g7221_decoder_lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g7221_decoder_lib.c; sourceTree = ""; }; + 8373341423F60C7B00DE14DC /* relic_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = relic_decoder.c; sourceTree = ""; }; + 8373341523F60C7B00DE14DC /* g7221_decoder_lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g7221_decoder_lib.h; sourceTree = ""; }; + 8373341E23F60CDB00DE14DC /* deblock_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = deblock_streamfile.h; sourceTree = ""; }; + 8373341F23F60CDB00DE14DC /* lrmd_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lrmd_streamfile.h; sourceTree = ""; }; + 8373342023F60CDB00DE14DC /* fda.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fda.c; sourceTree = ""; }; + 8373342123F60CDB00DE14DC /* deblock_streamfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = deblock_streamfile.c; sourceTree = ""; }; + 8373342223F60CDB00DE14DC /* lrmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lrmd.c; sourceTree = ""; }; + 8373342323F60CDB00DE14DC /* fwse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fwse.c; sourceTree = ""; }; + 8373342423F60CDB00DE14DC /* kwb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kwb.c; sourceTree = ""; }; + 8373342523F60CDC00DE14DC /* bnsf_keys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bnsf_keys.h; sourceTree = ""; }; + 8373342E23F60D4100DE14DC /* tgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tgc.c; sourceTree = ""; }; 8375737221F9507D00F01AF5 /* oki_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = oki_decoder.c; sourceTree = ""; }; 8375737421F950EC00F01AF5 /* gin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gin.c; sourceTree = ""; }; 8375737521F950EC00F01AF5 /* ubi_sb_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ubi_sb_streamfile.h; sourceTree = ""; }; @@ -1135,7 +1151,6 @@ 837CEA7623487E2400E62A4A /* ubi_adpcm_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_adpcm_decoder.c; sourceTree = ""; }; 837CEA7723487E2400E62A4A /* ffmpeg_decoder_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_utils.c; sourceTree = ""; }; 837CEAD423487E8300E62A4A /* bmp_konami.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bmp_konami.c; sourceTree = ""; }; - 837CEAD523487E8300E62A4A /* acb_utf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acb_utf.h; sourceTree = ""; }; 837CEAD623487E8300E62A4A /* acb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acb.c; sourceTree = ""; }; 837CEAD723487E8300E62A4A /* bgw_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bgw_streamfile.h; sourceTree = ""; }; 837CEADC23487F2900E62A4A /* xvas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xvas.c; sourceTree = ""; }; @@ -1240,7 +1255,6 @@ 83C7282622BC8C1400678B4A /* plugins.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = plugins.c; sourceTree = ""; }; 83CD42851F787878000F77BE /* libswresample.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libswresample.a; path = ../../ThirdParty/ffmpeg/lib/libswresample.a; sourceTree = ""; }; 83D2F58A2356B266007646ED /* libopus.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libopus.a; path = ../../ThirdParty/ffmpeg/lib/libopus.a; sourceTree = ""; }; - 83D730E51A738EB200CA1366 /* g7221.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = g7221.xcodeproj; path = ../g7221/g7221.xcodeproj; sourceTree = ""; }; 83D731381A74968900CA1366 /* g719.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = g719.xcodeproj; path = ../g719/g719.xcodeproj; sourceTree = ""; }; 83D7318B1A749EEE00CA1366 /* g719_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g719_decoder.c; sourceTree = ""; }; 83E56BA01F2EE3500026BC60 /* vorbis_custom_utils_ogl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_utils_ogl.c; sourceTree = ""; }; @@ -1267,7 +1281,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 830EBE19200465B00023AA10 /* libatrac9.framework in Frameworks */, 838BDB7F1D3B1FD10022CA6F /* Cocoa.framework in Frameworks */, 838BDB7D1D3B1FCC0022CA6F /* CoreVideo.framework in Frameworks */, 838BDB7B1D3B1FC20022CA6F /* CoreMedia.framework in Frameworks */, @@ -1281,26 +1294,18 @@ 83D2F58E2356B266007646ED /* libopus.a in Frameworks */, 83CD428A1F787879000F77BE /* libswresample.a in Frameworks */, 83D731891A749D1500CA1366 /* g719.framework in Frameworks */, - 83D731101A7394BF00CA1366 /* g7221.framework in Frameworks */, 838BDB641D3AF08C0022CA6F /* libavcodec.a in Frameworks */, 838BDB651D3AF08C0022CA6F /* libavformat.a in Frameworks */, 838BDB661D3AF08C0022CA6F /* libavutil.a in Frameworks */, 8313E3E61902020400B4B6F1 /* mpg123.framework in Frameworks */, 834D795520E4F0D400C4A5CC /* Vorbis.framework in Frameworks */, + 836C052B23F62F1A00FA07C7 /* libatrac9.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 830EBD9320045F190023AA10 /* Products */ = { - isa = PBXGroup; - children = ( - 830EBD9720045F1B0023AA10 /* libatrac9.framework */, - ); - name = Products; - sourceTree = ""; - }; 8313E33E1901FBDC00B4B6F1 /* Products */ = { isa = PBXGroup; children = ( @@ -1318,6 +1323,14 @@ path = ext_libs; sourceTree = ""; }; + 835FC6C223F62AEE006960FA /* Products */ = { + isa = PBXGroup; + children = ( + 835FC6C623F62AEF006960FA /* libatrac9.framework */, + ); + name = Products; + sourceTree = ""; + }; 836F6B2F18BDB8880095E648 = { isa = PBXGroup; children = ( @@ -1358,14 +1371,13 @@ 836F6B3E18BDB8880095E648 /* Other Frameworks */ = { isa = PBXGroup; children = ( - 830EBD9220045F190023AA10 /* libatrac9.xcodeproj */, + 835FC6C123F62AEE006960FA /* libatrac9.xcodeproj */, 838BDB611D3AF08C0022CA6F /* libavcodec.a */, 838BDB621D3AF08C0022CA6F /* libavformat.a */, 838BDB631D3AF08C0022CA6F /* libavutil.a */, 83CD42851F787878000F77BE /* libswresample.a */, 8313E33D1901FBDC00B4B6F1 /* mpg123.xcodeproj */, 83F412871E932F9A002E37D0 /* Vorbis.xcodeproj */, - 83D730E51A738EB200CA1366 /* g7221.xcodeproj */, 83D731381A74968900CA1366 /* g719.xcodeproj */, ); name = "Other Frameworks"; @@ -1441,6 +1453,11 @@ 836F6DE918BDC2180095E648 /* g72x_state.h */, 83D7318B1A749EEE00CA1366 /* g719_decoder.c */, 836F6DE718BDC2180095E648 /* g721_decoder.c */, + 8373340F23F60C7A00DE14DC /* g7221_decoder_aes.c */, + 8373340E23F60C7A00DE14DC /* g7221_decoder_aes.h */, + 8373341123F60C7A00DE14DC /* g7221_decoder_lib_data.h */, + 8373341323F60C7B00DE14DC /* g7221_decoder_lib.c */, + 8373341523F60C7B00DE14DC /* g7221_decoder_lib.h */, 836F6DE818BDC2180095E648 /* g7221_decoder.c */, 832389511D224C0800482226 /* hca_decoder.c */, 836F6DEA18BDC2180095E648 /* ima_decoder.c */, @@ -1470,8 +1487,11 @@ 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */, 836F6DFA18BDC2180095E648 /* psx_decoder.c */, 837CEA7523487E2400E62A4A /* ptadpcm_decoder.c */, + 8373341223F60C7B00DE14DC /* relic_decoder_mixfft.c */, + 8373341423F60C7B00DE14DC /* relic_decoder.c */, 836F6DFB18BDC2180095E648 /* SASSC_decoder.c */, 836F6DFC18BDC2180095E648 /* sdx2_decoder.c */, + 8373341023F60C7A00DE14DC /* tgcadpcm_decoder.c */, 837CEA7623487E2400E62A4A /* ubi_adpcm_decoder.c */, 839E21D61F2EDAF000EE54D7 /* vorbis_custom_data_fsb.h */, 839E21DC1F2EDAF000EE54D7 /* vorbis_custom_data_wwise.h */, @@ -1550,7 +1570,6 @@ 8351F32A2212B57000A606E4 /* 208.c */, 834FE0C8215C79E7000A5D3D /* a2m.c */, 836F6E2A18BDC2180095E648 /* aax.c */, - 837CEAD523487E8300E62A4A /* acb_utf.h */, 837CEAD623487E8300E62A4A /* acb.c */, 836F6E2B18BDC2180095E648 /* acm.c */, 834FE0CF215C79E8000A5D3D /* adpcm_capcom.c */, @@ -1588,6 +1607,7 @@ 83299FCE1E7660C7003A3242 /* bik.c */, 837CEAD423487E8300E62A4A /* bmp_konami.c */, 834FE0CA215C79E7000A5D3D /* bnk_sony.c */, + 8373342523F60CDC00DE14DC /* bnsf_keys.h */, 836F6E3918BDC2180095E648 /* bnsf.c */, 836F6E3A18BDC2180095E648 /* brstm.c */, 83EDE5D71A70951A005F5D84 /* btsnd.c */, @@ -1605,6 +1625,8 @@ 836F6E4018BDC2180095E648 /* dc_kcey.c */, 836F6E4118BDC2180095E648 /* dc_str.c */, 83C7280C22BC893D00678B4A /* dcs_wav.c */, + 8373342123F60CDB00DE14DC /* deblock_streamfile.c */, + 8373341E23F60CDB00DE14DC /* deblock_streamfile.h */, 8349A8EE1FE6257C00E26435 /* dec.c */, 834FE0CD215C79E8000A5D3D /* derf.c */, 836F6E4318BDC2180095E648 /* dmsg_segh.c */, @@ -1625,6 +1647,7 @@ 836F6E4A18BDC2180095E648 /* excitebots.c */, 8349A8EF1FE6257C00E26435 /* ezw.c */, 832BF80821E05135006F50F1 /* fag.c */, + 8373342023F60CDB00DE14DC /* fda.c */, 83C7280022BC893A00678B4A /* ffdl.c */, 838BDB6D1D3B043C0022CA6F /* ffmpeg.c */, 836F6E4B18BDC2180095E648 /* ffw.c */, @@ -1636,6 +1659,7 @@ 83C7280522BC893B00678B4A /* fsb5_fev.c */, 834FE0E3215C79EC000A5D3D /* fsb5_interleave_streamfile.h */, 83F5F8821908D0A400C8E65F /* fsb5.c */, + 8373342323F60CDB00DE14DC /* fwse.c */, 834D3A6D19F47C98001C54F6 /* g1l.c */, 836F6E4D18BDC2180095E648 /* gca.c */, 836F6E4E18BDC2180095E648 /* gcsw.c */, @@ -1666,6 +1690,9 @@ 83A21F83201D8981000F04B9 /* kma9.c */, 836F6E5918BDC2180095E648 /* kraw.c */, 830EBE122004656E0023AA10 /* ktss.c */, + 8373342423F60CDB00DE14DC /* kwb.c */, + 8373341F23F60CDB00DE14DC /* lrmd_streamfile.h */, + 8373342223F60CDB00DE14DC /* lrmd.c */, 836F6E5A18BDC2180095E648 /* lsf.c */, 836F6E5C18BDC2180095E648 /* mattel_hyperscan.c */, 836F6E5D18BDC2180095E648 /* maxis_xa.c */, @@ -1868,6 +1895,7 @@ 836F6EF918BDC2190095E648 /* svs.c */, 831BA6121EAC61A500CF89B0 /* sxd.c */, 83709E031ECBC1A4005C03D3 /* ta_aac.c */, + 8373342E23F60D4100DE14DC /* tgc.c */, 836F6EFA18BDC2190095E648 /* thp.c */, 836F6EFB18BDC2190095E648 /* tun.c */, 83C7280122BC893A00678B4A /* txth_streamfile.h */, @@ -1956,14 +1984,6 @@ path = meta; sourceTree = ""; }; - 83D730E61A738EB200CA1366 /* Products */ = { - isa = PBXGroup; - children = ( - 83D730EB1A738EB300CA1366 /* g7221.framework */, - ); - name = Products; - sourceTree = ""; - }; 83D731391A74968900CA1366 /* Products */ = { isa = PBXGroup; children = ( @@ -2013,6 +2033,7 @@ 839E21E01F2EDAF100EE54D7 /* vorbis_custom_data_fsb.h in Headers */, 836F705418BDC2190095E648 /* streamfile.h in Headers */, 83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */, + 8373342723F60CDC00DE14DC /* lrmd_streamfile.h in Headers */, 8323894B1D22419B00482226 /* clHCA.h in Headers */, 83C7281122BC893D00678B4A /* 9tav_streamfile.h in Headers */, 83C7280F22BC893D00678B4A /* xwb_xsb.h in Headers */, @@ -2020,15 +2041,16 @@ 839E21E81F2EDAF100EE54D7 /* mpeg_decoder.h in Headers */, 834FE10C215C79ED000A5D3D /* fsb5_interleave_streamfile.h in Headers */, 839E21E51F2EDAF100EE54D7 /* vorbis_custom_decoder.h in Headers */, - 837CEAD923487E8300E62A4A /* acb_utf.h in Headers */, 837CEADB23487E8300E62A4A /* bgw_streamfile.h in Headers */, 837CEB0323487F2C00E62A4A /* xavs_streamfile.h in Headers */, 8306B0E120984590000302D4 /* ubi_lyn_ogg_streamfile.h in Headers */, 836F705918BDC2190095E648 /* vgmstream.h in Headers */, + 8373342623F60CDC00DE14DC /* deblock_streamfile.h in Headers */, 83C7281522BC893D00678B4A /* txth_streamfile.h in Headers */, 8306B0DE20984590000302D4 /* awc_xma_streamfile.h in Headers */, 834FE0B5215C798C000A5D3D /* acm_decoder_libacm.h in Headers */, 839E21E61F2EDAF100EE54D7 /* vorbis_custom_data_wwise.h in Headers */, + 8373342D23F60CDC00DE14DC /* bnsf_keys.h in Headers */, 834FE103215C79ED000A5D3D /* ea_schl_streamfile.h in Headers */, 83F0AA6021E2028C004BBC04 /* vsv_streamfile.h in Headers */, 83FBD506235D31F800D35BCD /* riff_ogg_streamfile.h in Headers */, @@ -2037,7 +2059,10 @@ 836F6F9A18BDC2190095E648 /* meta.h in Headers */, 8306B0D820984590000302D4 /* ea_eaac_streamfile.h in Headers */, 837CEB0523487F2C00E62A4A /* sqex_sead_streamfile.h in Headers */, + 8373341D23F60C7B00DE14DC /* g7221_decoder_lib.h in Headers */, 8306B0E820984590000302D4 /* opus_interleave_streamfile.h in Headers */, + 8373341623F60C7B00DE14DC /* g7221_decoder_aes.h in Headers */, + 8373341923F60C7B00DE14DC /* g7221_decoder_lib_data.h in Headers */, 83AFABBD23795202002F3947 /* ea_eaac_opus_streamfile.h in Headers */, 83C7281822BC893D00678B4A /* sfh_streamfile.h in Headers */, 834FE0EF215C79ED000A5D3D /* xvag_streamfile.h in Headers */, @@ -2068,10 +2093,9 @@ 48C265101A5D424500A0A3D6 /* PBXBuildRule */, ); dependencies = ( + 836C052623F62F0000FA07C7 /* PBXTargetDependency */, 834D795420E4F0B900C4A5CC /* PBXTargetDependency */, - 830EBE162004659B0023AA10 /* PBXTargetDependency */, 83D731881A749D0D00CA1366 /* PBXTargetDependency */, - 83D7310F1A7394B500CA1366 /* PBXTargetDependency */, 8313E3E91902021F00B4B6F1 /* PBXTargetDependency */, ); name = libvgmstream; @@ -2111,12 +2135,8 @@ ProjectRef = 83D731381A74968900CA1366 /* g719.xcodeproj */; }, { - ProductGroup = 83D730E61A738EB200CA1366 /* Products */; - ProjectRef = 83D730E51A738EB200CA1366 /* g7221.xcodeproj */; - }, - { - ProductGroup = 830EBD9320045F190023AA10 /* Products */; - ProjectRef = 830EBD9220045F190023AA10 /* libatrac9.xcodeproj */; + ProductGroup = 835FC6C223F62AEE006960FA /* Products */; + ProjectRef = 835FC6C123F62AEE006960FA /* libatrac9.xcodeproj */; }, { ProductGroup = 8313E33E1901FBDC00B4B6F1 /* Products */; @@ -2135,13 +2155,6 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - 830EBD9720045F1B0023AA10 /* libatrac9.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = libatrac9.framework; - remoteRef = 830EBD9620045F1B0023AA10 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 8313E3431901FBDD00B4B6F1 /* mpg123.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; @@ -2149,11 +2162,11 @@ remoteRef = 8313E3421901FBDD00B4B6F1 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 83D730EB1A738EB300CA1366 /* g7221.framework */ = { + 835FC6C623F62AEF006960FA /* libatrac9.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; - path = g7221.framework; - remoteRef = 83D730EA1A738EB300CA1366 /* PBXContainerItemProxy */; + path = libatrac9.framework; + remoteRef = 835FC6C523F62AEF006960FA /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 83D7313E1A74968A00CA1366 /* g719.framework */ = { @@ -2239,6 +2252,7 @@ 836F6FAD18BDC2190095E648 /* ngc_dsp_konami.c in Sources */, 836F6FF818BDC2190095E648 /* ps2_smpl.c in Sources */, 836F703818BDC2190095E648 /* ubi_ckd.c in Sources */, + 8373341B23F60C7B00DE14DC /* g7221_decoder_lib.c in Sources */, 836F705318BDC2190095E648 /* streamfile.c in Sources */, 836F6F7418BDC2190095E648 /* bgw.c in Sources */, 836F6F7218BDC2190095E648 /* baf.c in Sources */, @@ -2247,6 +2261,7 @@ 836F700C18BDC2190095E648 /* ps2_wb.c in Sources */, 836F6F7D18BDC2190095E648 /* dc_str.c in Sources */, 83A5F75F198DF021009AF94C /* bfwav.c in Sources */, + 8373341723F60C7B00DE14DC /* g7221_decoder_aes.c in Sources */, 836F702018BDC2190095E648 /* rkv.c in Sources */, 834FE0F4215C79ED000A5D3D /* wsi.c in Sources */, 836F703218BDC2190095E648 /* str_asr.c in Sources */, @@ -2281,6 +2296,7 @@ 836F702318BDC2190095E648 /* rsf.c in Sources */, 834FE109215C79ED000A5D3D /* idsp_ie.c in Sources */, 83299FD01E7660C7003A3242 /* bik.c in Sources */, + 8373341823F60C7B00DE14DC /* tgcadpcm_decoder.c in Sources */, 836F6F3318BDC2190095E648 /* ngc_dtk_decoder.c in Sources */, 83C7281322BC893D00678B4A /* mta2.c in Sources */, 8306B0EF20984590000302D4 /* ubi_bao.c in Sources */, @@ -2382,6 +2398,7 @@ 836F6F6F18BDC2190095E648 /* akb.c in Sources */, 83EED5D6203A8BD7008BEB45 /* blocked_ea_swvr.c in Sources */, 8349A9181FE6258200E26435 /* ea_1snh.c in Sources */, + 8373342C23F60CDC00DE14DC /* kwb.c in Sources */, 83EED5D4203A8BC7008BEB45 /* aus.c in Sources */, 836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */, 832BF81D21E0514B006F50F1 /* msf_tamasoft.c in Sources */, @@ -2408,6 +2425,7 @@ 836F6FF918BDC2190095E648 /* ps2_snd.c in Sources */, 836F6F2918BDC2190095E648 /* l5_555_decoder.c in Sources */, 836F6FF318BDC2190095E648 /* ps2_rstm.c in Sources */, + 8373342923F60CDC00DE14DC /* deblock_streamfile.c in Sources */, 836F6F7918BDC2190095E648 /* dc_asd.c in Sources */, 836F6FC118BDC2190095E648 /* pc_adp.c in Sources */, 836F703B18BDC2190095E648 /* vsf.c in Sources */, @@ -2442,6 +2460,7 @@ 837CEAD823487E8300E62A4A /* bmp_konami.c in Sources */, 8306B0A220984552000302D4 /* blocked_bdsp.c in Sources */, 836F700118BDC2190095E648 /* ps2_tec.c in Sources */, + 8373341C23F60C7B00DE14DC /* relic_decoder.c in Sources */, 832BF82121E0514B006F50F1 /* zsnd.c in Sources */, 836F703018BDC2190095E648 /* sqex_scd.c in Sources */, 8306B0A320984552000302D4 /* blocked_ast.c in Sources */, @@ -2459,7 +2478,9 @@ 8306B0BA20984552000302D4 /* blocked_wsi.c in Sources */, 83BAFB6C19F45EB3005DAB60 /* bfstm.c in Sources */, 836F704418BDC2190095E648 /* ws_aud.c in Sources */, + 8373342F23F60D4100DE14DC /* tgc.c in Sources */, 83709E081ECBC1A4005C03D3 /* ps2_rxws.c in Sources */, + 8373342823F60CDC00DE14DC /* fda.c in Sources */, 836F6F6D18BDC2190095E648 /* aifc.c in Sources */, 836F702218BDC2190095E648 /* rsd.c in Sources */, 8349A90D1FE6258200E26435 /* ubi_sb.c in Sources */, @@ -2498,6 +2519,7 @@ 836F6F3718BDC2190095E648 /* pcm_decoder.c in Sources */, 834FE106215C79ED000A5D3D /* utk.c in Sources */, 831BA6281EAC61CB00CF89B0 /* coding_utils.c in Sources */, + 8373342B23F60CDC00DE14DC /* fwse.c in Sources */, 837CEAFF23487F2C00E62A4A /* raw_snds.c in Sources */, 836F700218BDC2190095E648 /* ps2_tk5.c in Sources */, 83AA5D271F6E2F9C0020821C /* stm.c in Sources */, @@ -2601,6 +2623,7 @@ 834FE10F215C79ED000A5D3D /* sdf.c in Sources */, 83FC177123AC59A800E1025F /* cri_utf.c in Sources */, 834FE0FF215C79ED000A5D3D /* sqex_scd_sscf.c in Sources */, + 8373341A23F60C7B00DE14DC /* relic_decoder_mixfft.c in Sources */, 836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */, 831BA6211EAC61A500CF89B0 /* x360_pasx.c in Sources */, 832BF82621E0514B006F50F1 /* nwav.c in Sources */, @@ -2656,6 +2679,7 @@ 836F6FBF18BDC2190095E648 /* otm.c in Sources */, 8306B0B420984552000302D4 /* blocked_tra.c in Sources */, 834FE0B8215C798C000A5D3D /* acm_decoder_decode.c in Sources */, + 8373342A23F60CDC00DE14DC /* lrmd.c in Sources */, 836F6FBD18BDC2190095E648 /* nwa.c in Sources */, 837CEAFC23487F2C00E62A4A /* raw_wavm.c in Sources */, 834FE0F7215C79ED000A5D3D /* vis.c in Sources */, @@ -2695,11 +2719,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 830EBE162004659B0023AA10 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libatrac9; - targetProxy = 830EBE152004659B0023AA10 /* PBXContainerItemProxy */; - }; 8313E3E91902021F00B4B6F1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = mpg123; @@ -2710,10 +2729,10 @@ name = Vorbis; targetProxy = 834D795320E4F0B900C4A5CC /* PBXContainerItemProxy */; }; - 83D7310F1A7394B500CA1366 /* PBXTargetDependency */ = { + 836C052623F62F0000FA07C7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = g7221; - targetProxy = 83D7310E1A7394B500CA1366 /* PBXContainerItemProxy */; + name = libatrac9; + targetProxy = 836C052523F62F0000FA07C7 /* PBXContainerItemProxy */; }; 83D731881A749D0D00CA1366 /* PBXTargetDependency */ = { isa = PBXTargetDependency; @@ -2869,7 +2888,10 @@ 836F6B6218BDB8880095E648 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_SEARCH_PATHS = ( @@ -2887,6 +2909,7 @@ INFOPLIST_FILE = "vgmstream/libvgmstream-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "NoWork-Inc.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = macosx; WRAPPER_EXTENSION = framework; }; @@ -2895,7 +2918,10 @@ 836F6B6318BDB8880095E648 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_SEARCH_PATHS = ( @@ -2913,6 +2939,7 @@ INFOPLIST_FILE = "vgmstream/libvgmstream-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "NoWork-Inc.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = macosx; WRAPPER_EXTENSION = framework; }; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding.h b/Frameworks/vgmstream/vgmstream/src/coding/coding.h index ef9db19b7..db56e1dcf 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding.h @@ -20,6 +20,7 @@ void decode_wv6_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspa void decode_alp_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_ffta2_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_blitz_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_mtf_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo); void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); @@ -137,6 +138,9 @@ void decode_nxap(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacin size_t yamaha_bytes_to_samples(size_t bytes, int channels); size_t aska_bytes_to_samples(size_t bytes, int channels); +/* tgcadpcm_decoder */ +void decode_tgc(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int32_t first_sample, int32_t samples_to_do); + /* nds_procyon_decoder */ void decode_nds_procyon(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); @@ -203,9 +207,16 @@ void flush_ea_mt(VGMSTREAM *vgmstream); void seek_ea_mt(VGMSTREAM * vgmstream, int32_t num_sample); void free_ea_mt(ea_mt_codec_data *data, int channels); +/* relic_decoder */ +relic_codec_data* init_relic(int channels, int bitrate, int codec_rate); +void decode_relic(VGMSTREAMCHANNEL* stream, relic_codec_data* data, sample_t* outbuf, int32_t samples_to_do); +void reset_relic(relic_codec_data* data); +void seek_relic(relic_codec_data* data, int32_t num_sample); +void free_relic(relic_codec_data* data); + /* hca_decoder */ hca_codec_data *init_hca(STREAMFILE *streamFile); -void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do); +void decode_hca(hca_codec_data * data, sample_t * outbuf, int32_t samples_to_do); void reset_hca(hca_codec_data * data); void loop_hca(hca_codec_data * data, int32_t num_sample); void free_hca(hca_codec_data * data); @@ -248,10 +259,12 @@ long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data *data); #ifdef VGM_USE_G7221 /* g7221_decoder */ -g7221_codec_data *init_g7221(int channel_count, int frame_size); -void decode_g7221(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel); -void reset_g7221(VGMSTREAM *vgmstream); -void free_g7221(VGMSTREAM *vgmstream); +g7221_codec_data* init_g7221(int channel_count, int frame_size); +void decode_g7221(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t samples_to_do, int channel); +void reset_g7221(g7221_codec_data* data); +void free_g7221(g7221_codec_data* data); +void set_key_g7221(g7221_codec_data* data, const uint8_t* key); +int test_key_g7221(g7221_codec_data* data, off_t start, STREAMFILE* sf); #endif #ifdef VGM_USE_G719 diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c index 6915d9950..496d54d6e 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c @@ -1,48 +1,68 @@ #include "coding.h" +#include "g7221_decoder_lib.h" #ifdef VGM_USE_G7221 -#define G7221_MAX_CODES (960/8) /* max frame 0xF0 uint8s = 0xF0/2 uint16s = 960/8 */ +#define G7221_MAX_FRAME_SIZE 0x78 /* 960/8 */ +#define G7221_MAX_FRAME_SAMPLES 640 /* 32000/50 */ +struct g7221_codec_data { + int channels; + int frame_size; + struct g7221_channel_data { + sample_t buffer[G7221_MAX_FRAME_SAMPLES]; + g7221_handle* handle; + } *ch; +}; -g7221_codec_data * init_g7221(int channel_count, int frame_size) { +g7221_codec_data* init_g7221(int channels, int frame_size) { int i; - g7221_codec_data *data = NULL; + g7221_codec_data* data = NULL; - if (frame_size / sizeof(int16_t) > G7221_MAX_CODES) + if (frame_size > G7221_MAX_FRAME_SIZE) goto fail; - data = calloc(channel_count, sizeof(g7221_codec_data)); /* one decoder per channel */ + data = calloc(1, sizeof(g7221_codec_data)); if (!data) goto fail; - for (i = 0; i < channel_count; i++) { - data[i].handle = g7221_init(frame_size, 14000); /* Siren 14 == 14khz bandwidth */ - if (!data[i].handle) goto fail; + data->channels = channels; + data->frame_size = frame_size; + + data->ch = calloc(channels, sizeof(struct g7221_channel_data)); + if (!data->ch) goto fail; + + for (i = 0; i < data->channels; i++) { + data->ch[i].handle = g7221_init(frame_size); + if (!data->ch[i].handle) goto fail; } return data; fail: - if (data) { - for (i = 0; i < channel_count; i++) { - g7221_free(data[i].handle); - } - } - free(data); - + free_g7221(data); return NULL; } -void decode_g7221(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) { - VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel]; - g7221_codec_data *data = vgmstream->codec_data; - g7221_codec_data *ch_data = &data[channel]; +void decode_g7221(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t samples_to_do, int channel) { + VGMSTREAMCHANNEL* ch = &vgmstream->ch[channel]; + g7221_codec_data* data = vgmstream->codec_data; + struct g7221_channel_data* ch_data = &data->ch[channel]; int i; if (0 == vgmstream->samples_into_block) { - int16_t code_buffer[G7221_MAX_CODES]; - vgmstream->ch[channel].streamfile->read(ch->streamfile, (uint8_t*)code_buffer, ch->offset, vgmstream->interleave_block_size); - g7221_decode_frame(ch_data->handle, code_buffer, ch_data->buffer); + uint8_t buf[G7221_MAX_FRAME_SIZE]; + size_t bytes; + size_t read = data->frame_size; + + bytes = read_streamfile(buf, ch->offset, read, ch->streamfile); + if (bytes != read) { + //g7221_decode_empty(ch_data->handle, ch_data->buffer); + memset(ch_data->buffer, 0, sizeof(ch_data->buffer)); + VGM_LOG("S14: EOF read\n"); + } + else { + g7221_decode_frame(ch_data->handle, buf, ch_data->buffer); + } } for (i = 0; i < samples_to_do; i++) { @@ -51,25 +71,89 @@ void decode_g7221(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, in } -void reset_g7221(VGMSTREAM *vgmstream) { - g7221_codec_data *data = vgmstream->codec_data; +void reset_g7221(g7221_codec_data* data) { int i; if (!data) return; - for (i = 0; i < vgmstream->channels; i++) { - g7221_reset(data[i].handle); + for (i = 0; i < data->channels; i++) { + g7221_reset(data->ch[i].handle); } } -void free_g7221(VGMSTREAM *vgmstream) { - g7221_codec_data *data = (g7221_codec_data *) vgmstream->codec_data; +void free_g7221(g7221_codec_data* data) { int i; if (!data) return; - for (i = 0; i < vgmstream->channels; i++) { - g7221_free(data[i].handle); + for (i = 0; i < data->channels; i++) { + g7221_free(data->ch[i].handle); } + free(data->ch); free(data); } +void set_key_g7221(g7221_codec_data* data, const uint8_t* key) { + int i; + if (!data) return; + + for (i = 0; i < data->channels; i++) { + g7221_set_key(data->ch[i].handle, key); + } +} + +/* just in case but very few should be enough */ +#define S14_KEY_MIN_TEST_FRAMES 3 +#define S14_KEY_MAX_TEST_FRAMES 5 + +/* Test a number of frames to check if current key decrypts correctly. + * Returns score: <0: error/wrong, 0: unknown/silent, >0: good (closer to 1 is better). */ +int test_key_g7221(g7221_codec_data* data, off_t start, STREAMFILE* sf) { + size_t test_frames = 0, current_frame = 0; + int total_score = 0; + int max_frames = (get_streamfile_size(sf) - start) / data->frame_size; + int cur_ch = 0; + + /* assumes key was set before this call */ + + while (test_frames < S14_KEY_MAX_TEST_FRAMES && current_frame < max_frames) { + int score, ok; + size_t bytes; + uint8_t buf[G7221_MAX_FRAME_SIZE]; + + + bytes = read_streamfile(buf, start, data->frame_size, sf); + if (bytes != data->frame_size) { + total_score = -1; + break; + } + + ok = g7221_decode_frame(data->ch[cur_ch].handle, buf, data->ch[cur_ch].buffer); + if (!ok) { + total_score = -1; + break; + } + + /* alternate channels (decode may affect scores otherwise) */ + cur_ch = (cur_ch + 1) % data->channels; + + /* good key if it decodes without error, encryption is easily detectable */ + score = 1; + + test_frames++; + + total_score += score; + + start += data->frame_size; + } + + /* signal best possible score (many perfect frames and few blank frames) */ + if (test_frames > S14_KEY_MIN_TEST_FRAMES && total_score > 0 && total_score <= test_frames) { + total_score = 1; + } + + /* clean up decoders */ + reset_g7221(data); + + return total_score; +} + #endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.c b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.c new file mode 100644 index 000000000..e7d250184 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.c @@ -0,0 +1,326 @@ +#include +#include "g7221_decoder_aes.h" + +/* Namco's NUS AES is just standard AES-192 in ECB mode, so this can be swapped with another lib, + * if more code needs AES. Most implementations out there either use pre-calculated look-up tables, + * or calculate manually every AES op. Namco's code calculates tables first in a slightly different + * layout, so it may be interesting as a sort of doc piece. */ + + +struct s14aes_handle { + /* substitution box look-up table and the inverse */ + uint8_t sbox[256]; + uint8_t ibox[256]; + /* helper for various tables, not too sure about it */ + uint8_t xors[256]; + /* round constant, though only sets up to 8 */ + uint8_t rcon[16]; + /* MixColumn(?) LUTs, unlike normal Rijndael which uses 4 tables: Td0a Td0b..., Td1a Td1b..., ... + * layout is: Td0a Td1a Td2a Td3a, Td0b Td0b Td1b Td2b, ... (better for CPU cache?) */ + uint32_t tds[256*4]; + /* expanded roundkey, actual final key */ + uint32_t rk[52]; +} ; + + +#define GET_U32LE(p) (((p)[0] << 0 ) | ((p)[1] << 8 ) | ((p)[2] << 16) | ((p)[3] << 24)) +#define GET_U32BE(p) (((p)[3] << 0 ) | ((p)[2] << 8 ) | ((p)[1] << 16) | ((p)[0] << 24)) +#define GET_B0(x) (((x) >> 0 ) & 0xFF) +#define GET_B1(x) (((x) >> 8 ) & 0xFF) +#define GET_B2(x) (((x) >> 16) & 0xFF) +#define GET_B3(x) (((x) >> 24) & 0xFF) + + +static void aes_key_expand(s14aes_handle* ctx, const uint8_t* key, uint32_t* rk) { + int i; + + rk[0] = GET_U32LE(key + 0); + rk[1] = GET_U32LE(key + 4); + rk[2] = GET_U32LE(key + 8); + rk[3] = GET_U32LE(key + 12); + rk[4] = GET_U32LE(key + 16); + rk[5] = GET_U32LE(key + 20); + + for (i = 6; i < 52; i++) { + uint8_t temp0 = (rk[5] >> 0 ) & 0xFF; + uint8_t temp1 = (rk[5] >> 8 ) & 0xFF; + uint8_t temp2 = (rk[5] >> 16) & 0xFF; + uint8_t temp3 = (rk[5] >> 24) & 0xFF; + if (i == 6 * (i / 6)) { + uint8_t sv = ctx->sbox[temp1]; + temp1 = ctx->sbox[temp2]; + temp2 = ctx->sbox[temp3]; + temp3 = ctx->sbox[temp0]; + temp0 = ctx->rcon[i / 6u - 1] ^ sv; + } + rk[6] = ((temp0 ^ ((rk[0] >> 0 ) & 0xFF)) << 0 ) | + ((temp1 ^ ((rk[0] >> 8 ) & 0xFF)) << 8 ) | + ((temp2 ^ ((rk[0] >> 16) & 0xFF)) << 16) | + ((temp3 ^ ((rk[0] >> 24) & 0xFF)) << 24); + rk++; + } +} + +static void aes_init_key(s14aes_handle* ctx, const uint8_t* key) { + const uint8_t invcols[4][4] = { + {0x0E,0x0B,0x0D,0x09}, + {0x09,0x0E,0x0B,0x0D}, + {0x0D,0x09,0x0E,0x0B}, + {0x0B,0x0D,0x09,0x0E} + }; + unsigned int roundkey[52]; + int i, j, row, col, b; + + aes_key_expand(ctx, key, roundkey); + + for (i = 0; i < 4; i++) { + ctx->rk[i] = ((roundkey[i] << 24) & 0xFF000000) | + ((roundkey[i] << 8 ) & 0x00FF0000) | + ((roundkey[i] >> 8 ) & 0x0000FF00) | + ((roundkey[i] >> 24) & 0x000000FF); + } + + for (i = 4; i < 48; i += 4) { + for (j = i; j < i + 4; j++) { + uint32_t val = 0; + + for (row = 0; row < 4; row++) { + uint8_t xv = 0; + + for (col = 0; col < 4; col++) { + uint16_t rv1 = 0; + uint16_t rv2 = (roundkey[j] >> (col * 8)) & 0xFF; + uint8_t ic = invcols[row][col]; + + for (b = 0; b < 8; b++) { + if (ic & (1 << b)) + rv1 ^= rv2; + rv2 *= 2; + } + + xv ^= rv1 ^ ctx->xors[rv1 >> 8]; + } + + val = (val << 8) | xv; + } + + ctx->rk[j] = val; + } + } + + for (i = 48; i < 52; i++) { + ctx->rk[i] = ((roundkey[i] << 24) & 0xFF000000) | + ((roundkey[i] << 8 ) & 0x00FF0000) | + ((roundkey[i] >> 8 ) & 0x0000FF00) | + ((roundkey[i] >> 24) & 0x000000FF); + } +} + +static void aes_init_state(s14aes_handle* ctx) { + const uint8_t invcol[4] = { + 0x0E, 0x0B, 0x0D, 0x09 + }; + unsigned int *tds_ptr; + uint8_t rcon[32]; + uint8_t box[256]; + int i, j, k, b; + + for (i = 0; i < 32; i++) { + uint16_t rv; + if (i >= 8) { + rv = 128; + for (j = 0; j < i - 7; j++) { + rv *= 2; + if (rv & 256) + rv ^= 0x11Bu; + } + } + else { + rv = 1 << i; + } + rcon[i] = rv; + } + + for (i = 0; i < 256; i++) { + uint8_t xv = 0; + for (j = 0; j < 8; j++) { + if (i & (1 << j)) + xv ^= rcon[j + 8]; + } + ctx->xors[i] = xv; + } + + tds_ptr = ctx->tds; + for (i = 0; i < 256; i++) { + uint32_t val = 0; + for (j = 0; j < 4; j++) { + uint16_t tv1 = 0; + uint16_t tv2 = invcol[j]; + for (b = 0; b < 8; b++) { + if (i & (1 << b)) + tv1 ^= tv2; + tv2 *= 2; + } + + val = ((val >> 8u) & 0x00FFFFFF) | ((val << 24u) & 0xFF000000); + val = ((uint8_t)tv1 ^ ctx->xors[tv1 >> 8]) | val; + } + + val = ((val >> 16u) & 0x0000FFFF) | ((val << 16u) & 0xFFFF0000); + for (j = 0; j < 4; j++) { + *tds_ptr++ = val; + val = ((val >> 8u) & 0x00FFFFFF) | ((val << 24u) & 0xFF000000); + } + } + + box[0] = 0; + for (i = 1; i < 256; i++) { + for (j = 1; j < 256; j++) { + uint16_t bv1 = 0; + uint16_t bv2 = j; + for (k = 0; k < 8; k++) { + if (i & (1 << k)) + bv1 ^= bv2; + bv2 *= 2; + } + + if (((uint8_t)bv1 ^ ctx->xors[bv1 >> 8]) == 1) + break; + } + box[i] = j; + + if (j == 256) /* ??? */ + return; + } + + for (i = 0; i < 256; i += 16) { + for (j = 0; j < 16; j++) { + uint8_t val = 0; + for (k = 0; k < 8; k++) { + val |= box[i | j] & (1 << k); + for (b = 0; b < 4; b++) { + uint8_t bv = box[i | j]; + if (bv & (1 << ((b + k - 4) & 7))) + val ^= 1 << k; + } + } + + ctx->sbox[i + j] = val ^ 0x63; + ctx->ibox[val ^ 0x63] = i + j; + } + } + + /* originally recalculated in Namco's code (inlined?) */ + for (i = 0; i < 8; i++) { + ctx->rcon[i] = rcon[i]; + } +} + +static void aes_decrypt_block(s14aes_handle* ctx, uint8_t* buf) { + uint32_t s0, s1, s2, s3, t0, t1, t2, t3; + uint8_t* ibox = ctx->ibox; + uint32_t* tds = ctx->tds; + uint32_t* rk = ctx->rk; + + s0 = rk[48] ^ GET_U32BE(buf + 0); + s1 = rk[49] ^ GET_U32BE(buf + 4); + s2 = rk[50] ^ GET_U32BE(buf + 8); + s3 = rk[51] ^ GET_U32BE(buf + 12); + + t0 = rk[44] ^ tds[4 * ibox[GET_B0(s1)] + 3] ^ tds[4 * ibox[GET_B1(s2)] + 2] ^ tds[4 * ibox[GET_B2(s3)] + 1] ^ tds[4 * ibox[GET_B3(s0)] + 0]; + t1 = rk[45] ^ tds[4 * ibox[GET_B0(s2)] + 3] ^ tds[4 * ibox[GET_B1(s3)] + 2] ^ tds[4 * ibox[GET_B2(s0)] + 1] ^ tds[4 * ibox[GET_B3(s1)] + 0]; + t2 = rk[46] ^ tds[4 * ibox[GET_B0(s3)] + 3] ^ tds[4 * ibox[GET_B1(s0)] + 2] ^ tds[4 * ibox[GET_B2(s1)] + 1] ^ tds[4 * ibox[GET_B3(s2)] + 0]; + t3 = rk[47] ^ tds[4 * ibox[GET_B0(s0)] + 3] ^ tds[4 * ibox[GET_B1(s1)] + 2] ^ tds[4 * ibox[GET_B2(s2)] + 1] ^ tds[4 * ibox[GET_B3(s3)] + 0]; + + s0 = rk[40] ^ tds[4 * ibox[GET_B0(t1)] + 3] ^ tds[4 * ibox[GET_B1(t2)] + 2] ^ tds[4 * ibox[GET_B2(t3)] + 1] ^ tds[4 * ibox[GET_B3(t0)] + 0]; + s1 = rk[41] ^ tds[4 * ibox[GET_B0(t2)] + 3] ^ tds[4 * ibox[GET_B1(t3)] + 2] ^ tds[4 * ibox[GET_B2(t0)] + 1] ^ tds[4 * ibox[GET_B3(t1)] + 0]; + s2 = rk[42] ^ tds[4 * ibox[GET_B0(t3)] + 3] ^ tds[4 * ibox[GET_B1(t0)] + 2] ^ tds[4 * ibox[GET_B2(t1)] + 1] ^ tds[4 * ibox[GET_B3(t2)] + 0]; + s3 = rk[43] ^ tds[4 * ibox[GET_B0(t0)] + 3] ^ tds[4 * ibox[GET_B1(t1)] + 2] ^ tds[4 * ibox[GET_B2(t2)] + 1] ^ tds[4 * ibox[GET_B3(t3)] + 0]; + + t0 = rk[36] ^ tds[4 * ibox[GET_B0(s1)] + 3] ^ tds[4 * ibox[GET_B1(s2)] + 2] ^ tds[4 * ibox[GET_B2(s3)] + 1] ^ tds[4 * ibox[GET_B3(s0)] + 0]; + t1 = rk[37] ^ tds[4 * ibox[GET_B0(s2)] + 3] ^ tds[4 * ibox[GET_B1(s3)] + 2] ^ tds[4 * ibox[GET_B2(s0)] + 1] ^ tds[4 * ibox[GET_B3(s1)] + 0]; + t2 = rk[38] ^ tds[4 * ibox[GET_B0(s3)] + 3] ^ tds[4 * ibox[GET_B1(s0)] + 2] ^ tds[4 * ibox[GET_B2(s1)] + 1] ^ tds[4 * ibox[GET_B3(s2)] + 0]; + t3 = rk[39] ^ tds[4 * ibox[GET_B0(s0)] + 3] ^ tds[4 * ibox[GET_B1(s1)] + 2] ^ tds[4 * ibox[GET_B2(s2)] + 1] ^ tds[4 * ibox[GET_B3(s3)] + 0]; + + s0 = rk[32] ^ tds[4 * ibox[GET_B0(t1)] + 3] ^ tds[4 * ibox[GET_B1(t2)] + 2] ^ tds[4 * ibox[GET_B2(t3)] + 1] ^ tds[4 * ibox[GET_B3(t0)] + 0]; + s1 = rk[33] ^ tds[4 * ibox[GET_B0(t2)] + 3] ^ tds[4 * ibox[GET_B1(t3)] + 2] ^ tds[4 * ibox[GET_B2(t0)] + 1] ^ tds[4 * ibox[GET_B3(t1)] + 0]; + s2 = rk[34] ^ tds[4 * ibox[GET_B0(t3)] + 3] ^ tds[4 * ibox[GET_B1(t0)] + 2] ^ tds[4 * ibox[GET_B2(t1)] + 1] ^ tds[4 * ibox[GET_B3(t2)] + 0]; + s3 = rk[35] ^ tds[4 * ibox[GET_B0(t0)] + 3] ^ tds[4 * ibox[GET_B1(t1)] + 2] ^ tds[4 * ibox[GET_B2(t2)] + 1] ^ tds[4 * ibox[GET_B3(t3)] + 0]; + + t0 = rk[28] ^ tds[4 * ibox[GET_B0(s1)] + 3] ^ tds[4 * ibox[GET_B1(s2)] + 2] ^ tds[4 * ibox[GET_B2(s3)] + 1] ^ tds[4 * ibox[GET_B3(s0)] + 0]; + t1 = rk[29] ^ tds[4 * ibox[GET_B0(s2)] + 3] ^ tds[4 * ibox[GET_B1(s3)] + 2] ^ tds[4 * ibox[GET_B2(s0)] + 1] ^ tds[4 * ibox[GET_B3(s1)] + 0]; + t2 = rk[30] ^ tds[4 * ibox[GET_B0(s3)] + 3] ^ tds[4 * ibox[GET_B1(s0)] + 2] ^ tds[4 * ibox[GET_B2(s1)] + 1] ^ tds[4 * ibox[GET_B3(s2)] + 0]; + t3 = rk[31] ^ tds[4 * ibox[GET_B0(s0)] + 3] ^ tds[4 * ibox[GET_B1(s1)] + 2] ^ tds[4 * ibox[GET_B2(s2)] + 1] ^ tds[4 * ibox[GET_B3(s3)] + 0]; + + s0 = rk[24] ^ tds[4 * ibox[GET_B0(t1)] + 3] ^ tds[4 * ibox[GET_B1(t2)] + 2] ^ tds[4 * ibox[GET_B2(t3)] + 1] ^ tds[4 * ibox[GET_B3(t0)] + 0]; + s1 = rk[25] ^ tds[4 * ibox[GET_B0(t2)] + 3] ^ tds[4 * ibox[GET_B1(t3)] + 2] ^ tds[4 * ibox[GET_B2(t0)] + 1] ^ tds[4 * ibox[GET_B3(t1)] + 0]; + s2 = rk[26] ^ tds[4 * ibox[GET_B0(t3)] + 3] ^ tds[4 * ibox[GET_B1(t0)] + 2] ^ tds[4 * ibox[GET_B2(t1)] + 1] ^ tds[4 * ibox[GET_B3(t2)] + 0]; + s3 = rk[27] ^ tds[4 * ibox[GET_B0(t0)] + 3] ^ tds[4 * ibox[GET_B1(t1)] + 2] ^ tds[4 * ibox[GET_B2(t2)] + 1] ^ tds[4 * ibox[GET_B3(t3)] + 0]; + + t0 = rk[20] ^ tds[4 * ibox[GET_B0(s1)] + 3] ^ tds[4 * ibox[GET_B1(s2)] + 2] ^ tds[4 * ibox[GET_B2(s3)] + 1] ^ tds[4 * ibox[GET_B3(s0)] + 0]; + t1 = rk[21] ^ tds[4 * ibox[GET_B0(s2)] + 3] ^ tds[4 * ibox[GET_B1(s3)] + 2] ^ tds[4 * ibox[GET_B2(s0)] + 1] ^ tds[4 * ibox[GET_B3(s1)] + 0]; + t2 = rk[22] ^ tds[4 * ibox[GET_B0(s3)] + 3] ^ tds[4 * ibox[GET_B1(s0)] + 2] ^ tds[4 * ibox[GET_B2(s1)] + 1] ^ tds[4 * ibox[GET_B3(s2)] + 0]; + t3 = rk[23] ^ tds[4 * ibox[GET_B0(s0)] + 3] ^ tds[4 * ibox[GET_B1(s1)] + 2] ^ tds[4 * ibox[GET_B2(s2)] + 1] ^ tds[4 * ibox[GET_B3(s3)] + 0]; + + s0 = rk[16] ^ tds[4 * ibox[GET_B0(t1)] + 3] ^ tds[4 * ibox[GET_B1(t2)] + 2] ^ tds[4 * ibox[GET_B2(t3)] + 1] ^ tds[4 * ibox[GET_B3(t0)] + 0]; + s1 = rk[17] ^ tds[4 * ibox[GET_B0(t2)] + 3] ^ tds[4 * ibox[GET_B1(t3)] + 2] ^ tds[4 * ibox[GET_B2(t0)] + 1] ^ tds[4 * ibox[GET_B3(t1)] + 0]; + s2 = rk[18] ^ tds[4 * ibox[GET_B0(t3)] + 3] ^ tds[4 * ibox[GET_B1(t0)] + 2] ^ tds[4 * ibox[GET_B2(t1)] + 1] ^ tds[4 * ibox[GET_B3(t2)] + 0]; + s3 = rk[19] ^ tds[4 * ibox[GET_B0(t0)] + 3] ^ tds[4 * ibox[GET_B1(t1)] + 2] ^ tds[4 * ibox[GET_B2(t2)] + 1] ^ tds[4 * ibox[GET_B3(t3)] + 0]; + + t0 = rk[12] ^ tds[4 * ibox[GET_B0(s1)] + 3] ^ tds[4 * ibox[GET_B1(s2)] + 2] ^ tds[4 * ibox[GET_B2(s3)] + 1] ^ tds[4 * ibox[GET_B3(s0)] + 0]; + t1 = rk[13] ^ tds[4 * ibox[GET_B0(s2)] + 3] ^ tds[4 * ibox[GET_B1(s3)] + 2] ^ tds[4 * ibox[GET_B2(s0)] + 1] ^ tds[4 * ibox[GET_B3(s1)] + 0]; + t2 = rk[14] ^ tds[4 * ibox[GET_B0(s3)] + 3] ^ tds[4 * ibox[GET_B1(s0)] + 2] ^ tds[4 * ibox[GET_B2(s1)] + 1] ^ tds[4 * ibox[GET_B3(s2)] + 0]; + t3 = rk[15] ^ tds[4 * ibox[GET_B0(s0)] + 3] ^ tds[4 * ibox[GET_B1(s1)] + 2] ^ tds[4 * ibox[GET_B2(s2)] + 1] ^ tds[4 * ibox[GET_B3(s3)] + 0]; + + s0 = rk[8 ] ^ tds[4 * ibox[GET_B0(t1)] + 3] ^ tds[4 * ibox[GET_B1(t2)] + 2] ^ tds[4 * ibox[GET_B2(t3)] + 1] ^ tds[4 * ibox[GET_B3(t0)] + 0]; + s1 = rk[9 ] ^ tds[4 * ibox[GET_B0(t2)] + 3] ^ tds[4 * ibox[GET_B1(t3)] + 2] ^ tds[4 * ibox[GET_B2(t0)] + 1] ^ tds[4 * ibox[GET_B3(t1)] + 0]; + s2 = rk[10] ^ tds[4 * ibox[GET_B0(t3)] + 3] ^ tds[4 * ibox[GET_B1(t0)] + 2] ^ tds[4 * ibox[GET_B2(t1)] + 1] ^ tds[4 * ibox[GET_B3(t2)] + 0]; + s3 = rk[11] ^ tds[4 * ibox[GET_B0(t0)] + 3] ^ tds[4 * ibox[GET_B1(t1)] + 2] ^ tds[4 * ibox[GET_B2(t2)] + 1] ^ tds[4 * ibox[GET_B3(t3)] + 0]; + + t0 = rk[4 ] ^ tds[4 * ibox[GET_B0(s1)] + 3] ^ tds[4 * ibox[GET_B1(s2)] + 2] ^ tds[4 * ibox[GET_B2(s3)] + 1] ^ tds[4 * ibox[GET_B3(s0)] + 0]; + t1 = rk[5 ] ^ tds[4 * ibox[GET_B0(s2)] + 3] ^ tds[4 * ibox[GET_B1(s3)] + 2] ^ tds[4 * ibox[GET_B2(s0)] + 1] ^ tds[4 * ibox[GET_B3(s1)] + 0]; + t2 = rk[6 ] ^ tds[4 * ibox[GET_B0(s3)] + 3] ^ tds[4 * ibox[GET_B1(s0)] + 2] ^ tds[4 * ibox[GET_B2(s1)] + 1] ^ tds[4 * ibox[GET_B3(s2)] + 0]; + t3 = rk[7 ] ^ tds[4 * ibox[GET_B0(s0)] + 3] ^ tds[4 * ibox[GET_B1(s1)] + 2] ^ tds[4 * ibox[GET_B2(s2)] + 1] ^ tds[4 * ibox[GET_B3(s3)] + 0]; + + buf[0 ] = GET_B3(rk[0]) ^ ibox[GET_B3(t0)]; + buf[1 ] = GET_B2(rk[0]) ^ ibox[GET_B2(t3)]; + buf[2 ] = GET_B1(rk[0]) ^ ibox[GET_B1(t2)]; + buf[3 ] = GET_B0(rk[0]) ^ ibox[GET_B0(t1)]; + buf[4 ] = GET_B3(rk[1]) ^ ibox[GET_B3(t1)]; + buf[5 ] = GET_B2(rk[1]) ^ ibox[GET_B2(t0)]; + buf[6 ] = GET_B1(rk[1]) ^ ibox[GET_B1(t3)]; + buf[7 ] = GET_B0(rk[1]) ^ ibox[GET_B0(t2)]; + buf[8 ] = GET_B3(rk[2]) ^ ibox[GET_B3(t2)]; + buf[9 ] = GET_B2(rk[2]) ^ ibox[GET_B2(t1)]; + buf[10] = GET_B1(rk[2]) ^ ibox[GET_B1(t0)]; + buf[11] = GET_B0(rk[2]) ^ ibox[GET_B0(t3)]; + buf[12] = GET_B3(rk[3]) ^ ibox[GET_B3(t3)]; + buf[13] = GET_B2(rk[3]) ^ ibox[GET_B2(t2)]; + buf[14] = GET_B1(rk[3]) ^ ibox[GET_B1(t1)]; + buf[15] = GET_B0(rk[3]) ^ ibox[GET_B0(t0)]; +} + +/* **************************** */ + +s14aes_handle* s14aes_init() { + s14aes_handle* ctx = malloc(sizeof(s14aes_handle)); + if (!ctx) goto fail; + + aes_init_state(ctx); + + return ctx; +fail: + return NULL; +} + +void s14aes_close(s14aes_handle* ctx) { + free(ctx); +} + +void s14aes_set_key(s14aes_handle* ctx, const uint8_t* key) { + aes_init_key(ctx, key); +} + +void s14aes_decrypt(s14aes_handle* ctx, uint8_t* buf) { + aes_decrypt_block(ctx, buf); +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.h b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.h new file mode 100644 index 000000000..7f8d6dbed --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.h @@ -0,0 +1,19 @@ +#ifndef _G7221_DECODER_AES_H +#define _G7221_DECODER_AES_H + +#include + +typedef struct s14aes_handle s14aes_handle; + +/* init/close handle (AES-192 in ECB mode) */ +s14aes_handle* s14aes_init(); + +void s14aes_close(s14aes_handle* ctx); + +/* set new key (can be called multiple times) */ +void s14aes_set_key(s14aes_handle* ctx, const uint8_t* key); + +/* decrypt a single 0x10 block */ +void s14aes_decrypt(s14aes_handle* ctx, uint8_t* buf); + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_lib.c b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_lib.c new file mode 100644 index 000000000..b5e474145 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_lib.c @@ -0,0 +1,1257 @@ +#include +#include +#include + +#include "g7221_decoder_lib.h" +#include "g7221_decoder_aes.h" + + +/* Decodes Siren14 from Namco's BNSF, a mono MLT/DCT-based codec for speech/sound (low bandwidth). + * Reverse engineered for various exes with info from Polycom's reference int decoder. + * - Reference decoder and codec info: https://www.itu.int/rec/T-REC-G.722.1/en + * + * Technically the name is "ITU-T G.722.1 Annex C" (official ITU-T spec), while "Siren14" + * was Polycom's original format with slightly different frames, though Namco calls it + * "Siren14 Version 3.02 For Products" while using G.722.1's frame format. + * Siren7 (7000hz bandwidth) isn't supported, only Siren14 (14000hz). + * + * Very roughly the encoder works like this: + * - Apply a Modulated Lapped Transform (MLT) function over 640*2 samples to get spectrum + * coefficients (can be decomposed into a window, overlap and add with a DCT-IV, of samples + * from a current frame and samples from a prev frame). + * - resulting coefs are divided into 28 bands called "regions" of 500hz. + * - Each region contains 20 MLT spectrum coefs, total 28 regions * 500hz = 14000hz. + * - Bands above 14khz are ignored (overall output quality isn't high). + * - Pack amplitude envelope bits, defined as the RMS (Root-Mean-Square) of the coefs in + * the region. First region sets all bits, rest is differentially and huffman coded. + * Remaning bits are left to quantize coefs. + * - Regions are given a "category" to quantize, that define the number of quantization bits + * and other coding parameters. Results are combined into vector indices, + * and Huffman-coded (frequent vectors require less bits). + * Decoding thus unpacks amplitudes, region coefs and does inverse MLT. + * + * Namco roughly follows the reference decoder ('refdec') with some differences: + * - uses mostly int32, while refdec has int16 with exact rounding/overflow handling (no output diffs) + * - modified random number generator (minor output diffs) + * - very minor change in bit unpacking (minor output diffs) + * - modified DCT-IV optimizations, scaling and window functions (minor output diffs) + * - internally PCM16 bufs, but converts to float (sample/32768.0) afterwards if the platform needs it + * - less error control (on error decoder is supposed to repeat last coefs) + * - can't decode Siren7, and given output diffs it's not actually ITU-compliant + * - minor optimizations here and there but otherwise very similar + * This decoder generally uses Polycom's terminology, and while some parts like the bitreader could be + * reimplemented they are mostly untouched for documentation purposes. + * + * TODO: missing some validations (may segfault on bad data), + * access indexes with (idx & max) and clamp buffer reads + */ + +#include "g7221_decoder_lib_data.h" + +/***************************************************************************** + * IMLT + *****************************************************************************/ + +static int imlt_window(int16_t* new_samples, int16_t* old_samples, int16_t* out_samples) { + int i; + int sample_lo, sample_hi; + int16_t win_val_lo, win_val_hi, new_val, old_val; + const int16_t *win_ptr_lo, *win_ptr_hi; + int16_t *new_ptr, *old_ptr, *out_ptr_lo, *out_ptr_hi; + + + /* overlap 2nd half of prev frame's samples and 1st half of current frame's samples with + * a window function to smooth out between frames */ + win_ptr_lo = imlt_samples_window + 0; + win_ptr_hi = imlt_samples_window + 640; + new_ptr = new_samples + 320; + old_ptr = old_samples + 0; + out_ptr_lo = out_samples + 0; + out_ptr_hi = out_samples + 640; + + while (out_ptr_lo != out_ptr_hi) { + win_val_lo = *win_ptr_lo++; + win_val_hi = *--win_ptr_hi; + new_val = *--new_ptr; + old_val = *old_ptr++; + + sample_lo = (new_val * win_val_lo + old_val * *win_ptr_hi + 32768) >> 13; + if (sample_lo > 32767) + sample_lo = 32767; + else if (sample_lo < -32768) + sample_lo = -32768; + *out_ptr_lo++ = sample_lo; + + sample_hi = (new_val * win_val_hi - old_val * win_val_lo + 32768) >> 13; + if (sample_hi > 32767) + sample_hi = 32767; + else if (sample_hi < -32768) + sample_hi = -32768; + *--out_ptr_hi = sample_hi; + } + + /* save the 2nd half of the new samples to use above in next frame */ + old_ptr = old_samples + 0; + new_ptr = new_samples + 320; + + for (i = 0; i < 320; i++) { + old_ptr[i] = new_ptr[i]; + } + + return 0; +} + +/* "dct4_x640_int" */ +static int imlt_dct4(int16_t* mlt_coefs, int16_t* new_samples, int mag_shift) { + int i, j, k, n; + const uint8_t *set1_ptr; + int mod_shift, sub_shift; + + + /* vs refdec: very optimized, output is slightly different (louder) but it's massively + * faster (around 20% vs float refdec, int refdec was very slow to begin with). + * Can't quite clean this due to the complex math simplifications. + * Should correspond to: cos(PI*(t+0.5)*(k+0.5)/block_length) */ + + /* rotation butterflies? (cos/sin 640 groups) */ + { + int cos_val, sin_val; + const uint16_t *cos_ptr, *sin_ptr; + int16_t mlt_val_lo, mlt_val_hi; + int16_t *mlt_ptr_lo, *mlt_ptr_hi; + + mlt_ptr_lo = mlt_coefs + 0; + mlt_ptr_hi = mlt_coefs + 640; + cos_ptr = &imlt_cos_tables[0]; /* cos_table_64 */ + sin_ptr = &imlt_sin_tables[0]; /* sin_table_64 */ + + for (i = 40; i > 0; --i) { + cos_val = *cos_ptr++; + sin_val = *sin_ptr++; + mlt_val_lo = *mlt_ptr_lo >> 1; + *mlt_ptr_lo++ = (cos_val * mlt_val_lo + 32768) >> 16; + *--mlt_ptr_hi = (sin_val * -mlt_val_lo + 32768) >> 16; + + cos_val = *cos_ptr++; + sin_val = *sin_ptr++; + mlt_val_lo = *mlt_ptr_lo >> 1; + *mlt_ptr_lo++ = (cos_val * mlt_val_lo + 32768) >> 16; + *--mlt_ptr_hi = (sin_val * mlt_val_lo + 32768) >> 16; + } + + for (i = 120; i > 0; --i) { + cos_val = *cos_ptr++; + sin_val = *sin_ptr++; + mlt_val_lo = *mlt_ptr_lo >> 1; + mlt_val_hi = *--mlt_ptr_hi >> 1; + *mlt_ptr_lo++ = (cos_val * mlt_val_lo + sin_val * mlt_val_hi + 32768) >> 16; + *mlt_ptr_hi = (sin_val * -mlt_val_lo + cos_val * mlt_val_hi + 32768) >> 16; + + cos_val = *cos_ptr++; + sin_val = *sin_ptr++; + mlt_val_lo = *mlt_ptr_lo >> 1; + mlt_val_hi = *--mlt_ptr_hi >> 1; + *mlt_ptr_lo++ = (cos_val * mlt_val_lo + sin_val * mlt_val_hi + 32768) >> 16; + *mlt_ptr_hi = (sin_val * mlt_val_lo - cos_val * mlt_val_hi + 32768) >> 16; + } + } + + /* sum/diff butterflies? */ + { + int16_t mlt_val_lo, mlt_val_mlo, mlt_val_mhi, mlt_val_hi; + int16_t *mlt_ptr, *mlt_ptr_lo, *mlt_ptr_mlo, *mlt_ptr_mhi, *mlt_ptr_hi; + + mlt_ptr = mlt_coefs + 0; + for (i = 2; i > 0; --i) { + mlt_ptr_lo = mlt_ptr + 0; + mlt_ptr_hi = mlt_ptr + 320; + mlt_ptr_mlo = mlt_ptr + 160; + mlt_ptr_mhi = mlt_ptr + 160; + for (j = 80; j > 0; --j) { + mlt_val_lo = *mlt_ptr_lo; + mlt_val_hi = *--mlt_ptr_hi; + mlt_val_mhi = *--mlt_ptr_mhi; + mlt_val_mlo = *mlt_ptr_mlo; + *mlt_ptr_lo++ = (mlt_val_hi + mlt_val_lo) >> 1; + *mlt_ptr_mlo++ = (mlt_val_lo - mlt_val_hi) >> 1; + *mlt_ptr_mhi = (mlt_val_mlo + mlt_val_mhi) >> 1; + *mlt_ptr_hi = (mlt_val_mhi - mlt_val_mlo) >> 1; + } + mlt_ptr += 320; + } + } + + /* helper table used in next 3 sections */ + set1_ptr = imlt_set1_table; + + /* rotation butterflies? (cos/sin 160/80/40/20/10 groups) */ + { + int cos_val, sin_val; + const uint16_t *cos_ptr, *sin_ptr, *cos_ptr_lo, *sin_ptr_lo; + int16_t mlt_val_lo, mlt_val_hi, mlt_val_mlo, mlt_val_mhi; + int16_t *mlt_ptr, *mlt_ptr_lo, *mlt_ptr_hi, *mlt_ptr_mlo, *mlt_ptr_mhi; + + cos_ptr = &imlt_cos_tables[320+160]; /* cos_table_16 > 8 > 4 > 2 */ + sin_ptr = &imlt_sin_tables[320+160]; /* sin_table_16 > 8 > 4 > 2 */ + + for (n = 160; n >= 20; n /= 2) { + mlt_ptr = mlt_coefs + 0; + while (mlt_ptr < mlt_coefs + 640) { + for (j = *set1_ptr; j > 0; --j) { + mlt_ptr_lo = mlt_ptr + 0; + mlt_ptr_hi = mlt_ptr + n; + mlt_ptr_mlo = mlt_ptr + (n / 2); + mlt_ptr_mhi = mlt_ptr + (n / 2); + for (k = n / 4; k > 0; --k) { + mlt_val_lo = *mlt_ptr_lo; + mlt_val_hi = *--mlt_ptr_hi; + mlt_val_mhi = *--mlt_ptr_mhi; + mlt_val_mlo = *mlt_ptr_mlo; + *mlt_ptr_lo++ = mlt_val_lo + mlt_val_hi; + *mlt_ptr_mlo++ = mlt_val_lo - mlt_val_hi; + *mlt_ptr_mhi = mlt_val_mlo + mlt_val_mhi; + *mlt_ptr_hi = mlt_val_mhi - mlt_val_mlo; + } + mlt_ptr += n; + } + set1_ptr++; + + for (j = *set1_ptr; j > 0; --j) { + mlt_ptr_lo = mlt_ptr + 0; + mlt_ptr_hi = mlt_ptr + n; + cos_ptr_lo = cos_ptr + 0; + sin_ptr_lo = sin_ptr + 0; + for (k = n / 4; k > 0; --k) { + cos_val = *cos_ptr_lo++; + sin_val = *sin_ptr_lo++; + mlt_val_lo = *mlt_ptr_lo; + mlt_val_hi = *--mlt_ptr_hi; + *mlt_ptr_lo++ = (cos_val * mlt_val_lo + sin_val * mlt_val_hi + 32768) >> 16; + *mlt_ptr_hi = (sin_val * -mlt_val_lo + cos_val * mlt_val_hi + 32768) >> 16; + + cos_val = *cos_ptr_lo++; + sin_val = *sin_ptr_lo++; + mlt_val_lo = *mlt_ptr_lo; + mlt_val_hi = *--mlt_ptr_hi; + *mlt_ptr_lo++ = (cos_val * mlt_val_lo + sin_val * mlt_val_hi + 32768) >> 16; + *mlt_ptr_hi = (sin_val * mlt_val_lo - cos_val * mlt_val_hi + 32768) >> 16; + } + mlt_ptr += n; + } + set1_ptr++; + } + + /* next sub-tables */ + cos_ptr += n / 2; + sin_ptr += n / 2; + } + } + + /* rotation butterflies? (cos/sin 5 groups) */ + { + int cos_val, sin_val; + const uint16_t *cos_ptr, *sin_ptr; + int16_t mlt_val_lo, mlt_val_hi, mlt_val_mlo, mlt_val_mhi; + int16_t *mlt_ptr; + + /* n/cos-sin would continue from above but for clarity: */ + cos_ptr = &imlt_cos_tables[320+160+80+40+20+10]; /* cos_table_1 */ + sin_ptr = &imlt_sin_tables[320+160+80+40+20+10]; /* sin_table_1 */ + + { + n = 10; + mlt_ptr = mlt_coefs + 0; + while (mlt_ptr < mlt_coefs + 640) { + for (j = *set1_ptr; j > 0; --j) { + mlt_val_lo = mlt_ptr[0]; + mlt_val_hi = mlt_ptr[n - 1]; + mlt_val_mlo = mlt_ptr[n / 2 - 1]; + mlt_val_mhi = mlt_ptr[n / 2]; + mlt_ptr[0] = mlt_val_lo + mlt_val_hi; + mlt_ptr[n / 2] = mlt_val_lo - mlt_val_hi; + mlt_ptr[n / 2 - 1] = mlt_val_mhi + mlt_val_mlo; + mlt_ptr[n - 1] = mlt_val_mlo - mlt_val_mhi; + + mlt_val_lo = mlt_ptr[1]; + mlt_val_hi = mlt_ptr[n - 2]; + mlt_val_mlo = mlt_ptr[n / 2 - 2]; + mlt_val_mhi = mlt_ptr[n / 2 + 1]; + mlt_ptr[1] = mlt_val_hi + mlt_val_lo; + mlt_ptr[n / 2 + 1] = mlt_val_lo - mlt_val_hi; + mlt_ptr[n / 2 - 2] = mlt_val_mhi + mlt_val_mlo; + mlt_ptr[n - 2] = mlt_val_mlo - mlt_val_mhi; + + mlt_val_lo = mlt_ptr[2]; + mlt_val_hi = mlt_ptr[n - 3]; + mlt_ptr[2] = mlt_val_hi + mlt_val_lo; + mlt_ptr[n / 2 + 2] = mlt_val_lo - mlt_val_hi; + + mlt_ptr += n; + } + + cos_val = cos_ptr[0]; + sin_val = sin_ptr[0]; + mlt_val_lo = mlt_ptr[0]; + mlt_val_hi = mlt_ptr[n - 1]; + mlt_ptr[0] = (cos_val * mlt_val_lo + sin_val * mlt_val_hi + 32768) >> 16; + mlt_ptr[n - 1] = (sin_val * mlt_val_lo - cos_val * mlt_val_hi + 32768) >> 16; + + cos_val = cos_ptr[1]; + sin_val = sin_ptr[1]; + mlt_val_lo = mlt_ptr[1]; + mlt_val_hi = mlt_ptr[n - 2]; + mlt_ptr[1] = (cos_val * mlt_val_lo + sin_val * mlt_val_hi + 32768) >> 16; + mlt_ptr[n - 2] = (sin_val * -mlt_val_lo + cos_val * mlt_val_hi + 32768) >> 16; + + cos_val = cos_ptr[2]; + sin_val = sin_ptr[2]; + mlt_val_lo = mlt_ptr[2]; + mlt_val_hi = mlt_ptr[n - 3]; + mlt_ptr[2] = (cos_val * mlt_val_lo + sin_val * mlt_val_hi + 32768) >> 16; + mlt_ptr[n - 3]= (sin_val * mlt_val_lo - cos_val * mlt_val_hi + 32768) >> 16; + + cos_val = cos_ptr[3]; + sin_val = sin_ptr[3]; + mlt_val_lo = mlt_ptr[3]; + mlt_val_hi = mlt_ptr[n - 4]; + mlt_ptr[3] = (cos_val * mlt_val_lo + sin_val * mlt_val_hi + 32768) >> 16; + mlt_ptr[n - 4] = (sin_val * -mlt_val_lo + cos_val * mlt_val_hi + 32768) >> 16; + + cos_val = cos_ptr[4]; + sin_val = sin_ptr[4]; + mlt_val_lo = mlt_ptr[4]; + mlt_val_hi = mlt_ptr[n - 5]; + mlt_ptr[4] = (cos_val * mlt_val_lo + sin_val * mlt_val_hi + 32768) >> 16; + mlt_ptr[n - 5] = (sin_val * mlt_val_lo - cos_val * mlt_val_hi + 32768) >> 16; + + mlt_ptr += n; + set1_ptr += 2; + } + } + } + + + mod_shift = mag_shift - 1; + sub_shift = 1; + if (mod_shift >= 8) + sub_shift = 2; + mod_shift -= sub_shift; + + + /* dct core? */ + { + const int16_t *mlt_ptr; + int16_t *new_ptr; + + mlt_ptr = mlt_coefs + 0; + new_ptr = new_samples + 0; + while (1) { + for (i = *set1_ptr; i; --i) { + new_ptr[0] = (mlt_ptr[4] + mlt_ptr[3] + mlt_ptr[2] + mlt_ptr[1] + mlt_ptr[0]) >> sub_shift; + new_ptr[1] = (19261 * mlt_ptr[1] + 31164 * mlt_ptr[0] - 19261 * mlt_ptr[3] - 31164 * mlt_ptr[4]) >> (sub_shift + 15); + new_ptr[2] = (26510 * mlt_ptr[4] + 26510 * mlt_ptr[0] - 10126 * mlt_ptr[1] - 32768 * mlt_ptr[2] - 10126 * mlt_ptr[3]) >> (sub_shift + 15); + new_ptr[3] = (31164 * mlt_ptr[3] + 19261 * mlt_ptr[0] - 31164 * mlt_ptr[1] - 19261 * mlt_ptr[4]) >> (sub_shift + 15); + new_ptr[4] = (10126 * mlt_ptr[4] + 32768 * mlt_ptr[2] + 10126 * mlt_ptr[0] - 26510 * mlt_ptr[1] - 26510 * mlt_ptr[3]) >> (sub_shift + 15); + mlt_ptr += 5; + new_ptr += 5; + } + set1_ptr += 2; + + if (mlt_ptr >= mlt_coefs + 640) + break; + + new_ptr[0] = ( 5126 * mlt_ptr[4] + 14876 * mlt_ptr[3] + 23170 * mlt_ptr[2] + 32365 * mlt_ptr[0] + 29197 * mlt_ptr[1]) >> (sub_shift + 15); + new_ptr[1] = (-14876 * mlt_ptr[4] + -32365 * mlt_ptr[3] + 5126 * mlt_ptr[1] + 29197 * mlt_ptr[0] - 23170 * mlt_ptr[2]) >> (sub_shift + 15); + new_ptr[2] = ( 23170 * mlt_ptr[4] + 23170 * mlt_ptr[3] + -23170 * mlt_ptr[1] + 23170 * mlt_ptr[0] - 23170 * mlt_ptr[2]) >> (sub_shift + 15); + new_ptr[3] = (-29197 * mlt_ptr[4] + 5126 * mlt_ptr[3] + 23170 * mlt_ptr[2] + 14876 * mlt_ptr[0] - 32365 * mlt_ptr[1]) >> (sub_shift + 15); + new_ptr[4] = ( 32365 * mlt_ptr[4] + -29197 * mlt_ptr[3] + 23170 * mlt_ptr[2] + 5126 * mlt_ptr[0] - 14876 * mlt_ptr[1]) >> (sub_shift + 15); + mlt_ptr += 5; + new_ptr += 5; + } + } + + /* swapping and sum/diffs? */ + { + const uint8_t *set2_ptr; + int16_t *mlt_ptr, *new_ptr; + int16_t tmp1_val_a, tmp1_val_b; + int16_t *tmp0_ptr, *tmp1_ptr, *tmp1_ptr_lo, *tmp1_ptr_mlo, *tmp1_ptr_mhi, *tmp2_ptr; + + set2_ptr = imlt_set2_table; + + mlt_ptr = mlt_coefs + 0; + new_ptr = new_samples + 0; + while (new_ptr < new_samples + 640) { + for (i = *set2_ptr; i; --i) { + *mlt_ptr++ = new_ptr[0]; + *mlt_ptr++ = new_ptr[5]; + *mlt_ptr++ = new_ptr[1]; + *mlt_ptr++ = new_ptr[6]; + *mlt_ptr++ = new_ptr[2]; + *mlt_ptr++ = new_ptr[7]; + *mlt_ptr++ = new_ptr[3]; + *mlt_ptr++ = new_ptr[8]; + *mlt_ptr++ = new_ptr[4]; + *mlt_ptr++ = new_ptr[9]; + new_ptr += 10; + } + set2_ptr++; + + *mlt_ptr++ = new_ptr[0]; + *mlt_ptr++ = new_ptr[9] + new_ptr[1]; + *mlt_ptr++ = new_ptr[1] - new_ptr[9]; + *mlt_ptr++ = new_ptr[2] - new_ptr[8]; + *mlt_ptr++ = new_ptr[8] + new_ptr[2]; + *mlt_ptr++ = new_ptr[7] + new_ptr[3]; + *mlt_ptr++ = new_ptr[3] - new_ptr[7]; + *mlt_ptr++ = new_ptr[4] - new_ptr[6]; + *mlt_ptr++ = new_ptr[6] + new_ptr[4]; + *mlt_ptr++ = new_ptr[5]; + new_ptr += 10; + } + + /* below is some three way swapping, tmp ptrs change between mlt<>new */ + tmp0_ptr = mlt_coefs + 640; + tmp1_ptr = new_samples + 640; + for (n = 20; n <= 160; n *= 2) { + tmp2_ptr = tmp0_ptr + 0; + tmp0_ptr = tmp1_ptr - 640; + tmp1_ptr = tmp2_ptr - 640; + do { + for (j = *set2_ptr; j > 0; --j) { + tmp1_ptr_mhi = tmp1_ptr + (n / 2); + for (k = n / 4; k > 0; --k) { + *tmp0_ptr++ = *tmp1_ptr++; + *tmp0_ptr++ = *tmp1_ptr_mhi++; + *tmp0_ptr++ = *tmp1_ptr++; + *tmp0_ptr++ = *tmp1_ptr_mhi++; + } + tmp1_ptr += n / 2; + } + set2_ptr++; + + if (tmp1_ptr >= tmp2_ptr) + break; + + tmp1_ptr_lo = tmp1_ptr + 0; + tmp1_ptr_mlo = tmp1_ptr + (n - 1); + + *tmp0_ptr++ = *tmp1_ptr_lo++; + + tmp1_val_a = *tmp1_ptr_lo++; + tmp1_val_b = *tmp1_ptr_mlo; + *tmp0_ptr++ = tmp1_val_b + tmp1_val_a; + *tmp0_ptr++ = tmp1_val_a - tmp1_val_b; + for (j = (n / 2 - 2) / 2; j > 0; --j) { + tmp1_val_a = *tmp1_ptr_lo++; + tmp1_val_b = *--tmp1_ptr_mlo; + *tmp0_ptr++ = tmp1_val_a - tmp1_val_b; + *tmp0_ptr++ = tmp1_val_b + tmp1_val_a; + + tmp1_val_a = *tmp1_ptr_lo++; + tmp1_val_b = *--tmp1_ptr_mlo; + *tmp0_ptr++ = tmp1_val_b + tmp1_val_a; + *tmp0_ptr++ = tmp1_val_a - tmp1_val_b; + } + *tmp0_ptr++ = -*tmp1_ptr_lo; + tmp1_ptr += n; + } + while (tmp1_ptr < tmp2_ptr); + } + } + + /* final modifications and post scaling? */ + { + int16_t mlt_val_lo, mlt_val_mhi, mlt_val_mlo, mlt_val_hi; + const int16_t *mlt_ptr_lo, *mlt_ptr_hi, *mlt_ptr_mlo, *mlt_ptr_mhi; + int16_t *new_ptr; + + if (mod_shift <= 0) { + /* negative scale (right shift) */ + mod_shift = -mod_shift; + + mlt_ptr_lo = mlt_coefs + 0; + mlt_ptr_mlo = mlt_coefs + 160; + mlt_ptr_mhi = mlt_coefs + 480; + mlt_ptr_hi = mlt_coefs + 640; + new_ptr = new_samples + 0; + + mlt_val_lo = *mlt_ptr_lo++; + *new_ptr++ = mlt_val_lo << mod_shift; + + mlt_val_mlo = *mlt_ptr_mlo++; + mlt_val_hi = *--mlt_ptr_hi; + *new_ptr++ = (mlt_val_hi + mlt_val_mlo) << mod_shift; + *new_ptr++ = (mlt_val_mlo - mlt_val_hi) << mod_shift; + + for (i = 159; i > 0; --i) { + mlt_val_lo = *mlt_ptr_lo++; + mlt_val_mhi = *--mlt_ptr_mhi; + *new_ptr++ = (mlt_val_lo - mlt_val_mhi) << mod_shift; + *new_ptr++ = (mlt_val_mhi + mlt_val_lo) << mod_shift; + + mlt_val_mlo = *mlt_ptr_mlo++; + mlt_val_hi = *--mlt_ptr_hi; + *new_ptr++ = (mlt_val_hi + mlt_val_mlo) << mod_shift; + *new_ptr++ = (mlt_val_mlo - mlt_val_hi) << mod_shift; + } + + *new_ptr = -*mlt_ptr_mlo << mod_shift; + } + else { + /* same but positive (left shift) */ + + mlt_ptr_lo = mlt_coefs + 0; + mlt_ptr_mlo = mlt_coefs + 160; + mlt_ptr_mhi = mlt_coefs + 480; + mlt_ptr_hi = mlt_coefs + 640; + new_ptr = new_samples + 0; + + mlt_val_lo = *mlt_ptr_lo++; + *new_ptr++ = mlt_val_lo >> mod_shift; + + mlt_val_mlo = *mlt_ptr_mlo++; + mlt_val_hi = *--mlt_ptr_hi; + *new_ptr++ = (mlt_val_hi + mlt_val_mlo) >> mod_shift; + *new_ptr++ = (mlt_val_mlo - mlt_val_hi) >> mod_shift; + + for (i = 159; i > 0; --i) { + mlt_val_lo = *mlt_ptr_lo++; + mlt_val_mhi = *--mlt_ptr_mhi; + *new_ptr++ = (mlt_val_lo - mlt_val_mhi) >> mod_shift; + *new_ptr++ = (mlt_val_mhi + mlt_val_lo) >> mod_shift; + + mlt_val_mlo = *mlt_ptr_mlo++; + mlt_val_hi = *--mlt_ptr_hi; + *new_ptr++ = (mlt_val_hi + mlt_val_mlo) >> mod_shift; + *new_ptr++ = (mlt_val_mlo - mlt_val_hi) >> mod_shift; + } + + *new_ptr = -*mlt_ptr_mlo >> mod_shift; + } + } + + return 0; +} + +/* "inverse_MLT" */ +static int rmlt_coefs_to_samples(int mag_shift, int16_t* mlt_coefs, int16_t* old_samples, int16_t* out_samples /*, int p_samples_done*/) { + int res; + int16_t new_samples[640]; + + /* block transform MLT spectrum coefs to time domain PCM samples using DCT-IV (inverse) */ + res = imlt_dct4(mlt_coefs, new_samples, mag_shift); + if (res < 0) return res; + + /* apply IMLT overlapped window filter function (640 samples) */ + res = imlt_window(new_samples, old_samples, out_samples); + if (res < 0) return res; + + //*p_samples_done = 640; /* in Namco's code but actually ignored */ + + return 0; +} + +/***************************************************************************** + * UNPACKING + *****************************************************************************/ + +static inline int calc_offset(const int* absolute_region_power_index, int available_bits) { + int region, cat_index; + int offset, delta; + + offset = -32; + delta = 32; + do { + int test_offset = offset + delta; + int bits = 0; + + /* obtain a category for each region using the test offset */ + for (region = 0; region < NUMBER_OF_REGIONS; region++) { + cat_index = (test_offset - absolute_region_power_index[region]) / 2; + if (cat_index < 0) + cat_index = 0; + else if (cat_index > NUM_CATEGORIES - 1) + cat_index = NUM_CATEGORIES - 1; + + /* compute the number of bits that will be used given the cat assignments */ + bits += expected_bits_table[cat_index]; + } + + /* if (bits > available_bits - 32) then divide the offset region for the bin search */ + if (bits >= available_bits - 32) { + offset = test_offset; + } + delta /= 2; + } + while (delta > 0); + + return offset; +} + +static inline void compute_raw_power_categories(int* power_categories, const int* absolute_region_power_index, int offset) { + int region, cat_index; + + for (region = 0; region < NUMBER_OF_REGIONS; region++) { + cat_index = (offset - absolute_region_power_index[region]) / 2; + if (cat_index < 0) + cat_index = 0; + else if (cat_index > NUM_CATEGORIES - 1) + cat_index = NUM_CATEGORIES - 1; + + power_categories[region] = cat_index; + } +} + +static inline void comp_powercat_and_catbalance(int* power_categories, int* category_balances, const int* absolute_region_power_index, int available_bits, int offset) { + int region, ccp; + int max_rate_categories[NUMBER_OF_REGIONS]; + int min_rate_categories[NUMBER_OF_REGIONS]; + int temp_category_balances[2*NUM_CATEGORIZATION_CONTROL_POSSIBILITIES]; + int expected_number_of_code_bits, max, min, max_rate_pointer, min_rate_pointer; + + + /* Namco uses power_categories directly instead of max_rate_categories, but we'll separate for clarity. + * It also loads min_rate_categories and expected_number_of_code_bits in the previous region loop */ + expected_number_of_code_bits = 0; + for (region = 0; region < NUMBER_OF_REGIONS; region++) { + int power_category = power_categories[region]; + max_rate_categories[region] = power_category; + min_rate_categories[region] = power_category; + expected_number_of_code_bits += expected_bits_table[power_category]; + } + + max = expected_number_of_code_bits; + min = expected_number_of_code_bits; + max_rate_pointer = NUM_CATEGORIZATION_CONTROL_POSSIBILITIES; + min_rate_pointer = NUM_CATEGORIZATION_CONTROL_POSSIBILITIES; + + for (ccp = 0; ccp < NUM_CATEGORIZATION_CONTROL_POSSIBILITIES - 1; ccp++) { + + if (max + min <= available_bits * 2) { + int raw_min = 10000; + int raw_min_index = 0; + + /* Search from lowest freq regions to highest for best */ + /* region to reassign to a higher bit rate category. */ + for (region = 0; region < NUMBER_OF_REGIONS; region++) { + if (max_rate_categories[region] > 0) { + int tmp = (offset - absolute_region_power_index[region]) - (max_rate_categories[region] * 2); + if (tmp < raw_min) { + raw_min = tmp; + raw_min_index = region; + } + } + } + + max_rate_pointer--; + temp_category_balances[max_rate_pointer] = raw_min_index; + + max -= expected_bits_table[max_rate_categories[raw_min_index]]; + max_rate_categories[raw_min_index]--; + max += expected_bits_table[max_rate_categories[raw_min_index]]; + } + else { + int raw_max = -10000; + int raw_max_index = NUMBER_OF_REGIONS - 1; + + /* Search from highest freq regions to lowest for best region to reassign to a lower bit rate category. */ + for (region = NUMBER_OF_REGIONS - 1; region >= 0; region--) { + if (min_rate_categories[region] < NUM_CATEGORIES - 1) { + int tmp = (offset - absolute_region_power_index[region]) - (min_rate_categories[region] * 2); + if (tmp > raw_max) { + raw_max = tmp; + raw_max_index = region; + } + } + } + + temp_category_balances[min_rate_pointer] = raw_max_index; + min_rate_pointer++; + + min -= expected_bits_table[min_rate_categories[raw_max_index]]; + min_rate_categories[raw_max_index]++; + min += expected_bits_table[min_rate_categories[raw_max_index]]; + } + } + + for (region = 0; region < NUMBER_OF_REGIONS; region++) { + power_categories[region] = max_rate_categories[region]; + } + + for (ccp = 0; ccp < NUM_CATEGORIZATION_CONTROL_POSSIBILITIES - 1; ccp++) { + category_balances[ccp] = temp_category_balances[max_rate_pointer + ccp]; + } +} + +static int categorize(int available_bits, const int* absolute_region_power_index, int* power_categories, int* category_balances) { + int offset; + + /* compensate increased bit usage for higher bitrates (used?) */ + if (available_bits > MAX_DCT_LENGTH) { + available_bits = 5 * (available_bits - MAX_DCT_LENGTH) / 8 + MAX_DCT_LENGTH; + } + + /* calculate category stuff (originally inline'd) */ + + offset = calc_offset(absolute_region_power_index, available_bits); + + compute_raw_power_categories(power_categories, absolute_region_power_index, offset); + + comp_powercat_and_catbalance(power_categories, category_balances, absolute_region_power_index, available_bits, offset); + + return 0; +} + +static inline void index_to_array(int index, int* array_cv, int category) { + int q, p; + int max_bin_plus_one = max_bin_plus1[category]; + int inverse_of_max_bin_plus_one_scaled = max_bin_plus_one_inverse_scaled[category]; + + /* vs refdec: unrolled, inline'd version of the inverted loop, with some ops simplified + * (depending on pre-scaled tables), since this is called many times. + * From tests it's not too noticeable though. */ + + p = index; + /* fills array (vector_dimension[category] - 1) times inversely */ + switch (category) { + case 0: + case 1: + case 2: + q = (p * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[1] = p - (q * max_bin_plus_one); + p = q; + + q = (q * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[0] = p - (q * max_bin_plus_one); + //p = q; + break; + + case 3: + q = (p * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[3] = p - (q * 5); //max_bin_plus_one = 5 + p = q; + + q = (q * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[2] = p - (q * 5); //max_bin_plus_one = 5 + p = q; + + q = (q * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[1] = p - (q * 5); //max_bin_plus_one = 5 + p = q; + + q = (q * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[0] = p - (q * 5); //max_bin_plus_one = 5 + //p = q; + break; + + case 4: + array_cv[3] = p & 3; + p >>= 2; + + array_cv[2] = p & 3; + p >>= 2; + + array_cv[1] = p & 3; + p >>= 2; + + array_cv[0] = p & 3; + /* not sure how this case is optimized */ + break; + + case 5: + q = (p * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[4] = p - (q * 3); //max_bin_plus_one = 3 + p = q; + + q = (q * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[3] = p - (q * 3); //max_bin_plus_one = 3 + p = q; + + q = (q * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[2] = p - (q * 3); //max_bin_plus_one = 3 + p = q; + + q = (q * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[1] = p - (q * 3); //max_bin_plus_one = 3 + p = q; + + q = (q * inverse_of_max_bin_plus_one_scaled) >> 16; + array_cv[0] = p - (q * 3); //max_bin_plus_one = 3 + //p = q; + break; + + case 6: + array_cv[4] = p & 1; + p >>= 1; + + array_cv[3] = p & 1; + p >>= 1; + + array_cv[2] = p & 1; + p >>= 1; + + array_cv[1] = p & 1; + p >>= 1; + + array_cv[0] = p & 1; + //p >>= 1; + /* not sure how this case is optimized */ + break; + + default: + break; + } +} + +static int decode_vector_quantized_mlt_indices(uint32_t* data_u32, int* p_bitpos, int bit_count, uint32_t* p_random_value, int* decoder_region_standard_deviation, int* power_categories, int16_t* mlt_coefs) { + int16_t standard_deviation; + int array_cv[MAX_VECTOR_DIMENSION]; + int i, v, region, category, index; + uint32_t cur_u32, bitmask; + uint32_t* ptr_u32; + + /* bitreading setup */ + ptr_u32 = &data_u32[(*p_bitpos >> 5)]; + bitmask = 1 << (31 - (*p_bitpos & 0x1F)); + cur_u32 = *ptr_u32; + ptr_u32++; + + + /* read MLT coefs per region, differently depending on the category config */ + for (region = 0; region < NUMBER_OF_REGIONS; region++) { + standard_deviation = decoder_region_standard_deviation[region]; + category = power_categories[region]; + + /* lower categories encode MLT coefs based on vectors incides + huffman (?) */ + if (category < 7) { + const int16_t* decoder_tree_ptr = table_of_decoder_tables[category]; + int16_t* decoder_mlt_ptr = &mlt_coefs[region * REGION_SIZE]; + + for (v = 0; v < number_of_vectors[category]; v++) { + index = 0; + + do { + int bit = (bitmask & cur_u32) != 0; + bitmask >>= 1; + (*p_bitpos)++; + if (bitmask == 0) { + bitmask = 0x80000000; + cur_u32 = *ptr_u32; + ptr_u32++; + } + + index = *(decoder_tree_ptr + (index*2) + bit); + } + while (index > 0); + + /* ran out of bits */ + if (ptr_u32 > &data_u32[bit_count >> 5]) { + category = 7; /* this category doesn't bitread and only noise fills */ + + /* Namco doesn't set remaining regions to category 7 like the spec, nor checks + * when reading sign bits below, but doesn't seem to cause any problems */ + //for (i = region + 1; i < NUMBER_OF_REGIONS; i++) { + // power_categories[i] = 7; + //} + break; + } + + index = -index; + + /* convert index into array of sign bits used to access the centroid table */ + index_to_array(index, array_cv, category); + + /* vs refdec: sign reading slightly simplified */ + + for (i = 0; i < vector_dimension[category]; i++) { + int decoder_mlt_value = 0; + int negative; + + /* non-zero array = results in non-zero coef and encodes bit sign */ + if (array_cv[i] != 0) { + decoder_mlt_value = standard_deviation * mlt_quant_centroid[category][array_cv[i]]; + decoder_mlt_value = decoder_mlt_value >> 12; + + negative = (bitmask & cur_u32) != 0; + bitmask >>= 1; + (*p_bitpos)++; + if (bitmask == 0) { + bitmask = 0x80000000; + cur_u32 = *ptr_u32; + ptr_u32++; + } + + if (negative == 0) + decoder_mlt_value = -decoder_mlt_value; + } + + *decoder_mlt_ptr = decoder_mlt_value; + decoder_mlt_ptr++; + } + } + } + + /* higher categories don't encode all 20 MLT coefs, so rest are filled with + * noise to pretend we have something */ + if (category >= 5) { + static const int noise_fill_factor[3] = {5793, 8192, 23170}; /* 0.176777, 0.25, 0.707107 */ + uint32_t random_value; + + int16_t* decoder_mlt_ptr = &mlt_coefs[region * REGION_SIZE]; + int16_t noise_fill_pos = (standard_deviation * noise_fill_factor[category - 5]) >> 15; /* should be int16 */ + int16_t noise_fill_neg = -noise_fill_pos; + + /* vs refdec: updated differently (with hist state), and reupdated after 10 coefs */ + *p_random_value *= 69069; + random_value = *p_random_value; + + /* in some versions of Namco's decoder this is unrolled too */ + + if (category >= 7) { + /* all coefs are noise-filled */ + for (i = 0; i < REGION_SIZE; i++) { + { + if (random_value & 1) + *decoder_mlt_ptr = noise_fill_pos; + else + *decoder_mlt_ptr = noise_fill_neg; + random_value = (random_value >> 1); + } + decoder_mlt_ptr++; + } + } + else { + /* some coefs are noise-filled */ + for (i = 0; i < REGION_SIZE; i++) { + if (*decoder_mlt_ptr == 0) { + if (random_value & 1) + *decoder_mlt_ptr = noise_fill_pos; + else + *decoder_mlt_ptr = noise_fill_neg; + random_value = (random_value >> 1); + } + decoder_mlt_ptr++; + } + } + } + } + + return 0; +} + +/* unpacks input buffer into MLT coefs */ +static int unpack_frame(int bit_rate, const uint8_t* data, int frame_size, /*int* p_frame_size, */ int* p_mag_shift, int16_t* mlt_coefs, uint32_t* p_random_value) { + uint32_t data_u32[0x78/4 + 2]; + int bitpos, expected_frame_size; + int power_categories[NUMBER_OF_REGIONS]; + int category_balances[NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1]; + int absolute_region_power_index[NUMBER_OF_REGIONS]; /* a.k.a. RMS_index */ + int decoder_region_standard_deviation[NUMBER_OF_REGIONS]; + uint16_t categorization_control; + int i; + int res; + + + /* setup bitreading */ + { + expected_frame_size = bit_rate / 8 / 50; + if (frame_size < expected_frame_size) + return 1; + //p_frame_size = expected_frame_size; /* Namco returns this, for some reason */ + + /* Siren14 data is packed into U16 LE, but Namco reads and stores them in a U32 LE temp array for their bitreading */ + for (i = 0; i < (expected_frame_size >> 2); i++) { + data_u32[i] = (data[0x04*i + 2] << 0) | (data[0x04*i + 3] << 8) | (data[0x04*i + 0] << 16) | (data[0x04*i + 1] << 24); + } + /* data32 also has extra ints probably against outside reads, which wasn't originally + * memset'ed but we'll do just in case (doesn't seem to matter) */ + for (i = (expected_frame_size >> 2); i < 0x78/4 + 2; i++) { + data_u32[i] = 0; + } + + bitpos = 0; + } + + /* decode amplitude envelope scales */ + { + int rms_index = 0; /* amplitudes are root-mean-square */ + int region; + + /* get amplitude envelope (5b) for region 0 */ + for (i = 0; i < 5; i++) { + int bit = (data_u32[bitpos >> 5] >> (31 - (bitpos & 0x1F))) & 1; + bitpos++; + + rms_index = (rms_index << 1) | bit; + } + absolute_region_power_index[0] = rms_index - ESF_ADJUSTMENT_TO_RMS_INDEX; + + /* get amplitudes for other regions, coded differentially based on region 0 (done with a temp array in refdec) */ + for (region = 1; region < NUMBER_OF_REGIONS; region++) { + int diff_index = 0; + int region_index = region > 13 ? 13 - 1 : region - 1; + + do { + int bit = (data_u32[bitpos >> 5] >> (31 - (bitpos & 0x1F))) & 1; + bitpos++; + + diff_index = differential_region_power_decoder_tree[region_index][diff_index][bit]; + } + while (diff_index > 0); + + absolute_region_power_index[region] = absolute_region_power_index[region-1] - diff_index - DRP_DIFF_MIN; + } + } + + /* read categorization info bits */ + { + categorization_control = 0; + for (i = 0; i < NUM_CATEGORIZATION_CONTROL_BITS; i++) { + int bit = (data_u32[bitpos >> 5] >> (31 - (bitpos & 0x1F))) & 1; + bitpos++; + + categorization_control = (categorization_control << 1) | bit; + } + } + + /* determine categorization config per region */ + res = categorize( + 8 * expected_frame_size - bitpos, + absolute_region_power_index, power_categories, category_balances); + if (res < 0) return res; + + /* adjust power categories (rate_adjust_categories) */ + { + for (i = 0; i < categorization_control; i++) { + int region = category_balances[i]; + power_categories[region]++; + } + } + + /* recover amplitude envelope deviation (done in decode_envelope in refdec) */ + { + int region, region_index, max_index /*, test_index*/; + + /* vs refdec: Namco *doesn't* calc test_index here, so resulting region_index + * can be +-1 vs refdec, and final samples around +-10 (usually quieter). + * Also reuses and mods absolute_region_power_index but we have decoder_region_standard_deviation for clarity */ + + //test_index = 0; + max_index = 0; + for (region = 0; region < NUMBER_OF_REGIONS; region++) { + region_index = absolute_region_power_index[region]; + if (max_index < region_index) + max_index = region_index; + //test_index += region_standard_deviation_table[region_index + REGION_POWER_TABLE_NUM_NEGATIVES]; + } + + max_index += REGION_POWER_TABLE_NUM_NEGATIVES; + region_index = 9; + while ((region_index >= 0) && (/*test_index >= 8 ||*/ max_index > 28)) { + max_index -= 2; + region_index--; + //test_index /= 2; + } + + for (region = 0; region < NUMBER_OF_REGIONS; region++) { + int rsd_index = absolute_region_power_index[region] + REGION_POWER_TABLE_NUM_NEGATIVES + region_index * 2; + decoder_region_standard_deviation[region] = region_standard_deviation_table[rsd_index]; + } + + *p_mag_shift = region_index; + } + + /* decode the quantized bits into MLT coefs */ + res = decode_vector_quantized_mlt_indices( + data_u32, &bitpos, 8 * expected_frame_size, + p_random_value, + decoder_region_standard_deviation, power_categories, mlt_coefs); + if (res < 0) return res; + + + /* test for errors (in refdec but not Namco's, useful to detect decryption) */ + { + int bits_left = 8 * expected_frame_size - bitpos; + int i; + + if (bits_left > 0) { + /* frame must be padded with 1s */ + for (i = 0; i < bits_left; i++) { + int bit = (data_u32[bitpos >> 5] >> (31 - (bitpos & 0x1F))) & 1; + bitpos++; + + if (bit == 0) + return -1; + } + } + else { + /* ? */ + if (categorization_control < NUM_CATEGORIZATION_CONTROL_BITS - 1 && bits_left < 0) + return -2; + } + + for (i = 0; i < NUMBER_OF_REGIONS; i++) { + if ((absolute_region_power_index[i] + ESF_ADJUSTMENT_TO_RMS_INDEX > 31) || + (absolute_region_power_index[i] + ESF_ADJUSTMENT_TO_RMS_INDEX < -8)) + return -4; + } + } + + return 0; +} + + +/***************************************************************************** + * API + *****************************************************************************/ + +struct g7221_handle { + /* control */ + int bit_rate; + int frame_size; + /* AES setup/state */ + s14aes_handle* aes; + /* state */ + int16_t mlt_coefs[MAX_DCT_LENGTH]; + int16_t old_samples[MAX_DCT_LENGTH >> 1]; + uint32_t random_value; +}; + +g7221_handle* g7221_init(int bytes_per_frame) { + g7221_handle* handle = NULL; + int bit_rate; + + /* valid only: 0x78, 0x50 or 0x3c */ + bit_rate = bytes_per_frame * 8 * 50; + if (bit_rate != 24000 && bit_rate != 32000 && bit_rate != 48000) + goto fail; + + handle = calloc(1, sizeof(g7221_handle)); + if (!handle) goto fail; + + handle->bit_rate = bit_rate; + handle->frame_size = bytes_per_frame; + + g7221_reset(handle); + + return handle; +fail: + free(handle); + return NULL; +} + + +int g7221_decode_frame(g7221_handle* handle, uint8_t* data, int16_t* out_samples) { + int res; + int mag_shift; + + /* first 0x10 bytes may be encrypted with AES. Original code also saves encrypted bytes, + * then re-crypts after unpacking, presumably to guard against memdumps. */ + if (handle->aes != NULL) { + s14aes_decrypt(handle->aes, data); + } + + /* Namco's decoder is designed so that out_samples can be set in place of mlt_coefs, + * so we could avoid one extra buffer, but for clarity we'll leave as is */ + + /* unpack data into MLT spectrum coefs */ + res = unpack_frame(handle->bit_rate, data, handle->frame_size, &mag_shift, handle->mlt_coefs, &handle->random_value); + if (res < 0) goto fail; + + /* convert coefs to samples using reverse (inverse) MLT */ + res = rmlt_coefs_to_samples(mag_shift, handle->mlt_coefs, handle->old_samples, out_samples); + if (res < 0) goto fail; + + /* Namco also sets number of codes/samples done from unpack_frame/rmlt (ptr arg), + * but they seem unused */ + + return 1; +fail: + //;printf("S14: fail %i\n", res); + return 0; +} + +#if 0 +int g7221_decode_empty(g7221_handle* handle, int16_t* out_samples) { + static const uint8_t empty_frame[0x3c] = { + 0x1E,0x0B,0x89,0x40,0x02,0x4F,0x51,0x35, 0x10,0xA1,0xFE,0xDF,0x52,0x51,0x10,0x0B, + 0xF0,0x69,0x7B,0xAE,0x18,0x17,0x00,0x52, 0x07,0x74,0xF4,0x65,0xA2,0x58,0xD8,0x3F, + 0xD9,0xAA,0x65,0x35,0x2A,0x14,0xE3,0x58, 0xD7,0xC0,0xD2,0x02,0x5B,0x0E,0x2A,0x98, + 0xA3,0x04,0x5E,0x51,0xE5,0xC5,0xB2,0x14, 0xBF,0x58,0xFF,0xFF + }; + int res; + int mag_shift; + + /* This only seems to exist in older exes. Namco's samples don't reach EOF, so this + * wouldn't need to be called. Doesn't seem to use encoder delay either. */ + + res = unpack_frame(24000, empty_frame, 0x3c, &mag_shift, handle->mlt_coefs, &handle->random_value); + if (res) goto fail; + + /* convert coefs to samples using reverse (inverse) MLT */ + res = rmlt_coefs_to_samples(mag_shift, handle->mlt_coefs, handle->old_samples, out_samples); + if (res) goto fail; + + return 1; +fail: + return 0; +} +#endif + +void g7221_reset(g7221_handle* handle) { + + /* initialize old values (others get overwritten) */ + memset(&handle->old_samples, 0, sizeof(handle->old_samples)); + + /* initialize the random number generator */ + handle->random_value = 0x10001; + + /* vs refdec: different default random. Namco used a global, so maybe multiple + * bnsf playing at the same time would get slightly different results */ +} + +void g7221_free(g7221_handle* handle) { + if (!handle) + return; + + s14aes_close(handle->aes); + free(handle); +} + +int g7221_set_key(g7221_handle* handle, const uint8_t* key) { + const int key_size = 192 / 8; /* only 192 bit mode */ + uint8_t temp_key[192 / 8]; + const char* mod_key = "Ua#oK3P94vdxX,ft*k-mnjoO"; /* constant for all platform/games */ + int i; + + if (!handle) + goto fail; + + /* disable, useful for testing? */ + if (key == NULL) { + s14aes_close(handle->aes); + handle->aes = NULL; + return 1; + } + + /* init AES state (tables) or reuse if already exists */ + if (handle->aes == NULL) { + handle->aes = s14aes_init(); + if (!handle->aes) goto fail; + } + + /* Base key is XORed probably against memdumps, as plain key would be part of the final AES key. However + * roundkey is still in memdumps near AES state (~0x1310 from sbox table, that starts with 0x63,0x7c,0x77,0x7b...) + * so it isn't too effective. XORing was originally done inside aes_expand_key during S14/S22 init. */ + for (i = 0; i < key_size; i++) { + temp_key[i] = key[i] ^ mod_key[i]; + } + + /* reset new key */ + s14aes_set_key(handle->aes, temp_key); + + return 1; +fail: + return 0; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_lib.h b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_lib.h new file mode 100644 index 000000000..08468c3e2 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_lib.h @@ -0,0 +1,32 @@ +/* + Interface to Namco G.722.1 decoder +*/ +#ifndef _G7221_DECODER_LIB_H +#define _G7221_DECODER_LIB_H + +#include + +/* forward definition for the opaque handle object */ +typedef struct g7221_handle g7221_handle; + +/* return a handle for decoding on successful init, NULL on failure */ +g7221_handle* g7221_init(int bytes_per_frame); + +/* decode a frame, at code_words, into 16-bit PCM in sample_buffer */ +int g7221_decode_frame(g7221_handle* handle, uint8_t* data, int16_t* out_samples); + +#if 0 +/* decodes an empty frame after no more data is found (may be used to "drain" window samples */ +int g7221_decode_empty(g7221_handle* handle, int16_t* out_samples); +#endif + +/* reset the decoder to its initial state */ +void g7221_reset(g7221_handle* handle); + +/* free resources */ +void g7221_free(g7221_handle* handle); + +/* set new key (ignores key on failure) */ +int g7221_set_key(g7221_handle* handle, const uint8_t* key); + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_lib_data.h b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_lib_data.h new file mode 100644 index 000000000..eace81846 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_lib_data.h @@ -0,0 +1,576 @@ +#ifndef _DATA_H_ +#define _DATA_H_ + +#include + +/***************************************************************************** + * MAIN + *****************************************************************************/ +#define MAX_DCT_LENGTH 640 + + +/***************************************************************************** + * IMLT + *****************************************************************************/ + +/* vs refdec: this window seems based on float refdec with a scale: + * for (i = 0; i < 640; i++) + * window[i] = floor(sin((PI/2.0) * (i + 0.5) / 640) * 32767.0) + * while the original int refdec table uses an altered formula? (smaller values) */ +static const int16_t imlt_samples_window[MAX_DCT_LENGTH] = { /* "Out_Window"? */ + 40, 120, 201, 281, 361, 442, 522, 603, 683, 763, + 844, 924, 1005, 1085, 1165, 1246, 1326, 1406, 1487, 1567, + 1647, 1728, 1808, 1888, 1969, 2049, 2129, 2209, 2290, 2370, + 2450, 2530, 2610, 2691, 2771, 2851, 2931, 3011, 3091, 3171, + 3251, 3331, 3411, 3491, 3571, 3651, 3731, 3811, 3891, 3971, + 4050, 4130, 4210, 4290, 4369, 4449, 4529, 4608, 4688, 4768, + 4847, 4927, 5006, 5086, 5165, 5245, 5324, 5403, 5483, 5562, + 5641, 5720, 5799, 5879, 5958, 6037, 6116, 6195, 6274, 6353, + 6431, 6510, 6589, 6668, 6747, 6825, 6904, 6982, 7061, 7140, + 7218, 7296, 7375, 7453, 7531, 7610, 7688, 7766, 7844, 7922, + 8000, 8078, 8156, 8234, 8312, 8390, 8467, 8545, 8623, 8700, + 8778, 8855, 8932, 9010, 9087, 9164, 9242, 9319, 9396, 9473, + 9550, 9627, 9703, 9780, 9857, 9934, 10010, 10087, 10163, 10240, + 10316, 10392, 10469, 10545, 10621, 10697, 10773, 10849, 10925, 11001, + 11076, 11152, 11227, 11303, 11378, 11454, 11529, 11604, 11680, 11755, + 11830, 11905, 11980, 12054, 12129, 12204, 12278, 12353, 12427, 12502, + 12576, 12650, 12724, 12798, 12872, 12946, 13020, 13094, 13168, 13241, + 13315, 13388, 13462, 13535, 13608, 13681, 13754, 13827, 13900, 13973, + 14046, 14118, 14191, 14263, 14335, 14408, 14480, 14552, 14624, 14696, + 14768, 14840, 14911, 14983, 15054, 15126, 15197, 15268, 15339, 15410, + 15481, 15552, 15623, 15693, 15764, 15834, 15905, 15975, 16045, 16115, + 16185, 16255, 16325, 16395, 16464, 16534, 16603, 16672, 16742, 16811, + 16880, 16948, 17017, 17086, 17154, 17223, 17291, 17360, 17428, 17496, + 17564, 17632, 17699, 17767, 17834, 17902, 17969, 18036, 18103, 18170, + 18237, 18304, 18371, 18437, 18504, 18570, 18636, 18702, 18768, 18834, + 18900, 18966, 19031, 19096, 19162, 19227, 19292, 19357, 19422, 19486, + 19551, 19616, 19680, 19744, 19808, 19872, 19936, 20000, 20064, 20127, + 20190, 20254, 20317, 20380, 20443, 20506, 20568, 20631, 20693, 20756, + 20818, 20880, 20942, 21003, 21065, 21127, 21188, 21249, 21311, 21372, + 21432, 21493, 21554, 21614, 21675, 21735, 21795, 21855, 21915, 21975, + 22034, 22094, 22153, 22212, 22271, 22330, 22389, 22448, 22506, 22565, + 22623, 22681, 22739, 22797, 22854, 22912, 22969, 23027, 23084, 23141, + 23198, 23254, 23311, 23367, 23424, 23480, 23536, 23592, 23648, 23703, + 23759, 23814, 23869, 23924, 23979, 24034, 24088, 24143, 24197, 24251, + 24305, 24359, 24413, 24466, 24520, 24573, 24626, 24679, 24732, 24785, + 24837, 24890, 24942, 24994, 25046, 25098, 25149, 25201, 25252, 25303, + 25354, 25405, 25456, 25506, 25557, 25607, 25657, 25707, 25757, 25806, + 25856, 25905, 25954, 26003, 26052, 26101, 26150, 26198, 26246, 26294, + 26342, 26390, 26437, 26485, 26532, 26579, 26626, 26673, 26720, 26766, + 26812, 26859, 26905, 26950, 26996, 27042, 27087, 27132, 27177, 27222, + 27267, 27311, 27355, 27400, 27444, 27488, 27531, 27575, 27618, 27661, + 27704, 27747, 27790, 27832, 27875, 27917, 27959, 28001, 28042, 28084, + 28125, 28167, 28208, 28248, 28289, 28330, 28370, 28410, 28450, 28490, + 28529, 28569, 28608, 28647, 28686, 28725, 28764, 28802, 28840, 28878, + 28916, 28954, 28992, 29029, 29066, 29103, 29140, 29177, 29213, 29250, + 29286, 29322, 29358, 29393, 29429, 29464, 29499, 29534, 29569, 29603, + 29638, 29672, 29706, 29740, 29773, 29807, 29840, 29873, 29906, 29939, + 29972, 30004, 30036, 30068, 30100, 30132, 30163, 30195, 30226, 30257, + 30288, 30318, 30349, 30379, 30409, 30439, 30468, 30498, 30527, 30556, + 30585, 30614, 30643, 30671, 30699, 30727, 30755, 30783, 30810, 30838, + 30865, 30892, 30918, 30945, 30971, 30997, 31023, 31049, 31075, 31100, + 31125, 31150, 31175, 31200, 31224, 31249, 31273, 31297, 31320, 31344, + 31367, 31390, 31413, 31436, 31459, 31481, 31503, 31525, 31547, 31569, + 31590, 31612, 31633, 31653, 31674, 31695, 31715, 31735, 31755, 31775, + 31794, 31814, 31833, 31852, 31871, 31889, 31907, 31926, 31944, 31961, + 31979, 31997, 32014, 32031, 32048, 32064, 32081, 32097, 32113, 32129, + 32145, 32160, 32176, 32191, 32206, 32220, 32235, 32249, 32263, 32277, + 32291, 32304, 32318, 32331, 32344, 32357, 32369, 32382, 32394, 32406, + 32418, 32429, 32441, 32452, 32463, 32474, 32484, 32495, 32505, 32515, + 32525, 32535, 32544, 32553, 32562, 32571, 32580, 32588, 32597, 32605, + 32613, 32620, 32628, 32635, 32642, 32649, 32656, 32662, 32669, 32675, + 32681, 32686, 32692, 32697, 32702, 32707, 32712, 32717, 32721, 32725, + 32729, 32733, 32736, 32740, 32743, 32746, 32749, 32751, 32753, 32756, + 32758, 32759, 32761, 32762, 32764, 32765, 32765, 32766, 32766, 32766, +}; + +/* set helper for DCT-IV optimizations (code seem to stop at 174) */ +static const uint8_t imlt_set1_table[176] = { + 1, 1, 1, 1, 1, 1, 3, 1, 2, 0, 1, 1, 3, 1, 1, 1, + 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, + 3, 1, 3, 1, 1, 1, 1, 1, 3, 1, 2, 0, 1, 1, 3, 1, + 1, 1, 1, 1, 3, 1, 3, 1, 3, 1, 1, 1, 1, 1, 3, 1, + 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 3, 1, + 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, + 3, 1, 3, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, + 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 3, 1, 1, 1, 1, 1, + 3, 1, 3, 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 3, 1, + 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, + 3, 1, 3, 1, 3, 1, 1, 1, 1, 1, 3, 1, 2, 0, 0, 0, +}; +static const uint8_t imlt_set2_table[44] = { + 1, 3, 1, 1, 3, 3, 3, 1, 1, 3, 1, 1, 3, 1, 1, 3, + 3, 3, 1, 1, 3, 1, 1, 3, 1, 1, 3, 3, 3, 1, 1, 3, + 2, 1, 3, 1, 1, 3, 1, 1, 3, 2, 1, 1, +}; + +/* vs refdec: bigger values calculated differently (unsure how), probably: + * for (i = 0; i < size; i++) + * cos/sin( (PI / (4 * size)) * (i + 0.5) * unknown_scale ) + * Originally were multiple separate tables, but here they are fused into one + * (could be cleaned up, may be a compiler optimization) + * Note this uses *unsigned* int16s, for temp vars we can use ints */ +static const uint16_t imlt_cos_tables[636] = { + /* imlt_cos_table_64[320] (640/2) */ + 65535, 65535, 65534, 65533, 65532, 65530, 65527, 65524, + 65521, 65518, 65514, 65509, 65505, 65500, 65494, 65488, + 65482, 65475, 65468, 65460, 65453, 65444, 65436, 65427, + 65417, 65407, 65397, 65386, 65375, 65364, 65352, 65340, + 65327, 65314, 65301, 65287, 65273, 65258, 65243, 65228, + 65212, 65196, 65179, 65162, 65145, 65127, 65109, 65091, + 65072, 65052, 65033, 65013, 64992, 64971, 64950, 64928, + 64906, 64884, 64861, 64838, 64814, 64790, 64766, 64741, + 64716, 64690, 64665, 64638, 64611, 64584, 64557, 64529, + 64501, 64472, 64443, 64414, 64384, 64353, 64323, 64292, + 64261, 64229, 64197, 64164, 64131, 64098, 64064, 64030, + 63996, 63961, 63925, 63890, 63854, 63817, 63781, 63743, + 63706, 63668, 63630, 63591, 63552, 63512, 63473, 63432, + 63392, 63351, 63309, 63268, 63225, 63183, 63140, 63097, + 63053, 63009, 62965, 62920, 62875, 62829, 62783, 62737, + 62690, 62643, 62596, 62548, 62500, 62451, 62402, 62353, + 62303, 62253, 62203, 62152, 62100, 62049, 61997, 61945, + 61892, 61839, 61785, 61732, 61677, 61623, 61568, 61513, + 61457, 61401, 61344, 61288, 61231, 61173, 61115, 61057, + 60998, 60939, 60880, 60820, 60760, 60700, 60639, 60578, + 60516, 60454, 60392, 60329, 60266, 60203, 60139, 60075, + 60011, 59946, 59881, 59815, 59749, 59683, 59616, 59549, + 59482, 59414, 59346, 59278, 59209, 59140, 59070, 59000, + 58930, 58860, 58789, 58718, 58646, 58574, 58502, 58429, + 58356, 58283, 58209, 58135, 58060, 57986, 57910, 57835, + 57759, 57683, 57606, 57530, 57452, 57375, 57297, 57219, + 57140, 57061, 56982, 56902, 56822, 56742, 56661, 56580, + 56499, 56417, 56335, 56253, 56170, 56087, 56004, 55920, + 55836, 55752, 55667, 55582, 55497, 55411, 55325, 55238, + 55152, 55065, 54977, 54889, 54801, 54713, 54624, 54535, + 54446, 54356, 54266, 54176, 54085, 53994, 53903, 53811, + 53719, 53627, 53534, 53441, 53348, 53255, 53161, 53066, + 52972, 52877, 52782, 52686, 52591, 52494, 52398, 52301, + 52204, 52107, 52009, 51911, 51813, 51714, 51615, 51516, + 51416, 51316, 51216, 51116, 51015, 50914, 50812, 50710, + 50608, 50506, 50403, 50301, 50197, 50094, 49990, 49886, + 49781, 49676, 49571, 49466, 49360, 49254, 49148, 49042, + 48935, 48828, 48720, 48612, 48504, 48396, 48288, 48179, + 48069, 47960, 47850, 47740, 47630, 47519, 47408, 47297, + 47186, 47074, 46962, 46849, 46737, 46624, 46511, 46397, + /* imlt_cos_table_32[160] (640/4) (seems unused) */ + 65535, 65534, 65531, 65526, 65520, 65512, 65502, 65491, + 65478, 65464, 65448, 65431, 65412, 65392, 65370, 65346, + 65321, 65294, 65265, 65235, 65204, 65171, 65136, 65100, + 65062, 65023, 64982, 64939, 64895, 64850, 64802, 64754, + 64703, 64651, 64598, 64543, 64486, 64428, 64369, 64307, + 64245, 64180, 64115, 64047, 63978, 63908, 63836, 63762, + 63687, 63610, 63532, 63452, 63371, 63289, 63204, 63118, + 63031, 62942, 62852, 62760, 62667, 62572, 62475, 62377, + 62278, 62177, 62075, 61971, 61865, 61759, 61650, 61540, + 61429, 61316, 61202, 61086, 60969, 60850, 60730, 60608, + 60485, 60361, 60235, 60107, 59978, 59848, 59716, 59583, + 59448, 59312, 59174, 59035, 58895, 58753, 58610, 58465, + 58319, 58172, 58023, 57873, 57721, 57568, 57414, 57258, + 57101, 56942, 56782, 56621, 56458, 56294, 56129, 55962, + 55794, 55624, 55454, 55282, 55108, 54933, 54757, 54580, + 54401, 54221, 54040, 53857, 53673, 53488, 53301, 53114, + 52925, 52734, 52543, 52350, 52155, 51960, 51763, 51565, + 51366, 51166, 50964, 50761, 50557, 50352, 50146, 49938, + 49729, 49519, 49307, 49095, 48881, 48666, 48450, 48233, + 48015, 47795, 47575, 47353, 47130, 46906, 46680, 46454, + /* imlt_cos_table_16[80] (640/8) */ + 65535, 65528, 65516, 65497, 65472, 65440, 65402, 65358, + 65307, 65251, 65188, 65118, 65043, 64961, 64873, 64778, + 64678, 64571, 64458, 64338, 64213, 64081, 63943, 63799, + 63649, 63493, 63330, 63162, 62987, 62806, 62619, 62427, + 62228, 62023, 61812, 61595, 61373, 61144, 60910, 60669, + 60423, 60171, 59913, 59650, 59380, 59105, 58824, 58538, + 58246, 57948, 57645, 57336, 57022, 56702, 56376, 56046, + 55709, 55368, 55021, 54669, 54311, 53949, 53581, 53208, + 52830, 52446, 52058, 51665, 51266, 50863, 50455, 50042, + 49624, 49201, 48774, 48342, 47905, 47464, 47018, 46567, + /* imlt_cos_table_8[40] (640/16) */ + 65532, 65507, 65457, 65381, 65280, 65154, 65002, 64826, + 64625, 64399, 64148, 63872, 63571, 63247, 62897, 62524, + 62126, 61705, 61259, 60790, 60298, 59782, 59243, 58682, + 58098, 57491, 56862, 56212, 55539, 54846, 54131, 53395, + 52639, 51862, 51065, 50249, 49413, 48558, 47685, 46793, + /* imlt_cos_table_4[20] (640/32) */ + 65523, 65422, 65220, 64917, 64515, 64013, 63412, 62714, + 61918, 61028, 60043, 58965, 57797, 56540, 55195, 53765, + 52253, 50660, 48988, 47241, + /* imlt_cos_table_2[10] (640/64) */ + 65485, 65081, 64276, 63075, 61485, 59516, 57179, 54491, + 51466, 48124, + /* imlt_cos_table_1[5] (640/128) */ + 65333, 63725, 60547, 55878, 49833, + /* extra */ + 0, +}; + +/* see cos table info */ +static const uint16_t imlt_sin_tables[636] = { /* "sin_table" */ + /* imlt_sin_table_64[320] (640/2) */ + 80, 241, 402, 562, 723, 884, 1045, 1206, + 1367, 1527, 1688, 1849, 2010, 2171, 2331, 2492, + 2653, 2814, 2974, 3135, 3296, 3456, 3617, 3777, + 3938, 4098, 4259, 4420, 4580, 4740, 4901, 5061, + 5222, 5382, 5542, 5702, 5863, 6023, 6183, 6343, + 6503, 6663, 6823, 6983, 7143, 7303, 7463, 7623, + 7782, 7942, 8102, 8261, 8421, 8580, 8740, 8899, + 9058, 9218, 9377, 9536, 9695, 9854, 10013, 10172, + 10331, 10490, 10649, 10807, 10966, 11124, 11283, 11441, + 11600, 11758, 11916, 12074, 12232, 12390, 12548, 12706, + 12864, 13021, 13179, 13337, 13494, 13651, 13809, 13966, + 14123, 14280, 14437, 14594, 14751, 14907, 15064, 15220, + 15377, 15533, 15689, 15845, 16001, 16157, 16313, 16469, + 16625, 16780, 16936, 17091, 17246, 17401, 17556, 17711, + 17866, 18021, 18175, 18330, 18484, 18638, 18793, 18947, + 19101, 19254, 19408, 19562, 19715, 19868, 20022, 20175, + 20328, 20481, 20633, 20786, 20938, 21091, 21243, 21395, + 21547, 21699, 21851, 22002, 22154, 22305, 22456, 22607, + 22758, 22909, 23059, 23210, 23360, 23511, 23661, 23811, + 23960, 24110, 24259, 24409, 24558, 24707, 24856, 25005, + 25153, 25302, 25450, 25598, 25746, 25894, 26042, 26189, + 26337, 26484, 26631, 26778, 26925, 27071, 27217, 27364, + 27510, 27656, 27801, 27947, 28092, 28238, 28383, 28528, + 28672, 28817, 28961, 29105, 29250, 29393, 29537, 29681, + 29824, 29967, 30110, 30253, 30395, 30538, 30680, 30822, + 30964, 31106, 31247, 31388, 31529, 31670, 31811, 31952, + 32092, 32232, 32372, 32512, 32651, 32791, 32930, 33069, + 33208, 33346, 33485, 33623, 33761, 33898, 34036, 34173, + 34311, 34447, 34584, 34721, 34857, 34993, 35129, 35265, + 35400, 35535, 35670, 35805, 35940, 36074, 36208, 36342, + 36476, 36610, 36743, 36876, 37009, 37142, 37274, 37406, + 37538, 37670, 37801, 37933, 38064, 38195, 38325, 38456, + 38586, 38716, 38845, 38975, 39104, 39233, 39362, 39490, + 39618, 39746, 39874, 40002, 40129, 40256, 40383, 40509, + 40636, 40762, 40887, 41013, 41138, 41263, 41388, 41513, + 41637, 41761, 41885, 42009, 42132, 42255, 42378, 42501, + 42623, 42745, 42867, 42988, 43110, 43231, 43351, 43472, + 43592, 43712, 43832, 43951, 44070, 44189, 44308, 44426, + 44544, 44662, 44780, 44897, 45014, 45131, 45247, 45364, + 45480, 45595, 45711, 45826, 45941, 46055, 46170, 46284, + /* imlt_sin_table_32[160] (640/4) */ + 160, 482, 804, 1125, 1447, 1769, 2090, 2412, + 2733, 3055, 3376, 3697, 4018, 4339, 4660, 4981, + 5302, 5622, 5943, 6263, 6583, 6903, 7223, 7543, + 7862, 8181, 8501, 8819, 9138, 9456, 9775, 10093, + 10410, 10728, 11045, 11362, 11679, 11995, 12311, 12627, + 12943, 13258, 13573, 13887, 14202, 14515, 14829, 15142, + 15455, 15767, 16079, 16391, 16702, 17013, 17324, 17634, + 17943, 18253, 18561, 18870, 19177, 19485, 19792, 20098, + 20404, 20710, 21015, 21319, 21623, 21926, 22229, 22532, + 22833, 23135, 23435, 23736, 24035, 24334, 24633, 24930, + 25228, 25524, 25820, 26116, 26410, 26704, 26998, 27291, + 27583, 27874, 28165, 28455, 28745, 29033, 29321, 29609, + 29895, 30181, 30467, 30751, 31035, 31318, 31600, 31881, + 32162, 32442, 32721, 32999, 33277, 33554, 33830, 34105, + 34379, 34652, 34925, 35197, 35468, 35738, 36007, 36275, + 36543, 36810, 37075, 37340, 37604, 37867, 38129, 38390, + 38651, 38910, 39168, 39426, 39682, 39938, 40192, 40446, + 40699, 40950, 41201, 41451, 41699, 41947, 42194, 42439, + 42684, 42928, 43170, 43412, 43652, 43891, 44130, 44367, + 44603, 44839, 45073, 45306, 45537, 45768, 45998, 46227, + /* imlt_sin_table_16[80] (640/8) */ + 321, 965, 1608, 2251, 2894, 3536, 4179, 4821, + 5462, 6103, 6743, 7383, 8022, 8660, 9297, 9934, + 10569, 11204, 11837, 12469, 13100, 13730, 14359, 14986, + 15611, 16235, 16858, 17479, 18098, 18716, 19331, 19945, + 20557, 21167, 21775, 22381, 22984, 23586, 24185, 24782, + 25376, 25968, 26557, 27144, 27729, 28310, 28889, 29465, + 30038, 30609, 31176, 31741, 32302, 32860, 33415, 33967, + 34516, 35061, 35603, 36141, 36676, 37208, 37736, 38260, + 38780, 39297, 39810, 40319, 40825, 41326, 41823, 42317, + 42806, 43291, 43772, 44249, 44721, 45189, 45653, 46112, + /* imlt_sin_table_8[40] (640/16) */ + 643, 1929, 3215, 4500, 5783, 7063, 8341, 9616, + 10887, 12153, 13415, 14672, 15923, 17169, 18407, 19638, + 20862, 22078, 23285, 24483, 25672, 26851, 28020, 29178, + 30324, 31459, 32582, 33692, 34789, 35873, 36943, 37998, + 39039, 40065, 41076, 42070, 43049, 44011, 44956, 45883, + /* imlt_sin_table_4[20] (640/32) */ + 1286, 3858, 6423, 8979, 11520, 14044, 16547, 19024, + 21471, 23885, 26263, 28600, 30893, 33138, 35332, 37472, + 39554, 41575, 43532, 45422, + /* imlt_sin_table_2[10] (640/64) */ + 2572, 7702, 12785, 17789, 22683, 27437, 32022, 36409, + 40572, 44485, + /* imlt_sin_table_1[5] (640/128) */ + 5141, 15299, 25079, 34242, 42562, + /* extra */ + 0, +}; + + +/***************************************************************************** + * UNPACK + *****************************************************************************/ + +#define REGION_POWER_TABLE_SIZE 64 +#define REGION_POWER_TABLE_NUM_NEGATIVES 24 + +#define NUM_CATEGORIZATION_CONTROL_BITS 5 +#define NUM_CATEGORIZATION_CONTROL_POSSIBILITIES 32 + +#define NUM_CATEGORIES 8 +#define DRP_DIFF_MIN 12 /* used as negative */ +//#define DRP_DIFF_MAX 11 +#define NUM_BINS 16 +//#define MAX_VECTOR_INDICES 625 +#define MAX_VECTOR_DIMENSION 5 +//#define ABS_REGION_POWER_LEVELS 32 +#define NUMBER_OF_REGIONS 28 +#define REGION_SIZE 20 +#define DIFF_REGION_POWER_LEVELS 24 + +/* Default scale factor is a bit high due to something something and this compensates + * (using 9-1 may sound better since most Siren14 BNSF get a bit clippy) */ +#define ESF_ADJUSTMENT_TO_RMS_INDEX (9-2) + + +/* vs refdec: has region 0 (unused, all 0s) and regions>13 (repeats of region 13) so they were removed. + * 2nd index only went to DIFF_REGION_POWER_LEVELS-1 and last was added (all 0s though so probably unused). */ +static const int16_t differential_region_power_decoder_tree[NUMBER_OF_REGIONS][DIFF_REGION_POWER_LEVELS][2] = { /* "rms_table"? */ + {{ 1, 2},{ 3, 4},{ 5, 6},{ 7, 8},{ 9, 10},{ 11,-12},{-11,-10},{ -8, -9},{ -7, -6},{-13, 12},{ -5, -4},{ 0, 13},{ -3,-14},{ -2, 14},{ -1, 15},{-15, 16},{-16, 17},{-17, 18},{ 19, 20},{ 21, 22},{-18,-19},{-20,-21},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5, 6},{ 7, 8},{-10, -9},{ -8,-11},{ -7, -6},{ 9, -5},{ 10,-12},{ -4, 11},{-13, -3},{ 12, -2},{ 13,-14},{ -1, 14},{ 15,-15},{ 0, 16},{-16, 17},{-17, 18},{-18, 19},{ 20, 21},{ 22,-19},{-20,-21},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5, 6},{ 7, 8},{ 9, 10},{-12, 11},{-11,-13},{-10, -9},{ 12,-14},{ -8, -7},{-15, -6},{ 13, -5},{-16, -4},{ 14,-17},{ 15, -3},{ 16,-18},{ -2, 17},{ 18,-19},{ -1, 19},{-20, 20},{ 0, 21},{ 22,-21},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5, 6},{-11,-10},{ 7,-12},{ 8, -9},{ 9,-13},{-14, 10},{ -8,-15},{-16, 11},{ -7, 12},{-17, -6},{ 13, 14},{-18, 15},{ -5, -4},{ 16, 17},{ -3, -2},{-19, 18},{ -1, 19},{-20, 20},{ 21, 22},{ 0,-21},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5, 6},{-12,-11},{-13, 7},{ 8,-14},{-10, 9},{ 10,-15},{ -9, 11},{ -8, 12},{-16, 13},{ -7, -6},{-17, 14},{ -5,-18},{ 15, -4},{ 16,-19},{ 17, -3},{-20, 18},{ -2, 19},{-21, 20},{ 0, 21},{ 22, -1},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5, 6},{-11, 7},{-12,-10},{-13, -9},{ 8, 9},{-14, -8},{ 10,-15},{ -7, 11},{-16, 12},{ -6,-17},{ 13, 14},{ -5, 15},{-18, 16},{ -4, 17},{ -3,-19},{ 18, -2},{-20, 19},{ -1, 20},{ 0, 21},{ 22,-21},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5,-12},{ 6,-11},{-10,-13},{ -9, 7},{ 8,-14},{ 9, -8},{-15, 10},{ -7,-16},{ 11, -6},{ 12,-17},{ 13, -5},{-18, 14},{ 15, -4},{-19, 16},{ 17, -3},{-20, 18},{ 19, 20},{ 21, 22},{ 0, -2},{ -1,-21},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5,-12},{ 6,-13},{-11,-10},{ 7,-14},{ 8, -9},{ 9,-15},{ -8, 10},{ -7,-16},{ 11, 12},{ -6,-17},{ -5, 13},{ 14, 15},{-18, -4},{-19, 16},{ -3, 17},{ 18, -2},{-20, 19},{ 20, 21},{ 22, 0},{ -1,-21},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5, 6},{-11,-10},{-12, -9},{ 7, 8},{-13, -8},{ 9,-14},{ -7, 10},{ -6,-15},{ 11, 12},{ -5,-16},{ 13, 14},{-17, 15},{ -4, 16},{ 17,-18},{ 18, -3},{ -2, 19},{ -1, 0},{-19, 20},{-20, 21},{ 22,-21},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5, 6},{-11, 7},{-10,-12},{ -9, 8},{ -8,-13},{ 9, -7},{ 10,-14},{ -6, 11},{-15, 12},{ -5, 13},{-16, -4},{ 14, 15},{-17, -3},{-18, 16},{ 17,-19},{ -2, 18},{-20, 19},{ -1, 20},{ 21, 22},{ 0,-21},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5,-12},{ 6,-11},{ 7, 8},{-10,-13},{ -9, 9},{ -8,-14},{ 10, -7},{ 11,-15},{ -6, 12},{ -5, 13},{ -4,-16},{ 14, 15},{ -3,-17},{ 16, 17},{-18, -2},{ 18,-19},{ -1, 19},{-20, 20},{-21, 21},{ 22, 0},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{ 5,-12},{-13, 6},{-11, 7},{-14, 8},{-10, 9},{-15, -9},{ -8, 10},{ -7,-16},{ 11, -6},{ 12, -5},{-17, 13},{ 14,-18},{ 15, -4},{ 16,-19},{ 17, -3},{ 18, -2},{ 19, -1},{-20, 20},{ 21, 22},{ 0,-21},{-22,-23},{ 0, 0}}, + {{ 1, 2},{ 3, 4},{-12, 5},{-11,-13},{ 6,-14},{-10, 7},{ 8,-15},{ -9, 9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22, 0},{ -1, -3},{ -2,-21},{-22,-23},{ 0, 0}}, +}; + +/* vs refdec: same table */ +static const int16_t mlt_quant_centroid[NUM_CATEGORIES][NUM_BINS] = { /* "mlt_q" */ + { 0, 1606, 3119, 4586, 6049, 7502, 8941,10406,11851,13292,14736,16146,17566,19351, 0, 0}, + { 0, 2229, 4341, 6401, 8471,10531,12583,14588,16673,18924, 0, 0, 0, 0, 0, 0}, + { 0, 3055, 5998, 8929,11806,14680,17680, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 4121, 8192,12259,16322, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 5413,11071,16315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 6785,14300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 8044, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 8019, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +/* vs refdec: Namco uses a stack array with these values */ +static const int16_t expected_bits_table[NUM_CATEGORIES] = { + 52, 47, 43, 37, 29, 22, 16, 0 +}; + +/* vs refdec: Namco uses positive values *2 but I'm not sure what they are for (some index access) + * so these are the refdec values */ +static const int16_t mlt_decoder_tree_category_0[180][2] = { /* "reasion_huffman_table"? */ + { 1, 0},{ 2, 3},{ 4, 5},{ 6, 7},{ 8, 9},{ -1, -14},{ 10, 11},{ 12, 13}, + { 14, 15},{ 16, 17},{ 18, 19},{ -15, 20},{ 21, 22},{ 23, -28},{ 24, -2},{ 25, 26}, + { 27, 28},{ 29, 30},{ 31, 32},{ -29, 33},{ -16, 34},{ -3, 35},{ 36, 37},{ -42, 38}, + { 39, 40},{ 41, 42},{ 43, 44},{ -17, 45},{ -43, 46},{ 47, 48},{ -4, 49},{ -56, 50}, + { 51, 52},{ 53, 54},{ 55, 56},{ -57, -5},{ -30, 57},{ 58, 59},{ -18, 60},{ 61, -70}, + { 62, 63},{ 64, -6},{ 65, 66},{ -44, 67},{ -71, 68},{ 69, 70},{ -19, -31},{ -84, 71}, + { 72, 73},{ 74, 75},{ 76, 77},{ -7, 78},{ 79, -20},{ 80, 81},{ -85, 82},{ -98, 83}, + { -58, 84},{ 85, -32},{ -99, 86},{ -8, 87},{ 88, 89},{ -72, -45},{ 90, -33},{ 91,-112}, + { -21, 92},{ -59,-113},{ -46, 93},{ -9, 94},{ -22, 95},{ 96, 97},{ 98, 99},{ -23, -86}, + { 100, 101},{ -34, -73},{ 102,-126},{-127, -35},{ 103, -47},{ 104, 105},{ 106, 107},{-140,-100}, + {-114, -87},{ 108, 109},{ 110, 111},{-141, -60},{ 112, -48},{ 113, -24},{ -10, -61},{ 114,-101}, + { 115, 116},{ -74, -36},{ 117,-128},{ 118, -62},{ 119, 120},{ -37, 121},{ -11, -49},{ -88, 122}, + { 123,-115},{-154, -25},{-142, 124},{-155,-129},{ 125, -50},{ 126, 127},{ -76, -75},{ 128, 129}, + { -63, -77},{-102, -39},{ -38, 130},{ -51, 131},{ -89,-116},{-117,-156},{ 132, -52},{ -78, 133}, + { 134,-103},{ 135, 136},{-143, -65},{ 137, -64},{-130,-131},{ -90, 138},{-104, -91},{ -92, 139}, + {-169,-183},{ -26,-118},{ 140, 141},{-144, -66},{ -12, 142},{-168, 143},{-105,-157},{ 144,-182}, + { 145, 146},{ -79, 147},{ -53,-170},{ 148, 149},{ -27,-145},{ 150, -80},{-106, -13},{-132, -67}, + {-158, -40},{-119, 151},{ 152,-107},{ 153, 154},{ -41,-184},{ 155, 156},{ -54, 157},{-171, 158}, + { -94, 159},{-134,-146},{ -93,-133},{-159,-108},{ 160, -81},{ 161,-160},{ 162, -68},{-120,-122}, + {-172, 163},{ -55, -95},{ 164,-109},{-161, -82},{-173,-185},{ 165, -69},{-147,-186},{ 166, 167}, + {-121, -96},{ 168,-148},{-174, 169},{ 170,-136},{ -83, 171},{ 172, 173},{-135,-110},{-187, 174}, + {-149,-150},{ 175,-123},{-162,-163},{ -97,-175},{-188, 176},{ 177, 178},{ 179,-111},{-151,-124}, + {-137,-177},{-176,-125},{-164,-138},{-189,-190},}; +static const int16_t mlt_decoder_tree_category_1[93][2] = { + { 1, 0},{ 2, 3},{ 4, 5},{ 6, 7},{ 8, -10},{ -1, 9},{ 10, 11},{ 12, 13}, + { -11, 14},{ 15, 16},{ 17, 18},{ -20, -2},{ 19, 20},{ -21, 21},{ 22, 23},{ -12, 24}, + { 25, 26},{ 27, 28},{ 29, 30},{ -30, 31},{ -31, -3},{ 32, -22},{ 33, -13},{ 34, 35}, + { 36, 37},{ 38, 39},{ 40, -4},{ -41, -14},{ 41, -40},{ -32, 42},{ 43, -23},{ 44, 45}, + { 46, 47},{ 48, -5},{ -51, -50},{ -42, 49},{ -33, 50},{ -15, 51},{ 52, 53},{ 54, -24}, + { 55, -43},{ 56, -52},{ 57, -61},{ -60, 58},{ -25, 59},{ -16, -34},{ -6, 60},{ -62, 61}, + { -71, 62},{ -35, -7},{ 63, -72},{ -53, -17},{ 64, -44},{ -26, -70},{ 65, -45},{ -36, 66}, + { -63, 67},{ -80, -54},{ -81, 68},{ -27, 69},{ 70, -82},{ -18, 71},{ 72, -55},{ 73, -64}, + { 74, -73},{ 75, -46},{ -37, 76},{ -91, -8},{ -9, 77},{ -90, -83},{ 78, -28},{ 79, -56}, + { -65, -38},{ -74, 80},{ -19, -57},{ -92, 81},{ -47, -48},{ 82, -66},{ 83, -29},{ -84, 84}, + { -75, -85},{ -67, -93},{ -39, 85},{ -76, 86},{ -58, 87},{ 88, -49},{ -94, 89},{ 90, -68}, + { 91, -78},{ -86, -59},{ -77, -95},{ 92, -69},{ -87, -96},}; +static const int16_t mlt_decoder_tree_category_2[47][2] = { + { 1, 0},{ 2, 3},{ 4, 5},{ 6, -7},{ -1, 7},{ -8, 8},{ 9, 10},{ 11, 12}, + { 13, -14},{ -15, -9},{ -2, 14},{ 15, 16},{ 17, 18},{ 19, -16},{ 20, -22},{ -10, 21}, + { -21, -3},{ 22, 23},{ 24, 25},{ -23, -17},{ 26, 27},{ 28, -29},{ -11, -28},{ 29, 30}, + { -4, -24},{ -30, 31},{ 32, -18},{ 33, -35},{ -36, 34},{ -31, -12},{ 35, -25},{ -5, -37}, + { 36, 37},{ -42, 38},{ -19, -43},{ -32, 39},{ -13, -38},{ -26, -20},{ 40, -6},{ -44, 41}, + { 42, -39},{ -33, -45},{ 43, -27},{ 44, -46},{ 45, -34},{ -40, 46},{ -41, -47},}; +static const int16_t mlt_decoder_tree_category_3[519][2] = { + { 1, 2},{ 3, 4},{ 5, 0},{ 6, 7},{ 8, 9},{ 10, 11},{ 12, 13},{ 14, 15}, + { 16, 17},{-125, 18},{ -1, 19},{ 20, 21},{ 22, 23},{ 24, 25},{ -5, -25},{ 26, 27}, + { -6,-150},{ 28, 29},{ 30, 31},{ 32, 33},{ 34, -30},{ 35, 36},{ 37, 38},{ 39, -31}, + {-126,-155},{ 40, 41},{-156, 42},{ 43,-130},{ 44,-131},{-151, -26},{ 45, 46},{-250, 47}, + { 48, 49},{ 50, 51},{ 52,-275},{ 53, 54},{ -2, -7},{ 55, 56},{ 57, 58},{ 59, 60}, + { 61, 62},{ 63, 64},{ 65, 66},{ 67, 68},{ 69, 70},{ 71, -50},{ 72,-180},{ 73, 74}, + { 75, 76},{ 77, -55},{ 78,-175},{ 79, -36},{ 80, 81},{ -35, -10},{ 82, 83},{-280, 84}, + { -11, 85},{ 86, -32},{ 87, 88},{ 89,-161},{ 90,-276},{ 91, 92},{-281, 93},{ -8, 94}, + { 95, 96},{ 97,-157},{-181,-400},{-132, 98},{-375, 99},{-160, 100},{-127, 101},{ -27, 102}, + { 103,-251},{ -56, 104},{ 105,-256},{-300, -3},{-152,-255},{ 106, 107},{ -37, 108},{-305, 109}, + {-176, 110},{-136, 111},{ -12, 112},{ 113, 114},{ 115,-135},{ 116, 117},{-162, 118},{ -16, -51}, + {-186, 119},{ 120, 121},{ 122, 123},{ -41, 124},{ -61, 125},{ 126, 127},{ 128, 129},{ 130, -60}, + { 131, 132},{-306, 133},{ 134,-205},{-405, 135},{ 136, 137},{ 138, 139},{-185, 140},{ 141,-500}, + { -15, 142},{ 143, -80},{ -75, -40},{-301, 144},{ 145, 146},{-200, 147},{ 148, 149},{ 150, 151}, + { 152,-525},{ 153,-177},{-425, 154},{ 155, -13},{-430, 156},{ 157,-406},{ 158, 159},{-206,-380}, + { 160, 161},{ 162, 163},{ 164,-182},{-137, 165},{-286, 166},{ 167,-401},{ 168, 169},{ -42, -33}, + { 170,-166},{ -57,-325},{ 171,-187},{ -38, 172},{ 173, 174},{-165,-330},{ -4,-282},{ 175,-257}, + {-261,-311},{-376, 176},{ 177, 178},{ -28, 179},{ 180, -9},{-285, 181},{ 182, 183},{ 184,-277}, + { 185,-133},{-310, -81},{ -85, 186},{-158,-210},{ -17, 187},{ 188, 189},{ 190, -52},{-141, 191}, + { 192,-128},{-191, -20},{ 193,-140},{ 194, 195},{-211,-260},{ 196, 197},{ 198, 199},{ 200, -66}, + {-201,-225},{-381, 201},{ 202, 203},{ 204, 205},{ 206, 207},{-163,-287},{ 208,-100},{ 209, 210}, + { 211, 212},{ 213,-252},{-105, -76},{ 214, 215},{ 216, -21},{ -86, -62},{-307, 217},{ -65,-455}, + {-550, 218},{ 219, 220},{ 221, 222},{ 223, 224},{ 225,-230},{-142, 226},{-302,-426},{-431, 227}, + { 228, 229},{ 230,-190},{-402, -46},{-153,-450},{-505, 231},{ 232, 233},{ 234, 235},{ 236, 237}, + { 238, 239},{-262, -29},{ 240, 241},{ 242, 243},{-167, -67},{-331,-530},{ 244, 245},{ 246, 247}, + { 248, 249},{ 250, 251},{ 252, 253},{ 254, 255},{ 256, 257},{ 258, 259},{ 260, 261},{ 262,-336}, + { 263,-171},{-192,-207},{-258,-138},{ 264, 265},{ 266, 267},{ 268, 269},{ 270, 271},{ 272, 273}, + { 274, -45},{-335,-411},{ -43, -18},{-265, -71},{-316,-326},{-350,-407},{-146, -14},{ 275, 276}, + { 277, 278},{ 279, 280},{ 281,-216},{ -34,-283},{-291,-312},{-410,-168},{-555, 282},{ -70, -53}, + {-235, -87},{ -77,-183},{-315,-332},{-178, -58},{ 283, 284},{ 285, 286},{ 287, 288},{ 289, 290}, + { 291, 292},{ 293, 294},{ 295, 296},{ 297, 298},{-202,-226},{-170,-267},{-134,-290},{-355,-385}, + {-386, -47},{-526,-196},{ 299, 300},{ 301, 302},{ 303, 304},{ 305, 306},{ 307, 308},{ 309, 310}, + { 311, 312},{ 313, 314},{ 315, 316},{ 317, 318},{ 319, 320},{ 321, 322},{ 323, 324},{ 325,-111}, + {-231,-253},{ -91, -82},{-172,-145},{ -22,-317},{ -90,-356},{-382,-159},{ 326, 327},{ 328, 329}, + { 330, 331},{ 332, 333},{ 334, 335},{-106,-263},{-278,-215},{-110, -39},{-101,-377},{-129, -63}, + {-436,-195},{-506,-531},{ 336,-212},{-154,-266},{ -59,-288},{-292,-303},{-337,-432},{-188,-451}, + {-456,-460},{-501,-236},{-551, 337},{ 338, 339},{ 340, 341},{ 342, 343},{ 344, 345},{ 346, 347}, + { 348, 349},{ 350, 351},{ 352, 353},{ 354, 355},{ 356, 357},{ 358, 359},{ 360, 361},{ 362, 363}, + { 364, 365},{ 366, 367},{ 368, 369},{ 370, 371},{ 372, 373},{ 374, 375},{ 376, 377},{ 378, 379}, + { 380, 381},{ 382, 383},{ 384, 385},{ 386, 387},{ 388, 389},{ 390, 391},{ 392, 393},{ 394, 395}, + { 396, 397},{ 398, 399},{ 400, 401},{ 402, 403},{ 404, 405},{ 406, 407},{ -72,-272},{-309,-333}, + {-340,-360},{ -68,-387},{-184,-416},{-427,-147},{-435,-437},{-115,-480},{-510,-532},{-164,-556}, + { 408,-295},{-296,-297},{-107,-313},{-193,-173},{-320,-327},{-341,-351},{-352,-143},{-378, -19}, + {-403,-412},{-268, -54},{ -83,-441},{-442,-457},{-475, -44},{ -97,-511},{-515,-208},{-527,-528}, + {-237,-536},{-552, 409},{ 410, 411},{ 412, 413},{ 414, 415},{ 416, 417},{ 418, 419},{ 420, 421}, + { 422, 423},{ 424, 425},{ 426, 427},{ 428, 429},{ 430, 431},{ 432, 433},{ 434, 435},{ 436, 437}, + { 438, 439},{ 440, 441},{ 442, 443},{ 444, 445},{ 446, 447},{ 448, 449},{ 450, 451},{ 452, 453}, + { 454, 455},{ 456, 457},{ 458, 459},{ 460, 461},{ 462, 463},{ 464, 465},{ 466, 467},{ 468, 469}, + { 470, 471},{ 472, 473},{ 474, 475},{ 476, 477},{ 478, 479},{ 480, 481},{ 482, 483},{ 484, 485}, + { 486, 487},{ 488, 489},{ 490, 491},{ 492, 493},{ 494, 495},{ 496, 497},{ 498, 499},{ 500, 501}, + { 502, 503},{ 504, 505},{ 506, 507},{ 508, 509},{ 510, 511},{ 512, 513},{ 514, 515},{ 516, 517}, + { 518,-104},{ -84,-218},{-318,-319},{-117,-321},{-322,-323},{-219,-174},{-243,-328},{-329, -94}, + {-228,-194},{-240,-334},{-102,-229},{-169,-338},{-339,-116},{-289,-342},{-343,-345},{-346,-347}, + { -23,-203},{-214,-353},{-204,-220},{-357,-358},{-264,-361},{-362,-363},{-365,-366},{-367, -92}, + {-245,-121},{-293,-379},{-108,-232},{-221,-383},{-384,-233},{-294,-241},{-388,-389},{-390,-391}, + {-392,-393},{-394,-395},{-396,-397},{-398, -24},{-109,-149},{-242,-404},{ -64, -79},{ -89,-408}, + {-409,-213},{-120,-113},{-413,-414},{-415, -96},{-417,-418},{-419,-420},{-421,-422},{-423,-298}, + { -69,-269},{-428,-429},{ -78,-270},{ -88,-433},{-434,-271},{-234,-259},{-438,-439},{-440,-227}, + {-179,-443},{-445,-446},{-447,-223},{-238,-452},{-453,-454},{-273,-254},{-246,-458},{-459, -48}, + {-461,-462},{-463,-465},{-466,-467},{-468,-470},{-471,-304},{-476,-477},{-478,-112},{-481,-482}, + {-483,-485},{-486,-487},{-490,-491},{-103,-118},{-502,-503},{-504,-189},{ -93,-507},{-508,-509}, + {-148,-139},{-512,-513},{-308,-516},{-517,-518},{-520,-521},{ -73, -98},{ -95, -49},{-529,-222}, + {-217,-197},{-533,-534},{-535,-284},{-537,-538},{-540,-541},{-542,-543},{-545,-546},{-144,-198}, + {-314,-553},{-209,-279},{-557,-558},{-560,-561},{-562,-563},{-565,-566},{-567,-575},{-576,-577}, + {-578,-580},{-581,-582},{-583,-585},{-586,-587},{-590,-591},{-600,-601},{-605,-606},}; +static const int16_t mlt_decoder_tree_category_4[208][2] = { + { 1, 2},{ 3, 0},{ 4, 5},{ 6, 7},{ 8, 9},{ 10, 11},{ 12, -64},{ -1, 13}, + { 14, -16},{ -4, 15},{ 16, 17},{ 18, -80},{ -5, 19},{ 20, 21},{ -20, 22},{ 23, -65}, + { -84, -21},{ -68, 24},{ -17, 25},{ 26, 27},{ 28, -81},{ -69, -85},{ 29, 30},{ 31, 32}, + {-128, 33},{ 34, 35},{ -2, 36},{ 37, 38},{-144, 39},{ 40, -6},{ 41, 42},{ -32, 43}, + { 44, -8},{ 45, -25},{ -96, 46},{ 47,-100},{ -9, 48},{ 49, -36},{ 50, -24},{ 51, 52}, + { 53,-148},{ 54, 55},{ -22, 56},{ 57, 58},{-132, -89},{ 59, 60},{-101, 61},{ -37, 62}, + { -18, 63},{ -88,-129},{ -66, -70},{ -97, 64},{ -72, -73},{ 65,-145},{-149, -86},{ 66, -33}, + { 67,-133},{ 68, 69},{ 70, 71},{-192, 72},{ 73,-160},{ -82, 74},{-164, 75},{ -10, 76}, + { 77,-208},{ 78, -40},{ 79, 80},{ -3, 81},{ -7, 82},{ 83, 84},{-104, 85},{ 86, -26}, + { 87,-105},{ 88,-112},{ 89, 90},{ 91, -41},{ 92, 93},{ 94, 95},{ -48, 96},{ -90, 97}, + { 98, -28},{ -52, 99},{ -12, 100},{ 101, -74},{ -13,-116},{-161, 102},{ 103, -29},{-102, 104}, + {-152,-165},{ 105, 106},{ 107, 108},{ 109, 110},{ 111,-212},{ 112, 113},{-136, 114},{ 115,-137}, + { 116, -23},{ -19,-153},{ -98,-134},{-196, 117},{ 118, 119},{ -38,-193},{-113,-150},{-209, 120}, + { 121, -93},{ -83, 122},{ 123, 124},{ 125, 126},{ 127, 128},{ 129, 130},{ 131, -34},{-146, -53}, + { 132, 133},{ 134, 135},{ 136, 137},{ 138,-130},{ -49, 139},{ 140, 141},{-117, -42},{ -67, -92}, + { 142, -87},{ -77,-197},{ -71, 143},{ 144, 145},{ 146, 147},{ 148, 149},{ 150, 151},{ 152, 153}, + { 154, 155},{ 156, 157},{ 158, 159},{ 160, 161},{ 162, 163},{ 164, 165},{ 166, 167},{ 168, 169}, + {-108, -76},{-168,-169},{-176, -44},{-224, -56},{ -45,-180},{ -11,-106},{-213, 170},{ 171, 172}, + { 173, 174},{ 175, 176},{ 177, 178},{ 179, 180},{ 181, 182},{ 183, 184},{ 185, 186},{ 187, 188}, + { 189, 190},{ 191, 192},{ 193, 194},{ 195, 196},{ 197, 198},{ 199, 200},{ 201, 202},{ 203, 204}, + { 205, 206},{ 207,-131},{ -30, -27},{ -43,-151},{ -75,-154},{-156,-162},{-109,-194},{-198,-201}, + {-114,-225},{-228,-229},{-141,-142},{ -94,-124},{ -95,-147},{-115,-125},{ -54, -55},{-107, -58}, + { -39,-155},{-121,-157},{-158,-103},{ -14,-122},{-163, -51},{ -57,-166},{-167, -46},{-110,-170}, + {-172,-173},{ -61,-177},{-178, -99},{-181,-182},{-184,-185},{-118, -35},{ -15,-195},{ -31, -60}, + {-135,-199},{-200, -79},{-202,-204},{-205,-119},{ -91,-210},{-211, -78},{-120,-214},{-215,-216}, + {-217,-218},{-220,-221},{ -50,-138},{-226,-139},{-140,-230},{-232,-233},{-240,-241},{-244,-245},}; +static const int16_t mlt_decoder_tree_category_5[191][2] = { + { 1, 2},{ 0, 3},{ 4, 5},{ 6, 7},{ 8, 9},{ 10, 11},{ -81, -1},{ 12, 13}, + { 14, -27},{ -3, -9},{ 15, 16},{ 17, 18},{ 19, 20},{-108, 21},{ -4, 22},{ 23, -36}, + { -12, 24},{ -82, 25},{ 26, -84},{ 27, -90},{ -10, -30},{ 28, 29},{ 30, -28},{ 31,-117}, + { -13, 32},{ -39, 33},{ 34,-109},{ 35, -93},{ -85,-111},{ -37, 36},{ -31, 37},{ -91, 38}, + { 39, 40},{ -40,-120},{ 41, 42},{-118, 43},{ -94, 44},{-112,-162},{ 45, 46},{ -2, 47}, + { 48, 49},{-121,-189},{ 50, -54},{ 51, 52},{ 53, -18},{ 54, 55},{ -6, 56},{ 57, -5}, + {-135, 58},{ 59, 60},{ 61, 62},{ -63, 63},{ 64, -7},{ -15, 65},{ 66, 67},{ -45, 68}, + { 69, 70},{ 71, -21},{ 72, 73},{ 74, 75},{ 76, 77},{-163, 78},{ 79,-171},{-144, 80}, + { -48, 81},{ -57, 82},{ 83, 84},{-165, 85},{ -16,-198},{ 86, 87},{ -11, 88},{ 89, -99}, + { 90, -83},{ -19, 91},{ 92, 93},{ 94, 95},{ 96, 97},{ 98, 99},{ -87, 100},{ 101, 102}, + {-190, -66},{ -33,-192},{ 103, 104},{ 105, 106},{-102, -42},{ 107,-126},{ 108, -29},{-129, -46}, + { -86, -14},{-114, -32},{-172, 109},{ 110, -58},{ -34,-138},{ 111, 112},{ 113, 114},{ 115, 116}, + { 117, 118},{ 119, 120},{-127,-166},{-174, 121},{ 122, 123},{ 124, 125},{ -88, -96},{ 126,-100}, + { -38,-110},{ -22,-136},{ -55,-139},{-201, 127},{ -64,-193},{ 128, -49},{-175,-199},{ 129, 130}, + { 131, 132},{ 133, 134},{ 135, 136},{ 137, 138},{ 139, 140},{ 141, 142},{ 143, 144},{ 145, 146}, + { 147, 148},{ 149, 150},{-103, -92},{ -43,-130},{-145,-147},{-148, -41},{-216,-115},{-119,-123}, + { -95, 151},{ 152, 153},{ 154, 155},{ 156, 157},{ 158, 159},{ 160, 161},{ 162, 163},{ 164, 165}, + { 166, 167},{ 168, 169},{ 170, 171},{ 172, 173},{ 174, 175},{ 176, 177},{ 178, 179},{ 180, 181}, + { 182, 183},{ 184, 185},{ 186, 187},{ 188, 189},{ 190,-153},{-180, -8},{ -97, -24},{-122,-113}, + {-124,-125},{ -67, -44},{-128, -69},{-106,-131},{-132,-133},{ -61, -73},{-137,-116},{ -89,-140}, + {-141,-142},{ -23, -25},{-146, -17},{-104,-149},{-150,-151},{ -52,-154},{-156,-157},{ -76, -70}, + {-164, -51},{ -72,-167},{-168,-169},{ -47, -20},{-173, -59},{-101,-176},{-177,-178},{ -68,-181}, + {-183,-184},{ -35, -60},{-191, -98},{ -56,-194},{-195,-196},{ -75, -65},{-200,-105},{-202,-203}, + {-204,-205},{-207,-208},{-210,-211},{ -50,-217},{-219,-220},{-225,-226},{-228,-229},}; +static const int16_t mlt_decoder_tree_category_6[31][2] = { + { 1, 0},{ 2, 3},{ 4, 5},{ 6, 7},{ 8, -16},{ -1, -8},{ -2, -4},{ 9, 10}, + { 11, 12},{ 13, 14},{ 15, 16},{ 17, -24},{ -3, -12},{ -6, 18},{ 19, -20},{ -10, -5}, + { -17, -9},{ -18, 20},{ 21, 22},{ 23, 24},{ 25, -28},{ 26, -7},{ -14, -22},{ -26, -11}, + { 27, -19},{ -25, -13},{ -21, 28},{ 29, -30},{ -27, 30},{ -15, -29},{ -23, -31},}; + +static const int16_t *table_of_decoder_tables[NUM_CATEGORIES-1] = { + (const int16_t *)mlt_decoder_tree_category_0, + (const int16_t *)mlt_decoder_tree_category_1, + (const int16_t *)mlt_decoder_tree_category_2, + (const int16_t *)mlt_decoder_tree_category_3, + (const int16_t *)mlt_decoder_tree_category_4, + (const int16_t *)mlt_decoder_tree_category_5, + (const int16_t *)mlt_decoder_tree_category_6, +}; + + +/* vs refdec: same table */ +static const int16_t region_standard_deviation_table[REGION_POWER_TABLE_SIZE] = { /* "rnd_reg"? */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 2, 3, 4, 6, 8, 11, + 16, 23, 32, 45, 64, 91, 128, 181, + 256, 362, 512, 724, 1024, 1448, 2048, 2896, + 4096,5793,8192,11585,16384,23170, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +/* the following tables don't use last index since category 7 isn't quantized */ + +/* vs refdec: same table but last index is 20 */ +static const int16_t number_of_vectors[NUM_CATEGORIES] = { + 10, 10, 10, 5, 5, 4, 4, 0, +}; +/* vs refdec: same table but last index is 1 */ +static const int16_t vector_dimension[NUM_CATEGORIES] = { /* "vd_inv"? */ + 2, 2, 2, 4, 4, 5, 5, 0, +}; + +/* vs refdec: pre-adds one instead of in runtime and last index is 1 */ +static const int16_t max_bin_plus1[NUM_CATEGORIES] = { /* "kmax_p1" */ + 14, 10, 7, 5, 4, 3, 2, 0, +}; + +/* vs refdec: pre-scaled x2 (cat3 subs -1 and cat5/7 -2 too) */ +static const uint16_t max_bin_plus_one_inverse_scaled[8] = { /* "kmax_p1_inv" */ + 4682, 6554, 9363, 13108, 16384, 21846, 32768, 0, +}; + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c index 1c290e4c6..ee8f4c509 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c @@ -263,6 +263,26 @@ static void blitz_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset if (*step_index > 88) *step_index=88; } +static const int CIMAADPCM_INDEX_TABLE[16] = {8, 6, 4, 2, -1, -1, -1, -1, + -1, -1, -1, -1, 2, 4, 6, 8}; + +/* Capcom's MT Framework modified IMA, reverse engineered from the exe */ +static void mtf_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { + int sample_nibble, sample_decoded, step, delta; + + sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf; + sample_decoded = *hist1; + step = ADPCMTable[*step_index]; + + delta = step * (2 * sample_nibble - 15); + sample_decoded += delta; + + *hist1 = sample_decoded; + *step_index += CIMAADPCM_INDEX_TABLE[sample_nibble]; + if (*step_index < 0) *step_index=0; + if (*step_index > 88) *step_index=88; +} + /* ************************************ */ /* DVI/IMA */ /* ************************************ */ @@ -298,6 +318,34 @@ void decode_standard_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int chann stream->adpcm_step_index = step_index; } +void decode_mtf_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo) { + int i, sample_count = 0; + int32_t hist1 = stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + /* external interleave */ + + /* no header (external setup), pre-clamp for wrong values */ + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + /* decode nibbles (layout: varies) */ + for (i = first_sample; i < first_sample + samples_to_do; i++, sample_count += channelspacing) { + off_t byte_offset = is_stereo ? + stream->offset + i : /* stereo: one nibble per channel */ + stream->offset + i/2; /* mono: consecutive nibbles */ + int nibble_shift = is_stereo ? + ((channel&1) ? 0:4) : + ((i&1) ? 0:4); + + mtf_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + outbuf[sample_count] = clamp16(hist1 >> 4); + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_step_index = step_index; +} + void decode_3ds_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { int i, sample_count; int32_t hist1 = stream->adpcm_history1_32; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/psv_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/psv_decoder.c index a6d1b9414..6daf057a6 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/psv_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/psv_decoder.c @@ -188,6 +188,7 @@ void decode_hevag(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspaci hist3 * hevag_coefs[coef_index][2] + hist4 * hevag_coefs[coef_index][3] ) / 32; sample = (sample + (scale << (20 - shift_factor)) + 128) >> 8; + sample = clamp16(sample); } outbuf[sample_count] = sample; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/relic_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/relic_decoder.c new file mode 100644 index 000000000..d10b421c9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/relic_decoder.c @@ -0,0 +1,500 @@ +#include "coding.h" + +/* Relic Codec decoder, a fairly simple mono-interleave DCT-based codec. + * + * Decompiled from Relic's dec.exe with some info from Homeworld source code .h/lib + * files (released around 2003 through Relic Dev Network), accurate with minor +-1 + * samples due to double<>float ops or maybe original compiler (Intel's) diffs. + * + * TODO: clean API, improve validations (can segfault on bad data) and naming + */ + +/* mixfft.c */ +extern void fft(int n, float *xRe, float *xIm, float *yRe, float *yIm); + +static relic_codec_data* init_codec(int channels, int bitrate, int codec_rate); +static int decode_frame_next(VGMSTREAMCHANNEL* stream, relic_codec_data* data); +static void copy_samples(relic_codec_data* data, sample_t* outbuf, int32_t samples_to_get); +static void reset_codec(relic_codec_data* data); + +#define RELIC_MAX_CHANNELS 2 +#define RELIC_MAX_SCALES 6 +#define RELIC_BASE_SCALE 10.0f +#define RELIC_FREQUENCY_MASKING_FACTOR 1.0f +#define RELIC_CRITICAL_BAND_COUNT 27 +#define RELIC_PI 3.14159265358979323846f +#define RELIC_SIZE_LOW 128 +#define RELIC_SIZE_MID 256 +#define RELIC_SIZE_HIGH 512 +#define RELIC_MAX_SIZE RELIC_SIZE_HIGH +#define RELIC_MAX_FREQ (RELIC_MAX_SIZE / 2) +#define RELIC_MAX_FFT (RELIC_MAX_SIZE / 4) +#define RELIC_BITRATE_22 256 +#define RELIC_BITRATE_44 512 +#define RELIC_BITRATE_88 1024 +#define RELIC_BITRATE_176 2048 +#define RELIC_MAX_FRAME_SIZE ((RELIC_BITRATE_176 / 8) + 0x04) /* extra 0x04 for the bitreader */ + + +struct relic_codec_data { + /* decoder info */ + int channels; + int frame_size; + int wave_size; + int freq_size; + int dct_mode; + int samples_mode; + /* decoder init state */ + float scales[RELIC_MAX_SCALES]; /* quantization scales */ + float dct[RELIC_MAX_SIZE]; + float window[RELIC_MAX_SIZE]; + /* decoder frame state */ + uint8_t exponents[RELIC_MAX_CHANNELS][RELIC_MAX_FREQ]; /* quantization/scale indexes */ + float freq1[RELIC_MAX_FREQ]; /* dequantized spectrum */ + float freq2[RELIC_MAX_FREQ]; + float wave_cur[RELIC_MAX_CHANNELS][RELIC_MAX_SIZE]; /* current frame samples */ + float wave_prv[RELIC_MAX_CHANNELS][RELIC_MAX_SIZE]; /* previous frame samples */ + + /* sample state */ + int32_t samples_discard; + int32_t samples_consumed; + int32_t samples_filled; +}; + +/* ************************************* */ + + +relic_codec_data* init_relic(int channels, int bitrate, int codec_rate) { + return init_codec(channels, bitrate, codec_rate); +} + +void decode_relic(VGMSTREAMCHANNEL* stream, relic_codec_data* data, sample_t* outbuf, int32_t samples_to_do) { + + while (samples_to_do > 0) { + + if (data->samples_consumed < data->samples_filled) { + /* consume samples */ + int samples_to_get = (data->samples_filled - data->samples_consumed); + + if (data->samples_discard) { + /* discard samples for looping */ + if (samples_to_get > data->samples_discard) + samples_to_get = data->samples_discard; + data->samples_discard -= samples_to_get; + } + else { + /* get max samples and copy */ + if (samples_to_get > samples_to_do) + samples_to_get = samples_to_do; + + copy_samples(data, outbuf, samples_to_get); + + samples_to_do -= samples_to_get; + outbuf += samples_to_get * data->channels; + } + + /* mark consumed samples */ + data->samples_consumed += samples_to_get; + } + else { + int ok = decode_frame_next(stream, data); + if (!ok) goto decode_fail; + } + } + return; + +decode_fail: + /* on error just put some 0 samples */ + VGM_LOG("RELIC: decode fail, missing %i samples\n", samples_to_do); + memset(outbuf, 0, samples_to_do * data->channels * sizeof(sample)); +} + +void reset_relic(relic_codec_data* data) { + if (!data) return; + + reset_codec(data); + data->samples_filled = 0; + data->samples_consumed = 0; + data->samples_discard = 0; +} + +void seek_relic(relic_codec_data* data, int32_t num_sample) { + if (!data) return; + + reset_relic(data); + data->samples_discard = num_sample; +} + +void free_relic(relic_codec_data* data) { + if (!data) return; + + free(data); +} + +/* ***************************************** */ + +static const int16_t critical_band_data[RELIC_CRITICAL_BAND_COUNT] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 9, 11, 13, 15, 17, 20, 23, 27, + 31, 37, 43, 51, 62, 74, 89, 110, + 139, 180, 256 +}; + +static void init_dct(float *dct, int dct_size) { + int i; + int dct_quarter = dct_size >> 2; + + for (i = 0; i < dct_quarter; i++) { + double temp = ((float)i + 0.125f) * (RELIC_PI * 2.0f) * (1.0f / (float)dct_size); + dct[i] = sin(temp); + dct[dct_quarter + i] = cos(temp); + } +} + +static int apply_idct(const float *freq, float *wave, const float *dct, int dct_size) { + int i; + float factor; + float out_re[RELIC_MAX_FFT]; + float out_im[RELIC_MAX_FFT]; + float in_re[RELIC_MAX_FFT]; + float in_im[RELIC_MAX_FFT]; + float wave_tmp[RELIC_MAX_SIZE]; + int dct_half = dct_size >> 1; + int dct_quarter = dct_size >> 2; + int dct_3quarter = 3 * (dct_size >> 2); + + /* prerotation? */ + for (i = 0; i < dct_quarter; i++) { + float coef1 = freq[2 * i] * 0.5f; + float coef2 = freq[dct_half - 1 - 2 * i] * 0.5f; + in_re[i] = coef1 * dct[dct_quarter + i] + coef2 * dct[i]; + in_im[i] = -coef1 * dct[i] + coef2 * dct[dct_quarter + i]; + } + + /* main FFT */ + fft(dct_quarter, in_re, in_im, out_re, out_im); + + /* postrotation, window and reorder? */ + factor = 8.0 / sqrt(dct_size); + for (i = 0; i < dct_quarter; i++) { + float out_re_i = out_re[i]; + out_re[i] = (out_re[i] * dct[dct_quarter + i] + out_im[i] * dct[i]) * factor; + out_im[i] = (-out_re_i * dct[i] + out_im[i] * dct[dct_quarter + i]) * factor; + wave_tmp[i * 2] = out_re[i]; + wave_tmp[i * 2 + dct_half] = out_im[i]; + } + for (i = 1; i < dct_size; i += 2) { + wave_tmp[i] = -wave_tmp[dct_size - 1 - i]; + } + + /* wave mix thing? */ + for (i = 0; i < dct_3quarter; i++) { + wave[i] = wave_tmp[dct_quarter + i]; + } + for (i = dct_3quarter; i < dct_size; i++) { + wave[i] = -wave_tmp[i - dct_3quarter]; + } + return 0; +} + +static void decode_frame(const float *freq1, const float *freq2, float *wave_cur, float *wave_prv, const float *dct, const float *window, int dct_size) { + int i; + float wave_tmp[RELIC_MAX_SIZE]; + int dct_half = dct_size >> 1; + + /* copy for first half(?) */ + memcpy(wave_cur, wave_prv, RELIC_MAX_SIZE * sizeof(float)); + + /* transform frequency domain to time domain with DCT/FFT */ + apply_idct(freq1, wave_tmp, dct, dct_size); + apply_idct(freq2, wave_prv, dct, dct_size); + + /* overlap and apply window function to filter this block's beginning */ + for (i = 0; i < dct_half; i++) { + wave_cur[dct_half + i] = wave_tmp[i] * window[i] + wave_cur[dct_half + i] * window[dct_half + i]; + wave_prv[i] = wave_prv[i] * window[i] + wave_tmp[dct_half + i] * window[dct_half + i]; + } +} + +static void init_window(float *window, int dct_size) { + int i; + + for (i = 0; i < dct_size; i++) { + window[i] = sin((float)i * (RELIC_PI / dct_size)); + } +} + +static void decode_frame_base(const float *freq1, const float *freq2, float *wave_cur, float *wave_prv, const float *dct, const float *window, int dct_mode, int samples_mode) { + int i; + float wave_tmp[RELIC_MAX_SIZE]; + + /* dec_relic only uses 512/512 mode, source references 256/256 (effects only?) too */ + + if (samples_mode == RELIC_SIZE_LOW) { + { + /* 128 DCT to 128 samples */ + decode_frame(freq1, freq2, wave_cur, wave_prv, dct, window, RELIC_SIZE_LOW); + } + } + else if (samples_mode == RELIC_SIZE_MID) { + if (dct_mode == RELIC_SIZE_LOW) { + /* 128 DCT to 256 samples (repeat sample x2) */ + decode_frame(freq1, freq2, wave_tmp, wave_prv, dct, window, RELIC_SIZE_LOW); + for (i = 0; i < 256 - 1; i += 2) { + wave_cur[i + 0] = wave_tmp[i >> 1]; + wave_cur[i + 1] = wave_tmp[i >> 1]; + } + } + else { + /* 256 DCT to 256 samples */ + decode_frame(freq1, freq2, wave_cur, wave_prv, dct, window, RELIC_SIZE_MID); + } + } + else if (samples_mode == RELIC_SIZE_HIGH) { + if (dct_mode == RELIC_SIZE_LOW) { + /* 128 DCT to 512 samples (repeat sample x4) */ + decode_frame(freq1, freq2, wave_tmp, wave_prv, dct, window, RELIC_SIZE_LOW); + for (i = 0; i < 512 - 1; i += 4) { + wave_cur[i + 0] = wave_tmp[i >> 2]; + wave_cur[i + 1] = wave_tmp[i >> 2]; + wave_cur[i + 2] = wave_tmp[i >> 2]; + wave_cur[i + 3] = wave_tmp[i >> 2]; + } + } + else if (dct_mode == RELIC_SIZE_MID) { + /* 256 DCT to 512 samples (repeat sample x2) */ + decode_frame(freq1, freq2, wave_tmp, wave_prv, dct, window, RELIC_SIZE_MID); + for (i = 0; i < 512 - 1; i += 2) { + wave_cur[i + 0] = wave_tmp[i >> 1]; + wave_cur[i + 1] = wave_tmp[i >> 1]; + } + } + else { + /* 512 DCT to 512 samples */ + decode_frame(freq1, freq2, wave_cur, wave_prv, dct, window, RELIC_SIZE_HIGH); + } + } +} + + +/* reads 32b max, packed in LSB order per byte (like Vorbis), ex. + * with 0x45 6A=01000101 01101010 could read 4b=0101, 6b=100100, 3b=010 ... + * assumes buf has enough extra bits to read 32b (size +0x04) */ +static uint32_t read_ubits(uint8_t bits, uint32_t offset, uint8_t *buf) { + uint32_t shift, mask, pos, val; + + shift = offset - 8 * (offset / 8); + mask = (1 << bits) - 1; + pos = offset / 8; + val = (buf[pos+0]) | (buf[pos+1]<<8) | (buf[pos+2]<<16) | (buf[pos+3]<<24); + return (val >> shift) & mask; +} +static int read_sbits(uint8_t bits, uint32_t offset, uint8_t *buf) { + uint32_t val = read_ubits(bits, offset, buf); + if (val >> (bits - 1) == 1) { /* upper bit = sign */ + uint32_t mask = (1 << (bits - 1)) - 1; + return -(val & mask); + } + return val; +} + +static void init_dequantization(float* scales) { + int i; + + scales[0] = RELIC_BASE_SCALE; + for (i = 1; i < RELIC_MAX_SCALES; i++) { + scales[i] = scales[i - 1] * scales[0]; + } + for (i = 0; i < RELIC_MAX_SCALES; i++) { + scales[i] = RELIC_FREQUENCY_MASKING_FACTOR / (double) ((1 << (i + 1)) - 1) * scales[i]; + } +} + +static void unpack_frame(uint8_t *buf, int buf_size, float *freq1, float *freq2, const float* scales, uint8_t *exponents, int freq_size) { + uint8_t flags, cb_bits, ev_bits, ei_bits, qv_bits; + int qv; + uint8_t ev; + uint8_t move, pos; + uint32_t bit_offset; + int i, j; + int freq_half = freq_size >> 1; + + + memset(freq1, 0, RELIC_MAX_FREQ * sizeof(float)); + memset(freq2, 0, RELIC_MAX_FREQ * sizeof(float)); + + flags = read_ubits(2u, 0u, buf); + cb_bits = read_ubits(3u, 2u, buf); + ev_bits = read_ubits(2u, 5u, buf); + ei_bits = read_ubits(4u, 7u, buf); + bit_offset = 11; + + /* reset exponents indexes */ + if ((flags & 1) == 1) { + memset(exponents, 0, RELIC_MAX_FREQ); + } + + /* read packed exponents indexes for all bands */ + if (cb_bits > 0 && ev_bits > 0) { + pos = 0; + for (i = 0; i < RELIC_CRITICAL_BAND_COUNT - 1; i++) { + if (bit_offset >= 8*buf_size) + break; + + move = read_ubits(cb_bits, bit_offset, buf); + bit_offset += cb_bits; + if (i > 0 && move == 0) + break; + pos += move; + + ev = read_ubits(ev_bits, bit_offset, buf); + bit_offset += ev_bits; + for (j = critical_band_data[pos]; j < critical_band_data[pos + 1]; j++) + exponents[j] = ev; + } + } + + /* read quantized values */ + if (freq_half > 0 && ei_bits > 0) { + + /* read first part */ + pos = 0; + for (i = 0; i < RELIC_MAX_FREQ; i++) { + if (bit_offset >= 8*buf_size) + break; + + move = read_ubits(ei_bits, bit_offset, buf); + bit_offset += ei_bits; + if (i > 0 && move == 0) + break; + pos += move; + + qv_bits = exponents[pos]; + qv = read_sbits(qv_bits + 2u, bit_offset, buf); + bit_offset += qv_bits + 2u; + + if (qv != 0 && pos < freq_half && qv_bits < 6) + freq1[pos] = (float)qv * scales[qv_bits]; + } + + /* read second part, or clone it */ + if ((flags & 2) == 2) { + memcpy(freq2, freq1, RELIC_MAX_FREQ * sizeof(float)); + } + else { + pos = 0; + for (i = 0; i < RELIC_MAX_FREQ; i++) { + if (bit_offset >= 8*buf_size) + break; + + move = read_ubits(ei_bits, bit_offset, buf); + bit_offset += ei_bits; + if (i > 0 && move == 0) + break; + pos += move; + + qv_bits = exponents[pos]; + qv = read_sbits(qv_bits + 2u, bit_offset, buf); + bit_offset += qv_bits + 2u; + + if (qv != 0 && pos < freq_half && qv_bits < 6) + freq2[pos] = (float)qv * scales[qv_bits]; + } + } + } +} + +static int decode_frame_next(VGMSTREAMCHANNEL* stream, relic_codec_data* data) { + int ch; + int bytes; + uint8_t buf[RELIC_MAX_FRAME_SIZE]; + + for (ch = 0; ch < data->channels; ch++) { + /* clean extra bytes for bitreader */ + memset(buf + data->frame_size, 0, RELIC_MAX_FRAME_SIZE - data->frame_size); + + bytes = read_streamfile(buf, stream->offset, data->frame_size, stream->streamfile); + if (bytes != data->frame_size) goto fail; + stream->offset += data->frame_size; + + unpack_frame(buf, sizeof(buf), data->freq1, data->freq2, data->scales, data->exponents[ch], data->freq_size); + + decode_frame_base(data->freq1, data->freq2, data->wave_cur[ch], data->wave_prv[ch], data->dct, data->window, data->dct_mode, data->samples_mode); + } + + data->samples_consumed = 0; + data->samples_filled = data->wave_size; + return 1; +fail: + return 0; +} + +static void copy_samples(relic_codec_data* data, sample_t* outbuf, int32_t samples) { + int s, ch; + int ichs = data->channels; + int skip = data->samples_consumed; + for (ch = 0; ch < ichs; ch++) { + for (s = 0; s < samples; s++) { + double d64_sample = data->wave_cur[ch][skip + s]; + int pcm_sample = clamp16(d64_sample); + + /* f32 in PCM 32767.0 .. -32768.0 format, original code + * does some custom double-to-int rint() though */ + //FQ_BNUM ((float)(1<<26)*(1<<26)*1.5) + //rint(x) ((d64 = (double)(x)+FQ_BNUM), *(int*)(&d64)) + + outbuf[s*ichs + ch] = pcm_sample; + } + } +} + +static relic_codec_data* init_codec(int channels, int bitrate, int codec_rate) { + relic_codec_data *data = NULL; + + if (channels > RELIC_MAX_CHANNELS) + goto fail; + + data = calloc(1, sizeof(relic_codec_data)); + if (!data) goto fail; + + data->channels = channels; + + /* dequantized freq1+2 size (separate from DCT) */ + if (codec_rate < 22050) /* probably 11025 only */ + data->freq_size = RELIC_SIZE_LOW; + if (codec_rate == 22050) + data->freq_size = RELIC_SIZE_MID; + if (codec_rate > 22050) /* probably 44100 only */ + data->freq_size = RELIC_SIZE_HIGH; + + /* default for streams (only a few mode combos are valid, see decode) */ + data->wave_size = RELIC_SIZE_HIGH; + data->dct_mode = RELIC_SIZE_HIGH; + data->samples_mode = RELIC_SIZE_HIGH; + + init_dct(data->dct, RELIC_SIZE_HIGH); + init_window(data->window, RELIC_SIZE_HIGH); + init_dequantization(data->scales); + memset(data->wave_prv, 0, RELIC_MAX_CHANNELS * RELIC_MAX_SIZE * sizeof(float)); + + switch(bitrate) { + case RELIC_BITRATE_22: + case RELIC_BITRATE_44: + case RELIC_BITRATE_88: + case RELIC_BITRATE_176: + data->frame_size = (bitrate / 8); /* 0x100 and 0x80 are common */ + break; + default: + goto fail; + } + + + return data; +fail: + free_relic(data); + return NULL; +} + +static void reset_codec(relic_codec_data* data) { + memset(data->wave_prv, 0, RELIC_MAX_CHANNELS * RELIC_MAX_SIZE * sizeof(float)); +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/relic_decoder_mixfft.c b/Frameworks/vgmstream/vgmstream/src/coding/relic_decoder_mixfft.c new file mode 100644 index 000000000..0e977e735 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/relic_decoder_mixfft.c @@ -0,0 +1,618 @@ +/* Original Relic code uses mixfft.c v1 by Jens Jorgen Nielsen, though was + * modified to use floats instead of doubles. This is a 100% decompilation + * that somehow resulted in the exact same code (no compiler optims set?), + * so restores comments back but removes/cleans globals (could be simplified). */ + +#include +#include +#include +#include + +/* ------------------------------------------------------------------------- */ + +/************************************************************************ + fft(int n, double xRe[], double xIm[], double yRe[], double yIm[]) + ------------------------------------------------------------------------ + NOTE : This is copyrighted material, Not public domain. See below. + ------------------------------------------------------------------------ + Input/output: + int n transformation length. + double xRe[] real part of input sequence. + double xIm[] imaginary part of input sequence. + double yRe[] real part of output sequence. + double yIm[] imaginary part of output sequence. + ------------------------------------------------------------------------ + Function: + The procedure performs a fast discrete Fourier transform (FFT) of + a complex sequence, x, of an arbitrary length, n. The output, y, + is also a complex sequence of length n. + + y[k] = sum(x[m]*exp(-i*2*pi*k*m/n), m=0..(n-1)), k=0,...,(n-1) + + The largest prime factor of n must be less than or equal to the + constant maxPrimeFactor defined below. + ------------------------------------------------------------------------ + Author: + Jens Joergen Nielsen For non-commercial use only. + Bakkehusene 54 A $100 fee must be paid if used + DK-2970 Hoersholm commercially. Please contact. + DENMARK + + E-mail : jjn@get2net.dk All rights reserved. October 2000. + Homepage : http://home.get2net.dk/jjn + ------------------------------------------------------------------------ + Implementation notes: + The general idea is to factor the length of the DFT, n, into + factors that are efficiently handled by the routines. + + A number of short DFT's are implemented with a minimum of + arithmetical operations and using (almost) straight line code + resulting in very fast execution when the factors of n belong + to this set. Especially radix-10 is optimized. + + Prime factors, that are not in the set of short DFT's are handled + with direct evaluation of the DFP expression. + + Please report any problems to the author. + Suggestions and improvements are welcomed. + ------------------------------------------------------------------------ + Benchmarks: + The Microsoft Visual C++ compiler was used with the following + compile options: + /nologo /Gs /G2 /W4 /AH /Ox /D "NDEBUG" /D "_DOS" /FR + and the FFTBENCH test executed on a 50MHz 486DX : + + Length Time [s] Accuracy [dB] + + 128 0.0054 -314.8 + 256 0.0116 -309.8 + 512 0.0251 -290.8 + 1024 0.0567 -313.6 + 2048 0.1203 -306.4 + 4096 0.2600 -291.8 + 8192 0.5800 -305.1 + 100 0.0040 -278.5 + 200 0.0099 -280.3 + 500 0.0256 -278.5 + 1000 0.0540 -278.5 + 2000 0.1294 -280.6 + 5000 0.3300 -278.4 + 10000 0.7133 -278.5 + ------------------------------------------------------------------------ + The following procedures are used : + factorize : factor the transformation length. + transTableSetup : setup table with sofar-, actual-, and remainRadix. + permute : permutation allows in-place calculations. + twiddleTransf : twiddle multiplications and DFT's for one stage. + initTrig : initialise sine/cosine table. + fft_4 : length 4 DFT, a la Nussbaumer. + fft_5 : length 5 DFT, a la Nussbaumer. + fft_10 : length 10 DFT using prime factor FFT. + fft_odd : length n DFT, n odd. +*************************************************************************/ + +#define maxPrimeFactor 37 +#define maxPrimeFactorDiv2 ((maxPrimeFactor+1)/2) +#define maxFactorCount 20 + +static const float c3_1 = -1.5f; /* c3_1 = cos(2*pi/3)-1; */ +static const float c3_2 = 0.866025388240814208984375f; /* c3_2 = sin(2*pi/3); */ + +// static const float u5 = 1.256637096405029296875f; /* u5 = 2*pi/5; */ +static const float c5_1 = -1.25f; /* c5_1 = (cos(u5)+cos(2*u5))/2-1;*/ +static const float c5_2 = 0.559017002582550048828125f; /* c5_2 = (cos(u5)-cos(2*u5))/2; */ +static const float c5_3 = -0.951056540012359619140625f; /* c5_3 = -sin(u5); */ +static const float c5_4 = -1.538841724395751953125f; /* c5_4 = -(sin(u5)+sin(2*u5)); */ +static const float c5_5 = 0.3632712662220001220703125f; /* c5_5 = (sin(u5)-sin(2*u5)); */ +static const float c8 = 0.707106769084930419921875f; /* c8 = 1/sqrt(2); */ + +static const float pi = 3.1415927410125732421875f; + +#if 0 /* extra */ +static int groupOffset,dataOffset,adr; //,blockOffset +static int groupNo,dataNo,blockNo,twNo; +static float omega, tw_re,tw_im; +static float twiddleRe[maxPrimeFactor], twiddleIm[maxPrimeFactor], + trigRe[maxPrimeFactor], trigIm[maxPrimeFactor], + zRe[maxPrimeFactor], zIm[maxPrimeFactor]; +static float vRe[maxPrimeFactorDiv2], vIm[maxPrimeFactorDiv2]; +static float wRe[maxPrimeFactorDiv2], wIm[maxPrimeFactorDiv2]; +#endif + + +static void factorize(int n, int *nFact, int *fact) +{ + int i,j,k; + int nRadix; + int radices[7]; + int factors[maxFactorCount]; + + nRadix = 6; + radices[1]= 2; + radices[2]= 3; + radices[3]= 4; + radices[4]= 5; + radices[5]= 8; + radices[6]= 10; + + radices[0]= 1; /* extra (assumed) */ + factors[0]= 0; /* extra (assumed) */ + fact[0]= 0; /* extra (assumed) */ + fact[1]= 0; /* extra (assumed) */ + + if (n==1) + { + j=1; + factors[1]=1; + } + else j=0; + i=nRadix; + while ((n>1) && (i>0)) + { + if ((n % radices[i]) == 0) + { + n=n / radices[i]; + j=j+1; + factors[j]=radices[i]; + } + else i=i-1; + } + if (factors[j] == 2) /*substitute factors 2*8 with 4*4 */ + { + i = j-1; + while ((i>0) && (factors[i] != 8)) i--; + if (i>0) + { + factors[j] = 4; + factors[i] = 4; + } + } + if (n>1) + { + for (k=2; k1) + { + j=j+1; + factors[j]=n; + } + } + for (i=1; i<=j; i++) + { + fact[i] = factors[j-i+1]; + } + *nFact=j; +} /* factorize */ + +/**************************************************************************** + After N is factored the parameters that control the stages are generated. + For each stage we have: + sofar : the product of the radices so far. + actual : the radix handled in this stage. + remain : the product of the remaining radices. + ****************************************************************************/ + +static void transTableSetup(int *sofar, int *actual, int *remain, + int *nFact, + int *nPoints) +{ + int i; + + factorize(*nPoints, nFact, actual); + if (actual[*nFact] > maxPrimeFactor) + { +#if 0 /* extra */ + printf("\nPrime factor of FFT length too large : %6d", actual[*nFact]); + exit(1); +#endif + actual[*nFact] = maxPrimeFactor - 1; /* extra */ + } + remain[0]=*nPoints; + sofar[1]=1; + remain[1]=*nPoints / actual[1]; + for (i=2; i<=*nFact; i++) + { + sofar[i]=sofar[i-1]*actual[i-1]; + remain[i]=remain[i-1] / actual[i]; + } +} /* transTableSetup */ + +/**************************************************************************** + The sequence y is the permuted input sequence x so that the following + transformations can be performed in-place, and the final result is the + normal order. + ****************************************************************************/ + +static void permute(int nPoint, int nFact, + int *fact, int *remain, + float *xRe, float *xIm, + float *yRe, float *yIm) + +{ + int i,j,k; + int count[maxFactorCount]; + + for (i=1; i<=nFact; i++) count[i]=0; + k=0; + for (i=0; i<=nPoint-2; i++) + { + yRe[i] = xRe[k]; + yIm[i] = xIm[k]; + j=1; + k=k+remain[j]; + count[1] = count[1]+1; + while (count[j] >= fact[j]) + { + count[j]=0; + k=k-remain[j-1]+remain[j+1]; + j=j+1; + count[j]=count[j]+1; + } + } + yRe[nPoint-1]=xRe[nPoint-1]; + yIm[nPoint-1]=xIm[nPoint-1]; +} /* permute */ + + +/**************************************************************************** + Twiddle factor multiplications and transformations are performed on a + group of data. The number of multiplications with 1 are reduced by skipping + the twiddle multiplication of the first stage and of the first group of the + following stages. + ***************************************************************************/ + +static void initTrig(int radix, float *trigRe, float*trigIm) +{ + int i; + float w,xre,xim; + + w=2*pi/radix; + trigRe[0]=1; trigIm[0]=0; + xre=cos(w); + xim=-sin(w); + trigRe[1]=xre; trigIm[1]=xim; + for (i=2; i= n) k = k - n; + } + } + for (j=1; j < max; j++) + { + zRe[0]=zRe[0] + vRe[j]; + zIm[0]=zIm[0] + wIm[j]; + } +} /* fft_odd */ + + +static void twiddleTransf(int sofarRadix, int radix, int remainRadix, + float *yRe, float *yIm) + +{ /* twiddleTransf */ + float cosw, sinw, gem; + float t1_re,t1_im, t2_re,t2_im, t3_re,t3_im; + float t4_re,t4_im, t5_re,t5_im; + float m1_re,m1_im, m2_re,m2_im, m3_re,m3_im; + float m4_re,m4_im, m5_re,m5_im; + float s1_re,s1_im, s2_re,s2_im, s3_re,s3_im; + float s4_re,s4_im, s5_re,s5_im; + int groupOffset,dataOffset,adr; //,blockOffset /* extra */ + int groupNo,dataNo,blockNo,twNo; /* extra */ + float omega, tw_re,tw_im; /* extra */ + float twiddleRe[maxPrimeFactor] = {0}, twiddleIm[maxPrimeFactor] = {0}, /* extra */ + trigRe[maxPrimeFactor] = {0}, trigIm[maxPrimeFactor] = {0}, /* extra */ + zRe[maxPrimeFactor] = {0}, zIm[maxPrimeFactor] = {0}; /* extra */ + + + initTrig(radix, trigRe, trigIm); + omega = 2*pi/(double)(sofarRadix*radix); + cosw = cos(omega); + sinw = -sin(omega); + tw_re = 1.0; + tw_im = 0; + dataOffset=0; + groupOffset=dataOffset; + adr=groupOffset; + for (dataNo=0; dataNo1) + { + twiddleRe[0] = 1.0; + twiddleIm[0] = 0.0; + twiddleRe[1] = tw_re; + twiddleIm[1] = tw_im; + for (twNo=2; twNo1) && (dataNo > 0)) + { + zRe[0]=yRe[adr]; + zIm[0]=yIm[adr]; + blockNo=1; + do { + adr = adr + sofarRadix; + zRe[blockNo]= twiddleRe[blockNo] * yRe[adr] + - twiddleIm[blockNo] * yIm[adr]; + zIm[blockNo]= twiddleRe[blockNo] * yIm[adr] + + twiddleIm[blockNo] * yRe[adr]; + + blockNo++; + } while (blockNo < radix); + } + else { + for (blockNo=0; blockNostreamfile) >> + (i & 1 ? 4 : 0)) & 0xf; + + uint8_t slopeIndex = stream->adpcm_scale | (samp >> 1); + + stream->adpcm_step_index = slopeTable[slopeIndex] >> 8; + stream->adpcm_scale = slopeTable[slopeIndex] & 0xff; + + stream->adpcm_history1_16 += (samp & 1) ? + -stream->adpcm_step_index: + stream->adpcm_step_index; + + if (stream->adpcm_history1_16 < 0) + stream->adpcm_history1_16 = 0; + + if (stream->adpcm_history1_16 > 0xff) + stream->adpcm_history1_16 = 0xff; + + outbuf[sample_count] = stream->adpcm_history1_16 * 0x100 - 0x8000; + } +} \ No newline at end of file diff --git a/Frameworks/vgmstream/vgmstream/src/coding/yamaha_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/yamaha_decoder.c index 3374f505b..d0345c2e6 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/yamaha_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/yamaha_decoder.c @@ -1,209 +1,201 @@ -#include "../util.h" -#include "coding.h" - -/* fixed point amount to scale the current step size */ -static const unsigned int scale_step_aica[16] = { - 230, 230, 230, 230, 307, 409, 512, 614, - 230, 230, 230, 230, 307, 409, 512, 614 -}; - -static const int scale_step_adpcmb[16] = { - 57, 57, 57, 57, 77, 102, 128, 153, - 57, 57, 57, 57, 77, 102, 128, 153, -}; - -/* look-up for 'mul' IMA's sign*((code&7) * 2 + 1) for every code */ -static const int scale_delta[16] = { - 1, 3, 5, 7, 9, 11, 13, 15, - -1, -3, -5, -7, -9,-11,-13,-15 -}; - -/* Yamaha ADPCM-B (aka DELTA-T) expand used in YM2608/YM2610/etc (cross referenced with various sources and .so) */ -static void yamaha_adpcmb_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t* hist1, int32_t* step_size, int16_t *out_sample) { - int code, delta, sample; - - code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf; - delta = ((((code & 0x7) * 2) + 1) * (*step_size)) >> 3; /* like 'mul' IMA */ - if (code & 8) - delta = -delta; - sample = *hist1 + delta; - - sample = clamp16(sample); /* this may not be needed (not done in Aska) but no byte changes */ - - *step_size = ((*step_size) * scale_step_adpcmb[code]) >> 6; - if (*step_size < 0x7f) *step_size = 0x7f; - else if (*step_size > 0x6000) *step_size = 0x6000; - - *out_sample = sample; - *hist1 = sample; -} - -/* Yamaha AICA expand, slightly filtered vs "ACM" Yamaha ADPCM, same as Creative ADPCM - * (some info from https://github.com/vgmrips/vgmplay, https://wiki.multimedia.cx/index.php/Creative_ADPCM) */ -static void yamaha_aica_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t* hist1, int32_t* step_size, int16_t *out_sample) { - int code, delta, sample; - - *hist1 = *hist1 * 254 / 256; /* hist filter is vital to get correct waveform but not done in many emus */ - - code = ((read_8bit(byte_offset,stream->streamfile) >> nibble_shift))&0xf; - delta = (*step_size * scale_delta[code]) / 8; /* 'mul' IMA with table (not sure if part of encoder) */ - sample = *hist1 + delta; - - sample = clamp16(sample); /* apparently done by official encoder */ - - *step_size = ((*step_size) * scale_step_aica[code]) >> 8; - if (*step_size < 0x7f) *step_size = 0x7f; - else if (*step_size > 0x6000) *step_size = 0x6000; - - *out_sample = sample; - *hist1 = sample; -} - - -/* info about Yamaha ADPCM as created by official yadpcm.acm (in 'Yamaha-ADPCM-ACM-Driver-100-j') - * - possibly RIFF codec 0x20 - * - simply called "Yamaha ADPCM Codec" (even though not quite like Yamaha ADPCM-B) - * - block_align = (sample_rate / 0x3C + 0x04) * channels (ex. 0x2E6 for 22050 stereo, probably given in RIFF) - * - low nibble first, stereo or mono modes (no interleave) - * - expand (old IMA 'shift+add' style, not 'mul' style): - * delta = step_size >> 3; - * if (code & 1) delta += step_size >> 2; - * if (code & 2) delta += step_size >> 1; - * if (code & 4) delta += step_size; - * if (code & 8) delta = -delta; - * sample = hist + clamp16(delta); - * though compiled more like: - * sample = hist + (1-2*(code & 8) * (step_size/8 + step_size/2 * (code&2) + step_size/4 * (code&1) + step_size * (code&4)) - * - step_size update: - * step_size = clamp_range(step_size * scale_step_aica[code] >> 8, 0x7F, 0x6000) - */ - - -/* Yamaha AICA ADPCM (also used in YMZ280B with high nibble first) */ -void decode_aica(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo) { - int i, sample_count = 0; - int16_t out_sample; - int32_t hist1 = stream->adpcm_history1_16; - int step_size = stream->adpcm_step_index; - - /* no header (external setup), pre-clamp for wrong values */ - if (step_size < 0x7f) step_size = 0x7f; - if (step_size > 0x6000) step_size = 0x6000; - - for (i = first_sample; i < first_sample + samples_to_do; i++) { - off_t byte_offset = is_stereo ? - stream->offset + i : /* stereo: one nibble per channel */ - stream->offset + i/2; /* mono: consecutive nibbles */ - int nibble_shift = is_stereo ? - (!(channel&1) ? 0:4) : /* even = low/L, odd = high/R */ - (!(i&1) ? 0:4); /* low nibble first */ - - yamaha_aica_expand_nibble(stream, byte_offset, nibble_shift, &hist1, &step_size, &out_sample); - outbuf[sample_count] = out_sample; - sample_count += channelspacing; - } - - stream->adpcm_history1_16 = hist1; - stream->adpcm_step_index = step_size; -} - -/* tri-Ace Aska ADPCM, Yamaha ADPCM-B with headered frames (reversed from Android SO's .so) - * implements table with if-else/switchs too but that's too goofy */ -void decode_aska(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { - int i, sample_count = 0, num_frame; - int16_t out_sample; - int32_t hist1 = stream->adpcm_history1_32; - int step_size = stream->adpcm_step_index; - - /* external interleave */ - int block_samples = (0x40 - 0x04*channelspacing) * 2 / channelspacing; - num_frame = first_sample / block_samples; - first_sample = first_sample % block_samples; - - /* header (hist+step) */ - if (first_sample == 0) { - off_t header_offset = stream->offset + 0x40*num_frame + 0x04*channel; - - hist1 = read_16bitLE(header_offset+0x00,stream->streamfile); - step_size = read_16bitLE(header_offset+0x02,stream->streamfile); - /* in most files 1st frame has step 0 but it seems ok and accounted for */ - //if (step_size < 0x7f) step_size = 0x7f; - //else if (step_size > 0x6000) step_size = 0x6000; - } - - /* decode nibbles (layout: varies) */ - for (i = first_sample; i < first_sample + samples_to_do; i++) { - off_t byte_offset = (channelspacing == 2) ? - (stream->offset + 0x40*num_frame + 0x04*channelspacing) + i : /* stereo: one nibble per channel */ - (stream->offset + 0x40*num_frame + 0x04*channelspacing) + i/2; /* mono: consecutive nibbles */ - int nibble_shift = (channelspacing == 2) ? - (!(channel&1) ? 0:4) : - (!(i&1) ? 0:4); /* even = low, odd = high */ - - yamaha_adpcmb_expand_nibble(stream, byte_offset, nibble_shift, &hist1, &step_size, &out_sample); - outbuf[sample_count] = out_sample; - sample_count += channelspacing; - } - - stream->adpcm_history1_32 = hist1; - stream->adpcm_step_index = step_size; -} - - -/* Yamaha ADPCM with unknown expand variation (noisy), step size is double of normal Yamaha? */ -void decode_nxap(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i, sample_count = 0, num_frame; - int32_t hist1 = stream->adpcm_history1_32; - int step_size = stream->adpcm_step_index; - - /* external interleave */ - int block_samples = (0x40 - 0x4) * 2; - num_frame = first_sample / block_samples; - first_sample = first_sample % block_samples; - - /* header (hist+step) */ - if (first_sample == 0) { - off_t header_offset = stream->offset + 0x40*num_frame; - - hist1 = read_16bitLE(header_offset+0x00,stream->streamfile); - step_size = read_16bitLE(header_offset+0x02,stream->streamfile); - if (step_size < 0x7f) step_size = 0x7f; - else if (step_size > 0x6000) step_size = 0x6000; - } - - /* decode nibbles (layout: all nibbles from one channel) */ - for (i = first_sample; i < first_sample + samples_to_do; i++) { - int code, delta, sample; - off_t byte_offset = (stream->offset + 0x40*num_frame + 0x04) + i/2; - int nibble_shift = (i&1?4:0); /* low nibble first? */ - - code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; - delta = (step_size * scale_delta[code]) / 8; //todo wrong - sample = hist1 + delta; - - outbuf[sample_count] = clamp16(sample); - hist1 = outbuf[sample_count]; - - step_size = (step_size * scale_step_aica[code]) / 260.0; //todo wrong - if (step_size < 0x7f) step_size = 0x7f; - else if (step_size > 0x6000) step_size = 0x6000; - - sample_count += channelspacing; - } - - stream->adpcm_history1_32 = hist1; - stream->adpcm_step_index = step_size; -} - -size_t yamaha_bytes_to_samples(size_t bytes, int channels) { - if (channels <= 0) return 0; - /* 2 samples per byte (2 nibbles) in stereo or mono config */ - return bytes * 2 / channels; -} - -size_t aska_bytes_to_samples(size_t bytes, int channels) { - int block_align = 0x40; - if (channels <= 0) return 0; - return (bytes / block_align) * (block_align - 0x04*channels) * 2 / channels - + ((bytes % block_align) ? ((bytes % block_align) - 0x04*channels) * 2 / channels : 0); -} +#include "../util.h" +#include "coding.h" + +/* fixed point amount to scale the current step size */ +static const unsigned int scale_step_aica[16] = { + 230, 230, 230, 230, 307, 409, 512, 614, + 230, 230, 230, 230, 307, 409, 512, 614 +}; + +static const int scale_step_adpcmb[16] = { + 57, 57, 57, 57, 77, 102, 128, 153, + 57, 57, 57, 57, 77, 102, 128, 153, +}; + +/* look-up for 'mul' IMA's sign*((code&7) * 2 + 1) for every code */ +static const int scale_delta[16] = { + 1, 3, 5, 7, 9, 11, 13, 15, + -1, -3, -5, -7, -9,-11,-13,-15 +}; + +/* Yamaha ADPCM-B (aka DELTA-T) expand used in YM2608/YM2610/etc (cross referenced with various sources and .so) */ +static void yamaha_adpcmb_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t* hist1, int32_t* step_size, int16_t *out_sample) { + int code, delta, sample; + + code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf; + delta = ((((code & 0x7) * 2) + 1) * (*step_size)) >> 3; /* like 'mul' IMA */ + if (code & 8) + delta = -delta; + sample = *hist1 + delta; + + sample = clamp16(sample); /* not needed in Aska but seems others do */ + + *step_size = ((*step_size) * scale_step_adpcmb[code]) >> 6; + if (*step_size < 0x7f) *step_size = 0x7f; + else if (*step_size > 0x6000) *step_size = 0x6000; + + *out_sample = sample; + *hist1 = sample; +} + +/* Yamaha AICA expand, slightly filtered vs "ACM" Yamaha ADPCM, same as Creative ADPCM + * (some info from https://github.com/vgmrips/vgmplay, https://wiki.multimedia.cx/index.php/Creative_ADPCM) */ +static void yamaha_aica_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t* hist1, int32_t* step_size, int16_t *out_sample) { + int code, delta, sample; + + *hist1 = *hist1 * 254 / 256; /* hist filter is vital to get correct waveform but not done in many emus */ + + code = ((read_8bit(byte_offset,stream->streamfile) >> nibble_shift))&0xf; + delta = (*step_size * scale_delta[code]) / 8; /* 'mul' IMA with table (not sure if part of encoder) */ + sample = *hist1 + delta; + + sample = clamp16(sample); /* apparently done by official encoder */ + + *step_size = ((*step_size) * scale_step_aica[code]) >> 8; + if (*step_size < 0x7f) *step_size = 0x7f; + else if (*step_size > 0x6000) *step_size = 0x6000; + + *out_sample = sample; + *hist1 = sample; +} + + +/* info about Yamaha ADPCM as created by official yadpcm.acm (in 'Yamaha-ADPCM-ACM-Driver-100-j') + * - possibly RIFF codec 0x20 + * - simply called "Yamaha ADPCM Codec" (even though not quite like Yamaha ADPCM-B) + * - block_align = (sample_rate / 0x3C + 0x04) * channels (ex. 0x2E6 for 22050 stereo, probably given in RIFF) + * - low nibble first, stereo or mono modes (no interleave) + * - expand (old IMA 'shift+add' style, not 'mul' style): + * delta = step_size >> 3; + * if (code & 1) delta += step_size >> 2; + * if (code & 2) delta += step_size >> 1; + * if (code & 4) delta += step_size; + * if (code & 8) delta = -delta; + * sample = hist + clamp16(delta); + * though compiled more like: + * sample = hist + (1-2*(code & 8) * (step_size/8 + step_size/2 * (code&2) + step_size/4 * (code&1) + step_size * (code&4)) + * - step_size update: + * step_size = clamp_range(step_size * scale_step_aica[code] >> 8, 0x7F, 0x6000) + */ + + +/* Yamaha AICA ADPCM (also used in YMZ280B with high nibble first) */ +void decode_aica(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo) { + int i, sample_count = 0; + int16_t out_sample; + int32_t hist1 = stream->adpcm_history1_16; + int step_size = stream->adpcm_step_index; + + /* no header (external setup), pre-clamp for wrong values */ + if (step_size < 0x7f) step_size = 0x7f; + if (step_size > 0x6000) step_size = 0x6000; + + for (i = first_sample; i < first_sample + samples_to_do; i++) { + off_t byte_offset = is_stereo ? + stream->offset + i : /* stereo: one nibble per channel */ + stream->offset + i/2; /* mono: consecutive nibbles */ + int nibble_shift = is_stereo ? + (!(channel&1) ? 0:4) : /* even = low/L, odd = high/R */ + (!(i&1) ? 0:4); /* low nibble first */ + + yamaha_aica_expand_nibble(stream, byte_offset, nibble_shift, &hist1, &step_size, &out_sample); + outbuf[sample_count] = out_sample; + sample_count += channelspacing; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_step_index = step_size; +} + +/* tri-Ace Aska ADPCM, Yamaha ADPCM-B with headered frames (reversed from Android SO's .so) + * implements table with if-else/switchs too but that's too goofy */ +void decode_aska(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + int i, sample_count = 0, num_frame; + int16_t out_sample; + int32_t hist1 = stream->adpcm_history1_32; + int step_size = stream->adpcm_step_index; + + /* external interleave */ + int block_samples = (0x40 - 0x04*channelspacing) * 2 / channelspacing; + num_frame = first_sample / block_samples; + first_sample = first_sample % block_samples; + + /* header (hist+step) */ + if (first_sample == 0) { + off_t header_offset = stream->offset + 0x40*num_frame + 0x04*channel; + + hist1 = read_16bitLE(header_offset+0x00,stream->streamfile); + step_size = read_16bitLE(header_offset+0x02,stream->streamfile); + /* in most files 1st frame has step 0 but it seems ok and accounted for */ + //if (step_size < 0x7f) step_size = 0x7f; + //else if (step_size > 0x6000) step_size = 0x6000; + } + + /* decode nibbles (layout: varies) */ + for (i = first_sample; i < first_sample + samples_to_do; i++) { + off_t byte_offset = (channelspacing == 2) ? + (stream->offset + 0x40*num_frame + 0x04*channelspacing) + i : /* stereo: one nibble per channel */ + (stream->offset + 0x40*num_frame + 0x04*channelspacing) + i/2; /* mono: consecutive nibbles */ + int nibble_shift = (channelspacing == 2) ? + (!(channel&1) ? 0:4) : + (!(i&1) ? 0:4); /* even = low, odd = high */ + + yamaha_adpcmb_expand_nibble(stream, byte_offset, nibble_shift, &hist1, &step_size, &out_sample); + outbuf[sample_count] = out_sample; + sample_count += channelspacing; + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_step_index = step_size; +} + + +/* NXAP ADPCM, Yamaha ADPCM-B with weird headered frames */ +void decode_nxap(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i, sample_count = 0, num_frame; + int32_t hist1 = stream->adpcm_history1_32; + int step_size = stream->adpcm_step_index; + int16_t out_sample; + + /* external interleave, mono */ + int block_samples = (0x40 - 0x4) * 2; + num_frame = first_sample / block_samples; + first_sample = first_sample % block_samples; + + /* header (hist+step) */ + if (first_sample == 0) { + off_t header_offset = stream->offset + 0x40*num_frame; + + hist1 = read_s16le(header_offset+0x00,stream->streamfile); + step_size = read_u16le(header_offset+0x02,stream->streamfile) >> 1; /* remove lower bit, also note unsignedness */ + if (step_size < 0x7f) step_size = 0x7f; + else if (step_size > 0x6000) step_size = 0x6000; + /* step's lower bit is hist1 sign (useless), and code doesn't seem to do anything useful with it? */ + } + + /* decode nibbles (layout: all nibbles from one channel) */ + for (i = first_sample; i < first_sample + samples_to_do; i++) { + off_t byte_offset = (stream->offset + 0x40*num_frame + 0x04) + i/2; + int nibble_shift = (i&1?0:4); + + yamaha_adpcmb_expand_nibble(stream, byte_offset, nibble_shift, &hist1, &step_size, &out_sample); + outbuf[sample_count] = out_sample; + sample_count += channelspacing; + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_step_index = step_size; +} + +size_t yamaha_bytes_to_samples(size_t bytes, int channels) { + if (channels <= 0) return 0; + /* 2 samples per byte (2 nibbles) in stereo or mono config */ + return bytes * 2 / channels; +} + +size_t aska_bytes_to_samples(size_t bytes, int channels) { + int block_align = 0x40; + if (channels <= 0) return 0; + return (bytes / block_align) * (block_align - 0x04*channels) * 2 / channels + + ((bytes % block_align) ? ((bytes % block_align) - 0x04*channels) * 2 / channels : 0); +} diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index e8020a640..543c066d0 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -25,6 +25,7 @@ static const char* extension_list[] = { "208", "2dx9", "2pfs", + "4", // for Game.com audio "8", //txth/reserved [Gungage (PS1)] "800", "9tav", @@ -164,6 +165,7 @@ static const char* extension_list[] = { "ezw", "fag", + "fda", "ffw", "filp", //"flac", //common @@ -171,6 +173,7 @@ static const char* extension_list[] = { "fsb", "fsv", "fwav", + "fwse", "g1l", "gbts", @@ -268,6 +271,7 @@ static const char* extension_list[] = { "lpcm", "lpk", "lps", + "lrmb", "lse", "lsf", "lstm", //fake extension for .stm @@ -389,6 +393,7 @@ static const char* extension_list[] = { "rxx", //txth/reserved [Full Auto (X360)] "s14", + "s3v", //txth/reserved [Sound Voltex 5 (AC)] "sab", "sad", "sap", @@ -418,6 +423,7 @@ static const char* extension_list[] = { "sdf", "sdt", "seb", + "sed", "seg", "sf0", "sfl", @@ -530,6 +536,8 @@ static const char* extension_list[] = { "wavm", "wavx", //txth/reserved [LEGO Star Wars (Xbox)] "wb", + "wb2", + "wbd", "wd", "wem", "wii", @@ -691,6 +699,7 @@ static const coding_info coding_info_list[] = { {coding_ALP_IMA, "High Voltage ALP 4-bit IMA ADPCM"}, {coding_FFTA2_IMA, "Final Fantasy Tactics A2 4-bit IMA ADPCM"}, {coding_BLITZ_IMA, "Blitz Games 4-bit IMA ADPCM"}, + {coding_MTF_IMA, "MT Framework 4-bit IMA ADPCM"}, {coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"}, {coding_XBOX_IMA, "XBOX 4-bit IMA ADPCM"}, @@ -717,6 +726,7 @@ static const coding_info coding_info_list[] = { {coding_AICA_int, "Yamaha AICA 4-bit ADPCM (mono/interleave)"}, {coding_ASKA, "tri-Ace Aska 4-bit ADPCM"}, {coding_NXAP, "Nex NXAP 4-bit ADPCM"}, + {coding_TGC, "Tiger Game.com 4-bit ADPCM"}, {coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"}, {coding_L5_555, "Level-5 0x555 4-bit ADPCM"}, {coding_LSF, "lsf 4-bit ADPCM"}, @@ -745,6 +755,7 @@ static const coding_info coding_info_list[] = { {coding_EA_MT, "Electronic Arts MicroTalk"}, + {coding_RELIC, "Relic Codec"}, {coding_CRI_HCA, "CRI HCA"}, #ifdef VGM_USE_VORBIS @@ -1120,7 +1131,7 @@ static const meta_info meta_info_list[] = { {meta_FFMPEG, "FFmpeg supported file format"}, {meta_X360_CXS, "tri-Crescendo CXS header"}, {meta_AKB, "Square-Enix AKB header"}, - {meta_X360_PASX, "Namco PASX header"}, + {meta_X360_PASX, "Premium Agency PASX header"}, {meta_XMA_RIFF, "Microsoft XMA RIFF header"}, {meta_X360_AST, "Capcom AST (X360) header"}, {meta_WWISE_RIFF, "Audiokinetic Wwise RIFF header"}, @@ -1224,7 +1235,7 @@ static const meta_info meta_info_list[] = { {meta_XPCM, "Circus XPCM header"}, {meta_MSF_TAMASOFT, "Tama-Soft MSF header"}, {meta_XPS_DAT, "From Software .XPS+DAT header"}, - {meta_ZSND, "Vicarious Visions ZSND header"}, + {meta_ZSND, "Z-Axis ZSND header"}, {meta_DSP_ADPY, "AQUASTYLE ADPY header"}, {meta_DSP_ADPX, "AQUASTYLE ADPX header"}, {meta_OGG_OPUS, "Ogg Opus header"}, @@ -1252,6 +1263,11 @@ static const meta_info meta_info_list[] = { {meta_ISB, "Creative ISACT header"}, {meta_XSSB, "Artoon XSSB header"}, {meta_XMA_UE3, "Unreal Engine XMA header"}, + {meta_FWSE, "MT Framework FWSE header"}, + {meta_FDA, "Relic FDA header"}, + {meta_TGC, "Tiger Game.com .4 header"}, + {meta_KWB, "Koei Tecmo WaveBank header"}, + {meta_LRMD, "Sony LRMD header"}, }; diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_swvr.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_swvr.c index 1fd324cbd..36f6faea0 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_swvr.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_swvr.c @@ -66,17 +66,30 @@ void block_update_ea_swvr(off_t block_offset, VGMSTREAM * vgmstream) { header_size = 0x1c; channel_size = (block_size - header_size) / vgmstream->channels; break; + case 0x53484F43: /* "SHOC" (a generic block but hopefully has PC sounds) */ - header_size = 0x14; //todo the first block is 0x18 - channel_size = (block_size - header_size) / vgmstream->channels; + if (read_32bit(block_offset+0x10, streamFile) == 0x53444154) { /* "SDAT" */ + header_size = 0x14; + channel_size = (block_size - header_size) / vgmstream->channels; + } + else { + header_size = 0; + channel_size = 0; + } break; - case 0x46494C4C: /* "FILL" (FILLs do that up to 0x6000, but at 0x5FFC don't actually have size) */ + case 0x46494C4C: /* "FILL" (FILLs do that up to a block size, but near end don't actually have size) */ if ((block_offset + 0x04) % 0x6000 == 0) block_size = 0x04; + else if ((block_offset + 0x04) % 0x10000 == 0) + block_size = 0x04; + else if (block_size > 0x100000) { /* other unknown block sizes */ + VGM_LOG("EA SWVR: bad block size at 0x%lx\n", block_offset); + block_size = 0x04; + } header_size = 0x08; break; - + case 0xFFFFFFFF: channel_size = -1; /* signal bad block */ break; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aax.c b/Frameworks/vgmstream/vgmstream/src/meta/aax.c index 542899f5c..329598894 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/aax.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/aax.c @@ -52,9 +52,9 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { /* get offsets of constituent segments */ for (i = 0; i < segment_count; i++) { uint32_t offset, size; - int8_t segment_loop_flag = 0; + uint8_t segment_loop_flag = 0; - if (!utf_query_s8(utf, i, "lpflg", &segment_loop_flag)) /* usually in last segment */ + if (!utf_query_u8(utf, i, "lpflg", &segment_loop_flag)) /* usually in last segment */ goto fail; if (!utf_query_data(utf, i, "data", &offset, &size)) goto fail; @@ -138,8 +138,8 @@ fail: VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; - int8_t loop_flag = 0, channel_count; - int sample_rate, num_samples, loop_start, loop_end, interleave; + uint8_t loop_flag = 0, channel_count; + uint32_t sample_rate, num_samples, loop_start, loop_end, interleave; uint32_t data_offset, data_size, header_offset, header_size; utf_context *utf = NULL; @@ -168,13 +168,13 @@ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) { if (rows != 1) goto fail; - if (!utf_query_s32(utf, 0, "sfreq", &sample_rate)) + if (!utf_query_u32(utf, 0, "sfreq", &sample_rate)) goto fail; - if (!utf_query_s32(utf, 0, "nsmpl", &num_samples)) + if (!utf_query_u32(utf, 0, "nsmpl", &num_samples)) goto fail; - if (!utf_query_s8(utf, 0, "nch", &channel_count)) + if (!utf_query_u8(utf, 0, "nch", &channel_count)) goto fail; - if (!utf_query_s8(utf, 0, "lpflg", &loop_flag)) /* full loops */ + if (!utf_query_u8(utf, 0, "lpflg", &loop_flag)) /* full loops */ goto fail; /* for some reason data is stored before header */ if (!utf_query_data(utf, 0, "data", &data_offset, &data_size)) @@ -196,7 +196,7 @@ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) { /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channel_count, loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = sample_rate; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/acb.c b/Frameworks/vgmstream/vgmstream/src/meta/acb.c index 27693b245..18b365d9d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/acb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/acb.c @@ -183,22 +183,22 @@ static void add_acb_name(acb_header* acb, int8_t Waveform_Streaming) { static int load_acb_waveform(acb_header* acb, int16_t Index) { - int16_t Waveform_Id; - int8_t Waveform_Streaming; + uint16_t Waveform_Id; + uint8_t Waveform_Streaming; /* read Waveform[Index] */ if (!open_utf_subtable(acb, &acb->WaveformSf, &acb->WaveformTable, "WaveformTable", NULL)) goto fail; - if (!utf_query_s16(acb->WaveformTable, Index, "Id", &Waveform_Id)) { /* older versions use Id */ + if (!utf_query_u16(acb->WaveformTable, Index, "Id", &Waveform_Id)) { /* older versions use Id */ if (acb->is_memory) { - if (!utf_query_s16(acb->WaveformTable, Index, "MemoryAwbId", &Waveform_Id)) + if (!utf_query_u16(acb->WaveformTable, Index, "MemoryAwbId", &Waveform_Id)) goto fail; } else { - if (!utf_query_s16(acb->WaveformTable, Index, "StreamAwbId", &Waveform_Id)) + if (!utf_query_u16(acb->WaveformTable, Index, "StreamAwbId", &Waveform_Id)) goto fail; } } - if (!utf_query_s8(acb->WaveformTable, Index, "Streaming", &Waveform_Streaming)) + if (!utf_query_u8(acb->WaveformTable, Index, "Streaming", &Waveform_Streaming)) goto fail; //;VGM_LOG("ACB: Waveform[%i]: Id=%i, Streaming=%i\n", Index, Waveform_Id, Waveform_Streaming); @@ -222,7 +222,7 @@ static int load_acb_sequence(acb_header* acb, int16_t Index); static int load_acb_synth(acb_header* acb, int16_t Index) { int i, count; - int8_t Synth_Type; + uint8_t Synth_Type; uint32_t Synth_ReferenceItems_offset; uint32_t Synth_ReferenceItems_size; @@ -230,7 +230,7 @@ static int load_acb_synth(acb_header* acb, int16_t Index) { /* read Synth[Index] */ if (!open_utf_subtable(acb, &acb->SynthSf, &acb->SynthTable, "SynthTable", NULL)) goto fail; - if (!utf_query_s8(acb->SynthTable, Index, "Type", &Synth_Type)) + if (!utf_query_u8(acb->SynthTable, Index, "Type", &Synth_Type)) goto fail; if (!utf_query_data(acb->SynthTable, Index, "ReferenceItems", &Synth_ReferenceItems_offset, &Synth_ReferenceItems_size)) goto fail; @@ -249,7 +249,7 @@ static int load_acb_synth(acb_header* acb, int16_t Index) { * - 1: sequential (1 to N?) * - 2: shuffle (1 from N?) * - 3: random (1 from N?) - * - 4: no repeat + * - 4: random no repeat * - 5: switch game variable * - 6: combo sequential * - 7: switch selector @@ -300,7 +300,7 @@ fail: } static int load_acb_track_event_command(acb_header* acb, int16_t Index) { - int16_t Track_EventIndex; + uint16_t Track_EventIndex; uint32_t Track_Command_offset; uint32_t Track_Command_size; @@ -308,7 +308,7 @@ static int load_acb_track_event_command(acb_header* acb, int16_t Index) { /* read Track[Index] */ if (!open_utf_subtable(acb, &acb->TrackSf, &acb->TrackTable, "TrackTable", NULL)) goto fail; - if (!utf_query_s16(acb->TrackTable, Index, "EventIndex", &Track_EventIndex)) + if (!utf_query_u16(acb->TrackTable, Index, "EventIndex", &Track_EventIndex)) goto fail; //;VGM_LOG("ACB: Track[%i]: EventIndex=%i\n", Index, Track_EventIndex); @@ -370,6 +370,15 @@ static int load_acb_track_event_command(acb_header* acb, int16_t Index) { goto fail; break; + /* possible values? (from debug): + * - sequence + * - track + * - synth + * - trackEvent + * - seqParameterPallet, + * - trackParameterPallet, + * - synthParameterPallet, + */ default: VGM_LOG("ACB: unknown TLV type %x at %x + %x\n", tlv_type, offset, tlv_size); max_offset = 0; /* force end without failing */ @@ -390,7 +399,7 @@ fail: static int load_acb_sequence(acb_header* acb, int16_t Index) { int i; - int16_t Sequence_NumTracks; + uint16_t Sequence_NumTracks; uint32_t Sequence_TrackIndex_offset; uint32_t Sequence_TrackIndex_size; @@ -398,7 +407,7 @@ static int load_acb_sequence(acb_header* acb, int16_t Index) { /* read Sequence[Index] */ if (!open_utf_subtable(acb, &acb->SequenceSf, &acb->SequenceTable, "SequenceTable", NULL)) goto fail; - if (!utf_query_s16(acb->SequenceTable, Index, "NumTracks", &Sequence_NumTracks)) + if (!utf_query_u16(acb->SequenceTable, Index, "NumTracks", &Sequence_NumTracks)) goto fail; if (!utf_query_data(acb->SequenceTable, Index, "TrackIndex", &Sequence_TrackIndex_offset, &Sequence_TrackIndex_size)) goto fail; @@ -433,7 +442,7 @@ fail: static int load_acb_block(acb_header* acb, int16_t Index) { int i; - int16_t Block_NumTracks; + uint16_t Block_NumTracks; uint32_t Block_TrackIndex_offset; uint32_t Block_TrackIndex_size; @@ -441,7 +450,7 @@ static int load_acb_block(acb_header* acb, int16_t Index) { /* read Block[Index] */ if (!open_utf_subtable(acb, &acb->BlockSf, &acb->BlockTable, "BlockTable", NULL)) goto fail; - if (!utf_query_s16(acb->BlockTable, Index, "NumTracks", &Block_NumTracks)) + if (!utf_query_u16(acb->BlockTable, Index, "NumTracks", &Block_NumTracks)) goto fail; if (!utf_query_data(acb->BlockTable, Index, "TrackIndex", &Block_TrackIndex_offset, &Block_TrackIndex_size)) goto fail; @@ -467,16 +476,16 @@ fail: } static int load_acb_cue(acb_header* acb, int16_t Index) { - int8_t Cue_ReferenceType; - int16_t Cue_ReferenceIndex; + uint8_t Cue_ReferenceType; + uint16_t Cue_ReferenceIndex; /* read Cue[Index] */ if (!open_utf_subtable(acb, &acb->CueSf, &acb->CueTable, "CueTable", NULL)) goto fail; - if (!utf_query_s8 (acb->CueTable, Index, "ReferenceType", &Cue_ReferenceType)) + if (!utf_query_u8(acb->CueTable, Index, "ReferenceType", &Cue_ReferenceType)) goto fail; - if (!utf_query_s16(acb->CueTable, Index, "ReferenceIndex", &Cue_ReferenceIndex)) + if (!utf_query_u16(acb->CueTable, Index, "ReferenceIndex", &Cue_ReferenceIndex)) goto fail; //;VGM_LOG("ACB: Cue[%i]: ReferenceType=%i, ReferenceIndex=%i\n", Index, Cue_ReferenceType, Cue_ReferenceIndex); @@ -484,28 +493,35 @@ static int load_acb_cue(acb_header* acb, int16_t Index) { /* usually older games use older references but not necessarily */ switch(Cue_ReferenceType) { - case 1: /* Cue > Waveform (ex. PES 2015) */ + case 0x01: /* Cue > Waveform (ex. PES 2015) */ if (!load_acb_waveform(acb, Cue_ReferenceIndex)) goto fail; break; - case 2: /* Cue > Synth > Waveform (ex. Ukiyo no Roushi) */ + case 0x02: /* Cue > Synth > Waveform (ex. Ukiyo no Roushi) */ if (!load_acb_synth(acb, Cue_ReferenceIndex)) goto fail; break; - case 3: /* Cue > Sequence > Track > Command > Synth > Waveform (ex. Valkyrie Profile anatomia, Yakuza Kiwami 2) */ + case 0x03: /* Cue > Sequence > Track > Command > Synth > Waveform (ex. Valkyrie Profile anatomia, Yakuza Kiwami 2) */ if (!load_acb_sequence(acb, Cue_ReferenceIndex)) goto fail; break; - case 8: /* Cue > Block > Track > Command > Synth > Waveform (ex. Sonic Lost World, rare) */ + //todo "blockSequence"? + case 0x08: /* Cue > Block > Track > Command > Synth > Waveform (ex. Sonic Lost World, rare) */ if (!load_acb_block(acb, Cue_ReferenceIndex)) goto fail; break; - case 6: /* Cue > (Waveform/Synth/Command)? (ex. PES 2014) */ - case 7: /* Cue > (Waveform/Synth/Command)? (ex. PES 2014) */ + case 0x00: /* none */ + case 0x04: /* "track" */ + case 0x05: /* "outsideLink" */ + case 0x06: /* "insideLinkSynth" (ex. PES 2014) */ + case 0x07: /* "insideLinkSequence" (ex. PES 2014) */ + case 0x09: /* "insideLinkBlockSequence" */ + case 0x0a: /* "eventCue_UnUse" */ + case 0x0b: /* "soundGenerator" */ default: VGM_LOG("ACB: unknown Cue.ReferenceType=%x, Cue.ReferenceIndex=%x\n", Cue_ReferenceType, Cue_ReferenceIndex); break; /* ignore and continue */ @@ -519,14 +535,14 @@ fail: } static int load_acb_cuename(acb_header* acb, int16_t Index) { - int16_t CueName_CueIndex; + uint16_t CueName_CueIndex; const char* CueName_CueName; /* read CueName[Index] */ if (!open_utf_subtable(acb, &acb->CueNameSf, &acb->CueNameTable, "CueNameTable", NULL)) goto fail; - if (!utf_query_s16(acb->CueNameTable, Index, "CueIndex", &CueName_CueIndex)) + if (!utf_query_u16(acb->CueNameTable, Index, "CueIndex", &CueName_CueIndex)) goto fail; if (!utf_query_string(acb->CueNameTable, Index, "CueName", &CueName_CueName)) goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/acb_utf.h b/Frameworks/vgmstream/vgmstream/src/meta/acb_utf.h deleted file mode 100644 index 8c7c27d55..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/acb_utf.h +++ /dev/null @@ -1,376 +0,0 @@ -#include "cri_utf.h" - -/* possibly 3b+5b from clUTF decompilation */ -#define COLUMN_BITMASK_STORAGE 0xf0 -#define COLUMN_BITMASK_TYPE 0x0f - -enum column_storage_t { - COLUMN_STORAGE_ZERO = 0x10, - COLUMN_STORAGE_CONSTANT = 0x30, - COLUMN_STORAGE_ROW = 0x50 - //COLUMN_STORAGE_CONSTANT2 = 0x70 /* from vgmtoolbox */ -}; - -enum column_type_t { - COLUMN_TYPE_SINT8 = 0x00, - COLUMN_TYPE_UINT8 = 0x01, - COLUMN_TYPE_SINT16 = 0x02, - COLUMN_TYPE_UINT16 = 0x03, - COLUMN_TYPE_SINT32 = 0x04, - COLUMN_TYPE_UINT32 = 0x05, - COLUMN_TYPE_SINT64 = 0x06, - //COLUMN_TYPE_UINT64 = 0x07, - COLUMN_TYPE_FLOAT = 0x08, - //COLUMN_TYPE_DOUBLE = 0x09, - COLUMN_TYPE_STRING = 0x0a, - COLUMN_TYPE_DATA = 0x0b -}; - -typedef struct { - int found; - enum column_type_t type; - union { - int8_t value_s8; - uint8_t value_u8; - int16_t value_s16; - uint16_t value_u16; - int32_t value_s32; - uint32_t value_u32; - int64_t value_s64; - uint64_t value_u64; - float value_float; - double value_double; - struct utf_data_t { - uint32_t offset; - uint32_t size; - } value_data; - const char *value_string; - } value; -} utf_result_t; - -struct utf_context { - STREAMFILE *sf; - uint32_t table_offset; - - /* header */ - uint32_t table_size; - uint16_t version; - uint16_t rows_offset; - uint32_t strings_offset; - uint32_t data_offset; - uint32_t name_offset; - uint16_t columns; - uint16_t row_width; - uint32_t rows; - struct utf_column_t { - uint8_t flags; - const char *name; - uint32_t offset; - } *schema; - - /* derived */ - uint32_t schema_offset; - uint32_t strings_size; - char *string_table; - const char *table_name; -}; - - -/* @UTF table context creation */ -utf_context* utf_open(STREAMFILE *sf, uint32_t table_offset, int *p_rows, const char **p_row_name) { - utf_context* utf = NULL; - - - utf = calloc(1, sizeof(utf_context)); - if (!utf) goto fail; - - utf->sf = sf; - utf->table_offset = table_offset; - - /* check header */ - if (read_u32be(table_offset + 0x00, sf) != 0x40555446) /* "@UTF" */ - goto fail; - - /* load table header */ - utf->table_size = read_u32be(table_offset + 0x04, sf) + 0x08; - utf->version = read_u16be(table_offset + 0x08, sf); - utf->rows_offset = read_u16be(table_offset + 0x0a, sf) + 0x08; - utf->strings_offset = read_u32be(table_offset + 0x0c, sf) + 0x08; - utf->data_offset = read_u32be(table_offset + 0x10, sf) + 0x08; - utf->name_offset = read_u32be(table_offset + 0x14, sf); /* within string table */ - utf->columns = read_u16be(table_offset + 0x18, sf); - utf->row_width = read_u16be(table_offset + 0x1a, sf); - utf->rows = read_u32be(table_offset + 0x1c, sf); - - utf->schema_offset = 0x20; - utf->strings_size = utf->data_offset - utf->strings_offset; - - /* 00: early (32b rows_offset?), 01: +2017 (no apparent differences) */ - if (utf->version != 0x00 && utf->version != 0x01) { - VGM_LOG("@UTF: unknown version\n"); - } - if (utf->table_offset + utf->table_size > get_streamfile_size(sf)) - goto fail; - if (utf->rows_offset > utf->table_size || utf->strings_offset > utf->table_size || utf->data_offset > utf->table_size) - goto fail; - if (utf->strings_size <= 0 || utf->name_offset > utf->strings_size) - goto fail; - /* no rows is possible for empty tables (have schema and columns names but no data) [PES 2013 (PC)] */ - if (utf->columns <= 0 /*|| utf->rows <= 0 || utf->rows_width <= 0*/) - goto fail; - - - /* load string table */ - { - size_t read; - - utf->string_table = calloc(utf->strings_size + 1, sizeof(char)); - if (!utf->string_table) goto fail; - - utf->table_name = utf->string_table + utf->name_offset; - - read = read_streamfile((unsigned char*)utf->string_table, utf->table_offset + utf->strings_offset, utf->strings_size, sf); - if (utf->strings_size != read) goto fail; - } - - - /* load column schema */ - { - int i; - uint32_t value_size, column_offset = 0; - uint32_t schema_offset = utf->table_offset + utf->schema_offset; - - - utf->schema = malloc(sizeof(struct utf_column_t) * utf->columns); - if (!utf->schema) goto fail; - - for (i = 0; i < utf->columns; i++) { - uint8_t flags = read_u8(schema_offset + 0x00, sf); - uint32_t name_offset = read_u32be(schema_offset + 0x01, sf); - if (name_offset > utf->strings_size) - goto fail; - - utf->schema[i].flags = flags; - utf->schema[i].name = utf->string_table + name_offset; - schema_offset += 0x01 + 0x04; - - switch (utf->schema[i].flags & COLUMN_BITMASK_TYPE) { - case COLUMN_TYPE_SINT8: - case COLUMN_TYPE_UINT8: - value_size = 0x01; - break; - case COLUMN_TYPE_SINT16: - case COLUMN_TYPE_UINT16: - value_size = 0x02; - break; - case COLUMN_TYPE_SINT32: - case COLUMN_TYPE_UINT32: - case COLUMN_TYPE_FLOAT: - case COLUMN_TYPE_STRING: - value_size = 0x04; - break; - case COLUMN_TYPE_SINT64: - //case COLUMN_TYPE_UINT64: - //case COLUMN_TYPE_DOUBLE: - case COLUMN_TYPE_DATA: - value_size = 0x08; - break; - default: - VGM_LOG("@UTF: unknown column type\n"); - goto fail; - } - - switch (utf->schema[i].flags & COLUMN_BITMASK_STORAGE) { - case COLUMN_STORAGE_ROW: - utf->schema[i].offset = column_offset; - column_offset += value_size; - break; - case COLUMN_STORAGE_CONSTANT: - //case COLUMN_STORAGE_CONSTANT2: - utf->schema[i].offset = schema_offset - (utf->table_offset + utf->schema_offset); /* relative to schema */ - schema_offset += value_size; - break; - case COLUMN_STORAGE_ZERO: - utf->schema[i].offset = 0; /* ? */ - break; - default: - VGM_LOG("@UTF: unknown column storage\n"); - goto fail; - } - } - } - - - /* write info */ - if (p_rows) *p_rows = utf->rows; - if (p_row_name) *p_row_name = utf->string_table + utf->name_offset; - - return utf; -fail: - utf_close(utf); - VGM_LOG("@UTF: fail\n"); - return NULL; -} - -void utf_close(utf_context *utf) { - if (!utf) return; - - free(utf->string_table); - free(utf->schema); - free(utf); -} - - -static int utf_query(utf_context *utf, int row, const char *column, utf_result_t *result) { - int i; - - - result->found = 0; - - if (row >= utf->rows || row < 0) - goto fail; - - /* find target column */ - for (i = 0; i < utf->columns; i++) { - struct utf_column_t *col = &utf->schema[i]; - uint32_t data_offset; - - if (strcmp(col->name, column) != 0) - continue; - - result->found = 1; - result->type = col->flags & COLUMN_BITMASK_TYPE; - - switch (col->flags & COLUMN_BITMASK_STORAGE) { - case COLUMN_STORAGE_ROW: - data_offset = utf->table_offset + utf->rows_offset + row * utf->row_width + col->offset; - break; - case COLUMN_STORAGE_CONSTANT: - //case COLUMN_STORAGE_CONSTANT2: - data_offset = utf->table_offset + utf->schema_offset + col->offset; - break; - case COLUMN_STORAGE_ZERO: - data_offset = 0; - memset(&result->value, 0, sizeof(result->value)); - break; - default: - goto fail; - } - - /* ignore zero value */ - if (!data_offset) - break; - - /* read row/constant value */ - switch (col->flags & COLUMN_BITMASK_TYPE) { - case COLUMN_TYPE_SINT8: - result->value.value_s8 = read_s8(data_offset, utf->sf); - break; - case COLUMN_TYPE_UINT8: - result->value.value_u8 = read_u8(data_offset, utf->sf); - break; - case COLUMN_TYPE_SINT16: - result->value.value_s16 = read_s16be(data_offset, utf->sf); - break; - case COLUMN_TYPE_UINT16: - result->value.value_u16 = read_u16be(data_offset, utf->sf); - break; - case COLUMN_TYPE_SINT32: - result->value.value_s32 = read_s32be(data_offset, utf->sf); - break; - case COLUMN_TYPE_UINT32: - result->value.value_u32 = read_u32be(data_offset, utf->sf); - break; - case COLUMN_TYPE_SINT64: - result->value.value_s64 = read_s64be(data_offset, utf->sf); - break; -#if 0 - case COLUMN_TYPE_UINT64: - result->value.value_u64 = read_u64be(data_offset, utf->sf); - break; -#endif - case COLUMN_TYPE_FLOAT: { - result->value.value_float = read_f32be(data_offset, utf->sf); - break; - } -#if 0 - case COLUMN_TYPE_DOUBLE: { - result->value.value_double = read_d64be(data_offset, utf->sf); - break; - } -#endif - case COLUMN_TYPE_STRING: { - uint32_t name_offset = read_u32be(data_offset, utf->sf); - if (name_offset > utf->strings_size) - goto fail; - result->value.value_string = utf->string_table + name_offset; - break; - } - - case COLUMN_TYPE_DATA: - result->value.value_data.offset = read_u32be(data_offset + 0x00, utf->sf); - result->value.value_data.size = read_u32be(data_offset + 0x04, utf->sf); - break; - - default: - goto fail; - } - - break; /* column found and read */ - } - - return 1; -fail: - return 0; -} - -static int utf_query_value(utf_context *utf, int row, const char *column, void *value, enum column_type_t type) { - utf_result_t result = {0}; - int valid; - - valid = utf_query(utf, row, column, &result); - if (!valid || !result.found || result.type != type) - return 0; - - switch(result.type) { - case COLUMN_TYPE_SINT8: (*(int8_t*)value) = result.value.value_s8; break; - case COLUMN_TYPE_UINT8: (*(uint8_t*)value) = result.value.value_u8; break; - case COLUMN_TYPE_SINT16: (*(int16_t*)value) = result.value.value_s16; break; - case COLUMN_TYPE_UINT16: (*(uint16_t*)value) = result.value.value_u16; break; - case COLUMN_TYPE_SINT32: (*(int32_t*)value) = result.value.value_s32; break; - case COLUMN_TYPE_UINT32: (*(uint32_t*)value) = result.value.value_u32; break; - case COLUMN_TYPE_SINT64: (*(int64_t*)value) = result.value.value_s64; break; - //case COLUMN_TYPE_UINT64: (*(uint64_t*)value) = result.value.value_u64; break; - case COLUMN_TYPE_STRING: (*(const char**)value) = result.value.value_string; break; - default: - return 0; - } - - return 1; -} - -int utf_query_s8(utf_context *utf, int row, const char *column, int8_t *value) { - return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_SINT8); -} -int utf_query_s16(utf_context *utf, int row, const char *column, int16_t *value) { - return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_SINT16); -} -int utf_query_s32(utf_context *utf, int row, const char *column, int32_t *value) { - return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_SINT32); -} -int utf_query_string(utf_context *utf, int row, const char *column, const char **value) { - return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_STRING); -} - -int utf_query_data(utf_context *utf, int row, const char *column, uint32_t *p_offset, uint32_t *p_size) { - utf_result_t result = {0}; - int valid; - - valid = utf_query(utf, row, column, &result); - if (!valid || !result.found || result.type != COLUMN_TYPE_DATA) - return 0; - - if (p_offset) *p_offset = utf->table_offset + utf->data_offset + result.value.value_data.offset; - if (p_size) *p_size = result.value.value_data.size; - return 1; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/adx_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/adx_keys.h index c3844ae6c..027f0b068 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/adx_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/adx_keys.h @@ -187,6 +187,12 @@ static const adxkey_info adxkey8_list[] = { /* Lucky Star: RAvish Romance (PS2) [Vridge] */ {0x5347,0x4FB7,0x6415, "LUCKYSRARPS2",0}, + /* Katekyoo Hitman Reborn! Nerae! Ring x Bongole Trainers (PS2) */ + {0x61C7,0x4549,0x4337, "ORN2HITMAN",0}, + + /* Katekyoo Hitman Reborn! Let's Ansatsu! Nerawareta 10-daime! (PS2) */ + {0x5381,0x52E5,0x53E9, "REBHITMAN",0}, + }; static const adxkey_info adxkey9_list[] = { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aifc.c b/Frameworks/vgmstream/vgmstream/src/meta/aifc.c index d9b2a46a0..58546894c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/aifc.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/aifc.c @@ -1,15 +1,17 @@ #include "meta.h" #include "../layout/layout.h" +#include "../coding/coding.h" /* for reading integers inexplicably packed into 80-bit ('double extended') floats */ static uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) { - uint8_t buf[10]; + uint8_t buf[0x0a]; int32_t exponent; int32_t mantissa; int i; - if (read_streamfile(buf,offset,10,streamFile) != 10) return 0; + if (read_streamfile(buf,offset,0x0a,streamFile) != 0x0a) + return 0; exponent = ((buf[0]<<8)|(buf[1]))&0x7fff; exponent -= 16383; @@ -26,13 +28,13 @@ static uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) { return mantissa*((buf[0]&0x80)?-1:1); } -static uint32_t find_marker(STREAMFILE *streamFile, off_t MarkerChunkOffset, int marker_id) { +static uint32_t find_marker(STREAMFILE *streamFile, off_t mark_offset, int marker_id) { uint16_t marker_count; int i; off_t marker_offset; - marker_count = read_16bitBE(MarkerChunkOffset+8,streamFile); - marker_offset = MarkerChunkOffset+10; + marker_count = read_16bitBE(mark_offset+8,streamFile); + marker_offset = mark_offset+10; for (i=0;i= sizeof(comp_name) - 1) goto fail; + + read_streamfile(comp_name, current_chunk + 0x1f, comp_size, streamFile); + if (memcmp(comp_name, "Relic Codec v1.6", comp_size) == 0) { /* Homeworld 2 (PC) */ + coding_type = coding_RELIC; + sample_count = sample_count * 512; + } + else { + goto fail; + } + break; + } + default: VGM_LOG("AIFC: unknown codec\n"); goto fail; @@ -192,25 +216,25 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) { case 0x53534E44: /* "SSND" (main data) */ case 0x4150434D: /* "APCM" (main data for XA) */ - if (SoundDataChunkFound) goto fail; - SoundDataChunkFound = 1; + if (data_found) goto fail; + data_found = 1; start_offset = current_chunk + 0x10 + read_32bitBE(current_chunk+0x08,streamFile); /* when "APCM" XA frame size is at 0x0c, fixed to 0x914 */ break; case 0x4D41524B: /* "MARK" (loops) */ - if (MarkerChunkFound) goto fail; - MarkerChunkFound = 1; + if (mark_found) goto fail; + mark_found = 1; - MarkerChunkOffset = current_chunk; + mark_offset = current_chunk; break; case 0x494E5354: /* "INST" (loops) */ - if (InstrumentChunkFound) goto fail; - InstrumentChunkFound = 1; + if (inst_found) goto fail; + inst_found = 1; - InstrumentChunkOffset = current_chunk; + inst_offset = current_chunk; break; default: @@ -223,28 +247,28 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) { } if (is_aifc) { - if (!FormatVersionChunkFound || !CommonChunkFound || !SoundDataChunkFound) + if (!fver_found || !comm_found || !data_found) goto fail; } else if (is_aiff) { - if (!CommonChunkFound || !SoundDataChunkFound) + if (!comm_found || !data_found) goto fail; } /* read loop points */ - if (InstrumentChunkFound && MarkerChunkFound) { + if (inst_found && mark_found) { int start_marker; int end_marker; /* use the sustain loop */ /* if playMode=ForwardLooping */ - if (read_16bitBE(InstrumentChunkOffset+16,streamFile) == 1) { - start_marker = read_16bitBE(InstrumentChunkOffset+18,streamFile); - end_marker = read_16bitBE(InstrumentChunkOffset+20,streamFile); + if (read_16bitBE(inst_offset+16,streamFile) == 1) { + start_marker = read_16bitBE(inst_offset+18,streamFile); + end_marker = read_16bitBE(inst_offset+20,streamFile); /* check for sustain markers != 0 (invalid marker no) */ if (start_marker && end_marker) { /* find start marker */ - loop_start = find_marker(streamFile,MarkerChunkOffset,start_marker); - loop_end = find_marker(streamFile,MarkerChunkOffset,end_marker); + loop_start = find_marker(streamFile,mark_offset,start_marker); + loop_end = find_marker(streamFile,mark_offset,end_marker); /* find_marker is type uint32_t as the spec says that's the type * of the position value, but it returns a -1 on error, and the @@ -257,6 +281,8 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) { loop_flag = 0; } } + + /* Relic has "beg loop" "end loop" comments but no actual looping? */ } @@ -270,14 +296,28 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) { vgmstream->loop_end_sample = loop_end; vgmstream->coding_type = coding_type; - if (coding_type == coding_XA) { - vgmstream->layout_type = layout_blocked_xa_aiff; - /* AIFF XA can use sample rates other than 37800/18900 */ - /* some Crusader: No Remorse tracks have XA headers with incorrect 0xFF, rip bug/encoder feature? */ - } - else { - vgmstream->layout_type = (channel_count > 1) ? layout_interleave : layout_none; - vgmstream->interleave_block_size = interleave; + switch(coding_type) { + case coding_XA: + vgmstream->layout_type = layout_blocked_xa_aiff; + /* AIFF XA can use sample rates other than 37800/18900 */ + /* some Crusader: No Remorse tracks have XA headers with incorrect 0xFF, rip bug/encoder feature? */ + break; + + case coding_RELIC: { + int bitrate = read_16bitBE(start_offset, streamFile); + start_offset += 0x02; + + vgmstream->codec_data = init_relic(channel_count, bitrate, sample_rate); + if (!vgmstream->codec_data) goto fail; + vgmstream->layout_type = layout_none; + + vgmstream->sample_rate = 44100; /* fixed output */ + break; + } + default: + vgmstream->layout_type = (channel_count > 1) ? layout_interleave : layout_none; + vgmstream->interleave_block_size = interleave; + break; } if (is_aifc) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aix_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/aix_streamfile.h index cf560f182..7001235ce 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/aix_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/aix_streamfile.h @@ -1,133 +1,51 @@ -#ifndef _AIX_STREAMFILE_H_ -#define _AIX_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - /* config */ - off_t stream_offset; - size_t stream_size; - int layer_number; - - /* state */ - off_t logical_offset; /* fake offset */ - off_t physical_offset; /* actual offset */ - size_t block_size; /* current size */ - size_t skip_size; /* size from block start to reach data */ - size_t data_size; /* usable size in a block */ - - size_t logical_size; -} aix_io_data; - - -static size_t aix_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, aix_io_data* data) { - size_t total_read = 0; - - - /* re-start when previous offset (can't map logical<>physical offsets) */ - if (data->logical_offset < 0 || offset < data->logical_offset) { - data->physical_offset = data->stream_offset; - data->logical_offset = 0x00; - data->data_size = 0; - } - - /* read blocks */ - while (length > 0) { - - /* ignore EOF */ - if (offset < 0 || data->physical_offset >= data->stream_offset + data->stream_size) { - break; - } - - /* process new block */ - if (data->data_size == 0) { - uint32_t block_id = read_u32be(data->physical_offset+0x00, streamfile); - data->block_size = read_u32be(data->physical_offset+0x04, streamfile) + 0x08; - - /* check valid block "AIXP" id, knowing that AIX segments end with "AIXE" block too */ - if (block_id != 0x41495850 || data->block_size == 0 || data->block_size == 0xFFFFFFFF) { - break; - } - - /* read target layer, otherwise skip to next block and try again */ - if (read_s8(data->physical_offset+0x08, streamfile) == data->layer_number) { - /* 0x09(1): layer count */ - data->data_size = read_s16be(data->physical_offset+0x0a, streamfile); - /* 0x0c: -1 */ - data->skip_size = 0x10; - } - - /* strange AIX in Tetris Collection (PS2) with padding before ADX start (no known flag) */ - if (data->logical_offset == 0x00 && - read_u32be(data->physical_offset + 0x10, streamfile) == 0 && - read_u16be(data->physical_offset + data->block_size - 0x28, streamfile) == 0x8000) { - data->data_size = 0x28; - data->skip_size = data->block_size - 0x28; - } - } - - /* move to next block */ - if (data->data_size == 0 || offset >= data->logical_offset + data->data_size) { - data->physical_offset += data->block_size; - data->logical_offset += data->data_size; - data->data_size = 0; - continue; - } - - /* read data */ - { - size_t bytes_consumed, bytes_done, to_read; - - bytes_consumed = offset - data->logical_offset; - to_read = data->data_size - bytes_consumed; - if (to_read > length) - to_read = length; - bytes_done = read_streamfile(dest, data->physical_offset + data->skip_size + bytes_consumed, to_read, streamfile); - - total_read += bytes_done; - dest += bytes_done; - offset += bytes_done; - length -= bytes_done; - - if (bytes_done != to_read || bytes_done == 0) { - break; /* error/EOF */ - } - } - } - - return total_read; -} - -static size_t aix_io_size(STREAMFILE *streamfile, aix_io_data* data) { - uint8_t buf[1]; - - if (data->logical_size) - return data->logical_size; - - /* force a fake read at max offset, to get max logical_offset (will be reset next read) */ - aix_io_read(streamfile, buf, 0x7FFFFFFF, 1, data); - data->logical_size = data->logical_offset; - - return data->logical_size; -} - -/* Handles deinterleaving of AIX blocked layer streams */ -static STREAMFILE* setup_aix_streamfile(STREAMFILE *sf, off_t stream_offset, size_t stream_size, int layer_number, const char* extension) { - STREAMFILE *new_sf = NULL; - aix_io_data io_data = {0}; - - io_data.stream_offset = stream_offset; - io_data.stream_size = stream_size; - io_data.layer_number = layer_number; - io_data.logical_offset = -1; /* force reset */ - - new_sf = open_wrap_streamfile(sf); - new_sf = open_io_streamfile_f(new_sf, &io_data, sizeof(aix_io_data), aix_io_read, aix_io_size); - new_sf = open_buffer_streamfile_f(new_sf, 0); - if (extension) { - new_sf = open_fakename_streamfile_f(new_sf, NULL, extension); - } - return new_sf; -} - -#endif /* _AIX_STREAMFILE_H_ */ +#ifndef _AIX_STREAMFILE_H_ +#define _AIX_STREAMFILE_H_ +#include "deblock_streamfile.h" + +//todo block size must check >= stream_size + +static void block_callback(STREAMFILE *sf, deblock_io_data *data) { + uint32_t block_id = read_u32be(data->physical_offset + 0x00, sf); + data->block_size = read_u32be(data->physical_offset + 0x04, sf) + 0x08; + + /* check "AIXP" id, (AIX segments end with "AIXE" too) */ + if (block_id != 0x41495850) { + return; + } + + /* read target layer, otherwise ignore block */ + if (read_s8(data->physical_offset + 0x08, sf) == data->cfg.track_number) { + /* 0x09(1): layer count */ + data->data_size = read_s16be(data->physical_offset + 0x0a, sf); + /* 0x0c: -1 */ + data->skip_size = 0x10; + } + + /* strange AIX in Tetris Collection (PS2) with padding before ADX start (no known flag) */ + if (data->logical_offset == 0x00 && + read_u32be(data->physical_offset + 0x10, sf) == 0 && + read_u16be(data->physical_offset + data->block_size - 0x28, sf) == 0x8000) { + data->data_size = 0x28; + data->skip_size = data->block_size - 0x28; + } +} + +/* Deinterleaves AIX layers */ +static STREAMFILE* setup_aix_streamfile(STREAMFILE *sf, off_t stream_offset, size_t stream_size, int layer_number, const char* extension) { + STREAMFILE *new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.stream_start = stream_offset; + cfg.stream_size = stream_size; + cfg.track_number = layer_number; + cfg.block_callback = block_callback; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + //new_sf = open_buffer_streamfile_f(new_sf, 0); + if (extension) + new_sf = open_fakename_streamfile_f(new_sf, NULL, extension); + return new_sf; +} + +#endif /* _AIX_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bnk_sony.c b/Frameworks/vgmstream/vgmstream/src/meta/bnk_sony.c index 36e343637..9fecfc0a8 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bnk_sony.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bnk_sony.c @@ -10,7 +10,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { size_t stream_size, interleave = 0; off_t sblk_offset, data_offset; size_t data_size; - int channel_count = 0, loop_flag, sample_rate, parts, version, big_endian; + int channel_count = 0, loop_flag, sample_rate, parts, sblk_version, big_endian; int loop_start = 0, loop_end = 0; uint32_t pitch, flags; uint32_t atrac9_info = 0; @@ -18,6 +18,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { int total_subsongs, target_subsong = streamFile->stream_index; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + float (*read_f32)(off_t,STREAMFILE*) = NULL; bnk_codec codec; @@ -25,14 +26,17 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { if (!check_extensions(streamFile, "bnk")) goto fail; + /* bnk version */ if (read_32bitBE(0x00,streamFile) == 0x00000003) { /* PS3 */ read_32bit = read_32bitBE; read_16bit = read_16bitBE; + read_f32 = read_f32be; big_endian = 1; } - else if (read_32bitBE(0x00,streamFile) == 0x03000000) { /* Vita/PS4 */ + else if (read_32bitBE(0x00,streamFile) == 0x03000000) { /* PS2/Vita/PS4 */ read_32bit = read_32bitLE; read_16bit = read_16bitLE; + read_f32 = read_f32le; big_endian = 0; } else { @@ -58,9 +62,9 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { /* SBlk part: parse header */ if (read_32bit(sblk_offset+0x00,streamFile) != 0x6B6C4253) /* "klBS" (SBlk = sample block?) */ goto fail; - version = read_32bit(sblk_offset+0x04,streamFile); - /* 0x08: possibly when version=0x0d, 0x03=Vita, 0x06=PS4 */ - //;VGM_LOG("BNK: sblk_offset=%lx, data_offset=%lx, version %x\n", sblk_offset, data_offset, version); + sblk_version = read_32bit(sblk_offset+0x04,streamFile); + /* 0x08: possibly when sblk_version=0x0d, 0x03=Vita, 0x06=PS4 */ + //;VGM_LOG("BNK: sblk_offset=%lx, data_offset=%lx, sblk_version %x\n", sblk_offset, data_offset, sblk_version); { int i; @@ -73,9 +77,23 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { off_t table4_entries_offset, table4_names_offset; - switch(version) { - case 0x03: /* L@ove Once - Mermaid's Tears (PS3) */ + switch(sblk_version) { + case 0x01: /* Ratchet & Clank (PS2) */ + section_entries = (uint16_t)read_16bit(sblk_offset+0x16,streamFile); /* entry size: ~0x0c */ + material_entries = (uint16_t)read_16bit(sblk_offset+0x18,streamFile); /* entry size: ~0x28 */ + stream_entries = (uint16_t)read_16bit(sblk_offset+0x1a,streamFile); /* entry size: none (count) */ + table1_offset = sblk_offset + read_32bit(sblk_offset+0x1c,streamFile); + table2_offset = sblk_offset + read_32bit(sblk_offset+0x20,streamFile); + table3_offset = table2_offset; /* mixed table in this version */ + table4_offset = 0; /* not included */ + + table1_entry_size = 0; /* not used */ + table1_suboffset = 0; + table2_suboffset = 0; + break; + case 0x04: /* Test banks */ + case 0x05: /* Ratchet & Clank (PS3) */ case 0x09: /* Puyo Puyo Tetris (PS4) */ section_entries = (uint16_t)read_16bit(sblk_offset+0x16,streamFile); /* entry size: ~0x0c */ material_entries = (uint16_t)read_16bit(sblk_offset+0x18,streamFile); /* entry size: ~0x08 */ @@ -106,7 +124,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { break; default: - VGM_LOG("BNK: unknown version %x\n", version); + VGM_LOG("BNK: unknown version %x\n", sblk_version); goto fail; } @@ -125,28 +143,44 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { * - get stream offsets * - find if one section points to the selected material, and get section name = stream name */ - /* parse materials */ total_subsongs = 0; if (target_subsong == 0) target_subsong = 1; - for (i = 0; i < material_entries; i++) { - uint32_t table2_value, table2_subinfo, table2_subtype; + switch(sblk_version) { + case 0x01: + /* table2/3 has size 0x28 entries, seemingly: + * 0x00: subtype(01=sound) + * 0x0A: pitch + * 0x18: stream offset + * there is no stream size so we'd need some sample counting + * many sounds repeat entries for no apparent reason + */ - table2_value = (uint32_t)read_32bit(table2_offset+(i*0x08)+table2_suboffset+0x00,streamFile); - table2_subinfo = (table2_value >> 0) & 0xFFFF; - table2_subtype = (table2_value >> 16) & 0xFFFF; - if (table2_subtype != 0x100) - continue; /* not sounds */ + goto fail; - total_subsongs++; - if (total_subsongs == target_subsong) { - table2_entry_offset = (i*0x08); - table3_entry_offset = table2_subinfo; - /* continue to count all subsongs*/ - } + default: + for (i = 0; i < material_entries; i++) { + uint32_t table2_value, table2_subinfo, table2_subtype; + + table2_value = (uint32_t)read_32bit(table2_offset+(i*0x08)+table2_suboffset+0x00,streamFile); + table2_subinfo = (table2_value >> 0) & 0xFFFF; + table2_subtype = (table2_value >> 16) & 0xFFFF; + if (table2_subtype != 0x100) + continue; /* not sounds */ + + total_subsongs++; + if (total_subsongs == target_subsong) { + table2_entry_offset = (i*0x08); + table3_entry_offset = table2_subinfo; + /* continue to count all subsongs*/ + } + } + + break; } + //;VGM_LOG("BNK: subsongs %i, table2_entry=%lx, table3_entry=%lx\n", total_subsongs,table2_entry_offset,table3_entry_offset); if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; @@ -159,9 +193,10 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { //;VGM_LOG("BNK: header entry at %lx\n", table3_offset+table3_entry_offset); /* parse sounds */ - switch(version) { + switch(sblk_version) { case 0x03: case 0x04: + case 0x05: case 0x09: pitch = (uint8_t)read_8bit(table3_offset+table3_entry_offset+0x02,streamFile); flags = (uint8_t)read_8bit(table3_offset+table3_entry_offset+0x0f,streamFile); @@ -185,6 +220,8 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { case 0xAC: sample_rate = 12000; break; //? case 0xAA: sample_rate = 11025; break; case 0xA9: sample_rate = 10000; break; //? + case 0xA4: sample_rate = 6000; break; //? + case 0x9d: sample_rate = 4000; break; //? default: VGM_LOG("BNK: unknown pitch %x\n", pitch); goto fail; @@ -196,20 +233,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { flags = (uint8_t)read_8bit(table3_offset+table3_entry_offset+0x12,streamFile); stream_offset = read_32bit(table3_offset+table3_entry_offset+0x44,streamFile); stream_size = read_32bit(table3_offset+table3_entry_offset+0x48,streamFile); - pitch = (uint32_t)read_32bit(table3_offset+table3_entry_offset+0x4c,streamFile); - - /* this looks like "((pitch >> 9) & 0xC000) | ((pitch >> 8) & 0xFFFF)" but... why??? */ - switch(pitch) { - case 0x467A0000: sample_rate = 64000; break; //? - case 0x46BB8000: sample_rate = 48000; break; - case 0x473B8000: sample_rate = 48000; break; - case 0x46AC4400: sample_rate = 44100; break; - case 0x47AC4400: sample_rate = 44100; break; - case 0x472C4400: sample_rate = 44100; break; - default: - VGM_LOG("BNK: unknown pitch %x\n", pitch); - goto fail; - } + sample_rate = (int)read_f32(table3_offset+table3_entry_offset+0x4c,streamFile); break; default: @@ -219,7 +243,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { //;VGM_LOG("BNK: stream at %lx + %x\n", stream_offset, stream_size); /* parse names */ - switch(version) { + switch(sblk_version) { //case 0x03: /* different format? */ //case 0x04: /* different format? */ case 0x09: @@ -271,9 +295,11 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { size_t extradata_size = 0, postdata_size = 0; start_offset = data_offset + stream_offset; - switch(version) { + switch(sblk_version) { + case 0x01: case 0x03: case 0x04: + case 0x05: channel_count = 1; /* hack for PS3 files that use dual subsongs as stereo */ @@ -382,6 +408,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) { break; default: + VGM_LOG("BNK: unknown data version %x\n", sblk_version); goto fail; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c b/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c index f8e7599de..b66dbc5d7 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c @@ -1,14 +1,18 @@ #include "meta.h" #include "../coding/coding.h" #include "../util.h" +#include "bnsf_keys.h" -/* BNSF - Namco Bandai's Bandai Namco Sound Format/File [Tales of Graces (Wii), Tales of Berseria (PS4)] */ + +static void find_bnsf_key(g7221_codec_data *data, off_t start, STREAMFILE *sf, uint8_t *best_key); + +/* BNSF - Bandai Namco Sound Format/File [Tales of Graces (Wii), Tales of Berseria (PS4)] */ VGMSTREAM * init_vgmstream_bnsf(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset = 0, first_offset = 0x0C; int loop_flag = 0, channel_count = 0, sample_rate; int num_samples, loop_start = 0, loop_end = 0, loop_adjust, block_samples; - uint32_t codec, subcodec = 0; + uint32_t codec, flags = 0; size_t bnsf_size, sdat_size, block_size; off_t loop_chunk = 0, sfmt_chunk, sdat_chunk; @@ -19,11 +23,10 @@ VGMSTREAM * init_vgmstream_bnsf(STREAMFILE *streamFile) { if (read_32bitBE(0,streamFile) != 0x424E5346) /* "BNSF" */ goto fail; + bnsf_size = read_32bitBE(0x04,streamFile); codec = read_32bitBE(0x08,streamFile); - /* check file size (siren22 uses full size) */ - bnsf_size = read_32bitBE(0x04,streamFile); - if (bnsf_size + (codec == 0x49533232 ? 0x00 : 0x08) != get_streamfile_size(streamFile)) + if (bnsf_size + (codec == 0x49533232 ? 0x00 : 0x08) != get_streamfile_size(streamFile)) /* IS22 uses full size */ goto fail; if (!find_chunk_be(streamFile, 0x73666d74,first_offset,0, &sfmt_chunk,NULL)) /* "sfmt" */ @@ -32,28 +35,27 @@ VGMSTREAM * init_vgmstream_bnsf(STREAMFILE *streamFile) { goto fail; if ( find_chunk_be(streamFile, 0x6C6F6F70,first_offset,0, &loop_chunk,NULL)) { /* "loop" */ loop_flag = 1; - loop_start = read_32bitBE(loop_chunk+0x00, streamFile); /* block-aligned */ + loop_start = read_32bitBE(loop_chunk+0x00,streamFile); /* block-aligned */ loop_end = read_32bitBE(loop_chunk+0x04,streamFile) + 1; } - subcodec = read_16bitBE(sfmt_chunk+0x00,streamFile); + flags = read_16bitBE(sfmt_chunk+0x00,streamFile); channel_count = read_16bitBE(sfmt_chunk+0x02,streamFile); sample_rate = read_32bitBE(sfmt_chunk+0x04,streamFile); num_samples = read_32bitBE(sfmt_chunk+0x08,streamFile); - loop_adjust = read_32bitBE(sfmt_chunk+0x0c,streamFile); /* 0 if no looping */ + loop_adjust = read_32bitBE(sfmt_chunk+0x0c,streamFile); /* 0 when no loop */ block_size = read_16bitBE(sfmt_chunk+0x10,streamFile); block_samples = read_16bitBE(sfmt_chunk+0x12,streamFile); - //max_samples = sdat_size / block_size * block_samples /* num_samples is smaller */ + //max_samples = sdat_size / block_size * block_samples; start_offset = sdat_chunk; - /* without adjust some files have a small pop when looping */ - if (loop_adjust >= block_samples) - goto fail; /* shouldn't happen, plus decoder can't handle it */ + if (loop_adjust >= block_samples) /* decoder can't handle this */ + goto fail; /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channel_count, loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = sample_rate; @@ -63,24 +65,38 @@ VGMSTREAM * init_vgmstream_bnsf(STREAMFILE *streamFile) { vgmstream->meta_type = meta_BNSF; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = block_size/channel_count; - - /* Late IS14 voice/ambient files use subcodec 0x02 [Tales of Zestiria (PS3/PC), The Idolm@ster 2 (PS3)]. - * Bitstream looks modified (most noticeable in silent frames), probably not encrypted, still 1ch frames */ - if (subcodec != 0) - goto fail; + vgmstream->interleave_block_size = block_size / channel_count; switch (codec) { #ifdef VGM_USE_G7221 - case 0x49533134: /* "IS14" */ + case 0x49533134: /* "IS14" (interleaved Siren14) */ vgmstream->coding_type = coding_G7221C; vgmstream->codec_data = init_g7221(vgmstream->channels, vgmstream->interleave_block_size); if (!vgmstream->codec_data) goto fail; + /* get decryption key in .bnsfkey file or list, for later games' voices + * [The Idolm@ster 2 (PS3/X360), Tales of Zestiria (PS3/PC)] */ + if (flags != 0) { /* only known value is 0x02 though */ + size_t keysize; + uint8_t key[24] = {0}; /* keystring 0-padded to 192-bit */ + + keysize = read_key_file(key, sizeof(key), streamFile); + if (keysize <= 0 || keysize > sizeof(key)) { + find_bnsf_key(vgmstream->codec_data, start_offset, streamFile, key); + } + + set_key_g7221(vgmstream->codec_data, key); + } + break; #endif #ifdef VGM_USE_G719 - case 0x49533232: /* "IS22" */ + case 0x49533232: /* "IS22" (interleaved Siren22) */ + + /* same encryption as IS14 but not seen */ + if (flags != 0) + goto fail; + vgmstream->coding_type = coding_G719; vgmstream->codec_data = init_g719(vgmstream->channels, vgmstream->interleave_block_size); if (!vgmstream->codec_data) goto fail; @@ -100,3 +116,41 @@ fail: close_vgmstream(vgmstream); return NULL; } + +static void find_bnsf_key(g7221_codec_data* data, off_t start, STREAMFILE* sf, uint8_t* best_key) { + const size_t keys_length = sizeof(s14key_list) / sizeof(bnsfkey_info); + int score, best_score = -1; + int i; + uint8_t tmpkey[24]; + + + for (i = 0; i < keys_length; i++) { + const char* key = s14key_list[i].key; + int keylen = strlen(key); + + if (keylen > sizeof(tmpkey)) + continue; + memcpy(tmpkey, key, keylen); + memset(tmpkey + keylen, 0, sizeof(tmpkey) - keylen); + + //;VGM_LOG("BNSF: test key=%.24s\n", tmpkey); + set_key_g7221(data, tmpkey); + + score = test_key_g7221(data, start, sf); + if (score < 0) continue; + + if (best_score <= 0 || (score < best_score && score > 0)) { + best_score = score; + memcpy(best_key, key, keylen); + memset(best_key + keylen, 0, sizeof(tmpkey) - keylen); + } + + if (best_score == 1) { + break; + } + + } + + VGM_ASSERT(best_score > 0, "BNSF: best key=%.24s (score=%i)\n", best_key, best_score); + VGM_ASSERT(best_score < 0, "BNSF: key not found\n"); /* defaults to all 0s */ +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bnsf_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/bnsf_keys.h new file mode 100644 index 000000000..3e36b38a4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/bnsf_keys.h @@ -0,0 +1,16 @@ +#ifndef _BNSF_KEYS_H_ +#define _BNSF_KEYS_H_ + +typedef struct { + const char* key; +} bnsfkey_info; + +/* Known keys, extracted from games' exe */ +static const bnsfkey_info s14key_list[] = { + + /* THE iDOLM@STER 2 (PS3/X360) */ + {"haruka17imas"}, + +}; + +#endif/*_BNSF_KEYS_H_*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/cri_utf.c b/Frameworks/vgmstream/vgmstream/src/meta/cri_utf.c index 8c7c27d55..f1dddb2d1 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/cri_utf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/cri_utf.c @@ -1,29 +1,30 @@ #include "cri_utf.h" -/* possibly 3b+5b from clUTF decompilation */ -#define COLUMN_BITMASK_STORAGE 0xf0 -#define COLUMN_BITMASK_TYPE 0x0f +#define COLUMN_BITMASK_FLAG 0xf0 +#define COLUMN_BITMASK_TYPE 0x0f -enum column_storage_t { - COLUMN_STORAGE_ZERO = 0x10, - COLUMN_STORAGE_CONSTANT = 0x30, - COLUMN_STORAGE_ROW = 0x50 - //COLUMN_STORAGE_CONSTANT2 = 0x70 /* from vgmtoolbox */ +enum columna_flag_t { + COLUMN_FLAG_NAME = 0x10, + COLUMN_FLAG_DEFAULT = 0x20, + COLUMN_FLAG_ROW = 0x40, + COLUMN_FLAG_UNDEFINED = 0x80 /* shouldn't exist */ }; enum column_type_t { - COLUMN_TYPE_SINT8 = 0x00, - COLUMN_TYPE_UINT8 = 0x01, - COLUMN_TYPE_SINT16 = 0x02, - COLUMN_TYPE_UINT16 = 0x03, - COLUMN_TYPE_SINT32 = 0x04, - COLUMN_TYPE_UINT32 = 0x05, - COLUMN_TYPE_SINT64 = 0x06, - //COLUMN_TYPE_UINT64 = 0x07, + COLUMN_TYPE_UINT8 = 0x00, + COLUMN_TYPE_SINT8 = 0x01, + COLUMN_TYPE_UINT16 = 0x02, + COLUMN_TYPE_SINT16 = 0x03, + COLUMN_TYPE_UINT32 = 0x04, + COLUMN_TYPE_SINT32 = 0x05, + COLUMN_TYPE_UINT64 = 0x06, + COLUMN_TYPE_SINT64 = 0x07, COLUMN_TYPE_FLOAT = 0x08, - //COLUMN_TYPE_DOUBLE = 0x09, + COLUMN_TYPE_DOUBLE = 0x09, COLUMN_TYPE_STRING = 0x0a, - COLUMN_TYPE_DATA = 0x0b + COLUMN_TYPE_VLDATA = 0x0b, + COLUMN_TYPE_UINT128 = 0x0c, /* for GUIDs */ + COLUMN_TYPE_UNDEFINED = -1 }; typedef struct { @@ -44,6 +45,10 @@ typedef struct { uint32_t offset; uint32_t size; } value_data; + //struct utf_u128_t { + // uint64_t hi; + // uint64_t lo; + //} value_u128; const char *value_string; } value; } utf_result_t; @@ -63,7 +68,8 @@ struct utf_context { uint16_t row_width; uint32_t rows; struct utf_column_t { - uint8_t flags; + uint8_t flag; + uint8_t type; const char *name; uint32_t offset; } *schema; @@ -77,7 +83,7 @@ struct utf_context { /* @UTF table context creation */ -utf_context* utf_open(STREAMFILE *sf, uint32_t table_offset, int *p_rows, const char **p_row_name) { +utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const char** p_row_name) { utf_context* utf = NULL; @@ -145,61 +151,75 @@ utf_context* utf_open(STREAMFILE *sf, uint32_t table_offset, int *p_rows, const if (!utf->schema) goto fail; for (i = 0; i < utf->columns; i++) { - uint8_t flags = read_u8(schema_offset + 0x00, sf); + uint8_t info = read_u8(schema_offset + 0x00, sf); uint32_t name_offset = read_u32be(schema_offset + 0x01, sf); if (name_offset > utf->strings_size) goto fail; - - utf->schema[i].flags = flags; - utf->schema[i].name = utf->string_table + name_offset; schema_offset += 0x01 + 0x04; - switch (utf->schema[i].flags & COLUMN_BITMASK_TYPE) { - case COLUMN_TYPE_SINT8: + + utf->schema[i].flag = info & COLUMN_BITMASK_FLAG; + utf->schema[i].type = info & COLUMN_BITMASK_TYPE; + utf->schema[i].name = NULL; + utf->schema[i].offset = 0; + + /* known flags are name+default or name+row, but name+default+row is mentioned in VGMToolbox + * even though isn't possible in CRI's craft utils, and no name is apparently possible */ + if ( (utf->schema[i].flag == 0) || + !(utf->schema[i].flag & COLUMN_FLAG_NAME) || + ((utf->schema[i].flag & COLUMN_FLAG_DEFAULT) && (utf->schema[i].flag & COLUMN_FLAG_ROW)) || + (utf->schema[i].flag & COLUMN_FLAG_UNDEFINED) ) { + VGM_LOG("@UTF: unknown column flag combo found\n"); + goto fail; + } + + switch (utf->schema[i].type) { case COLUMN_TYPE_UINT8: + case COLUMN_TYPE_SINT8: value_size = 0x01; break; - case COLUMN_TYPE_SINT16: case COLUMN_TYPE_UINT16: + case COLUMN_TYPE_SINT16: value_size = 0x02; break; - case COLUMN_TYPE_SINT32: case COLUMN_TYPE_UINT32: + case COLUMN_TYPE_SINT32: case COLUMN_TYPE_FLOAT: case COLUMN_TYPE_STRING: value_size = 0x04; break; + case COLUMN_TYPE_UINT64: case COLUMN_TYPE_SINT64: - //case COLUMN_TYPE_UINT64: - //case COLUMN_TYPE_DOUBLE: - case COLUMN_TYPE_DATA: + //case COLUMN_TYPE_DOUBLE: + case COLUMN_TYPE_VLDATA: value_size = 0x08; break; + //case COLUMN_TYPE_UINT128: + // value_size = 0x16; default: VGM_LOG("@UTF: unknown column type\n"); goto fail; } - switch (utf->schema[i].flags & COLUMN_BITMASK_STORAGE) { - case COLUMN_STORAGE_ROW: - utf->schema[i].offset = column_offset; - column_offset += value_size; - break; - case COLUMN_STORAGE_CONSTANT: - //case COLUMN_STORAGE_CONSTANT2: - utf->schema[i].offset = schema_offset - (utf->table_offset + utf->schema_offset); /* relative to schema */ - schema_offset += value_size; - break; - case COLUMN_STORAGE_ZERO: - utf->schema[i].offset = 0; /* ? */ - break; - default: - VGM_LOG("@UTF: unknown column storage\n"); - goto fail; + if (utf->schema[i].flag & COLUMN_FLAG_NAME) { + utf->schema[i].name = utf->string_table + name_offset; + } + + if (utf->schema[i].flag & COLUMN_FLAG_DEFAULT) { + /* data is found relative to schema start */ + utf->schema[i].offset = schema_offset - (utf->table_offset + utf->schema_offset); + schema_offset += value_size; + } + + if (utf->schema[i].flag & COLUMN_FLAG_ROW) { + /* data is found relative to row start */ + utf->schema[i].offset = column_offset; + column_offset += value_size; } } } + /* next section is row and variable length data (pointed above) then end of table */ /* write info */ if (p_rows) *p_rows = utf->rows; @@ -212,7 +232,7 @@ fail: return NULL; } -void utf_close(utf_context *utf) { +void utf_close(utf_context* utf) { if (!utf) return; free(utf->string_table); @@ -221,7 +241,7 @@ void utf_close(utf_context *utf) { } -static int utf_query(utf_context *utf, int row, const char *column, utf_result_t *result) { +static int utf_query(utf_context* utf, int row, const char* column, utf_result_t* result) { int i; @@ -235,60 +255,54 @@ static int utf_query(utf_context *utf, int row, const char *column, utf_result_t struct utf_column_t *col = &utf->schema[i]; uint32_t data_offset; - if (strcmp(col->name, column) != 0) + if (col->name == NULL || strcmp(col->name, column) != 0) continue; result->found = 1; - result->type = col->flags & COLUMN_BITMASK_TYPE; + result->type = col->type; - switch (col->flags & COLUMN_BITMASK_STORAGE) { - case COLUMN_STORAGE_ROW: - data_offset = utf->table_offset + utf->rows_offset + row * utf->row_width + col->offset; - break; - case COLUMN_STORAGE_CONSTANT: - //case COLUMN_STORAGE_CONSTANT2: - data_offset = utf->table_offset + utf->schema_offset + col->offset; - break; - case COLUMN_STORAGE_ZERO: - data_offset = 0; - memset(&result->value, 0, sizeof(result->value)); - break; - default: - goto fail; + if (col->flag & COLUMN_FLAG_DEFAULT) { + data_offset = utf->table_offset + utf->schema_offset + col->offset; + } + else if (col->flag & COLUMN_FLAG_ROW) { + data_offset = utf->table_offset + utf->rows_offset + row * utf->row_width + col->offset; + } + else { + data_offset = 0; } /* ignore zero value */ - if (!data_offset) + if (data_offset == 0) { + memset(&result->value, 0, sizeof(result->value)); /* just in case... */ break; + } /* read row/constant value */ - switch (col->flags & COLUMN_BITMASK_TYPE) { - case COLUMN_TYPE_SINT8: - result->value.value_s8 = read_s8(data_offset, utf->sf); - break; + switch (col->type) { case COLUMN_TYPE_UINT8: result->value.value_u8 = read_u8(data_offset, utf->sf); break; - case COLUMN_TYPE_SINT16: - result->value.value_s16 = read_s16be(data_offset, utf->sf); + case COLUMN_TYPE_SINT8: + result->value.value_s8 = read_s8(data_offset, utf->sf); break; case COLUMN_TYPE_UINT16: result->value.value_u16 = read_u16be(data_offset, utf->sf); break; - case COLUMN_TYPE_SINT32: - result->value.value_s32 = read_s32be(data_offset, utf->sf); + case COLUMN_TYPE_SINT16: + result->value.value_s16 = read_s16be(data_offset, utf->sf); break; case COLUMN_TYPE_UINT32: result->value.value_u32 = read_u32be(data_offset, utf->sf); break; - case COLUMN_TYPE_SINT64: - result->value.value_s64 = read_s64be(data_offset, utf->sf); + case COLUMN_TYPE_SINT32: + result->value.value_s32 = read_s32be(data_offset, utf->sf); break; -#if 0 case COLUMN_TYPE_UINT64: result->value.value_u64 = read_u64be(data_offset, utf->sf); break; -#endif + case COLUMN_TYPE_SINT64: + result->value.value_s64 = read_s64be(data_offset, utf->sf); + break; case COLUMN_TYPE_FLOAT: { result->value.value_float = read_f32be(data_offset, utf->sf); break; @@ -307,11 +321,17 @@ static int utf_query(utf_context *utf, int row, const char *column, utf_result_t break; } - case COLUMN_TYPE_DATA: + case COLUMN_TYPE_VLDATA: result->value.value_data.offset = read_u32be(data_offset + 0x00, utf->sf); result->value.value_data.size = read_u32be(data_offset + 0x04, utf->sf); break; - +#if 0 + case COLUMN_TYPE_UINT128: { + result->value.value_u128.hi = read_u64be(data_offset + 0x00, utf->sf); + result->value.value_u128.lo = read_u64be(data_offset + 0x08, utf->sf); + break; + } +#endif default: goto fail; } @@ -324,7 +344,7 @@ fail: return 0; } -static int utf_query_value(utf_context *utf, int row, const char *column, void *value, enum column_type_t type) { +static int utf_query_value(utf_context* utf, int row, const char* column, void* value, enum column_type_t type) { utf_result_t result = {0}; int valid; @@ -333,14 +353,14 @@ static int utf_query_value(utf_context *utf, int row, const char *column, void * return 0; switch(result.type) { - case COLUMN_TYPE_SINT8: (*(int8_t*)value) = result.value.value_s8; break; case COLUMN_TYPE_UINT8: (*(uint8_t*)value) = result.value.value_u8; break; - case COLUMN_TYPE_SINT16: (*(int16_t*)value) = result.value.value_s16; break; + case COLUMN_TYPE_SINT8: (*(int8_t*)value) = result.value.value_s8; break; case COLUMN_TYPE_UINT16: (*(uint16_t*)value) = result.value.value_u16; break; - case COLUMN_TYPE_SINT32: (*(int32_t*)value) = result.value.value_s32; break; + case COLUMN_TYPE_SINT16: (*(int16_t*)value) = result.value.value_s16; break; case COLUMN_TYPE_UINT32: (*(uint32_t*)value) = result.value.value_u32; break; + case COLUMN_TYPE_SINT32: (*(int32_t*)value) = result.value.value_s32; break; + case COLUMN_TYPE_UINT64: (*(uint64_t*)value) = result.value.value_u64; break; case COLUMN_TYPE_SINT64: (*(int64_t*)value) = result.value.value_s64; break; - //case COLUMN_TYPE_UINT64: (*(uint64_t*)value) = result.value.value_u64; break; case COLUMN_TYPE_STRING: (*(const char**)value) = result.value.value_string; break; default: return 0; @@ -349,25 +369,25 @@ static int utf_query_value(utf_context *utf, int row, const char *column, void * return 1; } -int utf_query_s8(utf_context *utf, int row, const char *column, int8_t *value) { - return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_SINT8); +int utf_query_u8(utf_context* utf, int row, const char* column, uint8_t* value) { + return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_UINT8); } -int utf_query_s16(utf_context *utf, int row, const char *column, int16_t *value) { - return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_SINT16); +int utf_query_u16(utf_context* utf, int row, const char* column, uint16_t* value) { + return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_UINT16); } -int utf_query_s32(utf_context *utf, int row, const char *column, int32_t *value) { - return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_SINT32); +int utf_query_u32(utf_context* utf, int row, const char* column, uint32_t* value) { + return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_UINT32); } -int utf_query_string(utf_context *utf, int row, const char *column, const char **value) { +int utf_query_string(utf_context* utf, int row, const char* column, const char** value) { return utf_query_value(utf, row, column, (void*)value, COLUMN_TYPE_STRING); } -int utf_query_data(utf_context *utf, int row, const char *column, uint32_t *p_offset, uint32_t *p_size) { +int utf_query_data(utf_context* utf, int row, const char* column, uint32_t* p_offset, uint32_t* p_size) { utf_result_t result = {0}; int valid; valid = utf_query(utf, row, column, &result); - if (!valid || !result.found || result.type != COLUMN_TYPE_DATA) + if (!valid || !result.found || result.type != COLUMN_TYPE_VLDATA) return 0; if (p_offset) *p_offset = utf->table_offset + utf->data_offset + result.value.value_data.offset; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/cri_utf.h b/Frameworks/vgmstream/vgmstream/src/meta/cri_utf.h index 1ceed7c9b..e8d2a6d20 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/cri_utf.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/cri_utf.h @@ -3,13 +3,14 @@ #include "../streamfile.h" -/* CRI @UTF (Universal Table Format?) is a generic database-like table made of - * rows/columns that contain numbers/strings/binary data, which also can be other tables. +/* CRI @UTF (Universal Table Format?) is a generic database-like table made of rows (called records) + * and columns (called fields) that contain numbers/strings/binary data, which also can be other tables. * * A table starts with "@UTF" and defines some values (row/data/string offsets, counts, etc) - * then DB schema (columns type+name), then rows, string table and binary data. Formats using @UTF + * then DB schema (column type+name), then rows, string table and binary data. Formats using @UTF * store and read data by row number + column name. Being a generic table with no fixed schema - * CRI uses it for different purposes (.acf: cues, .cpk: files, .aax: bgm, .usm: video, etc). + * CRI uses it for different purposes (.acf: cues, .cpk: files, .aax: bgm, .usm: video, etc), + * and seems used to serialize classes/objects too. * * (adapted from hcs's code to do multiple querys in the same table) */ @@ -20,13 +21,13 @@ typedef struct utf_context utf_context; /* open a CRI UTF table at offset, returning table name and rows. Passed streamfile is used internally for next calls */ -utf_context* utf_open(STREAMFILE *sf, uint32_t table_offset, int *p_rows, const char **p_row_name); -void utf_close(utf_context *utf); +utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const char** p_row_name); +void utf_close(utf_context* utf); /* query calls */ -int utf_query_s8(utf_context *utf, int row, const char *column, int8_t *value); -int utf_query_s16(utf_context *utf, int row, const char *column, int16_t *value); -int utf_query_s32(utf_context *utf, int row, const char *column, int32_t *value); -int utf_query_string(utf_context *utf, int row, const char *column, const char **value); -int utf_query_data(utf_context *utf, int row, const char *column, uint32_t *offset, uint32_t *size); +int utf_query_u8(utf_context* utf, int row, const char* column, uint8_t* value); +int utf_query_u16(utf_context* utf, int row, const char* column, uint16_t* value); +int utf_query_u32(utf_context* utf, int row, const char* column, uint32_t* value); +int utf_query_string(utf_context* utf, int row, const char* column, const char** value); +int utf_query_data(utf_context* utf, int row, const char* column, uint32_t* offset, uint32_t* size); #endif /* _CRI_UTF_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/csb.c b/Frameworks/vgmstream/vgmstream/src/meta/csb.c index bd429694a..dae785d0d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/csb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/csb.c @@ -12,7 +12,7 @@ VGMSTREAM * init_vgmstream_csb(STREAMFILE *streamFile) { utf_context *utf = NULL; utf_context *utf_sdl = NULL; int total_subsongs, target_subsong = streamFile->stream_index; - int8_t fmt = 0; + uint8_t fmt = 0; const char *stream_name; @@ -31,7 +31,7 @@ VGMSTREAM * init_vgmstream_csb(STREAMFILE *streamFile) { const char *sdl_name; uint32_t sdl_offset, sdl_size, offset, size; uint32_t table_offset = 0x00; - int8_t ttype; + uint8_t ttype; int found = 0; @@ -55,7 +55,7 @@ VGMSTREAM * init_vgmstream_csb(STREAMFILE *streamFile) { /* get SOUND_ELEMENT and table */ if (!utf_query_string(utf, sdl_row, "name", &row_name) || strcmp(row_name, "SOUND_ELEMENT") != 0) goto fail; - if (!utf_query_s8(utf, sdl_row, "ttype", &ttype) || ttype != 4) + if (!utf_query_u8(utf, sdl_row, "ttype", &ttype) || ttype != 4) goto fail; if (!utf_query_data(utf, sdl_row, "utf", &sdl_offset, &sdl_size)) goto fail; @@ -71,13 +71,13 @@ VGMSTREAM * init_vgmstream_csb(STREAMFILE *streamFile) { /* get target subsong */ for (i = 0; i < sdl_rows; i++) { - int8_t stmflg; + uint8_t stream_flag; - if (!utf_query_s8(utf_sdl, i, "stmflg", &stmflg)) + if (!utf_query_u8(utf_sdl, i, "stmflg", &stream_flag)) goto fail; /* only internal data for now (when 1 this refers to a .cpk subfile probably using "name", has size 0) */ - if (stmflg) + if (stream_flag) continue; total_subsongs++; @@ -87,9 +87,8 @@ VGMSTREAM * init_vgmstream_csb(STREAMFILE *streamFile) { goto fail; if (!utf_query_data(utf_sdl, i, "data", &offset, &size)) goto fail; - if (!utf_query_s8(utf_sdl, i, "fmt", &fmt)) + if (!utf_query_u8(utf_sdl, i, "fmt", &fmt)) goto fail; - VGM_LOG("fmt=%i\n", fmt); /* also nch/sfreq/nsmpl info */ found = 1; @@ -98,7 +97,7 @@ VGMSTREAM * init_vgmstream_csb(STREAMFILE *streamFile) { if (!found) goto fail; if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; -VGM_LOG("5: %x, %x\n", sdl_offset, offset); + subfile_offset = /*sdl_offset +*/ offset; subfile_size = size; @@ -107,14 +106,12 @@ VGM_LOG("5: %x, %x\n", sdl_offset, offset); goto fail; } - ;VGM_LOG("CSB: subfile offset=%lx + %x\n", subfile_offset, subfile_size); + //;VGM_LOG("CSB: subfile offset=%lx + %x\n", subfile_offset, subfile_size); temp_sf = setup_subfile_streamfile(streamFile, subfile_offset, subfile_size, "aax"); if (!temp_sf) goto fail; - VGM_LOG("7: %i\n", fmt); - switch(fmt) { case 0: /* AAX */ case 6: /* HCA */ @@ -132,8 +129,6 @@ VGM_LOG("5: %x, %x\n", sdl_offset, offset); goto fail; } - VGM_LOG("8\n"); - vgmstream->num_streams = total_subsongs; strncpy(vgmstream->stream_name, stream_name, STREAM_NAME_SIZE-1); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/deblock_streamfile.c b/Frameworks/vgmstream/vgmstream/src/meta/deblock_streamfile.c new file mode 100644 index 000000000..eda65a786 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/deblock_streamfile.c @@ -0,0 +1,181 @@ +#include "deblock_streamfile.h" + +//todo move to utils or something + +static void block_callback_default(STREAMFILE *sf, deblock_io_data *data) { + data->block_size = data->cfg.chunk_size; + data->skip_size = data->cfg.skip_size; + data->data_size = data->block_size - data->skip_size; + + //;VGM_LOG("DEBLOCK: of=%lx, bs=%lx, ss=%lx, ds=%lx\n", data->physical_offset, data->block_size, data->skip_size, data->data_size); +} + +static size_t deblock_io_read(STREAMFILE *sf, uint8_t *dest, off_t offset, size_t length, deblock_io_data* data) { + size_t total_read = 0; + + + /* re-start when previous offset (can't map logical<>physical offsets) */ + if (data->logical_offset < 0 || offset < data->logical_offset) { + ;VGM_LOG("DEBLOCK: restart offset=%lx + %x, po=%lx, lo=%lx\n", offset, length, data->physical_offset, data->logical_offset); + data->physical_offset = data->cfg.stream_start; + data->logical_offset = 0x00; + data->block_size = 0; + data->data_size = 0; + data->skip_size = 0; + + data->step_count = data->cfg.step_start; +/* + data->read_count = data->cfg.read_count; +*/ + } + + /* read blocks */ + while (length > 0) { + + /* ignore EOF */ + if (offset < 0 || + (data->physical_offset >= data->cfg.stream_start + data->physical_size) || + (data->logical_size > 0 && offset > data->logical_size)) { + break; + } + + /* process new block */ + if (data->data_size <= 0) { + data->cfg.block_callback(sf, data); + + if (data->block_size <= 0) { + VGM_LOG("DEBLOCK: block size not set at %lx\n", data->physical_offset); + break; + } + } + +#if 1 + if (data->step_count > 0) { + data->step_count--; + data->physical_offset += data->block_size; + data->data_size = 0; + continue; + } +#else + /* handle blocks from multiple streams */ + { + if (data->step_count > 0) { + data->step_count--; + data->data_size = 0; /* step over this block */ + } + else if (data->read_count) {//must detect when blocks has been read + data->read_count--; /* read this block */ + + /* reset */ + if (data->step_count == 0 && data->read_count == 0) { + data->step_count = data->cfg.step_count; + data->read_count = data->cfg.read_count; + } + } + } +#endif + /* move to next block */ + if (data->data_size == 0 || offset >= data->logical_offset + data->data_size) { + data->physical_offset += data->block_size; + data->logical_offset += data->data_size; + data->data_size = 0; + + data->step_count = data->cfg.step_count; + //VGM_LOG("ignore at %lx + %lx, skips=%i, reads=%i\n", data->physical_offset, data->block_size, data->step_count, data->read_count); + continue; + } + + //VGM_LOG("accept at %lx + %lx, skips=%i, reads=%i\n", data->physical_offset, data->block_size, data->step_count, data->read_count); + + /* read block data */ + { + size_t bytes_consumed, bytes_done, to_read; + + bytes_consumed = offset - data->logical_offset; + to_read = data->data_size - bytes_consumed; + if (to_read > length) + to_read = length; + bytes_done = read_streamfile(dest, data->physical_offset + data->skip_size + bytes_consumed, to_read, sf); + + total_read += bytes_done; + dest += bytes_done; + offset += bytes_done; + length -= bytes_done; + + if (bytes_done != to_read || bytes_done == 0) { + break; /* error/EOF */ + } + } + } + + return total_read; +} + +static size_t deblock_io_size(STREAMFILE *streamfile, deblock_io_data* data) { + uint8_t buf[0x04]; + + if (data->logical_size) + return data->logical_size; + + if (data->cfg.logical_size) { + data->logical_size = data->cfg.logical_size; + return data->logical_size; + } + + /* force a fake read at max offset, to get max logical_offset (will be reset next read) */ + deblock_io_read(streamfile, buf, 0x7FFFFFFF, 1, data); + data->logical_size = data->logical_offset; + + //todo tests: + //if (logical_size > max_physical_offset) + // return 0; + //if (logical_size != data->stream_size) + // return 0; + + + return data->logical_size; +} + +/* generic "de-blocker" helper for streams divided in blocks that have weird interleaves, their + * decoder can't easily use blocked layout, or some other weird feature. It "filters" data so + * reader only sees clean data without blocks. Must pass setup config and a callback that sets + * sizes of a single block. */ +STREAMFILE* open_io_deblock_streamfile_f(STREAMFILE *sf, deblock_config_t *cfg) { + STREAMFILE *new_sf = NULL; + deblock_io_data io_data = {0}; + + /* prepare data */ + io_data.cfg = *cfg; /* memcpy */ + + if (io_data.cfg.block_callback == NULL) + io_data.cfg.block_callback = block_callback_default; + + if (io_data.cfg.stream_start < 0) + goto fail; + if (io_data.cfg.step_start < 0 || io_data.cfg.step_count < 0) + goto fail; + + if (io_data.cfg.step_count > 0) { + io_data.cfg.step_count--; + } +/* + if (io_data.cfg.read_count == 0) + io_data.cfg.read_count = 1; +*/ + io_data.physical_size = io_data.cfg.stream_size; + if (io_data.physical_size > get_streamfile_size(sf) + io_data.cfg.stream_start || io_data.physical_size == 0) + io_data.physical_size = get_streamfile_size(sf) - io_data.cfg.stream_start; + io_data.physical_end = io_data.cfg.stream_start + io_data.physical_size; + + io_data.logical_offset = -1; /* read reset */ + + //TODO: other validations + + /* setup subfile */ + new_sf = open_io_streamfile_f(sf, &io_data, sizeof(deblock_io_data), deblock_io_read, deblock_io_size); + return new_sf; +fail: + VGM_LOG("DEBLOCK: bad init\n"); + close_streamfile(sf); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/deblock_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/deblock_streamfile.h new file mode 100644 index 000000000..e54039d96 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/deblock_streamfile.h @@ -0,0 +1,61 @@ +#ifndef _DEBLOCK_STREAMFILE_H_ +#define _DEBLOCK_STREAMFILE_H_ +#include "../streamfile.h" + +typedef struct deblock_config_t deblock_config_t; +typedef struct deblock_io_data deblock_io_data; + +struct deblock_config_t { + /* config (all optional) */ + size_t logical_size; /* pre-calculated size for performance (otherwise has to read the whole thing) */ + off_t stream_start; /* data start */ + size_t stream_size; /* data max */ + + size_t chunk_size; /* some size like a constant interleave */ + size_t frame_size; /* some other size */ + size_t skip_size; /* same */ + + int codec; /* codec or type variations */ + int channels; + int big_endian; + uint32_t config; /* some non-standard config value */ + + /* read=blocks from out stream to read) and "steps" (blocks from other streams to skip) */ + int step_start; /* initial step_count at stream start (often 0) */ + int step_count; /* number of blocks to step over from other streams */ + //int read_count; /* number of blocks to read from this stream, after steps */ + + size_t track_size; + int track_number; + int track_count; + uint32_t track_type; + + size_t interleave_count; + size_t interleave_last_count; + + /* callback that setups deblock_io_data state, normally block_size and data_size */ + void (*block_callback)(STREAMFILE *sf, deblock_io_data *data); +} ; + +struct deblock_io_data { + /* initial config */ + deblock_config_t cfg; + + /* state */ + off_t logical_offset; /* fake deblocked offset */ + off_t physical_offset; /* actual file offset */ + off_t block_size; /* current block (added to physical offset) */ + off_t skip_size; /* data to skip from block start to reach data (like a header) */ + off_t data_size; /* usable data in a block (added to logical offset) */ + + int step_count; /* number of blocks to step over */ + //int read_count; /* number of blocks to read */ + + size_t logical_size; + size_t physical_size; + off_t physical_end; +}; + +STREAMFILE* open_io_deblock_streamfile_f(STREAMFILE *sf, deblock_config_t *cfg); + +#endif /* _DEBLOCK_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c index 5cdfe46d9..b8323f9ea 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c @@ -39,7 +39,7 @@ static VGMSTREAM *parse_s10a_header(STREAMFILE *streamFile, off_t offset, uint16 VGMSTREAM * init_vgmstream_gin_header(STREAMFILE *streamFile, off_t offset); -/* .SNR+SNS - from EA latest games (~2008-2013), v0 header */ +/* .SNR+SNS - from EA latest games (~2005-2010), v0 header */ VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile) { /* check extension, case insensitive */ if (!check_extensions(streamFile,"snr")) @@ -51,7 +51,7 @@ fail: return NULL; } -/* .SPS - from EA latest games (~2014), v1 header */ +/* .SPS - from EA latest games (~2010~present), v1 header */ VGMSTREAM * init_vgmstream_ea_sps(STREAMFILE * streamFile) { /* check extension, case insensitive */ if (!check_extensions(streamFile,"sps")) @@ -1262,7 +1262,7 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST #endif #ifdef VGM_USE_FFMPEG - case EAAC_CODEC_EAOPUS: { /* EAOpus (unknown FourCC) [FIFA 17 (PC), FIFA 19 (Switch)]*/ + case EAAC_CODEC_EAOPUS: { /* "Eop0"? : EAOpus [FIFA 17 (PC), FIFA 19 (Switch)]*/ vgmstream->layout_data = build_layered_eaaudiocore(streamFile, &eaac, 0x00); if (!vgmstream->layout_data) goto fail; vgmstream->coding_type = coding_FFmpeg; @@ -1556,6 +1556,7 @@ static layered_layout_data* build_layered_eaaudiocore(STREAMFILE *sf_data, eaac_ uint8_t buf[0x100]; int bytes, block_size, block_count; size_t stream_size; + int is_xma1; temp_sf = setup_eaac_audio_streamfile(sf_data, eaac->version, eaac->codec, eaac->streamed,i,layers, start_offset); if (!temp_sf) goto fail; @@ -1564,7 +1565,14 @@ static layered_layout_data* build_layered_eaaudiocore(STREAMFILE *sf_data, eaac_ block_size = 0x10000; /* unused */ block_count = stream_size / block_size + (stream_size % block_size ? 1 : 0); - bytes = ffmpeg_make_riff_xma2(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, block_count, block_size); + /* EA adopted XMA2 when it appeared around 2006, but detection isn't so easy + * (SNS with XMA2 do exist). Decoder should work when playing XMA1 as XMA2, but + * the other way around can cause issues, so it's safer to just use XMA2. */ + is_xma1 = 0; //eaac->version == EAAC_VERSION_V0; /* approximate */ + if (is_xma1) + bytes = ffmpeg_make_riff_xma1(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, 0); + else + bytes = ffmpeg_make_riff_xma2(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, block_count, block_size); data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_sf, buf,bytes, 0x00, stream_size); if (!data->layers[i]->codec_data) goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac_opus_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac_opus_streamfile.h index a71b810e4..06a40e899 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac_opus_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac_opus_streamfile.h @@ -1,241 +1,23 @@ #ifndef _EA_EAAC_OPUS_STREAMFILE_H_ #define _EA_EAAC_OPUS_STREAMFILE_H_ -#include "../streamfile.h" +#include "deblock_streamfile.h" -typedef struct deblock_config_t deblock_config_t; -typedef struct deblock_io_data deblock_io_data; - - struct deblock_config_t { - /* config (all optional) */ - size_t logical_size; /* pre-calculated size for performance (otherwise has to read the whole thing) */ - off_t stream_start; /* data start */ - size_t stream_size; /* data max */ - - size_t chunk_size; /* some size like a constant interleave */ - size_t skip_size; /* same */ - - int codec; /* codec or type variations */ - int channels; - int big_endian; - uint32_t config; /* some non-standard config value */ - - /* read=blocks from out stream to read) and "steps" (blocks from other streams to skip) */ - int step_start; /* initial step_count at stream start (often 0) */ - int step_count; /* number of blocks to step over from other streams */ - int read_count; /* number of blocks to read from this stream, after steps */ - - size_t track_size; - int track_number; - int track_count; - size_t interleave_count; - size_t interleave_last_count; - - /* callback that setups deblock_io_data state, normally block_size and data_size */ - void (*block_callback)(STREAMFILE *sf, off_t offset, deblock_io_data *data); -} ; - - -struct deblock_io_data{ - /* initial config */ - deblock_config_t cfg; - - /* state */ - off_t logical_offset; /* fake deblocked offset */ - off_t physical_offset; /* actual file offset */ - off_t block_size; /* current block (added to physical offset) */ - off_t skip_size; /* data to skip from block start to reach data (like a header) */ - off_t data_size; /* usable data in a block (added to logical offset) */ -//todo head/foot? - int step_count; /* number of blocks to step over */ - int read_count; /* number of blocks to read */ - - size_t logical_size; - size_t physical_size; - off_t physical_end; -} ; - - -static void block_callback_default(STREAMFILE *sf, off_t offset, deblock_io_data *data) { - data->block_size = data->cfg.chunk_size; - data->skip_size = data->cfg.skip_size; - data->data_size = data->block_size - data->skip_size; -} - -static size_t deblock_io_read(STREAMFILE *sf, uint8_t *dest, off_t offset, size_t length, deblock_io_data* data) { - size_t total_read = 0; - - - /* re-start when previous offset (can't map logical<>physical offsets) */ - if (data->logical_offset < 0 || offset < data->logical_offset) { - ;VGM_LOG("DEBLOCK: restart offset=%lx + %x, po=%lx, lo=%lx\n", offset, length, data->physical_offset, data->logical_offset); - data->physical_offset = data->cfg.stream_start; - data->logical_offset = 0x00; - data->block_size = 0; - data->data_size = 0; - data->skip_size = 0; - - data->step_count = data->cfg.step_start; - data->read_count = data->cfg.read_count; - } - - /* read blocks */ - while (length > 0) { - - /* ignore EOF */ - if (offset < 0 || - (data->physical_offset >= data->cfg.stream_start + data->physical_size) || - (data->logical_size > 0 && offset > data->logical_size)) { - break; - } - - /* process new block */ - if (data->data_size <= 0) { - data->cfg.block_callback(sf, offset, data); - - if (data->block_size <= 0) { - VGM_LOG("DEBLOCK: block size not set at %lx\n", data->physical_offset); - break; - } - } - -#if 1 - if (data->step_count > 0) { - data->step_count--; - data->physical_offset += data->block_size; - data->data_size = 0; - continue; - } -#else - /* handle blocks from multiple streams */ - { - if (data->step_count > 0) { - data->step_count--; - data->data_size = 0; /* step over this block */ - } - else if (data->read_count) {//must detect when blocks has been read - data->read_count--; /* read this block */ - - /* reset */ - if (data->step_count == 0 && data->read_count == 0) { - data->step_count = data->cfg.step_count; - data->read_count = data->cfg.read_count; - } - } - } -#endif - /* move to next block */ - if (data->data_size == 0 || offset >= data->logical_offset + data->data_size) { - data->physical_offset += data->block_size; - data->logical_offset += data->data_size; - data->data_size = 0; - - data->step_count = data->cfg.step_count; - //VGM_LOG("ignore at %lx + %lx, skips=%i, reads=%i\n", data->physical_offset, data->block_size, data->step_count, data->read_count); - continue; - } - - //VGM_LOG("accept at %lx + %lx, skips=%i, reads=%i\n", data->physical_offset, data->block_size, data->step_count, data->read_count); - - /* read block data */ - { - size_t bytes_consumed, bytes_done, to_read; - - bytes_consumed = offset - data->logical_offset; - to_read = data->data_size - bytes_consumed; - if (to_read > length) - to_read = length; - bytes_done = read_streamfile(dest, data->physical_offset + data->skip_size + bytes_consumed, to_read, sf); - - total_read += bytes_done; - dest += bytes_done; - offset += bytes_done; - length -= bytes_done; - - if (bytes_done != to_read || bytes_done == 0) { - break; /* error/EOF */ - } - } - } - - return total_read; -} - -static size_t deblock_io_size(STREAMFILE *streamfile, deblock_io_data* data) { - uint8_t buf[0x04]; - - if (data->logical_size) - return data->logical_size; - - if (data->cfg.logical_size) { - data->logical_size = data->cfg.logical_size; - return data->logical_size; - } - - /* force a fake read at max offset, to get max logical_offset (will be reset next read) */ - deblock_io_read(streamfile, buf, 0x7FFFFFFF, 1, data); - data->logical_size = data->logical_offset; - return data->logical_size; -} - -/* generic "de-blocker" helper for streams divided in blocks that have weird interleaves, their - * decoder can't easily use blocked layout, or some other weird feature. Must pass a - * deblock_config_t with setup and a callback that sets sizes of a single block. */ -static STREAMFILE* open_io_deblocker_streamfile_f(STREAMFILE *sf, deblock_config_t *cfg) { - STREAMFILE *new_sf = NULL; - deblock_io_data io_data = {0}; - - /* prepare data */ - io_data.cfg = *cfg; /* memcpy */ - - if (io_data.cfg.block_callback == NULL) - io_data.cfg.block_callback = block_callback_default; - - if (io_data.cfg.stream_start < 0) - goto fail; - if (io_data.cfg.step_start < 0 || io_data.cfg.step_count < 0) - goto fail; - - if (io_data.cfg.read_count == 0) - io_data.cfg.read_count = 1; - - io_data.physical_size = io_data.cfg.stream_size; - if (io_data.physical_size > get_streamfile_size(sf) + io_data.cfg.stream_start || io_data.physical_size == 0) - io_data.physical_size = get_streamfile_size(sf) - io_data.cfg.stream_start; - io_data.physical_end = io_data.cfg.stream_start + io_data.physical_size; -VGM_LOG("ps=%x, pe=%lx\n", io_data.physical_size, io_data.physical_end); - io_data.logical_offset = -1; /* read reset */ - - //TODO: other validations - - /* setup subfile */ - new_sf = open_io_streamfile_f(sf, &io_data, sizeof(deblock_io_data), deblock_io_read, deblock_io_size); - return new_sf; -fail: - VGM_LOG("DEBLOCK: bad init\n"); - close_streamfile(sf); - return NULL; -} - -/*****************************************************/ - -static void block_callback(STREAMFILE *sf, off_t offset, deblock_io_data *data) { - /* read the whole block, will be skipped for unwanted sub-streams */ +static void block_callback(STREAMFILE *sf, deblock_io_data *data) { data->block_size = 0x02 + read_u16be(data->physical_offset, sf); data->data_size = data->block_size; - //VGM_LOG("read at %lx + %lx, skips=%i, reads=%i\n", data->physical_offset, data->block_size, data->step_count, data->read_count); } static STREAMFILE* open_io_eaac_opus_streamfile_f(STREAMFILE *new_sf, int stream_number, int stream_count) { deblock_config_t cfg = {0}; cfg.step_start = stream_number; - cfg.step_count = stream_count - 1; + cfg.step_count = stream_count; cfg.block_callback = block_callback; /* starts from 0 since new_sf is pre-deblocked */ /* setup subfile */ //new_sf = open_wrap_streamfile(sf); /* to be used with others */ - new_sf = open_io_deblocker_streamfile_f(new_sf, &cfg); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); return new_sf; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c index c85a58c4b..a8f92043b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c @@ -629,6 +629,8 @@ static STREAMFILE* open_mapfile_pair(STREAMFILE *streamFile, int track, int num_ {"MUS_CTRL.MPF", "MUS_STR.MUS"}, /* GoldenEye - Rogue Agent (PS2) */ {"mus_ctrl.mpf", "mus_str.mus"}, /* GoldenEye - Rogue Agent (others) */ {"AKA_Mus.mpf", "Track.mus"}, /* Boogie */ + {"SSX4FE.mpf", "TrackFE.mus"}, /* SSX On Tour */ + {"SSX4Path.mpf", "Track.mus"}, /* SSX On Tour */ {"SSX4.mpf", "moments0.mus,main.mus,load_loop0.mus"}, /* SSX Blur */ {"willow.mpf", "willow.mus,willow_o.mus"}, /* Harry Potter and the Chamber of Secrets */ {"exterior.mpf", "exterior.mus,ext_o.mus"}, /* Harry Potter and the Chamber of Secrets */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_streamfile.h index 97eb0c123..e2711b77b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_streamfile.h @@ -1,182 +1,45 @@ -#ifndef _EA_SCHL_STREAMFILE_H_ -#define _EA_SCHL_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - /* state */ - off_t logical_offset; /* offset that corresponds to physical_offset */ - off_t physical_offset; /* actual file offset */ - - /* config */ - int codec; - int channels; - off_t start_offset; - size_t total_size; /* size of the resulting substream */ -} schl_io_data; - - -/* Reads skipping EA's block headers, so the resulting data is smaller or larger than physical data. - * physical/logical_offset should always be at the start of a block and only advance when a block is fully done */ -static size_t schl_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, schl_io_data* data) { - size_t total_read = 0; - - /* ignore bad reads */ - if (offset < 0 || offset > data->total_size) { - return total_read; - } - - /* previous offset: re-start as we can't map logical<>physical offsets - * (kinda slow as it trashes buffers, but shouldn't happen often) */ - if (offset < data->logical_offset) { - data->physical_offset = data->start_offset; - data->logical_offset = 0x00; - } - - /* read doing one EA block at a time */ - while (length > 0) { - size_t to_read, bytes_read; - off_t intrablock_offset, intradata_offset; - uint32_t block_id, block_size, data_size, skip_size; - - block_id = (uint32_t)read_32bitBE(data->physical_offset+0x00,streamfile); - block_size = read_32bitLE(data->physical_offset+0x04,streamfile); /* always LE, hopefully */ - - if (block_id == 0x5343456C) /* "SCEl" */ - break; /* end block (no need to look for more SCHl for codecs needed this custom IO) */ - - if (block_id != 0x5343446C) { /* "SCDl" */ - data->physical_offset += block_size; - continue; /* skip non-data blocks */ - } - - switch(data->codec) { - case 0x1b: /* ATRAC3plus */ - data_size = read_32bitLE(data->physical_offset+0x0c+0x04*data->channels,streamfile); - skip_size = 0x0c+0x04*data->channels+0x04; - break; - default: - return total_read; - } - - /* requested offset is outside current block, try next */ - if (offset >= data->logical_offset + data_size) { - data->physical_offset += block_size; - data->logical_offset += data_size; - continue; - } - - /* reads could fall in the middle of the block */ - intradata_offset = offset - data->logical_offset; - intrablock_offset = skip_size + intradata_offset; - - /* clamp reads up to this block's end */ - to_read = (data_size - intradata_offset); - if (to_read > length) - to_read = length; - if (to_read == 0) - break; /* should never happen... */ - - /* finally read and move buffer/offsets */ - bytes_read = read_streamfile(dest, data->physical_offset + intrablock_offset, to_read, streamfile); - total_read += bytes_read; - if (bytes_read != to_read) - break; /* couldn't read fully */ - - dest += bytes_read; - offset += bytes_read; - length -= bytes_read; - - /* block fully read, go next */ - if (intradata_offset + bytes_read == data_size) { - data->physical_offset += block_size; - data->logical_offset += data_size; - } - } - - return total_read; -} - -static size_t schl_io_size(STREAMFILE *streamfile, schl_io_data* data) { - off_t physical_offset, max_physical_offset; - size_t total_size = 0; - - if (data->total_size) - return data->total_size; - - physical_offset = data->start_offset; - max_physical_offset = get_streamfile_size(streamfile); - - /* get size of the underlying, non-blocked data */ - while (physical_offset < max_physical_offset) { - uint32_t block_id, block_size, data_size; - - block_id = (uint32_t)read_32bitBE(physical_offset+0x00,streamfile); - block_size = read_32bitLE(physical_offset+0x04,streamfile); /* always LE, hopefully */ - - if (block_id == 0x5343456C) /* "SCEl" */ - break; /* end block (no need to look for more SCHl for codecs needed this custom IO) */ - - if (block_id != 0x5343446C) { /* "SCDl" */ - physical_offset += block_size; - continue; /* skip non-data blocks */ - } - - switch(data->codec) { - case 0x1b: /* ATRAC3plus */ - data_size = read_32bitLE(physical_offset+0x0c+0x04*data->channels,streamfile); - break; - default: - return 0; - } - - physical_offset += block_size; - total_size += data_size; - } - - - if (total_size > get_streamfile_size(streamfile)) { - VGM_LOG("EA SCHL: wrong streamfile total_size\n"); - total_size = 0; - } - - data->total_size = total_size; - return data->total_size; -} - - -/* Prepares custom IO for some blocked SCHl formats, that need clean reads without block headers. - * Basically done to feed FFmpeg clean ATRAC3plus. - */ -static STREAMFILE* setup_schl_streamfile(STREAMFILE *streamFile, int codec, int channels, off_t start_offset, size_t total_size) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - schl_io_data io_data = {0}; - size_t io_data_size = sizeof(schl_io_data); - - io_data.codec = codec; - io_data.channels = channels; - io_data.start_offset = start_offset; - io_data.total_size = total_size; /* optional */ - io_data.physical_offset = start_offset; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, schl_io_read,schl_io_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_buffer_streamfile(new_streamFile,0); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -#endif /* _EA_SCHL_STREAMFILE_H_ */ +#ifndef _EA_SCHL_STREAMFILE_H_ +#define _EA_SCHL_STREAMFILE_H_ +#include "deblock_streamfile.h" + +static void block_callback(STREAMFILE *sf, deblock_io_data *data) { + uint32_t block_type, block_size; + + block_type = read_u32be(data->physical_offset + 0x00, sf); + block_size = read_u32le(data->physical_offset + 0x04, sf); /* always LE, hopefully */ + + if (block_type == 0x5343456C) /* "SCEl" end block */ + return; + + data->block_size = block_size; + if (block_type != 0x5343446C) /* skip non-"SCDl" blocks */ + return; + + switch(data->cfg.codec) { + case 0x1b: /* ATRAC3plus */ + data->data_size = read_32bitLE(data->physical_offset + 0x0c + 0x04 * data->cfg.channels, sf); + data->skip_size = 0x0c + 0x04 * data->cfg.channels + 0x04; + break; + default: + break; + } +} + +/* Deblocks SCHl streams */ +static STREAMFILE* setup_schl_streamfile(STREAMFILE *sf, int codec, int channels, off_t stream_offset, size_t logical_size) { + STREAMFILE *new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.stream_start = stream_offset; + cfg.logical_size = logical_size; + cfg.codec = codec; + cfg.channels = channels; //todo chunk size? + cfg.block_callback = block_callback; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + //new_sf = open_buffer_streamfile(new_sf, 0); + return new_sf; +} + +#endif /* _EA_SCHL_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_swvr.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_swvr.c index da1f1070f..a82e52a3d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_swvr.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_swvr.c @@ -102,9 +102,14 @@ VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE *streamFile) { sample_rate = 14008; break; case 0x53484F43: /* "SHOC" (a generic block but hopefully has PC sounds) */ - coding = coding_PCM8_U_int; - channel_count = 1; - sample_rate = 14008; + if (read_32bit(start_offset+0x10, streamFile) == 0x53484F43) { /* SHDR */ + coding = coding_PCM8_U_int; //todo there are other codecs + channel_count = 1; + sample_rate = 14008; + } + else { + goto fail; + } break; default: VGM_LOG("EA SWVR: unknown block id\n"); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fda.c b/Frameworks/vgmstream/vgmstream/src/meta/fda.c new file mode 100644 index 000000000..57c9a0e19 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/fda.c @@ -0,0 +1,96 @@ +#include "meta.h" +#include "../coding/coding.h" + + +/* FDA - from Relic Entertainment games [Warhammer 4000: Dawn of War (PC)] */ +VGMSTREAM * init_vgmstream_fda(STREAMFILE *sf) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count, bitrate, sample_rate, num_samples; + + + /* checks */ + if (!check_extensions(sf, "fda")) + goto fail; + + if (read_u32be(0x00, sf) != 0x52656C69 || /* "Reli" */ + read_u32be(0x04, sf) != 0x63204368 || /* "c Ch" */ + read_u32be(0x08, sf) != 0x756E6B79 || /* "unky" */ + read_u32be(0x0c, sf) != 0x0D0A1A00) /* "\r\n\1a\00"*/ + goto fail; + + /* version? (later .fda change this) */ + if (read_u32le(0x10, sf) != 1 || + read_u32le(0x14, sf) != 1) + goto fail; + + /* read chunks (abridged) */ + { + off_t offset = 0x18; + size_t chunk_size, name_size, data_size; + + /* Relic Chunkys have: type, subtype, version, data size, name size, then + * name (optional) and data. But format has fixed chunks so we'll simplify a bit. */ + + /* DATA-FBIF (file info) */ + chunk_size = read_u32le(offset + 0x0c, sf); + name_size = read_u32le(offset + 0x10, sf); + offset += 0x14 + name_size + chunk_size; + + /* FOLD-FDA (folder of chunks) */ + if (read_u32be(offset + 0x04, sf) != 0x46444120) /* "FDA " */ + goto fail; + offset += 0x14; + + /* DATA-INFO (header) */ + if (read_u32be(offset + 0x04, sf) != 0x494E464F) /* "INFO" */ + goto fail; + chunk_size = read_u32le(offset + 0x0c, sf); + name_size = read_u32le(offset + 0x10, sf); + offset += 0x14 + name_size; + + channel_count = read_s32le(offset + 0x00, sf); + /* 0x04: bps */ + bitrate = read_s32le(offset + 0x08, sf); + sample_rate = read_s32le(offset + 0x0c, sf); + /* 0x10: loop start? (always 0) */ + /* 0x14: loop end? (always -1) */ + /* 0x18: loop offset? (always 0) */ + loop_flag = 0; /* never set? */ + offset += chunk_size; + + /* DATA-DATA (data) */ + if (read_u32be(offset + 0x04, sf) != 0x44415441) /* "DATA" */ + goto fail; + chunk_size = read_u32le(offset + 0x0c, sf); + name_size = read_u32le(offset + 0x10, sf); + offset += 0x14 + name_size; + + data_size = read_s32le(offset + 0x00, sf); + + start_offset = offset + 0x04; + num_samples = data_size / channel_count / (bitrate / 8) * 512; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_FDA; + vgmstream->sample_rate = 44100; /* fixed output */ + vgmstream->num_samples = num_samples; + + vgmstream->codec_data = init_relic(channel_count, bitrate, sample_rate); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_RELIC; + vgmstream->layout_type = layout_none; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c b/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c index 348f99753..67f008500 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c @@ -163,9 +163,9 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { /* disable some jingles, it's even possible one jingle (StingerA Var1) to not have loops * and next one (StingerA Var2) do [Sonic Boom Fire & Ice (3DS)] */ - full_loop = fsb5.loop_start == 0 && fsb5.loop_end + 20 >= fsb5.num_samples; /* around ~15 samples less */ - /* a few longer Sonic songs shouldn't repeat, may add if other games need it */ - is_small = 0; //fsb5.num_samples < 20 * fsb5.sample_rate; + full_loop = fsb5.loop_start == 0 && fsb5.loop_end + 1152 >= fsb5.num_samples; /* around ~15 samples less, ~1000 for MPEG */ + /* a few longer Sonic songs shouldn't repeat */ + is_small = 1; //fsb5.num_samples < 20 * fsb5.sample_rate; /* wrong values in some files [Pac-Man CE2 Plus (Switch) pce2p_bgm_ajurika_*.fsb] */ ajurika_loops = fsb5.loop_start == 0x3c && fsb5.loop_end == 0x007F007F && diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fwse.c b/Frameworks/vgmstream/vgmstream/src/meta/fwse.c new file mode 100644 index 000000000..b37da34d3 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/fwse.c @@ -0,0 +1,62 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* FWSE - Capcom's MT Framework V1.x sound file */ +VGMSTREAM *init_vgmstream_fwse(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + uint32_t version, /*data_size,*/ buffer_offset; + int channel_count, loop_flag, sample_count, sample_rate, loop_start, loop_end; + + + /* checks*/ + /* .fwse: header id, no apparent extension in bigfiles */ + if (!check_extensions(streamFile,"fwse")) + goto fail; + + if ((read_32bitBE(0x00,streamFile)) != 0x46575345) /* "FWSE" */ + goto fail; + + version = read_32bitLE(0x04,streamFile); + /* v2: Resident Evil 5 (PC) + * v3: Ace Attourney: Dual Destinies (Android) */ + if (version != 2 && version != 3) + goto fail; + + //data_size = read_32bitLE(0x08,streamFile); + buffer_offset = read_32bitLE(0x0C,streamFile); + channel_count = read_32bitLE(0x10,streamFile); + + if (channel_count > 2) + goto fail; + + sample_count = read_32bitLE(0x14,streamFile); + sample_rate = read_32bitLE(0x18,streamFile); + loop_start = read_32bitLE(0x20,streamFile); + loop_end = read_32bitLE(0x24,streamFile); + loop_flag = (loop_start != -1); + /* 0x28: some kind of setup? */ + /* 0x40: some kind of seek table with ADPCM hist/steps? */ + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_FWSE; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = sample_count; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + vgmstream->coding_type = coding_MTF_IMA; + vgmstream->layout_type = layout_none; + + + if (!vgmstream_open_stream(vgmstream,streamFile,buffer_offset)) + goto fail; + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h index e5e23eec6..3f3ff76ff 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h @@ -319,7 +319,7 @@ static const hcakey_info hcakey_list[] = { {0xA86BF72B4C852CA7}, // A86BF72B4C852CA7 / 12136065386219383975 /* Arca Last (Android) */ - {612310807}, // 00000000247F1F17 / 12136065386219383975 + {612310807}, // 00000000247F1F17 /* ArkResona (Android) */ {564321654321}, // 0000008364311631 @@ -327,6 +327,9 @@ static const hcakey_info hcakey_list[] = { /* Kemono Friends 3 (Android) */ {3315495188}, // 00000000C59E7114 + /* Inazuma Eleven SD (Android) */ + {0xC436E03737D55B5F}, // C436E03737D55B5F / 14138734607940803423 + /* Dragalia Lost (iOS/Android) */ {2967411924141, subkeys_dgl, sizeof(subkeys_dgl) / sizeof(subkeys_dgl[0]) }, // 000002B2E7889CAD diff --git a/Frameworks/vgmstream/vgmstream/src/meta/jstm_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/jstm_streamfile.h index e28e5a6bb..1a7289399 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/jstm_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/jstm_streamfile.h @@ -1,51 +1,36 @@ -#ifndef _JSTM_STREAMFILE_H_ -#define _JSTM_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - off_t start_offset; -} jstm_decryption_data; - -static size_t jstm_decryption_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, jstm_decryption_data* data) { - size_t bytes_read; - int i; - - bytes_read = streamfile->read(streamfile, dest, offset, length); - - /* decrypt data (xor) */ - for (i = 0; i < bytes_read; i++) { - if (offset+i >= data->start_offset) { - dest[i] = dest[i] ^ 0x5A; - } - } - - return bytes_read; -} - -static STREAMFILE* setup_jstm_streamfile(STREAMFILE *streamFile, off_t start_offset) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - jstm_decryption_data io_data = {0}; - size_t io_data_size = sizeof(jstm_decryption_data); - - /* setup decryption */ - io_data.start_offset = start_offset; - - - /* setup custom streamfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, jstm_decryption_read,NULL); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -#endif /* _JSTM_STREAMFILE_H_ */ +#ifndef _JSTM_STREAMFILE_H_ +#define _JSTM_STREAMFILE_H_ +#include "../streamfile.h" + + +typedef struct { + off_t start; +} jstm_io_data; + +static size_t jstm_io_read(STREAMFILE *sf, uint8_t *dest, off_t offset, size_t length, jstm_io_data* data) { + int i; + size_t bytes = read_streamfile(dest, offset, length, sf); + + /* decrypt data (xor) */ + for (i = 0; i < bytes; i++) { + if (offset + i >= data->start) { + dest[i] ^= 0x5A; + } + } + + return bytes; +} + +/* decrypts JSTM stream */ +static STREAMFILE* setup_jstm_streamfile(STREAMFILE *sf, off_t start) { + STREAMFILE *new_sf = NULL; + jstm_io_data io_data = {0}; + + io_data.start = start; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_streamfile_f(new_sf, &io_data, sizeof(jstm_io_data), jstm_io_read, NULL); + return new_sf; +} + +#endif /* _JSTM_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/kma9_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/kma9_streamfile.h index 34f21dde3..691c9cbd8 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/kma9_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/kma9_streamfile.h @@ -1,148 +1,21 @@ -#ifndef _KM9_STREAMFILE_H_ -#define _KM9_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - /* config */ - int stream_number; - int stream_count; - size_t interleave_size; - off_t stream_offset; - size_t stream_size; - - /* state */ - off_t logical_offset; /* offset that corresponds to physical_offset */ - off_t physical_offset; /* actual file offset */ - - size_t skip_size; /* size to skip from a block start to reach data start */ - size_t data_size; /* logical size of the block */ - - size_t logical_size; -} kma9_io_data; - - -static size_t kma9_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, kma9_io_data* data) { - size_t total_read = 0; - - /* ignore bad reads */ - if (offset < 0 || offset > data->logical_size) { - return 0; - } - - /* previous offset: re-start as we can't map logical<>physical offsets - * (kinda slow as it trashes buffers, but shouldn't happen often) */ - if (offset < data->logical_offset) { - data->logical_offset = 0x00; - data->physical_offset = data->stream_offset; - data->data_size = 0; - } - - /* read blocks, one at a time */ - while (length > 0) { - - /* ignore EOF */ - if (data->logical_offset >= data->logical_size) { - break; - } - - /* process new block */ - if (data->data_size == 0) { - data->skip_size = data->interleave_size * data->stream_number; - data->data_size = data->interleave_size; - } - - /* move to next block */ - if (offset >= data->logical_offset + data->data_size) { - data->physical_offset += data->interleave_size*data->stream_count; - data->logical_offset += data->data_size; - data->data_size = 0; - continue; - } - - /* read data */ - { - size_t bytes_consumed, bytes_done, to_read; - - bytes_consumed = offset - data->logical_offset; - - to_read = data->data_size - bytes_consumed; - if (to_read > length) - to_read = length; - bytes_done = read_streamfile(dest, data->physical_offset + data->skip_size + bytes_consumed, to_read, streamfile); - - offset += bytes_done; - total_read += bytes_done; - length -= bytes_done; - dest += bytes_done; - - if (bytes_done != to_read || bytes_done == 0) { - break; /* error/EOF */ - } - } - - } - - return total_read; -} - -static size_t kma9_io_size(STREAMFILE *streamfile, kma9_io_data* data) { - off_t physical_offset = data->stream_offset; - off_t max_physical_offset = get_streamfile_size(streamfile); - size_t logical_size = 0; - - if (data->logical_size) - return data->logical_size; - - /* get size of the logical stream */ - while (physical_offset < max_physical_offset) { - logical_size += data->interleave_size; - physical_offset += data->interleave_size*data->stream_count; - } - - if (logical_size > max_physical_offset) - return 0; - if (logical_size != data->stream_size) - return 0; - data->logical_size = logical_size; - return data->logical_size; -} - - -/* Prepares custom IO for KMA9, which interleaves ATRAC9 frames */ -static STREAMFILE* setup_kma9_streamfile(STREAMFILE *streamFile, off_t stream_offset, size_t stream_size, size_t interleave_size, int stream_number, int stream_count) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - kma9_io_data io_data = {0}; - size_t io_data_size = sizeof(kma9_io_data); - - io_data.stream_number = stream_number; - io_data.stream_count = stream_count; - io_data.stream_offset = stream_offset; - io_data.stream_size = stream_size; - io_data.interleave_size = interleave_size; - io_data.physical_offset = stream_offset; - io_data.logical_size = kma9_io_size(streamFile, &io_data); /* force init */ - - if (io_data.logical_size == 0) { - VGM_LOG("KMA9: wrong logical size\n"); - goto fail; - } - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, kma9_io_read,kma9_io_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - - -#endif /* _KM9_STREAMFILE_H_ */ +#ifndef _KM9_STREAMFILE_H_ +#define _KM9_STREAMFILE_H_ +#include "deblock_streamfile.h" + +/* Deinterleaves KMA9 streams */ +static STREAMFILE* setup_kma9_streamfile(STREAMFILE *sf, off_t stream_offset, size_t stream_size, size_t interleave_size, int stream_number, int stream_count) { + STREAMFILE *new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.stream_start = stream_offset; + cfg.logical_size = stream_size; + cfg.chunk_size = interleave_size; + cfg.step_start = stream_number; + cfg.step_count = stream_count; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + return new_sf; +} + +#endif /* _KM9_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ktss.c b/Frameworks/vgmstream/vgmstream/src/meta/ktss.c index 8b66a8f1f..56b93fba1 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ktss.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ktss.c @@ -3,52 +3,59 @@ VGMSTREAM * init_vgmstream_ktss(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - int loop_flag, channel_count; + int loop_flag, channel_count, sample_rate; int8_t version, num_layers, codec_id; - int32_t loop_length, coef_start_offset, coef_spacing; + int32_t num_samples, loop_start, loop_length, coef_offset, coef_spacing; off_t start_offset; size_t data_size, skip = 0; if (!check_extensions(streamFile, "kns,ktss")) goto fail; - if (read_32bitBE(0, streamFile) != 0x4B545353) /* "KTSS" */ + if (read_32bitBE(0x00, streamFile) != 0x4B545353) /* "KTSS" */ goto fail; + /* 0x04: data size */ codec_id = read_8bit(0x20, streamFile); - loop_length = read_32bitLE(0x38, streamFile); - loop_flag = loop_length > 0; + /* 0x01: null, part of codec? */ + version = read_8bit(0x22, streamFile); + /* 0x03: same as version? */ + start_offset = read_32bitLE(0x24, streamFile) + 0x20; // A layered stream/track model seems to be used in Hyrule Warriors (Switch). // It's also present in other Koei Tecmo KNS but the channel count was always // explicitly defined in the 0x29 byte and the number of layers was set to 1. // Here, 10 channel files are set up with 2 channels in 5 layers. // Super hacky on KT's part and ours to implement but it works. - num_layers = read_8bit(0x28, streamFile); - + num_layers = read_8bit(0x28, streamFile); channel_count = read_8bit(0x29, streamFile) * num_layers; + sample_rate = read_32bitLE(0x2c, streamFile); + + num_samples = read_32bitLE(0x30, streamFile); + loop_start = read_32bitLE(0x34, streamFile); + loop_length = read_32bitLE(0x38, streamFile); + loop_flag = loop_length > 0; + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count, loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = read_32bitLE(0x2c, streamFile); - vgmstream->num_samples = read_32bitLE(0x30, streamFile); - vgmstream->loop_start_sample = read_32bitLE(0x34, streamFile); - vgmstream->loop_end_sample = vgmstream->loop_start_sample + loop_length; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_start + loop_length; vgmstream->meta_type = meta_KTSS; - start_offset = read_32bitLE(0x24, streamFile) + 0x20; switch (codec_id) { - case 0x2: /* DSP ADPCM - Hyrule Warriors, Fire Emblem Warriors, and other Koei Tecmo games */ + case 0x2: /* DSP ADPCM - Hyrule Warriors, Fire Emblem Warriors */ /* check type details */ - version = read_8bit(0x22, streamFile); if (version == 1) { - coef_start_offset = 0x40; + coef_offset = 0x40; coef_spacing = 0x2e; } - else if (version == 3) { // Fire Emblem Warriors (Switch) - coef_start_offset = 0x5c; + else if (version == 3) { /* Fire Emblem Warriors (Switch) */ + coef_offset = 0x5c; coef_spacing = 0x60; } else @@ -57,18 +64,24 @@ VGMSTREAM * init_vgmstream_ktss(STREAMFILE *streamFile) { vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x8; - dsp_read_coefs_le(vgmstream, streamFile, coef_start_offset, coef_spacing); + dsp_read_coefs_le(vgmstream, streamFile, coef_offset, coef_spacing); break; #ifdef VGM_USE_FFMPEG case 0x9: { /* Opus - Dead or Alive Xtreme 3: Scarlet, Fire Emblem: Three Houses */ opus_config cfg = {0}; + start_offset = read_32bitLE(0x40, streamFile); /* after seek table, if any */ data_size = read_32bitLE(0x44, streamFile); + /* 0x48: seek table start (0 if no seek table) */ + /* 0x4c: number of frames */ - cfg.channels = vgmstream->channels; + /* 0x50: frame size, or 0 if VBR */ + /* 0x52: samples per frame */ + /* 0x54: sample rate */ cfg.skip = read_32bitLE(0x58, streamFile); - cfg.sample_rate = vgmstream->sample_rate; /* also at 0x54 */ + cfg.sample_rate = vgmstream->sample_rate; + cfg.channels = vgmstream->channels; /* this info seems always included even for stereo streams */ if (vgmstream->channels <= 8) { @@ -80,6 +93,10 @@ VGMSTREAM * init_vgmstream_ktss(STREAMFILE *streamFile) { } } + /* 0x60: null/reserved */ + /* 0x70: seek table (0x02 * frames) if VBR */ + /* later games use VBR frames, hence the seek table [Warriors Orochi 4 Ultimate DLC (Switch)] */ + vgmstream->codec_data = init_ffmpeg_switch_opus_config(streamFile, start_offset, data_size, &cfg); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/kwb.c b/Frameworks/vgmstream/vgmstream/src/meta/kwb.c new file mode 100644 index 000000000..6a9c14387 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/kwb.c @@ -0,0 +1,384 @@ +#include "meta.h" +#include "../coding/coding.h" + +typedef enum { PCM16, MSADPCM, DSP, AT9 } kwb_codec; + +typedef struct { + int total_subsongs; + int target_subsong; + kwb_codec codec; + + int channels; + int sample_rate; + int32_t num_samples; + int32_t loop_start; + int32_t loop_end; + int loop_flag; + int block_size; + + off_t stream_offset; + size_t stream_size; + + off_t dsp_offset; + //off_t name_offset; +} kwb_header; + +static int parse_kwb(kwb_header* kwb, STREAMFILE* sf_h, STREAMFILE* sf_b); + + +/* KWB - WaveBank from Koei games */ +VGMSTREAM * init_vgmstream_kwb(STREAMFILE* sf) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE *sf_h = NULL, *sf_b = NULL; + kwb_header kwb = {0}; + int target_subsong = sf->stream_index; + + + /* checks */ + /* .wbd+wbh: common [Bladestorm Nightmare (PC)] + * .wb2+wh2: newer [Nights of Azure 2 (PC)] + * .sed: mixed header+data [Dissidia NT (PC)] */ + if (!check_extensions(sf, "wbd,wb2,sed")) + goto fail; + + + /* open companion header */ + if (check_extensions(sf, "wbd")) { + sf_h = open_streamfile_by_ext(sf, "wbh"); + sf_b = sf; + } + else if (check_extensions(sf, "wb2")) { + sf_h = open_streamfile_by_ext(sf, "wh2"); + sf_b = sf; + } + else if (check_extensions(sf, "sed")) { + sf_h = sf; + sf_b = sf; + } + else { + goto fail; + } + + if (sf_h == NULL || sf_b == NULL) + goto fail; + + if (target_subsong == 0) target_subsong = 1; + kwb.target_subsong = target_subsong; + + if (!parse_kwb(&kwb, sf_h, sf_b)) + goto fail; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(kwb.channels, kwb.loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_KWB; + vgmstream->sample_rate = kwb.sample_rate; + vgmstream->num_samples = kwb.num_samples; + vgmstream->stream_size = kwb.stream_size; + vgmstream->num_streams = kwb.total_subsongs; + + switch(kwb.codec) { + case PCM16: /* PCM */ + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + break; + + case MSADPCM: + vgmstream->coding_type = coding_MSADPCM; + vgmstream->layout_type = layout_none; + vgmstream->frame_size = kwb.block_size; + break; + + case DSP: + if (kwb.channels > 1) goto fail; + vgmstream->coding_type = coding_NGC_DSP; /* subinterleave? */ + vgmstream->layout_type = layout_interleave; + vgmstream->layout_type = 0x08; + dsp_read_coefs_le(vgmstream, sf_h, kwb.dsp_offset + 0x1c, 0x60); + dsp_read_hist_le (vgmstream, sf_h, kwb.dsp_offset + 0x40, 0x60); + break; + +#ifdef VGM_USE_ATRAC9 + case AT9: { + atrac9_config cfg = {0}; + + { + size_t extra_size = read_u32le(kwb.stream_offset + 0x00, sf_b); + uint32_t config_data = read_u32be(kwb.stream_offset + 0x04, sf_b); + /* 0x0c: encoder delay? */ + /* 0x0e: encoder padding? */ + /* 0x10: samples per frame */ + /* 0x12: frame size */ + + cfg.channels = vgmstream->channels; + cfg.config_data = config_data; + + kwb.stream_offset += extra_size; + kwb.stream_size -= extra_size; + } + + vgmstream->codec_data = init_atrac9(&cfg); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_ATRAC9; + vgmstream->layout_type = layout_none; + + //TODO: check encoder delay + vgmstream->num_samples = atrac9_bytes_to_samples_cfg(kwb.stream_size, cfg.config_data); + break; + } +#endif + + + default: + goto fail; + } + + if (sf_h != sf) close_streamfile(sf_h); + + if (!vgmstream_open_stream(vgmstream, sf_b, kwb.stream_offset)) + goto fail; + return vgmstream; + +fail: + if (sf_h != sf) close_streamfile(sf_h); + close_vgmstream(vgmstream); + return NULL; +} + +static int parse_type_kwb2(kwb_header* kwb, off_t offset, STREAMFILE* sf_h) { + int i, j, sounds; + + /* 00: KWB2/KWBN id */ + /* 04: always 0x3200? */ + sounds = read_u16le(offset + 0x06, sf_h); + /* 08: ? */ + /* 0c: 1.0? */ + /* 10: null or 1 */ + /* 14: offset to HDDB table (from type), can be null */ + + /* offset table to entries */ + for (i = 0; i < sounds; i++) { + off_t sound_offset = read_u32le(offset + 0x18 + i*0x04, sf_h); + int subsounds, subsound_start, subsound_size; + uint16_t version; + + + if (sound_offset == 0) /* common... */ + continue; + sound_offset += offset; + + /* sound entry */ + version = read_u16le(sound_offset + 0x00, sf_h); + /* 00: version? */ + /* 02: 0x2b or 0x32 */ + subsounds = read_u8(sound_offset + 0x03, sf_h); + /* 03: subsounds? */ + /* others: unknown or null */ + + /* unsure but seems to work, maybe upper byte only */ + if (version < 0xc000) { + subsound_start = 0x2c; + subsound_size = 0x48; + } + else { + subsound_start = read_u16le(sound_offset + 0x2c, sf_h); + subsound_size = read_u16le(sound_offset + 0x2e, sf_h); + } + + subsound_start = sound_offset + subsound_start; + + for (j = 0; j < subsounds; j++) { + off_t subsound_offset; + uint8_t codec; + + kwb->total_subsongs++; + if (kwb->total_subsongs != kwb->target_subsong) + continue; + subsound_offset = subsound_start + j*subsound_size; + + kwb->sample_rate = read_u16le(subsound_offset + 0x00, sf_h); + codec = read_u8 (subsound_offset + 0x02, sf_h); + kwb->channels = read_u8 (subsound_offset + 0x03, sf_h); + kwb->block_size = read_u16le(subsound_offset + 0x04, sf_h); + /* 0x06: samples per frame in MSADPCM? */ + /* 0x08: some id? (not always) */ + kwb->num_samples = read_u32le(subsound_offset + 0x0c, sf_h); + kwb->stream_offset = read_u32le(subsound_offset + 0x10, sf_h); + kwb->stream_size = read_u32le(subsound_offset + 0x14, sf_h); + /* when size > 0x48 */ + /* 0x48: subsound entry size */ + /* rest: reserved per codec? (usually null) */ + + switch(codec) { + case 0x00: + kwb->codec = PCM16; + break; + case 0x10: + kwb->codec = MSADPCM; + break; + case 0x90: + kwb->codec = DSP; + kwb->dsp_offset = subsound_offset + 0x4c; + break; + default: + VGM_LOG("KWB2: unknown codec\n"); + goto fail; + } + } + } + + //TODO: read names + /* HDDB table (optional and not too common) + 00 HDDB id + 04 1? + 08: 20? start? + 0c: 14? start? + 10: size + 14: name table start + 20: name offsets? + then some subtable + then name table (null terminated and one after other) + */ + + if (kwb->target_subsong < 0 || kwb->target_subsong > kwb->total_subsongs || kwb->total_subsongs < 1) goto fail; + + return 1; +fail: + return 0; +} + +static int parse_type_k4hd(kwb_header* kwb, off_t offset, STREAMFILE* sf_h) { + off_t ppva_offset, header_offset; + int entries; + size_t entry_size; + + + /* a format mimicking PSVita's hd4+bd4 format */ + /* 00 K4HD id */ + /* 04 chunk size */ + /* 08: ? */ + /* 0c: ? */ + /* 10: PPPG offset ('program'? cues?) */ + /* 14: PPTN offset ('tone'? sounds?) */ + /* 18: PPVA offset ('VAG'? waves) */ + ppva_offset = read_u16le(offset + 0x18, sf_h); + ppva_offset += offset; + + /* PPVA table: */ + if (read_u32be(ppva_offset + 0x00, sf_h) != 0x50505641) /* "PPVA" */ + goto fail; + + entry_size = read_u32le(ppva_offset + 0x08, sf_h); /* */ + /* 0x0c: -1? */ + /* 0x10: 0? */ + entries = read_u32le(ppva_offset + 0x14, sf_h) + 1; + /* 0x18: -1? */ + /* 0x1c: -1? */ + + if (entry_size != 0x1c) { + VGM_LOG("K4HD: unknown entry size\n"); + goto fail; + } + + kwb->total_subsongs = entries; + if (kwb->target_subsong < 0 || kwb->target_subsong > kwb->total_subsongs || kwb->total_subsongs < 1) goto fail; + + header_offset = ppva_offset + 0x20 + (kwb->target_subsong-1) * entry_size; + + kwb->stream_offset = read_u32le(header_offset + 0x00, sf_h); + kwb->sample_rate = read_u32le(header_offset + 0x04, sf_h); + kwb->stream_size = read_u32le(header_offset + 0x08, sf_h); + /* 0x0c: -1? loop? */ + if (read_u32le(header_offset + 0x10, sf_h) != 2) { /* codec? */ + VGM_LOG("K4HD: unknown codec\n"); + goto fail; + } + /* 0x14: loop start? */ + /* 0x18: loop end? */ + + kwb->codec = AT9; + kwb->channels = 1; /* always, devs use dual subsongs to fake stereo (like as hd3+bd3) */ + + + return 1; +fail: + return 0; +} + +static int parse_type_sdsd(kwb_header* kwb, off_t offset, STREAMFILE* sf_h) { + /* has Vers, Head, Prog, Smpl sections (like Sony VABs) + unknown codec, blocked with some common start, variable sized */ + return 0; +} + +static int parse_kwb(kwb_header* kwb, STREAMFILE* sf_h, STREAMFILE* sf_b) { + off_t head_offset, body_offset, start; + uint32_t type; + + + if (read_u32be(0x00, sf_h) == 0x57484431) { /* "WHD1" */ + /* container of wbh+wbd */ + /* 0x04: fixed value? */ + /* 0x08: version? */ + start = read_u32le(0x0c, sf_h); + /* 0x10: file size */ + /* 0x14: subfiles? */ + /* 0x18: subfiles? */ + /* 0x1c: null */ + /* 0x20: some size? */ + /* 0x24: some size? */ + + head_offset = read_u32le(start + 0x00, sf_h); + body_offset = read_u32le(start + 0x04, sf_h); + /* 0x10: head size */ + /* 0x14: body size */ + } + else { + /* dual file */ + head_offset = 0x00; + body_offset = 0x00; + } + + if (read_u32be(head_offset + 0x00, sf_h) != 0x5F484257 || /* "_HBW" */ + read_u32be(head_offset + 0x04, sf_h) != 0x30303030) /* "0000" */ + goto fail; + if (read_u32be(body_offset + 0x00, sf_b) != 0x5F444257 || /* "_DBW" */ + read_u32be(body_offset + 0x04, sf_b) != 0x30303030) /* "0000" */ + goto fail; + /* 0x08: head/body size */ + + head_offset += 0x0c; + body_offset += 0x0c; + + /* format has multiple bank subtypes that are quite different from each other */ + type = read_u32be(head_offset + 0x00, sf_h); + switch(type) { + case 0x4B574232: /* "KWB2" (PC) */ + case 0x4B57424E: /* "KWBN" (Switch) */ + if (!parse_type_kwb2(kwb, head_offset, sf_h)) + goto fail; + break; + + case 0x4B344844: /* "K4HD" (PS4/Vita) */ + if (!parse_type_k4hd(kwb, head_offset, sf_h)) + goto fail; + break; + + case 0x53447364: /* "SDsd" (PS3?) */ + if (!parse_type_sdsd(kwb, head_offset, sf_h)) + goto fail; + break; + + default: + goto fail; + } + + kwb->stream_offset += body_offset; + + return 1; +fail: + return 0; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/lrmd.c b/Frameworks/vgmstream/vgmstream/src/meta/lrmd.c new file mode 100644 index 000000000..e53e9bfed --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/lrmd.c @@ -0,0 +1,145 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "lrmd_streamfile.h" + +/* LRMD - Sony/SCEI's format (Loco Roco Music Data?) [LocoRoco 2 (PSP), LocoRoco: Midnight Carnival (PSP)] */ +VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * sf_h = NULL, *temp_sf = NULL; + off_t stream_offset, section1_offset, section2_offset, basename_offset, subname_offset; + size_t stream_size, layer_chunk; + int loop_flag, channel_count, sample_rate, layers; + int32_t num_samples, loop_start, loop_end; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + if (!check_extensions(sf, "lrmb")) + goto fail; + sf_h = open_streamfile_by_ext(sf, "lrmh"); + if (!sf_h) goto fail; + + + if (read_u32be(0x00, sf_h) != 0x4C524D44) /* "LRMD" */ + goto fail; + /* 0x00: version 1? */ + /* 0x08: header size */ + /* 0x0c: body size */ + + if (read_u32be(0x10, sf_h) != 0x52455144) /* "REQD" */ + goto fail; + /* 0x14: chunk size */ + /* 0x18: null? */ + /* 0x1c: 1? */ + /* 0x20: null */ + basename_offset = read_u32le(0x24, sf_h); + if (read_u16le(0x28, sf_h) != 0x4000) { /* pitch? */ + VGM_LOG("LRMD: unknown value\n"); + goto fail; + } + layer_chunk = read_u16le(0x2a, sf_h); + num_samples = read_u32le(0x2c, sf_h); + /* 0x30: null? */ + /* 0x34: data size for all layers */ + layers = read_u32le(0x38, sf_h); + section1_offset = read_u32le(0x3c, sf_h); + /* 0x40: seek/layer? table entries */ + /* 0x44: seek/layer? table offset */ + /* 0x48: section2 flag */ + section2_offset = read_u32le(0x4c, sf_h); + /* 0x40: section3 flag */ + /* 0x44: section3 (unknown) */ + + total_subsongs = layers; + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + /* data is divided into N interleaved layers sharing config, so it could be implemented as + * layered, but since they have names it's worth showing as subsongs */ + + /* section1: layer config */ + section1_offset += (target_subsong - 1) * 0x18; + /* 0x00: null */ + subname_offset = read_u32le(section1_offset + 0x04, sf_h); + /* 0x08: unk */ + /* 0x0c: flags? */ + /* 0x10: null? */ + /* 0x14: null? */ + sample_rate = 44100; + channel_count = 2; + + /* section2: loops */ + /* 0x00: offset to "loop" name */ + if (section2_offset > 0) { + loop_end = read_u32le(section2_offset + 0x04, sf_h); + loop_start = read_u32le(section2_offset + 0x08, sf_h); + loop_flag = read_u32le(section2_offset + 0x0c, sf_h); + } + else { + loop_end = 0; + loop_start = 0; + loop_flag = 0; + } + + + //TODO: LR2's muihouse has buggy 7-layer interleave + /* data de-interleave */ + temp_sf = setup_lrmd_streamfile(sf, layer_chunk / layers, (target_subsong-1), total_subsongs); + if (!temp_sf) goto fail; + + stream_offset = 0x00; + stream_size = get_streamfile_size(temp_sf); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_LRMD; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + vgmstream->stream_size = stream_size; + vgmstream->num_streams = total_subsongs; + +#ifdef VGM_USE_FFMPEG + { + int block_align, encoder_delay; + + block_align = layer_chunk / layers; + encoder_delay = 1024; /* assumed */ + vgmstream->num_samples -= encoder_delay; + + vgmstream->codec_data = init_ffmpeg_atrac3_raw(temp_sf, stream_offset, stream_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_align, encoder_delay); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + } +#else + goto fail; +#endif + + /* name custom main + layer name */ + { + int name_len = read_string(vgmstream->stream_name, STREAM_NAME_SIZE - 1, basename_offset, sf_h); + + strcat(vgmstream->stream_name, "/"); + name_len++; + + read_string(vgmstream->stream_name + name_len, STREAM_NAME_SIZE - name_len, subname_offset, sf_h); + } + + if (!vgmstream_open_stream(vgmstream, temp_sf, stream_offset)) + goto fail; + + close_streamfile(sf_h); + close_streamfile(temp_sf); + return vgmstream; + +fail: + close_streamfile(sf_h); + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/lrmd_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/lrmd_streamfile.h new file mode 100644 index 000000000..f46ce4c46 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/lrmd_streamfile.h @@ -0,0 +1,19 @@ +#ifndef _LRMD_STREAMFILE_H_ +#define _LRMD_STREAMFILE_H_ +#include "deblock_streamfile.h" + +/* Deinterleaves LRMD streams */ +static STREAMFILE* setup_lrmd_streamfile(STREAMFILE *sf, size_t interleave_size, int stream_number, int stream_count) { + STREAMFILE *new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.chunk_size = interleave_size; + cfg.step_start = stream_number; + cfg.step_count = stream_count; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + return new_sf; +} + +#endif /* _LRMD_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index e9f5aa757..a78e2feda 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -877,4 +877,14 @@ VGMSTREAM* init_vgmstream_xma_ue3(STREAMFILE *sf); VGMSTREAM* init_vgmstream_csb(STREAMFILE *sf); +VGMSTREAM *init_vgmstream_fwse(STREAMFILE *streamFile); + +VGMSTREAM* init_vgmstream_fda(STREAMFILE *sf); + +VGMSTREAM * init_vgmstream_tgc(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_kwb(STREAMFILE* sf); + +VGMSTREAM * init_vgmstream_lrmd(STREAMFILE* sf); + #endif /*_META_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/msf.c b/Frameworks/vgmstream/vgmstream/src/meta/msf.c index e99475985..9dc94fd56 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/msf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/msf.c @@ -12,9 +12,10 @@ VGMSTREAM * init_vgmstream_msf(STREAMFILE *streamFile) { /* checks */ /* .msf: standard + * .msa: Sonic & Sega All-Stars Racing (PS3) * .at3: Silent Hill HD Collection (PS3) * .mp3: Darkstalkers Resurrection (PS3) */ - if (!check_extensions(streamFile,"msf,at3,mp3")) + if (!check_extensions(streamFile,"msf,msa,at3,mp3")) goto fail; /* check header "MSF" + version-char, usually: @@ -65,8 +66,8 @@ VGMSTREAM * init_vgmstream_msf(STREAMFILE *streamFile) { case 0x00: /* PCM (Big Endian) */ case 0x01: { /* PCM (Little Endian) [Smash Cars (PS3)] */ vgmstream->coding_type = codec==0 ? coding_PCM16BE : coding_PCM16LE; - vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave; - vgmstream->interleave_block_size = 2; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count,16); if (loop_flag){ @@ -125,28 +126,7 @@ VGMSTREAM * init_vgmstream_msf(STREAMFILE *streamFile) { break; } #endif -#if defined(VGM_USE_FFMPEG) && !defined(VGM_USE_MPEG) - case 0x07: { /* MPEG (CBR LAME MP3) [Dengeki Bunko Fighting Climax (PS3)] */ - ffmpeg_codec_data *ffmpeg_data = NULL; - - ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset, streamFile->get_size(streamFile) ); - if ( !ffmpeg_data ) goto fail; - vgmstream->codec_data = ffmpeg_data; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - - vgmstream->num_samples = (int64_t)data_size * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; - if (loop_flag) { - vgmstream->loop_start_sample = (int64_t)loop_start * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; - vgmstream->loop_end_sample = (int64_t)loop_end * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; - /* loops are always aligned to CBR frame beginnings */ - } - - /* encoder delay varies between 1152 (1f), 528, 576, etc; probably not actually skipped */ - break; - } -#endif -#ifdef VGM_USE_MPEG +#if defined(VGM_USE_MPEG) case 0x07: { /* MPEG (CBR LAME MP3) [Dengeki Bunko Fighting Climax (PS3)] */ mpeg_codec_data *mpeg_data = NULL; @@ -162,6 +142,27 @@ VGMSTREAM * init_vgmstream_msf(STREAMFILE *streamFile) { /* loops are always aligned to CBR frame beginnings */ } + /* encoder delay varies between 1152 (1f), 528, 576, etc; probably not actually skipped */ + break; + } +#elif defined(VGM_USE_FFMPEG) + case 0x07: + { /* MPEG (CBR LAME MP3) [Dengeki Bunko Fighting Climax (PS3)] */ + ffmpeg_codec_data *ffmpeg_data = NULL; + + ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset, streamFile->get_size(streamFile)); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = (int64_t)data_size * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; + if (loop_flag) { + vgmstream->loop_start_sample = (int64_t)loop_start * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; + vgmstream->loop_end_sample = (int64_t)loop_end * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; + /* loops are always aligned to CBR frame beginnings */ + } + /* encoder delay varies between 1152 (1f), 528, 576, etc; probably not actually skipped */ break; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mzrt_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/mzrt_streamfile.h index f9483d37c..e187c68e4 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mzrt_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/mzrt_streamfile.h @@ -1,124 +1,27 @@ -#ifndef _MZRT_STREAMFILE_H_ -#define _MZRT_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - /* config */ - off_t stream_offset; - size_t stream_size; - - /* state */ - off_t logical_offset; /* fake offset */ - off_t physical_offset; /* actual offset */ - size_t block_size; /* current size */ - size_t skip_size; /* size from block start to reach data */ - size_t data_size; /* usable size in a block */ - - size_t logical_size; -} mzrt_io_data; - - -static size_t mzrt_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, mzrt_io_data* data) { - size_t total_read = 0; - - - /* re-start when previous offset (can't map logical<>physical offsets) */ - if (data->logical_offset < 0 || offset < data->logical_offset) { - data->physical_offset = data->stream_offset; - data->logical_offset = 0x00; - data->data_size = 0; - } - - /* read blocks */ - while (length > 0) { - - /* ignore EOF */ - if (offset < 0 || data->physical_offset >= data->stream_offset + data->stream_size) { - break; - } - - /* process new block */ - if (data->data_size == 0) { - /* 0x00: samples in this block */ - data->data_size = read_32bitBE(data->stream_offset + 0x04, streamfile); - data->skip_size = 0x08; - data->block_size = data->skip_size + data->data_size; - } - - /* move to next block */ - if (data->data_size == 0 || offset >= data->logical_offset + data->data_size) { - data->physical_offset += data->block_size; - data->logical_offset += data->data_size; - data->data_size = 0; - continue; - } - - /* read data */ - { - size_t bytes_consumed, bytes_done, to_read; - - bytes_consumed = offset - data->logical_offset; - to_read = data->data_size - bytes_consumed; - if (to_read > length) - to_read = length; - bytes_done = read_streamfile(dest, data->physical_offset + data->skip_size + bytes_consumed, to_read, streamfile); - - total_read += bytes_done; - dest += bytes_done; - offset += bytes_done; - length -= bytes_done; - - if (bytes_done != to_read || bytes_done == 0) { - break; /* error/EOF */ - } - } - } - - return total_read; -} - -static size_t mzrt_io_size(STREAMFILE *streamfile, mzrt_io_data* data) { - uint8_t buf[1]; - - if (data->logical_size) - return data->logical_size; - - /* force a fake read at max offset, to get max logical_offset (will be reset next read) */ - mzrt_io_read(streamfile, buf, 0x7FFFFFFF, 1, data); - data->logical_size = data->logical_offset; - - return data->logical_size; -} - -/* Handles deinterleaving of MZRT blocked streams */ -static STREAMFILE* setup_mzrt_streamfile(STREAMFILE *streamFile, off_t stream_offset) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - mzrt_io_data io_data = {0}; - size_t io_data_size = sizeof(mzrt_io_data); - - io_data.stream_offset = stream_offset; - io_data.stream_size = get_streamfile_size(streamFile) - stream_offset; - io_data.logical_offset = -1; /* force phys offset reset */ - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(new_streamFile, &io_data,io_data_size, mzrt_io_read,mzrt_io_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_buffer_streamfile(new_streamFile,0); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -#endif /* _MZRT_STREAMFILE_H_ */ +#ifndef _MZRT_STREAMFILE_H_ +#define _MZRT_STREAMFILE_H_ +#include "deblock_streamfile.h" + +static void block_callback(STREAMFILE *sf, deblock_io_data *data) { + /* 0x00: samples in this block */ + data->data_size = read_s32be(data->physical_offset + 0x04, sf); + data->skip_size = 0x08; + data->block_size = data->skip_size + data->data_size; +} + +/* Deblocks MZRT streams */ +static STREAMFILE* setup_mzrt_streamfile(STREAMFILE *sf, off_t stream_offset) { + STREAMFILE *new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.stream_start = stream_offset; + cfg.block_callback = block_callback; + + /* setup sf */ + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + //new_sf = open_buffer_streamfile_f(new_sf, 0); + return new_sf; +} + +#endif /* _MZRT_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nxap.c b/Frameworks/vgmstream/vgmstream/src/meta/nxap.c index d87be6638..cd434cb65 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nxap.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nxap.c @@ -1,49 +1,48 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* NXAP - Nex Entertainment header [Time Crisis 4 (PS3), Time Crisis Razing Storm (PS3)] */ -VGMSTREAM * init_vgmstream_nxap(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - - - /* checks */ - if (!check_extensions(streamFile, "adp")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x4E584150) /* "NXAP" */ - goto fail; - if (read_32bitLE(0x14,streamFile) != 0x40 || /* expected frame size? */ - read_32bitLE(0x18,streamFile) != 0x40) /* expected interleave? */ - goto fail; - - start_offset = read_32bitLE(0x04,streamFile); - channel_count = read_32bitLE(0x0c,streamFile); - loop_flag = 0; //(read_32bitLE(0x24,streamFile) > 0); //todo - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitLE(0x10, streamFile); - vgmstream->num_samples = read_32bitLE(0x1c,streamFile) * (0x40-0x04)*2 / channel_count; /* number of frames */ - - /* unknown loop format, also 0x28/2c values seem related */ - //vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile) * (0x40-0x04)*2 / channel_count; - //vgmstream->loop_end_sample = read_32bitLE(0x24,streamFile) * (0x40-0x04)*2 / channel_count; - //vgmstream->loop_end_sample = vgmstream->loop_start_sample + vgmstream->loop_end_sample; - - vgmstream->meta_type = meta_NXAP; - vgmstream->coding_type = coding_NXAP; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x40; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* NXAP - Nex Entertainment header [Time Crisis 4 (PS3), Time Crisis Razing Storm (PS3)] */ +VGMSTREAM * init_vgmstream_nxap(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count; + + + /* checks */ + if (!check_extensions(streamFile, "adp")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x4E584150) /* "NXAP" */ + goto fail; + if (read_32bitLE(0x14,streamFile) != 0x40 || /* expected frame size? */ + read_32bitLE(0x18,streamFile) != 0x40) /* expected interleave? */ + goto fail; + + start_offset = read_32bitLE(0x04,streamFile); + channel_count = read_32bitLE(0x0c,streamFile); + loop_flag = (read_32bitLE(0x24,streamFile) > 0); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitLE(0x10, streamFile); + vgmstream->num_samples = read_32bitLE(0x1c,streamFile) * (0x40-0x04)*2 / channel_count; /* number of frames */ + + /* in channel blocks, also 0x28/2c values seem related */ + vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile) * (0x40-0x04)*2; + vgmstream->loop_end_sample = read_32bitLE(0x24,streamFile) * (0x40-0x04)*2; + + vgmstream->meta_type = meta_NXAP; + vgmstream->coding_type = coding_NXAP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x40; + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogg_opus.c b/Frameworks/vgmstream/vgmstream/src/meta/ogg_opus.c index dd1d34096..521b8acc5 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ogg_opus.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogg_opus.c @@ -1,174 +1,182 @@ -#include "meta.h" -#include "../coding/coding.h" - - -static int get_ogg_page_size(STREAMFILE *streamFile, off_t page_offset, off_t *out_data_offset, size_t *out_page_size); -static int ogg_get_num_samples(STREAMFILE *streamFile, off_t start_offset); - -/* Ogg Opus - standard Opus with optional looping comments [The Pillars of Earth (PC), Monster Boy and the Cursed Kingdom (Switch)] */ -VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset, data_offset = 0; - size_t page_size = 0; - int loop_flag, channel_count, original_rate; - int loop_start = 0, loop_end = 0; - - - /* checks */ - /* .opus: standard, .lopus: fake extension for plugins - * .ogg: less common, .logg: same */ - if (!check_extensions(streamFile, "opus,lopus,ogg,logg")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x4F676753) /* "OggS" */ - goto fail; - /* see: https://tools.ietf.org/html/rfc7845.html */ - - start_offset = 0x00; - - /* parse 1st page: opus head */ - if (!get_ogg_page_size(streamFile, start_offset, &data_offset, &page_size)) - goto fail; - if (read_32bitBE(data_offset+0x00,streamFile) != 0x4F707573 && /* "Opus" */ - read_32bitBE(data_offset+0x04,streamFile) != 0x48656164) /* "Head" */ - goto fail; - /* 0x01: version 1, fixed */ - channel_count = read_8bit(data_offset+0x09,streamFile); - /* 0x0A: skip samples */ - original_rate = read_32bitLE(data_offset+0x0c,streamFile); - /* 0x10: gain */ - /* 0x12: mapping family */ - - /* parse 2nd page: opus tags (also mandatory) */ - if (!get_ogg_page_size(streamFile, start_offset+page_size, &data_offset, &page_size)) - goto fail; - if (read_32bitBE(data_offset+0x00,streamFile) != 0x4F707573 && /* "Opus" */ - read_32bitBE(data_offset+0x04,streamFile) != 0x54616773) /* "Tags" */ - goto fail; - - loop_flag = 0; - { - char user_comment[1024+1]; - off_t offset; - int vendor_size, comment_count, user_comment_size, user_comment_max; - int i; - int has_encoder_options = 0, has_title = 0; - - vendor_size = read_32bitLE(data_offset+0x08,streamFile); - comment_count = read_32bitLE(data_offset+0x0c+vendor_size,streamFile); - - /* parse comments */ - offset = data_offset + 0x0c + vendor_size + 0x04; - for (i = 0; i < comment_count; i++) { - user_comment_size = read_32bitLE(offset+0x00,streamFile); - user_comment_max = user_comment_size > 1024 ? 1024 : user_comment_size; - read_string(user_comment,user_comment_max+1, offset+0x04,streamFile); - - - /* parse loop strings */ - if (strstr(user_comment,"LOOP_START=")==user_comment) { /* Monster Boy and the Cursed Kingdom (Switch) */ - loop_start = atol(strrchr(user_comment,'=')+1); - loop_flag = (loop_start >= 0); - } - else if (strstr(user_comment,"LOOP_END=")==user_comment) { /* LOOP_START pair */ - loop_end = atol(strrchr(user_comment,'=')+1); - } - else if (strstr(user_comment,"ENCODER_OPTIONS=")==user_comment) { /* for detection */ - has_encoder_options = 1; - } - else if (strstr(user_comment,"TITLE=")==user_comment) { /* for detection */ - has_title = 1; - } - - - //;VGM_LOG("OggOpus: user_comment=%s\n", user_comment); - offset += 0x04 + user_comment_size; - } - - - /* Monster Boy has loop points for 44100hz (what), but Opus is resampled so - * they must be adjusted (with extra checks just in case). */ - if (loop_flag && original_rate < 48000 && has_encoder_options && has_title) { - float modifier = 48000.0f / (float)original_rate; - loop_start = loop_start * modifier; - loop_end = loop_end * modifier; - } - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_OGG_OPUS; - vgmstream->sample_rate = 48000; /* Opus always resamples to this */ - vgmstream->num_samples = ogg_get_num_samples(streamFile, 0x00); - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; - -#ifdef VGM_USE_FFMPEG - { - vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset, get_streamfile_size(streamFile)); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - vgmstream->channel_layout = ffmpeg_get_channel_layout(vgmstream->codec_data); - /* FFmpeg+libopus handles skip samples ok, FFmpeg+opus doesn't */ - } -#else - goto fail; -#endif - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} - - -/* parse OggS's bizarre segment table */ -static int get_ogg_page_size(STREAMFILE *streamFile, off_t page_offset, off_t *out_data_offset, size_t *out_page_size) { - uint8_t segments; - size_t page_size = 0; - int i; - - if (read_32bitBE(page_offset+0x00,streamFile) != 0x4F676753) /* "OggS" */ - goto fail; - - /* read all segment sizes */ - segments = (uint8_t)read_8bit(page_offset+0x1a, streamFile); - for (i = 0; i < segments; i++) { - page_size += (uint8_t)read_8bit(page_offset + 0x1b + i, streamFile); - } - page_size += 0x1b + segments; - - if (out_data_offset) *out_data_offset = page_offset + 0x1b + segments; - if (out_page_size) *out_page_size = page_size; - return 1; -fail: - return 0; -} - -/* Ogg doesn't have num_samples info, must manually seek+read last granule - * (Xiph is insistent this is the One True Way). */ -static int ogg_get_num_samples(STREAMFILE *streamFile, off_t start_offset) { - uint32_t expected_id = 0x4F676753; - off_t offset = get_streamfile_size(streamFile) - 0x04-0x01-0x01-0x08-0x04-0x04-0x04; - - //todo better buffer reads (Ogg page max is 0xFFFF) - //lame way to force buffer, assuming it's around that - read_32bitBE(offset - 0x4000, streamFile); - - while (offset >= start_offset) { - uint32_t current_id = read_32bitBE(offset, streamFile); - if (current_id == expected_id) { /* if more checks are needed last page starts with 0x0004 */ - return read_32bitLE(offset+0x04+0x01+0x01, streamFile); /* get last granule = total samples (64b but whatevs) */ - } - - offset--; - } - - return 0; -} +#include "meta.h" +#include "../coding/coding.h" + + +static int get_ogg_page_size(STREAMFILE *streamFile, off_t page_offset, off_t *out_data_offset, size_t *out_page_size); +static int ogg_get_num_samples(STREAMFILE *streamFile, off_t start_offset); + +/* Ogg Opus - standard Opus with optional looping comments [The Pillars of Earth (PC), Monster Boy and the Cursed Kingdom (Switch)] */ +VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, data_offset = 0; + size_t page_size = 0; + int loop_flag, channel_count, original_rate; + int loop_start = 0, loop_end = 0; + + + /* checks */ + /* .opus: standard, .lopus: fake extension for plugins + * .ogg: less common, .logg: same + * .bgm: Utawarerumono: Mask of Truth (PC) */ + if (!check_extensions(streamFile, "opus,lopus,ogg,logg,bgm")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x4F676753) /* "OggS" */ + goto fail; + /* see: https://tools.ietf.org/html/rfc7845.html */ + + start_offset = 0x00; + + /* parse 1st page: opus head */ + if (!get_ogg_page_size(streamFile, start_offset, &data_offset, &page_size)) + goto fail; + if (read_32bitBE(data_offset+0x00,streamFile) != 0x4F707573 && /* "Opus" */ + read_32bitBE(data_offset+0x04,streamFile) != 0x48656164) /* "Head" */ + goto fail; + /* 0x01: version 1, fixed */ + channel_count = read_8bit(data_offset+0x09,streamFile); + /* 0x0A: skip samples */ + original_rate = read_32bitLE(data_offset+0x0c,streamFile); + /* 0x10: gain */ + /* 0x12: mapping family */ + + /* parse 2nd page: opus tags (also mandatory) */ + if (!get_ogg_page_size(streamFile, start_offset+page_size, &data_offset, &page_size)) + goto fail; + if (read_32bitBE(data_offset+0x00,streamFile) != 0x4F707573 && /* "Opus" */ + read_32bitBE(data_offset+0x04,streamFile) != 0x54616773) /* "Tags" */ + goto fail; + + loop_flag = 0; + { + char user_comment[1024+1]; + off_t offset; + int vendor_size, comment_count, user_comment_size, user_comment_max; + int i; + int has_encoder_options = 0, has_title = 0; + + vendor_size = read_32bitLE(data_offset+0x08,streamFile); + comment_count = read_32bitLE(data_offset+0x0c+vendor_size,streamFile); + + /* parse comments */ + offset = data_offset + 0x0c + vendor_size + 0x04; + for (i = 0; i < comment_count; i++) { + user_comment_size = read_32bitLE(offset+0x00,streamFile); + user_comment_max = user_comment_size > 1024 ? 1024 : user_comment_size; + read_string(user_comment,user_comment_max+1, offset+0x04,streamFile); + + + /* parse loop strings */ + if (strstr(user_comment,"LOOP_START=")==user_comment) { /* Monster Boy and the Cursed Kingdom (Switch) */ + loop_start = atol(strrchr(user_comment,'=')+1); + loop_flag = (loop_start >= 0); + } + else if (strstr(user_comment,"LOOP_END=")==user_comment) { /* LOOP_START pair */ + loop_end = atol(strrchr(user_comment,'=')+1); + } + else if (strstr(user_comment,"ENCODER_OPTIONS=")==user_comment) { /* for detection */ + has_encoder_options = 1; + } + else if (strstr(user_comment,"TITLE=")==user_comment) { /* for detection */ + has_title = 1; + } + else if (strstr(user_comment,"LoopStart=")==user_comment) { /* Utawarerumono: Mask of Truth (PC) */ + loop_start= atol(strrchr(user_comment,'=')+1); + loop_flag = (loop_start >= 0); + } + else if (strstr(user_comment,"LoopEnd=")==user_comment) { /* LoopStart pair */ + loop_end = atol(strrchr(user_comment,'=')+1); + } + + + //;VGM_LOG("OggOpus: user_comment=%s\n", user_comment); + offset += 0x04 + user_comment_size; + } + + + /* Monster Boy has loop points for 44100hz (what), but Opus is resampled so + * they must be adjusted (with extra checks just in case). */ + if (loop_flag && original_rate < 48000 && has_encoder_options && has_title) { + float modifier = 48000.0f / (float)original_rate; + loop_start = loop_start * modifier; + loop_end = loop_end * modifier; + } + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_OGG_OPUS; + vgmstream->sample_rate = 48000; /* Opus always resamples to this */ + vgmstream->num_samples = ogg_get_num_samples(streamFile, 0x00); + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + +#ifdef VGM_USE_FFMPEG + { + vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset, get_streamfile_size(streamFile)); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + vgmstream->channel_layout = ffmpeg_get_channel_layout(vgmstream->codec_data); + /* FFmpeg+libopus handles skip samples ok, FFmpeg+opus doesn't */ + } +#else + goto fail; +#endif + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + + +/* parse OggS's bizarre segment table */ +static int get_ogg_page_size(STREAMFILE *streamFile, off_t page_offset, off_t *out_data_offset, size_t *out_page_size) { + uint8_t segments; + size_t page_size = 0; + int i; + + if (read_32bitBE(page_offset+0x00,streamFile) != 0x4F676753) /* "OggS" */ + goto fail; + + /* read all segment sizes */ + segments = (uint8_t)read_8bit(page_offset+0x1a, streamFile); + for (i = 0; i < segments; i++) { + page_size += (uint8_t)read_8bit(page_offset + 0x1b + i, streamFile); + } + page_size += 0x1b + segments; + + if (out_data_offset) *out_data_offset = page_offset + 0x1b + segments; + if (out_page_size) *out_page_size = page_size; + return 1; +fail: + return 0; +} + +/* Ogg doesn't have num_samples info, must manually seek+read last granule + * (Xiph is insistent this is the One True Way). */ +static int ogg_get_num_samples(STREAMFILE *streamFile, off_t start_offset) { + uint32_t expected_id = 0x4F676753; + off_t offset = get_streamfile_size(streamFile) - 0x04-0x01-0x01-0x08-0x04-0x04-0x04; + + //todo better buffer reads (Ogg page max is 0xFFFF) + //lame way to force buffer, assuming it's around that + read_32bitBE(offset - 0x4000, streamFile); + + while (offset >= start_offset) { + uint32_t current_id = read_32bitBE(offset, streamFile); + if (current_id == expected_id) { /* if more checks are needed last page starts with 0x0004 */ + return read_32bitLE(offset+0x04+0x01+0x01, streamFile); /* get last granule = total samples (64b but whatevs) */ + } + + offset--; + } + + return 0; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_streamfile.h index ca55dcdaa..c7b1e1056 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_streamfile.h @@ -1,76 +1,59 @@ -#ifndef _OGG_VORBIS_STREAMFILE_H_ -#define _OGG_VORBIS_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - int is_encrypted; - uint8_t key[0x100]; - size_t key_len; - int is_nibble_swap; - int is_header_swap; -} ogg_vorbis_io_config_data; - -typedef struct { - /* config */ - ogg_vorbis_io_config_data cfg; -} ogg_vorbis_io_data; - - -static size_t ogg_vorbis_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, ogg_vorbis_io_data* data) { - size_t bytes_read; - int i; - static const uint8_t header_swap[4] = { 0x4F,0x67,0x67,0x53 }; /* "OggS" */ - static const size_t header_size = 0x04; - - bytes_read = streamfile->read(streamfile, dest, offset, length); - - if (data->cfg.is_encrypted) { - for (i = 0; i < bytes_read; i++) { - if (data->cfg.is_header_swap && (offset + i) < header_size) { - dest[i] = header_swap[(offset + i) % header_size]; - } - else { - if (!data->cfg.key_len && !data->cfg.is_nibble_swap) - break; - if (data->cfg.key_len) - dest[i] ^= data->cfg.key[(offset + i) % data->cfg.key_len]; - if (data->cfg.is_nibble_swap) - dest[i] = ((dest[i] << 4) & 0xf0) | ((dest[i] >> 4) & 0x0f); - } - } - } - - return bytes_read; -} - -//todo maybe use generic decryption streamfile -static STREAMFILE* setup_ogg_vorbis_streamfile(STREAMFILE *streamFile, ogg_vorbis_io_config_data cfg) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - ogg_vorbis_io_data io_data = {0}; - size_t io_data_size = sizeof(ogg_vorbis_io_data); - - /* setup decryption */ - io_data.cfg = cfg; /* memcpy */ - - - /* setup custom streamfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - //todo extension .ogg? - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, ogg_vorbis_io_read,NULL); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - - -#endif /* _OGG_VORBIS_STREAMFILE_H_ */ +#ifndef _OGG_VORBIS_STREAMFILE_H_ +#define _OGG_VORBIS_STREAMFILE_H_ +#include "../streamfile.h" + + +typedef struct { + int is_encrypted; + uint8_t key[0x100]; + size_t key_len; + int is_nibble_swap; + int is_header_swap; +} ogg_vorbis_io_config_data; + +typedef struct { + /* config */ + ogg_vorbis_io_config_data cfg; +} ogg_vorbis_io_data; + + +static size_t ogg_vorbis_io_read(STREAMFILE *sf, uint8_t *dest, off_t offset, size_t length, ogg_vorbis_io_data* data) { + static const uint8_t header_swap[4] = { 0x4F,0x67,0x67,0x53 }; /* "OggS" */ + static const size_t header_size = 0x04; + int i; + size_t bytes = read_streamfile(dest, offset, length, sf); + + if (data->cfg.is_encrypted) { + for (i = 0; i < bytes; i++) { + if (data->cfg.is_header_swap && (offset + i) < header_size) { + dest[i] = header_swap[(offset + i) % header_size]; + } + else { + if (!data->cfg.key_len && !data->cfg.is_nibble_swap) + break; + if (data->cfg.key_len) + dest[i] ^= data->cfg.key[(offset + i) % data->cfg.key_len]; + if (data->cfg.is_nibble_swap) + dest[i] = ((dest[i] << 4) & 0xf0) | ((dest[i] >> 4) & 0x0f); + } + } + } + + return bytes; +} + +//todo maybe use generic decryption streamfile +/* Decrypts Ogg Vorbis streams */ +static STREAMFILE* setup_ogg_vorbis_streamfile(STREAMFILE *sf, ogg_vorbis_io_config_data cfg) { + STREAMFILE *new_sf = NULL; + ogg_vorbis_io_data io_data = {0}; + + io_data.cfg = cfg; /* memcpy */ + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_streamfile_f(new_sf, &io_data, sizeof(ogg_vorbis_io_data), ogg_vorbis_io_read, NULL); + //new_sf = open_fakename_streamfile_f(new_sf, NULL, "ogg"); //todo? + return new_sf; +} + +#endif /* _OGG_VORBIS_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/opus.c b/Frameworks/vgmstream/vgmstream/src/meta/opus.c index 5007e758b..5213a0655 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/opus.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/opus.c @@ -1,439 +1,454 @@ -#include "meta.h" -#include "../coding/coding.h" -#include "../layout/layout.h" -#include "opus_interleave_streamfile.h" - -/* Nintendo OPUS - from Switch games, including header variations (not the same as Ogg Opus) */ - -static VGMSTREAM * init_vgmstream_opus(STREAMFILE *streamFile, meta_t meta_type, off_t offset, int32_t num_samples, int32_t loop_start, int32_t loop_end) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag = 0, channel_count; - off_t data_offset, multichannel_offset = 0; - size_t data_size, skip = 0; - - - if ((uint32_t)read_32bitLE(offset + 0x00,streamFile) != 0x80000001) - goto fail; - - channel_count = read_8bit(offset + 0x09, streamFile); - /* 0x0a: packet size if CBR, 0 if VBR */ - data_offset = offset + read_32bitLE(offset + 0x10, streamFile); - skip = read_16bitLE(offset + 0x1c, streamFile); - /* 0x1e: ? (seen in Lego Movie 2 (Switch)) */ - - /* recent >2ch info [Clannad (Switch)] */ - if ((uint32_t)read_32bitLE(offset + 0x20, streamFile) == 0x80000005) { - multichannel_offset = offset + 0x20; - } - - if ((uint32_t)read_32bitLE(data_offset, streamFile) != 0x80000004) - goto fail; - - data_size = read_32bitLE(data_offset + 0x04, streamFile); - - start_offset = data_offset + 0x08; - loop_flag = (loop_end > 0); /* -1 when not set */ - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_type; - vgmstream->sample_rate = read_32bitLE(offset + 0x0c,streamFile); - if (vgmstream->sample_rate == 16000) - vgmstream->sample_rate = 48000; // Grandia HD Collection contains a false sample_rate in header - vgmstream->num_samples = num_samples; - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; - vgmstream->stream_size = data_size; /* to avoid inflated sizes from fake OggS IO */ - -#ifdef VGM_USE_FFMPEG - { - opus_config cfg = {0}; - - cfg.channels = vgmstream->channels; - cfg.skip = skip; - cfg.sample_rate = vgmstream->sample_rate; - - if (multichannel_offset && vgmstream->channels <= 8) { - int i; - cfg.stream_count = read_8bit(multichannel_offset + 0x08,streamFile); - cfg.coupled_count = read_8bit(multichannel_offset + 0x09,streamFile); - for (i = 0; i < vgmstream->channels; i++) { - cfg.channel_mapping[i] = read_8bit(multichannel_offset + 0x0a + i,streamFile); - } - } - - vgmstream->codec_data = init_ffmpeg_switch_opus_config(streamFile, start_offset,data_size, &cfg); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - vgmstream->channel_layout = ffmpeg_get_channel_layout(vgmstream->codec_data); - - if (vgmstream->num_samples == 0) { - vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, streamFile) - skip; - } - } -#else - goto fail; -#endif - - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} - - -/* standard Switch Opus, Nintendo header + raw data (generated by opus_test.c?) [Lego City Undercover (Switch)] */ -VGMSTREAM * init_vgmstream_opus_std(STREAMFILE *streamFile) { - STREAMFILE * PSIFile = NULL; - off_t offset; - int num_samples, loop_start, loop_end; - - /* checks */ - if (!check_extensions(streamFile,"opus,lopus")) - goto fail; - - offset = 0x00; - - /* BlazBlue: Cross Tag Battle (Switch) PSI Metadata for corresponding Opus */ - /* Maybe future Arc System Works games will use this too? */ - PSIFile = open_streamfile_by_ext(streamFile, "psi"); - if (PSIFile) { - num_samples = read_32bitLE(0x8C, PSIFile); - loop_start = read_32bitLE(0x84, PSIFile); - loop_end = read_32bitLE(0x88, PSIFile); - close_streamfile(PSIFile); - } - else { - num_samples = 0; - loop_start = 0; - loop_end = 0; - } - - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); -fail: - return NULL; -} - -/* Nippon1 variation [Disgaea 5 (Switch)] */ -VGMSTREAM * init_vgmstream_opus_n1(STREAMFILE *streamFile) { - off_t offset; - int num_samples, loop_start, loop_end; - - /* checks */ - if ( !check_extensions(streamFile,"opus,lopus")) - goto fail; - if (!((read_32bitBE(0x04,streamFile) == 0x00000000 && read_32bitBE(0x0c,streamFile) == 0x00000000) || - (read_32bitBE(0x04,streamFile) == 0xFFFFFFFF && read_32bitBE(0x0c,streamFile) == 0xFFFFFFFF))) - goto fail; - - offset = 0x10; - num_samples = 0; - loop_start = read_32bitLE(0x00,streamFile); - loop_end = read_32bitLE(0x08,streamFile); - - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); -fail: - return NULL; -} - -/* Capcom variation [Ultra Street Fighter II (Switch), Resident Evil: Revelations (Switch)] */ -VGMSTREAM * init_vgmstream_opus_capcom(STREAMFILE *streamFile) { - VGMSTREAM *vgmstream = NULL; - off_t offset; - int num_samples, loop_start, loop_end; - int channel_count; - - /* checks */ - if ( !check_extensions(streamFile,"opus,lopus")) - goto fail; - - channel_count = read_32bitLE(0x04,streamFile); - if (channel_count != 1 && channel_count != 2 && channel_count != 6) - goto fail; /* unknown stream layout */ - - num_samples = read_32bitLE(0x00,streamFile); - /* 0x04: channels, >2 uses interleaved streams (2ch+2ch+2ch) */ - loop_start = read_32bitLE(0x08,streamFile); - loop_end = read_32bitLE(0x0c,streamFile); - /* 0x10: frame size (with extra data) */ - /* 0x14: extra chunk count */ - /* 0x18: null */ - offset = read_32bitLE(0x1c,streamFile); - /* 0x20-8: config? (0x0077C102 04000000 E107070C) */ - /* 0x2c: some size? */ - /* 0x30+: extra chunks (0x00: 0x7f, 0x04: num_sample), alt loop starts/regions? */ - - if (channel_count == 6) { - /* 2ch multistream hacky-hacks, don't try this at home. We'll end up with: - * main vgmstream > N vgmstream layers > substream IO deinterleaver > opus meta > Opus IO transmogrifier (phew) */ - layered_layout_data* data = NULL; - int layers = channel_count / 2; - int i; - int loop_flag = (loop_end > 0); - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->layout_type = layout_layered; - - /* init layout */ - data = init_layout_layered(layers); - if (!data) goto fail; - vgmstream->layout_data = data; - - /* open each layer subfile */ - for (i = 0; i < layers; i++) { - STREAMFILE* temp_streamFile = setup_opus_interleave_streamfile(streamFile, offset+0x28*i, layers); - if (!temp_streamFile) goto fail; - - data->layers[i] = init_vgmstream_opus(temp_streamFile, meta_OPUS, 0x00, num_samples,loop_start,loop_end); - close_streamfile(temp_streamFile); - if (!data->layers[i]) goto fail; - } - - /* setup layered VGMSTREAMs */ - if (!setup_layout_layered(data)) - goto fail; - - vgmstream->sample_rate = data->layers[0]->sample_rate; - vgmstream->num_samples = data->layers[0]->num_samples; - vgmstream->loop_start_sample = data->layers[0]->loop_start_sample; - vgmstream->loop_end_sample = data->layers[0]->loop_end_sample; - vgmstream->meta_type = meta_OPUS; - vgmstream->coding_type = data->layers[0]->coding_type; - - return vgmstream; - } - else { - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); - } - - -fail: - close_vgmstream(vgmstream); - return NULL; -} - -/* Procyon Studio variation [Xenoblade Chronicles 2 (Switch)] */ -VGMSTREAM * init_vgmstream_opus_nop(STREAMFILE *streamFile) { - off_t offset; - int num_samples, loop_start = 0, loop_end = 0, loop_flag; - - /* checks */ - if (!check_extensions(streamFile,"nop")) - goto fail; - if (read_32bitBE(0x00, streamFile) != 0x73616466 || /* "sadf" */ - read_32bitBE(0x08, streamFile) != 0x6f707573) /* "opus" */ - goto fail; - - offset = read_32bitLE(0x1c, streamFile); - num_samples = read_32bitLE(0x28, streamFile); - loop_flag = read_8bit(0x19, streamFile); - if (loop_flag) { - loop_start = read_32bitLE(0x2c, streamFile); - loop_end = read_32bitLE(0x30, streamFile); - } - - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); -fail: - return NULL; -} - -/* Shin'en variation [Fast RMX (Switch)] */ -VGMSTREAM * init_vgmstream_opus_shinen(STREAMFILE *streamFile) { - off_t offset = 0; - int num_samples, loop_start, loop_end; - - /* checks */ - if ( !check_extensions(streamFile,"opus,lopus")) - goto fail; - if (read_32bitBE(0x08,streamFile) != 0x01000080) - goto fail; - - offset = 0x08; - num_samples = 0; - loop_start = read_32bitLE(0x00,streamFile); - loop_end = read_32bitLE(0x04,streamFile); /* 0 if no loop */ - - if (loop_start > loop_end) - goto fail; /* just in case */ - - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); -fail: - return NULL; -} - -/* Bandai Namco Opus (found in NUS3Banks) [Taiko no Tatsujin: Nintendo Switch Version!] */ -VGMSTREAM * init_vgmstream_opus_nus3(STREAMFILE *streamFile) { - off_t offset = 0; - int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; - - /* checks */ - /* .opus: header ID (they only exist inside .nus3bank) */ - if (!check_extensions(streamFile, "opus,lopus")) - goto fail; - if (read_32bitBE(0x00, streamFile) != 0x4F505553) /* "OPUS" */ - goto fail; - - /* Here's an interesting quirk, OPUS header contains big endian values - while the Nintendo Opus header and data that follows remain little endian as usual */ - offset = read_32bitBE(0x20, streamFile); - num_samples = read_32bitBE(0x08, streamFile); - - /* Check if there's a loop end value to determine loop_flag*/ - loop_flag = read_32bitBE(0x18, streamFile); - if (loop_flag) { - loop_start = read_32bitBE(0x14, streamFile); - loop_end = read_32bitBE(0x18, streamFile); - } - - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); -fail: - return NULL; -} - -/* Nippon Ichi SPS wrapper (non-segmented) [Ys VIII: Lacrimosa of Dana (Switch)] */ -VGMSTREAM * init_vgmstream_opus_sps_n1(STREAMFILE *streamFile) { - off_t offset; - int num_samples, loop_start = 0, loop_end = 0, loop_flag; - - /* checks */ - /* .sps: Labyrinth of Refrain - Coven of Dusk (Switch) - * .nlsd: Disgaea Refine (Switch), Ys VIII (Switch) */ - if (!check_extensions(streamFile, "sps,nlsd")) - goto fail; - if (read_32bitBE(0x00, streamFile) != 0x09000000) /* file type (see other N1 SPS) */ - goto fail; - - offset = 0x1C; - num_samples = read_32bitLE(0x0C, streamFile); - - /* sections num_samples (remnant of segmented opus_sps_n1): - * 0x10: intro, 0x14: loop, 0x18: end (all must add up to num_samples) */ - loop_flag = read_32bitLE(0x18, streamFile); /* with loop disabled only loop section has samples */ - if (loop_flag) { - loop_start = read_32bitLE(0x10, streamFile); - loop_end = loop_start + read_32bitLE(0x14, streamFile); - } - - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); -fail: - return NULL; -} - -/* AQUASTYLE wrapper [Touhou Genso Wanderer -Reloaded- (Switch)] */ -VGMSTREAM * init_vgmstream_opus_opusx(STREAMFILE *streamFile) { - off_t offset; - int num_samples, loop_start = 0, loop_end = 0; - float modifier; - - /* checks */ - if (!check_extensions(streamFile, "opusx")) - goto fail; - if (read_32bitBE(0x00, streamFile) != 0x4F505553) /* "OPUS" */ - goto fail; - - offset = 0x10; - /* values are for the original 44100 files, but Opus resamples to 48000 */ - modifier = 48000.0f / 44100.0f; - num_samples = 0;//read_32bitLE(0x04, streamFile) * modifier; /* better use calc'd num_samples */ - loop_start = read_32bitLE(0x08, streamFile) * modifier; - loop_end = read_32bitLE(0x0c, streamFile) * modifier; - - /* resampling calcs are slighly off and may to over num_samples, but by removing delay seems ok */ - if (loop_start >= 120) { - loop_start -= 128; - loop_end -= 128; - } - else { - loop_end = 0; - } - - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); -fail: - return NULL; -} - -/* Prototype variation [Clannad (Switch)] */ -VGMSTREAM * init_vgmstream_opus_prototype(STREAMFILE *streamFile) { - off_t offset = 0; - int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; - - /* checks */ - if (!check_extensions(streamFile, "opus,lopus")) - goto fail; - if (read_32bitBE(0x00, streamFile) != 0x4F505553 || /* "OPUS" */ - read_32bitBE(0x18, streamFile) != 0x01000080) - goto fail; - - offset = 0x18; - num_samples = read_32bitLE(0x08, streamFile); - - /* Check if there's a loop end value to determine loop_flag*/ - loop_flag = read_32bitLE(0x10, streamFile); - if (loop_flag) { - loop_start = read_32bitLE(0x0C, streamFile); - loop_end = read_32bitLE(0x10, streamFile); - } - - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); -fail: - return NULL; -} - -/* Edelweiss variation [Astebreed (Switch)] */ -VGMSTREAM * init_vgmstream_opus_opusnx(STREAMFILE *streamFile) { - off_t offset = 0; - int num_samples = 0, loop_start = 0, loop_end = 0; - - /* checks */ - if (!check_extensions(streamFile, "opus,lopus")) - goto fail; - if (read_64bitBE(0x00, streamFile) != 0x4F5055534E580000) /* "OPUSNX\0\0" */ - goto fail; - - offset = 0x10; - num_samples = 0; //read_32bitLE(0x08, streamFile); /* samples with encoder delay */ - if (read_32bitLE(0x0c, streamFile) != 0) - goto fail; - - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); -fail: - return NULL; -} - -/* Square Enix variation [Dragon Quest I-III (Switch)] */ -VGMSTREAM * init_vgmstream_opus_sqex(STREAMFILE *streamFile) { - off_t offset = 0; - int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; - - /* checks */ - if (!check_extensions(streamFile, "opus,lopus")) - goto fail; - if (read_64bitBE(0x00, streamFile) != 0x0100000002000000) - goto fail; - - offset = read_32bitLE(0x0C, streamFile); - num_samples = read_32bitLE(0x1C, streamFile); - - /* Check if there's a loop end value to determine loop_flag*/ - loop_flag = read_32bitLE(0x18, streamFile); - if (loop_flag) { - loop_start = read_32bitLE(0x14, streamFile); - loop_end = read_32bitLE(0x18, streamFile); - } - - return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); -fail: - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" +#include "../layout/layout.h" +#include "opus_interleave_streamfile.h" + +/* Nintendo OPUS - from Switch games, including header variations (not the same as Ogg Opus) */ + +static VGMSTREAM * init_vgmstream_opus(STREAMFILE *streamFile, meta_t meta_type, off_t offset, int32_t num_samples, int32_t loop_start, int32_t loop_end) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag = 0, channel_count; + off_t data_offset, multichannel_offset = 0; + size_t data_size, skip = 0; + + + if ((uint32_t)read_32bitLE(offset + 0x00,streamFile) != 0x80000001) + goto fail; + + channel_count = read_8bit(offset + 0x09, streamFile); + /* 0x0a: packet size if CBR, 0 if VBR */ + data_offset = offset + read_32bitLE(offset + 0x10, streamFile); + skip = read_16bitLE(offset + 0x1c, streamFile); + /* 0x1e: ? (seen in Lego Movie 2 (Switch)) */ + + /* recent >2ch info [Clannad (Switch)] */ + if ((uint32_t)read_32bitLE(offset + 0x20, streamFile) == 0x80000005) { + multichannel_offset = offset + 0x20; + } + + if ((uint32_t)read_32bitLE(data_offset, streamFile) != 0x80000004) + goto fail; + + data_size = read_32bitLE(data_offset + 0x04, streamFile); + + start_offset = data_offset + 0x08; + loop_flag = (loop_end > 0); /* -1 when not set */ + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_type; + vgmstream->sample_rate = read_32bitLE(offset + 0x0c,streamFile); + if (vgmstream->sample_rate == 16000) + vgmstream->sample_rate = 48000; // Grandia HD Collection contains a false sample_rate in header + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + vgmstream->stream_size = data_size; /* to avoid inflated sizes from fake OggS IO */ + +#ifdef VGM_USE_FFMPEG + { + opus_config cfg = {0}; + + cfg.channels = vgmstream->channels; + cfg.skip = skip; + cfg.sample_rate = vgmstream->sample_rate; + + if (multichannel_offset && vgmstream->channels <= 8) { + int i; + cfg.stream_count = read_8bit(multichannel_offset + 0x08,streamFile); + cfg.coupled_count = read_8bit(multichannel_offset + 0x09,streamFile); + for (i = 0; i < vgmstream->channels; i++) { + cfg.channel_mapping[i] = read_8bit(multichannel_offset + 0x0a + i,streamFile); + } + } + + vgmstream->codec_data = init_ffmpeg_switch_opus_config(streamFile, start_offset,data_size, &cfg); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + vgmstream->channel_layout = ffmpeg_get_channel_layout(vgmstream->codec_data); + + if (vgmstream->num_samples == 0) { + vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, streamFile) - skip; + } + } +#else + goto fail; +#endif + + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + + +/* standard Switch Opus, Nintendo header + raw data (generated by opus_test.c?) [Lego City Undercover (Switch)] */ +VGMSTREAM * init_vgmstream_opus_std(STREAMFILE *streamFile) { + STREAMFILE * PSIFile = NULL; + off_t offset; + int num_samples, loop_start, loop_end; + + /* checks */ + if (!check_extensions(streamFile,"opus,lopus")) + goto fail; + + offset = 0x00; + + /* BlazBlue: Cross Tag Battle (Switch) PSI Metadata for corresponding Opus */ + /* Maybe future Arc System Works games will use this too? */ + PSIFile = open_streamfile_by_ext(streamFile, "psi"); + if (PSIFile) { + num_samples = read_32bitLE(0x8C, PSIFile); + loop_start = read_32bitLE(0x84, PSIFile); + loop_end = read_32bitLE(0x88, PSIFile); + close_streamfile(PSIFile); + } + else { + num_samples = 0; + loop_start = 0; + loop_end = 0; + } + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); +fail: + return NULL; +} + +/* Nippon1 variation [Disgaea 5 (Switch)] */ +VGMSTREAM * init_vgmstream_opus_n1(STREAMFILE *streamFile) { + off_t offset; + int num_samples, loop_start, loop_end; + + /* checks */ + if ( !check_extensions(streamFile,"opus,lopus")) + goto fail; + if (!((read_32bitBE(0x04,streamFile) == 0x00000000 && read_32bitBE(0x0c,streamFile) == 0x00000000) || + (read_32bitBE(0x04,streamFile) == 0xFFFFFFFF && read_32bitBE(0x0c,streamFile) == 0xFFFFFFFF))) + goto fail; + + offset = 0x10; + num_samples = 0; + loop_start = read_32bitLE(0x00,streamFile); + loop_end = read_32bitLE(0x08,streamFile); + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); +fail: + return NULL; +} + +/* Capcom variation [Ultra Street Fighter II (Switch), Resident Evil: Revelations (Switch)] */ +VGMSTREAM * init_vgmstream_opus_capcom(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + off_t offset; + int num_samples, loop_start, loop_end; + int channel_count; + + /* checks */ + if ( !check_extensions(streamFile,"opus,lopus")) + goto fail; + + channel_count = read_32bitLE(0x04,streamFile); + if (channel_count != 1 && channel_count != 2 && channel_count != 6) + goto fail; /* unknown stream layout */ + + num_samples = read_32bitLE(0x00,streamFile); + /* 0x04: channels, >2 uses interleaved streams (2ch+2ch+2ch) */ + loop_start = read_32bitLE(0x08,streamFile); + loop_end = read_32bitLE(0x0c,streamFile); + /* 0x10: frame size (with extra data) */ + /* 0x14: extra chunk count */ + /* 0x18: null */ + offset = read_32bitLE(0x1c,streamFile); + /* 0x20-8: config? (0x0077C102 04000000 E107070C) */ + /* 0x2c: some size? */ + /* 0x30+: extra chunks (0x00: 0x7f, 0x04: num_sample), alt loop starts/regions? */ + + if (channel_count == 6) { + /* 2ch multistream hacky-hacks, don't try this at home. We'll end up with: + * main vgmstream > N vgmstream layers > substream IO deinterleaver > opus meta > Opus IO transmogrifier (phew) */ + layered_layout_data* data = NULL; + int layers = channel_count / 2; + int i; + int loop_flag = (loop_end > 0); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->layout_type = layout_layered; + + /* init layout */ + data = init_layout_layered(layers); + if (!data) goto fail; + vgmstream->layout_data = data; + + /* open each layer subfile */ + for (i = 0; i < layers; i++) { + STREAMFILE* temp_streamFile = setup_opus_interleave_streamfile(streamFile, offset+0x28*i, layers); + if (!temp_streamFile) goto fail; + + data->layers[i] = init_vgmstream_opus(temp_streamFile, meta_OPUS, 0x00, num_samples,loop_start,loop_end); + close_streamfile(temp_streamFile); + if (!data->layers[i]) goto fail; + } + + /* setup layered VGMSTREAMs */ + if (!setup_layout_layered(data)) + goto fail; + + vgmstream->sample_rate = data->layers[0]->sample_rate; + vgmstream->num_samples = data->layers[0]->num_samples; + vgmstream->loop_start_sample = data->layers[0]->loop_start_sample; + vgmstream->loop_end_sample = data->layers[0]->loop_end_sample; + vgmstream->meta_type = meta_OPUS; + vgmstream->coding_type = data->layers[0]->coding_type; + + return vgmstream; + } + else { + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); + } + + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +/* Procyon Studio variation [Xenoblade Chronicles 2 (Switch)] */ +VGMSTREAM * init_vgmstream_opus_nop(STREAMFILE *streamFile) { + off_t offset; + int num_samples, loop_start = 0, loop_end = 0, loop_flag; + + /* checks */ + if (!check_extensions(streamFile,"nop")) + goto fail; + if (read_32bitBE(0x00, streamFile) != 0x73616466 || /* "sadf" */ + read_32bitBE(0x08, streamFile) != 0x6f707573) /* "opus" */ + goto fail; + + offset = read_32bitLE(0x1c, streamFile); + num_samples = read_32bitLE(0x28, streamFile); + loop_flag = read_8bit(0x19, streamFile); + if (loop_flag) { + loop_start = read_32bitLE(0x2c, streamFile); + loop_end = read_32bitLE(0x30, streamFile); + } + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); +fail: + return NULL; +} + +/* Shin'en variation [Fast RMX (Switch)] */ +VGMSTREAM * init_vgmstream_opus_shinen(STREAMFILE *streamFile) { + off_t offset = 0; + int num_samples, loop_start, loop_end; + + /* checks */ + if ( !check_extensions(streamFile,"opus,lopus")) + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x01000080) + goto fail; + + offset = 0x08; + num_samples = 0; + loop_start = read_32bitLE(0x00,streamFile); + loop_end = read_32bitLE(0x04,streamFile); /* 0 if no loop */ + + if (loop_start > loop_end) + goto fail; /* just in case */ + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); +fail: + return NULL; +} + +/* Bandai Namco Opus (found in NUS3Banks) [Taiko no Tatsujin: Nintendo Switch Version!] */ +VGMSTREAM * init_vgmstream_opus_nus3(STREAMFILE *streamFile) { + off_t offset = 0; + int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; + + /* checks */ + /* .opus: header ID (they only exist inside .nus3bank) */ + if (!check_extensions(streamFile, "opus,lopus")) + goto fail; + if (read_32bitBE(0x00, streamFile) != 0x4F505553) /* "OPUS" */ + goto fail; + + /* Here's an interesting quirk, OPUS header contains big endian values + while the Nintendo Opus header and data that follows remain little endian as usual */ + offset = read_32bitBE(0x20, streamFile); + num_samples = read_32bitBE(0x08, streamFile); + + /* Check if there's a loop end value to determine loop_flag*/ + loop_flag = read_32bitBE(0x18, streamFile); + if (loop_flag) { + loop_start = read_32bitBE(0x14, streamFile); + loop_end = read_32bitBE(0x18, streamFile); + } + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); +fail: + return NULL; +} + +/* Nippon Ichi SPS wrapper (non-segmented) [Ys VIII: Lacrimosa of Dana (Switch)] */ +VGMSTREAM * init_vgmstream_opus_sps_n1(STREAMFILE *streamFile) { + off_t offset; + int num_samples, loop_start = 0, loop_end = 0, loop_flag; + + /* checks */ + /* .sps: Labyrinth of Refrain: Coven of Dusk (Switch) + * .nlsd: Disgaea Refine (Switch), Ys VIII (Switch) + * .at9: void tRrLM(); //Void Terrarium (Switch) */ + if (!check_extensions(streamFile, "sps,nlsd,at9")) + goto fail; + if (read_32bitBE(0x00, streamFile) != 0x09000000) /* file type (see other N1 SPS) */ + goto fail; + + num_samples = read_32bitLE(0x0C, streamFile); + + if (read_32bitBE(0x1c, streamFile) == 0x01000080) { + offset = 0x1C; + + /* older games loop section (remnant of segmented opus_sps_n1): */ + loop_start = read_32bitLE(0x10, streamFile); /* intro samples */ + loop_end = loop_start + read_32bitLE(0x14, streamFile); /* loop samples */ + /* 0x18: end samples (all must add up to num_samples) */ + loop_flag = read_32bitLE(0x18, streamFile); /* with loop disabled only loop_end has a value */ + } + else { + offset = 0x18; + + /* newer games loop section: */ + loop_start = read_32bitLE(0x10, streamFile); + loop_end = read_32bitLE(0x14, streamFile); + loop_flag = loop_start != loop_end; /* with loop disabled start and end are the same as num samples */ + } + + if (!loop_flag) { + loop_start = 0; + loop_end = 0; + } + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); +fail: + return NULL; +} + +/* AQUASTYLE wrapper [Touhou Genso Wanderer -Reloaded- (Switch)] */ +VGMSTREAM * init_vgmstream_opus_opusx(STREAMFILE *streamFile) { + off_t offset; + int num_samples, loop_start = 0, loop_end = 0; + float modifier; + + /* checks */ + if (!check_extensions(streamFile, "opusx")) + goto fail; + if (read_32bitBE(0x00, streamFile) != 0x4F505553) /* "OPUS" */ + goto fail; + + offset = 0x10; + /* values are for the original 44100 files, but Opus resamples to 48000 */ + modifier = 48000.0f / 44100.0f; + num_samples = 0;//read_32bitLE(0x04, streamFile) * modifier; /* better use calc'd num_samples */ + loop_start = read_32bitLE(0x08, streamFile) * modifier; + loop_end = read_32bitLE(0x0c, streamFile) * modifier; + + /* resampling calcs are slighly off and may to over num_samples, but by removing delay seems ok */ + if (loop_start >= 120) { + loop_start -= 128; + loop_end -= 128; + } + else { + loop_end = 0; + } + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); +fail: + return NULL; +} + +/* Prototype variation [Clannad (Switch)] */ +VGMSTREAM * init_vgmstream_opus_prototype(STREAMFILE *streamFile) { + off_t offset = 0; + int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; + + /* checks */ + if (!check_extensions(streamFile, "opus,lopus")) + goto fail; + if (read_32bitBE(0x00, streamFile) != 0x4F505553 || /* "OPUS" */ + read_32bitBE(0x18, streamFile) != 0x01000080) + goto fail; + + offset = 0x18; + num_samples = read_32bitLE(0x08, streamFile); + + /* Check if there's a loop end value to determine loop_flag*/ + loop_flag = read_32bitLE(0x10, streamFile); + if (loop_flag) { + loop_start = read_32bitLE(0x0C, streamFile); + loop_end = read_32bitLE(0x10, streamFile); + } + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); +fail: + return NULL; +} + +/* Edelweiss variation [Astebreed (Switch)] */ +VGMSTREAM * init_vgmstream_opus_opusnx(STREAMFILE *streamFile) { + off_t offset = 0; + int num_samples = 0, loop_start = 0, loop_end = 0; + + /* checks */ + if (!check_extensions(streamFile, "opus,lopus")) + goto fail; + if (read_64bitBE(0x00, streamFile) != 0x4F5055534E580000) /* "OPUSNX\0\0" */ + goto fail; + + offset = 0x10; + num_samples = 0; //read_32bitLE(0x08, streamFile); /* samples with encoder delay */ + if (read_32bitLE(0x0c, streamFile) != 0) + goto fail; + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); +fail: + return NULL; +} + +/* Square Enix variation [Dragon Quest I-III (Switch)] */ +VGMSTREAM * init_vgmstream_opus_sqex(STREAMFILE *streamFile) { + off_t offset = 0; + int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; + + /* checks */ + if (!check_extensions(streamFile, "opus,lopus")) + goto fail; + if (read_64bitBE(0x00, streamFile) != 0x0100000002000000) + goto fail; + + offset = read_32bitLE(0x0C, streamFile); + num_samples = read_32bitLE(0x1C, streamFile); + + /* Check if there's a loop end value to determine loop_flag*/ + loop_flag = read_32bitLE(0x18, streamFile); + if (loop_flag) { + loop_start = read_32bitLE(0x14, streamFile); + loop_end = read_32bitLE(0x18, streamFile); + } + + return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); +fail: + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c index 0519069eb..1c901af63 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -497,8 +497,8 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { if (fmt.coding_type == coding_PCM16LE || fmt.coding_type == coding_MSADPCM) { uint32_t num_cues = read_32bitLE(current_chunk + 0x08, streamFile); - if (num_cues == 1 || num_cues == 2) { - // The second cue sets loop end point but it's not actually used by the engine. + if (num_cues > 0) { + /* The second cue sets loop end point but it's not actually used by the engine. */ loop_flag = 1; loop_start_cue = read_32bitLE(current_chunk + 0x20, streamFile); } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff_ogg_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/riff_ogg_streamfile.h index 6c7c599de..35ee7b167 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff_ogg_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff_ogg_streamfile.h @@ -1,130 +1,127 @@ -#ifndef _RIFF_OGG_STREAMFILE_H_ -#define _RIFF_OGG_STREAMFILE_H_ -#include "../streamfile.h" - -#ifdef VGM_USE_VORBIS -typedef struct { - off_t patch_offset; -} riff_ogg_io_data; - -static size_t riff_ogg_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, riff_ogg_io_data* data) { - size_t bytes_read = streamfile->read(streamfile, dest, offset, length); - - /* has garbage init Oggs pages, patch bad flag */ - if (data->patch_offset && data->patch_offset >= offset && data->patch_offset < offset + bytes_read) { - VGM_ASSERT(dest[data->patch_offset - offset] != 0x02, "RIFF Ogg: bad patch offset at %lx\n", data->patch_offset); - dest[data->patch_offset - offset] = 0x00; - } - - return bytes_read; -} - -static size_t ogg_get_page(uint8_t *buf, size_t bufsize, off_t offset, STREAMFILE *sf) { - size_t segments, bytes, page_size; - int i; - - if (0x1b > bufsize) goto fail; - bytes = read_streamfile(buf, offset, 0x1b, sf); - if (bytes != 0x1b) goto fail; - - segments = get_u8(buf + 0x1a); - if (0x1b + segments > bufsize) goto fail; - - bytes = read_streamfile(buf + 0x1b, offset + 0x1b, segments, sf); - if (bytes != segments) goto fail; - - page_size = 0x1b + segments; - for (i = 0; i < segments; i++) { - page_size += get_u8(buf + 0x1b + i); - } - - return page_size; -fail: - return 0; -} - -/* patches Oggs with weirdness */ -static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE *sf, off_t start, size_t size) { - off_t patch_offset = 0; - size_t real_size = size; - uint8_t buf[0x1000]; - - - /* initial page flag is repeated and causes glitches in decoders, find bad offset */ - //todo callback could patch on-the-fly by analyzing all "OggS", but is problematic due to arbitrary offsets - { - off_t offset = start; - size_t page_size; - off_t offset_limit = start + size; /* usually in the first 0x3000 but can be +0x100000 */ - //todo this doesn't seem to help much - STREAMFILE *temp_sf = reopen_streamfile(sf, 0x100); /* use small-ish sf to avoid reading the whole thing */ - - /* first page is ok */ - page_size = ogg_get_page(buf, sizeof(buf), offset, temp_sf); - offset += page_size; - - while (offset < offset_limit) { - page_size = ogg_get_page(buf, sizeof(buf), offset, temp_sf); - if (page_size == 0) break; - - if (get_u32be(buf + 0x00) != 0x4f676753) /* "OggS" */ - break; - - if (get_u16be(buf + 0x04) == 0x0002) { /* start page flag */ - //;VGM_ASSERT(patch_offset > 0, "RIFF Ogg: found multiple repeated start pages\n"); - patch_offset = (offset - start) + 0x04 + 0x01; /* clamp'ed */ - break; - } - - offset += page_size; - } - - close_streamfile(temp_sf); - - if (patch_offset == 0) - return NULL; - } - - /* has a bunch of padding(?) pages at the end with no data nor flag that confuse decoders, find actual end */ - { - size_t chunk_size = sizeof(buf); /* not worth testing more */ - size_t max_size = size; - size_t pos; - off_t read_offset = start + size - chunk_size; - - pos = read_streamfile(buf, read_offset, chunk_size, sf); - if (read_offset < 0 || pos <= 0x1a) return NULL; - - pos -= 0x1a; /* at least one OggS page */ - while (pos > 0) { - if (get_u32be(buf + pos + 0x00) == 0x4f676753) { /* "OggS" */ - - if (get_u16be(buf + pos + 0x04) == 0x0004) { /* last page flag is ok */ - real_size = max_size; - break; - } - else { /* last page flag is wrong */ - max_size = size - (chunk_size - pos); /* update size up to this page */ - } - } - pos--; - } - } - - /* actual custom streamfile init */ - { - STREAMFILE *new_sf = NULL; - riff_ogg_io_data io_data = {0}; - - io_data.patch_offset = patch_offset; - - new_sf = open_wrap_streamfile(sf); - new_sf = open_clamp_streamfile_f(new_sf, start, real_size); - new_sf = open_io_streamfile_f(new_sf, &io_data, sizeof(riff_ogg_io_data), riff_ogg_io_read, NULL); - return new_sf; - } -} - -#endif /* VGM_USE_VORBIS */ - -#endif /* _RIFF_OGG_STREAMFILE_H_ */ +#ifndef _RIFF_OGG_STREAMFILE_H_ +#define _RIFF_OGG_STREAMFILE_H_ +#include "deblock_streamfile.h" + +typedef struct { + off_t patch_offset; +} riff_ogg_io_data; + +static size_t riff_ogg_io_read(STREAMFILE *sf, uint8_t *dest, off_t offset, size_t length, riff_ogg_io_data* data) { + size_t bytes = read_streamfile(dest, offset, length, sf); + + /* has garbage init Oggs pages, patch bad flag */ + if (data->patch_offset && data->patch_offset >= offset && data->patch_offset < offset + bytes) { + VGM_ASSERT(dest[data->patch_offset - offset] != 0x02, "RIFF Ogg: bad patch offset at %lx\n", data->patch_offset); + dest[data->patch_offset - offset] = 0x00; + } + + return bytes; +} + +static size_t ogg_get_page(uint8_t *buf, size_t bufsize, off_t offset, STREAMFILE *sf) { + size_t segments, bytes, page_size; + int i; + + if (0x1b > bufsize) goto fail; + bytes = read_streamfile(buf, offset, 0x1b, sf); + if (bytes != 0x1b) goto fail; + + segments = get_u8(buf + 0x1a); + if (0x1b + segments > bufsize) goto fail; + + bytes = read_streamfile(buf + 0x1b, offset + 0x1b, segments, sf); + if (bytes != segments) goto fail; + + page_size = 0x1b + segments; + for (i = 0; i < segments; i++) { + page_size += get_u8(buf + 0x1b + i); + } + + return page_size; +fail: + return 0; +} + +/* patches Ogg with weirdness */ +static STREAMFILE* setup_riff_ogg_streamfile(STREAMFILE *sf, off_t start, size_t size) { + off_t patch_offset = 0; + size_t real_size = size; + uint8_t buf[0x1000]; + + + /* initial page flag is repeated and causes glitches in decoders, find bad offset */ + //todo callback could patch on-the-fly by analyzing all "OggS", but is problematic due to arbitrary offsets + { + off_t offset = start; + size_t page_size; + off_t offset_limit = start + size; /* usually in the first 0x3000 but can be +0x100000 */ + //todo this doesn't seem to help much + STREAMFILE *temp_sf = reopen_streamfile(sf, 0x100); /* use small-ish sf to avoid reading the whole thing */ + + /* first page is ok */ + page_size = ogg_get_page(buf, sizeof(buf), offset, temp_sf); + offset += page_size; + + while (offset < offset_limit) { + page_size = ogg_get_page(buf, sizeof(buf), offset, temp_sf); + if (page_size == 0) break; + + if (get_u32be(buf + 0x00) != 0x4f676753) /* "OggS" */ + break; + + if (get_u16be(buf + 0x04) == 0x0002) { /* start page flag */ + //;VGM_ASSERT(patch_offset > 0, "RIFF Ogg: found multiple repeated start pages\n"); + patch_offset = (offset - start) + 0x04 + 0x01; /* clamp'ed */ + break; + } + + offset += page_size; + } + + close_streamfile(temp_sf); + + if (patch_offset == 0) + return NULL; + } + + /* has a bunch of padding(?) pages at the end with no data nor flag that confuse decoders, find actual end */ + { + size_t chunk_size = sizeof(buf); /* not worth testing more */ + size_t max_size = size; + size_t pos; + off_t read_offset = start + size - chunk_size; + + pos = read_streamfile(buf, read_offset, chunk_size, sf); + if (read_offset < 0 || pos <= 0x1a) return NULL; + + pos -= 0x1a; /* at least one OggS page */ + while (pos > 0) { + if (get_u32be(buf + pos + 0x00) == 0x4f676753) { /* "OggS" */ + + if (get_u16be(buf + pos + 0x04) == 0x0004) { /* last page flag is ok */ + real_size = max_size; + break; + } + else { /* last page flag is wrong */ + max_size = size - (chunk_size - pos); /* update size up to this page */ + } + } + pos--; + } + } + + /* actual custom streamfile init */ + { + STREAMFILE *new_sf = NULL; + riff_ogg_io_data io_data = {0}; + + io_data.patch_offset = patch_offset; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_clamp_streamfile_f(new_sf, start, real_size); + new_sf = open_io_streamfile_f(new_sf, &io_data, sizeof(riff_ogg_io_data), riff_ogg_io_read, NULL); + return new_sf; + } +} + +#endif /* _RIFF_OGG_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sfh_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/sfh_streamfile.h index 954df1a0d..9af0990a5 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sfh_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/sfh_streamfile.h @@ -1,133 +1,24 @@ -#ifndef _SFH_STREAMFILE_H_ -#define _SFH_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - /* config */ - off_t stream_offset; - size_t stream_size; - - /* state */ - off_t logical_offset; /* fake offset */ - off_t physical_offset; /* actual offset */ - size_t block_size; /* current size */ - size_t skip_size; /* size from block start to reach data */ - size_t data_size; /* usable size in a block */ - - size_t logical_size; -} sfh_io_data; - - -static size_t sfh_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, sfh_io_data* data) { - size_t total_read = 0; - - - /* re-start when previous offset (can't map logical<>physical offsets) */ - if (data->logical_offset < 0 || offset < data->logical_offset) { - data->physical_offset = data->stream_offset; - data->logical_offset = 0x00; - data->data_size = 0; - } - - /* read blocks */ - while (length > 0) { - - /* ignore EOF */ - if (offset < 0 || data->physical_offset >= data->stream_offset + data->stream_size) { - break; - } - - /* process new block */ - if (data->data_size == 0) { - data->skip_size = 0x10; /* skip 0x10 garbage on every block */ - data->data_size = data->block_size - 0x10; - } - - /* move to next block */ - if (data->data_size == 0 || offset >= data->logical_offset + data->data_size) { - data->physical_offset += data->block_size; - data->logical_offset += data->data_size; - data->data_size = 0; - continue; - } - - /* read data */ - { - size_t bytes_consumed, bytes_done, to_read; - - bytes_consumed = offset - data->logical_offset; - to_read = data->data_size - bytes_consumed; - if (to_read > length) - to_read = length; - bytes_done = read_streamfile(dest, data->physical_offset + data->skip_size + bytes_consumed, to_read, streamfile); - - total_read += bytes_done; - dest += bytes_done; - offset += bytes_done; - length -= bytes_done; - - if (bytes_done != to_read || bytes_done == 0) { - break; /* error/EOF */ - } - } - } - - return total_read; -} - -static size_t sfh_io_size(STREAMFILE *streamfile, sfh_io_data* data) { - uint8_t buf[1]; - - if (data->logical_size) - return data->logical_size; - - /* force a fake read at max offset, to get max logical_offset (will be reset next read) */ - sfh_io_read(streamfile, buf, 0x7FFFFFFF, 1, data); - data->logical_size = data->logical_offset; - - return data->logical_size; -} - -/* Handles deinterleaving of SFH blocked streams */ -static STREAMFILE* setup_sfh_streamfile(STREAMFILE *streamFile, off_t stream_offset, size_t block_size, size_t clean_size, const char* extension) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - sfh_io_data io_data = {0}; - size_t io_data_size = sizeof(sfh_io_data); - - io_data.stream_offset = stream_offset; - io_data.stream_size = get_streamfile_size(streamFile) - stream_offset; - io_data.block_size = block_size; - io_data.logical_offset = -1; /* force phys offset reset */ - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(new_streamFile, &io_data,io_data_size, sfh_io_read,sfh_io_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_buffer_streamfile(new_streamFile,0); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(new_streamFile,0x00, clean_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - if (extension) { - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,extension); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - } - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -#endif /* _SFH_STREAMFILE_H_ */ +#ifndef _SFH_STREAMFILE_H_ +#define _SFH_STREAMFILE_H_ +#include "deblock_streamfile.h" + +/* Deblocks SFH streams, skipping 0x10 garbage added to every chunk */ +static STREAMFILE* setup_sfh_streamfile(STREAMFILE *sf, off_t stream_offset, size_t chunk_size, size_t clean_size, const char* extension) { + STREAMFILE *new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.stream_start = stream_offset; + cfg.chunk_size = chunk_size; + cfg.skip_size = 0x10; + + /* setup sf */ + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + //new_sf = open_buffer_streamfile_f(new_sf, 0); + new_sf = open_clamp_streamfile_f(new_sf, 0x00, clean_size); + if (extension) + new_sf = open_fakename_streamfile_f(new_sf, NULL, extension); + return new_sf; +} + +#endif /* _SFH_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/tgc.c b/Frameworks/vgmstream/vgmstream/src/meta/tgc.c new file mode 100644 index 000000000..a865309ec --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/tgc.c @@ -0,0 +1,30 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* Tiger Game.com ADPCM file */ +VGMSTREAM * init_vgmstream_tgc(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + + /* checks */ + if (!check_extensions(streamFile, "4")) + goto fail; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(1, 0); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = 8000; + vgmstream->num_samples = ((uint16_t)read_16bitBE(1, streamFile) - 3) * 2; + vgmstream->meta_type = meta_TGC; + vgmstream->layout_type = layout_none; + vgmstream->coding_type = coding_TGC; + + if (!vgmstream_open_stream(vgmstream, streamFile, 3)) + goto fail; + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txth.c b/Frameworks/vgmstream/vgmstream/src/meta/txth.c index e4c654eea..2d763728b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txth.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/txth.c @@ -36,6 +36,7 @@ typedef enum { PCM4_U = 26, /* 4-bit unsigned PCM (3rd and 4th gen games) */ OKI16 = 27, /* OKI ADPCM with 16-bit output (unlike OKI/VOX/Dialogic ADPCM's 12-bit) */ AAC = 28, /* Advanced Audio Coding (raw without .mp4) */ + TGC = 29 /* Tiger Game.com 4-bit ADPCM */ } txth_type; typedef struct { @@ -221,6 +222,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { case PCM4: coding = coding_PCM4; break; case PCM4_U: coding = coding_PCM4_U; break; case OKI16: coding = coding_OKI16; break; + case TGC: coding = coding_TGC; break; default: goto fail; } @@ -266,6 +268,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { case coding_IMA: case coding_AICA: case coding_APPLE_IMA4: + case coding_TGC: vgmstream->interleave_block_size = txth.interleave; vgmstream->interleave_last_block_size = txth.interleave_last; if (vgmstream->channels > 1) @@ -843,6 +846,8 @@ static int parse_keyval(STREAMFILE * streamFile_, txth_header * txth, const char else if (is_string(val,"PCM4_U")) txth->codec = PCM4_U; else if (is_string(val,"OKI16")) txth->codec = OKI16; else if (is_string(val,"AAC")) txth->codec = AAC; + else if (is_string(val,"TGC")) txth->codec = TGC; + else if (is_string(val,"GCOM_ADPCM")) txth->codec = TGC; else goto fail; /* set common interleaves to simplify usage @@ -1698,6 +1703,7 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) { return pcm_bytes_to_samples(bytes, txth->channels, 8); case PCM4: case PCM4_U: + case TGC: return pcm_bytes_to_samples(bytes, txth->channels, 4); case MSADPCM: return msadpcm_bytes_to_samples(bytes, txth->interleave, txth->channels); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_hx.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_hx.c index 454f8c85b..37446233c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_hx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_hx.c @@ -1,717 +1,726 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../coding/coding.h" - - -typedef enum { PCM, UBI, PSX, DSP, XIMA, ATRAC3, XMA2 } ubi_hx_codec; - -typedef struct { - int big_endian; - int total_subsongs; - - int codec_id; - ubi_hx_codec codec; /* unified codec */ - int header_index; /* entry number within section2 */ - off_t header_offset; /* entry offset within internal .HXx */ - size_t header_size; /* entry offset within internal .HXx */ - char class_name[255]; - size_t class_size; - size_t stream_mode; - - off_t stream_offset; /* data offset within external stream */ - size_t stream_size; /* data size within external stream */ - uint32_t cuuid1; /* usually "Res" id1: class (1=Event, 3=Wave), id2: group id+sound id, */ - uint32_t cuuid2; /* others have some complex id (not hash), id1: parent id?, id2: file id? */ - - int loop_flag; - int channels; - int sample_rate; - int num_samples; - - int is_external; - char resource_name[0x28]; /* filename to the external stream */ - char internal_name[255]; /* WavRes's assigned name */ - char readable_name[255]; /* final subsong name */ - -} ubi_hx_header; - - -static int parse_hx(ubi_hx_header * hx, STREAMFILE *sf, int target_subsong); -static VGMSTREAM * init_vgmstream_ubi_hx_header(ubi_hx_header *hx, STREAMFILE *sf); - -/* .HXx - banks from Ubisoft's HXAudio engine games [Rayman Arena, Rayman 3, XIII] */ -VGMSTREAM * init_vgmstream_ubi_hx(STREAMFILE *streamFile) { - VGMSTREAM* vgmstream = NULL; - ubi_hx_header hx = {0}; - int target_subsong = streamFile->stream_index; - - - /* checks */ - /* .hxd: Rayman M/Arena (all), PK: Out of Shadows (all) - * .hxc: Rayman 3 (PC), XIII (PC) - * .hx2: Rayman 3 (PS2), XIII (PS2) - * .hxg: Rayman 3 (GC), XIII (GC) - * .hxx: Rayman 3 (Xbox), Rayman 3 HD (X360) - * .hx3: Rayman 3 HD (PS3) */ - if (!check_extensions(streamFile, "hxd,hxc,hx2,hxg,hxx,hx3")) - goto fail; - - /* .HXx is a slightly less bizarre bank with various resource classes (events, streams, etc, not unlike other Ubi's engines) - * then an index to those types. Some games leave a companion .bnh with text info, probably leftover from their tools. - * Game seems to play files by calling linked ids: EventResData (play/stop/etc) > Random/Program/Wav ResData (1..N refs) > FileIdObj */ - - /* HX CONFIG */ - hx.big_endian = guess_endianness32bit(0x00, streamFile); - - /* HX HEADER */ - if (!parse_hx(&hx, streamFile, target_subsong)) - goto fail; - - /* CREATE VGMSTREAM */ - vgmstream = init_vgmstream_ubi_hx_header(&hx, streamFile); - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} - - -static void build_readable_name(char * buf, size_t buf_size, ubi_hx_header * hx) { - const char *grp_name; - - if (hx->is_external) - grp_name = hx->resource_name; - else - grp_name = "internal"; - - if (hx->internal_name[0]) - snprintf(buf,buf_size, "%s/%i/%08x-%08x/%s/%s", "hx", hx->header_index, hx->cuuid1,hx->cuuid2, grp_name, hx->internal_name); - else - snprintf(buf,buf_size, "%s/%i/%08x-%08x/%s", "hx", hx->header_index, hx->cuuid1,hx->cuuid2, grp_name); -} - -#define TXT_LINE_MAX 0x1000 - -/* get name */ -static int parse_name_bnh(ubi_hx_header * hx, STREAMFILE *sf, uint32_t cuuid1, uint32_t cuuid2) { - STREAMFILE *sf_t; - off_t txt_offset = 0; - char line[TXT_LINE_MAX]; - char cuuid[40]; - - sf_t = open_streamfile_by_ext(sf,"bnh"); - if (sf_t == NULL) goto fail; - - snprintf(cuuid,sizeof(cuuid), "cuuid( 0x%08x, 0x%08x )", cuuid1, cuuid2); - - /* each .bnh line has a cuuid, a bunch of repeated fields and name (sometimes name is filename or "bad name") */ - while (txt_offset < get_streamfile_size(sf)) { - int line_ok, bytes_read; - - bytes_read = read_line(line, sizeof(line), txt_offset, sf_t, &line_ok); - if (!line_ok) break; - txt_offset += bytes_read; - - if (strncmp(line,cuuid,31) != 0) - continue; - if (bytes_read <= 79) - goto fail; - - /* cuuid found, copy name (lines are fixed and always starts from the same position) */ - strcpy(hx->internal_name, &line[79]); - - close_streamfile(sf_t); - return 1; - } - -fail: - close_streamfile(sf_t); - return 0; -} - - -/* get referenced name from WavRes, using the index again (abridged) */ -static int parse_name(ubi_hx_header * hx, STREAMFILE *sf) { - int32_t (*read_32bit)(off_t,STREAMFILE*) = hx->big_endian ? read_32bitBE : read_32bitLE; - off_t index_offset, offset; - int i, index_entries; - char class_name[255]; - - - index_offset = read_32bit(0x00, sf); - index_entries = read_32bit(index_offset + 0x08, sf); - offset = index_offset + 0x0c; - for (i = 0; i < index_entries; i++) { - off_t header_offset; - size_t class_size; - int j, link_count, language_count, is_found = 0; - uint32_t cuuid1, cuuid2; - - - class_size = read_32bit(offset + 0x00, sf); - if (class_size > sizeof(class_name)+1) goto fail; - read_string(class_name,class_size+1, offset + 0x04, sf); /* not null-terminated */ - offset += 0x04 + class_size; - - cuuid1 = (uint32_t)read_32bit(offset + 0x00, sf); - cuuid2 = (uint32_t)read_32bit(offset + 0x04, sf); - - header_offset = read_32bit(offset + 0x08, sf); - offset += 0x10; - - //unknown_count = read_32bit(offset + 0x00, sf); - offset += 0x04; - - link_count = read_32bit(offset + 0x00, sf); - offset += 0x04; - for (j = 0; j < link_count; j++) { - uint32_t link_id1 = (uint32_t)read_32bit(offset + 0x00, sf); - uint32_t link_id2 = (uint32_t)read_32bit(offset + 0x04, sf); - - if (link_id1 == hx->cuuid1 && link_id2 == hx->cuuid2) { - is_found = 1; - } - offset += 0x08; - } - - language_count = read_32bit(offset + 0x00, sf); - offset += 0x04; - for (j = 0; j < language_count; j++) { - uint32_t link_id1 = (uint32_t)read_32bit(offset + 0x08, sf); - uint32_t link_id2 = (uint32_t)read_32bit(offset + 0x0c, sf); - - if (link_id1 == hx->cuuid1 && link_id2 == hx->cuuid2) { - is_found = 1; - } - - offset += 0x10; - } - - /* identify all possible names so unknown platforms fail */ - if (is_found && ( - strcmp(class_name, "CPCWavResData") == 0 || - strcmp(class_name, "CPS2WavResData") == 0 || - strcmp(class_name, "CGCWavResData") == 0 || - strcmp(class_name, "CXBoxWavResData") == 0 || - strcmp(class_name, "CPS3WavResData") == 0)) { - size_t resclass_size, internal_size; - off_t wavres_offset = header_offset; - - /* parse WavRes header */ - resclass_size = read_32bit(wavres_offset, sf); - wavres_offset += 0x04 + resclass_size + 0x08 + 0x04; /* skip class + cuiid + flags */ - - internal_size = read_32bit(wavres_offset + 0x00, sf); - if (internal_size > sizeof(hx->internal_name)+1) goto fail; - - /* usually 0 in consoles */ - if (internal_size != 0) { - read_string(hx->internal_name,internal_size+1, wavres_offset + 0x04, sf); - return 1; - } - else { - parse_name_bnh(hx, sf, cuuid1, cuuid2); - return 1; /* ignore error */ - } - } - } - -fail: - return 0; -} - - -/* parse a single known header resource at offset */ -static int parse_header(ubi_hx_header * hx, STREAMFILE *sf, off_t offset, size_t size, int index) { - int32_t (*read_32bit)(off_t,STREAMFILE*) = hx->big_endian ? read_32bitBE : read_32bitLE; - int16_t (*read_16bit)(off_t,STREAMFILE*) = hx->big_endian ? read_16bitBE : read_16bitLE; - off_t riff_offset, riff_size, chunk_offset, stream_adjust = 0, resource_size; - size_t chunk_size; - int cue_flag = 0; - - //todo cleanup/unify common readings - - //;VGM_LOG("UBI HX: header o=%lx, s=%x\n\n", offset, size); - - hx->header_index = index; - hx->header_offset = offset; - hx->header_size = size; - - hx->class_size = read_32bit(offset + 0x00, sf); - if (hx->class_size > sizeof(hx->class_name)+1) goto fail; - read_string(hx->class_name,hx->class_size+1, offset + 0x04, sf); - offset += 0x04 + hx->class_size; - - hx->cuuid1 = (uint32_t)read_32bit(offset + 0x00, sf); - hx->cuuid2 = (uint32_t)read_32bit(offset + 0x04, sf); - offset += 0x08; - - if (strcmp(hx->class_name, "CPCWaveFileIdObj") == 0 || - strcmp(hx->class_name, "CPS2WaveFileIdObj") == 0 || - strcmp(hx->class_name, "CGCWaveFileIdObj") == 0) { - uint32_t flag_type = read_32bit(offset + 0x00, sf); - - if (flag_type == 0x01 || flag_type == 0x02) { /* Rayman Arena */ - if (read_32bit(offset + 0x04, sf) != 0x00) goto fail; - hx->stream_mode = read_32bit(offset + 0x08, sf); /* flag: 0=internal, 1=external */ - /* 0x0c: flag: 0=static, 1=stream */ - offset += 0x10; - } - else if (flag_type == 0x03) { /* others */ - /* 0x04: some kind of parent id shared by multiple Waves, or 0 */ - offset += 0x08; - - if (strcmp(hx->class_name, "CGCWaveFileIdObj") == 0) { - if (read_32bit(offset + 0x00, sf) != read_32bit(offset + 0x04, sf)) goto fail; /* meaning? */ - hx->stream_mode = read_32bit(offset + 0x04, sf); - offset += 0x08; - } - else { - hx->stream_mode = read_8bit(offset, sf); - offset += 0x01; - } - } - else { - VGM_LOG("UBI HX: unknown flag-type\n"); - goto fail; - } - - /* get bizarro adjust (found in XIII external files) */ - if (hx->stream_mode == 0x0a) { - stream_adjust = read_32bit(offset, sf); /* what */ - offset += 0x04; - } - - //todo probably a flag: &1=external, &2=stream, &8=has adjust (XIII), &4=??? (XIII PS2, small, mono) - switch(hx->stream_mode) { - case 0x00: /* memory (internal file) */ - riff_offset = offset; - riff_size = read_32bit(riff_offset + 0x04, sf) + 0x08; - break; - - case 0x01: /* static (smaller external file) */ - case 0x03: /* stream (bigger external file) */ - case 0x07: /* static? */ - case 0x0a: /* static? */ - resource_size = read_32bit(offset + 0x00, sf); - if (resource_size > sizeof(hx->resource_name)+1) goto fail; - read_string(hx->resource_name,resource_size+1, offset + 0x04, sf); - - riff_offset = offset + 0x04 + resource_size; - riff_size = read_32bit(riff_offset + 0x04, sf) + 0x08; - - hx->is_external = 1; - break; - - default: - goto fail; - } - - - /* parse pseudo-RIFF "fmt" */ - if (read_32bit(riff_offset, sf) != 0x46464952) /* "RIFF" in machine endianness */ - goto fail; - - hx->codec_id = read_16bit(riff_offset + 0x14 , sf); - switch(hx->codec_id) { - case 0x01: hx->codec = PCM; break; - case 0x02: hx->codec = UBI; break; - case 0x03: hx->codec = PSX; break; - case 0x04: hx->codec = DSP; break; - default: goto fail; - } - hx->channels = read_16bit(riff_offset + 0x16, sf); - hx->sample_rate = read_32bit(riff_offset + 0x18, sf); - - /* find "datx" (external) or "data" (internal) also in machine endianness */ - if (hx->is_external) { - if (find_chunk_riff_ve(sf, 0x78746164,riff_offset + 0x0c,riff_size - 0x0c, &chunk_offset,NULL, hx->big_endian)) { - hx->stream_size = read_32bit(chunk_offset + 0x00, sf); - hx->stream_offset = read_32bit(chunk_offset + 0x04, sf) + stream_adjust; - } - else if ((flag_type == 0x01 || flag_type == 0x02) && /* Rayman M (not Arena) uses "data" instead */ - find_chunk_riff_ve(sf, 0x61746164,riff_offset + 0x0c,riff_size - 0x0c, &chunk_offset,&chunk_size, hx->big_endian)) { - hx->stream_size = chunk_size; - hx->stream_offset = read_32bit(chunk_offset + 0x00, sf) + stream_adjust; - } - else { - goto fail; - } - } - else { - if (!find_chunk_riff_ve(sf, 0x61746164,riff_offset + 0x0c,riff_size - 0x0c, &chunk_offset,NULL, hx->big_endian)) - goto fail; - hx->stream_offset = chunk_offset; - hx->stream_size = riff_size - (chunk_offset - riff_offset); - } - - /* can contain other RIFF stuff like "cue ", "labl" and "ump3" - * XIII music uses cue/labl to play/loop dynamic sections */ - } - else if (strcmp(hx->class_name, "CXBoxStaticHWWaveFileIdObj") == 0 || - strcmp(hx->class_name, "CXBoxStreamHWWaveFileIdObj") == 0 || - strcmp(hx->class_name, "CPS3StaticAC3WaveFileIdObj") == 0 || - strcmp(hx->class_name, "CPS3StreamAC3WaveFileIdObj") == 0) { - - hx->stream_offset = read_32bit(offset + 0x00, sf); - hx->stream_size = read_32bit(offset + 0x04, sf); - offset += 0x08; - - //todo some dummy files have 0 size - - if (read_32bit(offset + 0x00, sf) != 0x01) goto fail; - /* 0x04: some kind of parent id shared by multiple Waves, or 0 */ - offset += 0x08; - - hx->stream_mode = read_8bit(offset, sf); - offset += 0x01; - - if ((strcmp(hx->class_name, "CXBoxStaticHWWaveFileIdObj") == 0 || - strcmp(hx->class_name, "CXBoxStreamHWWaveFileIdObj") == 0) && !hx->big_endian) { - /* micro header: some mix of channels + block size + sample rate + flags, unsure of which bits */ - hx->codec = XIMA; - hx->channels = (uint8_t)read_8bit(offset + 0x01, sf); - switch(hx->channels) { /* upper 2 bits? */ - case 0x48: hx->channels = 1; break; - case 0x90: hx->channels = 2; break; - default: goto fail; - } - hx->sample_rate = (uint16_t)(read_16bit(offset + 0x02, sf) & 0x7FFF) << 1; /* ??? */ - cue_flag = (uint8_t) read_8bit (offset + 0x03, sf) & (1<<7); - offset += 0x04; - } - else if ((strcmp(hx->class_name, "CXBoxStaticHWWaveFileIdObj") == 0 || - strcmp(hx->class_name, "CXBoxStreamHWWaveFileIdObj") == 0) && hx->big_endian) { - /* fake fmt chunk */ - hx->codec = XMA2; - hx->channels = (uint16_t)read_16bit(offset + 0x02, sf); - hx->sample_rate = read_32bit(offset + 0x04, sf); - hx->num_samples = read_32bit(offset + 0x18, sf) / 0x02 / hx->channels; - cue_flag = read_32bit(offset + 0x34, sf); - offset += 0x38; - } - else { - /* MSFC header */ - hx->codec = ATRAC3; - hx->codec_id = read_32bit(offset + 0x04, sf); - hx->channels = read_32bit(offset + 0x08, sf); - hx->sample_rate = read_32bit(offset + 0x10, sf); - cue_flag = read_32bit(offset + 0x40, sf); - offset += 0x44; - } - - /* skip cue table that sometimes exists in streams */ - if (cue_flag) { - int j; - - size_t cue_count = read_32bit(offset, sf); - offset += 0x04; - for (j = 0; j < cue_count; j++) { - /* 0x00: id? */ - size_t description_size = read_32bit(offset + 0x04, sf); /* for next string */ - offset += 0x08 + description_size; - } - } - - - switch(hx->stream_mode) { - case 0x01: /* static (smaller external file) */ - case 0x03: /* stream (bigger external file) */ - case 0x07: /* stream? */ - resource_size = read_32bit(offset + 0x00, sf); - if (resource_size > sizeof(hx->resource_name)+1) goto fail; - read_string(hx->resource_name,resource_size+1, offset + 0x04, sf); - - hx->is_external = 1; - break; - - default: - goto fail; - } - } - else { - goto fail; - } - - return 1; -fail: - VGM_LOG("UBI HX: error parsing header at %lx\n", hx->header_offset); - return 0; -} - - -/* parse a bank index and its possible audio headers (some info from Droolie's .bms) */ -static int parse_hx(ubi_hx_header * hx, STREAMFILE *sf, int target_subsong) { - int32_t (*read_32bit)(off_t,STREAMFILE*) = hx->big_endian ? read_32bitBE : read_32bitLE; - off_t index_offset, offset; - int i, index_entries; - char class_name[255]; - - - index_offset = read_32bit(0x00, sf); - if (read_32bit(index_offset + 0x00, sf) != 0x58444E49) /* "XDNI" (INDX in given endianness) */ - goto fail; - if (read_32bit(index_offset + 0x04, sf) != 0x02) /* type? */ - goto fail; - - if (target_subsong == 0) target_subsong = 1; - - index_entries = read_32bit(index_offset + 0x08, sf); - offset = index_offset + 0x0c; - for (i = 0; i < index_entries; i++) { - off_t header_offset; - size_t class_size, header_size; - int j, unknown_count, link_count, language_count; - - //;VGM_LOG("UBI HX: index %i at %lx\n", i, offset); - - /* parse index entries: offset to actual header plus some extra info also in the header */ - - class_size = read_32bit(offset + 0x00, sf); - if (class_size > sizeof(class_name)+1) goto fail; - - read_string(class_name,class_size+1, offset + 0x04, sf); /* not null-terminated */ - offset += 0x04 + class_size; - - /* 0x00: id1+2 */ - header_offset = read_32bit(offset + 0x08, sf); - header_size = read_32bit(offset + 0x0c, sf); - offset += 0x10; - - /* not seen */ - unknown_count = read_32bit(offset + 0x00, sf); - if (unknown_count != 0) { - VGM_LOG("UBI HX: found unknown near %lx\n", offset); - goto fail; - } - offset += 0x04; - - /* ids that this object directly points to (ex. Event > Random) */ - link_count = read_32bit(offset + 0x00, sf); - offset += 0x04 + 0x08 * link_count; - - /* localized id list of WavRes (can use this list instead of the prev one) */ - language_count = read_32bit(offset + 0x00, sf); - offset += 0x04; - for (j = 0; j < language_count; j++) { - /* 0x00: lang code, in reverse endianness: "en ", "fr ", etc */ - /* 0x04: possibly count of ids for this lang */ - /* 0x08: id1+2 */ - - if (read_32bit(offset + 0x04, sf) != 1) { - VGM_LOG("UBI HX: wrong lang count near %lx\n", offset); - goto fail; /* WavRes doesn't have this field */ - } - offset += 0x10; - } - - //todo figure out CProgramResData sequences - // Format is pretty complex list of values and some offsets in between, then field names - // then more values and finally a list of linked IDs Links are the same as in the index, - // but doesn't seem to be a straight sequence list. Seems it can be used for other config too. - - /* identify all possible names so unknown platforms fail */ - if (strcmp(class_name, "CEventResData") == 0 || /* play/stop/etc event */ - strcmp(class_name, "CProgramResData") == 0 || /* some kind of map/object-like config to make sequences in some cases? */ - strcmp(class_name, "CActorResData") == 0 || /* same? */ - strcmp(class_name, "CRandomResData") == 0 || /* chooses random WavRes from a list */ - strcmp(class_name, "CTreeBank") == 0 || /* points to TreeRes? */ - strcmp(class_name, "CTreeRes") == 0 || /* points to TreeBank? */ - strcmp(class_name, "CSwitchResData") == 0 || /* big list of WavRes */ - strcmp(class_name, "CPCWavResData") == 0 || /* points to WaveFileIdObj */ - strcmp(class_name, "CPS2WavResData") == 0 || - strcmp(class_name, "CGCWavResData") == 0 || - strcmp(class_name, "CXBoxWavResData") == 0 || - strcmp(class_name, "CPS3WavResData") == 0) { - continue; - } - else if (strcmp(class_name, "CPCWaveFileIdObj") == 0 || - strcmp(class_name, "CPS2WaveFileIdObj") == 0 || - strcmp(class_name, "CGCWaveFileIdObj") == 0 || - strcmp(class_name, "CXBoxStaticHWWaveFileIdObj") == 0 || - strcmp(class_name, "CXBoxStreamHWWaveFileIdObj") == 0 || - strcmp(class_name, "CPS3StaticAC3WaveFileIdObj") == 0 || - strcmp(class_name, "CPS3StreamAC3WaveFileIdObj") == 0) { - ; - } - else { - VGM_LOG("UBI HX: unknown type: %s\n", class_name); - goto fail; - } - - if (link_count != 0) { - VGM_LOG("UBI HX: found links in wav object\n"); - goto fail; - } - - hx->total_subsongs++; - if (hx->total_subsongs != target_subsong) - continue; - - if (!parse_header(hx, sf, header_offset, header_size, i)) - goto fail; - if (!parse_name(hx, sf)) - goto fail; - - build_readable_name(hx->readable_name,sizeof(hx->readable_name), hx); - } - - if (target_subsong < 0 || target_subsong > hx->total_subsongs || hx->total_subsongs < 1) goto fail; - - - return 1; -fail: - return 0; -} - - -static STREAMFILE * open_hx_streamfile(ubi_hx_header *hx, STREAMFILE *sf) { - STREAMFILE *streamData = NULL; - - - if (!hx->is_external) - return NULL; - - streamData = open_streamfile_by_filename(sf, hx->resource_name); - if (streamData == NULL) { - VGM_LOG("UBI HX: external stream '%s' not found\n", hx->resource_name); - goto fail; - } - - /* streams often have a "RIFF" with "fmt" and "data" but stream offset/size is already adjusted to skip them */ - - return streamData; -fail: - return NULL; -} - -static VGMSTREAM * init_vgmstream_ubi_hx_header(ubi_hx_header *hx, STREAMFILE *streamFile) { - STREAMFILE *streamTemp = NULL; - STREAMFILE *streamData = NULL; - VGMSTREAM* vgmstream = NULL; - - - if (hx->is_external) { - streamTemp = open_hx_streamfile(hx, streamFile); - if (streamTemp == NULL) goto fail; - streamData = streamTemp; - } - else { - streamData = streamFile; - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(hx->channels, hx->loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_UBI_HX; - vgmstream->sample_rate = hx->sample_rate; - vgmstream->num_streams = hx->total_subsongs; - vgmstream->stream_size = hx->stream_size; - - switch(hx->codec) { - case PCM: - vgmstream->coding_type = coding_PCM16LE; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x02; - - vgmstream->num_samples = pcm_bytes_to_samples(hx->stream_size, hx->channels, 16); - break; - - case UBI: - vgmstream->codec_data = init_ubi_adpcm(streamData, hx->stream_offset, vgmstream->channels); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_UBI_ADPCM; - vgmstream->layout_type = layout_none; - - vgmstream->num_samples = ubi_adpcm_get_samples(vgmstream->codec_data); - /* XIII has 6-bit stereo music, Rayman 3 4-bit music, both use 6-bit mono) */ - break; - - case PSX: - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x10; - - vgmstream->num_samples = ps_bytes_to_samples(hx->stream_size, hx->channels); - break; - - case DSP: - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x08; - - /* dsp header at start offset */ - vgmstream->num_samples = read_32bitBE(hx->stream_offset + 0x00, streamData); - dsp_read_coefs_be(vgmstream, streamData, hx->stream_offset + 0x1c, 0x60); - dsp_read_hist_be (vgmstream, streamData, hx->stream_offset + 0x40, 0x60); - hx->stream_offset += 0x60 * hx->channels; - hx->stream_size -= 0x60 * hx->channels; - break; - - case XIMA: - vgmstream->coding_type = coding_XBOX_IMA; - vgmstream->layout_type = layout_none; - - vgmstream->num_samples = xbox_ima_bytes_to_samples(hx->stream_size, hx->channels); - break; - -#ifdef VGM_USE_FFMPEG - case XMA2: { - int bytes, block_count, block_size; - uint8_t buf[0x200]; - - block_size = 0x800; - block_count = hx->stream_size / block_size; - - bytes = ffmpeg_make_riff_xma2(buf,0x200, hx->num_samples, hx->stream_size, hx->channels, hx->sample_rate, block_count, block_size); - vgmstream->codec_data = init_ffmpeg_header_offset(streamData, buf,bytes, hx->stream_offset,hx->stream_size); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - - vgmstream->num_samples = hx->num_samples; - - xma_fix_raw_samples_ch(vgmstream, streamData, hx->stream_offset,hx->stream_size, hx->channels, 0,0); - break; - } - - case ATRAC3: { - int block_align, encoder_delay; - - encoder_delay = 1024 + 69*2; - switch(hx->codec_id) { - case 4: block_align = 0x60 * vgmstream->channels; break; - case 5: block_align = 0x98 * vgmstream->channels; break; - case 6: block_align = 0xC0 * vgmstream->channels; break; - default: goto fail; - } - - vgmstream->num_samples = atrac3_bytes_to_samples(hx->stream_size, block_align) - encoder_delay; - - vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamData, hx->stream_offset,hx->stream_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - break; - } -#endif - - default: - goto fail; - } - - strcpy(vgmstream->stream_name, hx->readable_name); - - if (!vgmstream_open_stream(vgmstream, streamData, hx->stream_offset)) - goto fail; - close_streamfile(streamTemp); - return vgmstream; - -fail: - close_streamfile(streamTemp); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" + + +typedef enum { PCM, UBI, PSX, DSP, XIMA, ATRAC3, XMA2 } ubi_hx_codec; + +typedef struct { + int big_endian; + int total_subsongs; + + int codec_id; + ubi_hx_codec codec; /* unified codec */ + int header_index; /* entry number within section2 */ + off_t header_offset; /* entry offset within internal .HXx */ + size_t header_size; /* entry offset within internal .HXx */ + char class_name[255]; + size_t class_size; + size_t stream_mode; + + off_t stream_offset; /* data offset within external stream */ + size_t stream_size; /* data size within external stream */ + uint32_t cuuid1; /* usually "Res" id1: class (1=Event, 3=Wave), id2: group id+sound id, */ + uint32_t cuuid2; /* others have some complex id (not hash), id1: parent id?, id2: file id? */ + + int loop_flag; + int channels; + int sample_rate; + int num_samples; + + int is_external; + char resource_name[0x28]; /* filename to the external stream */ + char internal_name[255]; /* WavRes's assigned name */ + char readable_name[255]; /* final subsong name */ + +} ubi_hx_header; + + +static int parse_hx(ubi_hx_header * hx, STREAMFILE *sf, int target_subsong); +static VGMSTREAM * init_vgmstream_ubi_hx_header(ubi_hx_header *hx, STREAMFILE *sf); + +/* .HXx - banks from Ubisoft's HXAudio engine games [Rayman Arena, Rayman 3, XIII] */ +VGMSTREAM * init_vgmstream_ubi_hx(STREAMFILE *streamFile) { + VGMSTREAM* vgmstream = NULL; + ubi_hx_header hx = {0}; + int target_subsong = streamFile->stream_index; + + + /* checks */ + /* .hxd: Rayman M/Arena (all), PK: Out of Shadows (all) + * .hxc: Rayman 3 (PC), XIII (PC) + * .hx2: Rayman 3 (PS2), XIII (PS2) + * .hxg: Rayman 3 (GC), XIII (GC) + * .hxx: Rayman 3 (Xbox), Rayman 3 HD (X360) + * .hx3: Rayman 3 HD (PS3) */ + if (!check_extensions(streamFile, "hxd,hxc,hx2,hxg,hxx,hx3")) + goto fail; + + /* .HXx is a slightly less bizarre bank with various resource classes (events, streams, etc, not unlike other Ubi's engines) + * then an index to those types. Some games leave a companion .bnh with text info, probably leftover from their tools. + * Game seems to play files by calling linked ids: EventResData (play/stop/etc) > Random/Program/Wav ResData (1..N refs) > FileIdObj */ + + /* HX CONFIG */ + hx.big_endian = guess_endianness32bit(0x00, streamFile); + + /* HX HEADER */ + if (!parse_hx(&hx, streamFile, target_subsong)) + goto fail; + + /* CREATE VGMSTREAM */ + vgmstream = init_vgmstream_ubi_hx_header(&hx, streamFile); + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + + +static void build_readable_name(char * buf, size_t buf_size, ubi_hx_header * hx) { + const char *grp_name; + + if (hx->is_external) + grp_name = hx->resource_name; + else + grp_name = "internal"; + + if (hx->internal_name[0]) + snprintf(buf,buf_size, "%s/%i/%08x-%08x/%s/%s", "hx", hx->header_index, hx->cuuid1,hx->cuuid2, grp_name, hx->internal_name); + else + snprintf(buf,buf_size, "%s/%i/%08x-%08x/%s", "hx", hx->header_index, hx->cuuid1,hx->cuuid2, grp_name); +} + +#define TXT_LINE_MAX 0x1000 + +/* get name */ +static int parse_name_bnh(ubi_hx_header * hx, STREAMFILE *sf, uint32_t cuuid1, uint32_t cuuid2) { + STREAMFILE *sf_t; + off_t txt_offset = 0; + char line[TXT_LINE_MAX]; + char cuuid[40]; + + sf_t = open_streamfile_by_ext(sf,"bnh"); + if (sf_t == NULL) goto fail; + + snprintf(cuuid,sizeof(cuuid), "cuuid( 0x%08x, 0x%08x )", cuuid1, cuuid2); + + /* each .bnh line has a cuuid, a bunch of repeated fields and name (sometimes name is filename or "bad name") */ + while (txt_offset < get_streamfile_size(sf)) { + int line_ok, bytes_read; + + bytes_read = read_line(line, sizeof(line), txt_offset, sf_t, &line_ok); + if (!line_ok) break; + txt_offset += bytes_read; + + if (strncmp(line,cuuid,31) != 0) + continue; + if (bytes_read <= 79) + goto fail; + + /* cuuid found, copy name (lines are fixed and always starts from the same position) */ + strcpy(hx->internal_name, &line[79]); + + close_streamfile(sf_t); + return 1; + } + +fail: + close_streamfile(sf_t); + return 0; +} + + +/* get referenced name from WavRes, using the index again (abridged) */ +static int parse_name(ubi_hx_header * hx, STREAMFILE *sf) { + int32_t (*read_32bit)(off_t,STREAMFILE*) = hx->big_endian ? read_32bitBE : read_32bitLE; + off_t index_offset, offset; + int i, index_entries; + char class_name[255]; + + + index_offset = read_32bit(0x00, sf); + index_entries = read_32bit(index_offset + 0x08, sf); + offset = index_offset + 0x0c; + for (i = 0; i < index_entries; i++) { + off_t header_offset; + size_t class_size; + int j, link_count, language_count, is_found = 0; + uint32_t cuuid1, cuuid2; + + + class_size = read_32bit(offset + 0x00, sf); + if (class_size > sizeof(class_name)+1) goto fail; + read_string(class_name,class_size+1, offset + 0x04, sf); /* not null-terminated */ + offset += 0x04 + class_size; + + cuuid1 = (uint32_t)read_32bit(offset + 0x00, sf); + cuuid2 = (uint32_t)read_32bit(offset + 0x04, sf); + + header_offset = read_32bit(offset + 0x08, sf); + offset += 0x10; + + //unknown_count = read_32bit(offset + 0x00, sf); + offset += 0x04; + + link_count = read_32bit(offset + 0x00, sf); + offset += 0x04; + for (j = 0; j < link_count; j++) { + uint32_t link_id1 = (uint32_t)read_32bit(offset + 0x00, sf); + uint32_t link_id2 = (uint32_t)read_32bit(offset + 0x04, sf); + + if (link_id1 == hx->cuuid1 && link_id2 == hx->cuuid2) { + is_found = 1; + } + offset += 0x08; + } + + language_count = read_32bit(offset + 0x00, sf); + offset += 0x04; + for (j = 0; j < language_count; j++) { + uint32_t link_id1 = (uint32_t)read_32bit(offset + 0x08, sf); + uint32_t link_id2 = (uint32_t)read_32bit(offset + 0x0c, sf); + + if (link_id1 == hx->cuuid1 && link_id2 == hx->cuuid2) { + is_found = 1; + } + + offset += 0x10; + } + + /* identify all possible names so unknown platforms fail */ + if (is_found && ( + strcmp(class_name, "CPCWavResData") == 0 || + strcmp(class_name, "CPS2WavResData") == 0 || + strcmp(class_name, "CGCWavResData") == 0 || + strcmp(class_name, "CXBoxWavResData") == 0 || + strcmp(class_name, "CPS3WavResData") == 0)) { + size_t resclass_size, internal_size; + off_t wavres_offset = header_offset; + + /* parse WavRes header */ + resclass_size = read_32bit(wavres_offset, sf); + wavres_offset += 0x04 + resclass_size + 0x08 + 0x04; /* skip class + cuiid + flags */ + + internal_size = read_32bit(wavres_offset + 0x00, sf); + /* Xbox has some kind of big size and "flags" has a value of 2, instead of 3/4 like other platforms */ + if (strcmp(class_name, "CXBoxWavResData") == 0 && internal_size > 0x100) + return 1; + if (internal_size > sizeof(hx->internal_name)+1) + goto fail; + + /* usually 0 in consoles */ + if (internal_size != 0) { + read_string(hx->internal_name,internal_size+1, wavres_offset + 0x04, sf); + return 1; + } + else { + parse_name_bnh(hx, sf, cuuid1, cuuid2); + return 1; /* ignore error */ + } + } + } + +fail: + return 0; +} + + +/* parse a single known header resource at offset */ +static int parse_header(ubi_hx_header * hx, STREAMFILE *sf, off_t offset, size_t size, int index) { + int32_t (*read_32bit)(off_t,STREAMFILE*) = hx->big_endian ? read_32bitBE : read_32bitLE; + int16_t (*read_16bit)(off_t,STREAMFILE*) = hx->big_endian ? read_16bitBE : read_16bitLE; + off_t riff_offset, riff_size, chunk_offset, stream_adjust = 0, resource_size; + size_t chunk_size; + int cue_flag = 0; + + //todo cleanup/unify common readings + + //;VGM_LOG("UBI HX: header o=%lx, s=%x\n\n", offset, size); + + hx->header_index = index; + hx->header_offset = offset; + hx->header_size = size; + + hx->class_size = read_32bit(offset + 0x00, sf); + if (hx->class_size > sizeof(hx->class_name)+1) goto fail; + read_string(hx->class_name,hx->class_size+1, offset + 0x04, sf); + offset += 0x04 + hx->class_size; + + hx->cuuid1 = (uint32_t)read_32bit(offset + 0x00, sf); + hx->cuuid2 = (uint32_t)read_32bit(offset + 0x04, sf); + offset += 0x08; + + if (strcmp(hx->class_name, "CPCWaveFileIdObj") == 0 || + strcmp(hx->class_name, "CPS2WaveFileIdObj") == 0 || + strcmp(hx->class_name, "CGCWaveFileIdObj") == 0 || + strcmp(hx->class_name, "CXBoxWaveFileIdObj") == 0) { + uint32_t flag_type = read_32bit(offset + 0x00, sf); + + if (flag_type == 0x01 || flag_type == 0x02) { /* Rayman Arena */ + if (read_32bit(offset + 0x04, sf) != 0x00) goto fail; + hx->stream_mode = read_32bit(offset + 0x08, sf); /* flag: 0=internal, 1=external */ + /* 0x0c: flag: 0=static, 1=stream */ + offset += 0x10; + } + else if (flag_type == 0x03) { /* others */ + /* 0x04: some kind of parent id shared by multiple Waves, or 0 */ + offset += 0x08; + + if (strcmp(hx->class_name, "CGCWaveFileIdObj") == 0) { + if (read_32bit(offset + 0x00, sf) != read_32bit(offset + 0x04, sf)) goto fail; /* meaning? */ + hx->stream_mode = read_32bit(offset + 0x04, sf); + offset += 0x08; + } + else { + hx->stream_mode = read_8bit(offset, sf); + offset += 0x01; + } + } + else { + VGM_LOG("UBI HX: unknown flag-type\n"); + goto fail; + } + + /* get bizarro adjust (found in XIII external files) */ + if (hx->stream_mode == 0x0a) { + stream_adjust = read_32bit(offset, sf); /* what */ + offset += 0x04; + } + + //todo probably a flag: &1=external, &2=stream, &8=has adjust (XIII), &4=??? (XIII PS2, small, mono) + switch(hx->stream_mode) { + case 0x00: /* memory (internal file) */ + riff_offset = offset; + riff_size = read_32bit(riff_offset + 0x04, sf) + 0x08; + break; + + case 0x01: /* static (smaller external file) */ + case 0x03: /* stream (bigger external file) */ + case 0x07: /* static? */ + case 0x0a: /* static? */ + resource_size = read_32bit(offset + 0x00, sf); + if (resource_size > sizeof(hx->resource_name)+1) goto fail; + read_string(hx->resource_name,resource_size+1, offset + 0x04, sf); + + riff_offset = offset + 0x04 + resource_size; + riff_size = read_32bit(riff_offset + 0x04, sf) + 0x08; + + hx->is_external = 1; + break; + + default: + goto fail; + } + + + /* parse pseudo-RIFF "fmt" */ + if (read_32bit(riff_offset, sf) != 0x46464952) /* "RIFF" in machine endianness */ + goto fail; + + hx->codec_id = read_16bit(riff_offset + 0x14 , sf); + switch(hx->codec_id) { + case 0x01: hx->codec = PCM; break; + case 0x02: hx->codec = UBI; break; + case 0x03: hx->codec = PSX; break; + case 0x04: hx->codec = DSP; break; + case 0x05: hx->codec = XIMA; break; + default: + VGM_LOG("UBI HX: unknown codec %i\n", hx->codec_id); + goto fail; + } + hx->channels = read_16bit(riff_offset + 0x16, sf); + hx->sample_rate = read_32bit(riff_offset + 0x18, sf); + + /* find "datx" (external) or "data" (internal) also in machine endianness */ + if (hx->is_external) { + if (find_chunk_riff_ve(sf, 0x78746164,riff_offset + 0x0c,riff_size - 0x0c, &chunk_offset,NULL, hx->big_endian)) { + hx->stream_size = read_32bit(chunk_offset + 0x00, sf); + hx->stream_offset = read_32bit(chunk_offset + 0x04, sf) + stream_adjust; + } + else if ((flag_type == 0x01 || flag_type == 0x02) && /* Rayman M (not Arena) uses "data" instead */ + find_chunk_riff_ve(sf, 0x61746164,riff_offset + 0x0c,riff_size - 0x0c, &chunk_offset,&chunk_size, hx->big_endian)) { + hx->stream_size = chunk_size; + hx->stream_offset = read_32bit(chunk_offset + 0x00, sf) + stream_adjust; + } + else { + goto fail; + } + } + else { + if (!find_chunk_riff_ve(sf, 0x61746164,riff_offset + 0x0c,riff_size - 0x0c, &chunk_offset,NULL, hx->big_endian)) + goto fail; + hx->stream_offset = chunk_offset; + hx->stream_size = riff_size - (chunk_offset - riff_offset); + } + + /* can contain other RIFF stuff like "cue ", "labl" and "ump3" + * XIII music uses cue/labl to play/loop dynamic sections */ + } + else if (strcmp(hx->class_name, "CXBoxStaticHWWaveFileIdObj") == 0 || + strcmp(hx->class_name, "CXBoxStreamHWWaveFileIdObj") == 0 || + strcmp(hx->class_name, "CPS3StaticAC3WaveFileIdObj") == 0 || + strcmp(hx->class_name, "CPS3StreamAC3WaveFileIdObj") == 0) { + + hx->stream_offset = read_32bit(offset + 0x00, sf); + hx->stream_size = read_32bit(offset + 0x04, sf); + offset += 0x08; + + //todo some dummy files have 0 size + + if (read_32bit(offset + 0x00, sf) != 0x01) goto fail; + /* 0x04: some kind of parent id shared by multiple Waves, or 0 */ + offset += 0x08; + + hx->stream_mode = read_8bit(offset, sf); + offset += 0x01; + + if ((strcmp(hx->class_name, "CXBoxStaticHWWaveFileIdObj") == 0 || + strcmp(hx->class_name, "CXBoxStreamHWWaveFileIdObj") == 0) && !hx->big_endian) { + /* micro header: some mix of channels + block size + sample rate + flags, unsure of which bits */ + hx->codec = XIMA; + hx->channels = (uint8_t)read_8bit(offset + 0x01, sf); + switch(hx->channels) { /* upper 2 bits? */ + case 0x48: hx->channels = 1; break; + case 0x90: hx->channels = 2; break; + default: goto fail; + } + hx->sample_rate = (uint16_t)(read_16bit(offset + 0x02, sf) & 0x7FFF) << 1; /* ??? */ + cue_flag = (uint8_t) read_8bit (offset + 0x03, sf) & (1<<7); + offset += 0x04; + } + else if ((strcmp(hx->class_name, "CXBoxStaticHWWaveFileIdObj") == 0 || + strcmp(hx->class_name, "CXBoxStreamHWWaveFileIdObj") == 0) && hx->big_endian) { + /* fake fmt chunk */ + hx->codec = XMA2; + hx->channels = (uint16_t)read_16bit(offset + 0x02, sf); + hx->sample_rate = read_32bit(offset + 0x04, sf); + hx->num_samples = read_32bit(offset + 0x18, sf) / 0x02 / hx->channels; + cue_flag = read_32bit(offset + 0x34, sf); + offset += 0x38; + } + else { + /* MSFC header */ + hx->codec = ATRAC3; + hx->codec_id = read_32bit(offset + 0x04, sf); + hx->channels = read_32bit(offset + 0x08, sf); + hx->sample_rate = read_32bit(offset + 0x10, sf); + cue_flag = read_32bit(offset + 0x40, sf); + offset += 0x44; + } + + /* skip cue table that sometimes exists in streams */ + if (cue_flag) { + int j; + + size_t cue_count = read_32bit(offset, sf); + offset += 0x04; + for (j = 0; j < cue_count; j++) { + /* 0x00: id? */ + size_t description_size = read_32bit(offset + 0x04, sf); /* for next string */ + offset += 0x08 + description_size; + } + } + + + switch(hx->stream_mode) { + case 0x01: /* static (smaller external file) */ + case 0x03: /* stream (bigger external file) */ + case 0x07: /* stream? */ + resource_size = read_32bit(offset + 0x00, sf); + if (resource_size > sizeof(hx->resource_name)+1) goto fail; + read_string(hx->resource_name,resource_size+1, offset + 0x04, sf); + + hx->is_external = 1; + break; + + default: + goto fail; + } + } + else { + goto fail; + } + + return 1; +fail: + VGM_LOG("UBI HX: error parsing header at %lx\n", hx->header_offset); + return 0; +} + + +/* parse a bank index and its possible audio headers (some info from Droolie's .bms) */ +static int parse_hx(ubi_hx_header * hx, STREAMFILE *sf, int target_subsong) { + int32_t (*read_32bit)(off_t,STREAMFILE*) = hx->big_endian ? read_32bitBE : read_32bitLE; + off_t index_offset, offset; + int i, index_entries; + char class_name[255]; + + + index_offset = read_32bit(0x00, sf); + if (read_32bit(index_offset + 0x00, sf) != 0x58444E49) /* "XDNI" (INDX in given endianness) */ + goto fail; + if (read_32bit(index_offset + 0x04, sf) != 0x02) /* type? */ + goto fail; + + if (target_subsong == 0) target_subsong = 1; + + index_entries = read_32bit(index_offset + 0x08, sf); + offset = index_offset + 0x0c; + for (i = 0; i < index_entries; i++) { + off_t header_offset; + size_t class_size, header_size; + int j, unknown_count, link_count, language_count; + + //;VGM_LOG("UBI HX: index %i at %lx\n", i, offset); + + /* parse index entries: offset to actual header plus some extra info also in the header */ + + class_size = read_32bit(offset + 0x00, sf); + if (class_size > sizeof(class_name)+1) goto fail; + + read_string(class_name,class_size+1, offset + 0x04, sf); /* not null-terminated */ + offset += 0x04 + class_size; + + /* 0x00: id1+2 */ + header_offset = read_32bit(offset + 0x08, sf); + header_size = read_32bit(offset + 0x0c, sf); + offset += 0x10; + + /* not seen */ + unknown_count = read_32bit(offset + 0x00, sf); + if (unknown_count != 0) { + VGM_LOG("UBI HX: found unknown near %lx\n", offset); + goto fail; + } + offset += 0x04; + + /* ids that this object directly points to (ex. Event > Random) */ + link_count = read_32bit(offset + 0x00, sf); + offset += 0x04 + 0x08 * link_count; + + /* localized id list of WavRes (can use this list instead of the prev one) */ + language_count = read_32bit(offset + 0x00, sf); + offset += 0x04; + for (j = 0; j < language_count; j++) { + /* 0x00: lang code, in reverse endianness: "en ", "fr ", etc */ + /* 0x04: possibly count of ids for this lang */ + /* 0x08: id1+2 */ + + if (read_32bit(offset + 0x04, sf) != 1) { + VGM_LOG("UBI HX: wrong lang count near %lx\n", offset); + goto fail; /* WavRes doesn't have this field */ + } + offset += 0x10; + } + + //todo figure out CProgramResData sequences + // Format is pretty complex list of values and some offsets in between, then field names + // then more values and finally a list of linked IDs Links are the same as in the index, + // but doesn't seem to be a straight sequence list. Seems it can be used for other config too. + + /* identify all possible names so unknown platforms fail */ + if (strcmp(class_name, "CEventResData") == 0 || /* play/stop/etc event */ + strcmp(class_name, "CProgramResData") == 0 || /* some kind of map/object-like config to make sequences in some cases? */ + strcmp(class_name, "CActorResData") == 0 || /* same? */ + strcmp(class_name, "CRandomResData") == 0 || /* chooses random WavRes from a list */ + strcmp(class_name, "CTreeBank") == 0 || /* points to TreeRes? */ + strcmp(class_name, "CTreeRes") == 0 || /* points to TreeBank? */ + strcmp(class_name, "CSwitchResData") == 0 || /* big list of WavRes */ + strcmp(class_name, "CPCWavResData") == 0 || /* points to WaveFileIdObj */ + strcmp(class_name, "CPS2WavResData") == 0 || + strcmp(class_name, "CGCWavResData") == 0 || + strcmp(class_name, "CXBoxWavResData") == 0 || + strcmp(class_name, "CPS3WavResData") == 0) { + continue; + } + else if (strcmp(class_name, "CPCWaveFileIdObj") == 0 || + strcmp(class_name, "CPS2WaveFileIdObj") == 0 || + strcmp(class_name, "CGCWaveFileIdObj") == 0 || + strcmp(class_name, "CXBoxWaveFileIdObj") == 0 || + strcmp(class_name, "CXBoxStaticHWWaveFileIdObj") == 0 || + strcmp(class_name, "CXBoxStreamHWWaveFileIdObj") == 0 || + strcmp(class_name, "CPS3StaticAC3WaveFileIdObj") == 0 || + strcmp(class_name, "CPS3StreamAC3WaveFileIdObj") == 0) { + ; + } + else { + VGM_LOG("UBI HX: unknown type: %s\n", class_name); + goto fail; + } + + if (link_count != 0) { + VGM_LOG("UBI HX: found links in wav object\n"); + goto fail; + } + + hx->total_subsongs++; + if (hx->total_subsongs != target_subsong) + continue; + + if (!parse_header(hx, sf, header_offset, header_size, i)) + goto fail; + if (!parse_name(hx, sf)) + goto fail; + + build_readable_name(hx->readable_name,sizeof(hx->readable_name), hx); + } + + if (target_subsong < 0 || target_subsong > hx->total_subsongs || hx->total_subsongs < 1) goto fail; + + + return 1; +fail: + return 0; +} + + +static STREAMFILE * open_hx_streamfile(ubi_hx_header *hx, STREAMFILE *sf) { + STREAMFILE *streamData = NULL; + + + if (!hx->is_external) + return NULL; + + streamData = open_streamfile_by_filename(sf, hx->resource_name); + if (streamData == NULL) { + VGM_LOG("UBI HX: external stream '%s' not found\n", hx->resource_name); + goto fail; + } + + /* streams often have a "RIFF" with "fmt" and "data" but stream offset/size is already adjusted to skip them */ + + return streamData; +fail: + return NULL; +} + +static VGMSTREAM * init_vgmstream_ubi_hx_header(ubi_hx_header *hx, STREAMFILE *streamFile) { + STREAMFILE *streamTemp = NULL; + STREAMFILE *streamData = NULL; + VGMSTREAM* vgmstream = NULL; + + + if (hx->is_external) { + streamTemp = open_hx_streamfile(hx, streamFile); + if (streamTemp == NULL) goto fail; + streamData = streamTemp; + } + else { + streamData = streamFile; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(hx->channels, hx->loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_UBI_HX; + vgmstream->sample_rate = hx->sample_rate; + vgmstream->num_streams = hx->total_subsongs; + vgmstream->stream_size = hx->stream_size; + + switch(hx->codec) { + case PCM: + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + + vgmstream->num_samples = pcm_bytes_to_samples(hx->stream_size, hx->channels, 16); + break; + + case UBI: + vgmstream->codec_data = init_ubi_adpcm(streamData, hx->stream_offset, vgmstream->channels); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_UBI_ADPCM; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = ubi_adpcm_get_samples(vgmstream->codec_data); + /* XIII has 6-bit stereo music, Rayman 3 4-bit music, both use 6-bit mono) */ + break; + + case PSX: + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + + vgmstream->num_samples = ps_bytes_to_samples(hx->stream_size, hx->channels); + break; + + case DSP: + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x08; + + /* dsp header at start offset */ + vgmstream->num_samples = read_32bitBE(hx->stream_offset + 0x00, streamData); + dsp_read_coefs_be(vgmstream, streamData, hx->stream_offset + 0x1c, 0x60); + dsp_read_hist_be (vgmstream, streamData, hx->stream_offset + 0x40, 0x60); + hx->stream_offset += 0x60 * hx->channels; + hx->stream_size -= 0x60 * hx->channels; + break; + + case XIMA: + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = xbox_ima_bytes_to_samples(hx->stream_size, hx->channels); + break; + +#ifdef VGM_USE_FFMPEG + case XMA2: { + int bytes, block_count, block_size; + uint8_t buf[0x200]; + + block_size = 0x800; + block_count = hx->stream_size / block_size; + + bytes = ffmpeg_make_riff_xma2(buf,0x200, hx->num_samples, hx->stream_size, hx->channels, hx->sample_rate, block_count, block_size); + vgmstream->codec_data = init_ffmpeg_header_offset(streamData, buf,bytes, hx->stream_offset,hx->stream_size); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = hx->num_samples; + + xma_fix_raw_samples_ch(vgmstream, streamData, hx->stream_offset,hx->stream_size, hx->channels, 0,0); + break; + } + + case ATRAC3: { + int block_align, encoder_delay; + + encoder_delay = 1024 + 69*2; + switch(hx->codec_id) { + case 4: block_align = 0x60 * vgmstream->channels; break; + case 5: block_align = 0x98 * vgmstream->channels; break; + case 6: block_align = 0xC0 * vgmstream->channels; break; + default: goto fail; + } + + vgmstream->num_samples = atrac3_bytes_to_samples(hx->stream_size, block_align) - encoder_delay; + + vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamData, hx->stream_offset,hx->stream_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + break; + } +#endif + + default: + goto fail; + } + + strcpy(vgmstream->stream_name, hx->readable_name); + + if (!vgmstream_open_stream(vgmstream, streamData, hx->stream_offset)) + goto fail; + close_streamfile(streamTemp); + return vgmstream; + +fail: + close_streamfile(streamTemp); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vag.c b/Frameworks/vgmstream/vgmstream/src/meta/vag.c index 35ddc30c3..eba4bdb55 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vag.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vag.c @@ -190,16 +190,16 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) { channel_size = channel_size / channel_count; /* mono files also have channel/volume, but start at 0x30 and are probably named .vag */ } - else if (read_32bitBE(0x30,streamFile) == 0x53544552 /* "STER" */ - && read_32bitBE(0x34,streamFile) == 0x454F5641 /* "EOVA" */ - && read_32bitBE(0x38,streamFile) == 0x47324B00){ /* "G2K " */ + else if (read_32bitBE(0x30,streamFile) == 0x53544552 /* "STEREOVAG2K " */ + && read_32bitBE(0x34,streamFile) == 0x454F5641 + && read_32bitBE(0x38,streamFile) == 0x47324B00) { /* The Simpsons Skateboarding (PS2) */ start_offset = 0x800; channel_count = 2; interleave = 0x800; loop_flag = 0; } - else if (read_32bitBE(0x24, streamFile) == 0x56414778) { /* "VAGx" */ + else if (version == 0x00000002 && read_32bitBE(0x24, streamFile) == 0x56414778) { /* "VAGx" */ /* Need for Speed: Hot Pursuit 2 (PS2) */ start_offset = 0x30; channel_count = read_32bitBE(0x2c, streamFile); @@ -232,6 +232,16 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) { if (!interleave) goto fail; } } + else if (version == 0x00000020 && channel_size == file_size - 0x800 && read_32bitBE(0x08, streamFile) == 0x01) { + /* Garfield: Saving Arlene (PS2) */ + start_offset = 0x800; + channel_count = 2; + interleave = 0x400; + loop_flag = 0; + + channel_size -= ps_find_padding(streamFile, start_offset, channel_size, channel_count, interleave, 0); + channel_size = channel_size / channel_count; + } else { /* standard PS1/PS2/PS3 .vag [Ecco the Dolphin (PS2), Legasista (PS3)] */ start_offset = 0x30; @@ -313,7 +323,7 @@ VGMSTREAM* init_vgmstream_vag_aaap(STREAMFILE* streamFile) { } /* check version */ - if (read_u32be(vag_offset + 0x04, streamFile) != 0x20) + if (read_u32be(vag_offset + 0x04, streamFile) != 0x00000020) goto fail; channel_size = read_u32be(vag_offset + 0x0c, streamFile); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vsv.c b/Frameworks/vgmstream/vgmstream/src/meta/vsv.c index 8240fd285..8a98b56b4 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vsv.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vsv.c @@ -1,85 +1,85 @@ -#include "meta.h" -#include "../coding/coding.h" -#include "vsv_streamfile.h" - - -/* .VSV - from Square Enix games [Dawn of Mana: Seiken Densetsu 4 (PS2), Kingdom Hearts Re:Chain of Memories (PS2)] */ -VGMSTREAM * init_vgmstream_vsv(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; - off_t start_offset; - int loop_flag, channel_count, flags, sample_rate, is_rs; - size_t loop_start, adjust, data_size, interleave; - - - /* checks */ - /* .vsv: extension from internal filenames [KH Re:CoM (PS2), DoM (PS2), KH HD I.5 + II.5 ReMIX (PS4)] - * .psh: fake */ - if (!check_extensions(streamFile, "vsv,psh")) - goto fail; - - /* 0x00(1x4): flags/config? */ - if ((uint8_t)read_8bit(0x03,streamFile) > 0x64) /* possibly volume */ - goto fail; - if ((uint8_t)read_8bit(0x0a,streamFile) != 0) /* not seen */ - goto fail; - - /* Romancing SaGa (PS2) uses an earlier? version, this seems to work */ - is_rs = ((uint16_t)read_16bitLE(0x00,streamFile) == 0); - - start_offset = 0x00; /* correct, but needs some tricks to fix sound (see below) */ - interleave = 0x800; - - adjust = (uint16_t)read_16bitLE(0x04,streamFile); - loop_start = ((uint16_t)read_16bitLE(0x06,streamFile) & 0x7FFF) * interleave; - loop_flag = (uint16_t)read_16bitLE(0x06,streamFile) & 0x8000; /* loop_start != 0 works too, no files loop from beginning to end */ - sample_rate = (uint16_t)read_16bitLE(0x08,streamFile); - flags = (uint8_t)read_8bit (0x0b,streamFile); /* values: 0x01=stereo, 0x10=mono */ - data_size = (uint16_t)read_16bitLE(0x0c,streamFile) * interleave; - /* 0x0e: ? (may be a low-ish value) */ - - channel_count = (flags & 1) ? 2 : 1; - - /* must discard to avoid wrong loops and unwanted data (easier to see in voices) */ - if (!is_rs) { /* RS doesn't do this */ - /* adjust & 0xF800 is unknown (values=0x0000|0x0800|0xF800, can be mono/stereo, loop/no, adjust/no) */ - size_t discard = adjust & 0x07FF; - /* at (file_end - 0x800 + discard) is a 0x03 PS flag to check this (adjust 0 does discard full block) */ - data_size -= (0x800 - discard) * channel_count; - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_VSV; - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); - vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count); - vgmstream->loop_end_sample = vgmstream->num_samples; - - /* these loops are odd, but comparing the audio wave with the OSTs values seem correct */ - if (is_rs) { - vgmstream->loop_start_sample -= ps_bytes_to_samples(channel_count*interleave,channel_count); /* maybe *before* loop block? */ - vgmstream->loop_start_sample -= ps_bytes_to_samples(0x200*channel_count,channel_count); /* maybe default adjust? */ - } - - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; - - temp_streamFile = setup_vsv_streamfile(streamFile, start_offset, data_size); - if (!temp_streamFile) goto fail; - - if (!vgmstream_open_stream(vgmstream, temp_streamFile, start_offset)) - goto fail; - - close_streamfile(temp_streamFile); - return vgmstream; - -fail: - close_streamfile(temp_streamFile); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" +#include "vsv_streamfile.h" + + +/* .VSV - from Square Enix games [Dawn of Mana: Seiken Densetsu 4 (PS2), Kingdom Hearts Re:Chain of Memories (PS2)] */ +VGMSTREAM * init_vgmstream_vsv(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE *temp_streamFile = NULL; + off_t start_offset; + int loop_flag, channel_count, flags, sample_rate, is_rs; + size_t loop_start, adjust, data_size, interleave; + + + /* checks */ + /* .vsv: extension from internal filenames [KH Re:CoM (PS2), DoM (PS2), KH HD I.5 + II.5 ReMIX (PS4)] + * .psh: fake */ + if (!check_extensions(streamFile, "vsv,psh")) + goto fail; + + /* 0x00(1x4): flags/config? */ + if ((uint8_t)read_8bit(0x03,streamFile) > 0x64) /* possibly volume */ + goto fail; + if ((uint8_t)read_8bit(0x0a,streamFile) != 0) /* not seen */ + goto fail; + + /* Romancing SaGa (PS2) uses an earlier? version, this seems to work */ + is_rs = ((uint16_t)read_16bitLE(0x00,streamFile) == 0); + + start_offset = 0x00; /* correct, but needs some tricks to fix sound (see below) */ + interleave = 0x800; + + adjust = (uint16_t)read_16bitLE(0x04,streamFile); + loop_start = ((uint16_t)read_16bitLE(0x06,streamFile) & 0x7FFF) * interleave; + loop_flag = (uint16_t)read_16bitLE(0x06,streamFile) & 0x8000; /* loop_start != 0 works too, no files loop from beginning to end */ + sample_rate = (uint16_t)read_16bitLE(0x08,streamFile); + flags = (uint8_t)read_8bit (0x0b,streamFile); /* values: 0x01=stereo, 0x10=mono */ + data_size = (uint16_t)read_16bitLE(0x0c,streamFile) * interleave; + /* 0x0e: ? (may be a low-ish value) */ + + channel_count = (flags & 1) ? 2 : 1; + + /* must discard to avoid wrong loops and unwanted data (easier to see in voices) */ + if (!is_rs) { /* RS doesn't do this */ + /* adjust & 0xF800 is unknown (values=0x0000|0x0800|0xF800, can be mono/stereo, loop/no, adjust/no) */ + size_t discard = adjust & 0x07FF; + /* at (file_end - 0x800 + discard) is a 0x03 PS flag to check this (adjust 0 does discard full block) */ + data_size -= (0x800 - discard) * channel_count; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_VSV; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); + vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count); + vgmstream->loop_end_sample = vgmstream->num_samples; + + /* these loops are odd, but comparing the audio wave with the OSTs values seem correct */ + if (is_rs) { + vgmstream->loop_start_sample -= ps_bytes_to_samples(channel_count*interleave,channel_count); /* maybe *before* loop block? */ + vgmstream->loop_start_sample -= ps_bytes_to_samples(0x200*channel_count,channel_count); /* maybe default adjust? */ + } + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + + temp_streamFile = setup_vsv_streamfile(streamFile); + if (!temp_streamFile) goto fail; + + if (!vgmstream_open_stream(vgmstream, temp_streamFile, start_offset)) + goto fail; + + close_streamfile(temp_streamFile); + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vsv_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/vsv_streamfile.h index 2f62fa0c0..dd546a63f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vsv_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/vsv_streamfile.h @@ -1,53 +1,40 @@ -#ifndef _VSV_STREAMFILE_H_ -#define _VSV_STREAMFILE_H_ -#include "../streamfile.h" - -typedef struct { - off_t null_offset; -} vsv_io_data; - -static size_t vsv_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, vsv_io_data* data) { - size_t bytes_read; - int i; - - bytes_read = streamfile->read(streamfile, dest, offset, length); - - /* VSVs do start at 0x00, but first line is also the header; must null it to avoid clicks */ - if (offset < data->null_offset) { - int max = data->null_offset - offset; - if (max > bytes_read) - max = bytes_read; - - for (i = 0; i < max; i++) { - dest[i] = 0; - } - } - /* VSV also has last 0x800 block with a PS-ADPCM flag of 0x10 (incorrect), but it's ignored by the decoder */ - - return bytes_read; -} - -static STREAMFILE* setup_vsv_streamfile(STREAMFILE *streamFile, off_t start_offset, size_t data_size) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - vsv_io_data io_data = {0}; - size_t io_data_size = sizeof(vsv_io_data); - - io_data.null_offset = 0x10; - - /* setup custom streamfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, vsv_io_read,NULL); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -#endif /* _VSV_STREAMFILE_H_ */ +#ifndef _VSV_STREAMFILE_H_ +#define _VSV_STREAMFILE_H_ +#include "../streamfile.h" + +typedef struct { + off_t null_offset; +} vsv_io_data; + +static size_t vsv_io_read(STREAMFILE *sf, uint8_t *dest, off_t offset, size_t length, vsv_io_data *data) { + int i; + size_t bytes = read_streamfile(dest, offset, length, sf); + + /* VSVs do start at 0x00, but first line is also the header; must null it to avoid clicks */ + if (offset < data->null_offset) { + int max = data->null_offset - offset; + if (max > bytes) + max = bytes; + + for (i = 0; i < max; i++) { + dest[i] = 0; + } + } + /* VSV also has last 0x800 block with a PS-ADPCM flag of 0x10 (incorrect), but it's ignored by the decoder */ + + return bytes; +} + +/* cleans VSV data */ +static STREAMFILE* setup_vsv_streamfile(STREAMFILE *sf) { + STREAMFILE *new_sf = NULL; + vsv_io_data io_data = {0}; + + io_data.null_offset = 0x10; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_streamfile_f(new_sf, &io_data, sizeof(vsv_io_data), vsv_io_read, NULL); + return new_sf; +} + +#endif /* _VSV_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/x360_pasx.c b/Frameworks/vgmstream/vgmstream/src/meta/x360_pasx.c index 44d6819fb..45b60c5d2 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/x360_pasx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/x360_pasx.c @@ -1,69 +1,71 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* PASX - from SoulCalibur II HD (X360) */ -VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset, chunk_offset; - size_t data_size, chunk_size; - int loop_flag, channel_count, sample_rate; - int num_samples, loop_start_sample, loop_end_sample; - - - /* checks */ - if ( !check_extensions(streamFile,"past")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x50415358) /* "PASX" */ - goto fail; - - - /* custom header with a "fmt " data chunk inside */ - chunk_size = read_32bitBE(0x08,streamFile); - data_size = read_32bitBE(0x0c,streamFile); - chunk_offset = read_32bitBE(0x10,streamFile); /* 0x14: fmt offset end */ - start_offset = read_32bitBE(0x18,streamFile); - - channel_count = read_16bitBE(chunk_offset+0x02,streamFile); - sample_rate = read_32bitBE(chunk_offset+0x04,streamFile); - xma2_parse_fmt_chunk_extra(streamFile, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1); - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples; - vgmstream->loop_start_sample = loop_start_sample; - vgmstream->loop_end_sample = loop_end_sample; - vgmstream->meta_type = meta_X360_PASX; - -#ifdef VGM_USE_FFMPEG - { - uint8_t buf[0x100]; - size_t bytes; - - bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, 1); - if (bytes <= 0) goto fail; - - vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); - if ( !vgmstream->codec_data ) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - - xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1); - } -#else - goto fail; -#endif - - - /* open the file for reading */ - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* PASX - from Premium Agency games [SoulCalibur II HD (X360), Death By Cube (X360)] */ +VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, chunk_offset; + size_t data_size, chunk_size; + int loop_flag, channel_count, sample_rate; + int num_samples, loop_start_sample, loop_end_sample; + + + /* checks */ + /* .past: Soul Calibur II HD + * .sgb: Death By Cube */ + if ( !check_extensions(streamFile,"past,sgb")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x50415358) /* "PASX" */ + goto fail; + + + /* custom header with a "fmt " data chunk inside */ + chunk_size = read_32bitBE(0x08,streamFile); + data_size = read_32bitBE(0x0c,streamFile); + chunk_offset = read_32bitBE(0x10,streamFile); /* 0x14: fmt offset end */ + start_offset = read_32bitBE(0x18,streamFile); + + channel_count = read_16bitBE(chunk_offset+0x02,streamFile); + sample_rate = read_32bitBE(chunk_offset+0x04,streamFile); + xma2_parse_fmt_chunk_extra(streamFile, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = loop_end_sample; + vgmstream->meta_type = meta_X360_PASX; + +#ifdef VGM_USE_FFMPEG + { + uint8_t buf[0x100]; + size_t bytes; + + bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, 1); + if (bytes <= 0) goto fail; + + vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); + if ( !vgmstream->codec_data ) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1); + } +#else + goto fail; +#endif + + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xa.c b/Frameworks/vgmstream/vgmstream/src/meta/xa.c index a2de512a1..49417cc57 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xa.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xa.c @@ -22,8 +22,9 @@ VGMSTREAM * init_vgmstream_xa(STREAMFILE *streamFile) { /* .xa: common * .str: often videos and sometimes speech/music * .adp: Phantasy Star Collection (SAT) raw XA + * .pxa: Mortal Kombat 4 (PS1) * (extensionless): bigfiles [Castlevania: Symphony of the Night (PS1)] */ - if (!check_extensions(streamFile,"xa,str,adp,")) + if (!check_extensions(streamFile,"xa,str,adp,pxa,")) goto fail; /* Proper XA comes in raw (BIN 2352 mode2/form2) CD sectors, that contain XA subheaders. diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xavs_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/xavs_streamfile.h index ac5e7d3b3..62aa10568 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xavs_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/xavs_streamfile.h @@ -1,160 +1,61 @@ -#ifndef _XAVS_STREAMFILE_H_ -#define _XAVS_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - /* config */ - off_t stream_offset; - size_t stream_size; - int stream_number; - - /* state */ - off_t logical_offset; /* fake offset */ - off_t physical_offset; /* actual offset */ - size_t block_size; /* current size */ - size_t skip_size; /* size from block start to reach data */ - size_t data_size; /* usable size in a block */ - - size_t logical_size; -} xavs_io_data; - - -static size_t xavs_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, xavs_io_data* data) { - size_t total_read = 0; - - - /* re-start when previous offset (can't map logical<>physical offsets) */ - if (data->logical_offset < 0 || offset < data->logical_offset) { - data->physical_offset = data->stream_offset; - data->logical_offset = 0x00; - data->data_size = 0; - } - - /* read blocks */ - while (length > 0) { - - /* ignore EOF */ - if (offset < 0 || data->physical_offset >= data->stream_offset + data->stream_size) { - break; - } - - /* process new block */ - if (data->data_size == 0) { - uint32_t chunk_id = read_32bitLE(data->physical_offset+0x00, streamfile) & 0xFF; - uint32_t chunk_size = read_32bitLE(data->physical_offset+0x00, streamfile) >> 8; - - data->skip_size = 0x04; - - switch(chunk_id) { - /* audio */ - case 0x41: - case 0x61: - case 0x62: - case 0x63: - data->block_size = 0x04 + chunk_size; - if (data->stream_number + 1 == (chunk_id & 0x0F)) { - data->data_size = chunk_size; - } else { - data->data_size = 0; /* ignore other subsongs */ - } - break; - - /* video */ - case 0x56: - data->block_size = 0x04 + chunk_size; - data->data_size = 0; - break; - - /* empty */ - case 0x21: /* related to video */ - case 0x5F: /* "_EOS" */ - data->block_size = 0x04; - data->data_size = 0; - break; - - default: - VGM_LOG("XAVS: unknown type at %lx\n", data->physical_offset); - data->block_size = 0x04; - data->data_size = 0; - break; - } - } - - /* move to next block */ - if (data->data_size == 0 || offset >= data->logical_offset + data->data_size) { - data->physical_offset += data->block_size; - data->logical_offset += data->data_size; - data->data_size = 0; - continue; - } - - /* read data */ - { - size_t bytes_consumed, bytes_done, to_read; - - bytes_consumed = offset - data->logical_offset; - to_read = data->data_size - bytes_consumed; - if (to_read > length) - to_read = length; - bytes_done = read_streamfile(dest, data->physical_offset + data->skip_size + bytes_consumed, to_read, streamfile); - - total_read += bytes_done; - dest += bytes_done; - offset += bytes_done; - length -= bytes_done; - - if (bytes_done != to_read || bytes_done == 0) { - break; /* error/EOF */ - } - } - } - - return total_read; -} - -static size_t xavs_io_size(STREAMFILE *streamfile, xavs_io_data* data) { - uint8_t buf[1]; - - if (data->logical_size) - return data->logical_size; - - /* force a fake read at max offset, to get max logical_offset (will be reset next read) */ - xavs_io_read(streamfile, buf, 0x7FFFFFFF, 1, data); - data->logical_size = data->logical_offset; - - return data->logical_size; -} - -/* Handles deinterleaving of XAVS blocked streams */ -static STREAMFILE* setup_xavs_streamfile(STREAMFILE *streamFile, off_t stream_offset, int stream_number) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - xavs_io_data io_data = {0}; - size_t io_data_size = sizeof(xavs_io_data); - - io_data.stream_offset = stream_offset; - io_data.stream_size = get_streamfile_size(streamFile) - stream_offset; - io_data.stream_number = stream_number; - io_data.logical_offset = -1; /* force phys offset reset */ - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(new_streamFile, &io_data,io_data_size, xavs_io_read,xavs_io_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_buffer_streamfile(new_streamFile,0); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -#endif /* _XAVS_STREAMFILE_H_ */ +#ifndef _XAVS_STREAMFILE_H_ +#define _XAVS_STREAMFILE_H_ +#include "deblock_streamfile.h" + +static void block_callback(STREAMFILE *sf, deblock_io_data *data) { + uint32_t chunk_type = read_u32le(data->physical_offset, sf) & 0xFF; + uint32_t chunk_size = read_u32le(data->physical_offset, sf) >> 8; + + data->skip_size = 0x04; + + switch(chunk_type) { + /* audio */ + case 0x41: + case 0x61: + case 0x62: + case 0x63: + data->block_size = 0x04 + chunk_size; + if (data->cfg.track_number + 1 == (chunk_type & 0x0F)) { + data->data_size = chunk_size; + } else { + data->data_size = 0; /* ignore other subsongs */ + } + break; + + /* video */ + case 0x56: + data->block_size = 0x04 + chunk_size; + data->data_size = 0; + break; + + /* empty */ + case 0x21: /* related to video */ + case 0x5F: /* "_EOS" */ + data->block_size = 0x04; + data->data_size = 0; + break; + + default: + VGM_LOG("XAVS: unknown type at %lx\n", data->physical_offset); + data->block_size = 0x04; + data->data_size = 0; + break; + } +} + +/* Deblocks XAVS video/audio data */ +static STREAMFILE* setup_xavs_streamfile(STREAMFILE *sf, off_t stream_offset, int stream_number) { + STREAMFILE *new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.stream_start = stream_offset; + cfg.track_number = stream_number; + cfg.block_callback = block_callback; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + //new_sf = open_buffer_streamfile(new_sf,0); + return new_sf; +} + +#endif /* _XAVS_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xmv_valve.c b/Frameworks/vgmstream/vgmstream/src/meta/xmv_valve.c index c0e587521..9573b6128 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xmv_valve.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xmv_valve.c @@ -35,6 +35,9 @@ VGMSTREAM *init_vgmstream_xbox_hlwav(STREAMFILE *streamFile) { default: goto fail; } + if (channels > 2) /* Source only supports mono and stereo */ + goto fail; + loop_flag = (loop_start != -1); /* build the VGMSTREAM */ @@ -73,7 +76,7 @@ fail: return NULL; } -/* .360.WAV, .PS3.WAV - from Valve games running on Source Engine, evolution of Xbox .WAV format */ +/* .360.WAV, .PS3.WAV - from Valve games running on Source Engine, evolution of Xbox .WAV format seen above */ /* [The Orange Box (X360), Portal 2 (PS3/X360), Counter-Strike: Global Offensive (PS3/X360)] */ VGMSTREAM *init_vgmstream_xmv_valve(STREAMFILE *streamFile) { VGMSTREAM *vgmstream = NULL; @@ -116,6 +119,9 @@ VGMSTREAM *init_vgmstream_xmv_valve(STREAMFILE *streamFile) { default: goto fail; } + if (channels > 2) /* Source only supports mono and stereo */ + goto fail; + loop_flag = (loop_start != -1); /* build the VGMSTREAM */ @@ -163,6 +169,9 @@ VGMSTREAM *init_vgmstream_xmv_valve(STREAMFILE *streamFile) { mpeg_codec_data *mpeg_data; coding_t mpeg_coding; + if (loop_flag) /* should never happen, Source cannot loop MP3 */ + goto fail; + mpeg_data = init_mpeg(streamFile, start_offset, &mpeg_coding, channels); if (!mpeg_data) goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwc.c b/Frameworks/vgmstream/vgmstream/src/meta/xwc.c index dcd1e4fa3..3bd30ac25 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwc.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwc.c @@ -74,17 +74,30 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) { #ifdef VGM_USE_FFMPEG case 0x584D4100: { /* "XMA\0" (X360) */ uint8_t buf[0x100]; - int32_t bytes, seek_size, block_size, block_count, sample_rate; + int32_t bytes, seek_size, block_size, block_count, sample_rate, chunk_size; - seek_size = read_32bitLE(extra_offset+0x00, streamFile); - start_offset = extra_offset+0x04 + seek_size + read_32bitLE(extra_offset+0x04+seek_size, streamFile) + 0x08; + seek_size = read_32bitLE(extra_offset + 0x00, streamFile); + chunk_size = read_32bitLE(extra_offset + 0x04 + seek_size, streamFile); + + start_offset = extra_offset+ 0x04 + seek_size + chunk_size + 0x08; start_offset += (start_offset % 0x800) ? 0x800 - (start_offset % 0x800) : 0; /* padded */ data_size = data_size - start_offset; - sample_rate = read_32bitBE(extra_offset+0x04+seek_size+0x10, streamFile); - block_size = read_32bitBE(extra_offset+0x04+seek_size+0x1c, streamFile); - block_count = read_32bitBE(extra_offset+0x04+seek_size+0x28, streamFile); - /* others: scrambled RIFF fmt BE values */ + if (chunk_size == 0x34) { /* new XMA2 */ + sample_rate = read_32bitLE(extra_offset+0x04+seek_size+0x08, streamFile); + block_size = read_32bitLE(extra_offset+0x04+seek_size+0x20, streamFile); + block_count = data_size / block_size; + /* others: standard RIFF XMA2 fmt? */ + } + else if (chunk_size == 0x2c) { /* old XMA2 */ + sample_rate = read_32bitBE(extra_offset+0x04+seek_size+0x10, streamFile); + block_size = read_32bitBE(extra_offset+0x04+seek_size+0x1c, streamFile); + block_count = read_32bitBE(extra_offset+0x04+seek_size+0x28, streamFile); + /* others: scrambled RIFF fmt BE values */ + } + else { + goto fail; + } bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, sample_rate, block_count, block_size); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/zsnd.c b/Frameworks/vgmstream/vgmstream/src/meta/zsnd.c index 63d1e9b78..72c990aed 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/zsnd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/zsnd.c @@ -1,224 +1,324 @@ -#include "meta.h" -#include "../coding/coding.h" -#include "zsnd_streamfile.h" - - -/* ZSND - Vicarious Visions games [X-Men Legends II (multi), Marvel Ultimate Alliance (multi)] */ -VGMSTREAM * init_vgmstream_zsnd(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; - off_t start_offset, name_offset; - size_t stream_size, name_size; - int loop_flag, channel_count, sample_rate, layers; - uint32_t codec; - int total_subsongs, target_subsong = streamFile->stream_index; - int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; - - - /* checks */ - /* .zss/zsm: standard, .ens/enm: same for PS2 */ - if (!check_extensions(streamFile, "zss,zsm,ens,enm")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x5A534E44) /* "ZSND" */ - goto fail; - /* probably zss=stream, zsm=memory; no diffs other than size */ - - codec = read_32bitBE(0x04,streamFile); - /* 0x08: file size, but slightly bigger (+0x01~04) in some platforms */ - /* 0x0c: header end/first stream start (unneeded as all offsets are absolute) */ - - if (codec == 0x47435542) { /* "GCUB" */ - read_32bit = read_32bitBE; - read_16bit = read_16bitBE; - } - else { - read_32bit = read_32bitLE; - read_16bit = read_16bitLE; - } - - - /* parse header tables (7*0x0c) */ - { - off_t header2_offset, header3_offset; - - /* table2: stream head */ - int table2_entries = read_32bit(0x1c,streamFile); - //off_t table2_head = read_32bit(0x20,streamFile); - off_t table2_body = read_32bit(0x24,streamFile); - - /* table3: stream body */ - int table3_entries = read_32bit(0x28,streamFile); - //off_t table3_head = read_32bit(0x2c,streamFile); - off_t table3_body = read_32bit(0x30,streamFile); - - /* table1: stream cues? (entry=0x18) - * tables 4-7 seem reserved with 0 entries and offsets to header end, - * though table5 can be seen in boss4_m.zsm (1 entry) */ - - /* table heads are always 0x08 * entries */ - /* 0x00 = ? (varies between tables but consistent between platforms) */ - /* 0x04 = id? (also in table2_body at 0x00?) */ - - /* table1 may have more entries than table2/3 */ - if (table2_entries != table3_entries) { - VGM_LOG("ZSND: table2/3 entries don't match\n"); - goto fail; - } - - - total_subsongs = table2_entries; - if (target_subsong == 0) target_subsong = 1; - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - - switch (codec) { - case 0x50432020: /* "PC " */ - header2_offset = table2_body + 0x18*(target_subsong-1); - header3_offset = table3_body + 0x4c*(target_subsong-1); - - layers = read_16bit(header2_offset + 0x02,streamFile); - sample_rate = read_32bit(header2_offset + 0x04,streamFile); - start_offset = read_32bit(header3_offset + 0x00,streamFile); - stream_size = read_32bit(header3_offset + 0x04,streamFile); - name_offset = header3_offset + 0x0c; - name_size = 0x40; - break; - - case 0x58424F58: /* "XBOX" */ - header2_offset = table2_body + 0x1c*(target_subsong-1); - header3_offset = table3_body + 0x54*(target_subsong-1); - - layers = read_16bit(header2_offset + 0x02,streamFile); - sample_rate = read_32bit(header2_offset + 0x04,streamFile); - start_offset = read_32bit(header3_offset + 0x00,streamFile); - stream_size = read_32bit(header3_offset + 0x04,streamFile); - name_offset = header3_offset + 0x14; - name_size = 0x40; - break; - - case 0x50533220: /* "PS2 " (also for PSP) */ - header2_offset = table2_body + 0x10*(target_subsong-1); - header3_offset = table3_body + 0x08*(target_subsong-1); - - sample_rate = read_16bit(header2_offset + 0x02,streamFile); - layers = read_16bit(header2_offset + 0x04,streamFile); - start_offset = read_32bit(header3_offset + 0x00,streamFile); - stream_size = read_32bit(header3_offset + 0x04,streamFile); - name_offset = 0; - name_size = 0; - switch(sample_rate) { - case 0x0800: sample_rate = 22050; break; - case 0x0687: sample_rate = 18000; break; - case 0x05ce: sample_rate = 16000; break; - case 0x0400: sample_rate = 11025; break; - default: - VGM_LOG("ZSND: unknown sample_rate %x at %x\n", sample_rate, (uint32_t)header2_offset); - goto fail; - } - break; - - case 0x47435542: /* "GCUB" (also for Wii) */ - header2_offset = table2_body + 0x18*(target_subsong-1); - header3_offset = table3_body + 0x0c*(target_subsong-1); - - layers = read_16bit(header2_offset + 0x02,streamFile); - sample_rate = read_32bit(header2_offset + 0x04,streamFile); - start_offset = read_32bit(header3_offset + 0x00,streamFile); - stream_size = read_32bit(header3_offset + 0x04,streamFile); - /* 0x08: "DSP " for some reason */ - name_offset = 0; - name_size = 0; - break; - - default: - goto fail; - } - - /* maybe flags? */ - switch (layers) { - case 0x00: channel_count = 1; break; - case 0x01: channel_count = 1; break; /* related to looping? */ - case 0x02: channel_count = 2; break; - case 0x22: channel_count = 4; break; - default: - VGM_LOG("ZSND: unknown layers\n"); - goto fail; - } - - loop_flag = 0; - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_ZSND; - vgmstream->sample_rate = sample_rate; - - switch (codec) { - case 0x50432020: /* "PC " */ - vgmstream->coding_type = coding_IMA; - vgmstream->layout_type = layout_none; - //todo interleaved stereo (needs to adapt decoder) - //vgmstream->layout_type = layout_interleave; /* interleaved stereo for >2ch*/ - //vgmstream->interleave_block_size = 0x2000 * 2 / channel_count; - - vgmstream->num_samples = ima_bytes_to_samples(stream_size, channel_count); - break; - - case 0x58424F58: /* "XBOX" */ - vgmstream->coding_type = coding_XBOX_IMA; - vgmstream->layout_type = layout_interleave; /* interleaved stereo for >2ch*/ - vgmstream->interleave_block_size = 0x9000 * 2 / channel_count; - - vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, channel_count); - break; - - case 0x50533220: /* "PS2 " (also for PSP) */ - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x800; - - vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count); - break; - - case 0x47435542: /* "GCUB" (also for Wii) */ - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x8000; - - /* has a full DSP header, but num_samples may vary slighly between channels, so calc manually */ - dsp_read_coefs_be(vgmstream, streamFile, start_offset+0x1c,0x60); - dsp_read_hist_be(vgmstream, streamFile, start_offset+0x40, 0x60); - start_offset += 0x60*channel_count; - stream_size -= 0x60*channel_count; - - vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channel_count); - break; - - default: - goto fail; - } - - vgmstream->num_streams = total_subsongs; - vgmstream->stream_size = stream_size; - - if (name_offset) { - read_string(vgmstream->stream_name,name_size, name_offset,streamFile); - } - - - temp_streamFile = setup_zsnd_streamfile(streamFile, start_offset, stream_size); /* fixes last interleave reads */ - if (!temp_streamFile) goto fail; - - if (!vgmstream_open_stream(vgmstream,temp_streamFile,start_offset)) - goto fail; - close_streamfile(temp_streamFile); - return vgmstream; - -fail: - close_streamfile(temp_streamFile); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" +#include "zsnd_streamfile.h" + + +/* ZSND - Z-Axis/Vicarious Visions games [X-Men Legends II (multi), Marvel Ultimate Alliance (multi)] */ +VGMSTREAM * init_vgmstream_zsnd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE *temp_streamFile = NULL; + off_t start_offset, name_offset; + size_t stream_size, name_size; + int loop_flag, channel_count, sample_rate, layers, layers2 = 0; + uint32_t codec; + int total_subsongs, target_subsong = streamFile->stream_index; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + + + /* checks */ + /* .zss/zsm: standard + * .ens/enm: same for PS2 + * .zsd: normal or compact [BMX XXX (Xbox), Aggresive Inline (Xbox)] */ + if (!check_extensions(streamFile, "zss,zsm,ens,enm,zsd")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x5A534E44) /* "ZSND" */ + goto fail; + /* probably zss=stream, zsm=memory; no diffs other than size */ + + codec = read_32bitBE(0x04,streamFile); + /* 0x08: file size, but slightly bigger (+0x01~04) in some platforms */ + /* 0x0c: header end/first stream start (unneeded as all offsets are absolute) */ + + if (codec == 0x47435542) { /* "GCUB" */ + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } + else { + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } + + + /* parse header tables */ + { + off_t header2_offset, header3_offset; + int table2_entries, table3_entries; + off_t table2_body, table3_body; + int is_v1, i; + + + /* multiple config tables: + * 0x00: entries + * 0x04: table head offset + * 0x08: table body offset + * + * table heads are 0x08 * entries: + * 0x00 = id? (crc-like, varies between tables but consistent between platforms) + * 0x04 = entry? (number, also in table2_body?) + * + * main tables: + * table1: stream cues? (entry=0x18) + * table2: stream heads (optional, rarely not all stream bodies may have heads) + * table3: stream body + * table4: unknown, very rare, some kind of seek table with numbers going up? (Aggresive Inline: speech01.zsd) + * table5: unknown, very rare, (X-Men Legends II: boss4_m.zsm) + * table6/7: not seen + * + * table1 may have more entries than table2/3, and sometimes isn't set + */ + + /* V1 has no table heads, rare [Aggresive Inline (Xbox)] + * no apparent flag but we can test if table heads offsets appear */ + is_v1 = read_32bit(0x14,streamFile) <= read_32bit(0x1c,streamFile) && + read_32bit(0x1c,streamFile) <= read_32bit(0x24,streamFile) && + read_32bit(0x24,streamFile) <= read_32bit(0x2c,streamFile) && + read_32bit(0x2c,streamFile) <= read_32bit(0x34,streamFile) && + read_32bit(0x34,streamFile) <= read_32bit(0x3c,streamFile) && + read_32bit(0x3c,streamFile) <= read_32bit(0x44,streamFile); + + if (!is_v1) { + table2_entries = read_32bit(0x1c,streamFile); + table2_body = read_32bit(0x24,streamFile); + + table3_entries = read_32bit(0x28,streamFile); + table3_body = read_32bit(0x30,streamFile); + } + else { + table2_entries = read_32bit(0x18,streamFile); + table2_body = read_32bit(0x1C,streamFile); + + table3_entries = read_32bit(0x20,streamFile); + table3_body = read_32bit(0x24,streamFile); + } + + total_subsongs = table3_entries; + + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + switch (codec) { + case 0x50432020: /* "PC " */ + if (table2_entries == 0) goto fail; + + header2_offset = table2_body + 0x18*(target_subsong-1); + layers = read_16bit(header2_offset + 0x02,streamFile); + sample_rate = read_32bit(header2_offset + 0x04,streamFile); + + header3_offset = table3_body + 0x4c*(target_subsong-1); + start_offset = read_32bit(header3_offset + 0x00,streamFile); + stream_size = read_32bit(header3_offset + 0x04,streamFile); + name_offset = header3_offset + 0x0c; + name_size = 0x40; + break; + + case 0x58424F58: { /* "XBOX" */ + size_t entry2_size = is_v1 || check_extensions(streamFile, "zsd") ? 0x14 : 0x1c; + + /* BMX has unordered stream headers, and not every stream has a header */ + header2_offset = 0; + for (i = 0; i < table2_entries; i++) { + int16_t id = read_16bit(table2_body + entry2_size*i + 0x00,streamFile); + + if (id >= 0 && id + 1 != target_subsong) /* can be -1 == deleted entry */ + continue; + header2_offset = table2_body + entry2_size*i; + break; + } + + if (header2_offset == 0) { + if (table2_entries > 0) { + /* seems usable for sfx, meh */ + header2_offset = table2_body + entry2_size*0; + layers = read_16bit(header2_offset + 0x02,streamFile); + sample_rate = read_32bit(header2_offset + 0x04,streamFile); + } + else { + layers = 0; + sample_rate = 0; + } + } + else { + layers = read_16bit(header2_offset + 0x02,streamFile); + sample_rate = read_32bit(header2_offset + 0x04,streamFile); + if (entry2_size > 0x18) { + layers2 = read_32bit(header2_offset + 0x18,streamFile); + } + } + + header3_offset = table3_body + 0x54*(target_subsong-1); + start_offset = read_32bit(header3_offset + 0x00,streamFile); + stream_size = read_32bit(header3_offset + 0x04,streamFile); + /* 0x08: flags? related to looping? (not channels) */ + //loop_end = read_32bit(header3_offset + 0x10,streamFile); + name_offset = header3_offset + 0x14; + name_size = 0x40; + + /* early games sometimes don't seem to have info or headers, not sure how to detect better + * ex. Aggresive Inline speech (1ch) vs music (2ch), or BMX cutscenes (2ch) */ + if (sample_rate == 0) { + int is_music = 0; + if (is_v1) { + char filename[PATH_LIMIT]; + + /* stream length isn't enough */ + get_streamfile_filename(streamFile, filename, sizeof(filename)); + is_music = strcmp(filename, "music.zsd") == 0; + } + else { + is_music = stream_size > 0x20000; + } + + if (is_music) { + layers = 0x02; + sample_rate = 44100; + } + else { + layers = 0x00; + sample_rate = is_v1 ? 16000 : 22050; /* some BMX need 16000 but can't detect? */ + } + } + + break; + } + + case 0x50533220: /* "PS2 " (also for PSP) */ + if (table2_entries == 0) goto fail; + + header2_offset = table2_body + 0x10*(target_subsong-1); + sample_rate = read_16bit(header2_offset + 0x02,streamFile); + layers = read_16bit(header2_offset + 0x04,streamFile); + + header3_offset = table3_body + 0x08*(target_subsong-1); + start_offset = read_32bit(header3_offset + 0x00,streamFile); + stream_size = read_32bit(header3_offset + 0x04,streamFile); + name_offset = 0; + name_size = 0; + + //TODO: possibly pitch: sample_rate = round10(pitch * 44100 / 4096); + switch(sample_rate) { + case 0x0800: sample_rate = 22050; break; + case 0x0687: sample_rate = 18000; break; + case 0x05ce: sample_rate = 16000; break; + case 0x0400: sample_rate = 11025; break; + default: + VGM_LOG("ZSND: unknown sample_rate %x at %x\n", sample_rate, (uint32_t)header2_offset); + goto fail; + } + break; + + case 0x47435542: /* "GCUB" (also for Wii) */ + header2_offset = table2_body + 0x18*(target_subsong-1); + layers = read_16bit(header2_offset + 0x02,streamFile); + sample_rate = read_32bit(header2_offset + 0x04,streamFile); + + header3_offset = table3_body + 0x0c*(target_subsong-1); + start_offset = read_32bit(header3_offset + 0x00,streamFile); + stream_size = read_32bit(header3_offset + 0x04,streamFile); + /* 0x08: "DSP " for some reason */ + name_offset = 0; + name_size = 0; + break; + + default: + goto fail; + } + + /* maybe flags? */ + switch (layers) { + case 0x00: channel_count = 1; break; + case 0x01: channel_count = 1; break; /* set when looping? */ + case 0x02: channel_count = 2; break; + case 0x22: channel_count = 4; break; + default: + VGM_LOG("ZSND: unknown layers\n"); + goto fail; + } + + if (layers2) { + channel_count = channel_count * layers2; + } + + loop_flag = 0; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_ZSND; + vgmstream->sample_rate = sample_rate; + + switch (codec) { + case 0x50432020: /* "PC " */ + vgmstream->coding_type = coding_IMA; + vgmstream->layout_type = layout_none; + //todo interleaved stereo (needs to adapt decoder) + //vgmstream->layout_type = layout_interleave; /* interleaved stereo for >2ch*/ + //vgmstream->interleave_block_size = 0x2000 * 2 / channel_count; + + vgmstream->num_samples = ima_bytes_to_samples(stream_size, channel_count); + break; + + case 0x58424F58: /* "XBOX" */ + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_interleave; /* interleaved stereo for >2ch*/ + vgmstream->interleave_block_size = 0x9000 * 2 / channel_count; + + vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, channel_count); + + /* very rarely entries refer to external .wma, but redoing the logic to handle only real + * streams handle is a pain, so signal this case with an empty file [Aggresive Inline (Xbox)] */ + if (vgmstream->num_samples == 0) { + vgmstream->num_samples = 48; + } + break; + + case 0x50533220: /* "PS2 " (also for PSP) */ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x800; + + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count); + break; + + case 0x47435542: /* "GCUB" (also for Wii) */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x8000; + + /* has a full DSP header, but num_samples may vary slighly between channels, so calc manually */ + dsp_read_coefs_be(vgmstream, streamFile, start_offset+0x1c,0x60); + dsp_read_hist_be(vgmstream, streamFile, start_offset+0x40, 0x60); + start_offset += 0x60*channel_count; + stream_size -= 0x60*channel_count; + + vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channel_count); + break; + + default: + goto fail; + } + + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + if (name_offset) { + read_string(vgmstream->stream_name,name_size, name_offset,streamFile); + } + + + temp_streamFile = setup_zsnd_streamfile(streamFile, start_offset, stream_size); /* fixes last interleave reads */ + if (!temp_streamFile) goto fail; + + if (!vgmstream_open_stream(vgmstream,temp_streamFile,start_offset)) + goto fail; + close_streamfile(temp_streamFile); + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 22be6fb56..9d54ec843 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -486,6 +486,11 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_xssb, init_vgmstream_xma_ue3, init_vgmstream_csb, + init_vgmstream_fwse, + init_vgmstream_fda, + init_vgmstream_tgc, + init_vgmstream_kwb, + init_vgmstream_lrmd, /* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */ init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */ @@ -656,6 +661,10 @@ void reset_vgmstream(VGMSTREAM * vgmstream) { } #endif + if (vgmstream->coding_type == coding_RELIC) { + reset_relic(vgmstream->codec_data); + } + if (vgmstream->coding_type == coding_CRI_HCA) { reset_hca(vgmstream->codec_data); } @@ -686,7 +695,7 @@ void reset_vgmstream(VGMSTREAM * vgmstream) { #ifdef VGM_USE_G7221 if (vgmstream->coding_type == coding_G7221C) { - reset_g7221(vgmstream); + reset_g7221(vgmstream->codec_data); } #endif @@ -823,6 +832,11 @@ void close_vgmstream(VGMSTREAM * vgmstream) { } #endif + if (vgmstream->coding_type == coding_RELIC) { + free_relic(vgmstream->codec_data); + vgmstream->codec_data = NULL; + } + if (vgmstream->coding_type == coding_CRI_HCA) { free_hca(vgmstream->codec_data); vgmstream->codec_data = NULL; @@ -865,7 +879,7 @@ void close_vgmstream(VGMSTREAM * vgmstream) { #ifdef VGM_USE_G7221 if (vgmstream->coding_type == coding_G7221C) { - free_g7221(vgmstream); + free_g7221(vgmstream->codec_data); vgmstream->codec_data = NULL; } #endif @@ -1164,6 +1178,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_UBI_IMA: case coding_OKI16: case coding_OKI4S: + case coding_MTF_IMA: return 1; case coding_PCM4: case coding_PCM4_U: @@ -1273,6 +1288,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { return 0; /* varies per mode */ case coding_EA_MT: return 0; /* 432, but variable in looped files */ + case coding_RELIC: + return 0; /* 512 */ case coding_CRI_HCA: return 0; /* 1024 - delay/padding (which can be bigger than 1024) */ #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) @@ -1356,6 +1373,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_PCFX: case coding_OKI16: case coding_OKI4S: + case coding_MTF_IMA: return 0x01; case coding_MS_IMA: case coding_RAD_IMA: @@ -1757,6 +1775,10 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do,vgmstream->channels); break; #endif + case coding_RELIC: + decode_relic(&vgmstream->ch[0], vgmstream->codec_data, buffer+samples_written*vgmstream->channels, + samples_to_do); + break; case coding_CRI_HCA: decode_hca(vgmstream->codec_data, buffer+samples_written*vgmstream->channels, samples_to_do); @@ -1824,6 +1846,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to is_stereo, is_high_first); } break; + case coding_MTF_IMA: + for (ch = 0; ch < vgmstream->channels; ch++) { + int is_stereo = (vgmstream->channels > 1); + decode_mtf_ima(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch, + vgmstream->channels,vgmstream->samples_into_block,samples_to_do, ch, + is_stereo); + } + break; case coding_3DS_IMA: for (ch = 0; ch < vgmstream->channels; ch++) { decode_3ds_ima(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch, @@ -2015,6 +2045,12 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to vgmstream->channels,vgmstream->samples_into_block,samples_to_do); } break; + case coding_TGC: + for (ch = 0; ch < vgmstream->channels; ch++) { + decode_tgc(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch, + vgmstream->samples_into_block,samples_to_do); + } + break; case coding_NDS_PROCYON: for (ch = 0; ch < vgmstream->channels; ch++) { decode_nds_procyon(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch, @@ -2191,6 +2227,10 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { /* prepare certain codecs' internal state for looping */ + if (vgmstream->coding_type == coding_RELIC) { + seek_relic(vgmstream->codec_data, vgmstream->loop_sample); + } + if (vgmstream->coding_type == coding_CRI_HCA) { loop_hca(vgmstream->codec_data, vgmstream->loop_sample); } diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 4f5ac7ba6..36ed47d03 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -42,14 +42,6 @@ enum { VGMSTREAM_MAX_NUM_SAMPLES = 1000000000 }; /* no ~5h vgm hopefully */ #endif #endif -#ifdef VGM_USE_G7221 -#ifdef __MACOSX__ -#include -#else -#include -#endif -#endif - #ifdef VGM_USE_MP4V2 #define MP4V2_NO_STDINT_DEFS #include @@ -79,6 +71,7 @@ enum { VGMSTREAM_MAX_NUM_SAMPLES = 1000000000 }; /* no ~5h vgm hopefully */ #include "nwa_decoder.h" #endif + /* The encoding type specifies the format the sound data itself takes */ typedef enum { /* PCM */ @@ -155,6 +148,7 @@ typedef enum { coding_AWC_IMA, /* Rockstar AWC IMA ADPCM */ coding_UBI_IMA, /* Ubisoft IMA ADPCM */ coding_H4M_IMA, /* H4M IMA ADPCM (stereo or mono, high nibble first) */ + coding_MTF_IMA, /* Capcom MT Framework IMA ADPCM */ coding_MSADPCM, /* Microsoft ADPCM (stereo/mono) */ coding_MSADPCM_int, /* Microsoft ADPCM (mono) */ @@ -166,6 +160,8 @@ typedef enum { coding_ASKA, /* Aska ADPCM */ coding_NXAP, /* NXAP ADPCM */ + coding_TGC, /* Tiger Game.com 4-bit ADPCM */ + coding_NDS_PROCYON, /* Procyon Studio ADPCM */ coding_L5_555, /* Level-5 0x555 ADPCM */ coding_LSF, /* lsf ADPCM (Fastlane Street Racing iPhone)*/ @@ -195,6 +191,7 @@ typedef enum { coding_EA_MT, /* Electronic Arts MicroTalk (linear-predictive speech codec) */ + coding_RELIC, /* Relic Codec (DCT-based) */ coding_CRI_HCA, /* CRI High Compression Audio (MDCT-based) */ #ifdef VGM_USE_VORBIS @@ -730,7 +727,11 @@ typedef enum { meta_ISB, meta_XSSB, meta_XMA_UE3, - + meta_FWSE, + meta_FDA, + meta_TGC, + meta_KWB, + meta_LRMD, } meta_t; /* standard WAVEFORMATEXTENSIBLE speaker positions */ @@ -1091,10 +1092,7 @@ typedef struct { #endif #ifdef VGM_USE_G7221 -typedef struct { - sample_t buffer[640]; - g7221_handle *handle; -} g7221_codec_data; +typedef struct g7221_codec_data g7221_codec_data; #endif #ifdef VGM_USE_G719 @@ -1159,6 +1157,7 @@ typedef struct { NWAData *nwa; } nwa_codec_data; +typedef struct relic_codec_data relic_codec_data; typedef struct { STREAMFILE *streamfile; diff --git a/Plugins/AdPlug/AdPlug.xcodeproj/project.pbxproj b/Plugins/AdPlug/AdPlug.xcodeproj/project.pbxproj index f8fbd95ac..777b055dd 100644 --- a/Plugins/AdPlug/AdPlug.xcodeproj/project.pbxproj +++ b/Plugins/AdPlug/AdPlug.xcodeproj/project.pbxproj @@ -168,7 +168,7 @@ TargetAttributes = { 83D3C5F2201C674D005564CB = { CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; + ProvisioningStyle = Manual; }; }; }; @@ -351,9 +351,9 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../../Frameworks/libbinio/libbinio/libbinio/src", "$(SRCROOT)/../../Frameworks/libbinio/libbinio", @@ -363,6 +363,7 @@ LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = net.kode54.AdPlug; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; WRAPPER_EXTENSION = bundle; }; @@ -372,9 +373,9 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../../Frameworks/libbinio/libbinio/libbinio/src", "$(SRCROOT)/../../Frameworks/libbinio/libbinio", @@ -384,6 +385,7 @@ LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = net.kode54.AdPlug; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; WRAPPER_EXTENSION = bundle; }; diff --git a/Plugins/OpenMPT/OpenMPT.xcodeproj/project.pbxproj b/Plugins/OpenMPT/OpenMPT.xcodeproj/project.pbxproj index c558c1228..d99025d4d 100644 --- a/Plugins/OpenMPT/OpenMPT.xcodeproj/project.pbxproj +++ b/Plugins/OpenMPT/OpenMPT.xcodeproj/project.pbxproj @@ -162,7 +162,7 @@ TargetAttributes = { 83E5EFA21FFEF78100659F0F = { CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; + ProvisioningStyle = Manual; }; }; }; @@ -343,13 +343,14 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = OpenMPT/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; PRODUCT_BUNDLE_IDENTIFIER = net.kode54.OpenMPT; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; WRAPPER_EXTENSION = bundle; }; @@ -359,13 +360,14 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = N6E749HJ2X; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = OpenMPT/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; PRODUCT_BUNDLE_IDENTIFIER = net.kode54.OpenMPT; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; WRAPPER_EXTENSION = bundle; }; diff --git a/Plugins/vgmstream/vgmstream.xcodeproj/project.pbxproj b/Plugins/vgmstream/vgmstream.xcodeproj/project.pbxproj index 86fd5d550..c78ea1a4d 100644 --- a/Plugins/vgmstream/vgmstream.xcodeproj/project.pbxproj +++ b/Plugins/vgmstream/vgmstream.xcodeproj/project.pbxproj @@ -409,7 +409,10 @@ 836F6B2318BDB80D0095E648 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "vgmstream/vgmstream-Prefix.pch"; HEADER_SEARCH_PATHS = ( @@ -423,6 +426,7 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; PRODUCT_BUNDLE_IDENTIFIER = "NoWork-Inc.vgmstream"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = macosx; SKIP_INSTALL = YES; WRAPPER_EXTENSION = bundle; @@ -432,7 +436,10 @@ 836F6B2418BDB80D0095E648 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "vgmstream/vgmstream-Prefix.pch"; HEADER_SEARCH_PATHS = ( @@ -446,6 +453,7 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; PRODUCT_BUNDLE_IDENTIFIER = "NoWork-Inc.vgmstream"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = macosx; SKIP_INSTALL = YES; WRAPPER_EXTENSION = bundle;