diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index ff30b8d30..a72e6dd70 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -141,6 +141,7 @@ 8359009D17FF06570060F3ED /* ArchiveSource.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8359FF3117FEF35D0060F3ED /* ArchiveSource.bundle */; }; 8360EF6D17F92E56005208A4 /* HighlyComplete.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8360EF0517F92B24005208A4 /* HighlyComplete.bundle */; }; 836D28A818086386005B7299 /* MiniModeMenuTitleTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */; }; + 836FB5A718206F2500B3AD2D /* Hively.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836FB5471820538800B3AD2D /* Hively.bundle */; }; 8375B36517FFEF130092A79F /* Opus.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8375B05717FFEA410092A79F /* Opus.bundle */; }; 83790D501809F4980073CF51 /* NSObject+SPInvocationGrabbing.m in Sources */ = {isa = PBXBuildFile; fileRef = 83790D4D1809F4980073CF51 /* NSObject+SPInvocationGrabbing.m */; }; 83790D511809F4980073CF51 /* SPMediaKeyTap.m in Sources */ = {isa = PBXBuildFile; fileRef = 83790D4F1809F4980073CF51 /* SPMediaKeyTap.m */; }; @@ -433,6 +434,20 @@ remoteGlobalIDString = 8360EEE417F92AC8005208A4; remoteInfo = HighlyComplete; }; + 836FB5461820538800B3AD2D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 836FB5421820538700B3AD2D /* Hively.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 836FB52D1820538700B3AD2D; + remoteInfo = Hively; + }; + 836FB5A518206F1500B3AD2D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 836FB5421820538700B3AD2D /* Hively.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 836FB52C1820538700B3AD2D; + remoteInfo = Hively; + }; 8375B05617FFEA410092A79F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 8375B05117FFEA400092A79F /* Opus.xcodeproj */; @@ -605,6 +620,7 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( + 836FB5A718206F2500B3AD2D /* Hively.bundle in CopyFiles */, 83A0F4E31816DBF900119DB4 /* playptmod.bundle in CopyFiles */, 83B06704180D579E008E3612 /* MIDI.bundle in CopyFiles */, 8375B36517FFEF130092A79F /* Opus.bundle in CopyFiles */, @@ -850,6 +866,7 @@ 8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyComplete.xcodeproj; path = Plugins/HighlyComplete/HighlyComplete.xcodeproj; sourceTree = ""; }; 836D28A618086386005B7299 /* MiniModeMenuTitleTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MiniModeMenuTitleTransformer.h; path = Window/MiniModeMenuTitleTransformer.h; sourceTree = ""; }; 836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MiniModeMenuTitleTransformer.m; path = Window/MiniModeMenuTitleTransformer.m; sourceTree = ""; }; + 836FB5421820538700B3AD2D /* Hively.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Hively.xcodeproj; path = Plugins/Hively/Hively.xcodeproj; sourceTree = ""; }; 8375B05117FFEA400092A79F /* Opus.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Opus.xcodeproj; path = Plugins/Opus/Opus.xcodeproj; sourceTree = ""; }; 83790D4C1809F4980073CF51 /* NSObject+SPInvocationGrabbing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+SPInvocationGrabbing.h"; sourceTree = ""; }; 83790D4D1809F4980073CF51 /* NSObject+SPInvocationGrabbing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+SPInvocationGrabbing.m"; sourceTree = ""; }; @@ -1203,6 +1220,7 @@ 8375B05117FFEA400092A79F /* Opus.xcodeproj */, 83B0669C180D5668008E3612 /* MIDI.xcodeproj */, 83A0F4841816CE5E00119DB4 /* playptmod.xcodeproj */, + 836FB5421820538700B3AD2D /* Hively.xcodeproj */, ); name = PlugIns; sourceTree = ""; @@ -1533,6 +1551,14 @@ name = Products; sourceTree = ""; }; + 836FB5431820538700B3AD2D /* Products */ = { + isa = PBXGroup; + children = ( + 836FB5471820538800B3AD2D /* Hively.bundle */, + ); + name = Products; + sourceTree = ""; + }; 8375B05217FFEA400092A79F /* Products */ = { isa = PBXGroup; children = ( @@ -1728,6 +1754,7 @@ buildRules = ( ); dependencies = ( + 836FB5A618206F1500B3AD2D /* PBXTargetDependency */, 83A0F4E21816DBE800119DB4 /* PBXTargetDependency */, 83E6B7641816138800D4576D /* PBXTargetDependency */, 83B06703180D5776008E3612 /* PBXTargetDependency */, @@ -1833,6 +1860,10 @@ ProductGroup = 8360EF0117F92B23005208A4 /* Products */; ProjectRef = 8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */; }, + { + ProductGroup = 836FB5431820538700B3AD2D /* Products */; + ProjectRef = 836FB5421820538700B3AD2D /* Hively.xcodeproj */; + }, { ProductGroup = 17C808840C3BD181005707C4 /* Products */; ProjectRef = 17C808830C3BD181005707C4 /* HTTPSource.xcodeproj */; @@ -2013,6 +2044,13 @@ remoteRef = 8360EF0417F92B24005208A4 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 836FB5471820538800B3AD2D /* Hively.bundle */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = Hively.bundle; + remoteRef = 836FB5461820538800B3AD2D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 8375B05717FFEA410092A79F /* Opus.bundle */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; @@ -2374,6 +2412,11 @@ name = General; targetProxy = 17F5623A0C3BD9280019975C /* PBXContainerItemProxy */; }; + 836FB5A618206F1500B3AD2D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Hively; + targetProxy = 836FB5A518206F1500B3AD2D /* PBXContainerItemProxy */; + }; 8375B36217FFEF010092A79F /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = ArchiveSource; diff --git a/Frameworks/HivelyPlayer/HivelyPlayer.xcodeproj/project.pbxproj b/Frameworks/HivelyPlayer/HivelyPlayer.xcodeproj/project.pbxproj new file mode 100644 index 000000000..c0cb8633d --- /dev/null +++ b/Frameworks/HivelyPlayer/HivelyPlayer.xcodeproj/project.pbxproj @@ -0,0 +1,306 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 836FB564182053D700B3AD2D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 836FB562182053D700B3AD2D /* InfoPlist.strings */; }; + 836FB591182054B700B3AD2D /* hvl_replay.c in Sources */ = {isa = PBXBuildFile; fileRef = 836FB58D182054B700B3AD2D /* hvl_replay.c */; }; + 836FB592182054B700B3AD2D /* hvl_replay.h in Headers */ = {isa = PBXBuildFile; fileRef = 836FB58E182054B700B3AD2D /* hvl_replay.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 836FB593182054B700B3AD2D /* blip_buf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836FB58F182054B700B3AD2D /* blip_buf.c */; }; + 836FB594182054B700B3AD2D /* blip_buf.h in Headers */ = {isa = PBXBuildFile; fileRef = 836FB590182054B700B3AD2D /* blip_buf.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 836FB556182053D700B3AD2D /* HivelyPlayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HivelyPlayer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 836FB561182053D700B3AD2D /* HivelyPlayer-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HivelyPlayer-Info.plist"; sourceTree = ""; }; + 836FB563182053D700B3AD2D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 836FB58D182054B700B3AD2D /* hvl_replay.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hvl_replay.c; sourceTree = ""; }; + 836FB58E182054B700B3AD2D /* hvl_replay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hvl_replay.h; sourceTree = ""; }; + 836FB58F182054B700B3AD2D /* blip_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blip_buf.c; sourceTree = ""; }; + 836FB590182054B700B3AD2D /* blip_buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blip_buf.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 836FB552182053D700B3AD2D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 836FB54C182053D700B3AD2D = { + isa = PBXGroup; + children = ( + 836FB55F182053D700B3AD2D /* HivelyPlayer */, + 836FB558182053D700B3AD2D /* Frameworks */, + 836FB557182053D700B3AD2D /* Products */, + ); + sourceTree = ""; + }; + 836FB557182053D700B3AD2D /* Products */ = { + isa = PBXGroup; + children = ( + 836FB556182053D700B3AD2D /* HivelyPlayer.framework */, + ); + name = Products; + sourceTree = ""; + }; + 836FB558182053D700B3AD2D /* Frameworks */ = { + isa = PBXGroup; + children = ( + 836FB55B182053D700B3AD2D /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 836FB55B182053D700B3AD2D /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 836FB55F182053D700B3AD2D /* HivelyPlayer */ = { + isa = PBXGroup; + children = ( + 836FB58D182054B700B3AD2D /* hvl_replay.c */, + 836FB58E182054B700B3AD2D /* hvl_replay.h */, + 836FB58F182054B700B3AD2D /* blip_buf.c */, + 836FB590182054B700B3AD2D /* blip_buf.h */, + 836FB560182053D700B3AD2D /* Supporting Files */, + ); + path = HivelyPlayer; + sourceTree = ""; + }; + 836FB560182053D700B3AD2D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 836FB561182053D700B3AD2D /* HivelyPlayer-Info.plist */, + 836FB562182053D700B3AD2D /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 836FB553182053D700B3AD2D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 836FB592182054B700B3AD2D /* hvl_replay.h in Headers */, + 836FB594182054B700B3AD2D /* blip_buf.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 836FB555182053D700B3AD2D /* HivelyPlayer */ = { + isa = PBXNativeTarget; + buildConfigurationList = 836FB57E182053D700B3AD2D /* Build configuration list for PBXNativeTarget "HivelyPlayer" */; + buildPhases = ( + 836FB551182053D700B3AD2D /* Sources */, + 836FB552182053D700B3AD2D /* Frameworks */, + 836FB553182053D700B3AD2D /* Headers */, + 836FB554182053D700B3AD2D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = HivelyPlayer; + productName = HivelyPlayer; + productReference = 836FB556182053D700B3AD2D /* HivelyPlayer.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 836FB54D182053D700B3AD2D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Christopher Snowhill"; + }; + buildConfigurationList = 836FB550182053D700B3AD2D /* Build configuration list for PBXProject "HivelyPlayer" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 836FB54C182053D700B3AD2D; + productRefGroup = 836FB557182053D700B3AD2D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 836FB555182053D700B3AD2D /* HivelyPlayer */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 836FB554182053D700B3AD2D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 836FB564182053D700B3AD2D /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 836FB551182053D700B3AD2D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 836FB593182054B700B3AD2D /* blip_buf.c in Sources */, + 836FB591182054B700B3AD2D /* hvl_replay.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 836FB562182053D700B3AD2D /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 836FB563182053D700B3AD2D /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 836FB57C182053D700B3AD2D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = 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; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 836FB57D182053D700B3AD2D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = 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; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 836FB57F182053D700B3AD2D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "HivelyPlayer/HivelyPlayer-Info.plist"; + INSTALL_PATH = "@loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = framework; + }; + name = Debug; + }; + 836FB580182053D700B3AD2D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "HivelyPlayer/HivelyPlayer-Info.plist"; + INSTALL_PATH = "@loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 836FB550182053D700B3AD2D /* Build configuration list for PBXProject "HivelyPlayer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 836FB57C182053D700B3AD2D /* Debug */, + 836FB57D182053D700B3AD2D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 836FB57E182053D700B3AD2D /* Build configuration list for PBXNativeTarget "HivelyPlayer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 836FB57F182053D700B3AD2D /* Debug */, + 836FB580182053D700B3AD2D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 836FB54D182053D700B3AD2D /* Project object */; +} diff --git a/Frameworks/HivelyPlayer/HivelyPlayer/HivelyPlayer-Info.plist b/Frameworks/HivelyPlayer/HivelyPlayer/HivelyPlayer-Info.plist new file mode 100644 index 000000000..02410e2cd --- /dev/null +++ b/Frameworks/HivelyPlayer/HivelyPlayer/HivelyPlayer-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + net.kode54.hivelyplayer + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2013 Christopher Snowhill. All rights reserved. + NSPrincipalClass + + + diff --git a/Frameworks/HivelyPlayer/HivelyPlayer/blip_buf.c b/Frameworks/HivelyPlayer/HivelyPlayer/blip_buf.c new file mode 100644 index 000000000..70f1afb0a --- /dev/null +++ b/Frameworks/HivelyPlayer/HivelyPlayer/blip_buf.c @@ -0,0 +1,334 @@ +/* blip_buf 1.1.0. http://www.slack.net/~ant/ */ + +#include "blip_buf.h" + +#include +#include +#include +#include + +/* Library Copyright (C) 2003-2009 Shay Green. This library is free software; +you can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +library is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#if defined (BLARGG_TEST) && BLARGG_TEST + #include "blargg_test.h" +#endif + +/* Equivalent to ULONG_MAX >= 0xFFFFFFFF00000000. +Avoids constants that don't fit in 32 bits. */ +#if ULONG_MAX/0xFFFFFFFF > 0xFFFFFFFF + typedef unsigned long fixed_t; + enum { pre_shift = 32 }; + +#elif defined(ULLONG_MAX) + typedef unsigned long long fixed_t; + enum { pre_shift = 32 }; + +#else + typedef unsigned fixed_t; + enum { pre_shift = 0 }; + +#endif + +enum { time_bits = pre_shift + 20 }; + +static fixed_t const time_unit = (fixed_t) 1 << time_bits; + +enum { bass_shift = 9 }; /* affects high-pass filter breakpoint frequency */ +enum { end_frame_extra = 2 }; /* allows deltas slightly after frame length */ + +enum { half_width = 8 }; +enum { buf_extra = half_width*2 + end_frame_extra }; +enum { phase_bits = 5 }; +enum { phase_count = 1 << phase_bits }; +enum { delta_bits = 15 }; +enum { delta_unit = 1 << delta_bits }; +enum { frac_bits = time_bits - pre_shift }; + +/* We could eliminate avail and encode whole samples in offset, but that would +limit the total buffered samples to blip_max_frame. That could only be +increased by decreasing time_bits, which would reduce resample ratio accuracy. +*/ + +/** Sample buffer that resamples to output rate and accumulates samples +until they're read out */ +struct hvl_blip_t +{ + fixed_t factor; + fixed_t offset; + int avail; + int size; + fixed_t integrator; +}; + +typedef int buf_t; + +/* probably not totally portable */ +#define SAMPLES( buf ) ((buf_t*) ((buf) + 1)) + +/* Arithmetic (sign-preserving) right shift */ +#define ARITH_SHIFT( n, shift ) \ + ((n) >> (shift)) + +enum { max_sample = +32767 }; +enum { min_sample = -32768 }; + +#define CLAMP( n ) \ + {\ + if ( (short) n != n )\ + n = ARITH_SHIFT( n, 16 ) ^ max_sample;\ + } + +static void check_assumptions( void ) +{ + int n; + + #if INT_MAX < 0x7FFFFFFF || UINT_MAX < 0xFFFFFFFF + #error "int must be at least 32 bits" + #endif + + assert( (-3 >> 1) == -2 ); /* right shift must preserve sign */ + + n = max_sample * 2; + CLAMP( n ); + assert( n == max_sample ); + + n = min_sample * 2; + CLAMP( n ); + assert( n == min_sample ); + + assert( hvl_blip_max_ratio <= time_unit ); + assert( hvl_blip_max_frame <= (fixed_t) -1 >> time_bits ); +} + +size_t hvl_blip_size( int size ) +{ + assert( size >= 0 ); + return sizeof (hvl_blip_t) + (size + buf_extra) * sizeof (buf_t); +} + +void hvl_blip_new_inplace( hvl_blip_t* m, int size ) +{ + assert( size >= 0 ); + + if ( m ) + { + m->factor = time_unit / hvl_blip_max_ratio; + m->size = size; + hvl_blip_clear( m ); + check_assumptions(); + } +} + +void hvl_blip_set_rates( hvl_blip_t* m, double clock_rate, double sample_rate ) +{ + double factor = time_unit * sample_rate / clock_rate; + m->factor = (fixed_t) factor; + + /* Fails if clock_rate exceeds maximum, relative to sample_rate */ + assert( 0 <= factor - m->factor && factor - m->factor < 1 ); + + /* Avoid requiring math.h. Equivalent to + m->factor = (int) ceil( factor ) */ + if ( m->factor < factor ) + m->factor++; + + /* At this point, factor is most likely rounded up, but could still + have been rounded down in the floating-point calculation. */ +} + +void hvl_blip_clear( hvl_blip_t* m ) +{ + /* We could set offset to 0, factor/2, or factor-1. 0 is suitable if + factor is rounded up. factor-1 is suitable if factor is rounded down. + Since we don't know rounding direction, factor/2 accommodates either, + with the slight loss of showing an error in half the time. Since for + a 64-bit factor this is years, the halving isn't a problem. */ + + m->offset = m->factor / 2; + m->avail = 0; + m->integrator = 0; + memset( SAMPLES( m ), 0, (m->size + buf_extra) * sizeof (buf_t) ); +} + +int hvl_blip_clocks_needed( const hvl_blip_t* m, int samples ) +{ + fixed_t needed; + + /* Fails if buffer can't hold that many more samples */ + assert( samples >= 0 && m->avail + samples <= m->size ); + + needed = (fixed_t) samples * time_unit; + if ( needed < m->offset ) + return 0; + + return (needed - m->offset + m->factor - 1) / m->factor; +} + +void hvl_blip_end_frame( hvl_blip_t* m, unsigned t ) +{ + fixed_t off = t * m->factor + m->offset; + m->avail += off >> time_bits; + m->offset = off & (time_unit - 1); + + /* Fails if buffer size was exceeded */ + assert( m->avail <= m->size ); +} + +int hvl_blip_samples_avail( const hvl_blip_t* m ) +{ + return m->avail; +} + +static void remove_samples( hvl_blip_t* m, int count ) +{ + buf_t* buf = SAMPLES( m ); + int remain = m->avail + buf_extra - count; + m->avail -= count; + + memmove( &buf [0], &buf [count], remain * sizeof buf [0] ); + memset( &buf [remain], 0, count * sizeof buf [0] ); +} + +int hvl_blip_read_samples( hvl_blip_t* m, int out [], int count, int gain ) +{ + assert( count >= 0 ); + + if ( count > m->avail ) + count = m->avail; + + if ( count ) + { + buf_t const* in = SAMPLES( m ); + buf_t const* end = in + count; + fixed_t sum = m->integrator; + do + { + /* Eliminate fraction */ + int s = ARITH_SHIFT( sum, delta_bits ); + + sum += *in++; + + *out = s * gain; + out += 2; + + /* High-pass filter */ + sum -= s << (delta_bits - bass_shift); + } + while ( in != end ); + m->integrator = sum; + + remove_samples( m, count ); + } + + return count; +} + +/* Things that didn't help performance on x86: + __attribute__((aligned(128))) + #define short int + restrict +*/ + +/* Sinc_Generator( 0.9, 0.55, 4.5 ) */ +static short const bl_step [phase_count + 1] [half_width] = +{ +{ 43, -115, 350, -488, 1136, -914, 5861,21022}, +{ 44, -118, 348, -473, 1076, -799, 5274,21001}, +{ 45, -121, 344, -454, 1011, -677, 4706,20936}, +{ 46, -122, 336, -431, 942, -549, 4156,20829}, +{ 47, -123, 327, -404, 868, -418, 3629,20679}, +{ 47, -122, 316, -375, 792, -285, 3124,20488}, +{ 47, -120, 303, -344, 714, -151, 2644,20256}, +{ 46, -117, 289, -310, 634, -17, 2188,19985}, +{ 46, -114, 273, -275, 553, 117, 1758,19675}, +{ 44, -108, 255, -237, 471, 247, 1356,19327}, +{ 43, -103, 237, -199, 390, 373, 981,18944}, +{ 42, -98, 218, -160, 310, 495, 633,18527}, +{ 40, -91, 198, -121, 231, 611, 314,18078}, +{ 38, -84, 178, -81, 153, 722, 22,17599}, +{ 36, -76, 157, -43, 80, 824, -241,17092}, +{ 34, -68, 135, -3, 8, 919, -476,16558}, +{ 32, -61, 115, 34, -60, 1006, -683,16001}, +{ 29, -52, 94, 70, -123, 1083, -862,15422}, +{ 27, -44, 73, 106, -184, 1152,-1015,14824}, +{ 25, -36, 53, 139, -239, 1211,-1142,14210}, +{ 22, -27, 34, 170, -290, 1261,-1244,13582}, +{ 20, -20, 16, 199, -335, 1301,-1322,12942}, +{ 18, -12, -3, 226, -375, 1331,-1376,12293}, +{ 15, -4, -19, 250, -410, 1351,-1408,11638}, +{ 13, 3, -35, 272, -439, 1361,-1419,10979}, +{ 11, 9, -49, 292, -464, 1362,-1410,10319}, +{ 9, 16, -63, 309, -483, 1354,-1383, 9660}, +{ 7, 22, -75, 322, -496, 1337,-1339, 9005}, +{ 6, 26, -85, 333, -504, 1312,-1280, 8355}, +{ 4, 31, -94, 341, -507, 1278,-1205, 7713}, +{ 3, 35, -102, 347, -506, 1238,-1119, 7082}, +{ 1, 40, -110, 350, -499, 1190,-1021, 6464}, +{ 0, 43, -115, 350, -488, 1136, -914, 5861} +}; + +/* Shifting by pre_shift allows calculation using unsigned int rather than +possibly-wider fixed_t. On 32-bit platforms, this is likely more efficient. +And by having pre_shift 32, a 32-bit platform can easily do the shift by +simply ignoring the low half. */ + +void hvl_blip_add_delta( hvl_blip_t* m, unsigned time, int delta ) +{ + unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift); + buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits); + + int const phase_shift = frac_bits - phase_bits; + int phase = fixed >> phase_shift & (phase_count - 1); + short const* in = bl_step [phase]; + short const* rev = bl_step [phase_count - phase]; + + int interp = fixed >> (phase_shift - delta_bits) & (delta_unit - 1); + int delta2 = (delta * interp) >> delta_bits; + delta -= delta2; + + /* Fails if buffer size was exceeded */ + assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] ); + + out [0] += in[0]*delta + in[half_width+0]*delta2; + out [1] += in[1]*delta + in[half_width+1]*delta2; + out [2] += in[2]*delta + in[half_width+2]*delta2; + out [3] += in[3]*delta + in[half_width+3]*delta2; + out [4] += in[4]*delta + in[half_width+4]*delta2; + out [5] += in[5]*delta + in[half_width+5]*delta2; + out [6] += in[6]*delta + in[half_width+6]*delta2; + out [7] += in[7]*delta + in[half_width+7]*delta2; + + in = rev; + out [ 8] += in[7]*delta + in[7-half_width]*delta2; + out [ 9] += in[6]*delta + in[6-half_width]*delta2; + out [10] += in[5]*delta + in[5-half_width]*delta2; + out [11] += in[4]*delta + in[4-half_width]*delta2; + out [12] += in[3]*delta + in[3-half_width]*delta2; + out [13] += in[2]*delta + in[2-half_width]*delta2; + out [14] += in[1]*delta + in[1-half_width]*delta2; + out [15] += in[0]*delta + in[0-half_width]*delta2; +} + +void hvl_blip_add_delta_fast( hvl_blip_t* m, unsigned time, int delta ) +{ + unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift); + buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits); + + int interp = fixed >> (frac_bits - delta_bits) & (delta_unit - 1); + int delta2 = delta * interp; + + /* Fails if buffer size was exceeded */ + assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] ); + + out [7] += delta * delta_unit - delta2; + out [8] += delta2; +} diff --git a/Frameworks/HivelyPlayer/HivelyPlayer/blip_buf.h b/Frameworks/HivelyPlayer/HivelyPlayer/blip_buf.h new file mode 100644 index 000000000..37d1fda91 --- /dev/null +++ b/Frameworks/HivelyPlayer/HivelyPlayer/blip_buf.h @@ -0,0 +1,69 @@ +/** \file +Sample buffer that resamples from input clock rate to output sample rate */ + +#include + +/* blip_buf 1.1.0 */ +#ifndef HVL_BLIP_BUF_H +#define HVL_BLIP_BUF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** First parameter of most functions is blip_t*, or const blip_t* if nothing +is changed. */ +typedef struct hvl_blip_t hvl_blip_t; + +/** Returns the size of a blip_t object of the given sample count. */ +size_t hvl_blip_size( int sample_count ); + +/** Creates new buffer that can hold at most sample_count samples. Sets rates +so that there are blip_max_ratio clocks per sample. */ +void hvl_blip_new_inplace( hvl_blip_t*, int sample_count ); + +/** Sets approximate input clock rate and output sample rate. For every +clock_rate input clocks, approximately sample_rate samples are generated. */ +void hvl_blip_set_rates( hvl_blip_t*, double clock_rate, double sample_rate ); + +enum { /** Maximum clock_rate/sample_rate ratio. For a given sample_rate, +clock_rate must not be greater than sample_rate*blip_max_ratio. */ +hvl_blip_max_ratio = 1 << 20 }; + +/** Clears entire buffer. Afterwards, blip_samples_avail() == 0. */ +void hvl_blip_clear( hvl_blip_t* ); + +/** Adds positive/negative delta into buffer at specified clock time. */ +void hvl_blip_add_delta( hvl_blip_t*, unsigned int clock_time, int delta ); + +/** Same as blip_add_delta(), but uses faster, lower-quality synthesis. */ +void hvl_blip_add_delta_fast( hvl_blip_t*, unsigned int clock_time, int delta ); + +/** Length of time frame, in clocks, needed to make sample_count additional +samples available. */ +int hvl_blip_clocks_needed( const hvl_blip_t*, int sample_count ); + +enum { /** Maximum number of samples that can be generated from one time frame. */ +hvl_blip_max_frame = 4000 }; + +/** Makes input clocks before clock_duration available for reading as output +samples. Also begins new time frame at clock_duration, so that clock time 0 in +the new time frame specifies the same clock as clock_duration in the old time +frame specified. Deltas can have been added slightly past clock_duration (up to +however many clocks there are in two output samples). */ +void hvl_blip_end_frame( hvl_blip_t*, unsigned int clock_duration ); + +/** Number of buffered samples available for reading. */ +int hvl_blip_samples_avail( const hvl_blip_t* ); + +/** Reads and removes at most 'count' samples and writes them to 'out'. If +'stereo' is true, writes output to every other element of 'out', allowing easy +interleaving of two buffers into a stereo sample stream. Outputs 16-bit signed +samples. Returns number of samples actually read. */ +int hvl_blip_read_samples( hvl_blip_t*, int out [], int count, int gain ); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/Frameworks/HivelyPlayer/HivelyPlayer/en.lproj/InfoPlist.strings b/Frameworks/HivelyPlayer/HivelyPlayer/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..477b28ff8 --- /dev/null +++ b/Frameworks/HivelyPlayer/HivelyPlayer/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Frameworks/HivelyPlayer/HivelyPlayer/hvl_replay.c b/Frameworks/HivelyPlayer/HivelyPlayer/hvl_replay.c new file mode 100644 index 000000000..7a2978e04 --- /dev/null +++ b/Frameworks/HivelyPlayer/HivelyPlayer/hvl_replay.c @@ -0,0 +1,2079 @@ +/* +** Changes for the 1.4 release are commented. You can do +** a search for "1.4" and merge them into your own replay +** code. +** +** Changes for 1.5 are marked also. +** +** ... as are those for 1.6 +** +** ... and for 1.8 +*/ + + +#include +#include +#include +#include + +#include "hvl_replay.h" + +#undef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +const int32 stereopan_left[] = { 128, 96, 64, 32, 0 }; +const int32 stereopan_right[] = { 128, 160, 193, 225, 255 }; + +/* +** Waves +*/ +#define WHITENOISELEN (0x280*3) + +#define WO_LOWPASSES 0 +#define WO_TRIANGLE_04 (WO_LOWPASSES+((0xfc+0xfc+0x80*0x1f+0x80+3*0x280)*31)) +#define WO_TRIANGLE_08 (WO_TRIANGLE_04+0x04) +#define WO_TRIANGLE_10 (WO_TRIANGLE_08+0x08) +#define WO_TRIANGLE_20 (WO_TRIANGLE_10+0x10) +#define WO_TRIANGLE_40 (WO_TRIANGLE_20+0x20) +#define WO_TRIANGLE_80 (WO_TRIANGLE_40+0x40) +#define WO_SAWTOOTH_04 (WO_TRIANGLE_80+0x80) +#define WO_SAWTOOTH_08 (WO_SAWTOOTH_04+0x04) +#define WO_SAWTOOTH_10 (WO_SAWTOOTH_08+0x08) +#define WO_SAWTOOTH_20 (WO_SAWTOOTH_10+0x10) +#define WO_SAWTOOTH_40 (WO_SAWTOOTH_20+0x20) +#define WO_SAWTOOTH_80 (WO_SAWTOOTH_40+0x40) +#define WO_SQUARES (WO_SAWTOOTH_80+0x80) +#define WO_WHITENOISE (WO_SQUARES+(0x80*0x20)) +#define WO_HIGHPASSES (WO_WHITENOISE+WHITENOISELEN) +#define WAVES_SIZE (WO_HIGHPASSES+((0xfc+0xfc+0x80*0x1f+0x80+3*0x280)*31)) + +int8 waves[WAVES_SIZE]; +int16 waves2[WAVES_SIZE]; + +const int16 vib_tab[] = +{ + 0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255, + 253,250,244,235,224,212,197,180,161,141,120,97,74,49,24, + 0,-24,-49,-74,-97,-120,-141,-161,-180,-197,-212,-224,-235,-244,-250,-253,-255, + -253,-250,-244,-235,-224,-212,-197,-180,-161,-141,-120,-97,-74,-49,-24 +}; + +const uint16 period_tab[] = +{ + 0x0000, 0x0D60, 0x0CA0, 0x0BE8, 0x0B40, 0x0A98, 0x0A00, 0x0970, + 0x08E8, 0x0868, 0x07F0, 0x0780, 0x0714, 0x06B0, 0x0650, 0x05F4, + 0x05A0, 0x054C, 0x0500, 0x04B8, 0x0474, 0x0434, 0x03F8, 0x03C0, + 0x038A, 0x0358, 0x0328, 0x02FA, 0x02D0, 0x02A6, 0x0280, 0x025C, + 0x023A, 0x021A, 0x01FC, 0x01E0, 0x01C5, 0x01AC, 0x0194, 0x017D, + 0x0168, 0x0153, 0x0140, 0x012E, 0x011D, 0x010D, 0x00FE, 0x00F0, + 0x00E2, 0x00D6, 0x00CA, 0x00BE, 0x00B4, 0x00AA, 0x00A0, 0x0097, + 0x008F, 0x0087, 0x007F, 0x0078, 0x0071 +}; + +uint32 panning_left[256], panning_right[256]; + +void hvl_GenPanningTables( void ) +{ + uint32 i; + float64 aa, ab; + + // Sine based panning table + aa = (3.14159265f*2.0f)/4.0f; // Quarter of the way through the sinewave == top peak + ab = 0.0f; // Start of the climb from zero + + for( i=0; i<256; i++ ) + { + panning_left[i] = (uint32)(sin(aa)*255.0f); + panning_right[i] = (uint32)(sin(ab)*255.0f); + + aa += (3.14159265*2.0f/4.0f)/256.0f; + ab += (3.14159265*2.0f/4.0f)/256.0f; + } + panning_left[255] = 0; + panning_right[0] = 0; +} + +void hvl_GenSawtooth( int8 *buf, uint32 len ) +{ + uint32 i; + int32 val, add; + + add = 256 / (len-1); + val = -128; + + for( i=0; i> 2; + d1 = 128/d5; + d4 = -(d2 >> 1); + val = 0; + + for( i=0; i 127.f ) + x = 127.f; + else if( x < -128.f ) + x = -128.f; + return x; +} + +void hvl_GenFilterWaves( int8 *buf, int8 *lowbuf, int8 *highbuf ) +{ + static const uint16 lentab[45] = { 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, + 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, + 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, + (0x280*3)-1 }; + + float64 freq; + uint32 temp; + + for( temp=0, freq=8.3115f; temp<31; temp++, freq+=3.f ) + { + uint32 wv; + int8 *a0 = buf; + + for( wv=0; wv<6+6+0x20+1; wv++ ) + { + float64 fre, high, mid, low; + uint32 i; + + mid = 0.f; + low = 0.f; + fre = freq * 1.17250f / 100.0f; + + for( i=0; i<=lentab[wv]; i++ ) + { + high = a0[i] - mid - low; + high = clip( high ); + mid += high * fre; + mid = clip( mid ); + low += mid * fre; + low = clip( low ); + } + + for( i=0; i<=lentab[wv]; i++ ) + { + high = a0[i] - mid - low; + high = clip( high ); + mid += high * fre; + mid = clip( mid ); + low += mid * fre; + low = clip( low ); + *lowbuf++ = (int8)low; + *highbuf++ = (int8)high; + } + + a0 += lentab[wv]+1; + } + } +} + +void hvl_GenWhiteNoise( int8 *buf, uint32 len ) +{ + uint32 ays; + + ays = 0x41595321; + + do { + uint16 ax, bx; + int8 s; + + s = ays; + + if( ays & 0x100 ) + { + s = 0x7F; + + if( ays & 0x8000 ) + s = 0x80; + } + + *buf++ = s; + len--; + + ays = (ays >> 5) | (ays << 27); + ays = (ays & 0xffffff00) | ((ays & 0xff) ^ 0x9a); + bx = ays; + ays = (ays << 2) | (ays >> 30); + ax = ays; + bx += ax; + ax ^= bx; + ays = (ays & 0xffff0000) | ax; + ays = (ays >> 3) | (ays << 29); + } while( len ); +} + +void hvl_reset_some_stuff( struct hvl_tune *ht ) +{ + uint32 i; + + for( i=0; iht_Voices[i].vc_Delta=~0; + ht->ht_Voices[i].vc_OverrideTranspose=1000; // 1.5 + ht->ht_Voices[i].vc_SamplePos=ht->ht_Voices[i].vc_Track=ht->ht_Voices[i].vc_Transpose=ht->ht_Voices[i].vc_NextTrack = ht->ht_Voices[i].vc_NextTranspose = 0; + ht->ht_Voices[i].vc_ADSRVolume=ht->ht_Voices[i].vc_InstrPeriod=ht->ht_Voices[i].vc_TrackPeriod=ht->ht_Voices[i].vc_VibratoPeriod=ht->ht_Voices[i].vc_NoteMaxVolume=ht->ht_Voices[i].vc_PerfSubVolume=ht->ht_Voices[i].vc_TrackMasterVolume=0; + ht->ht_Voices[i].vc_NewWaveform=ht->ht_Voices[i].vc_Waveform=ht->ht_Voices[i].vc_PlantSquare=ht->ht_Voices[i].vc_PlantPeriod=ht->ht_Voices[i].vc_IgnoreSquare=0; + ht->ht_Voices[i].vc_TrackOn=ht->ht_Voices[i].vc_FixedNote=ht->ht_Voices[i].vc_VolumeSlideUp=ht->ht_Voices[i].vc_VolumeSlideDown=ht->ht_Voices[i].vc_HardCut=ht->ht_Voices[i].vc_HardCutRelease=ht->ht_Voices[i].vc_HardCutReleaseF=0; + ht->ht_Voices[i].vc_PeriodSlideSpeed=ht->ht_Voices[i].vc_PeriodSlidePeriod=ht->ht_Voices[i].vc_PeriodSlideLimit=ht->ht_Voices[i].vc_PeriodSlideOn=ht->ht_Voices[i].vc_PeriodSlideWithLimit=0; + ht->ht_Voices[i].vc_PeriodPerfSlideSpeed=ht->ht_Voices[i].vc_PeriodPerfSlidePeriod=ht->ht_Voices[i].vc_PeriodPerfSlideOn=ht->ht_Voices[i].vc_VibratoDelay=ht->ht_Voices[i].vc_VibratoCurrent=ht->ht_Voices[i].vc_VibratoDepth=ht->ht_Voices[i].vc_VibratoSpeed=0; + ht->ht_Voices[i].vc_SquareOn=ht->ht_Voices[i].vc_SquareInit=ht->ht_Voices[i].vc_SquareLowerLimit=ht->ht_Voices[i].vc_SquareUpperLimit=ht->ht_Voices[i].vc_SquarePos=ht->ht_Voices[i].vc_SquareSign=ht->ht_Voices[i].vc_SquareSlidingIn=ht->ht_Voices[i].vc_SquareReverse=0; + ht->ht_Voices[i].vc_FilterOn=ht->ht_Voices[i].vc_FilterInit=ht->ht_Voices[i].vc_FilterLowerLimit=ht->ht_Voices[i].vc_FilterUpperLimit=ht->ht_Voices[i].vc_FilterPos=ht->ht_Voices[i].vc_FilterSign=ht->ht_Voices[i].vc_FilterSpeed=ht->ht_Voices[i].vc_FilterSlidingIn=ht->ht_Voices[i].vc_IgnoreFilter=0; + ht->ht_Voices[i].vc_PerfCurrent=ht->ht_Voices[i].vc_PerfSpeed=ht->ht_Voices[i].vc_WaveLength=ht->ht_Voices[i].vc_NoteDelayOn=ht->ht_Voices[i].vc_NoteCutOn=0; + ht->ht_Voices[i].vc_AudioPeriod=ht->ht_Voices[i].vc_AudioVolume=ht->ht_Voices[i].vc_VoiceVolume=ht->ht_Voices[i].vc_VoicePeriod=ht->ht_Voices[i].vc_VoiceNum=ht->ht_Voices[i].vc_WNRandom=0; + ht->ht_Voices[i].vc_SquareWait=ht->ht_Voices[i].vc_FilterWait=ht->ht_Voices[i].vc_PerfWait=ht->ht_Voices[i].vc_NoteDelayWait=ht->ht_Voices[i].vc_NoteCutWait=0; + ht->ht_Voices[i].vc_PerfList=0; + ht->ht_Voices[i].vc_RingSamplePos=ht->ht_Voices[i].vc_RingDelta=ht->ht_Voices[i].vc_RingPlantPeriod=ht->ht_Voices[i].vc_RingAudioPeriod=ht->ht_Voices[i].vc_RingNewWaveform=ht->ht_Voices[i].vc_RingWaveform=ht->ht_Voices[i].vc_RingFixedPeriod=ht->ht_Voices[i].vc_RingBasePeriod=0; + + ht->ht_Voices[i].vc_RingMixSource = NULL; + ht->ht_Voices[i].vc_RingAudioSource = NULL; + + memset(&ht->ht_Voices[i].vc_SquareTempBuffer,0,0x80); + memset(&ht->ht_Voices[i].vc_ADSR,0,sizeof(struct hvl_envelope)); + memset(&ht->ht_Voices[i].vc_VoiceBuffer,0,0x281); + memset(&ht->ht_Voices[i].vc_RingVoiceBuffer,0,0x281); + } + + for( i=0; iht_Voices[i].vc_WNRandom = 0x280; + ht->ht_Voices[i].vc_VoiceNum = i; + ht->ht_Voices[i].vc_TrackMasterVolume = 0x40; + ht->ht_Voices[i].vc_TrackOn = 1; + ht->ht_Voices[i].vc_MixSource = ht->ht_Voices[i].vc_VoiceBuffer; + + ht->ht_Voices[i].vc_LastAmp[0] = 0; + ht->ht_Voices[i].vc_LastAmp[1] = 0; + ht->ht_Voices[i].vc_LastClock[0] = 0; + ht->ht_Voices[i].vc_LastClock[1] = 0; + } + + hvl_blip_clear(ht->ht_BlipBuffers[0]); + hvl_blip_clear(ht->ht_BlipBuffers[1]); +} + +BOOL hvl_InitSubsong( struct hvl_tune *ht, uint32 nr ) +{ + uint32 PosNr, i; + + if( nr > ht->ht_SubsongNr ) + return FALSE; + + ht->ht_SongNum = nr; + + PosNr = 0; + if( nr ) PosNr = ht->ht_Subsongs[nr-1]; + + ht->ht_PosNr = PosNr; + ht->ht_PosJump = 0; + ht->ht_PatternBreak = 0; + ht->ht_NoteNr = 0; + ht->ht_PosJumpNote = 0; + ht->ht_Tempo = 6; + ht->ht_StepWaitFrames = 0; + ht->ht_GetNewPosition = 1; + ht->ht_SongEndReached = 0; + ht->ht_PlayingTime = 0; + + for( i=0; iht_Voices[i+0].vc_Pan = ht->ht_defpanleft; + ht->ht_Voices[i+0].vc_SetPan = ht->ht_defpanleft; // 1.4 + ht->ht_Voices[i+0].vc_PanMultLeft = panning_left[ht->ht_defpanleft]; + ht->ht_Voices[i+0].vc_PanMultRight = panning_right[ht->ht_defpanleft]; + ht->ht_Voices[i+1].vc_Pan = ht->ht_defpanright; + ht->ht_Voices[i+1].vc_SetPan = ht->ht_defpanright; // 1.4 + ht->ht_Voices[i+1].vc_PanMultLeft = panning_left[ht->ht_defpanright]; + ht->ht_Voices[i+1].vc_PanMultRight = panning_right[ht->ht_defpanright]; + ht->ht_Voices[i+2].vc_Pan = ht->ht_defpanright; + ht->ht_Voices[i+2].vc_SetPan = ht->ht_defpanright; // 1.4 + ht->ht_Voices[i+2].vc_PanMultLeft = panning_left[ht->ht_defpanright]; + ht->ht_Voices[i+2].vc_PanMultRight = panning_right[ht->ht_defpanright]; + ht->ht_Voices[i+3].vc_Pan = ht->ht_defpanleft; + ht->ht_Voices[i+3].vc_SetPan = ht->ht_defpanleft; // 1.4 + ht->ht_Voices[i+3].vc_PanMultLeft = panning_left[ht->ht_defpanleft]; + ht->ht_Voices[i+3].vc_PanMultRight = panning_right[ht->ht_defpanleft]; + } + + hvl_reset_some_stuff( ht ); + + return TRUE; +} + +void hvl_InitReplayer( void ) +{ + hvl_GenPanningTables(); + hvl_GenSawtooth( &waves[WO_SAWTOOTH_04], 0x04 ); + hvl_GenSawtooth( &waves[WO_SAWTOOTH_08], 0x08 ); + hvl_GenSawtooth( &waves[WO_SAWTOOTH_10], 0x10 ); + hvl_GenSawtooth( &waves[WO_SAWTOOTH_20], 0x20 ); + hvl_GenSawtooth( &waves[WO_SAWTOOTH_40], 0x40 ); + hvl_GenSawtooth( &waves[WO_SAWTOOTH_80], 0x80 ); + hvl_GenTriangle( &waves[WO_TRIANGLE_04], 0x04 ); + hvl_GenTriangle( &waves[WO_TRIANGLE_08], 0x08 ); + hvl_GenTriangle( &waves[WO_TRIANGLE_10], 0x10 ); + hvl_GenTriangle( &waves[WO_TRIANGLE_20], 0x20 ); + hvl_GenTriangle( &waves[WO_TRIANGLE_40], 0x40 ); + hvl_GenTriangle( &waves[WO_TRIANGLE_80], 0x80 ); + hvl_GenSquare( &waves[WO_SQUARES] ); + hvl_GenWhiteNoise( &waves[WO_WHITENOISE], WHITENOISELEN ); + hvl_GenFilterWaves( &waves[WO_TRIANGLE_04], &waves[WO_LOWPASSES], &waves[WO_HIGHPASSES] ); +} + +struct hvl_tune *hvl_load_ahx( uint8 *buf, uint32 buflen, uint32 defstereo, uint32 freq ) +{ + uint8 *bptr; + TEXT *nptr; + uint32 i, j, k, l, posn, insn, ssn, hs, trkn, trkl; + struct hvl_tune *ht; + struct hvl_plsentry *ple; + int32 defgain[] = { 71, 72, 76, 85, 100 }; + + if ( buflen < 14 ) + return NULL; + + posn = ((buf[6]&0x0f)<<8)|buf[7]; + insn = buf[12]; + ssn = buf[13]; + trkl = buf[10]; + trkn = buf[11]; + + hs = sizeof( struct hvl_tune ); + hs += sizeof( struct hvl_position ) * posn; + hs += sizeof( struct hvl_instrument ) * (insn+1); + hs += sizeof( uint16 ) * ssn; + hs += hvl_blip_size( 256 ) * 2; + + // Calculate the size of all instrument PList buffers + bptr = &buf[14]; + bptr += ssn*2; // Skip past the subsong list + bptr += posn*4*2; // Skip past the positions + bptr += trkn*trkl*3; + if((buf[6]&0x80)==0) bptr += trkl*3; + + // *NOW* we can finally calculate PList space + for( i=1; i<=insn; i++ ) + { + if ( bptr + 21 > buf + buflen ) + return NULL; + + hs += bptr[21] * sizeof( struct hvl_plsentry ); + bptr += 22 + bptr[21]*4; + } + + ht = malloc( hs ); + if( !ht ) + { + return NULL; + } + + ht->ht_Frequency = freq; + ht->ht_FreqF = (float64)freq; + + ht->ht_Positions = (struct hvl_position *)(&ht[1]); + ht->ht_Instruments = (struct hvl_instrument *)(&ht->ht_Positions[posn]); + ht->ht_Subsongs = (uint16 *)(&ht->ht_Instruments[(insn+1)]); + ht->ht_BlipBuffers[0] = (hvl_blip_t *)(&ht->ht_Subsongs[ssn]); + ht->ht_BlipBuffers[1] = (hvl_blip_t *)((uint8 *)(ht->ht_BlipBuffers[0]) + hvl_blip_size(256)); + ple = (struct hvl_plsentry *)(((uint8 *)ht->ht_BlipBuffers[1]) + hvl_blip_size(256)); + + hvl_blip_new_inplace(ht->ht_BlipBuffers[0], 256); + hvl_blip_new_inplace(ht->ht_BlipBuffers[1], 256); + hvl_blip_set_rates(ht->ht_BlipBuffers[0], 65536, 1); + hvl_blip_set_rates(ht->ht_BlipBuffers[1], 65536, 1); + + ht->ht_WaveformTab[0] = &waves[WO_TRIANGLE_04]; + ht->ht_WaveformTab[1] = &waves[WO_SAWTOOTH_04]; + ht->ht_WaveformTab[3] = &waves[WO_WHITENOISE]; + + ht->ht_Channels = 4; + ht->ht_PositionNr = posn; + ht->ht_Restart = (buf[8]<<8)|buf[9]; + ht->ht_SpeedMultiplier = ((buf[6]>>5)&3)+1; + ht->ht_TrackLength = trkl; + ht->ht_TrackNr = trkn; + ht->ht_InstrumentNr = insn; + ht->ht_SubsongNr = ssn; + ht->ht_defstereo = defstereo; + ht->ht_defpanleft = stereopan_left[ht->ht_defstereo]; + ht->ht_defpanright = stereopan_right[ht->ht_defstereo]; + ht->ht_mixgain = (defgain[ht->ht_defstereo]*256)/100; + + if( ht->ht_Restart >= ht->ht_PositionNr ) + ht->ht_Restart = ht->ht_PositionNr-1; + + // Do some validation + if( ( ht->ht_PositionNr > 1000 ) || + ( ht->ht_TrackLength > 64 ) || + ( ht->ht_InstrumentNr > 64 ) ) + { + free( ht ); + return NULL; + } + + bptr = &buf[(buf[4]<<8)|buf[5]]; + i = min( 128, buf + buflen - bptr ); + + strncpy( ht->ht_Name, (TEXT *)bptr, i ); + if ( i < 128 ) ht->ht_Name[ i ] = 0; + nptr = (TEXT *)bptr+strlen( ht->ht_Name )+1; + if ( nptr > buf + buflen ) + { + free( ht ); + return NULL; + } + + bptr = &buf[14]; + + // Subsongs + for( i=0; iht_SubsongNr; i++ ) + { + ht->ht_Subsongs[i] = (bptr[0]<<8)|bptr[1]; + if( ht->ht_Subsongs[i] >= ht->ht_PositionNr ) + ht->ht_Subsongs[i] = 0; + bptr += 2; + } + + // Position list + for( i=0; iht_PositionNr; i++ ) + { + for( j=0; j<4; j++ ) + { + ht->ht_Positions[i].pos_Track[j] = *bptr++; + ht->ht_Positions[i].pos_Transpose[j] = *(int8 *)bptr++; + } + } + + // Tracks + for( i=0; i<=ht->ht_TrackNr; i++ ) + { + if( ( ( buf[6]&0x80 ) == 0x80 ) && ( i == 0 ) ) + { + for( j=0; jht_TrackLength; j++ ) + { + ht->ht_Tracks[i][j].stp_Note = 0; + ht->ht_Tracks[i][j].stp_Instrument = 0; + ht->ht_Tracks[i][j].stp_FX = 0; + ht->ht_Tracks[i][j].stp_FXParam = 0; + ht->ht_Tracks[i][j].stp_FXb = 0; + ht->ht_Tracks[i][j].stp_FXbParam = 0; + } + continue; + } + + for( j=0; jht_TrackLength; j++ ) + { + ht->ht_Tracks[i][j].stp_Note = (bptr[0]>>2)&0x3f; + ht->ht_Tracks[i][j].stp_Instrument = ((bptr[0]&0x3)<<4) | (bptr[1]>>4); + ht->ht_Tracks[i][j].stp_FX = bptr[1]&0xf; + ht->ht_Tracks[i][j].stp_FXParam = bptr[2]; + ht->ht_Tracks[i][j].stp_FXb = 0; + ht->ht_Tracks[i][j].stp_FXbParam = 0; + bptr += 3; + } + } + + // Instruments + for( i=1; i<=ht->ht_InstrumentNr; i++ ) + { + if( nptr < (TEXT *)(buf+buflen) ) + { + strncpy( ht->ht_Instruments[i].ins_Name, nptr, 128 ); + nptr += strlen( nptr )+1; + } else { + ht->ht_Instruments[i].ins_Name[0] = 0; + } + + ht->ht_Instruments[i].ins_Volume = bptr[0]; + ht->ht_Instruments[i].ins_FilterSpeed = ((bptr[1]>>3)&0x1f)|((bptr[12]>>2)&0x20); + ht->ht_Instruments[i].ins_WaveLength = bptr[1]&0x07; + + ht->ht_Instruments[i].ins_Envelope.aFrames = bptr[2]; + ht->ht_Instruments[i].ins_Envelope.aVolume = bptr[3]; + ht->ht_Instruments[i].ins_Envelope.dFrames = bptr[4]; + ht->ht_Instruments[i].ins_Envelope.dVolume = bptr[5]; + ht->ht_Instruments[i].ins_Envelope.sFrames = bptr[6]; + ht->ht_Instruments[i].ins_Envelope.rFrames = bptr[7]; + ht->ht_Instruments[i].ins_Envelope.rVolume = bptr[8]; + + ht->ht_Instruments[i].ins_FilterLowerLimit = bptr[12]&0x7f; + ht->ht_Instruments[i].ins_VibratoDelay = bptr[13]; + ht->ht_Instruments[i].ins_HardCutReleaseFrames = (bptr[14]>>4)&0x07; + ht->ht_Instruments[i].ins_HardCutRelease = bptr[14]&0x80?1:0; + ht->ht_Instruments[i].ins_VibratoDepth = bptr[14]&0x0f; + ht->ht_Instruments[i].ins_VibratoSpeed = bptr[15]; + ht->ht_Instruments[i].ins_SquareLowerLimit = bptr[16]; + ht->ht_Instruments[i].ins_SquareUpperLimit = bptr[17]; + ht->ht_Instruments[i].ins_SquareSpeed = bptr[18]; + ht->ht_Instruments[i].ins_FilterUpperLimit = bptr[19]&0x3f; + ht->ht_Instruments[i].ins_PList.pls_Speed = bptr[20]; + ht->ht_Instruments[i].ins_PList.pls_Length = bptr[21]; + + ht->ht_Instruments[i].ins_PList.pls_Entries = ple; + ple += bptr[21]; + + bptr += 22; + for( j=0; jht_Instruments[i].ins_PList.pls_Length; j++ ) + { + k = (bptr[0]>>5)&7; + if( k == 6 ) k = 12; + if( k == 7 ) k = 15; + l = (bptr[0]>>2)&7; + if( l == 6 ) l = 12; + if( l == 7 ) l = 15; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_FX[1] = k; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_FX[0] = l; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_Waveform = ((bptr[0]<<1)&6) | (bptr[1]>>7); + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_Fixed = (bptr[1]>>6)&1; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_Note = bptr[1]&0x3f; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[0] = bptr[2]; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[1] = bptr[3]; + + // 1.6: Strip "toggle filter" commands if the module is + // version 0 (pre-filters). This is what AHX also does. + if( ( buf[3] == 0 ) && ( l == 4 ) && ( (bptr[2]&0xf0) != 0 ) ) + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[0] &= 0x0f; + if( ( buf[3] == 0 ) && ( k == 4 ) && ( (bptr[3]&0xf0) != 0 ) ) + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[1] &= 0x0f; // 1.8 + + bptr += 4; + } + } + + hvl_InitSubsong( ht, 0 ); + return ht; +} + +struct hvl_tune *hvl_LoadTune( const uint8 *buf, uint32 buflen, uint32 freq, uint32 defstereo ) +{ + struct hvl_tune *ht; + uint8 *bptr; + TEXT *nptr; + uint32 i, j, posn, insn, ssn, chnn, hs, trkl, trkn; + FILE *fh; + struct hvl_plsentry *ple; + + if ( !buf || buflen < 4 ) + return NULL; + + if( ( buf[0] == 'T' ) && + ( buf[1] == 'H' ) && + ( buf[2] == 'X' ) && + ( buf[3] < 3 ) ) + return hvl_load_ahx( buf, buflen, defstereo, freq ); + + if( ( buf[0] != 'H' ) || + ( buf[1] != 'V' ) || + ( buf[2] != 'L' ) || + ( buf[3] > 1 ) ) + { + return NULL; + } + + if ( buflen < 14 ) + return NULL; + + posn = ((buf[6]&0x0f)<<8)|buf[7]; + insn = buf[12]; + ssn = buf[13]; + chnn = (buf[8]>>2)+4; + trkl = buf[10]; + trkn = buf[11]; + + hs = sizeof( struct hvl_tune ); + hs += sizeof( struct hvl_position ) * posn; + hs += sizeof( struct hvl_instrument ) * (insn+1); + hs += sizeof( uint16 ) * ssn; + hs += hvl_blip_size(256) * 2; + + // Calculate the size of all instrument PList buffers + bptr = &buf[16]; + bptr += ssn*2; // Skip past the subsong list + bptr += posn*chnn*2; // Skip past the positions + + // Skip past the tracks + // 1.4: Fixed two really stupid bugs that cancelled each other + // out if the module had a blank first track (which is how + // come they were missed. + for( i=((buf[6]&0x80)==0x80)?1:0; i<=trkn; i++ ) + for( j=0; j buf + buflen ) + return NULL; + + if( bptr[0] == 0x3f ) + { + bptr++; + continue; + } + bptr += 5; + } + + // *NOW* we can finally calculate PList space + for( i=1; i<=insn; i++ ) + { + if ( bptr + 21 > buf + buflen ) + return NULL; + + hs += bptr[21] * sizeof( struct hvl_plsentry ); + bptr += 22 + bptr[21]*5; + } + + ht = malloc( hs ); + if( !ht ) + { + return NULL; + } + + ht->ht_Version = buf[3]; // 1.5 + ht->ht_Frequency = freq; + ht->ht_FreqF = (float64)freq; + + ht->ht_Positions = (struct hvl_position *)(&ht[1]); + ht->ht_Instruments = (struct hvl_instrument *)(&ht->ht_Positions[posn]); + ht->ht_Subsongs = (uint16 *)(&ht->ht_Instruments[(insn+1)]); + ht->ht_BlipBuffers[0] = (hvl_blip_t *)(&ht->ht_Subsongs[ssn]); + ht->ht_BlipBuffers[1] = (hvl_blip_t *)(((uint8 *)ht->ht_BlipBuffers[0]) + hvl_blip_size(256)); + ple = (struct hvl_plsentry *)(((uint8 *)ht->ht_BlipBuffers[1]) + hvl_blip_size(256)); + + hvl_blip_new_inplace(ht->ht_BlipBuffers[0], 256); + hvl_blip_new_inplace(ht->ht_BlipBuffers[1], 256); + hvl_blip_set_rates(ht->ht_BlipBuffers[0], 65536, 1); + hvl_blip_set_rates(ht->ht_BlipBuffers[1], 65536, 1); + + ht->ht_WaveformTab[0] = &waves[WO_TRIANGLE_04]; + ht->ht_WaveformTab[1] = &waves[WO_SAWTOOTH_04]; + ht->ht_WaveformTab[3] = &waves[WO_WHITENOISE]; + + ht->ht_PositionNr = posn; + ht->ht_Channels = (buf[8]>>2)+4; + ht->ht_Restart = ((buf[8]&3)<<8)|buf[9]; + ht->ht_SpeedMultiplier = ((buf[6]>>5)&3)+1; + ht->ht_TrackLength = buf[10]; + ht->ht_TrackNr = buf[11]; + ht->ht_InstrumentNr = insn; + ht->ht_SubsongNr = ssn; + ht->ht_mixgain = (buf[14]<<8)/100; + ht->ht_defstereo = buf[15]; + ht->ht_defpanleft = stereopan_left[ht->ht_defstereo]; + ht->ht_defpanright = stereopan_right[ht->ht_defstereo]; + + if( ht->ht_Restart >= ht->ht_PositionNr ) + ht->ht_Restart = ht->ht_PositionNr-1; + + // Do some validation + if( ( ht->ht_PositionNr > 1000 ) || + ( ht->ht_TrackLength > 64 ) || + ( ht->ht_InstrumentNr > 64 ) ) + { + free( ht ); + return NULL; + } + + bptr = &buf[(buf[4]<<8)|buf[5]]; + if ( bptr > buf + buflen ) + { + free( ht ); + return NULL; + } + i = min( 128, buf + buflen - bptr ); + + strncpy( ht->ht_Name, (TEXT *)bptr, i ); + if ( i < 128 ) ht->ht_Name[ i ] = 0; + nptr = (TEXT *)bptr+strlen( ht->ht_Name )+1; + if ( nptr > buf + buflen ) + { + free( ht ); + return NULL; + } + + bptr = &buf[16]; + + // Subsongs + for( i=0; iht_SubsongNr; i++ ) + { + ht->ht_Subsongs[i] = (bptr[0]<<8)|bptr[1]; + bptr += 2; + } + + // Position list + for( i=0; iht_PositionNr; i++ ) + { + for( j=0; jht_Channels; j++ ) + { + ht->ht_Positions[i].pos_Track[j] = *bptr++; + ht->ht_Positions[i].pos_Transpose[j] = *(int8 *)bptr++; + } + } + + // Tracks + for( i=0; i<=ht->ht_TrackNr; i++ ) + { + if( ( ( buf[6]&0x80 ) == 0x80 ) && ( i == 0 ) ) + { + for( j=0; jht_TrackLength; j++ ) + { + ht->ht_Tracks[i][j].stp_Note = 0; + ht->ht_Tracks[i][j].stp_Instrument = 0; + ht->ht_Tracks[i][j].stp_FX = 0; + ht->ht_Tracks[i][j].stp_FXParam = 0; + ht->ht_Tracks[i][j].stp_FXb = 0; + ht->ht_Tracks[i][j].stp_FXbParam = 0; + } + continue; + } + + for( j=0; jht_TrackLength; j++ ) + { + if( bptr[0] == 0x3f ) + { + ht->ht_Tracks[i][j].stp_Note = 0; + ht->ht_Tracks[i][j].stp_Instrument = 0; + ht->ht_Tracks[i][j].stp_FX = 0; + ht->ht_Tracks[i][j].stp_FXParam = 0; + ht->ht_Tracks[i][j].stp_FXb = 0; + ht->ht_Tracks[i][j].stp_FXbParam = 0; + bptr++; + continue; + } + + ht->ht_Tracks[i][j].stp_Note = bptr[0]; + ht->ht_Tracks[i][j].stp_Instrument = bptr[1]; + ht->ht_Tracks[i][j].stp_FX = bptr[2]>>4; + ht->ht_Tracks[i][j].stp_FXParam = bptr[3]; + ht->ht_Tracks[i][j].stp_FXb = bptr[2]&0xf; + ht->ht_Tracks[i][j].stp_FXbParam = bptr[4]; + bptr += 5; + } + } + + + // Instruments + for( i=1; i<=ht->ht_InstrumentNr; i++ ) + { + if( nptr < (TEXT *)(buf+buflen) ) + { + strncpy( ht->ht_Instruments[i].ins_Name, nptr, 128 ); + nptr += strlen( nptr )+1; + } else { + ht->ht_Instruments[i].ins_Name[0] = 0; + } + + ht->ht_Instruments[i].ins_Volume = bptr[0]; + ht->ht_Instruments[i].ins_FilterSpeed = ((bptr[1]>>3)&0x1f)|((bptr[12]>>2)&0x20); + ht->ht_Instruments[i].ins_WaveLength = bptr[1]&0x07; + + ht->ht_Instruments[i].ins_Envelope.aFrames = bptr[2]; + ht->ht_Instruments[i].ins_Envelope.aVolume = bptr[3]; + ht->ht_Instruments[i].ins_Envelope.dFrames = bptr[4]; + ht->ht_Instruments[i].ins_Envelope.dVolume = bptr[5]; + ht->ht_Instruments[i].ins_Envelope.sFrames = bptr[6]; + ht->ht_Instruments[i].ins_Envelope.rFrames = bptr[7]; + ht->ht_Instruments[i].ins_Envelope.rVolume = bptr[8]; + + ht->ht_Instruments[i].ins_FilterLowerLimit = bptr[12]&0x7f; + ht->ht_Instruments[i].ins_VibratoDelay = bptr[13]; + ht->ht_Instruments[i].ins_HardCutReleaseFrames = (bptr[14]>>4)&0x07; + ht->ht_Instruments[i].ins_HardCutRelease = bptr[14]&0x80?1:0; + ht->ht_Instruments[i].ins_VibratoDepth = bptr[14]&0x0f; + ht->ht_Instruments[i].ins_VibratoSpeed = bptr[15]; + ht->ht_Instruments[i].ins_SquareLowerLimit = bptr[16]; + ht->ht_Instruments[i].ins_SquareUpperLimit = bptr[17]; + ht->ht_Instruments[i].ins_SquareSpeed = bptr[18]; + ht->ht_Instruments[i].ins_FilterUpperLimit = bptr[19]&0x3f; + ht->ht_Instruments[i].ins_PList.pls_Speed = bptr[20]; + ht->ht_Instruments[i].ins_PList.pls_Length = bptr[21]; + + ht->ht_Instruments[i].ins_PList.pls_Entries = ple; + ple += bptr[21]; + + bptr += 22; + for( j=0; jht_Instruments[i].ins_PList.pls_Length; j++ ) + { + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_FX[0] = bptr[0]&0xf; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_FX[1] = (bptr[1]>>3)&0xf; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_Waveform = bptr[1]&7; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_Fixed = (bptr[2]>>6)&1; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_Note = bptr[2]&0x3f; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[0] = bptr[3]; + ht->ht_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[1] = bptr[4]; + bptr += 5; + } + } + + hvl_InitSubsong( ht, 0 ); + return ht; +} + +void hvl_FreeTune( struct hvl_tune *ht ) +{ + if( !ht ) return; + free( ht ); +} + +void hvl_process_stepfx_1( struct hvl_tune *ht, struct hvl_voice *voice, int32 FX, int32 FXParam ) +{ + switch( FX ) + { + case 0x0: // Position Jump HI + if( ((FXParam&0x0f) > 0) && ((FXParam&0x0f) <= 9) ) + ht->ht_PosJump = FXParam & 0xf; + break; + + case 0x5: // Volume Slide + Tone Portamento + case 0xa: // Volume Slide + voice->vc_VolumeSlideDown = FXParam & 0x0f; + voice->vc_VolumeSlideUp = FXParam >> 4; + break; + + case 0x7: // Panning + if( FXParam > 127 ) + FXParam -= 256; + voice->vc_Pan = (FXParam+128); + voice->vc_SetPan = (FXParam+128); // 1.4 + voice->vc_PanMultLeft = panning_left[voice->vc_Pan]; + voice->vc_PanMultRight = panning_right[voice->vc_Pan]; + break; + + case 0xb: // Position jump + ht->ht_PosJump = ht->ht_PosJump*100 + (FXParam & 0x0f) + (FXParam >> 4)*10; + ht->ht_PatternBreak = 1; + if( ht->ht_PosJump <= ht->ht_PosNr ) + ht->ht_SongEndReached = 1; + break; + + case 0xd: // Pattern break + ht->ht_PosJump = ht->ht_PosNr+1; + ht->ht_PosJumpNote = (FXParam & 0x0f) + (FXParam>>4)*10; + ht->ht_PatternBreak = 1; + if( ht->ht_PosJumpNote > ht->ht_TrackLength ) + ht->ht_PosJumpNote = 0; + break; + + case 0xe: // Extended commands + switch( FXParam >> 4 ) + { + case 0xc: // Note cut + if( (FXParam & 0x0f) < ht->ht_Tempo ) + { + voice->vc_NoteCutWait = FXParam & 0x0f; + if( voice->vc_NoteCutWait ) + { + voice->vc_NoteCutOn = 1; + voice->vc_HardCutRelease = 0; + } + } + break; + + // 1.6: 0xd case removed + } + break; + + case 0xf: // Speed + ht->ht_Tempo = FXParam; + if( FXParam == 0 ) + ht->ht_SongEndReached = 1; + break; + } +} + +void hvl_process_stepfx_2( struct hvl_tune *ht, struct hvl_voice *voice, int32 FX, int32 FXParam, int32 *Note ) +{ + switch( FX ) + { + case 0x9: // Set squarewave offset + voice->vc_SquarePos = FXParam >> (5 - voice->vc_WaveLength); +// voice->vc_PlantSquare = 1; + voice->vc_IgnoreSquare = 1; + break; + + case 0x5: // Tone portamento + volume slide + case 0x3: // Tone portamento + if( FXParam != 0 ) voice->vc_PeriodSlideSpeed = FXParam; + + if( *Note ) + { + int32 new, diff; + + new = period_tab[*Note]; + diff = period_tab[voice->vc_TrackPeriod]; + diff -= new; + new = diff + voice->vc_PeriodSlidePeriod; + + if( new ) + voice->vc_PeriodSlideLimit = -diff; + } + voice->vc_PeriodSlideOn = 1; + voice->vc_PeriodSlideWithLimit = 1; + *Note = 0; + break; + } +} + +void hvl_process_stepfx_3( struct hvl_tune *ht, struct hvl_voice *voice, int32 FX, int32 FXParam ) +{ + int32 i; + + switch( FX ) + { + case 0x01: // Portamento up (period slide down) + voice->vc_PeriodSlideSpeed = -FXParam; + voice->vc_PeriodSlideOn = 1; + voice->vc_PeriodSlideWithLimit = 0; + break; + case 0x02: // Portamento down + voice->vc_PeriodSlideSpeed = FXParam; + voice->vc_PeriodSlideOn = 1; + voice->vc_PeriodSlideWithLimit = 0; + break; + case 0x04: // Filter override + if( ( FXParam == 0 ) || ( FXParam == 0x40 ) ) break; + if( FXParam < 0x40 ) + { + voice->vc_IgnoreFilter = FXParam; + break; + } + if( FXParam > 0x7f ) break; + voice->vc_FilterPos = FXParam - 0x40; + break; + case 0x0c: // Volume + FXParam &= 0xff; + if( FXParam <= 0x40 ) + { + voice->vc_NoteMaxVolume = FXParam; + break; + } + + if( (FXParam -= 0x50) < 0 ) break; // 1.6 + + if( FXParam <= 0x40 ) + { + for( i=0; iht_Channels; i++ ) + ht->ht_Voices[i].vc_TrackMasterVolume = FXParam; + break; + } + + if( (FXParam -= 0xa0-0x50) < 0 ) break; // 1.6 + + if( FXParam <= 0x40 ) + voice->vc_TrackMasterVolume = FXParam; + break; + + case 0xe: // Extended commands; + switch( FXParam >> 4 ) + { + case 0x1: // Fineslide up + voice->vc_PeriodSlidePeriod -= (FXParam & 0x0f); // 1.8 + voice->vc_PlantPeriod = 1; + break; + + case 0x2: // Fineslide down + voice->vc_PeriodSlidePeriod += (FXParam & 0x0f); // 1.8 + voice->vc_PlantPeriod = 1; + break; + + case 0x4: // Vibrato control + voice->vc_VibratoDepth = FXParam & 0x0f; + break; + + case 0x0a: // Fine volume up + voice->vc_NoteMaxVolume += FXParam & 0x0f; + + if( voice->vc_NoteMaxVolume > 0x40 ) + voice->vc_NoteMaxVolume = 0x40; + break; + + case 0x0b: // Fine volume down + voice->vc_NoteMaxVolume -= FXParam & 0x0f; + + if( voice->vc_NoteMaxVolume < 0 ) + voice->vc_NoteMaxVolume = 0; + break; + + case 0x0f: // Misc flags (1.5) + if( ht->ht_Version < 1 ) break; + switch( FXParam & 0xf ) + { + case 1: + voice->vc_OverrideTranspose = voice->vc_Transpose; + break; + } + break; + } + break; + } +} + +void hvl_process_step( struct hvl_tune *ht, struct hvl_voice *voice ) +{ + int32 Note, Instr, donenotedel; + struct hvl_step *Step; + + if( voice->vc_TrackOn == 0 ) + return; + + voice->vc_VolumeSlideUp = voice->vc_VolumeSlideDown = 0; + + Step = &ht->ht_Tracks[ht->ht_Positions[ht->ht_PosNr].pos_Track[voice->vc_VoiceNum]][ht->ht_NoteNr]; + + Note = Step->stp_Note; + Instr = Step->stp_Instrument; + + // --------- 1.6: from here -------------- + + donenotedel = 0; + + // Do notedelay here + if( ((Step->stp_FX&0xf)==0xe) && ((Step->stp_FXParam&0xf0)==0xd0) ) + { + if( voice->vc_NoteDelayOn ) + { + voice->vc_NoteDelayOn = 0; + donenotedel = 1; + } else { + if( (Step->stp_FXParam&0x0f) < ht->ht_Tempo ) + { + voice->vc_NoteDelayWait = Step->stp_FXParam & 0x0f; + if( voice->vc_NoteDelayWait ) + { + voice->vc_NoteDelayOn = 1; + return; + } + } + } + } + + if( (donenotedel==0) && ((Step->stp_FXb&0xf)==0xe) && ((Step->stp_FXbParam&0xf0)==0xd0) ) + { + if( voice->vc_NoteDelayOn ) + { + voice->vc_NoteDelayOn = 0; + } else { + if( (Step->stp_FXbParam&0x0f) < ht->ht_Tempo ) + { + voice->vc_NoteDelayWait = Step->stp_FXbParam & 0x0f; + if( voice->vc_NoteDelayWait ) + { + voice->vc_NoteDelayOn = 1; + return; + } + } + } + } + + // --------- 1.6: to here -------------- + + if( Note ) voice->vc_OverrideTranspose = 1000; // 1.5 + + hvl_process_stepfx_1( ht, voice, Step->stp_FX&0xf, Step->stp_FXParam ); + hvl_process_stepfx_1( ht, voice, Step->stp_FXb&0xf, Step->stp_FXbParam ); + + if( ( Instr ) && ( Instr <= ht->ht_InstrumentNr ) ) + { + struct hvl_instrument *Ins; + int16 SquareLower, SquareUpper, d6, d3, d4; + + /* 1.4: Reset panning to last set position */ + voice->vc_Pan = voice->vc_SetPan; + voice->vc_PanMultLeft = panning_left[voice->vc_Pan]; + voice->vc_PanMultRight = panning_right[voice->vc_Pan]; + + voice->vc_PeriodSlideSpeed = voice->vc_PeriodSlidePeriod = voice->vc_PeriodSlideLimit = 0; + + voice->vc_PerfSubVolume = 0x40; + voice->vc_ADSRVolume = 0; + voice->vc_Instrument = Ins = &ht->ht_Instruments[Instr]; + voice->vc_SamplePos = 0; + + voice->vc_ADSR.aFrames = Ins->ins_Envelope.aFrames; + voice->vc_ADSR.aVolume = voice->vc_ADSR.aFrames ? Ins->ins_Envelope.aVolume*256/voice->vc_ADSR.aFrames : Ins->ins_Envelope.aVolume * 256; // XXX + voice->vc_ADSR.dFrames = Ins->ins_Envelope.dFrames; + voice->vc_ADSR.dVolume = voice->vc_ADSR.dFrames ? (Ins->ins_Envelope.dVolume-Ins->ins_Envelope.aVolume)*256/voice->vc_ADSR.dFrames : Ins->ins_Envelope.dVolume * 256; // XXX + voice->vc_ADSR.sFrames = Ins->ins_Envelope.sFrames; + voice->vc_ADSR.rFrames = Ins->ins_Envelope.rFrames; + voice->vc_ADSR.rVolume = voice->vc_ADSR.rFrames ? (Ins->ins_Envelope.rVolume-Ins->ins_Envelope.dVolume)*256/voice->vc_ADSR.rFrames : Ins->ins_Envelope.rVolume * 256; // XXX + + voice->vc_WaveLength = Ins->ins_WaveLength; + voice->vc_NoteMaxVolume = Ins->ins_Volume; + + voice->vc_VibratoCurrent = 0; + voice->vc_VibratoDelay = Ins->ins_VibratoDelay; + voice->vc_VibratoDepth = Ins->ins_VibratoDepth; + voice->vc_VibratoSpeed = Ins->ins_VibratoSpeed; + voice->vc_VibratoPeriod = 0; + + voice->vc_HardCutRelease = Ins->ins_HardCutRelease; + voice->vc_HardCut = Ins->ins_HardCutReleaseFrames; + + voice->vc_IgnoreSquare = voice->vc_SquareSlidingIn = 0; + voice->vc_SquareWait = voice->vc_SquareOn = 0; + + SquareLower = Ins->ins_SquareLowerLimit >> (5 - voice->vc_WaveLength); + SquareUpper = Ins->ins_SquareUpperLimit >> (5 - voice->vc_WaveLength); + + if( SquareUpper < SquareLower ) + { + int16 t = SquareUpper; + SquareUpper = SquareLower; + SquareLower = t; + } + + voice->vc_SquareUpperLimit = SquareUpper; + voice->vc_SquareLowerLimit = SquareLower; + + voice->vc_IgnoreFilter = voice->vc_FilterWait = voice->vc_FilterOn = 0; + voice->vc_FilterSlidingIn = 0; + + d6 = Ins->ins_FilterSpeed; + d3 = Ins->ins_FilterLowerLimit; + d4 = Ins->ins_FilterUpperLimit; + + if( d3 & 0x80 ) d6 |= 0x20; + if( d4 & 0x80 ) d6 |= 0x40; + + voice->vc_FilterSpeed = d6; + d3 &= ~0x80; + d4 &= ~0x80; + + if( d3 > d4 ) + { + int16 t = d3; + d3 = d4; + d4 = t; + } + + voice->vc_FilterUpperLimit = d4; + voice->vc_FilterLowerLimit = d3; + voice->vc_FilterPos = 32; + + voice->vc_PerfWait = voice->vc_PerfCurrent = 0; + voice->vc_PerfSpeed = Ins->ins_PList.pls_Speed; + voice->vc_PerfList = &voice->vc_Instrument->ins_PList; + + voice->vc_RingMixSource = NULL; // No ring modulation + voice->vc_RingSamplePos = 0; + voice->vc_RingPlantPeriod = 0; + voice->vc_RingNewWaveform = 0; + } + + voice->vc_PeriodSlideOn = 0; + + hvl_process_stepfx_2( ht, voice, Step->stp_FX&0xf, Step->stp_FXParam, &Note ); + hvl_process_stepfx_2( ht, voice, Step->stp_FXb&0xf, Step->stp_FXbParam, &Note ); + + if( Note ) + { + voice->vc_TrackPeriod = Note; + voice->vc_PlantPeriod = 1; + } + + hvl_process_stepfx_3( ht, voice, Step->stp_FX&0xf, Step->stp_FXParam ); + hvl_process_stepfx_3( ht, voice, Step->stp_FXb&0xf, Step->stp_FXbParam ); +} + +void hvl_plist_command_parse( struct hvl_tune *ht, struct hvl_voice *voice, int32 FX, int32 FXParam ) +{ + switch( FX ) + { + case 0: + if( ( FXParam > 0 ) && ( FXParam < 0x40 ) ) + { + if( voice->vc_IgnoreFilter ) + { + voice->vc_FilterPos = voice->vc_IgnoreFilter; + voice->vc_IgnoreFilter = 0; + } else { + voice->vc_FilterPos = FXParam; + } + voice->vc_NewWaveform = 1; + } + break; + + case 1: + voice->vc_PeriodPerfSlideSpeed = FXParam; + voice->vc_PeriodPerfSlideOn = 1; + break; + + case 2: + voice->vc_PeriodPerfSlideSpeed = -FXParam; + voice->vc_PeriodPerfSlideOn = 1; + break; + + case 3: + if( voice->vc_IgnoreSquare == 0 ) + voice->vc_SquarePos = FXParam >> (5-voice->vc_WaveLength); + else + voice->vc_IgnoreSquare = 0; + break; + + case 4: + if( FXParam == 0 ) + { + voice->vc_SquareInit = (voice->vc_SquareOn ^= 1); + voice->vc_SquareSign = 1; + } else { + + if( FXParam & 0x0f ) + { + voice->vc_SquareInit = (voice->vc_SquareOn ^= 1); + voice->vc_SquareSign = 1; + if(( FXParam & 0x0f ) == 0x0f ) + voice->vc_SquareSign = -1; + } + + if( FXParam & 0xf0 ) + { + voice->vc_FilterInit = (voice->vc_FilterOn ^= 1); + voice->vc_FilterSign = 1; + if(( FXParam & 0xf0 ) == 0xf0 ) + voice->vc_FilterSign = -1; + } + } + break; + + case 5: + voice->vc_PerfCurrent = FXParam; + break; + + case 7: + // Ring modulate with triangle + if(( FXParam >= 1 ) && ( FXParam <= 0x3C )) + { + voice->vc_RingBasePeriod = FXParam; + voice->vc_RingFixedPeriod = 1; + } else if(( FXParam >= 0x81 ) && ( FXParam <= 0xBC )) { + voice->vc_RingBasePeriod = FXParam-0x80; + voice->vc_RingFixedPeriod = 0; + } else { + voice->vc_RingBasePeriod = 0; + voice->vc_RingFixedPeriod = 0; + voice->vc_RingNewWaveform = 0; + voice->vc_RingAudioSource = NULL; // turn it off + voice->vc_RingMixSource = NULL; + break; + } + voice->vc_RingWaveform = 0; + voice->vc_RingNewWaveform = 1; + voice->vc_RingPlantPeriod = 1; + break; + + case 8: // Ring modulate with sawtooth + if(( FXParam >= 1 ) && ( FXParam <= 0x3C )) + { + voice->vc_RingBasePeriod = FXParam; + voice->vc_RingFixedPeriod = 1; + } else if(( FXParam >= 0x81 ) && ( FXParam <= 0xBC )) { + voice->vc_RingBasePeriod = FXParam-0x80; + voice->vc_RingFixedPeriod = 0; + } else { + voice->vc_RingBasePeriod = 0; + voice->vc_RingFixedPeriod = 0; + voice->vc_RingNewWaveform = 0; + voice->vc_RingAudioSource = NULL; + voice->vc_RingMixSource = NULL; + break; + } + + voice->vc_RingWaveform = 1; + voice->vc_RingNewWaveform = 1; + voice->vc_RingPlantPeriod = 1; + break; + + /* New in HivelyTracker 1.4 */ + case 9: + if( FXParam > 127 ) + FXParam -= 256; + voice->vc_Pan = (FXParam+128); + voice->vc_PanMultLeft = panning_left[voice->vc_Pan]; + voice->vc_PanMultRight = panning_right[voice->vc_Pan]; + break; + + case 12: + if( FXParam <= 0x40 ) + { + voice->vc_NoteMaxVolume = FXParam; + break; + } + + if( (FXParam -= 0x50) < 0 ) break; + + if( FXParam <= 0x40 ) + { + voice->vc_PerfSubVolume = FXParam; + break; + } + + if( (FXParam -= 0xa0-0x50) < 0 ) break; + + if( FXParam <= 0x40 ) + voice->vc_TrackMasterVolume = FXParam; + break; + + case 15: + voice->vc_PerfSpeed = voice->vc_PerfWait = FXParam; + break; + } +} + +void hvl_process_frame( struct hvl_tune *ht, struct hvl_voice *voice ) +{ + static uint8 Offsets[] = {0x00,0x04,0x04+0x08,0x04+0x08+0x10,0x04+0x08+0x10+0x20,0x04+0x08+0x10+0x20+0x40}; + + if( voice->vc_TrackOn == 0 ) + return; + + if( voice->vc_NoteDelayOn ) + { + if( voice->vc_NoteDelayWait <= 0 ) + hvl_process_step( ht, voice ); + else + voice->vc_NoteDelayWait--; + } + + if( voice->vc_HardCut ) + { + int32 nextinst; + + if( ht->ht_NoteNr+1 < ht->ht_TrackLength ) + nextinst = ht->ht_Tracks[voice->vc_Track][ht->ht_NoteNr+1].stp_Instrument; + else + nextinst = ht->ht_Tracks[voice->vc_NextTrack][0].stp_Instrument; + + if( nextinst ) + { + int32 d1; + + d1 = ht->ht_Tempo - voice->vc_HardCut; + + if( d1 < 0 ) d1 = 0; + + if( !voice->vc_NoteCutOn ) + { + voice->vc_NoteCutOn = 1; + voice->vc_NoteCutWait = d1; + voice->vc_HardCutReleaseF = -(d1-ht->ht_Tempo); + } else { + voice->vc_HardCut = 0; + } + } + } + + if( voice->vc_NoteCutOn ) + { + if( voice->vc_NoteCutWait <= 0 ) + { + voice->vc_NoteCutOn = 0; + + if( voice->vc_HardCutRelease ) + { + voice->vc_ADSR.rVolume = -(voice->vc_ADSRVolume - (voice->vc_Instrument->ins_Envelope.rVolume << 8)) / voice->vc_HardCutReleaseF; + voice->vc_ADSR.rFrames = voice->vc_HardCutReleaseF; + voice->vc_ADSR.aFrames = voice->vc_ADSR.dFrames = voice->vc_ADSR.sFrames = 0; + } else { + voice->vc_NoteMaxVolume = 0; + } + } else { + voice->vc_NoteCutWait--; + } + } + + // ADSR envelope + if( voice->vc_ADSR.aFrames ) + { + voice->vc_ADSRVolume += voice->vc_ADSR.aVolume; + + if( --voice->vc_ADSR.aFrames <= 0 ) + voice->vc_ADSRVolume = voice->vc_Instrument->ins_Envelope.aVolume << 8; + + } else if( voice->vc_ADSR.dFrames ) { + + voice->vc_ADSRVolume += voice->vc_ADSR.dVolume; + + if( --voice->vc_ADSR.dFrames <= 0 ) + voice->vc_ADSRVolume = voice->vc_Instrument->ins_Envelope.dVolume << 8; + + } else if( voice->vc_ADSR.sFrames ) { + + voice->vc_ADSR.sFrames--; + + } else if( voice->vc_ADSR.rFrames ) { + + voice->vc_ADSRVolume += voice->vc_ADSR.rVolume; + + if( --voice->vc_ADSR.rFrames <= 0 ) + voice->vc_ADSRVolume = voice->vc_Instrument->ins_Envelope.rVolume << 8; + } + + // VolumeSlide + voice->vc_NoteMaxVolume = voice->vc_NoteMaxVolume + voice->vc_VolumeSlideUp - voice->vc_VolumeSlideDown; + + if( voice->vc_NoteMaxVolume < 0 ) + voice->vc_NoteMaxVolume = 0; + else if( voice->vc_NoteMaxVolume > 0x40 ) + voice->vc_NoteMaxVolume = 0x40; + + // Portamento + if( voice->vc_PeriodSlideOn ) + { + if( voice->vc_PeriodSlideWithLimit ) + { + int32 d0, d2; + + d0 = voice->vc_PeriodSlidePeriod - voice->vc_PeriodSlideLimit; + d2 = voice->vc_PeriodSlideSpeed; + + if( d0 > 0 ) + d2 = -d2; + + if( d0 ) + { + int32 d3; + + d3 = (d0 + d2) ^ d0; + + if( d3 >= 0 ) + d0 = voice->vc_PeriodSlidePeriod + d2; + else + d0 = voice->vc_PeriodSlideLimit; + + voice->vc_PeriodSlidePeriod = d0; + voice->vc_PlantPeriod = 1; + } + } else { + voice->vc_PeriodSlidePeriod += voice->vc_PeriodSlideSpeed; + voice->vc_PlantPeriod = 1; + } + } + + // Vibrato + if( voice->vc_VibratoDepth ) + { + if( voice->vc_VibratoDelay <= 0 ) + { + voice->vc_VibratoPeriod = (vib_tab[voice->vc_VibratoCurrent] * voice->vc_VibratoDepth) >> 7; + voice->vc_PlantPeriod = 1; + voice->vc_VibratoCurrent = (voice->vc_VibratoCurrent + voice->vc_VibratoSpeed) & 0x3f; + } else { + voice->vc_VibratoDelay--; + } + } + + // PList + if( voice->vc_PerfList != 0 ) + { + if( voice->vc_Instrument && voice->vc_PerfCurrent < voice->vc_Instrument->ins_PList.pls_Length ) + { + if( --voice->vc_PerfWait <= 0 ) + { + uint32 i; + int32 cur; + + cur = voice->vc_PerfCurrent++; + voice->vc_PerfWait = voice->vc_PerfSpeed; + + if( voice->vc_PerfList->pls_Entries[cur].ple_Waveform ) + { + voice->vc_Waveform = voice->vc_PerfList->pls_Entries[cur].ple_Waveform-1; + voice->vc_NewWaveform = 1; + voice->vc_PeriodPerfSlideSpeed = voice->vc_PeriodPerfSlidePeriod = 0; + } + + // Holdwave + voice->vc_PeriodPerfSlideOn = 0; + + for( i=0; i<2; i++ ) + hvl_plist_command_parse( ht, voice, voice->vc_PerfList->pls_Entries[cur].ple_FX[i]&0xff, voice->vc_PerfList->pls_Entries[cur].ple_FXParam[i]&0xff ); + + // GetNote + if( voice->vc_PerfList->pls_Entries[cur].ple_Note ) + { + voice->vc_InstrPeriod = voice->vc_PerfList->pls_Entries[cur].ple_Note; + voice->vc_PlantPeriod = 1; + voice->vc_FixedNote = voice->vc_PerfList->pls_Entries[cur].ple_Fixed; + } + } + } else { + if( voice->vc_PerfWait ) + voice->vc_PerfWait--; + else + voice->vc_PeriodPerfSlideSpeed = 0; + } + } + + // PerfPortamento + if( voice->vc_PeriodPerfSlideOn ) + { + voice->vc_PeriodPerfSlidePeriod -= voice->vc_PeriodPerfSlideSpeed; + + if( voice->vc_PeriodPerfSlidePeriod ) + voice->vc_PlantPeriod = 1; + } + + if( voice->vc_Waveform == 3-1 && voice->vc_SquareOn ) + { + if( --voice->vc_SquareWait <= 0 ) + { + int32 d1, d2, d3; + + d1 = voice->vc_SquareLowerLimit; + d2 = voice->vc_SquareUpperLimit; + d3 = voice->vc_SquarePos; + + if( voice->vc_SquareInit ) + { + voice->vc_SquareInit = 0; + + if( d3 <= d1 ) + { + voice->vc_SquareSlidingIn = 1; + voice->vc_SquareSign = 1; + } else if( d3 >= d2 ) { + voice->vc_SquareSlidingIn = 1; + voice->vc_SquareSign = -1; + } + } + + // NoSquareInit + if( d1 == d3 || d2 == d3 ) + { + if( voice->vc_SquareSlidingIn ) + voice->vc_SquareSlidingIn = 0; + else + voice->vc_SquareSign = -voice->vc_SquareSign; + } + + d3 += voice->vc_SquareSign; + voice->vc_SquarePos = d3; + voice->vc_PlantSquare = 1; + voice->vc_SquareWait = voice->vc_Instrument->ins_SquareSpeed; + } + } + + if( voice->vc_FilterOn && --voice->vc_FilterWait <= 0 ) + { + uint32 i, FMax; + int32 d1, d2, d3; + + d1 = voice->vc_FilterLowerLimit; + d2 = voice->vc_FilterUpperLimit; + d3 = voice->vc_FilterPos; + + if( voice->vc_FilterInit ) + { + voice->vc_FilterInit = 0; + if( d3 <= d1 ) + { + voice->vc_FilterSlidingIn = 1; + voice->vc_FilterSign = 1; + } else if( d3 >= d2 ) { + voice->vc_FilterSlidingIn = 1; + voice->vc_FilterSign = -1; + } + } + + // NoFilterInit + FMax = (voice->vc_FilterSpeed < 3) ? (5-voice->vc_FilterSpeed) : 1; + + for( i=0; ivc_FilterSlidingIn ) + voice->vc_FilterSlidingIn = 0; + else + voice->vc_FilterSign = -voice->vc_FilterSign; + } + d3 += voice->vc_FilterSign; + } + + if( d3 < 1 ) d3 = 1; + if( d3 > 63 ) d3 = 63; + voice->vc_FilterPos = d3; + voice->vc_NewWaveform = 1; + voice->vc_FilterWait = voice->vc_FilterSpeed - 3; + + if( voice->vc_FilterWait < 1 ) + voice->vc_FilterWait = 1; + } + + if( voice->vc_Waveform == 3-1 || voice->vc_PlantSquare ) + { + // CalcSquare + uint32 i; + int32 Delta; + int8 *SquarePtr; + int32 X; + + SquarePtr = &waves[WO_SQUARES+(voice->vc_FilterPos-0x20)*(0xfc+0xfc+0x80*0x1f+0x80+0x280*3)]; + X = voice->vc_SquarePos << (5 - voice->vc_WaveLength); + + if( X > 0x20 ) + { + X = 0x40 - X; + voice->vc_SquareReverse = 1; + } + + // OkDownSquare + if( X > 0 ) + SquarePtr += (X-1) << 7; + + Delta = 32 >> voice->vc_WaveLength; + ht->ht_WaveformTab[2] = voice->vc_SquareTempBuffer; + + for( i=0; i<(1<vc_WaveLength)*4; i++ ) + { + voice->vc_SquareTempBuffer[i] = *SquarePtr; + SquarePtr += Delta; + } + + voice->vc_NewWaveform = 1; + voice->vc_Waveform = 3-1; + voice->vc_PlantSquare = 0; + } + + if( voice->vc_Waveform == 4-1 ) + voice->vc_NewWaveform = 1; + + if( voice->vc_RingNewWaveform ) + { + int8 *rasrc; + + if( voice->vc_RingWaveform > 1 ) voice->vc_RingWaveform = 1; + + rasrc = ht->ht_WaveformTab[voice->vc_RingWaveform]; + rasrc += Offsets[voice->vc_WaveLength]; + + voice->vc_RingAudioSource = rasrc; + } + + + if( voice->vc_NewWaveform ) + { + int8 *AudioSource; + + AudioSource = ht->ht_WaveformTab[voice->vc_Waveform]; + + if( voice->vc_Waveform != 3-1 ) + AudioSource += (voice->vc_FilterPos-0x20)*(0xfc+0xfc+0x80*0x1f+0x80+0x280*3); + + if( voice->vc_Waveform < 3-1) + { + // GetWLWaveformlor2 + AudioSource += Offsets[voice->vc_WaveLength]; + } + + if( voice->vc_Waveform == 4-1 ) + { + // AddRandomMoving + AudioSource += ( voice->vc_WNRandom & (2*0x280-1) ) & ~1; + // GoOnRandom + voice->vc_WNRandom += 2239384; + voice->vc_WNRandom = ((((voice->vc_WNRandom >> 8) | (voice->vc_WNRandom << 24)) + 782323) ^ 75) - 6735; + } + + voice->vc_AudioSource = AudioSource; + } + + // Ring modulation period calculation + if( voice->vc_RingAudioSource ) + { + voice->vc_RingAudioPeriod = voice->vc_RingBasePeriod; + + if( !(voice->vc_RingFixedPeriod) ) + { + if( voice->vc_OverrideTranspose != 1000 ) // 1.5 + voice->vc_RingAudioPeriod += voice->vc_OverrideTranspose + voice->vc_TrackPeriod - 1; + else + voice->vc_RingAudioPeriod += voice->vc_Transpose + voice->vc_TrackPeriod - 1; + } + + if( voice->vc_RingAudioPeriod > 5*12 ) + voice->vc_RingAudioPeriod = 5*12; + + if( voice->vc_RingAudioPeriod < 0 ) + voice->vc_RingAudioPeriod = 0; + + voice->vc_RingAudioPeriod = period_tab[voice->vc_RingAudioPeriod]; + + if( !(voice->vc_RingFixedPeriod) ) + voice->vc_RingAudioPeriod += voice->vc_PeriodSlidePeriod; + + voice->vc_RingAudioPeriod += voice->vc_PeriodPerfSlidePeriod + voice->vc_VibratoPeriod; + + if( voice->vc_RingAudioPeriod > 0x0d60 ) + voice->vc_RingAudioPeriod = 0x0d60; + + if( voice->vc_RingAudioPeriod < 0x0071 ) + voice->vc_RingAudioPeriod = 0x0071; + } + + // Normal period calculation + voice->vc_AudioPeriod = voice->vc_InstrPeriod; + + if( !(voice->vc_FixedNote) ) + { + if( voice->vc_OverrideTranspose != 1000 ) // 1.5 + voice->vc_AudioPeriod += voice->vc_OverrideTranspose + voice->vc_TrackPeriod - 1; + else + voice->vc_AudioPeriod += voice->vc_Transpose + voice->vc_TrackPeriod - 1; + } + + if( voice->vc_AudioPeriod > 5*12 ) + voice->vc_AudioPeriod = 5*12; + + if( voice->vc_AudioPeriod < 0 ) + voice->vc_AudioPeriod = 0; + + voice->vc_AudioPeriod = period_tab[voice->vc_AudioPeriod]; + + if( !(voice->vc_FixedNote) ) + voice->vc_AudioPeriod += voice->vc_PeriodSlidePeriod; + + voice->vc_AudioPeriod += voice->vc_PeriodPerfSlidePeriod + voice->vc_VibratoPeriod; + + if( voice->vc_AudioPeriod > 0x0d60 ) + voice->vc_AudioPeriod = 0x0d60; + + if( voice->vc_AudioPeriod < 0x0071 ) + voice->vc_AudioPeriod = 0x0071; + + voice->vc_AudioVolume = (((((((voice->vc_ADSRVolume >> 8) * voice->vc_NoteMaxVolume) >> 6) * voice->vc_PerfSubVolume) >> 6) * voice->vc_TrackMasterVolume) >> 6); +} + +void hvl_set_audio( struct hvl_voice *voice, float64 freqf ) +{ + if( voice->vc_TrackOn == 0 ) + { + voice->vc_VoiceVolume = 0; + return; + } + + voice->vc_VoiceVolume = voice->vc_AudioVolume; + + if( voice->vc_PlantPeriod ) + { + float64 freq2; + uint32 idelta; + + voice->vc_PlantPeriod = 0; + voice->vc_VoicePeriod = voice->vc_AudioPeriod; + + freq2 = Period2Freq( voice->vc_AudioPeriod ); + idelta = (uint32)(freqf / freq2 * 65536.f); + + if( idelta == 0 ) idelta = 1; + voice->vc_Delta = idelta; + } + + if( voice->vc_NewWaveform ) + { + int8 *src; + + src = voice->vc_AudioSource; + + if( voice->vc_Waveform == 4-1 ) + { + memcpy( &voice->vc_VoiceBuffer[0], src, 0x280 ); + } else { + uint32 i, WaveLoops; + + WaveLoops = (1 << (5 - voice->vc_WaveLength)) * 5; + + for( i=0; ivc_VoiceBuffer[i*4*(1<vc_WaveLength)], src, 4*(1<vc_WaveLength) ); + } + + voice->vc_VoiceBuffer[0x280] = voice->vc_VoiceBuffer[0]; + voice->vc_MixSource = voice->vc_VoiceBuffer; + } + + /* Ring Modulation */ + if( voice->vc_RingPlantPeriod ) + { + float64 freq2; + uint32 idelta; + + voice->vc_RingPlantPeriod = 0; + freq2 = Period2Freq( voice->vc_RingAudioPeriod ); + idelta = (uint32)(freqf / freq2 * 65536.f); + + if( idelta == 0 ) idelta = 1; + voice->vc_RingDelta = idelta; + } + + if( voice->vc_RingNewWaveform ) + { + int8 *src; + uint32 i, WaveLoops; + + src = voice->vc_RingAudioSource; + + WaveLoops = (1 << (5 - voice->vc_WaveLength)) * 5; + + for( i=0; ivc_RingVoiceBuffer[i*4*(1<vc_WaveLength)], src, 4*(1<vc_WaveLength) ); + + voice->vc_RingVoiceBuffer[0x280] = voice->vc_RingVoiceBuffer[0]; + voice->vc_RingMixSource = voice->vc_RingVoiceBuffer; + } +} + +void hvl_play_irq( struct hvl_tune *ht ) +{ + uint32 i; + + if( ht->ht_StepWaitFrames <= 0 ) + { + if( ht->ht_GetNewPosition ) + { + int32 nextpos = (ht->ht_PosNr+1==ht->ht_PositionNr)?0:(ht->ht_PosNr+1); + + for( i=0; iht_Channels; i++ ) + { + ht->ht_Voices[i].vc_Track = ht->ht_Positions[ht->ht_PosNr].pos_Track[i]; + ht->ht_Voices[i].vc_Transpose = ht->ht_Positions[ht->ht_PosNr].pos_Transpose[i]; + ht->ht_Voices[i].vc_NextTrack = ht->ht_Positions[nextpos].pos_Track[i]; + ht->ht_Voices[i].vc_NextTranspose = ht->ht_Positions[nextpos].pos_Transpose[i]; + } + ht->ht_GetNewPosition = 0; + } + + for( i=0; iht_Channels; i++ ) + hvl_process_step( ht, &ht->ht_Voices[i] ); + + ht->ht_StepWaitFrames = ht->ht_Tempo; + } + + for( i=0; iht_Channels; i++ ) + hvl_process_frame( ht, &ht->ht_Voices[i] ); + + ht->ht_PlayingTime++; + if( ht->ht_Tempo > 0 && --ht->ht_StepWaitFrames <= 0 ) + { + if( !ht->ht_PatternBreak ) + { + ht->ht_NoteNr++; + if( ht->ht_NoteNr >= ht->ht_TrackLength ) + { + ht->ht_PosJump = ht->ht_PosNr+1; + ht->ht_PosJumpNote = 0; + ht->ht_PatternBreak = 1; + } + } + + if( ht->ht_PatternBreak ) + { + ht->ht_PatternBreak = 0; + ht->ht_PosNr = ht->ht_PosJump; + ht->ht_NoteNr = ht->ht_PosJumpNote; + if( ht->ht_PosNr == ht->ht_PositionNr ) + { + ht->ht_SongEndReached = 1; + ht->ht_PosNr = ht->ht_Restart; + } + ht->ht_PosJumpNote = 0; + ht->ht_PosJump = 0; + + ht->ht_GetNewPosition = 1; + } + } + + for( i=0; iht_Channels; i++ ) + hvl_set_audio( &ht->ht_Voices[i], ht->ht_Frequency ); +} + +void hvl_mixchunk( struct hvl_tune *ht, uint32 samples, int8 *buf1, int8 *buf2, int32 bufmod ) +{ + int8 *src[MAX_CHANNELS]; + int8 *rsrc[MAX_CHANNELS]; + uint32 delta[MAX_CHANNELS]; + uint32 rdelta[MAX_CHANNELS]; + int32 vol[MAX_CHANNELS]; + uint32 pos[MAX_CHANNELS]; + uint32 rpos[MAX_CHANNELS]; + uint32 cnt; + int32 panl[MAX_CHANNELS]; + int32 panr[MAX_CHANNELS]; +// uint32 vu[MAX_CHANNELS]; + int32 last_amp[MAX_CHANNELS][2]; + uint32 last_clock[MAX_CHANNELS][2]; + uint32 clock, rclock, next_clock, current_clock, target_clock; + int32 j, blip_deltal, blip_deltar, last_ampl, last_ampr; + uint32 i, chans, loops; + + chans = ht->ht_Channels; + for( i=0; iht_Voices[i].vc_Delta; + vol[i] = ht->ht_Voices[i].vc_VoiceVolume; + pos[i] = ht->ht_Voices[i].vc_SamplePos; + src[i] = ht->ht_Voices[i].vc_MixSource; + panl[i] = ht->ht_Voices[i].vc_PanMultLeft; + panr[i] = ht->ht_Voices[i].vc_PanMultRight; + + /* Ring Modulation */ + rdelta[i]= ht->ht_Voices[i].vc_RingDelta; + rpos[i] = ht->ht_Voices[i].vc_RingSamplePos; + rsrc[i] = ht->ht_Voices[i].vc_RingMixSource; + + last_amp[i][0] = ht->ht_Voices[i].vc_LastAmp[0]; + last_amp[i][1] = ht->ht_Voices[i].vc_LastAmp[1]; + last_clock[i][0] = ht->ht_Voices[i].vc_LastClock[0]; + last_clock[i][1] = ht->ht_Voices[i].vc_LastClock[1]; + +// vu[i] = 0; + } + + do + { + loops = samples; + if (loops > 256) loops = 256; + + samples -= loops; + + target_clock = loops << 16; + + // Inner loop + for( i=0; i>7; + if( rclock < next_clock ) + { + rclock += rdelta[i]; + rpos[i] = (rpos[i] + 1) % 0x280; + } + } + j *= vol[i]; + +// if( abs( j ) > vu[i] ) vu[i] = abs( j ); + + blip_deltal = ((j * panl[i]) >> 7) - last_ampl; + blip_deltar = ((j * panr[i]) >> 7) - last_ampr; + last_ampl += blip_deltal; + last_ampr += blip_deltar; + if( blip_deltal ) hvl_blip_add_delta( ht->ht_BlipBuffers[0], current_clock, blip_deltal ); + if( blip_deltar ) hvl_blip_add_delta( ht->ht_BlipBuffers[1], current_clock, blip_deltar ); + + current_clock = next_clock; + } + clock -= target_clock; + if( rsrc[i] ) rclock -= target_clock; + last_clock[i][0] = clock; + last_clock[i][1] = rclock; + last_amp[i][0] = last_ampl; + last_amp[i][1] = last_ampr; + } + + hvl_blip_end_frame( ht->ht_BlipBuffers[0], target_clock ); + hvl_blip_end_frame( ht->ht_BlipBuffers[1], target_clock ); + + hvl_blip_read_samples( ht->ht_BlipBuffers[0], (int*)buf1, loops, ht->ht_mixgain ); + hvl_blip_read_samples( ht->ht_BlipBuffers[1], (int*)buf2, loops, ht->ht_mixgain ); + + buf1 += bufmod * loops; + buf2 += bufmod * loops; + } while( samples > 0 ); + + for( i=0; iht_Voices[i].vc_SamplePos = pos[i]; + ht->ht_Voices[i].vc_RingSamplePos = rpos[i]; + ht->ht_Voices[i].vc_LastAmp[0] = last_amp[i][0]; + ht->ht_Voices[i].vc_LastAmp[1] = last_amp[i][1]; + ht->ht_Voices[i].vc_LastClock[0] = last_clock[i][0]; + ht->ht_Voices[i].vc_LastClock[1] = last_clock[i][1]; +// ht->ht_Voices[i].vc_VUMeter = vu[i]; + } +} + +void hvl_DecodeFrame( struct hvl_tune *ht, int8 *buf1, int8 *buf2, int32 bufmod ) +{ + uint32 samples, loops; + + samples = ht->ht_Frequency/50/ht->ht_SpeedMultiplier; + loops = ht->ht_SpeedMultiplier; + + do + { + hvl_play_irq( ht ); + hvl_mixchunk( ht, samples, buf1, buf2, bufmod ); + buf1 += samples * bufmod; + buf2 += samples * bufmod; + loops--; + } while( loops ); +} diff --git a/Frameworks/HivelyPlayer/HivelyPlayer/hvl_replay.h b/Frameworks/HivelyPlayer/HivelyPlayer/hvl_replay.h new file mode 100644 index 000000000..148c9e0a8 --- /dev/null +++ b/Frameworks/HivelyPlayer/HivelyPlayer/hvl_replay.h @@ -0,0 +1,239 @@ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "blip_buf.h" + +#include + +typedef int8_t int8; +typedef uint8_t uint8; +typedef int16_t int16; +typedef uint16_t uint16; +typedef int32_t int32; +typedef uint32_t uint32; +typedef double float64; +typedef char TEXT; +typedef signed char BOOL; + +#define TRUE 1 +#define FALSE 0 + +// Woohoo! +#define MAX_CHANNELS 16 + +#define Period2Freq(period) (3546897.f / (period)) + +struct hvl_envelope +{ + int16 aFrames, aVolume; + int16 dFrames, dVolume; + int16 sFrames; + int16 rFrames, rVolume; + int16 pad; +}; + +struct hvl_plsentry +{ + uint8 ple_Note; + uint8 ple_Waveform; + int16 ple_Fixed; + int8 ple_FX[2]; + int8 ple_FXParam[2]; +}; + +struct hvl_plist +{ + int16 pls_Speed; + int16 pls_Length; + struct hvl_plsentry *pls_Entries; +}; + +struct hvl_instrument +{ + TEXT ins_Name[128]; + uint8 ins_Volume; + uint8 ins_WaveLength; + uint8 ins_FilterLowerLimit; + uint8 ins_FilterUpperLimit; + uint8 ins_FilterSpeed; + uint8 ins_SquareLowerLimit; + uint8 ins_SquareUpperLimit; + uint8 ins_SquareSpeed; + uint8 ins_VibratoDelay; + uint8 ins_VibratoSpeed; + uint8 ins_VibratoDepth; + uint8 ins_HardCutRelease; + uint8 ins_HardCutReleaseFrames; + struct hvl_envelope ins_Envelope; + struct hvl_plist ins_PList; +}; + +struct hvl_position +{ + uint8 pos_Track[MAX_CHANNELS]; + int8 pos_Transpose[MAX_CHANNELS]; +}; + +struct hvl_step +{ + uint8 stp_Note; + uint8 stp_Instrument; + uint8 stp_FX; + uint8 stp_FXParam; + uint8 stp_FXb; + uint8 stp_FXbParam; +}; + +struct hvl_voice +{ + int16 vc_Track; + int16 vc_NextTrack; + int16 vc_Transpose; + int16 vc_NextTranspose; + int16 vc_OverrideTranspose; // 1.5 + int32 vc_ADSRVolume; + struct hvl_envelope vc_ADSR; + struct hvl_instrument *vc_Instrument; + uint32 vc_SamplePos; + uint32 vc_Delta; + uint16 vc_InstrPeriod; + uint16 vc_TrackPeriod; + uint16 vc_VibratoPeriod; + uint16 vc_WaveLength; + int16 vc_NoteMaxVolume; + uint16 vc_PerfSubVolume; + uint8 vc_NewWaveform; + uint8 vc_Waveform; + uint8 vc_PlantPeriod; + uint8 vc_VoiceVolume; + uint8 vc_PlantSquare; + uint8 vc_IgnoreSquare; + uint8 vc_FixedNote; + int16 vc_VolumeSlideUp; + int16 vc_VolumeSlideDown; + int16 vc_HardCut; + uint8 vc_HardCutRelease; + int16 vc_HardCutReleaseF; + uint8 vc_PeriodSlideOn; + int16 vc_PeriodSlideSpeed; + int16 vc_PeriodSlidePeriod; + int16 vc_PeriodSlideLimit; + int16 vc_PeriodSlideWithLimit; + int16 vc_PeriodPerfSlideSpeed; + int16 vc_PeriodPerfSlidePeriod; + uint8 vc_PeriodPerfSlideOn; + int16 vc_VibratoDelay; + int16 vc_VibratoSpeed; + int16 vc_VibratoCurrent; + int16 vc_VibratoDepth; + int16 vc_SquareOn; + int16 vc_SquareInit; + int16 vc_SquareWait; + int16 vc_SquareLowerLimit; + int16 vc_SquareUpperLimit; + int16 vc_SquarePos; + int16 vc_SquareSign; + int16 vc_SquareSlidingIn; + int16 vc_SquareReverse; + uint8 vc_FilterOn; + uint8 vc_FilterInit; + int16 vc_FilterWait; + int16 vc_FilterSpeed; + int16 vc_FilterUpperLimit; + int16 vc_FilterLowerLimit; + int16 vc_FilterPos; + int16 vc_FilterSign; + int16 vc_FilterSlidingIn; + int16 vc_IgnoreFilter; + int16 vc_PerfCurrent; + int16 vc_PerfSpeed; + int16 vc_PerfWait; + struct hvl_plist *vc_PerfList; + int8 *vc_AudioPointer; + int8 *vc_AudioSource; + uint8 vc_NoteDelayOn; + uint8 vc_NoteCutOn; + int16 vc_NoteDelayWait; + int16 vc_NoteCutWait; + int16 vc_AudioPeriod; + int16 vc_AudioVolume; + int32 vc_WNRandom; + int8 *vc_MixSource; + int8 vc_SquareTempBuffer[0x80]; + int8 vc_VoiceBuffer[0x282*4]; + uint8 vc_VoiceNum; + uint8 vc_TrackMasterVolume; + uint8 vc_TrackOn; + int16 vc_VoicePeriod; + uint32 vc_Pan; + uint32 vc_SetPan; // New for 1.4 + uint32 vc_PanMultLeft; + uint32 vc_PanMultRight; + uint32 vc_RingSamplePos; + uint32 vc_RingDelta; + int8 *vc_RingMixSource; + uint8 vc_RingPlantPeriod; + int16 vc_RingInstrPeriod; + int16 vc_RingBasePeriod; + int16 vc_RingAudioPeriod; + int8 *vc_RingAudioSource; + uint8 vc_RingNewWaveform; + uint8 vc_RingWaveform; + uint8 vc_RingFixedPeriod; + int8 vc_RingVoiceBuffer[0x282*4]; + int32 vc_LastAmp[2]; + uint32 vc_LastClock[2]; +}; + +struct hvl_tune +{ + TEXT ht_Name[128]; + uint16 ht_SongNum; + uint32 ht_Frequency; + float64 ht_FreqF; + int8 *ht_WaveformTab[MAX_CHANNELS]; + uint16 ht_Restart; + uint16 ht_PositionNr; + uint8 ht_SpeedMultiplier; + uint8 ht_TrackLength; + uint8 ht_TrackNr; + uint8 ht_InstrumentNr; + uint8 ht_SubsongNr; + uint16 ht_PosJump; + uint32 ht_PlayingTime; + int16 ht_Tempo; + int16 ht_PosNr; + int16 ht_StepWaitFrames; + int16 ht_NoteNr; + uint16 ht_PosJumpNote; + uint8 ht_GetNewPosition; + uint8 ht_PatternBreak; + uint8 ht_SongEndReached; + uint8 ht_Stereo; + uint16 *ht_Subsongs; + uint16 ht_Channels; + struct hvl_position *ht_Positions; + struct hvl_step ht_Tracks[256][64]; + struct hvl_instrument *ht_Instruments; + struct hvl_voice ht_Voices[MAX_CHANNELS]; + hvl_blip_t *ht_BlipBuffers[2]; + int32 ht_defstereo; + int32 ht_defpanleft; + int32 ht_defpanright; + int32 ht_mixgain; + uint8 ht_Version; +}; + +void hvl_DecodeFrame( struct hvl_tune *ht, int8 *buf1, int8 *buf2, int32 bufmod ); +void hvl_InitReplayer( void ); +BOOL hvl_InitSubsong( struct hvl_tune *ht, uint32 nr ); +struct hvl_tune *hvl_LoadTune( const uint8 *buf, uint32 buflen, uint32 freq, uint32 defstereo ); +void hvl_FreeTune( struct hvl_tune *ht ); + +void hvl_play_irq( struct hvl_tune *ht ); + +#ifdef __cplusplus +} +#endif diff --git a/Plugins/Hively/Hively.xcodeproj/project.pbxproj b/Plugins/Hively/Hively.xcodeproj/project.pbxproj new file mode 100644 index 000000000..599828fd1 --- /dev/null +++ b/Plugins/Hively/Hively.xcodeproj/project.pbxproj @@ -0,0 +1,378 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 836FB5311820538700B3AD2D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 836FB5301820538700B3AD2D /* Cocoa.framework */; }; + 836FB53B1820538700B3AD2D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 836FB5391820538700B3AD2D /* InfoPlist.strings */; }; + 836FB5971820554E00B3AD2D /* HivelyPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 836FB58A182053D800B3AD2D /* HivelyPlayer.framework */; }; + 836FB5991820556100B3AD2D /* HivelyPlayer.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836FB58A182053D800B3AD2D /* HivelyPlayer.framework */; }; + 836FB5A01820556F00B3AD2D /* HVLDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 836FB59B1820556F00B3AD2D /* HVLDecoder.m */; }; + 836FB5A11820556F00B3AD2D /* HVLMetadataReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 836FB59D1820556F00B3AD2D /* HVLMetadataReader.m */; }; + 836FB5A21820556F00B3AD2D /* HVLContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 836FB59F1820556F00B3AD2D /* HVLContainer.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 836FB589182053D800B3AD2D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 836FB584182053D700B3AD2D /* HivelyPlayer.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 836FB556182053D700B3AD2D; + remoteInfo = HivelyPlayer; + }; + 836FB5951820554300B3AD2D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 836FB584182053D700B3AD2D /* HivelyPlayer.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 836FB555182053D700B3AD2D; + remoteInfo = HivelyPlayer; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 836FB5981820555500B3AD2D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 836FB5991820556100B3AD2D /* HivelyPlayer.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 836FB52D1820538700B3AD2D /* Hively.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Hively.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + 836FB5301820538700B3AD2D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 836FB5331820538700B3AD2D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 836FB5341820538700B3AD2D /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 836FB5351820538700B3AD2D /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 836FB5381820538700B3AD2D /* Hively-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Hively-Info.plist"; sourceTree = ""; }; + 836FB53A1820538700B3AD2D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 836FB53C1820538700B3AD2D /* Hively-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Hively-Prefix.pch"; sourceTree = ""; }; + 836FB584182053D700B3AD2D /* HivelyPlayer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HivelyPlayer.xcodeproj; path = ../../Frameworks/HivelyPlayer/HivelyPlayer.xcodeproj; sourceTree = ""; }; + 836FB59A1820556F00B3AD2D /* HVLDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HVLDecoder.h; sourceTree = ""; }; + 836FB59B1820556F00B3AD2D /* HVLDecoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HVLDecoder.m; sourceTree = ""; }; + 836FB59C1820556F00B3AD2D /* HVLMetadataReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HVLMetadataReader.h; sourceTree = ""; }; + 836FB59D1820556F00B3AD2D /* HVLMetadataReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HVLMetadataReader.m; sourceTree = ""; }; + 836FB59E1820556F00B3AD2D /* HVLContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HVLContainer.h; sourceTree = ""; }; + 836FB59F1820556F00B3AD2D /* HVLContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HVLContainer.m; sourceTree = ""; }; + 836FB5A31820557E00B3AD2D /* Plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Plugin.h; path = ../../../Audio/Plugin.h; sourceTree = ""; }; + 836FB5A41820558900B3AD2D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../../Utils/Logging.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 836FB52A1820538700B3AD2D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 836FB5971820554E00B3AD2D /* HivelyPlayer.framework in Frameworks */, + 836FB5311820538700B3AD2D /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 836FB5241820538700B3AD2D = { + isa = PBXGroup; + children = ( + 836FB5361820538700B3AD2D /* Hively */, + 836FB52F1820538700B3AD2D /* Frameworks */, + 836FB52E1820538700B3AD2D /* Products */, + ); + sourceTree = ""; + }; + 836FB52E1820538700B3AD2D /* Products */ = { + isa = PBXGroup; + children = ( + 836FB52D1820538700B3AD2D /* Hively.bundle */, + ); + name = Products; + sourceTree = ""; + }; + 836FB52F1820538700B3AD2D /* Frameworks */ = { + isa = PBXGroup; + children = ( + 836FB5301820538700B3AD2D /* Cocoa.framework */, + 836FB5321820538700B3AD2D /* Other Frameworks */, + 836FB584182053D700B3AD2D /* HivelyPlayer.xcodeproj */, + ); + name = Frameworks; + sourceTree = ""; + }; + 836FB5321820538700B3AD2D /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 836FB5331820538700B3AD2D /* Foundation.framework */, + 836FB5341820538700B3AD2D /* CoreData.framework */, + 836FB5351820538700B3AD2D /* AppKit.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 836FB5361820538700B3AD2D /* Hively */ = { + isa = PBXGroup; + children = ( + 836FB5A41820558900B3AD2D /* Logging.h */, + 836FB5A31820557E00B3AD2D /* Plugin.h */, + 836FB59A1820556F00B3AD2D /* HVLDecoder.h */, + 836FB59B1820556F00B3AD2D /* HVLDecoder.m */, + 836FB59C1820556F00B3AD2D /* HVLMetadataReader.h */, + 836FB59D1820556F00B3AD2D /* HVLMetadataReader.m */, + 836FB59E1820556F00B3AD2D /* HVLContainer.h */, + 836FB59F1820556F00B3AD2D /* HVLContainer.m */, + 836FB5371820538700B3AD2D /* Supporting Files */, + ); + path = Hively; + sourceTree = ""; + }; + 836FB5371820538700B3AD2D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 836FB5381820538700B3AD2D /* Hively-Info.plist */, + 836FB5391820538700B3AD2D /* InfoPlist.strings */, + 836FB53C1820538700B3AD2D /* Hively-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 836FB585182053D700B3AD2D /* Products */ = { + isa = PBXGroup; + children = ( + 836FB58A182053D800B3AD2D /* HivelyPlayer.framework */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 836FB52C1820538700B3AD2D /* Hively */ = { + isa = PBXNativeTarget; + buildConfigurationList = 836FB53F1820538700B3AD2D /* Build configuration list for PBXNativeTarget "Hively" */; + buildPhases = ( + 836FB5291820538700B3AD2D /* Sources */, + 836FB52A1820538700B3AD2D /* Frameworks */, + 836FB52B1820538700B3AD2D /* Resources */, + 836FB5981820555500B3AD2D /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 836FB5961820554300B3AD2D /* PBXTargetDependency */, + ); + name = Hively; + productName = Hively; + productReference = 836FB52D1820538700B3AD2D /* Hively.bundle */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 836FB5251820538700B3AD2D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Christopher Snowhill"; + }; + buildConfigurationList = 836FB5281820538700B3AD2D /* Build configuration list for PBXProject "Hively" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 836FB5241820538700B3AD2D; + productRefGroup = 836FB52E1820538700B3AD2D /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 836FB585182053D700B3AD2D /* Products */; + ProjectRef = 836FB584182053D700B3AD2D /* HivelyPlayer.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 836FB52C1820538700B3AD2D /* Hively */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 836FB58A182053D800B3AD2D /* HivelyPlayer.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = HivelyPlayer.framework; + remoteRef = 836FB589182053D800B3AD2D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 836FB52B1820538700B3AD2D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 836FB53B1820538700B3AD2D /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 836FB5291820538700B3AD2D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 836FB5A11820556F00B3AD2D /* HVLMetadataReader.m in Sources */, + 836FB5A21820556F00B3AD2D /* HVLContainer.m in Sources */, + 836FB5A01820556F00B3AD2D /* HVLDecoder.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 836FB5961820554300B3AD2D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = HivelyPlayer; + targetProxy = 836FB5951820554300B3AD2D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 836FB5391820538700B3AD2D /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 836FB53A1820538700B3AD2D /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 836FB53D1820538700B3AD2D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = 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; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 836FB53E1820538700B3AD2D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = 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; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + }; + name = Release; + }; + 836FB5401820538700B3AD2D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Hively/Hively-Prefix.pch"; + INFOPLIST_FILE = "Hively/Hively-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 836FB5411820538700B3AD2D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Hively/Hively-Prefix.pch"; + INFOPLIST_FILE = "Hively/Hively-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 836FB5281820538700B3AD2D /* Build configuration list for PBXProject "Hively" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 836FB53D1820538700B3AD2D /* Debug */, + 836FB53E1820538700B3AD2D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 836FB53F1820538700B3AD2D /* Build configuration list for PBXNativeTarget "Hively" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 836FB5401820538700B3AD2D /* Debug */, + 836FB5411820538700B3AD2D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 836FB5251820538700B3AD2D /* Project object */; +} diff --git a/Plugins/Hively/Hively/HVLContainer.h b/Plugins/Hively/Hively/HVLContainer.h new file mode 100755 index 000000000..ec675fb41 --- /dev/null +++ b/Plugins/Hively/Hively/HVLContainer.h @@ -0,0 +1,17 @@ +// +// HVLContainer.h +// Hively +// +// Created by Christopher Snowhill on 10/29/13. +// Copyright 2013 __NoWork, Inc__. All rights reserved. +// + +#import + +#import "Plugin.h" + +@interface HVLContainer : NSObject { + +} + +@end diff --git a/Plugins/Hively/Hively/HVLContainer.m b/Plugins/Hively/Hively/HVLContainer.m new file mode 100755 index 000000000..592189011 --- /dev/null +++ b/Plugins/Hively/Hively/HVLContainer.m @@ -0,0 +1,68 @@ +// +// HVLContainer.m +// Hively +// +// Created by Christopher Snowhill on 10/29/13. +// Copyright 2013 __NoWork, Inc__. All rights reserved. +// + +#import "HVLContainer.h" +#import "HVLDecoder.h" + +#import "Logging.h" + +@implementation HVLContainer + ++ (NSArray *)fileTypes +{ + return [HVLDecoder fileTypes]; +} + ++ (NSArray *)mimeTypes +{ + return nil; +} + ++ (NSArray *)urlsForContainerURL:(NSURL *)url +{ + if ([url fragment]) { + // input url already has fragment defined - no need to expand further + return [NSMutableArray arrayWithObject:url]; + } + + id audioSourceClass = NSClassFromString(@"AudioSource"); + id source = [audioSourceClass audioSourceForURL:url]; + + if (![source open:url]) + return 0; + + if (![source seekable]) + return 0; + + [source seek:0 whence:SEEK_END]; + long size = [source tell]; + [source seek:0 whence:SEEK_SET]; + + void * data = malloc(size); + [source read:data amount:size]; + + struct hvl_tune * tune = hvl_LoadTune( data, size, 44100, 2 ); + free( data ); + if ( !tune ) + return nil; + + int subsongNr = tune->ht_SubsongNr; + + hvl_FreeTune( tune ); + + NSMutableArray *tracks = [NSMutableArray array]; + + for (int i = 0; i <= subsongNr; ++i) { + [tracks addObject:[NSURL URLWithString:[[url absoluteString] stringByAppendingFormat:@"#%i", i]]]; + } + + return tracks; +} + + +@end diff --git a/Plugins/Hively/Hively/HVLDecoder.h b/Plugins/Hively/Hively/HVLDecoder.h new file mode 100755 index 000000000..9aadde922 --- /dev/null +++ b/Plugins/Hively/Hively/HVLDecoder.h @@ -0,0 +1,26 @@ +// +// HVLDecoder.h +// Hively +// +// Created by Christopher Snowhill on 10/29/13. +// Copyright 2013 __NoWork, Inc__. All rights reserved. +// + +#import + +#import + +#import "Plugin.h" + +@interface HVLDecoder : NSObject { + struct hvl_tune *tune; + int32_t *buffer; + long trackNumber; + + long totalFrames; + long framesLength; + long framesFade; + long framesRead; + long framesInBuffer; +} +@end diff --git a/Plugins/Hively/Hively/HVLDecoder.m b/Plugins/Hively/Hively/HVLDecoder.m new file mode 100755 index 000000000..66a0305af --- /dev/null +++ b/Plugins/Hively/Hively/HVLDecoder.m @@ -0,0 +1,194 @@ +// +// HVLDecoder.m +// Hively +// +// Created by Christopher Snowhill on 10/29/13. +// Copyright 2013 __NoWork, Inc__. All rights reserved. +// + +#import "HVLDecoder.h" + +#import "Logging.h" + +@implementation HVLDecoder + +void oneTimeInit() +{ + static BOOL initialized = NO; + if (!initialized) + { + hvl_InitReplayer(); + initialized = YES; + } +} + ++ (void)initialize +{ + if ([self class] == [HVLDecoder class]) + oneTimeInit(); +} + +- (BOOL)open:(id)s +{ + [s seek:0 whence:SEEK_END]; + long size = [s tell]; + [s seek:0 whence:SEEK_SET]; + + void * data = malloc(size); + [s read:data amount:size]; + + tune = hvl_LoadTune( data, size, 44100, 2 ); + free( data ); + if ( !tune ) + return NO; + + unsigned long safety = 2 * 60 * 60 * 50 * tune->ht_SpeedMultiplier; + + NSURL * url = [s url]; + if ([[url fragment] length] == 0) + trackNumber = 0; + else + trackNumber = [[url fragment] intValue]; + + hvl_InitSubsong( tune, trackNumber ); + + unsigned long loops = 0; + + while ( loops < 2 && safety ) + { + while ( !tune->ht_SongEndReached && safety ) + { + hvl_play_irq( tune ); + --safety; + } + tune->ht_SongEndReached = 0; + ++loops; + } + + framesLength = tune->ht_PlayingTime * 44100 / (tune->ht_SpeedMultiplier * 50); + framesFade = 44100 * 8; + totalFrames = framesLength + framesFade; + + framesRead = 0; + framesInBuffer = 0; + + buffer = malloc( sizeof(int32_t) * (44100 / 50) * 2 ); + + hvl_InitSubsong( tune, trackNumber ); + + [self willChangeValueForKey:@"properties"]; + [self didChangeValueForKey:@"properties"]; + + return YES; +} + +- (NSDictionary *)properties +{ + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:0], @"bitrate", + [NSNumber numberWithFloat:44100], @"sampleRate", + [NSNumber numberWithDouble:totalFrames], @"totalFrames", + [NSNumber numberWithInt:32], @"bitsPerSample", //Samples are short + [NSNumber numberWithBool:YES], @"floatingPoint", + [NSNumber numberWithInt:2], @"channels", //output from gme_play is in stereo + [NSNumber numberWithBool:YES], @"seekable", + @"host", @"endian", + nil]; +} + +- (int)readAudio:(void *)buf frames:(UInt32)frames +{ + int total = 0; + while ( total < frames ) { + if ( framesInBuffer ) + { + float * outbuffer = (( float * ) buf) + total * 2; + int framesToCopy = frames - total; + if ( framesToCopy > framesInBuffer ) + framesToCopy = framesInBuffer; + for ( int i = 0; i < framesToCopy; ++i ) + { + outbuffer[ 0 ] = buffer[ i * 2 + 0 ] * (1.0f / 16777216.0f); + outbuffer[ 1 ] = buffer[ i * 2 + 1 ] * (1.0f / 16777216.0f); + outbuffer += 2; + } + framesInBuffer -= framesToCopy; + total += framesToCopy; + if (framesInBuffer) + { + memcpy(buffer, buffer + framesToCopy * 2, sizeof(int32_t) * framesInBuffer * 2); + break; + } + } + hvl_DecodeFrame( tune, buffer, buffer + 1, 8 ); + framesInBuffer = 44100 / 50; + } + + if ( framesRead + total > framesLength ) { + long fadeStart = (framesLength > framesRead) ? framesLength : framesRead; + long fadeEnd = (framesRead + total) > totalFrames ? totalFrames : (framesRead + total); + long fadePos; + + float * buff = ( float * ) buf; + + float fadeScale = (float)(totalFrames - fadeStart) / (float)framesFade; + float fadeStep = 1.0 / (float)framesFade; + for (fadePos = fadeStart; fadePos < fadeEnd; ++fadePos) { + buff[ 0 ] *= fadeScale; + buff[ 1 ] *= fadeScale; + buff += 2; + fadeScale -= fadeStep; + if (fadeScale <= 0.0) break; + } + total = fadePos - fadeStart; + } + + framesRead += total; + + return total; +} + +- (long)seek:(long)frame +{ + if (frame < framesRead) { + hvl_InitSubsong( tune, trackNumber ); + framesRead = 0; + } + + while (framesRead < frame) { + hvl_play_irq( tune ); + framesRead += 44100 / 50; + } + + return framesRead; +} + +- (void)close +{ + if ( tune ) { + hvl_FreeTune( tune ); + tune = NULL; + } + + if ( buffer ) { + free( buffer ); + buffer = NULL; + } +} + ++ (NSArray *)fileTypes +{ + return [NSArray arrayWithObjects:@"hvl", @"ahx", nil]; +} + ++ (NSArray *)mimeTypes +{ + return nil; +} + ++ (float)priority +{ + return 1.0; +} + +@end diff --git a/Plugins/Hively/Hively/HVLMetadataReader.h b/Plugins/Hively/Hively/HVLMetadataReader.h new file mode 100644 index 000000000..3552b6bca --- /dev/null +++ b/Plugins/Hively/Hively/HVLMetadataReader.h @@ -0,0 +1,17 @@ +// +// HVLMetadataReader.h +// Hively +// +// Created by Christopher Snowhill on 10/29/13. +// Copyright 2013 __NoWork, Inc__. All rights reserved. +// + +#import + +#import "Plugin.h" + +@interface HVLMetadataReader : NSObject { + +} + +@end diff --git a/Plugins/Hively/Hively/HVLMetadataReader.m b/Plugins/Hively/Hively/HVLMetadataReader.m new file mode 100644 index 000000000..10a532058 --- /dev/null +++ b/Plugins/Hively/Hively/HVLMetadataReader.m @@ -0,0 +1,60 @@ +// +// HVLMetadataReader.m +// Hively +// +// Created by Christopher Snowhill on 10/29/13. +// Copyright 2013 __NoWork, Inc__. All rights reserved. +// + +#import "HVLMetadataReader.h" +#import "HVLDecoder.h" + +#import "Logging.H" + +@implementation HVLMetadataReader + ++ (NSArray *)fileTypes +{ + return [HVLDecoder fileTypes]; +} + ++ (NSArray *)mimeTypes +{ + return [HVLDecoder mimeTypes]; +} + ++ (NSDictionary *)metadataForURL:(NSURL *)url +{ + id audioSourceClass = NSClassFromString(@"AudioSource"); + id source = [audioSourceClass audioSourceForURL:url]; + + if (![source open:url]) + return 0; + + if (![source seekable]) + return 0; + + [source seek:0 whence:SEEK_END]; + long size = [source tell]; + [source seek:0 whence:SEEK_SET]; + + void * data = malloc(size); + [source read:data amount:size]; + + struct hvl_tune * tune = hvl_LoadTune( data, size, 44100, 2 ); + free( data ); + if ( !tune ) + return nil; + + NSString *title = [[NSString stringWithUTF8String: tune->ht_Name] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + + hvl_FreeTune( tune ); + + if (title == nil) { + title = @""; + } + + return [NSDictionary dictionaryWithObject:title forKey:@"title"]; +} + +@end diff --git a/Plugins/Hively/Hively/Hively-Info.plist b/Plugins/Hively/Hively/Hively-Info.plist new file mode 100644 index 000000000..7947bb8de --- /dev/null +++ b/Plugins/Hively/Hively/Hively-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + net.kode54.hively + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2013 Christopher Snowhill. All rights reserved. + NSPrincipalClass + + + diff --git a/Plugins/Hively/Hively/Hively-Prefix.pch b/Plugins/Hively/Hively/Hively-Prefix.pch new file mode 100644 index 000000000..35d76409f --- /dev/null +++ b/Plugins/Hively/Hively/Hively-Prefix.pch @@ -0,0 +1,9 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#ifdef __OBJC__ + #import +#endif diff --git a/Plugins/Hively/Hively/en.lproj/InfoPlist.strings b/Plugins/Hively/Hively/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..477b28ff8 --- /dev/null +++ b/Plugins/Hively/Hively/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ +