Decoders: Implemented Organya decoder
Based on the C++11 code by Joel Yliluoma / bisqwit, which in turn is based on information from NX-Engine. I have also taken the liberty of bundling the required wavetable bank and PixTone drums. Contrary to the documentation provided with the code, my version of dou_1006.zip, as downloaded over a decade ago, had the wavetable bank at offset 635,816 bytes into the file, not 1,115,748 bytes. Possibly a difference of having applied the translation patch? My copy is the original version, so I had to use a real resource parser to locate the waveforms. The player will obey the configured sample rate, loop count, and fade time for synthesizers, and also obey Repeat One to play indefinitely. The code should be quite robust to minor abuses, though I can't imagine how well it would hold up to random bad files, other than playing outright garbage. Signed-off-by: Christopher Snowhill <kode54@gmail.com>main
parent
6023acc10e
commit
1c09694f1b
|
@ -105,6 +105,7 @@
|
|||
83229C9F283B0095004626A8 /* SpectrumWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83229C9D283B0095004626A8 /* SpectrumWindowController.m */; };
|
||||
83256B68286661FC0036D9C0 /* libmpg123.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83256B672866617F0036D9C0 /* libmpg123.0.dylib */; };
|
||||
83256B69286661FC0036D9C0 /* libmpg123.0.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83256B672866617F0036D9C0 /* libmpg123.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
8327DBA9293CAD2400CD0580 /* Organya.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8327DB94293C923500CD0580 /* Organya.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
832923AF279FAC400048201E /* Cog.q1.json in Resources */ = {isa = PBXBuildFile; fileRef = 832923AE279FAC400048201E /* Cog.q1.json */; };
|
||||
832CFC4F2851AA1A002AC26F /* NSView+Visibility.m in Sources */ = {isa = PBXBuildFile; fileRef = 832CFC4E2851AA1A002AC26F /* NSView+Visibility.m */; };
|
||||
832CFC562851AA8B002AC26F /* SpectrumViewCG.m in Sources */ = {isa = PBXBuildFile; fileRef = 832CFC552851AA8B002AC26F /* SpectrumViewCG.m */; };
|
||||
|
@ -404,6 +405,20 @@
|
|||
remoteGlobalIDString = 8314D6311A354DFE00EEE8E6;
|
||||
remoteInfo = sidplay;
|
||||
};
|
||||
8327DB93293C923500CD0580 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 8327DB8F293C923500CD0580 /* Organya.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 8327DB7D293C90E300CD0580;
|
||||
remoteInfo = Organya;
|
||||
};
|
||||
8327DBA7293CAD0A00CD0580 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 8327DB8F293C923500CD0580 /* Organya.xcodeproj */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 8327DB7C293C90E300CD0580;
|
||||
remoteInfo = Organya;
|
||||
};
|
||||
834068BC20E4E40200A01561 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 17C808C00C3BD1DD005707C4 /* WavPack.xcodeproj */;
|
||||
|
@ -689,6 +704,7 @@
|
|||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
8327DBA9293CAD2400CD0580 /* Organya.bundle in CopyFiles */,
|
||||
8372C93D27C7895300E250C9 /* MAD.bundle in CopyFiles */,
|
||||
83489C6B2782F78700BDCEA2 /* libvgmPlayer.bundle in CopyFiles */,
|
||||
834D794020E4EFEF00C4A5CC /* VorbisPlugin.bundle in CopyFiles */,
|
||||
|
@ -927,6 +943,7 @@
|
|||
83229C9C283B0095004626A8 /* SpectrumWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpectrumWindowController.h; sourceTree = "<group>"; };
|
||||
83229C9D283B0095004626A8 /* SpectrumWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SpectrumWindowController.m; sourceTree = "<group>"; };
|
||||
83256B672866617F0036D9C0 /* libmpg123.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libmpg123.0.dylib; path = ThirdParty/mpg123/lib/libmpg123.0.dylib; sourceTree = "<group>"; };
|
||||
8327DB8F293C923500CD0580 /* Organya.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Organya.xcodeproj; path = Plugins/Organya/Organya.xcodeproj; sourceTree = "<group>"; };
|
||||
832923AE279FAC400048201E /* Cog.q1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Cog.q1.json; sourceTree = "<group>"; };
|
||||
832CFC4E2851AA1A002AC26F /* NSView+Visibility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSView+Visibility.m"; sourceTree = "<group>"; };
|
||||
832CFC532851AA37002AC26F /* NSView+Visibility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSView+Visibility.h"; sourceTree = "<group>"; };
|
||||
|
@ -1363,6 +1380,7 @@
|
|||
17C8089E0C3BD1AB005707C4 /* Musepack.xcodeproj */,
|
||||
83E5EFAC1FFEF78100659F0F /* OpenMPT.xcodeproj */,
|
||||
8375B05117FFEA400092A79F /* OpusPlugin.xcodeproj */,
|
||||
8327DB8F293C923500CD0580 /* Organya.xcodeproj */,
|
||||
8E8D41C20CBB0DA000135C1B /* Pls.xcodeproj */,
|
||||
17C808A70C3BD1BA005707C4 /* Shorten.xcodeproj */,
|
||||
8314D63B1A354DFE00EEE8E6 /* sidplay.xcodeproj */,
|
||||
|
@ -1737,6 +1755,14 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8327DB90293C923500CD0580 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8327DB94293C923500CD0580 /* Organya.bundle */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
834068A720E4E40200A01561 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -2040,6 +2066,7 @@
|
|||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
8327DBA8293CAD0A00CD0580 /* PBXTargetDependency */,
|
||||
8372C93C27C7893100E250C9 /* PBXTargetDependency */,
|
||||
83489C6A2782F76900BDCEA2 /* PBXTargetDependency */,
|
||||
ED69CBC625BE32B40090B90D /* PBXTargetDependency */,
|
||||
|
@ -2208,6 +2235,10 @@
|
|||
ProductGroup = 830B62AF20E4EF89004A74B2 /* Products */;
|
||||
ProjectRef = 8375B05117FFEA400092A79F /* OpusPlugin.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 8327DB90293C923500CD0580 /* Products */;
|
||||
ProjectRef = 8327DB8F293C923500CD0580 /* Organya.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 8E8D41C30CBB0DA000135C1B /* Products */;
|
||||
ProjectRef = 8E8D41C20CBB0DA000135C1B /* Pls.xcodeproj */;
|
||||
|
@ -2365,6 +2396,13 @@
|
|||
remoteRef = 8314D6401A354DFF00EEE8E6 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
8327DB94293C923500CD0580 /* Organya.bundle */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
path = Organya.bundle;
|
||||
remoteRef = 8327DB93293C923500CD0580 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
834068BD20E4E40200A01561 /* WavPack.bundle */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
|
@ -2753,6 +2791,11 @@
|
|||
name = Preferences;
|
||||
targetProxy = 17F5623A0C3BD9280019975C /* PBXContainerItemProxy */;
|
||||
};
|
||||
8327DBA8293CAD0A00CD0580 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = Organya;
|
||||
targetProxy = 8327DBA7293CAD0A00CD0580 /* PBXContainerItemProxy */;
|
||||
};
|
||||
83489C6A2782F76900BDCEA2 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = "libvgmPlayer Plugin";
|
||||
|
|
|
@ -1884,6 +1884,24 @@
|
|||
<key>LSTypeIsPackage</key>
|
||||
<false/>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>org</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>vg.icns</string>
|
||||
<key>CFBundleTypeIconSystemGenerated</key>
|
||||
<integer>1</integer>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Organya File</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Default</string>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<false/>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
|
|
|
@ -0,0 +1,368 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 56;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
8327DB96293C926F00CD0580 /* OrganyaDecoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8327DB95293C926F00CD0580 /* OrganyaDecoder.mm */; };
|
||||
8327DBA0293CACCC00CD0580 /* fx98.pxt in Resources */ = {isa = PBXBuildFile; fileRef = 8327DB99293CACCC00CD0580 /* fx98.pxt */; };
|
||||
8327DBA1293CACCC00CD0580 /* fx9a.pxt in Resources */ = {isa = PBXBuildFile; fileRef = 8327DB9A293CACCC00CD0580 /* fx9a.pxt */; };
|
||||
8327DBA2293CACCC00CD0580 /* fx9b.pxt in Resources */ = {isa = PBXBuildFile; fileRef = 8327DB9B293CACCC00CD0580 /* fx9b.pxt */; };
|
||||
8327DBA3293CACCC00CD0580 /* fx96.pxt in Resources */ = {isa = PBXBuildFile; fileRef = 8327DB9C293CACCC00CD0580 /* fx96.pxt */; };
|
||||
8327DBA4293CACCC00CD0580 /* fx99.pxt in Resources */ = {isa = PBXBuildFile; fileRef = 8327DB9D293CACCC00CD0580 /* fx99.pxt */; };
|
||||
8327DBA5293CACCC00CD0580 /* wavetable.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8327DB9E293CACCC00CD0580 /* wavetable.dat */; };
|
||||
8327DBA6293CACCC00CD0580 /* fx97.pxt in Resources */ = {isa = PBXBuildFile; fileRef = 8327DB9F293CACCC00CD0580 /* fx97.pxt */; };
|
||||
8327DBAD293CAE3F00CD0580 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8327DBAC293CAE3F00CD0580 /* Cocoa.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
8327DB7D293C90E300CD0580 /* Organya.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Organya.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8327DB8B293C913100CD0580 /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
8327DB8C293C915500CD0580 /* Plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Plugin.h; path = ../../Audio/Plugin.h; sourceTree = "<group>"; };
|
||||
8327DB8D293C916400CD0580 /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
8327DB95293C926F00CD0580 /* OrganyaDecoder.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OrganyaDecoder.mm; sourceTree = "<group>"; };
|
||||
8327DB97293C92A300CD0580 /* OrganyaDecoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OrganyaDecoder.h; sourceTree = "<group>"; };
|
||||
8327DB99293CACCC00CD0580 /* fx98.pxt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fx98.pxt; sourceTree = "<group>"; };
|
||||
8327DB9A293CACCC00CD0580 /* fx9a.pxt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fx9a.pxt; sourceTree = "<group>"; };
|
||||
8327DB9B293CACCC00CD0580 /* fx9b.pxt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fx9b.pxt; sourceTree = "<group>"; };
|
||||
8327DB9C293CACCC00CD0580 /* fx96.pxt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fx96.pxt; sourceTree = "<group>"; };
|
||||
8327DB9D293CACCC00CD0580 /* fx99.pxt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fx99.pxt; sourceTree = "<group>"; };
|
||||
8327DB9E293CACCC00CD0580 /* wavetable.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = wavetable.dat; sourceTree = "<group>"; };
|
||||
8327DB9F293CACCC00CD0580 /* fx97.pxt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fx97.pxt; sourceTree = "<group>"; };
|
||||
8327DBAA293CADCE00CD0580 /* PlaylistController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaylistController.h; path = ../../Playlist/PlaylistController.h; sourceTree = "<group>"; };
|
||||
8327DBAC293CAE3F00CD0580 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
8327DB7A293C90E300CD0580 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8327DBAD293CAE3F00CD0580 /* Cocoa.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
8327DB74293C90E300CD0580 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8327DB98293CA88700CD0580 /* Resources */,
|
||||
8327DBAB293CAE3100CD0580 /* Frameworks */,
|
||||
8327DB8E293C917000CD0580 /* Source */,
|
||||
8327DB8A293C90F700CD0580 /* Headers */,
|
||||
8327DB7E293C90E300CD0580 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8327DB7E293C90E300CD0580 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8327DB7D293C90E300CD0580 /* Organya.bundle */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8327DB8A293C90F700CD0580 /* Headers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8327DB8B293C913100CD0580 /* AudioChunk.h */,
|
||||
8327DB8D293C916400CD0580 /* Logging.h */,
|
||||
8327DB97293C92A300CD0580 /* OrganyaDecoder.h */,
|
||||
8327DBAA293CADCE00CD0580 /* PlaylistController.h */,
|
||||
8327DB8C293C915500CD0580 /* Plugin.h */,
|
||||
);
|
||||
name = Headers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8327DB8E293C917000CD0580 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8327DB95293C926F00CD0580 /* OrganyaDecoder.mm */,
|
||||
);
|
||||
name = Source;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8327DB98293CA88700CD0580 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8327DB9A293CACCC00CD0580 /* fx9a.pxt */,
|
||||
8327DB9B293CACCC00CD0580 /* fx9b.pxt */,
|
||||
8327DB9C293CACCC00CD0580 /* fx96.pxt */,
|
||||
8327DB9F293CACCC00CD0580 /* fx97.pxt */,
|
||||
8327DB99293CACCC00CD0580 /* fx98.pxt */,
|
||||
8327DB9D293CACCC00CD0580 /* fx99.pxt */,
|
||||
8327DB9E293CACCC00CD0580 /* wavetable.dat */,
|
||||
);
|
||||
name = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8327DBAB293CAE3100CD0580 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8327DBAC293CAE3F00CD0580 /* Cocoa.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
8327DB7C293C90E300CD0580 /* Organya */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8327DB81293C90E300CD0580 /* Build configuration list for PBXNativeTarget "Organya" */;
|
||||
buildPhases = (
|
||||
8327DB79293C90E300CD0580 /* Sources */,
|
||||
8327DB7A293C90E300CD0580 /* Frameworks */,
|
||||
8327DB7B293C90E300CD0580 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Organya;
|
||||
productName = Organya;
|
||||
productReference = 8327DB7D293C90E300CD0580 /* Organya.bundle */;
|
||||
productType = "com.apple.product-type.bundle";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
8327DB75293C90E300CD0580 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastUpgradeCheck = 1410;
|
||||
TargetAttributes = {
|
||||
8327DB7C293C90E300CD0580 = {
|
||||
CreatedOnToolsVersion = 14.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 8327DB78293C90E300CD0580 /* Build configuration list for PBXProject "Organya" */;
|
||||
compatibilityVersion = "Xcode 14.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 8327DB74293C90E300CD0580;
|
||||
productRefGroup = 8327DB7E293C90E300CD0580 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
8327DB7C293C90E300CD0580 /* Organya */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
8327DB7B293C90E300CD0580 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8327DBA5293CACCC00CD0580 /* wavetable.dat in Resources */,
|
||||
8327DBA3293CACCC00CD0580 /* fx96.pxt in Resources */,
|
||||
8327DBA6293CACCC00CD0580 /* fx97.pxt in Resources */,
|
||||
8327DBA0293CACCC00CD0580 /* fx98.pxt in Resources */,
|
||||
8327DBA4293CACCC00CD0580 /* fx99.pxt in Resources */,
|
||||
8327DBA1293CACCC00CD0580 /* fx9a.pxt in Resources */,
|
||||
8327DBA2293CACCC00CD0580 /* fx9b.pxt in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
8327DB79293C90E300CD0580 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8327DB96293C926F00CD0580 /* OrganyaDecoder.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
8327DB7F293C90E300CD0580 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8327DB80293C90E300CD0580 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8327DB82293C90E300CD0580 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSPrincipalClass = "";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = co.losno.Organya;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
WRAPPER_EXTENSION = bundle;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8327DB83293C90E300CD0580 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSPrincipalClass = "";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = co.losno.Organya;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
WRAPPER_EXTENSION = bundle;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
8327DB78293C90E300CD0580 /* Build configuration list for PBXProject "Organya" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8327DB7F293C90E300CD0580 /* Debug */,
|
||||
8327DB80293C90E300CD0580 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8327DB81293C90E300CD0580 /* Build configuration list for PBXNativeTarget "Organya" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8327DB82293C90E300CD0580 /* Debug */,
|
||||
8327DB83293C90E300CD0580 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 8327DB75293C90E300CD0580 /* Project object */;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// OrganyaDecoder.h
|
||||
// Organya
|
||||
//
|
||||
// Created by Christopher Snowhill on 12/4/22.
|
||||
//
|
||||
|
||||
#ifndef OrganyaDecoder_h
|
||||
#define OrganyaDecoder_h
|
||||
|
||||
#import "Plugin.h"
|
||||
|
||||
namespace Organya {
|
||||
struct Song;
|
||||
}
|
||||
|
||||
@interface OrganyaDecoder : NSObject <CogDecoder> {
|
||||
Organya::Song *m_song;
|
||||
id<CogSource> source;
|
||||
long length, lengthWithFade;
|
||||
long samplesDiscard;
|
||||
|
||||
double sampleRate;
|
||||
|
||||
long renderedTotal;
|
||||
long loopedTotal;
|
||||
long loopsRemain;
|
||||
long fadeTotal;
|
||||
long fadeRemain;
|
||||
}
|
||||
|
||||
- (void)setSource:(id<CogSource>)s;
|
||||
- (id<CogSource>)source;
|
||||
- (void)cleanUp;
|
||||
@end
|
||||
|
||||
#endif /* OrganyaDecoder_h */
|
|
@ -0,0 +1,511 @@
|
|||
//
|
||||
// OrganyaDecoder.m
|
||||
// Organya
|
||||
//
|
||||
// Created by Christopher Snowhill on 12/4/22.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "OrganyaDecoder.h"
|
||||
|
||||
#import "AudioChunk.h"
|
||||
#import "PlaylistController.h"
|
||||
|
||||
#import <cstdio>
|
||||
#import <cstring>
|
||||
#import <cstdlib>
|
||||
#import <vector>
|
||||
#import <cmath>
|
||||
#import <map>
|
||||
|
||||
/* SIMPLE CAVE STORY MUSIC PLAYER (Organya) */
|
||||
/* Written by Joel Yliluoma -- http://iki.fi/bisqwit/ */
|
||||
/* NX-Engine source code was used as reference. */
|
||||
/* Cave Story and its music were written by Pixel ( 天谷 大輔 ) */
|
||||
|
||||
namespace Organya {
|
||||
|
||||
//========= PART 0 : INPUT/OUTPUT AND UTILITY ========//
|
||||
using std::fgetc;
|
||||
int fgetw(FILE* fp) { int a = fgetc(fp), b = fgetc(fp); return (b<<8) + a; }
|
||||
int fgetd(FILE* fp) { int a = fgetw(fp), b = fgetw(fp); return (b<<16) + a; }
|
||||
double fgetv(FILE* fp) // Load a numeric value from text file; one per line.
|
||||
{
|
||||
char Buf[4096], *p=Buf; Buf[4095]='\0';
|
||||
if(!std::fgets(Buf, sizeof(Buf)-1, fp)) return 0.0;
|
||||
// Ignore empty lines. If the line was empty, try next line.
|
||||
if(!Buf[0] || Buf[0]=='\r' || Buf[0]=='\n') return fgetv(fp);
|
||||
while(*p && *p++ != ':') {} // Skip until a colon character.
|
||||
return std::strtod(p, 0); // Parse the value and return it.
|
||||
}
|
||||
|
||||
int coggetc(id<CogSource> fp) {
|
||||
uint8_t value;
|
||||
if([fp read:&value amount:sizeof(value)] != sizeof(value)) {
|
||||
return -1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
int coggetw(id<CogSource> fp) { int a = coggetc(fp); int b = coggetc(fp); return (b<<8) + a; }
|
||||
int coggetd(id<CogSource> fp) { int a = coggetw(fp); int b = coggetw(fp); return (b<<16) + a; }
|
||||
|
||||
//========= PART 1 : SOUND EFFECT PLAYER (PXT) ========//
|
||||
|
||||
static signed char Waveforms[6][256];
|
||||
static void GenerateWaveforms(void) {
|
||||
/* Six simple waveforms are used as basis for the signal generators in PXT: */
|
||||
for(unsigned seed=0, i=0; i<256; ++i) {
|
||||
/* These waveforms are bit-exact with PixTone v1.0.3. */
|
||||
seed = (seed * 214013) + 2531011; // Linear congruential generator
|
||||
Waveforms[0][i] = 0x40 * std::sin(i * 3.1416 / 0x80); // Sine
|
||||
Waveforms[1][i] = ((0x40+i) & 0x80) ? 0x80-i : i; // Triangle
|
||||
Waveforms[2][i] = -0x40 + i/2; // Sawtooth up
|
||||
Waveforms[3][i] = 0x40 - i/2; // Sawtooth down
|
||||
Waveforms[4][i] = 0x40 - (i & 0x80); // Square
|
||||
Waveforms[5][i] = (signed char)(seed >> 16) / 2; // Pseudorandom
|
||||
}
|
||||
}
|
||||
|
||||
struct Pxt {
|
||||
struct Channel {
|
||||
bool enabled;
|
||||
int nsamples;
|
||||
|
||||
// Waveform generator
|
||||
struct Wave {
|
||||
const signed char* wave;
|
||||
double pitch;
|
||||
int level, offset;
|
||||
};
|
||||
Wave carrier; // The main signal to be generated.
|
||||
Wave frequency; // Modulator to the main signal.
|
||||
Wave amplitude; // Modulator to the main signal.
|
||||
|
||||
// Envelope generator (controls the overall amplitude)
|
||||
struct Env {
|
||||
int initial; // initial value (0-63)
|
||||
struct { int time, val; } p[3]; // time offset & value, three of them
|
||||
int Evaluate(int i) const { // Linearly interpolate between the key points:
|
||||
int prevval = initial, prevtime=0;
|
||||
int nextval = 0, nexttime=256;
|
||||
for(int j=2; j>=0; --j) if(i < p[j].time) { nexttime=p[j].time; nextval=p[j].val; }
|
||||
for(int j=0; j<=2; ++j) if(i >=p[j].time) { prevtime=p[j].time; prevval=p[j].val; }
|
||||
if(nexttime <= prevtime) return prevval;
|
||||
return (i-prevtime) * (nextval-prevval) / (nexttime-prevtime) + prevval;
|
||||
}
|
||||
} envelope;
|
||||
|
||||
// Synthesize the sound effect.
|
||||
std::vector<int> Synth() {
|
||||
if(!enabled) return {};
|
||||
std::vector<int> result(nsamples);
|
||||
|
||||
auto& c = carrier, &f = frequency, &a = amplitude;
|
||||
double mainpos = c.offset, maindelta = 256*c.pitch/nsamples;
|
||||
for(size_t i=0; i<result.size(); ++i) {
|
||||
auto s = [=](double p=1) { return 256*p*i/nsamples; };
|
||||
// Take sample from each of the three signal generators:
|
||||
int freqval = f.wave[0xFF & int(f.offset + s(f.pitch))] * f.level;
|
||||
int ampval = a.wave[0xFF & int(a.offset + s(a.pitch))] * a.level;
|
||||
int mainval = c.wave[0xFF & int(mainpos) ] * c.level;
|
||||
// Apply amplitude & envelope to the main signal level:
|
||||
result[i] = mainval * (ampval+4096) / 4096 * envelope.Evaluate(s()) / 4096;
|
||||
// Apply frequency modulation to maindelta:
|
||||
mainpos += maindelta * (1 + (freqval / (freqval<0 ? 8192. : 2048.)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} channels[4]; /* Four parallel FM-AM modulators with envelope generators. */
|
||||
|
||||
void Load(FILE* fp) { // Load PXT file from disk and initialize synthesizer.
|
||||
/* C++11 simplifies things by a great deal. */
|
||||
/* This function would be a lot more complex without it. */
|
||||
auto f = [=](){ return (int) fgetv(fp); };
|
||||
for(auto&c: channels)
|
||||
c = { f() != 0, f(), // enabled, length
|
||||
{ Waveforms[f()%6], fgetv(fp), f(), f() }, // carrier wave
|
||||
{ Waveforms[f()%6], fgetv(fp), f(), f() }, // frequency wave
|
||||
{ Waveforms[f()%6], fgetv(fp), f(), f() }, // amplitude wave
|
||||
{ f(), { {f(),f()}, {f(),f()}, {f(),f()} } } // envelope
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
//========= PART 2 : SONG PLAYER (ORG) ========//
|
||||
/* Note: Requires PXT synthesis for percussion (drums). */
|
||||
|
||||
static short WaveTable[100*256];
|
||||
static std::vector<short> DrumSamples[12];
|
||||
|
||||
void LoadWaveTable(void) {
|
||||
NSURL *url = [[NSBundle bundleWithIdentifier:@"co.losno.Organya"] URLForResource:@"wavetable" withExtension:@"dat"];
|
||||
if(!url) return;
|
||||
NSString *path = [url path];
|
||||
FILE* fp = std::fopen([path UTF8String], "rb");
|
||||
if(!fp) return;
|
||||
for(size_t a=0; a<100*256; ++a)
|
||||
WaveTable[a] = (signed char) fgetc(fp);
|
||||
std::fclose(fp);
|
||||
}
|
||||
|
||||
void LoadDrums(void) {
|
||||
GenerateWaveforms();
|
||||
/* List of PXT files containing these percussion instruments: */
|
||||
static const int patch[] = {0x96,0,0x97,0, 0x9a,0x98,0x99,0, 0x9b,0,0,0};
|
||||
for(unsigned drumno=0; drumno<12; ++drumno)
|
||||
{
|
||||
if(!patch[drumno]) continue; // Leave that non-existed drum file unloaded
|
||||
// Load the drum parameters
|
||||
char Buf[64] = {};
|
||||
std::snprintf(Buf, sizeof(Buf)-1, "fx%02x", patch[drumno]);
|
||||
NSURL *url = [[NSBundle bundleWithIdentifier:@"co.losno.Organya"] URLForResource:[NSString stringWithUTF8String:Buf] withExtension:@"pxt"];
|
||||
if(!url) continue;
|
||||
NSString *path = [url path];
|
||||
FILE* fp = std::fopen([path UTF8String], "rb");
|
||||
if(!fp) continue;
|
||||
Pxt d;
|
||||
d.Load(fp);
|
||||
std::fclose(fp);
|
||||
// Synthesize and mix the drum's component channels
|
||||
auto& sample = DrumSamples[drumno];
|
||||
for(auto& c: d.channels)
|
||||
{
|
||||
auto buf = c.Synth();
|
||||
if(buf.size() > sample.size()) sample.resize(buf.size());
|
||||
for(size_t a=0; a<buf.size(); ++a)
|
||||
sample[a] += buf[a];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Song {
|
||||
int ms_per_beat, samples_per_beat, loop_start, loop_end;
|
||||
int cur_beat, total_beats;
|
||||
int loop_count;
|
||||
struct Ins {
|
||||
int tuning, wave;
|
||||
bool pi; // true=all notes play for exactly 1024 samples.
|
||||
std::size_t n_events;
|
||||
|
||||
struct Event { int note, length, volume, panning; };
|
||||
std::map<int/*beat*/, Event> events;
|
||||
|
||||
// Volatile data, used & changed during playback:
|
||||
double phaseacc, phaseinc, cur_vol;
|
||||
int cur_pan, cur_length, cur_wavesize;
|
||||
const short* cur_wave;
|
||||
} ins[16];
|
||||
|
||||
BOOL Load(id<CogSource> fp) {
|
||||
[fp seek:0 whence:SEEK_SET];
|
||||
char Signature[6];
|
||||
if([fp read:Signature amount:sizeof(Signature)] != sizeof(Signature))
|
||||
return NO;
|
||||
if(memcmp(Signature, "Org-02", 6) != 0)
|
||||
return NO;
|
||||
// Load song parameters
|
||||
ms_per_beat = coggetw(fp);
|
||||
/*steps_per_bar =*/coggetc(fp); // irrelevant
|
||||
/*beats_per_step=*/coggetc(fp); // irrelevant
|
||||
loop_start = coggetd(fp);
|
||||
loop_end = coggetd(fp);
|
||||
// Load each instrument parameters (and initialize them)
|
||||
for(auto& i: ins)
|
||||
i = { coggetw(fp), coggetc(fp), coggetc(fp)!=0, (unsigned)coggetw(fp),
|
||||
{}, 0,0,0,0,0,0,0 };
|
||||
// Load events for each instrument
|
||||
for(auto& i: ins)
|
||||
{
|
||||
std::vector<std::pair<int,Ins::Event>> events( i.n_events );
|
||||
for(auto& n: events) n.first = coggetd(fp);
|
||||
for(auto& n: events) n.second.note = coggetc(fp);
|
||||
for(auto& n: events) n.second.length = coggetc(fp);
|
||||
for(auto& n: events) n.second.volume = coggetc(fp);
|
||||
for(auto& n: events) n.second.panning = coggetc(fp);
|
||||
i.events.insert(events.begin(), events.end());
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
void Reset(void) {
|
||||
cur_beat = 0;
|
||||
total_beats = 0;
|
||||
loop_count = 0;
|
||||
}
|
||||
|
||||
std::vector<float> Synth(double sampling_rate)
|
||||
{
|
||||
// Determine playback settings:
|
||||
double samples_per_millisecond = sampling_rate * 1e-3, master_volume = 4e-6;
|
||||
int samples_per_beat = ms_per_beat * samples_per_millisecond; // rounded.
|
||||
// Begin synthesis
|
||||
{
|
||||
if(cur_beat == loop_end) {
|
||||
cur_beat = loop_start;
|
||||
loop_count++;
|
||||
}
|
||||
// Synthesize this beat in stereo sound (two channels).
|
||||
std::vector<float> result( samples_per_beat * 2, 0.f );
|
||||
for(auto &i: ins)
|
||||
{
|
||||
// Check if there is an event for this beat
|
||||
auto j = i.events.find(cur_beat);
|
||||
if(j != i.events.end())
|
||||
{
|
||||
auto& event = j->second;
|
||||
if(event.volume != 255) i.cur_vol = event.volume * master_volume;
|
||||
if(event.panning != 255) i.cur_pan = event.panning;
|
||||
if(event.note != 255)
|
||||
{
|
||||
// Calculate the note's wave data sampling frequency (equal temperament)
|
||||
double freq = std::pow(2.0, (event.note + i.tuning/1000.0 + 155.376) / 12);
|
||||
// Note: 155.376 comes from:
|
||||
// 12*log(256*440)/log(2) - (4*12-3-1) So that note 4*12-3 plays at 440 Hz.
|
||||
// Note: Optimizes into
|
||||
// pow(2, (note+155.376 + tuning/1000.0) / 12.0)
|
||||
// 2^(155.376/12) * exp( (note + tuning/1000.0)*log(2)/12 )
|
||||
// i.e. 7901.988*exp(0.057762265*(note + tuning*1e-3))
|
||||
i.phaseinc = freq / sampling_rate;
|
||||
i.phaseacc = 0;
|
||||
// And determine the actual wave data to play
|
||||
i.cur_wave = &WaveTable[256 * (i.wave % 100)];
|
||||
i.cur_wavesize = 256;
|
||||
i.cur_length = i.pi ? 1024/i.phaseinc : (event.length * samples_per_beat);
|
||||
|
||||
if(&i >= &ins[8]) // Percussion is different
|
||||
{
|
||||
const auto& d = DrumSamples[i.wave % 12];
|
||||
i.phaseinc = event.note * (22050/32.5) / sampling_rate; // Linear frequency
|
||||
i.cur_wave = &d[0];
|
||||
i.cur_wavesize = (int) d.size();
|
||||
i.cur_length = d.size() / i.phaseinc;
|
||||
}
|
||||
// Ignore missing drum samples
|
||||
if(i.cur_wavesize <= 0) i.cur_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate wave data. Calculate left & right volumes...
|
||||
auto left = (i.cur_pan > 6 ? 12 - i.cur_pan : 6) * i.cur_vol;
|
||||
auto right = (i.cur_pan < 6 ? i.cur_pan : 6) * i.cur_vol;
|
||||
int n = samples_per_beat > i.cur_length ? i.cur_length : samples_per_beat;
|
||||
for(int p=0; p<n; ++p)
|
||||
{
|
||||
double pos = i.phaseacc;
|
||||
// Take a sample from the wave data.
|
||||
/* We could do simply this: */
|
||||
//int sample = i.cur_wave[ unsigned(pos) % i.cur_wavesize ];
|
||||
/* But since we have plenty of time, use neat Lanczos filtering. */
|
||||
/* This improves especially the low rumble noises substantially. */
|
||||
enum { radius = 2 };
|
||||
auto lanczos = [](double d) -> double
|
||||
{
|
||||
if(d == 0.) return 1.;
|
||||
if(std::fabs(d) > radius) return 0.;
|
||||
double dr = (d *= 3.14159265) / radius;
|
||||
return std::sin(d) * std::sin(dr) / (d*dr);
|
||||
};
|
||||
double scale = 1/i.phaseinc > 1 ? 1 : 1/i.phaseinc, density = 0, sample = 0;
|
||||
int min = -radius/scale + pos - 0.5;
|
||||
int max = radius/scale + pos + 0.5;
|
||||
for(int m=min; m<max; ++m) // Collect a weighted average.
|
||||
{
|
||||
double factor = lanczos( (m-pos+0.5) * scale );
|
||||
density += factor;
|
||||
sample += i.cur_wave[m<0 ? 0 : m%i.cur_wavesize] * factor;
|
||||
}
|
||||
if(density > 0.) sample /= density; // Normalize
|
||||
// Save audio in float32 format:
|
||||
result[p*2 + 0] += sample * left;
|
||||
result[p*2 + 1] += sample * right;
|
||||
i.phaseacc += i.phaseinc;
|
||||
}
|
||||
i.cur_length -= n;
|
||||
}
|
||||
|
||||
cur_beat++;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@implementation OrganyaDecoder
|
||||
|
||||
// Need this static initializer to create the static global tables that sidplayfp doesn't really lock access to
|
||||
+ (void)initialize {
|
||||
Organya::LoadWaveTable();
|
||||
Organya::LoadDrums();
|
||||
}
|
||||
|
||||
- (BOOL)open:(id<CogSource>)s {
|
||||
[self setSource:s];
|
||||
|
||||
sampleRate = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthSampleRate"] doubleValue];
|
||||
if(sampleRate < 8000.0) {
|
||||
sampleRate = 44100.0;
|
||||
} else if(sampleRate > 192000.0) {
|
||||
sampleRate = 192000.0;
|
||||
}
|
||||
|
||||
m_song = new Organya::Song;
|
||||
if(!m_song->Load(s)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
long loopCount = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultLoopCount"] intValue];
|
||||
double fadeTime = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue];
|
||||
if(fadeTime < 0.0) {
|
||||
fadeTime = 0.0;
|
||||
}
|
||||
|
||||
long beatsToEnd = m_song->loop_start + (m_song->loop_end - m_song->loop_start) * loopCount;
|
||||
double lengthOfSong = ((double)m_song->ms_per_beat * 1e-3) * (double)beatsToEnd;
|
||||
length = (int)ceil(lengthOfSong * sampleRate);
|
||||
lengthWithFade = (int)ceil((lengthOfSong + fadeTime) * sampleRate);
|
||||
|
||||
renderedTotal = 0.0;
|
||||
fadeTotal = fadeRemain = (int)ceil(sampleRate * fadeTime);
|
||||
|
||||
samplesDiscard = 0;
|
||||
|
||||
m_song->Reset();
|
||||
|
||||
[self willChangeValueForKey:@"properties"];
|
||||
[self didChangeValueForKey:@"properties"];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSDictionary *)properties {
|
||||
return @{ @"bitrate": @(0),
|
||||
@"sampleRate": @(sampleRate),
|
||||
@"totalFrames": @(lengthWithFade),
|
||||
@"bitsPerSample": @(32),
|
||||
@"floatingPoint": @(YES),
|
||||
@"channels": @(2),
|
||||
@"seekable": @(YES),
|
||||
@"endian": @"host",
|
||||
@"encoding": @"synthesized" };
|
||||
}
|
||||
|
||||
- (NSDictionary *)metadata {
|
||||
return @{};
|
||||
}
|
||||
|
||||
- (AudioChunk *)readAudio {
|
||||
int total = 0;
|
||||
|
||||
std::vector<float> samples = m_song->Synth(sampleRate);
|
||||
|
||||
int rendered = (int)(samples.size() / 2);
|
||||
|
||||
renderedTotal += rendered;
|
||||
|
||||
if(!IsRepeatOneSet() && renderedTotal >= length) {
|
||||
float *sampleBuf = &samples[0];
|
||||
long fadeEnd = fadeRemain - rendered;
|
||||
if(fadeEnd < 0)
|
||||
fadeEnd = 0;
|
||||
float fadePosf = (float)fadeRemain / (float)fadeTotal;
|
||||
const float fadeStep = 1.0f / (float)fadeTotal;
|
||||
for(long fadePos = fadeRemain; fadePos > fadeEnd; --fadePos, fadePosf -= fadeStep) {
|
||||
long offset = (fadeRemain - fadePos) * 2;
|
||||
sampleBuf[offset + 0] *= fadePosf;
|
||||
sampleBuf[offset + 1] *= fadePosf;
|
||||
}
|
||||
rendered = (int)(fadeRemain - fadeEnd);
|
||||
fadeRemain = fadeEnd;
|
||||
}
|
||||
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
|
||||
if(samplesDiscard) {
|
||||
[chunk assignSamples:&samples[samplesDiscard * 2] frameCount:rendered - samplesDiscard];
|
||||
samplesDiscard = 0;
|
||||
} else {
|
||||
[chunk assignSamples:&samples[0] frameCount:rendered];
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
long originalFrame = frame;
|
||||
|
||||
if(frame < renderedTotal) {
|
||||
m_song->Reset();
|
||||
renderedTotal = 0;
|
||||
fadeRemain = fadeTotal;
|
||||
}
|
||||
|
||||
long msPerLoop = (m_song->loop_end - m_song->loop_start) * m_song->ms_per_beat;
|
||||
long msIntro = m_song->loop_start * m_song->ms_per_beat;
|
||||
|
||||
long samplesPerBeat = (long)ceil(m_song->ms_per_beat * 1e-3 * sampleRate);
|
||||
long samplesPerLoop = (long)ceil(msPerLoop * 1e-3 * sampleRate);
|
||||
long samplesIntro = (long)ceil(msIntro * 1e-3 * sampleRate);
|
||||
|
||||
if(samplesPerLoop) {
|
||||
while (frame >= (samplesIntro + samplesPerLoop)) {
|
||||
frame -= samplesPerLoop;
|
||||
m_song->loop_count++;
|
||||
}
|
||||
}
|
||||
|
||||
long beatTarget = frame / samplesPerBeat;
|
||||
samplesDiscard = frame % samplesPerBeat;
|
||||
|
||||
m_song->cur_beat = (int) beatTarget;
|
||||
|
||||
return originalFrame;
|
||||
}
|
||||
|
||||
- (void)cleanUp {
|
||||
if(m_song) {
|
||||
delete m_song;
|
||||
m_song = NULL;
|
||||
}
|
||||
|
||||
source = nil;
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
[self cleanUp];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self close];
|
||||
}
|
||||
|
||||
- (void)setSource:(id<CogSource>)s {
|
||||
source = s;
|
||||
}
|
||||
|
||||
- (id<CogSource>)source {
|
||||
return source;
|
||||
}
|
||||
|
||||
+ (NSArray *)fileTypes {
|
||||
return @[@"org"];
|
||||
}
|
||||
|
||||
+ (NSArray *)mimeTypes {
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (float)priority {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
+ (NSArray *)fileTypeAssociations {
|
||||
return @[
|
||||
@[@"Organya File", @"vg.icns", @"org"],
|
||||
];
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,92 @@
|
|||
use :1
|
||||
size :5000
|
||||
main_model :0
|
||||
main_freq :16.00
|
||||
main_top :63
|
||||
main_offset :0
|
||||
pitch_model :3
|
||||
pitch_freq :1.00
|
||||
pitch_top :32
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :32
|
||||
volume_offset:0
|
||||
initialY:63
|
||||
ax :64
|
||||
ay :63
|
||||
bx :166
|
||||
by :35
|
||||
cx :255
|
||||
cy :0
|
||||
|
||||
use :1
|
||||
size :1000
|
||||
main_model :5
|
||||
main_freq :1.00
|
||||
main_top :16
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :1.00
|
||||
pitch_top :32
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :32
|
||||
volume_offset:0
|
||||
initialY:63
|
||||
ax :64
|
||||
ay :63
|
||||
bx :91
|
||||
by :28
|
||||
cx :255
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
{1,5000,0,16.00,63,0,3,1.00,32,0,0,0.00,32,0,63,64,63,166,35,255,0},
|
||||
{1,1000,5,1.00,16,0,0,1.00,32,0,0,0.00,32,0,63,64,63,91,28,255,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
|
@ -0,0 +1,92 @@
|
|||
use :1
|
||||
size :5000
|
||||
main_model :0
|
||||
main_freq :20.00
|
||||
main_top :30
|
||||
main_offset :0
|
||||
pitch_model :3
|
||||
pitch_freq :1.00
|
||||
pitch_top :44
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :32
|
||||
volume_offset:0
|
||||
initialY:63
|
||||
ax :64
|
||||
ay :63
|
||||
bx :111
|
||||
by :19
|
||||
cx :255
|
||||
cy :0
|
||||
|
||||
use :1
|
||||
size :10000
|
||||
main_model :5
|
||||
main_freq :14.00
|
||||
main_top :41
|
||||
main_offset :0
|
||||
pitch_model :5
|
||||
pitch_freq :3.00
|
||||
pitch_top :32
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :32
|
||||
volume_offset:0
|
||||
initialY:63
|
||||
ax :64
|
||||
ay :18
|
||||
bx :91
|
||||
by :12
|
||||
cx :255
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
{1,5000,0,20.00,30,0,3,1.00,44,0,0,0.00,32,0,63,64,63,111,19,255,0},
|
||||
{1,10000,5,14.00,41,0,5,3.00,32,0,0,0.00,32,0,63,64,18,91,12,255,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
|
@ -0,0 +1,92 @@
|
|||
use :1
|
||||
size :1000
|
||||
main_model :5
|
||||
main_freq :48.00
|
||||
main_top :30
|
||||
main_offset :0
|
||||
pitch_model :5
|
||||
pitch_freq :1.00
|
||||
pitch_top :32
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :32
|
||||
volume_offset:0
|
||||
initialY:63
|
||||
ax :64
|
||||
ay :63
|
||||
bx :166
|
||||
by :27
|
||||
cx :255
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
{1,1000,5,48.00,30,0,5,1.00,32,0,0,0.00,32,0,63,64,63,166,27,255,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
|
@ -0,0 +1,92 @@
|
|||
use :1
|
||||
size :10000
|
||||
main_model :5
|
||||
main_freq :48.00
|
||||
main_top :30
|
||||
main_offset :0
|
||||
pitch_model :5
|
||||
pitch_freq :1.00
|
||||
pitch_top :32
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :32
|
||||
volume_offset:0
|
||||
initialY:63
|
||||
ax :64
|
||||
ay :43
|
||||
bx :166
|
||||
by :41
|
||||
cx :255
|
||||
cy :7
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
{1,10000,5,48.00,30,0,5,1.00,32,0,0,0.00,32,0,63,64,43,166,41,255,7},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
|
@ -0,0 +1,92 @@
|
|||
use :1
|
||||
size :4000
|
||||
main_model :5
|
||||
main_freq :35.00
|
||||
main_top :30
|
||||
main_offset :0
|
||||
pitch_model :3
|
||||
pitch_freq :35.00
|
||||
pitch_top :32
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :32
|
||||
volume_offset:0
|
||||
initialY:63
|
||||
ax :53
|
||||
ay :21
|
||||
bx :166
|
||||
by :13
|
||||
cx :255
|
||||
cy :0
|
||||
|
||||
use :1
|
||||
size :10000
|
||||
main_model :1
|
||||
main_freq :63.00
|
||||
main_top :32
|
||||
main_offset :0
|
||||
pitch_model :3
|
||||
pitch_freq :1.00
|
||||
pitch_top :32
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :32
|
||||
volume_offset:0
|
||||
initialY:63
|
||||
ax :64
|
||||
ay :39
|
||||
bx :91
|
||||
by :20
|
||||
cx :255
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
{1,4000,5,35.00,30,0,3,35.00,32,0,0,0.00,32,0,63,53,21,166,13,255,0},
|
||||
{1,10000,1,63.00,32,0,3,1.00,32,0,0,0.00,32,0,63,64,39,91,20,255,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
|
@ -0,0 +1,92 @@
|
|||
use :1
|
||||
size :4000
|
||||
main_model :5
|
||||
main_freq :6.00
|
||||
main_top :32
|
||||
main_offset :0
|
||||
pitch_model :3
|
||||
pitch_freq :2.00
|
||||
pitch_top :32
|
||||
pitch_offset :0
|
||||
volume_model :3
|
||||
volume_freq :2.00
|
||||
volume_top :32
|
||||
volume_offset:0
|
||||
initialY:63
|
||||
ax :26
|
||||
ay :30
|
||||
bx :66
|
||||
by :29
|
||||
cx :255
|
||||
cy :0
|
||||
|
||||
use :1
|
||||
size :4000
|
||||
main_model :0
|
||||
main_freq :150.00
|
||||
main_top :32
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :32
|
||||
pitch_offset :0
|
||||
volume_model :3
|
||||
volume_freq :2.00
|
||||
volume_top :32
|
||||
volume_offset:0
|
||||
initialY:63
|
||||
ax :26
|
||||
ay :30
|
||||
bx :66
|
||||
by :29
|
||||
cx :255
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
use :0
|
||||
size :0
|
||||
main_model :0
|
||||
main_freq :0.00
|
||||
main_top :0
|
||||
main_offset :0
|
||||
pitch_model :0
|
||||
pitch_freq :0.00
|
||||
pitch_top :0
|
||||
pitch_offset :0
|
||||
volume_model :0
|
||||
volume_freq :0.00
|
||||
volume_top :0
|
||||
volume_offset:0
|
||||
initialY:0
|
||||
ax :0
|
||||
ay :0
|
||||
bx :0
|
||||
by :0
|
||||
cx :0
|
||||
cy :0
|
||||
|
||||
{1,4000,5,6.00,32,0,3,2.00,32,0,3,2.00,32,0,63,26,30,66,29,255,0},
|
||||
{1,4000,0,150.00,32,0,0,0.00,32,0,3,2.00,32,0,63,26,30,66,29,255,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0.00,0,0,0,0.00,0,0,0,0.00,0,0,0,0,0,0,0,0,0},
|
Binary file not shown.
Loading…
Reference in New Issue