Updated DUMB
This commit is contained in:
parent
d969f5a6a7
commit
17682d4397
256 changed files with 47317 additions and 35807 deletions
|
@ -350,9 +350,15 @@
|
|||
/* Begin PBXProject section */
|
||||
0867D690FE84028FC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
};
|
||||
buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "CogAudio" */;
|
||||
compatibilityVersion = "Xcode 3.0";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 0867D691FE84028FC02AAC07 /* CogAudio */;
|
||||
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
|
||||
projectDirPath = "";
|
||||
|
@ -405,6 +411,7 @@
|
|||
1DEB91AE08733DA50010E9CD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
|
@ -421,6 +428,7 @@
|
|||
INSTALL_PATH = "@executable_path/../Frameworks";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = CogAudio;
|
||||
SDKROOT = macosx10.6;
|
||||
WARNING_LDFLAGS = "";
|
||||
WRAPPER_EXTENSION = framework;
|
||||
ZERO_LINK = YES;
|
||||
|
@ -431,8 +439,8 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = (
|
||||
ppc,
|
||||
i386,
|
||||
ppc,
|
||||
);
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
|
@ -447,6 +455,7 @@
|
|||
INSTALL_PATH = "@executable_path/../Frameworks";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = CogAudio;
|
||||
SDKROOT = macosx10.6;
|
||||
WARNING_LDFLAGS = "";
|
||||
WRAPPER_EXTENSION = framework;
|
||||
};
|
||||
|
|
|
@ -87,7 +87,6 @@
|
|||
17A8F6860D6A7FCA0095DA13 /* repeat_none.png in Resources */ = {isa = PBXBuildFile; fileRef = 17A8F6830D6A7FCA0095DA13 /* repeat_none.png */; };
|
||||
17A8F6870D6A7FCA0095DA13 /* repeat_one.png in Resources */ = {isa = PBXBuildFile; fileRef = 17A8F6840D6A7FCA0095DA13 /* repeat_one.png */; };
|
||||
17A8F71A0D6A89730095DA13 /* repeat_album.png in Resources */ = {isa = PBXBuildFile; fileRef = 17A8F7190D6A89730095DA13 /* repeat_album.png */; };
|
||||
17B6FA7F0D48225300C3BEF1 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17BF2B270CDD77EB007E1295 /* Sparkle.framework */; };
|
||||
17B7CF5C0F5A05EE00A47027 /* pauseBadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 17B7CF590F5A05EE00A47027 /* pauseBadge.png */; };
|
||||
17B7CF5D0F5A05EE00A47027 /* playBadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 17B7CF5A0F5A05EE00A47027 /* playBadge.png */; };
|
||||
17B7CF5E0F5A05EE00A47027 /* stopBadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 17B7CF5B0F5A05EE00A47027 /* stopBadge.png */; };
|
||||
|
@ -97,7 +96,6 @@
|
|||
17BB5CFA0B8A86350009ACB1 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CF70B8A86350009ACB1 /* CoreAudio.framework */; };
|
||||
17BB5CFB0B8A86350009ACB1 /* CoreAudioKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CF80B8A86350009ACB1 /* CoreAudioKit.framework */; };
|
||||
17BB5EA60B8A87850009ACB1 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5EA50B8A87850009ACB1 /* IOKit.framework */; };
|
||||
17BF2B280CDD7802007E1295 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BF2B270CDD77EB007E1295 /* Sparkle.framework */; };
|
||||
17C809910C3BD201005707C4 /* WavPack.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C808C80C3BD1DD005707C4 /* WavPack.bundle */; };
|
||||
17C809920C3BD206005707C4 /* Vorbis.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C808BF0C3BD1D2005707C4 /* Vorbis.bundle */; };
|
||||
17C809930C3BD21D005707C4 /* TagLib.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C808B60C3BD1C5005707C4 /* TagLib.bundle */; };
|
||||
|
@ -193,20 +191,6 @@
|
|||
remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
|
||||
remoteInfo = "AudioOverload Plugin";
|
||||
};
|
||||
17BF2B260CDD77EB007E1295 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 17BF2B1F0CDD77EB007E1295 /* Sparkle.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
|
||||
remoteInfo = Sparkle;
|
||||
};
|
||||
17BF2B390CDD7827007E1295 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 17BF2B1F0CDD77EB007E1295 /* Sparkle.xcodeproj */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
|
||||
remoteInfo = Sparkle;
|
||||
};
|
||||
17C808780C3BD167005707C4 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 17C808710C3BD167005707C4 /* FileSource.xcodeproj */;
|
||||
|
@ -518,7 +502,6 @@
|
|||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
17B6FA7F0D48225300C3BEF1 /* Sparkle.framework in CopyFiles */,
|
||||
17F561400C3BD4F30019975C /* CogAudio.framework in CopyFiles */,
|
||||
170680840B950164006BA573 /* Growl.framework in CopyFiles */,
|
||||
);
|
||||
|
@ -661,7 +644,6 @@
|
|||
17BB5CF70B8A86350009ACB1 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = "<absolute>"; };
|
||||
17BB5CF80B8A86350009ACB1 /* CoreAudioKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudioKit.framework; path = /System/Library/Frameworks/CoreAudioKit.framework; sourceTree = "<absolute>"; };
|
||||
17BB5EA50B8A87850009ACB1 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
|
||||
17BF2B1F0CDD77EB007E1295 /* Sparkle.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Sparkle.xcodeproj; path = Frameworks/Sparkle/Sparkle.xcodeproj; sourceTree = "<group>"; };
|
||||
17C808660C3BD0F8005707C4 /* CoreAudio.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CoreAudio.xcodeproj; path = Plugins/CoreAudio/CoreAudio.xcodeproj; sourceTree = SOURCE_ROOT; };
|
||||
17C808710C3BD167005707C4 /* FileSource.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FileSource.xcodeproj; path = Plugins/FileSource/FileSource.xcodeproj; sourceTree = "<group>"; };
|
||||
17C8087A0C3BD173005707C4 /* Flac.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Flac.xcodeproj; path = Plugins/Flac/Flac.xcodeproj; sourceTree = "<group>"; };
|
||||
|
@ -778,7 +760,6 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
17BF2B280CDD7802007E1295 /* Sparkle.framework in Frameworks */,
|
||||
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
|
||||
8E6889240AAA403C00AD3950 /* Carbon.framework in Frameworks */,
|
||||
17BB5CED0B8A86010009ACB1 /* AudioToolbox.framework in Frameworks */,
|
||||
|
@ -826,7 +807,6 @@
|
|||
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
17BF2B1F0CDD77EB007E1295 /* Sparkle.xcodeproj */,
|
||||
17F5612A0C3BD4DC0019975C /* CogAudio.xcodeproj */,
|
||||
170680620B950158006BA573 /* Growl.framework */,
|
||||
8E6889230AAA403C00AD3950 /* Carbon.framework */,
|
||||
|
@ -1036,14 +1016,6 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
17BF2B200CDD77EB007E1295 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
17BF2B270CDD77EB007E1295 /* Sparkle.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
17C808720C3BD167005707C4 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1511,7 +1483,6 @@
|
|||
17F3BB8B0CBC566200864489 /* PBXTargetDependency */,
|
||||
17C8F44C0CBEDD37008D969D /* PBXTargetDependency */,
|
||||
17C8F7DA0CBEF3F9008D969D /* PBXTargetDependency */,
|
||||
17BF2B3A0CDD7827007E1295 /* PBXTargetDependency */,
|
||||
17643CBC0D5BD44900F0A9FE /* PBXTargetDependency */,
|
||||
17B7CF960F5A0A3700A47027 /* PBXTargetDependency */,
|
||||
);
|
||||
|
@ -1526,8 +1497,11 @@
|
|||
/* Begin PBXProject section */
|
||||
29B97313FDCFA39411CA2CEA /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
};
|
||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Cog" */;
|
||||
compatibilityVersion = "Xcode 3.0";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
English,
|
||||
|
@ -1610,10 +1584,6 @@
|
|||
ProductGroup = 17C808A80C3BD1BA005707C4 /* Products */;
|
||||
ProjectRef = 17C808A70C3BD1BA005707C4 /* Shorten.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 17BF2B200CDD77EB007E1295 /* Products */;
|
||||
ProjectRef = 17BF2B1F0CDD77EB007E1295 /* Sparkle.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 17C808B10C3BD1C5005707C4 /* Products */;
|
||||
ProjectRef = 17C808B00C3BD1C5005707C4 /* TagLib.xcodeproj */;
|
||||
|
@ -1646,13 +1616,6 @@
|
|||
remoteRef = 17B7CF7B0F5A09FD00A47027 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
17BF2B270CDD77EB007E1295 /* Sparkle.framework */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.framework;
|
||||
path = Sparkle.framework;
|
||||
remoteRef = 17BF2B260CDD77EB007E1295 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
17C808790C3BD167005707C4 /* FileSource.bundle */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
|
@ -1958,11 +1921,6 @@
|
|||
name = "AudioOverload Plugin";
|
||||
targetProxy = 17B7CF950F5A0A3700A47027 /* PBXContainerItemProxy */;
|
||||
};
|
||||
17BF2B3A0CDD7827007E1295 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = Sparkle;
|
||||
targetProxy = 17BF2B390CDD7827007E1295 /* PBXContainerItemProxy */;
|
||||
};
|
||||
17C8097E0C3BD1F5005707C4 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = Musepack;
|
||||
|
@ -2166,9 +2124,11 @@
|
|||
OTHER_LDFLAGS = (
|
||||
"-weak_framework",
|
||||
CogAudio,
|
||||
"-undefined",
|
||||
dynamic_lookup,
|
||||
);
|
||||
PRODUCT_NAME = Cog;
|
||||
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
|
||||
SDKROOT = macosx10.6;
|
||||
WRAPPER_EXTENSION = app;
|
||||
ZERO_LINK = NO;
|
||||
};
|
||||
|
@ -2202,9 +2162,11 @@
|
|||
OTHER_LDFLAGS = (
|
||||
"-weak_framework",
|
||||
CogAudio,
|
||||
"-undefined",
|
||||
dynamic_lookup,
|
||||
);
|
||||
PRODUCT_NAME = Cog;
|
||||
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
|
||||
SDKROOT = macosx10.6;
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Release;
|
||||
|
|
|
@ -441,9 +441,15 @@
|
|||
/* Begin PBXProject section */
|
||||
0867D690FE84028FC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
};
|
||||
buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "AudioOverload" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 0867D691FE84028FC02AAC07 /* AudioOverload */;
|
||||
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
|
||||
projectDirPath = "";
|
||||
|
@ -522,6 +528,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
|
@ -545,6 +552,7 @@
|
|||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "@loader_path/../Frameworks";
|
||||
PRODUCT_NAME = AudioOverload;
|
||||
SDKROOT = macosx10.6;
|
||||
USE_HEADERMAP = NO;
|
||||
WRAPPER_EXTENSION = framework;
|
||||
};
|
||||
|
@ -554,6 +562,10 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = (
|
||||
i386,
|
||||
ppc,
|
||||
);
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
|
@ -574,6 +586,7 @@
|
|||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "@loader_path/../Frameworks";
|
||||
PRODUCT_NAME = AudioOverload;
|
||||
SDKROOT = macosx10.6;
|
||||
USE_HEADERMAP = NO;
|
||||
WRAPPER_EXTENSION = framework;
|
||||
};
|
||||
|
@ -589,7 +602,7 @@
|
|||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = macosx10.5;
|
||||
SDKROOT = macosx10.6;
|
||||
SYMROOT = ../../build;
|
||||
};
|
||||
name = Debug;
|
||||
|
@ -602,7 +615,7 @@
|
|||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = macosx10.5;
|
||||
SDKROOT = macosx10.6;
|
||||
SYMROOT = ../../build;
|
||||
};
|
||||
name = Release;
|
||||
|
|
|
@ -540,7 +540,7 @@ static void *MAINThread(int samp2run)
|
|||
lastch=ch;
|
||||
// lastns=ns; // changemeback
|
||||
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
/* Begin PBXBuildFile section */
|
||||
17C8F63E0CBEE797008D969D /* dumb.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C8F60C0CBEE797008D969D /* dumb.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
17C8F63F0CBEE797008D969D /* dumb.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C8F60E0CBEE797008D969D /* dumb.h */; };
|
||||
17C8F6400CBEE797008D969D /* it.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C8F60F0CBEE797008D969D /* it.h */; };
|
||||
17C8F6400CBEE797008D969D /* it.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C8F60F0CBEE797008D969D /* it.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
17C8F6410CBEE797008D969D /* atexit.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F6120CBEE797008D969D /* atexit.c */; };
|
||||
17C8F6420CBEE797008D969D /* duhlen.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F6130CBEE797008D969D /* duhlen.c */; };
|
||||
17C8F6430CBEE797008D969D /* duhtag.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F6140CBEE797008D969D /* duhtag.c */; };
|
||||
|
@ -49,6 +49,61 @@
|
|||
17C8F6680CBEE797008D969D /* readxm.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F63B0CBEE797008D969D /* readxm.c */; };
|
||||
17C8F6690CBEE797008D969D /* readxm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F63C0CBEE797008D969D /* readxm2.c */; };
|
||||
17C8F66A0CBEE797008D969D /* xmeffect.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F63D0CBEE797008D969D /* xmeffect.c */; };
|
||||
8370B62617F60FE2001A4D7A /* barray.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B61E17F60FE2001A4D7A /* barray.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
8370B62817F60FE2001A4D7A /* dumbfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B62017F60FE2001A4D7A /* dumbfile.h */; };
|
||||
8370B62A17F60FE2001A4D7A /* lpc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B62217F60FE2001A4D7A /* lpc.h */; };
|
||||
8370B62B17F60FE2001A4D7A /* riff.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B62317F60FE2001A4D7A /* riff.h */; };
|
||||
8370B62C17F60FE2001A4D7A /* stack_alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B62417F60FE2001A4D7A /* stack_alloc.h */; };
|
||||
8370B62D17F60FE2001A4D7A /* tarray.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B62517F60FE2001A4D7A /* tarray.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
8370B63417F61001001A4D7A /* barray.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B62E17F61001001A4D7A /* barray.c */; };
|
||||
8370B63517F61001001A4D7A /* blip_buf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B62F17F61001001A4D7A /* blip_buf.c */; };
|
||||
8370B63617F61001001A4D7A /* lanczos_resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63017F61001001A4D7A /* lanczos_resampler.c */; };
|
||||
8370B63717F61001001A4D7A /* lpc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63117F61001001A4D7A /* lpc.c */; };
|
||||
8370B63817F61001001A4D7A /* riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63217F61001001A4D7A /* riff.c */; };
|
||||
8370B63917F61001001A4D7A /* tarray.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63317F61001001A4D7A /* tarray.c */; };
|
||||
8370B66317F61038001A4D7A /* load669.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63A17F61038001A4D7A /* load669.c */; };
|
||||
8370B66417F61038001A4D7A /* load6692.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63B17F61038001A4D7A /* load6692.c */; };
|
||||
8370B66517F61038001A4D7A /* loadamf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63C17F61038001A4D7A /* loadamf.c */; };
|
||||
8370B66617F61038001A4D7A /* loadamf2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63D17F61038001A4D7A /* loadamf2.c */; };
|
||||
8370B66717F61038001A4D7A /* loadany.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63E17F61038001A4D7A /* loadany.c */; };
|
||||
8370B66817F61038001A4D7A /* loadany2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63F17F61038001A4D7A /* loadany2.c */; };
|
||||
8370B66917F61038001A4D7A /* loadasy.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64017F61038001A4D7A /* loadasy.c */; };
|
||||
8370B66A17F61038001A4D7A /* loadasy2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64117F61038001A4D7A /* loadasy2.c */; };
|
||||
8370B66B17F61038001A4D7A /* loadmtm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64217F61038001A4D7A /* loadmtm.c */; };
|
||||
8370B66C17F61038001A4D7A /* loadmtm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64317F61038001A4D7A /* loadmtm2.c */; };
|
||||
8370B66D17F61038001A4D7A /* loadokt.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64417F61038001A4D7A /* loadokt.c */; };
|
||||
8370B66E17F61038001A4D7A /* loadokt2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64517F61038001A4D7A /* loadokt2.c */; };
|
||||
8370B66F17F61038001A4D7A /* loadoldpsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64617F61038001A4D7A /* loadoldpsm.c */; };
|
||||
8370B67017F61038001A4D7A /* loadoldpsm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64717F61038001A4D7A /* loadoldpsm2.c */; };
|
||||
8370B67117F61038001A4D7A /* loadpsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64817F61038001A4D7A /* loadpsm.c */; };
|
||||
8370B67217F61038001A4D7A /* loadpsm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64917F61038001A4D7A /* loadpsm2.c */; };
|
||||
8370B67317F61038001A4D7A /* loadptm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64A17F61038001A4D7A /* loadptm.c */; };
|
||||
8370B67417F61038001A4D7A /* loadptm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64B17F61038001A4D7A /* loadptm2.c */; };
|
||||
8370B67517F61038001A4D7A /* loadriff.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64C17F61038001A4D7A /* loadriff.c */; };
|
||||
8370B67617F61038001A4D7A /* loadriff2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64D17F61038001A4D7A /* loadriff2.c */; };
|
||||
8370B67717F61038001A4D7A /* loadstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64E17F61038001A4D7A /* loadstm.c */; };
|
||||
8370B67817F61038001A4D7A /* loadstm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B64F17F61038001A4D7A /* loadstm2.c */; };
|
||||
8370B67917F61038001A4D7A /* ptmeffect.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65017F61038001A4D7A /* ptmeffect.c */; };
|
||||
8370B67A17F61038001A4D7A /* read669.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65117F61038001A4D7A /* read669.c */; };
|
||||
8370B67B17F61038001A4D7A /* read6692.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65217F61038001A4D7A /* read6692.c */; };
|
||||
8370B67C17F61038001A4D7A /* readam.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65317F61038001A4D7A /* readam.c */; };
|
||||
8370B67D17F61038001A4D7A /* readamf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65417F61038001A4D7A /* readamf.c */; };
|
||||
8370B67E17F61038001A4D7A /* readamf2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65517F61038001A4D7A /* readamf2.c */; };
|
||||
8370B67F17F61038001A4D7A /* readany.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65617F61038001A4D7A /* readany.c */; };
|
||||
8370B68017F61038001A4D7A /* readany2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65717F61038001A4D7A /* readany2.c */; };
|
||||
8370B68117F61038001A4D7A /* readasy.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65817F61038001A4D7A /* readasy.c */; };
|
||||
8370B68217F61038001A4D7A /* readdsmf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65917F61038001A4D7A /* readdsmf.c */; };
|
||||
8370B68317F61038001A4D7A /* readmtm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65A17F61038001A4D7A /* readmtm.c */; };
|
||||
8370B68417F61038001A4D7A /* readokt.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65B17F61038001A4D7A /* readokt.c */; };
|
||||
8370B68517F61038001A4D7A /* readokt2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65C17F61038001A4D7A /* readokt2.c */; };
|
||||
8370B68617F61038001A4D7A /* readoldpsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65D17F61038001A4D7A /* readoldpsm.c */; };
|
||||
8370B68717F61038001A4D7A /* readpsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65E17F61038001A4D7A /* readpsm.c */; };
|
||||
8370B68817F61038001A4D7A /* readptm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B65F17F61038001A4D7A /* readptm.c */; };
|
||||
8370B68917F61038001A4D7A /* readriff.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B66017F61038001A4D7A /* readriff.c */; };
|
||||
8370B68A17F61038001A4D7A /* readstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B66117F61038001A4D7A /* readstm.c */; };
|
||||
8370B68B17F61038001A4D7A /* readstm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B66217F61038001A4D7A /* readstm2.c */; };
|
||||
8370B7E917F62A40001A4D7A /* blip_buf.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B7E717F62A40001A4D7A /* blip_buf.h */; };
|
||||
8370B7EA17F62A40001A4D7A /* lanczos_resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B7E817F62A40001A4D7A /* lanczos_resampler.h */; };
|
||||
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
|
||||
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
@ -103,6 +158,61 @@
|
|||
17C8F63B0CBEE797008D969D /* readxm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = readxm.c; sourceTree = "<group>"; };
|
||||
17C8F63C0CBEE797008D969D /* readxm2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = readxm2.c; sourceTree = "<group>"; };
|
||||
17C8F63D0CBEE797008D969D /* xmeffect.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xmeffect.c; sourceTree = "<group>"; };
|
||||
8370B61E17F60FE2001A4D7A /* barray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = barray.h; sourceTree = "<group>"; };
|
||||
8370B62017F60FE2001A4D7A /* dumbfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dumbfile.h; sourceTree = "<group>"; };
|
||||
8370B62217F60FE2001A4D7A /* lpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lpc.h; sourceTree = "<group>"; };
|
||||
8370B62317F60FE2001A4D7A /* riff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = riff.h; sourceTree = "<group>"; };
|
||||
8370B62417F60FE2001A4D7A /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = "<group>"; };
|
||||
8370B62517F60FE2001A4D7A /* tarray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tarray.h; sourceTree = "<group>"; };
|
||||
8370B62E17F61001001A4D7A /* barray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = barray.c; sourceTree = "<group>"; };
|
||||
8370B62F17F61001001A4D7A /* blip_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blip_buf.c; sourceTree = "<group>"; };
|
||||
8370B63017F61001001A4D7A /* lanczos_resampler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lanczos_resampler.c; sourceTree = "<group>"; };
|
||||
8370B63117F61001001A4D7A /* lpc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpc.c; sourceTree = "<group>"; };
|
||||
8370B63217F61001001A4D7A /* riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = riff.c; sourceTree = "<group>"; };
|
||||
8370B63317F61001001A4D7A /* tarray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tarray.c; sourceTree = "<group>"; };
|
||||
8370B63A17F61038001A4D7A /* load669.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = load669.c; sourceTree = "<group>"; };
|
||||
8370B63B17F61038001A4D7A /* load6692.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = load6692.c; sourceTree = "<group>"; };
|
||||
8370B63C17F61038001A4D7A /* loadamf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadamf.c; sourceTree = "<group>"; };
|
||||
8370B63D17F61038001A4D7A /* loadamf2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadamf2.c; sourceTree = "<group>"; };
|
||||
8370B63E17F61038001A4D7A /* loadany.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadany.c; sourceTree = "<group>"; };
|
||||
8370B63F17F61038001A4D7A /* loadany2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadany2.c; sourceTree = "<group>"; };
|
||||
8370B64017F61038001A4D7A /* loadasy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadasy.c; sourceTree = "<group>"; };
|
||||
8370B64117F61038001A4D7A /* loadasy2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadasy2.c; sourceTree = "<group>"; };
|
||||
8370B64217F61038001A4D7A /* loadmtm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadmtm.c; sourceTree = "<group>"; };
|
||||
8370B64317F61038001A4D7A /* loadmtm2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadmtm2.c; sourceTree = "<group>"; };
|
||||
8370B64417F61038001A4D7A /* loadokt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadokt.c; sourceTree = "<group>"; };
|
||||
8370B64517F61038001A4D7A /* loadokt2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadokt2.c; sourceTree = "<group>"; };
|
||||
8370B64617F61038001A4D7A /* loadoldpsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadoldpsm.c; sourceTree = "<group>"; };
|
||||
8370B64717F61038001A4D7A /* loadoldpsm2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadoldpsm2.c; sourceTree = "<group>"; };
|
||||
8370B64817F61038001A4D7A /* loadpsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadpsm.c; sourceTree = "<group>"; };
|
||||
8370B64917F61038001A4D7A /* loadpsm2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadpsm2.c; sourceTree = "<group>"; };
|
||||
8370B64A17F61038001A4D7A /* loadptm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadptm.c; sourceTree = "<group>"; };
|
||||
8370B64B17F61038001A4D7A /* loadptm2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadptm2.c; sourceTree = "<group>"; };
|
||||
8370B64C17F61038001A4D7A /* loadriff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadriff.c; sourceTree = "<group>"; };
|
||||
8370B64D17F61038001A4D7A /* loadriff2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadriff2.c; sourceTree = "<group>"; };
|
||||
8370B64E17F61038001A4D7A /* loadstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadstm.c; sourceTree = "<group>"; };
|
||||
8370B64F17F61038001A4D7A /* loadstm2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadstm2.c; sourceTree = "<group>"; };
|
||||
8370B65017F61038001A4D7A /* ptmeffect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ptmeffect.c; sourceTree = "<group>"; };
|
||||
8370B65117F61038001A4D7A /* read669.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = read669.c; sourceTree = "<group>"; };
|
||||
8370B65217F61038001A4D7A /* read6692.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = read6692.c; sourceTree = "<group>"; };
|
||||
8370B65317F61038001A4D7A /* readam.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readam.c; sourceTree = "<group>"; };
|
||||
8370B65417F61038001A4D7A /* readamf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readamf.c; sourceTree = "<group>"; };
|
||||
8370B65517F61038001A4D7A /* readamf2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readamf2.c; sourceTree = "<group>"; };
|
||||
8370B65617F61038001A4D7A /* readany.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readany.c; sourceTree = "<group>"; };
|
||||
8370B65717F61038001A4D7A /* readany2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readany2.c; sourceTree = "<group>"; };
|
||||
8370B65817F61038001A4D7A /* readasy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readasy.c; sourceTree = "<group>"; };
|
||||
8370B65917F61038001A4D7A /* readdsmf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readdsmf.c; sourceTree = "<group>"; };
|
||||
8370B65A17F61038001A4D7A /* readmtm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readmtm.c; sourceTree = "<group>"; };
|
||||
8370B65B17F61038001A4D7A /* readokt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readokt.c; sourceTree = "<group>"; };
|
||||
8370B65C17F61038001A4D7A /* readokt2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readokt2.c; sourceTree = "<group>"; };
|
||||
8370B65D17F61038001A4D7A /* readoldpsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readoldpsm.c; sourceTree = "<group>"; };
|
||||
8370B65E17F61038001A4D7A /* readpsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readpsm.c; sourceTree = "<group>"; };
|
||||
8370B65F17F61038001A4D7A /* readptm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readptm.c; sourceTree = "<group>"; };
|
||||
8370B66017F61038001A4D7A /* readriff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readriff.c; sourceTree = "<group>"; };
|
||||
8370B66117F61038001A4D7A /* readstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readstm.c; sourceTree = "<group>"; };
|
||||
8370B66217F61038001A4D7A /* readstm2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readstm2.c; sourceTree = "<group>"; };
|
||||
8370B7E717F62A40001A4D7A /* blip_buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blip_buf.h; sourceTree = "<group>"; };
|
||||
8370B7E817F62A40001A4D7A /* lanczos_resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lanczos_resampler.h; sourceTree = "<group>"; };
|
||||
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
8DC2EF5B0486A6940098B216 /* Dumb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Dumb.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
|
||||
|
@ -197,6 +307,14 @@
|
|||
17C8F60D0CBEE797008D969D /* internal */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8370B7E717F62A40001A4D7A /* blip_buf.h */,
|
||||
8370B7E817F62A40001A4D7A /* lanczos_resampler.h */,
|
||||
8370B61E17F60FE2001A4D7A /* barray.h */,
|
||||
8370B62017F60FE2001A4D7A /* dumbfile.h */,
|
||||
8370B62217F60FE2001A4D7A /* lpc.h */,
|
||||
8370B62317F60FE2001A4D7A /* riff.h */,
|
||||
8370B62417F60FE2001A4D7A /* stack_alloc.h */,
|
||||
8370B62517F60FE2001A4D7A /* tarray.h */,
|
||||
17C8F60E0CBEE797008D969D /* dumb.h */,
|
||||
17C8F60F0CBEE797008D969D /* it.h */,
|
||||
);
|
||||
|
@ -236,6 +354,12 @@
|
|||
17C8F61E0CBEE797008D969D /* helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8370B62E17F61001001A4D7A /* barray.c */,
|
||||
8370B62F17F61001001A4D7A /* blip_buf.c */,
|
||||
8370B63017F61001001A4D7A /* lanczos_resampler.c */,
|
||||
8370B63117F61001001A4D7A /* lpc.c */,
|
||||
8370B63217F61001001A4D7A /* riff.c */,
|
||||
8370B63317F61001001A4D7A /* tarray.c */,
|
||||
17C8F61F0CBEE797008D969D /* clickrem.c */,
|
||||
17C8F6200CBEE797008D969D /* memfile.c */,
|
||||
17C8F6210CBEE797008D969D /* resamp2.inc */,
|
||||
|
@ -252,6 +376,47 @@
|
|||
17C8F6280CBEE797008D969D /* it */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8370B63A17F61038001A4D7A /* load669.c */,
|
||||
8370B63B17F61038001A4D7A /* load6692.c */,
|
||||
8370B63C17F61038001A4D7A /* loadamf.c */,
|
||||
8370B63D17F61038001A4D7A /* loadamf2.c */,
|
||||
8370B63E17F61038001A4D7A /* loadany.c */,
|
||||
8370B63F17F61038001A4D7A /* loadany2.c */,
|
||||
8370B64017F61038001A4D7A /* loadasy.c */,
|
||||
8370B64117F61038001A4D7A /* loadasy2.c */,
|
||||
8370B64217F61038001A4D7A /* loadmtm.c */,
|
||||
8370B64317F61038001A4D7A /* loadmtm2.c */,
|
||||
8370B64417F61038001A4D7A /* loadokt.c */,
|
||||
8370B64517F61038001A4D7A /* loadokt2.c */,
|
||||
8370B64617F61038001A4D7A /* loadoldpsm.c */,
|
||||
8370B64717F61038001A4D7A /* loadoldpsm2.c */,
|
||||
8370B64817F61038001A4D7A /* loadpsm.c */,
|
||||
8370B64917F61038001A4D7A /* loadpsm2.c */,
|
||||
8370B64A17F61038001A4D7A /* loadptm.c */,
|
||||
8370B64B17F61038001A4D7A /* loadptm2.c */,
|
||||
8370B64C17F61038001A4D7A /* loadriff.c */,
|
||||
8370B64D17F61038001A4D7A /* loadriff2.c */,
|
||||
8370B64E17F61038001A4D7A /* loadstm.c */,
|
||||
8370B64F17F61038001A4D7A /* loadstm2.c */,
|
||||
8370B65017F61038001A4D7A /* ptmeffect.c */,
|
||||
8370B65117F61038001A4D7A /* read669.c */,
|
||||
8370B65217F61038001A4D7A /* read6692.c */,
|
||||
8370B65317F61038001A4D7A /* readam.c */,
|
||||
8370B65417F61038001A4D7A /* readamf.c */,
|
||||
8370B65517F61038001A4D7A /* readamf2.c */,
|
||||
8370B65617F61038001A4D7A /* readany.c */,
|
||||
8370B65717F61038001A4D7A /* readany2.c */,
|
||||
8370B65817F61038001A4D7A /* readasy.c */,
|
||||
8370B65917F61038001A4D7A /* readdsmf.c */,
|
||||
8370B65A17F61038001A4D7A /* readmtm.c */,
|
||||
8370B65B17F61038001A4D7A /* readokt.c */,
|
||||
8370B65C17F61038001A4D7A /* readokt2.c */,
|
||||
8370B65D17F61038001A4D7A /* readoldpsm.c */,
|
||||
8370B65E17F61038001A4D7A /* readpsm.c */,
|
||||
8370B65F17F61038001A4D7A /* readptm.c */,
|
||||
8370B66017F61038001A4D7A /* readriff.c */,
|
||||
8370B66117F61038001A4D7A /* readstm.c */,
|
||||
8370B66217F61038001A4D7A /* readstm2.c */,
|
||||
17C8F6290CBEE797008D969D /* itload.c */,
|
||||
17C8F62A0CBEE797008D969D /* itload2.c */,
|
||||
17C8F62B0CBEE797008D969D /* itmisc.c */,
|
||||
|
@ -285,8 +450,16 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
17C8F63E0CBEE797008D969D /* dumb.h in Headers */,
|
||||
17C8F63F0CBEE797008D969D /* dumb.h in Headers */,
|
||||
17C8F6400CBEE797008D969D /* it.h in Headers */,
|
||||
8370B62D17F60FE2001A4D7A /* tarray.h in Headers */,
|
||||
8370B62617F60FE2001A4D7A /* barray.h in Headers */,
|
||||
8370B7EA17F62A40001A4D7A /* lanczos_resampler.h in Headers */,
|
||||
8370B7E917F62A40001A4D7A /* blip_buf.h in Headers */,
|
||||
17C8F63F0CBEE797008D969D /* dumb.h in Headers */,
|
||||
8370B62B17F60FE2001A4D7A /* riff.h in Headers */,
|
||||
8370B62A17F60FE2001A4D7A /* lpc.h in Headers */,
|
||||
8370B62817F60FE2001A4D7A /* dumbfile.h in Headers */,
|
||||
8370B62C17F60FE2001A4D7A /* stack_alloc.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -317,9 +490,15 @@
|
|||
/* Begin PBXProject section */
|
||||
0867D690FE84028FC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
};
|
||||
buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Dumb" */;
|
||||
compatibilityVersion = "Xcode 2.4";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 0867D691FE84028FC02AAC07 /* Dumb */;
|
||||
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
|
||||
projectDirPath = "";
|
||||
|
@ -346,29 +525,56 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8370B66D17F61038001A4D7A /* loadokt.c in Sources */,
|
||||
8370B68A17F61038001A4D7A /* readstm.c in Sources */,
|
||||
17C8F6410CBEE797008D969D /* atexit.c in Sources */,
|
||||
17C8F6420CBEE797008D969D /* duhlen.c in Sources */,
|
||||
8370B66E17F61038001A4D7A /* loadokt2.c in Sources */,
|
||||
8370B63817F61001001A4D7A /* riff.c in Sources */,
|
||||
17C8F6430CBEE797008D969D /* duhtag.c in Sources */,
|
||||
8370B63517F61001001A4D7A /* blip_buf.c in Sources */,
|
||||
8370B68117F61038001A4D7A /* readasy.c in Sources */,
|
||||
8370B67217F61038001A4D7A /* loadpsm2.c in Sources */,
|
||||
17C8F6440CBEE797008D969D /* dumbfile.c in Sources */,
|
||||
8370B68317F61038001A4D7A /* readmtm.c in Sources */,
|
||||
17C8F6450CBEE797008D969D /* loadduh.c in Sources */,
|
||||
8370B67D17F61038001A4D7A /* readamf.c in Sources */,
|
||||
8370B63717F61001001A4D7A /* lpc.c in Sources */,
|
||||
17C8F6460CBEE797008D969D /* makeduh.c in Sources */,
|
||||
17C8F6470CBEE797008D969D /* rawsig.c in Sources */,
|
||||
17C8F6480CBEE797008D969D /* readduh.c in Sources */,
|
||||
8370B67917F61038001A4D7A /* ptmeffect.c in Sources */,
|
||||
17C8F6490CBEE797008D969D /* register.c in Sources */,
|
||||
8370B67C17F61038001A4D7A /* readam.c in Sources */,
|
||||
17C8F64A0CBEE797008D969D /* rendduh.c in Sources */,
|
||||
8370B63417F61001001A4D7A /* barray.c in Sources */,
|
||||
8370B67817F61038001A4D7A /* loadstm2.c in Sources */,
|
||||
8370B66A17F61038001A4D7A /* loadasy2.c in Sources */,
|
||||
8370B68717F61038001A4D7A /* readpsm.c in Sources */,
|
||||
8370B67B17F61038001A4D7A /* read6692.c in Sources */,
|
||||
17C8F64B0CBEE797008D969D /* rendsig.c in Sources */,
|
||||
17C8F64C0CBEE797008D969D /* unload.c in Sources */,
|
||||
17C8F64D0CBEE797008D969D /* clickrem.c in Sources */,
|
||||
17C8F64E0CBEE797008D969D /* memfile.c in Sources */,
|
||||
17C8F6510CBEE797008D969D /* resample.c in Sources */,
|
||||
8370B66F17F61038001A4D7A /* loadoldpsm.c in Sources */,
|
||||
17C8F6530CBEE797008D969D /* sampbuf.c in Sources */,
|
||||
17C8F6540CBEE797008D969D /* silence.c in Sources */,
|
||||
17C8F6550CBEE797008D969D /* stdfile.c in Sources */,
|
||||
8370B67417F61038001A4D7A /* loadptm2.c in Sources */,
|
||||
8370B68817F61038001A4D7A /* readptm.c in Sources */,
|
||||
8370B67317F61038001A4D7A /* loadptm.c in Sources */,
|
||||
8370B66417F61038001A4D7A /* load6692.c in Sources */,
|
||||
17C8F6560CBEE797008D969D /* itload.c in Sources */,
|
||||
17C8F6570CBEE797008D969D /* itload2.c in Sources */,
|
||||
8370B63617F61001001A4D7A /* lanczos_resampler.c in Sources */,
|
||||
17C8F6580CBEE797008D969D /* itmisc.c in Sources */,
|
||||
8370B67517F61038001A4D7A /* loadriff.c in Sources */,
|
||||
8370B66917F61038001A4D7A /* loadasy.c in Sources */,
|
||||
17C8F6590CBEE797008D969D /* itorder.c in Sources */,
|
||||
8370B66317F61038001A4D7A /* load669.c in Sources */,
|
||||
17C8F65A0CBEE797008D969D /* itread.c in Sources */,
|
||||
8370B68B17F61038001A4D7A /* readstm2.c in Sources */,
|
||||
17C8F65B0CBEE797008D969D /* itread2.c in Sources */,
|
||||
17C8F65C0CBEE797008D969D /* itrender.c in Sources */,
|
||||
17C8F65D0CBEE797008D969D /* itunload.c in Sources */,
|
||||
|
@ -376,14 +582,34 @@
|
|||
17C8F65F0CBEE797008D969D /* loadmod2.c in Sources */,
|
||||
17C8F6600CBEE797008D969D /* loads3m.c in Sources */,
|
||||
17C8F6610CBEE797008D969D /* loads3m2.c in Sources */,
|
||||
8370B63917F61001001A4D7A /* tarray.c in Sources */,
|
||||
8370B66B17F61038001A4D7A /* loadmtm.c in Sources */,
|
||||
8370B68517F61038001A4D7A /* readokt2.c in Sources */,
|
||||
17C8F6620CBEE797008D969D /* loadxm.c in Sources */,
|
||||
17C8F6630CBEE797008D969D /* loadxm2.c in Sources */,
|
||||
8370B67117F61038001A4D7A /* loadpsm.c in Sources */,
|
||||
8370B67617F61038001A4D7A /* loadriff2.c in Sources */,
|
||||
8370B66C17F61038001A4D7A /* loadmtm2.c in Sources */,
|
||||
8370B67A17F61038001A4D7A /* read669.c in Sources */,
|
||||
8370B66717F61038001A4D7A /* loadany.c in Sources */,
|
||||
8370B68017F61038001A4D7A /* readany2.c in Sources */,
|
||||
17C8F6640CBEE797008D969D /* readmod.c in Sources */,
|
||||
8370B67017F61038001A4D7A /* loadoldpsm2.c in Sources */,
|
||||
8370B68217F61038001A4D7A /* readdsmf.c in Sources */,
|
||||
17C8F6650CBEE797008D969D /* readmod2.c in Sources */,
|
||||
8370B68617F61038001A4D7A /* readoldpsm.c in Sources */,
|
||||
17C8F6660CBEE797008D969D /* reads3m.c in Sources */,
|
||||
17C8F6670CBEE797008D969D /* reads3m2.c in Sources */,
|
||||
17C8F6680CBEE797008D969D /* readxm.c in Sources */,
|
||||
8370B68917F61038001A4D7A /* readriff.c in Sources */,
|
||||
17C8F6690CBEE797008D969D /* readxm2.c in Sources */,
|
||||
8370B66617F61038001A4D7A /* loadamf2.c in Sources */,
|
||||
8370B68417F61038001A4D7A /* readokt.c in Sources */,
|
||||
8370B66817F61038001A4D7A /* loadany2.c in Sources */,
|
||||
8370B66517F61038001A4D7A /* loadamf.c in Sources */,
|
||||
8370B67717F61038001A4D7A /* loadstm.c in Sources */,
|
||||
8370B67E17F61038001A4D7A /* readamf2.c in Sources */,
|
||||
8370B67F17F61038001A4D7A /* readany.c in Sources */,
|
||||
17C8F66A0CBEE797008D969D /* xmeffect.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -421,6 +647,7 @@
|
|||
OBJROOT = ../../build;
|
||||
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
|
||||
PRODUCT_NAME = Dumb;
|
||||
SDKROOT = macosx10.6;
|
||||
SHARED_PRECOMPS_DIR = "";
|
||||
SYMROOT = ../../build;
|
||||
WRAPPER_EXTENSION = framework;
|
||||
|
@ -448,6 +675,7 @@
|
|||
OBJROOT = ../../build;
|
||||
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
|
||||
PRODUCT_NAME = Dumb;
|
||||
SDKROOT = macosx10.6;
|
||||
SHARED_PRECOMPS_DIR = "";
|
||||
SYMROOT = ../../build;
|
||||
WRAPPER_EXTENSION = framework;
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0460"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8DC2EF4F0486A6940098B216"
|
||||
BuildableName = "Dumb.framework"
|
||||
BlueprintName = "Dumb Framework"
|
||||
ReferencedContainer = "container:Dumb.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>Dumb Framework.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>10</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>8DC2EF4F0486A6940098B216</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
File diff suppressed because it is too large
Load diff
27
Frameworks/Dumb/dumb/include/internal/aldumb.h
Normal file
27
Frameworks/Dumb/dumb/include/internal/aldumb.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* internal/aldumb.h - The internal header file / / \ \
|
||||
* for DUMB with Allegro. | < / \_
|
||||
* | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#ifndef INTERNAL_ALDUMB_H
|
||||
#define INTERNAL_ALDUMB_H
|
||||
|
||||
|
||||
void _dat_unload_duh(void *duh);
|
||||
|
||||
|
||||
#endif /* INTERNAL_DUMB_H */
|
20
Frameworks/Dumb/dumb/include/internal/barray.h
Normal file
20
Frameworks/Dumb/dumb/include/internal/barray.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef _B_ARRAY_H_
|
||||
#define _B_ARRAY_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void * bit_array_create(size_t size);
|
||||
void bit_array_destroy(void * array);
|
||||
void * bit_array_dup(void * array);
|
||||
|
||||
void bit_array_reset(void * array);
|
||||
|
||||
void bit_array_set(void * array, size_t bit);
|
||||
int bit_array_test(void * array, size_t bit);
|
||||
int bit_array_test_range(void * array, size_t bit, size_t count);
|
||||
void bit_array_clear(void * array, size_t bit);
|
||||
|
||||
void bit_array_merge(void * array, void * source, size_t offset);
|
||||
void bit_array_mask(void * array, void * source, size_t offset);
|
||||
|
||||
#endif
|
77
Frameworks/Dumb/dumb/include/internal/blip_buf.h
Normal file
77
Frameworks/Dumb/dumb/include/internal/blip_buf.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/** \file
|
||||
Sample buffer that resamples from input clock rate to output sample rate */
|
||||
|
||||
/* blip_buf 1.1.0 */
|
||||
#ifndef BLIP_BUF_H
|
||||
#define 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 blip_t blip_t;
|
||||
|
||||
/** Creates new buffer that can hold at most sample_count samples. Sets rates
|
||||
so that there are blip_max_ratio clocks per sample. Returns pointer to new
|
||||
buffer, or NULL if insufficient memory. */
|
||||
blip_t* blip_new( int sample_count );
|
||||
|
||||
blip_t* blip_dup( blip_t* );
|
||||
|
||||
/** Sets approximate input clock rate and output sample rate. For every
|
||||
clock_rate input clocks, approximately sample_rate samples are generated. */
|
||||
void blip_set_rates( 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. */
|
||||
blip_max_ratio = 1 << 20 };
|
||||
|
||||
/** Clears entire buffer. Afterwards, blip_samples_avail() == 0. */
|
||||
void blip_clear( blip_t* );
|
||||
|
||||
/** Adds positive/negative delta into buffer at specified clock time. */
|
||||
void blip_add_delta( blip_t*, unsigned int clock_time, int delta );
|
||||
|
||||
/** Same as blip_add_delta(), but uses faster, lower-quality synthesis. */
|
||||
void blip_add_delta_fast( blip_t*, unsigned int clock_time, int delta );
|
||||
|
||||
/** Length of time frame, in clocks, needed to make sample_count additional
|
||||
samples available. */
|
||||
int blip_clocks_needed( const blip_t*, int sample_count );
|
||||
|
||||
enum { /** Maximum number of samples that can be generated from one time frame. */
|
||||
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 blip_end_frame( blip_t*, unsigned int clock_duration );
|
||||
|
||||
/** Number of buffered samples available for reading. */
|
||||
int blip_samples_avail( const 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 blip_read_samples( blip_t*, int out [], int count );
|
||||
|
||||
/** Reads the current integrator and returns it */
|
||||
int blip_peek_sample( blip_t* );
|
||||
|
||||
/** Frees buffer. No effect if NULL is passed. */
|
||||
void blip_delete( blip_t* );
|
||||
|
||||
|
||||
/* Deprecated */
|
||||
typedef blip_t blip_buffer_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,61 +1,61 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* internal/dumb.h - DUMB's internal declarations. / / \ \
|
||||
* | < / \_
|
||||
* This header file provides access to the | \/ /\ /
|
||||
* internal structure of DUMB, and is liable \_ / > /
|
||||
* to change, mutate or cease to exist at any | \ / /
|
||||
* moment. Include it at your own peril. | ' /
|
||||
* \__/
|
||||
* ...
|
||||
*
|
||||
* Seriously. You don't need access to anything in this file. All right, you
|
||||
* probably do actually. But if you use it, you will be relying on a specific
|
||||
* version of DUMB, so please check DUMB_VERSION defined in dumb.h. Please
|
||||
* contact the authors so that we can provide a public API for what you need.
|
||||
*/
|
||||
|
||||
#ifndef INTERNAL_DUMB_H
|
||||
#define INTERNAL_DUMB_H
|
||||
|
||||
|
||||
typedef struct DUH_SIGTYPE_DESC_LINK
|
||||
{
|
||||
struct DUH_SIGTYPE_DESC_LINK *next;
|
||||
DUH_SIGTYPE_DESC *desc;
|
||||
}
|
||||
DUH_SIGTYPE_DESC_LINK;
|
||||
|
||||
|
||||
typedef struct DUH_SIGNAL
|
||||
{
|
||||
sigdata_t *sigdata;
|
||||
DUH_SIGTYPE_DESC *desc;
|
||||
}
|
||||
DUH_SIGNAL;
|
||||
|
||||
|
||||
struct DUH
|
||||
{
|
||||
long length;
|
||||
|
||||
int n_tags;
|
||||
char *(*tag)[2];
|
||||
|
||||
int n_signals;
|
||||
DUH_SIGNAL **signal;
|
||||
};
|
||||
|
||||
|
||||
DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type);
|
||||
|
||||
|
||||
#endif /* INTERNAL_DUMB_H */
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* internal/dumb.h - DUMB's internal declarations. / / \ \
|
||||
* | < / \_
|
||||
* This header file provides access to the | \/ /\ /
|
||||
* internal structure of DUMB, and is liable \_ / > /
|
||||
* to change, mutate or cease to exist at any | \ / /
|
||||
* moment. Include it at your own peril. | ' /
|
||||
* \__/
|
||||
* ...
|
||||
*
|
||||
* Seriously. You don't need access to anything in this file. All right, you
|
||||
* probably do actually. But if you use it, you will be relying on a specific
|
||||
* version of DUMB, so please check DUMB_VERSION defined in dumb.h. Please
|
||||
* contact the authors so that we can provide a public API for what you need.
|
||||
*/
|
||||
|
||||
#ifndef INTERNAL_DUMB_H
|
||||
#define INTERNAL_DUMB_H
|
||||
|
||||
|
||||
typedef struct DUH_SIGTYPE_DESC_LINK
|
||||
{
|
||||
struct DUH_SIGTYPE_DESC_LINK *next;
|
||||
DUH_SIGTYPE_DESC *desc;
|
||||
}
|
||||
DUH_SIGTYPE_DESC_LINK;
|
||||
|
||||
|
||||
typedef struct DUH_SIGNAL
|
||||
{
|
||||
sigdata_t *sigdata;
|
||||
DUH_SIGTYPE_DESC *desc;
|
||||
}
|
||||
DUH_SIGNAL;
|
||||
|
||||
|
||||
struct DUH
|
||||
{
|
||||
long length;
|
||||
|
||||
int n_tags;
|
||||
char *(*tag)[2];
|
||||
|
||||
int n_signals;
|
||||
DUH_SIGNAL **signal;
|
||||
};
|
||||
|
||||
|
||||
DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type);
|
||||
|
||||
|
||||
#endif /* INTERNAL_DUMB_H */
|
||||
|
|
13
Frameworks/Dumb/dumb/include/internal/dumbfile.h
Normal file
13
Frameworks/Dumb/dumb/include/internal/dumbfile.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef DUMBFILE_H
|
||||
#define DUMBFILE_H
|
||||
|
||||
#include "../dumb.h"
|
||||
|
||||
struct DUMBFILE
|
||||
{
|
||||
const DUMBFILE_SYSTEM *dfs;
|
||||
void *file;
|
||||
long pos;
|
||||
};
|
||||
|
||||
#endif // DUMBFILE_H
|
18
Frameworks/Dumb/dumb/include/internal/fir_resampler.h
Normal file
18
Frameworks/Dumb/dumb/include/internal/fir_resampler.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef _FIR_RESAMPLER_H_
|
||||
#define _FIR_RESAMPLER_H_
|
||||
|
||||
void fir_init();
|
||||
|
||||
void * fir_resampler_create();
|
||||
void fir_resampler_delete(void *);
|
||||
void * fir_resampler_dup(void *);
|
||||
|
||||
int fir_resampler_get_free_count(void *);
|
||||
void fir_resampler_write_sample(void *, short sample);
|
||||
void fir_resampler_set_rate( void *, double new_factor );
|
||||
int fir_resampler_ready(void *);
|
||||
void fir_resampler_clear(void *);
|
||||
int fir_resampler_get_sample(void *);
|
||||
void fir_resampler_remove_sample(void *);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
19
Frameworks/Dumb/dumb/include/internal/lanczos_resampler.h
Normal file
19
Frameworks/Dumb/dumb/include/internal/lanczos_resampler.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef _LANCZOS_RESAMPLER_H_
|
||||
#define _LANCZOS_RESAMPLER_H_
|
||||
|
||||
void lanczos_init();
|
||||
|
||||
void * lanczos_resampler_create();
|
||||
void lanczos_resampler_delete(void *);
|
||||
void * lanczos_resampler_dup(void *);
|
||||
|
||||
int lanczos_resampler_get_free_count(void *);
|
||||
void lanczos_resampler_write_sample(void *, short sample);
|
||||
void lanczos_resampler_set_rate( void *, double new_factor );
|
||||
int lanczos_resampler_ready(void *);
|
||||
void lanczos_resampler_clear(void *);
|
||||
int lanczos_resampler_get_sample_count(void *);
|
||||
int lanczos_resampler_get_sample(void *);
|
||||
void lanczos_resampler_remove_sample(void *);
|
||||
|
||||
#endif
|
30
Frameworks/Dumb/dumb/include/internal/lpc.h
Normal file
30
Frameworks/Dumb/dumb/include/internal/lpc.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LPC low level routines
|
||||
last mod: $Id: lpc.h 16037 2009-05-26 21:10:58Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LPC_H_
|
||||
#define _V_LPC_H_
|
||||
|
||||
/* simple linear scale LPC code */
|
||||
extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m);
|
||||
|
||||
extern void vorbis_lpc_predict(float *coeff,float *prime,int m,
|
||||
float *data,long n);
|
||||
|
||||
struct DUMB_IT_SIGDATA;
|
||||
extern void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata);
|
||||
|
||||
#endif
|
24
Frameworks/Dumb/dumb/include/internal/riff.h
Normal file
24
Frameworks/Dumb/dumb/include/internal/riff.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef RIFF_H
|
||||
#define RIFF_H
|
||||
|
||||
struct riff;
|
||||
|
||||
struct riff_chunk
|
||||
{
|
||||
unsigned type;
|
||||
long offset;
|
||||
unsigned size;
|
||||
struct riff * nested;
|
||||
};
|
||||
|
||||
struct riff
|
||||
{
|
||||
unsigned type;
|
||||
unsigned chunk_count;
|
||||
struct riff_chunk * chunks;
|
||||
};
|
||||
|
||||
struct riff * riff_parse( DUMBFILE * f, long offset, long size, unsigned proper );
|
||||
void riff_free( struct riff * );
|
||||
|
||||
#endif
|
113
Frameworks/Dumb/dumb/include/internal/stack_alloc.h
Normal file
113
Frameworks/Dumb/dumb/include/internal/stack_alloc.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
/* Copyright (C) 2002 Jean-Marc Valin */
|
||||
/**
|
||||
@file stack_alloc.h
|
||||
@brief Temporary memory allocation on stack
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef STACK_ALLOC_H
|
||||
#define STACK_ALLOC_H
|
||||
|
||||
#ifdef WIN32
|
||||
# include <malloc.h>
|
||||
#else
|
||||
# ifdef HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def ALIGN(stack, size)
|
||||
*
|
||||
* Aligns the stack to a 'size' boundary
|
||||
*
|
||||
* @param stack Stack
|
||||
* @param size New size boundary
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def PUSH(stack, size, type)
|
||||
*
|
||||
* Allocates 'size' elements of type 'type' on the stack
|
||||
*
|
||||
* @param stack Stack
|
||||
* @param size Number of elements
|
||||
* @param type Type of element
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def VARDECL(var)
|
||||
*
|
||||
* Declare variable on stack
|
||||
*
|
||||
* @param var Variable to declare
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def ALLOC(var, size, type)
|
||||
*
|
||||
* Allocate 'size' elements of 'type' on stack
|
||||
*
|
||||
* @param var Name of variable to allocate
|
||||
* @param size Number of elements
|
||||
* @param type Type of element
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_VALGRIND
|
||||
|
||||
#include <valgrind/memcheck.h>
|
||||
|
||||
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
|
||||
|
||||
#define PUSH(stack, size, type) (VALGRIND_MAKE_NOACCESS(stack, 1000),ALIGN((stack),sizeof(type)),VALGRIND_MAKE_WRITABLE(stack, ((size)*sizeof(type))),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type))))
|
||||
|
||||
#else
|
||||
|
||||
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
|
||||
|
||||
#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type))))
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(VAR_ARRAYS)
|
||||
#define VARDECL(var)
|
||||
#define ALLOC(var, size, type) type var[size]
|
||||
#elif defined(USE_ALLOCA)
|
||||
#define VARDECL(var) var
|
||||
#define ALLOC(var, size, type) var = alloca(sizeof(type)*(size))
|
||||
#else
|
||||
#define VARDECL(var) var
|
||||
#define ALLOC(var, size, type) var = PUSH(stack, size, type)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
25
Frameworks/Dumb/dumb/include/internal/tarray.h
Normal file
25
Frameworks/Dumb/dumb/include/internal/tarray.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef _T_ARRAY_H_
|
||||
#define _T_ARRAY_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __FRAMEWORK__
|
||||
#include <Dumb/dumb.h>
|
||||
#else
|
||||
#include "../dumb.h"
|
||||
#endif
|
||||
|
||||
void * timekeeping_array_create(size_t size);
|
||||
void timekeeping_array_destroy(void * array);
|
||||
void * timekeeping_array_dup(void * array);
|
||||
|
||||
void timekeeping_array_reset(void * array, size_t loop_start);
|
||||
|
||||
void timekeeping_array_push(void * array, size_t index, LONG_LONG time);
|
||||
void timekeeping_array_bump(void * array, size_t index);
|
||||
|
||||
unsigned int timekeeping_array_get_count(void * array, size_t index);
|
||||
|
||||
LONG_LONG timekeeping_array_get_item(void * array, size_t index);
|
||||
|
||||
#endif
|
3
Frameworks/Dumb/dumb/prj/.gitignore
vendored
Normal file
3
Frameworks/Dumb/dumb/prj/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
dumb-build-Desktop-Release
|
||||
dumb-build-Desktop-Debug
|
||||
*.user
|
132
Frameworks/Dumb/dumb/prj/dumb/dumb.pro
Normal file
132
Frameworks/Dumb/dumb/prj/dumb/dumb.pro
Normal file
|
@ -0,0 +1,132 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2012-12-22T16:33:53
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT -= core gui
|
||||
|
||||
TARGET = dumb
|
||||
TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
|
||||
DEFINES += _USE_SSE
|
||||
|
||||
INCLUDEPATH += ../../include
|
||||
|
||||
QMAKE_CFLAGS += -msse
|
||||
|
||||
SOURCES += \
|
||||
../../src/core/unload.c \
|
||||
../../src/core/rendsig.c \
|
||||
../../src/core/rendduh.c \
|
||||
../../src/core/register.c \
|
||||
../../src/core/readduh.c \
|
||||
../../src/core/rawsig.c \
|
||||
../../src/core/makeduh.c \
|
||||
../../src/core/loadduh.c \
|
||||
../../src/core/dumbfile.c \
|
||||
../../src/core/duhtag.c \
|
||||
../../src/core/duhlen.c \
|
||||
../../src/core/atexit.c \
|
||||
../../src/helpers/stdfile.c \
|
||||
../../src/helpers/silence.c \
|
||||
../../src/helpers/sampbuf.c \
|
||||
../../src/helpers/riff.c \
|
||||
../../src/helpers/resample.c \
|
||||
../../src/helpers/memfile.c \
|
||||
../../src/helpers/clickrem.c \
|
||||
../../src/helpers/blip_buf.c \
|
||||
../../src/helpers/barray.c \
|
||||
../../src/helpers/tarray.c \
|
||||
../../src/it/xmeffect.c \
|
||||
../../src/it/readxm2.c \
|
||||
../../src/it/readxm.c \
|
||||
../../src/it/readstm2.c \
|
||||
../../src/it/readstm.c \
|
||||
../../src/it/reads3m2.c \
|
||||
../../src/it/reads3m.c \
|
||||
../../src/it/readriff.c \
|
||||
../../src/it/readptm.c \
|
||||
../../src/it/readpsm.c \
|
||||
../../src/it/readoldpsm.c \
|
||||
../../src/it/readokt2.c \
|
||||
../../src/it/readokt.c \
|
||||
../../src/it/readmtm.c \
|
||||
../../src/it/readmod2.c \
|
||||
../../src/it/readmod.c \
|
||||
../../src/it/readdsmf.c \
|
||||
../../src/it/readasy.c \
|
||||
../../src/it/readamf2.c \
|
||||
../../src/it/readamf.c \
|
||||
../../src/it/readam.c \
|
||||
../../src/it/read6692.c \
|
||||
../../src/it/read669.c \
|
||||
../../src/it/ptmeffect.c \
|
||||
../../src/it/loadxm2.c \
|
||||
../../src/it/loadxm.c \
|
||||
../../src/it/loadstm2.c \
|
||||
../../src/it/loadstm.c \
|
||||
../../src/it/loads3m2.c \
|
||||
../../src/it/loads3m.c \
|
||||
../../src/it/loadriff2.c \
|
||||
../../src/it/loadriff.c \
|
||||
../../src/it/loadptm2.c \
|
||||
../../src/it/loadptm.c \
|
||||
../../src/it/loadpsm2.c \
|
||||
../../src/it/loadpsm.c \
|
||||
../../src/it/loadoldpsm2.c \
|
||||
../../src/it/loadoldpsm.c \
|
||||
../../src/it/loadokt2.c \
|
||||
../../src/it/loadokt.c \
|
||||
../../src/it/loadmtm2.c \
|
||||
../../src/it/loadmtm.c \
|
||||
../../src/it/loadmod2.c \
|
||||
../../src/it/loadmod.c \
|
||||
../../src/it/loadasy2.c \
|
||||
../../src/it/loadasy.c \
|
||||
../../src/it/loadamf2.c \
|
||||
../../src/it/loadamf.c \
|
||||
../../src/it/load6692.c \
|
||||
../../src/it/load669.c \
|
||||
../../src/it/itunload.c \
|
||||
../../src/it/itrender.c \
|
||||
../../src/it/itread2.c \
|
||||
../../src/it/itread.c \
|
||||
../../src/it/itorder.c \
|
||||
../../src/it/itmisc.c \
|
||||
../../src/it/itload2.c \
|
||||
../../src/it/itload.c \
|
||||
../../src/it/readany.c \
|
||||
../../src/it/loadany2.c \
|
||||
../../src/it/loadany.c \
|
||||
../../src/it/readany2.c \
|
||||
../../src/helpers/lanczos_resampler.c \
|
||||
../../src/helpers/lpc.c
|
||||
|
||||
HEADERS += \
|
||||
../../include/dumb.h \
|
||||
../../include/internal/riff.h \
|
||||
../../include/internal/it.h \
|
||||
../../include/internal/dumb.h \
|
||||
../../include/internal/blip_buf.h \
|
||||
../../include/internal/barray.h \
|
||||
../../include/internal/tarray.h \
|
||||
../../include/internal/aldumb.h \
|
||||
../../include/internal/lanczos_resampler.h \
|
||||
../../include/internal/stack_alloc.h \
|
||||
../../include/internal/lpc.h \
|
||||
../../include/internal/dumbfile.h
|
||||
unix:!symbian {
|
||||
maemo5 {
|
||||
target.path = /opt/usr/lib
|
||||
} else {
|
||||
target.path = /usr/lib
|
||||
}
|
||||
INSTALLS += target
|
||||
}
|
||||
|
||||
OTHER_FILES += \
|
||||
../../src/helpers/resample.inc \
|
||||
../../src/helpers/resamp3.inc \
|
||||
../../src/helpers/resamp2.inc
|
|
@ -1,71 +1,71 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* atexit.c - Library Clean-up Management. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
typedef struct DUMB_ATEXIT_PROC
|
||||
{
|
||||
struct DUMB_ATEXIT_PROC *next;
|
||||
void (*proc)(void);
|
||||
}
|
||||
DUMB_ATEXIT_PROC;
|
||||
|
||||
|
||||
|
||||
static DUMB_ATEXIT_PROC *dumb_atexit_proc = NULL;
|
||||
|
||||
|
||||
|
||||
int dumb_atexit(void (*proc)(void))
|
||||
{
|
||||
DUMB_ATEXIT_PROC *dap = dumb_atexit_proc;
|
||||
|
||||
while (dap) {
|
||||
if (dap->proc == proc) return 0;
|
||||
dap = dap->next;
|
||||
}
|
||||
|
||||
dap = malloc(sizeof(*dap));
|
||||
|
||||
if (!dap)
|
||||
return -1;
|
||||
|
||||
dap->next = dumb_atexit_proc;
|
||||
dap->proc = proc;
|
||||
dumb_atexit_proc = dap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_exit(void)
|
||||
{
|
||||
while (dumb_atexit_proc) {
|
||||
DUMB_ATEXIT_PROC *next = dumb_atexit_proc->next;
|
||||
(*dumb_atexit_proc->proc)();
|
||||
free(dumb_atexit_proc);
|
||||
dumb_atexit_proc = next;
|
||||
}
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* atexit.c - Library Clean-up Management. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
typedef struct DUMB_ATEXIT_PROC
|
||||
{
|
||||
struct DUMB_ATEXIT_PROC *next;
|
||||
void (*proc)(void);
|
||||
}
|
||||
DUMB_ATEXIT_PROC;
|
||||
|
||||
|
||||
|
||||
static DUMB_ATEXIT_PROC *dumb_atexit_proc = NULL;
|
||||
|
||||
|
||||
|
||||
int dumb_atexit(void (*proc)(void))
|
||||
{
|
||||
DUMB_ATEXIT_PROC *dap = dumb_atexit_proc;
|
||||
|
||||
while (dap) {
|
||||
if (dap->proc == proc) return 0;
|
||||
dap = dap->next;
|
||||
}
|
||||
|
||||
dap = malloc(sizeof(*dap));
|
||||
|
||||
if (!dap)
|
||||
return -1;
|
||||
|
||||
dap->next = dumb_atexit_proc;
|
||||
dap->proc = proc;
|
||||
dumb_atexit_proc = dap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_exit(void)
|
||||
{
|
||||
while (dumb_atexit_proc) {
|
||||
DUMB_ATEXIT_PROC *next = dumb_atexit_proc->next;
|
||||
(*dumb_atexit_proc->proc)();
|
||||
free(dumb_atexit_proc);
|
||||
dumb_atexit_proc = next;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* duhlen.c - Functions to set and return the / / \ \
|
||||
* length of a DUH. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* Note that the length of a DUH is a constant | ' /
|
||||
* stored in the DUH struct and in the DUH disk \__/
|
||||
* format. It will be calculated on loading for
|
||||
* other formats in which the length is not explicitly stored. Also note that
|
||||
* it does not necessarily correspond to the length of time for which the DUH
|
||||
* will generate samples. Rather it represents a suitable point for a player
|
||||
* such as Winamp to stop, and in any good DUH it will allow for any final
|
||||
* flourish to fade out and be appreciated.
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
long duh_get_length(DUH *duh)
|
||||
{
|
||||
return duh ? duh->length : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_set_length(DUH *duh, long length)
|
||||
{
|
||||
if (duh)
|
||||
duh->length = length;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* duhlen.c - Functions to set and return the / / \ \
|
||||
* length of a DUH. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* Note that the length of a DUH is a constant | ' /
|
||||
* stored in the DUH struct and in the DUH disk \__/
|
||||
* format. It will be calculated on loading for
|
||||
* other formats in which the length is not explicitly stored. Also note that
|
||||
* it does not necessarily correspond to the length of time for which the DUH
|
||||
* will generate samples. Rather it represents a suitable point for a player
|
||||
* such as Winamp to stop, and in any good DUH it will allow for any final
|
||||
* flourish to fade out and be appreciated.
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
long duh_get_length(DUH *duh)
|
||||
{
|
||||
return duh ? duh->length : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_set_length(DUH *duh, long length)
|
||||
{
|
||||
if (duh)
|
||||
duh->length = length;
|
||||
}
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* duhtag.c - Function to return the tags stored / / \ \
|
||||
* in a DUH struct (typically author | < / \_
|
||||
* information). | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
const char *duh_get_tag(DUH *duh, const char *key)
|
||||
{
|
||||
int i;
|
||||
ASSERT(key);
|
||||
if (!duh || !duh->tag) return NULL;
|
||||
|
||||
for (i = 0; i < duh->n_tags; i++)
|
||||
if (strcmp(key, duh->tag[i][0]) == 0)
|
||||
return duh->tag[i][1];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* duhtag.c - Function to return the tags stored / / \ \
|
||||
* in a DUH struct (typically author | < / \_
|
||||
* information). | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
const char *duh_get_tag(DUH *duh, const char *key)
|
||||
{
|
||||
int i;
|
||||
ASSERT(key);
|
||||
if (!duh || !duh->tag) return NULL;
|
||||
|
||||
for (i = 0; i < duh->n_tags; i++)
|
||||
if (strcmp(key, duh->tag[i][0]) == 0)
|
||||
return duh->tag[i][1];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,401 +1,418 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* dumbfile.c - Hookable, strictly sequential / / \ \
|
||||
* file input functions. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
static DUMBFILE_SYSTEM *the_dfs = NULL;
|
||||
|
||||
|
||||
|
||||
void register_dumbfile_system(DUMBFILE_SYSTEM *dfs)
|
||||
{
|
||||
ASSERT(dfs);
|
||||
ASSERT(dfs->open);
|
||||
ASSERT(dfs->getc);
|
||||
ASSERT(dfs->close);
|
||||
the_dfs = dfs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct DUMBFILE
|
||||
{
|
||||
DUMBFILE_SYSTEM *dfs;
|
||||
void *file;
|
||||
long pos;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DUMBFILE *dumbfile_open(const char *filename)
|
||||
{
|
||||
DUMBFILE *f;
|
||||
|
||||
ASSERT(the_dfs);
|
||||
|
||||
f = malloc(sizeof(*f));
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
f->dfs = the_dfs;
|
||||
|
||||
f->file = (*the_dfs->open)(filename);
|
||||
|
||||
if (!f->file) {
|
||||
free(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->pos = 0;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUMBFILE *dumbfile_open_ex(void *file, DUMBFILE_SYSTEM *dfs)
|
||||
{
|
||||
DUMBFILE *f;
|
||||
|
||||
ASSERT(dfs);
|
||||
ASSERT(dfs->getc);
|
||||
ASSERT(file);
|
||||
|
||||
f = malloc(sizeof(*f));
|
||||
|
||||
if (!f) {
|
||||
if (dfs->close)
|
||||
(*dfs->close)(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->dfs = dfs;
|
||||
f->file = file;
|
||||
|
||||
f->pos = 0;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumbfile_pos(DUMBFILE *f)
|
||||
{
|
||||
ASSERT(f);
|
||||
|
||||
return f->pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_skip(DUMBFILE *f, long n)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ASSERT(f);
|
||||
ASSERT(n >= 0);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
f->pos += n;
|
||||
|
||||
if (f->dfs->skip) {
|
||||
rv = (*f->dfs->skip)(f->file, n);
|
||||
if (rv) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
while (n) {
|
||||
rv = (*f->dfs->getc)(f->file);
|
||||
if (rv < 0) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_getc(DUMBFILE *f)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
rv = (*f->dfs->getc)(f->file);
|
||||
|
||||
if (rv < 0) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
f->pos++;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_igetw(DUMBFILE *f)
|
||||
{
|
||||
int l, h;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
l = (*f->dfs->getc)(f->file);
|
||||
if (l < 0) {
|
||||
f->pos = -1;
|
||||
return l;
|
||||
}
|
||||
|
||||
h = (*f->dfs->getc)(f->file);
|
||||
if (h < 0) {
|
||||
f->pos = -1;
|
||||
return h;
|
||||
}
|
||||
|
||||
f->pos += 2;
|
||||
|
||||
return l | (h << 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_mgetw(DUMBFILE *f)
|
||||
{
|
||||
int l, h;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
h = (*f->dfs->getc)(f->file);
|
||||
if (h < 0) {
|
||||
f->pos = -1;
|
||||
return h;
|
||||
}
|
||||
|
||||
l = (*f->dfs->getc)(f->file);
|
||||
if (l < 0) {
|
||||
f->pos = -1;
|
||||
return l;
|
||||
}
|
||||
|
||||
f->pos += 2;
|
||||
|
||||
return l | (h << 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumbfile_igetl(DUMBFILE *f)
|
||||
{
|
||||
unsigned long rv, b;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
rv = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)rv < 0) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b << 8;
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b << 16;
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b << 24;
|
||||
|
||||
f->pos += 4;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumbfile_mgetl(DUMBFILE *f)
|
||||
{
|
||||
unsigned long rv, b;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
rv = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)rv < 0) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
rv <<= 24;
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b << 16;
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b << 8;
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b;
|
||||
|
||||
f->pos += 4;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned long dumbfile_cgetul(DUMBFILE *f)
|
||||
{
|
||||
unsigned long rv = 0;
|
||||
int v;
|
||||
|
||||
do {
|
||||
v = dumbfile_getc(f);
|
||||
|
||||
if (v < 0)
|
||||
return v;
|
||||
|
||||
rv <<= 7;
|
||||
rv |= v & 0x7F;
|
||||
} while (v & 0x80);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
signed long dumbfile_cgetsl(DUMBFILE *f)
|
||||
{
|
||||
unsigned long rv = dumbfile_cgetul(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return rv;
|
||||
|
||||
return (rv >> 1) | (rv << 31);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumbfile_getnc(char *ptr, long n, DUMBFILE *f)
|
||||
{
|
||||
long rv;
|
||||
|
||||
ASSERT(f);
|
||||
ASSERT(n >= 0);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
if (f->dfs->getnc) {
|
||||
rv = (*f->dfs->getnc)(ptr, n, f->file);
|
||||
if (rv < n) {
|
||||
f->pos = -1;
|
||||
return MAX(rv, 0);
|
||||
}
|
||||
} else {
|
||||
for (rv = 0; rv < n; rv++) {
|
||||
int c = (*f->dfs->getc)(f->file);
|
||||
if (c < 0) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
*ptr++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
f->pos += rv;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_error(DUMBFILE *f)
|
||||
{
|
||||
ASSERT(f);
|
||||
|
||||
return f->pos < 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_close(DUMBFILE *f)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
rv = f->pos < 0;
|
||||
|
||||
if (f->dfs->close)
|
||||
(*f->dfs->close)(f->file);
|
||||
|
||||
free(f);
|
||||
|
||||
return rv;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* dumbfile.c - Hookable, strictly sequential / / \ \
|
||||
* file input functions. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
static const DUMBFILE_SYSTEM *the_dfs = NULL;
|
||||
|
||||
|
||||
|
||||
void register_dumbfile_system(const DUMBFILE_SYSTEM *dfs)
|
||||
{
|
||||
ASSERT(dfs);
|
||||
ASSERT(dfs->open);
|
||||
ASSERT(dfs->getc);
|
||||
ASSERT(dfs->close);
|
||||
ASSERT(dfs->seek);
|
||||
ASSERT(dfs->get_size);
|
||||
the_dfs = dfs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "internal/dumbfile.h"
|
||||
|
||||
|
||||
|
||||
DUMBFILE *dumbfile_open(const char *filename)
|
||||
{
|
||||
DUMBFILE *f;
|
||||
|
||||
ASSERT(the_dfs);
|
||||
|
||||
f = (DUMBFILE *) malloc(sizeof(*f));
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
f->dfs = the_dfs;
|
||||
|
||||
f->file = (*the_dfs->open)(filename);
|
||||
|
||||
if (!f->file) {
|
||||
free(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->pos = 0;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUMBFILE *dumbfile_open_ex(void *file, const DUMBFILE_SYSTEM *dfs)
|
||||
{
|
||||
DUMBFILE *f;
|
||||
|
||||
ASSERT(dfs);
|
||||
ASSERT(dfs->getc);
|
||||
ASSERT(file);
|
||||
|
||||
f = (DUMBFILE *) malloc(sizeof(*f));
|
||||
|
||||
if (!f) {
|
||||
if (dfs->close)
|
||||
(*dfs->close)(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->dfs = dfs;
|
||||
f->file = file;
|
||||
|
||||
f->pos = 0;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumbfile_pos(DUMBFILE *f)
|
||||
{
|
||||
ASSERT(f);
|
||||
|
||||
return f->pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_skip(DUMBFILE *f, long n)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ASSERT(f);
|
||||
ASSERT(n >= 0);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
f->pos += n;
|
||||
|
||||
if (f->dfs->skip) {
|
||||
rv = (*f->dfs->skip)(f->file, n);
|
||||
if (rv) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
while (n) {
|
||||
rv = (*f->dfs->getc)(f->file);
|
||||
if (rv < 0) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_getc(DUMBFILE *f)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
rv = (*f->dfs->getc)(f->file);
|
||||
|
||||
if (rv < 0) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
f->pos++;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_igetw(DUMBFILE *f)
|
||||
{
|
||||
int l, h;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
l = (*f->dfs->getc)(f->file);
|
||||
if (l < 0) {
|
||||
f->pos = -1;
|
||||
return l;
|
||||
}
|
||||
|
||||
h = (*f->dfs->getc)(f->file);
|
||||
if (h < 0) {
|
||||
f->pos = -1;
|
||||
return h;
|
||||
}
|
||||
|
||||
f->pos += 2;
|
||||
|
||||
return l | (h << 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_mgetw(DUMBFILE *f)
|
||||
{
|
||||
int l, h;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
h = (*f->dfs->getc)(f->file);
|
||||
if (h < 0) {
|
||||
f->pos = -1;
|
||||
return h;
|
||||
}
|
||||
|
||||
l = (*f->dfs->getc)(f->file);
|
||||
if (l < 0) {
|
||||
f->pos = -1;
|
||||
return l;
|
||||
}
|
||||
|
||||
f->pos += 2;
|
||||
|
||||
return l | (h << 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumbfile_igetl(DUMBFILE *f)
|
||||
{
|
||||
unsigned long rv, b;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
rv = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)rv < 0) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b << 8;
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b << 16;
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b << 24;
|
||||
|
||||
f->pos += 4;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumbfile_mgetl(DUMBFILE *f)
|
||||
{
|
||||
unsigned long rv, b;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
rv = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)rv < 0) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
rv <<= 24;
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b << 16;
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b << 8;
|
||||
|
||||
b = (*f->dfs->getc)(f->file);
|
||||
if ((signed long)b < 0) {
|
||||
f->pos = -1;
|
||||
return b;
|
||||
}
|
||||
rv |= b;
|
||||
|
||||
f->pos += 4;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned long dumbfile_cgetul(DUMBFILE *f)
|
||||
{
|
||||
unsigned long rv = 0;
|
||||
int v;
|
||||
|
||||
do {
|
||||
v = dumbfile_getc(f);
|
||||
|
||||
if (v < 0)
|
||||
return v;
|
||||
|
||||
rv <<= 7;
|
||||
rv |= v & 0x7F;
|
||||
} while (v & 0x80);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
signed long dumbfile_cgetsl(DUMBFILE *f)
|
||||
{
|
||||
unsigned long rv = dumbfile_cgetul(f);
|
||||
|
||||
if (f->pos < 0)
|
||||
return rv;
|
||||
|
||||
return (rv >> 1) | (rv << 31);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumbfile_getnc(char *ptr, long n, DUMBFILE *f)
|
||||
{
|
||||
long rv;
|
||||
|
||||
ASSERT(f);
|
||||
ASSERT(n >= 0);
|
||||
|
||||
if (f->pos < 0)
|
||||
return -1;
|
||||
|
||||
if (f->dfs->getnc) {
|
||||
rv = (*f->dfs->getnc)(ptr, n, f->file);
|
||||
if (rv < n) {
|
||||
f->pos = -1;
|
||||
return MAX(rv, 0);
|
||||
}
|
||||
} else {
|
||||
for (rv = 0; rv < n; rv++) {
|
||||
int c = (*f->dfs->getc)(f->file);
|
||||
if (c < 0) {
|
||||
f->pos = -1;
|
||||
return rv;
|
||||
}
|
||||
*ptr++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
f->pos += rv;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_seek(DUMBFILE *f, long n, int origin)
|
||||
{
|
||||
switch ( origin )
|
||||
{
|
||||
case DFS_SEEK_CUR: n += f->pos; break;
|
||||
case DFS_SEEK_END: n += (*f->dfs->get_size)(f->file); break;
|
||||
}
|
||||
f->pos = n;
|
||||
return (*f->dfs->seek)(f->file, n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumbfile_get_size(DUMBFILE *f)
|
||||
{
|
||||
return (*f->dfs->get_size)(f->file);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_error(DUMBFILE *f)
|
||||
{
|
||||
ASSERT(f);
|
||||
|
||||
return f->pos < 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumbfile_close(DUMBFILE *f)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ASSERT(f);
|
||||
|
||||
rv = f->pos < 0;
|
||||
|
||||
if (f->dfs->close)
|
||||
(*f->dfs->close)(f->file);
|
||||
|
||||
free(f);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadduh.c - Code to read a DUH from a file, / / \ \
|
||||
* opening and closing the file for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
/* load_duh(): loads a .duh file, returning a pointer to a DUH struct.
|
||||
* When you have finished with it, you must pass the pointer to unload_duh()
|
||||
* so that the memory can be freed.
|
||||
*/
|
||||
DUH *load_duh(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = read_duh(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadduh.c - Code to read a DUH from a file, / / \ \
|
||||
* opening and closing the file for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
/* load_duh(): loads a .duh file, returning a pointer to a DUH struct.
|
||||
* When you have finished with it, you must pass the pointer to unload_duh()
|
||||
* so that the memory can be freed.
|
||||
*/
|
||||
DUH *load_duh(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = read_duh(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
||||
|
|
|
@ -1,132 +1,151 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* makeduh.c - Function to construct a DUH from / / \ \
|
||||
* its components. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
static DUH_SIGNAL *make_signal(DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata)
|
||||
{
|
||||
DUH_SIGNAL *signal;
|
||||
|
||||
ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer));
|
||||
ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample);
|
||||
|
||||
signal = malloc(sizeof(*signal));
|
||||
|
||||
if (!signal) {
|
||||
if (desc->unload_sigdata)
|
||||
if (sigdata)
|
||||
(*desc->unload_sigdata)(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
signal->desc = desc;
|
||||
signal->sigdata = sigdata;
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUH *make_duh(
|
||||
long length,
|
||||
int n_tags,
|
||||
const char *const tags[][2],
|
||||
int n_signals,
|
||||
DUH_SIGTYPE_DESC *desc[],
|
||||
sigdata_t *sigdata[]
|
||||
)
|
||||
{
|
||||
DUH *duh = malloc(sizeof(*duh));
|
||||
int i;
|
||||
int fail;
|
||||
|
||||
if (duh) {
|
||||
duh->n_signals = n_signals;
|
||||
|
||||
duh->signal = malloc(n_signals * sizeof(*duh->signal));
|
||||
|
||||
if (!duh->signal) {
|
||||
free(duh);
|
||||
duh = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!duh) {
|
||||
for (i = 0; i < n_signals; i++)
|
||||
if (desc[i]->unload_sigdata)
|
||||
if (sigdata[i])
|
||||
(*desc[i]->unload_sigdata)(sigdata[i]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
duh->n_tags = 0;
|
||||
duh->tag = NULL;
|
||||
|
||||
fail = 0;
|
||||
|
||||
for (i = 0; i < n_signals; i++) {
|
||||
duh->signal[i] = make_signal(desc[i], sigdata[i]);
|
||||
if (!duh->signal[i])
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
unload_duh(duh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
duh->length = length;
|
||||
|
||||
{
|
||||
int mem = n_tags * 2; /* account for NUL terminators here */
|
||||
char *ptr;
|
||||
|
||||
for (i = 0; i < n_tags; i++)
|
||||
mem += strlen(tags[i][0]) + strlen(tags[i][1]);
|
||||
|
||||
if (mem <= 0) return duh;
|
||||
|
||||
duh->tag = malloc(n_tags * sizeof(*duh->tag));
|
||||
if (!duh->tag) return duh;
|
||||
duh->tag[0][0] = malloc(mem);
|
||||
if (!duh->tag[0][0]) {
|
||||
free(duh->tag);
|
||||
duh->tag = NULL;
|
||||
return duh;
|
||||
}
|
||||
duh->n_tags = n_tags;
|
||||
ptr = duh->tag[0][0];
|
||||
for (i = 0; i < n_tags; i++) {
|
||||
duh->tag[i][0] = ptr;
|
||||
strcpy(ptr, tags[i][0]);
|
||||
ptr += strlen(tags[i][0]) + 1;
|
||||
duh->tag[i][1] = ptr;
|
||||
strcpy(ptr, tags[i][1]);
|
||||
ptr += strlen(tags[i][1]) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* makeduh.c - Function to construct a DUH from / / \ \
|
||||
* its components. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
static DUH_SIGNAL *make_signal(DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata)
|
||||
{
|
||||
DUH_SIGNAL *signal;
|
||||
|
||||
ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer));
|
||||
ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample);
|
||||
|
||||
signal = malloc(sizeof(*signal));
|
||||
|
||||
if (!signal) {
|
||||
if (desc->unload_sigdata)
|
||||
if (sigdata)
|
||||
(*desc->unload_sigdata)(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
signal->desc = desc;
|
||||
signal->sigdata = sigdata;
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUH *make_duh(
|
||||
long length,
|
||||
int n_tags,
|
||||
const char *const tags[][2],
|
||||
int n_signals,
|
||||
DUH_SIGTYPE_DESC *desc[],
|
||||
sigdata_t *sigdata[]
|
||||
)
|
||||
{
|
||||
DUH *duh = malloc(sizeof(*duh));
|
||||
int i;
|
||||
int fail;
|
||||
|
||||
if (duh) {
|
||||
duh->n_signals = n_signals;
|
||||
|
||||
duh->signal = malloc(n_signals * sizeof(*duh->signal));
|
||||
|
||||
if (!duh->signal) {
|
||||
free(duh);
|
||||
duh = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!duh) {
|
||||
for (i = 0; i < n_signals; i++)
|
||||
if (desc[i]->unload_sigdata)
|
||||
if (sigdata[i])
|
||||
(*desc[i]->unload_sigdata)(sigdata[i]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
duh->n_tags = 0;
|
||||
duh->tag = NULL;
|
||||
|
||||
fail = 0;
|
||||
|
||||
for (i = 0; i < n_signals; i++) {
|
||||
duh->signal[i] = make_signal(desc[i], sigdata[i]);
|
||||
if (!duh->signal[i])
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
unload_duh(duh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
duh->length = length;
|
||||
|
||||
{
|
||||
int mem = n_tags * 2; /* account for NUL terminators here */
|
||||
char *ptr;
|
||||
|
||||
for (i = 0; i < n_tags; i++)
|
||||
mem += strlen(tags[i][0]) + strlen(tags[i][1]);
|
||||
|
||||
if (mem <= 0) return duh;
|
||||
|
||||
duh->tag = malloc(n_tags * sizeof(*duh->tag));
|
||||
if (!duh->tag) return duh;
|
||||
duh->tag[0][0] = malloc(mem);
|
||||
if (!duh->tag[0][0]) {
|
||||
free(duh->tag);
|
||||
duh->tag = NULL;
|
||||
return duh;
|
||||
}
|
||||
duh->n_tags = n_tags;
|
||||
ptr = duh->tag[0][0];
|
||||
for (i = 0; i < n_tags; i++) {
|
||||
duh->tag[i][0] = ptr;
|
||||
strcpy(ptr, tags[i][0]);
|
||||
ptr += strlen(tags[i][0]) + 1;
|
||||
duh->tag[i][1] = ptr;
|
||||
strcpy(ptr, tags[i][1]);
|
||||
ptr += strlen(tags[i][1]) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return duh;
|
||||
}
|
||||
|
||||
int duh_add_signal(DUH *duh, DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata)
|
||||
{
|
||||
DUH_SIGNAL **signal;
|
||||
|
||||
if ( !duh || !desc || !sigdata ) return -1;
|
||||
|
||||
signal = ( DUH_SIGNAL ** ) realloc( duh->signal, ( duh->n_signals + 1 ) * sizeof( *duh->signal ) );
|
||||
if ( !signal ) return -1;
|
||||
duh->signal = signal;
|
||||
|
||||
memmove( signal + 1, signal, duh->n_signals * sizeof( *signal ) );
|
||||
duh->n_signals++;
|
||||
|
||||
signal[ 0 ] = make_signal( desc, sigdata );
|
||||
if ( !signal[ 0 ] ) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,44 +1,58 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* rawsig.c - Function to retrieve raw signal / / \ \
|
||||
* data from a DUH provided you know | < / \_
|
||||
* what type of signal it is. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
/* You have to specify the type of sigdata, proving you know what to do with
|
||||
* the pointer. If you get it wrong, you can expect NULL back.
|
||||
*/
|
||||
sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type)
|
||||
{
|
||||
DUH_SIGNAL *signal;
|
||||
|
||||
if (!duh) return NULL;
|
||||
|
||||
if ((unsigned int)sig >= (unsigned int)duh->n_signals) return NULL;
|
||||
|
||||
signal = duh->signal[sig];
|
||||
|
||||
if (signal && signal->desc->type == type)
|
||||
return signal->sigdata;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* rawsig.c - Function to retrieve raw signal / / \ \
|
||||
* data from a DUH provided you know | < / \_
|
||||
* what type of signal it is. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
/* You have to specify the type of sigdata, proving you know what to do with
|
||||
* the pointer. If you get it wrong, you can expect NULL back.
|
||||
*/
|
||||
sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type)
|
||||
{
|
||||
int i;
|
||||
DUH_SIGNAL *signal;
|
||||
|
||||
if (!duh) return NULL;
|
||||
|
||||
if ( sig >= 0 )
|
||||
{
|
||||
if ((unsigned int)sig >= (unsigned int)duh->n_signals) return NULL;
|
||||
|
||||
signal = duh->signal[sig];
|
||||
|
||||
if (signal && signal->desc->type == type)
|
||||
return signal->sigdata;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( i = 0; i < duh->n_signals; i++ )
|
||||
{
|
||||
signal = duh->signal[i];
|
||||
|
||||
if (signal && signal->desc->type == type)
|
||||
return signal->sigdata;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,107 +1,107 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readduh.c - Code to read a DUH from an open / / \ \
|
||||
* file. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
static DUH_SIGNAL *read_signal(DUH *duh, DUMBFILE *f)
|
||||
{
|
||||
DUH_SIGNAL *signal;
|
||||
long type;
|
||||
|
||||
signal = malloc(sizeof(*signal));
|
||||
|
||||
if (!signal)
|
||||
return NULL;
|
||||
|
||||
type = dumbfile_mgetl(f);
|
||||
if (dumbfile_error(f)) {
|
||||
free(signal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
signal->desc = _dumb_get_sigtype_desc(type);
|
||||
if (!signal->desc) {
|
||||
free(signal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (signal->desc->load_sigdata) {
|
||||
signal->sigdata = (*signal->desc->load_sigdata)(duh, f);
|
||||
if (!signal->sigdata) {
|
||||
free(signal);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
signal->sigdata = NULL;
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* read_duh(): reads a DUH from an already open DUMBFILE, and returns its
|
||||
* pointer, or null on error. The file is not closed.
|
||||
*/
|
||||
DUH *read_duh(DUMBFILE *f)
|
||||
{
|
||||
DUH *duh;
|
||||
int i;
|
||||
|
||||
if (dumbfile_mgetl(f) != DUH_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
duh = malloc(sizeof(*duh));
|
||||
if (!duh)
|
||||
return NULL;
|
||||
|
||||
duh->length = dumbfile_igetl(f);
|
||||
if (dumbfile_error(f) || duh->length <= 0) {
|
||||
free(duh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
duh->n_signals = dumbfile_igetl(f);
|
||||
if (dumbfile_error(f) || duh->n_signals <= 0) {
|
||||
free(duh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
duh->signal = malloc(sizeof(*duh->signal) * duh->n_signals);
|
||||
if (!duh->signal) {
|
||||
free(duh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < duh->n_signals; i++)
|
||||
duh->signal[i] = NULL;
|
||||
|
||||
for (i = 0; i < duh->n_signals; i++) {
|
||||
if (!(duh->signal[i] = read_signal(duh, f))) {
|
||||
unload_duh(duh);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readduh.c - Code to read a DUH from an open / / \ \
|
||||
* file. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
static DUH_SIGNAL *read_signal(DUH *duh, DUMBFILE *f)
|
||||
{
|
||||
DUH_SIGNAL *signal;
|
||||
long type;
|
||||
|
||||
signal = malloc(sizeof(*signal));
|
||||
|
||||
if (!signal)
|
||||
return NULL;
|
||||
|
||||
type = dumbfile_mgetl(f);
|
||||
if (dumbfile_error(f)) {
|
||||
free(signal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
signal->desc = _dumb_get_sigtype_desc(type);
|
||||
if (!signal->desc) {
|
||||
free(signal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (signal->desc->load_sigdata) {
|
||||
signal->sigdata = (*signal->desc->load_sigdata)(duh, f);
|
||||
if (!signal->sigdata) {
|
||||
free(signal);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
signal->sigdata = NULL;
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* read_duh(): reads a DUH from an already open DUMBFILE, and returns its
|
||||
* pointer, or null on error. The file is not closed.
|
||||
*/
|
||||
DUH *read_duh(DUMBFILE *f)
|
||||
{
|
||||
DUH *duh;
|
||||
int i;
|
||||
|
||||
if (dumbfile_mgetl(f) != DUH_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
duh = malloc(sizeof(*duh));
|
||||
if (!duh)
|
||||
return NULL;
|
||||
|
||||
duh->length = dumbfile_igetl(f);
|
||||
if (dumbfile_error(f) || duh->length <= 0) {
|
||||
free(duh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
duh->n_signals = dumbfile_igetl(f);
|
||||
if (dumbfile_error(f) || duh->n_signals <= 0) {
|
||||
free(duh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
duh->signal = malloc(sizeof(*duh->signal) * duh->n_signals);
|
||||
if (!duh->signal) {
|
||||
free(duh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < duh->n_signals; i++)
|
||||
duh->signal[i] = NULL;
|
||||
|
||||
for (i = 0; i < duh->n_signals; i++) {
|
||||
if (!(duh->signal[i] = read_signal(duh, f))) {
|
||||
unload_duh(duh);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return duh;
|
||||
}
|
||||
|
|
|
@ -1,104 +1,104 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* register.c - Signal type registration. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
static DUH_SIGTYPE_DESC_LINK *sigtype_desc = NULL;
|
||||
static DUH_SIGTYPE_DESC_LINK **sigtype_desc_tail = &sigtype_desc;
|
||||
|
||||
|
||||
|
||||
/* destroy_sigtypes(): frees all memory allocated while registering signal
|
||||
* types. This function is set up to be called by dumb_exit().
|
||||
*/
|
||||
static void destroy_sigtypes(void)
|
||||
{
|
||||
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc, *next;
|
||||
sigtype_desc = NULL;
|
||||
sigtype_desc_tail = &sigtype_desc;
|
||||
|
||||
while (desc_link) {
|
||||
next = desc_link->next;
|
||||
free(desc_link);
|
||||
desc_link = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* dumb_register_sigtype(): registers a new signal type with DUMB. The signal
|
||||
* type is identified by a four-character string (e.g. "WAVE"), which you can
|
||||
* encode using the the DUMB_ID() macro (e.g. DUMB_ID('W','A','V','E')). The
|
||||
* signal's behaviour is defined by four functions, whose pointers you pass
|
||||
* here. See the documentation for details.
|
||||
*
|
||||
* If a DUH tries to use a signal that has not been registered using this
|
||||
* function, then the library will fail to load the DUH.
|
||||
*/
|
||||
void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc)
|
||||
{
|
||||
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc;
|
||||
|
||||
ASSERT((desc->load_sigdata && desc->unload_sigdata) || (!desc->load_sigdata && !desc->unload_sigdata));
|
||||
ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer));
|
||||
ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample);
|
||||
|
||||
if (desc_link) {
|
||||
do {
|
||||
if (desc_link->desc->type == desc->type) {
|
||||
desc_link->desc = desc;
|
||||
return;
|
||||
}
|
||||
desc_link = desc_link->next;
|
||||
} while (desc_link);
|
||||
} else
|
||||
dumb_atexit(&destroy_sigtypes);
|
||||
|
||||
desc_link = *sigtype_desc_tail = malloc(sizeof(DUH_SIGTYPE_DESC_LINK));
|
||||
|
||||
if (!desc_link)
|
||||
return;
|
||||
|
||||
desc_link->next = NULL;
|
||||
sigtype_desc_tail = &desc_link->next;
|
||||
|
||||
desc_link->desc = desc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _dumb_get_sigtype_desc(): searches the registered functions for a signal
|
||||
* type matching the parameter. If such a sigtype is found, it returns a
|
||||
* pointer to a sigtype descriptor containing the necessary functions to
|
||||
* manage the signal. If none is found, it returns NULL.
|
||||
*/
|
||||
DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type)
|
||||
{
|
||||
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc;
|
||||
|
||||
while (desc_link && desc_link->desc->type != type)
|
||||
desc_link = desc_link->next;
|
||||
|
||||
return desc_link ? desc_link->desc : NULL;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* register.c - Signal type registration. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
static DUH_SIGTYPE_DESC_LINK *sigtype_desc = NULL;
|
||||
static DUH_SIGTYPE_DESC_LINK **sigtype_desc_tail = &sigtype_desc;
|
||||
|
||||
|
||||
|
||||
/* destroy_sigtypes(): frees all memory allocated while registering signal
|
||||
* types. This function is set up to be called by dumb_exit().
|
||||
*/
|
||||
static void destroy_sigtypes(void)
|
||||
{
|
||||
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc, *next;
|
||||
sigtype_desc = NULL;
|
||||
sigtype_desc_tail = &sigtype_desc;
|
||||
|
||||
while (desc_link) {
|
||||
next = desc_link->next;
|
||||
free(desc_link);
|
||||
desc_link = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* dumb_register_sigtype(): registers a new signal type with DUMB. The signal
|
||||
* type is identified by a four-character string (e.g. "WAVE"), which you can
|
||||
* encode using the the DUMB_ID() macro (e.g. DUMB_ID('W','A','V','E')). The
|
||||
* signal's behaviour is defined by four functions, whose pointers you pass
|
||||
* here. See the documentation for details.
|
||||
*
|
||||
* If a DUH tries to use a signal that has not been registered using this
|
||||
* function, then the library will fail to load the DUH.
|
||||
*/
|
||||
void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc)
|
||||
{
|
||||
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc;
|
||||
|
||||
ASSERT((desc->load_sigdata && desc->unload_sigdata) || (!desc->load_sigdata && !desc->unload_sigdata));
|
||||
ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer));
|
||||
ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample);
|
||||
|
||||
if (desc_link) {
|
||||
do {
|
||||
if (desc_link->desc->type == desc->type) {
|
||||
desc_link->desc = desc;
|
||||
return;
|
||||
}
|
||||
desc_link = desc_link->next;
|
||||
} while (desc_link);
|
||||
} else
|
||||
dumb_atexit(&destroy_sigtypes);
|
||||
|
||||
desc_link = *sigtype_desc_tail = malloc(sizeof(DUH_SIGTYPE_DESC_LINK));
|
||||
|
||||
if (!desc_link)
|
||||
return;
|
||||
|
||||
desc_link->next = NULL;
|
||||
sigtype_desc_tail = &desc_link->next;
|
||||
|
||||
desc_link->desc = desc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _dumb_get_sigtype_desc(): searches the registered functions for a signal
|
||||
* type matching the parameter. If such a sigtype is found, it returns a
|
||||
* pointer to a sigtype descriptor containing the necessary functions to
|
||||
* manage the signal. If none is found, it returns NULL.
|
||||
*/
|
||||
DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type)
|
||||
{
|
||||
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc;
|
||||
|
||||
while (desc_link && desc_link->desc->type != type)
|
||||
desc_link = desc_link->next;
|
||||
|
||||
return desc_link ? desc_link->desc : NULL;
|
||||
}
|
||||
|
|
|
@ -1,184 +1,184 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* rendduh.c - Functions for rendering a DUH into / / \ \
|
||||
* an end-user sample format. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
/* On the x86, we can use some tricks to speed stuff up */
|
||||
#if (defined _MSC_VER) || (defined __DJGPP__) || (defined __MINGW__)
|
||||
// Can't we detect Linux and other x86 platforms here? :/
|
||||
|
||||
#define FAST_MID(var, min, max) { \
|
||||
var -= (min); \
|
||||
var &= (~var) >> (sizeof(var) * CHAR_BIT - 1); \
|
||||
var += (min); \
|
||||
var -= (max); \
|
||||
var &= var >> (sizeof(var) * CHAR_BIT - 1); \
|
||||
var += (max); \
|
||||
}
|
||||
|
||||
#define CONVERT8(src, pos, signconv) { \
|
||||
signed int f = (src + 0x8000) >> 16; \
|
||||
FAST_MID(f, -128, 127); \
|
||||
((char*)sptr)[pos] = (char)f ^ signconv; \
|
||||
}
|
||||
|
||||
#define CONVERT16(src, pos, signconv) { \
|
||||
signed int f = (src + 0x80) >> 8; \
|
||||
FAST_MID(f, -32768, 32767); \
|
||||
((short*)sptr)[pos] = (short)(f ^ signconv); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define CONVERT8(src, pos, signconv) \
|
||||
{ \
|
||||
signed int f = (src + 0x8000) >> 16; \
|
||||
f = MID(-128, f, 127); \
|
||||
((char *)sptr)[pos] = (char)f ^ signconv; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CONVERT16(src, pos, signconv) \
|
||||
{ \
|
||||
signed int f = (src + 0x80) >> 8; \
|
||||
f = MID(-32768, f, 32767); \
|
||||
((short *)sptr)[pos] = (short)(f ^ signconv); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos)
|
||||
{
|
||||
return duh_start_sigrenderer(duh, 0, n_channels, pos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long duh_render(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
int bits, int unsign,
|
||||
float volume, float delta,
|
||||
long size, void *sptr
|
||||
)
|
||||
{
|
||||
long n;
|
||||
|
||||
sample_t **sampptr;
|
||||
|
||||
int n_channels;
|
||||
|
||||
ASSERT(bits == 8 || bits == 16);
|
||||
ASSERT(sptr);
|
||||
|
||||
if (!sigrenderer)
|
||||
return 0;
|
||||
|
||||
n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
|
||||
|
||||
ASSERT(n_channels > 0);
|
||||
/* This restriction will be removed when need be. At the moment, tightly
|
||||
* optimised loops exist for exactly one or two channels.
|
||||
*/
|
||||
ASSERT(n_channels <= 2);
|
||||
|
||||
sampptr = allocate_sample_buffer(n_channels, size);
|
||||
|
||||
if (!sampptr)
|
||||
return 0;
|
||||
|
||||
dumb_silence(sampptr[0], n_channels * size);
|
||||
|
||||
size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
|
||||
|
||||
if (bits == 16) {
|
||||
int signconv = unsign ? 0x8000 : 0x0000;
|
||||
|
||||
for (n = 0; n < size * n_channels; n++) {
|
||||
CONVERT16(sampptr[0][n], n, signconv);
|
||||
}
|
||||
} else {
|
||||
char signconv = unsign ? 0x80 : 0x00;
|
||||
|
||||
for (n = 0; n < size * n_channels; n++) {
|
||||
CONVERT8(sampptr[0][n], n, signconv);
|
||||
}
|
||||
}
|
||||
|
||||
destroy_sample_buffer(sampptr);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr)
|
||||
{
|
||||
return duh_sigrenderer_get_n_channels(dr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
long duh_renderer_get_position(DUH_SIGRENDERER *dr)
|
||||
{
|
||||
return duh_sigrenderer_get_position(dr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
void duh_end_renderer(DUH_SIGRENDERER *dr)
|
||||
{
|
||||
duh_end_sigrenderer(dr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer)
|
||||
{
|
||||
return sigrenderer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr)
|
||||
{
|
||||
return dr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr)
|
||||
{
|
||||
return dr;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* rendduh.c - Functions for rendering a DUH into / / \ \
|
||||
* an end-user sample format. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
/* On the x86, we can use some tricks to speed stuff up */
|
||||
#if (defined _MSC_VER) || (defined __DJGPP__) || (defined __MINGW__)
|
||||
// Can't we detect Linux and other x86 platforms here? :/
|
||||
|
||||
#define FAST_MID(var, min, max) { \
|
||||
var -= (min); \
|
||||
var &= (~var) >> (sizeof(var) * CHAR_BIT - 1); \
|
||||
var += (min); \
|
||||
var -= (max); \
|
||||
var &= var >> (sizeof(var) * CHAR_BIT - 1); \
|
||||
var += (max); \
|
||||
}
|
||||
|
||||
#define CONVERT8(src, pos, signconv) { \
|
||||
signed int f = (src + 0x8000) >> 16; \
|
||||
FAST_MID(f, -128, 127); \
|
||||
((char*)sptr)[pos] = (char)f ^ signconv; \
|
||||
}
|
||||
|
||||
#define CONVERT16(src, pos, signconv) { \
|
||||
signed int f = (src + 0x80) >> 8; \
|
||||
FAST_MID(f, -32768, 32767); \
|
||||
((short*)sptr)[pos] = (short)(f ^ signconv); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define CONVERT8(src, pos, signconv) \
|
||||
{ \
|
||||
signed int f = (src + 0x8000) >> 16; \
|
||||
f = MID(-128, f, 127); \
|
||||
((char *)sptr)[pos] = (char)f ^ signconv; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CONVERT16(src, pos, signconv) \
|
||||
{ \
|
||||
signed int f = (src + 0x80) >> 8; \
|
||||
f = MID(-32768, f, 32767); \
|
||||
((short *)sptr)[pos] = (short)(f ^ signconv); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos)
|
||||
{
|
||||
return duh_start_sigrenderer(duh, 0, n_channels, pos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long duh_render(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
int bits, int unsign,
|
||||
float volume, float delta,
|
||||
long size, void *sptr
|
||||
)
|
||||
{
|
||||
long n;
|
||||
|
||||
sample_t **sampptr;
|
||||
|
||||
int n_channels;
|
||||
|
||||
ASSERT(bits == 8 || bits == 16);
|
||||
ASSERT(sptr);
|
||||
|
||||
if (!sigrenderer)
|
||||
return 0;
|
||||
|
||||
n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
|
||||
|
||||
ASSERT(n_channels > 0);
|
||||
/* This restriction will be removed when need be. At the moment, tightly
|
||||
* optimised loops exist for exactly one or two channels.
|
||||
*/
|
||||
ASSERT(n_channels <= 2);
|
||||
|
||||
sampptr = allocate_sample_buffer(n_channels, size);
|
||||
|
||||
if (!sampptr)
|
||||
return 0;
|
||||
|
||||
dumb_silence(sampptr[0], n_channels * size);
|
||||
|
||||
size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
|
||||
|
||||
if (bits == 16) {
|
||||
int signconv = unsign ? 0x8000 : 0x0000;
|
||||
|
||||
for (n = 0; n < size * n_channels; n++) {
|
||||
CONVERT16(sampptr[0][n], n, signconv);
|
||||
}
|
||||
} else {
|
||||
char signconv = unsign ? 0x80 : 0x00;
|
||||
|
||||
for (n = 0; n < size * n_channels; n++) {
|
||||
CONVERT8(sampptr[0][n], n, signconv);
|
||||
}
|
||||
}
|
||||
|
||||
destroy_sample_buffer(sampptr);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr)
|
||||
{
|
||||
return duh_sigrenderer_get_n_channels(dr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
long duh_renderer_get_position(DUH_SIGRENDERER *dr)
|
||||
{
|
||||
return duh_sigrenderer_get_position(dr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
void duh_end_renderer(DUH_SIGRENDERER *dr)
|
||||
{
|
||||
duh_end_sigrenderer(dr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer)
|
||||
{
|
||||
return sigrenderer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr)
|
||||
{
|
||||
return dr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr)
|
||||
{
|
||||
return dr;
|
||||
}
|
||||
|
|
|
@ -1,344 +1,352 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* rendsig.c - Wrappers to render samples from / / \ \
|
||||
* the signals in a DUH. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
struct DUH_SIGRENDERER
|
||||
{
|
||||
DUH_SIGTYPE_DESC *desc;
|
||||
|
||||
sigrenderer_t *sigrenderer;
|
||||
|
||||
int n_channels;
|
||||
|
||||
long pos;
|
||||
int subpos;
|
||||
|
||||
DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback;
|
||||
void *callback_data;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos)
|
||||
{
|
||||
DUH_SIGRENDERER *sigrenderer;
|
||||
|
||||
DUH_SIGNAL *signal;
|
||||
DUH_START_SIGRENDERER proc;
|
||||
|
||||
if (!duh)
|
||||
return NULL;
|
||||
|
||||
if ((unsigned int)sig >= (unsigned int)duh->n_signals)
|
||||
return NULL;
|
||||
|
||||
signal = duh->signal[sig];
|
||||
if (!signal)
|
||||
return NULL;
|
||||
|
||||
sigrenderer = malloc(sizeof(*sigrenderer));
|
||||
if (!sigrenderer)
|
||||
return NULL;
|
||||
|
||||
sigrenderer->desc = signal->desc;
|
||||
|
||||
proc = sigrenderer->desc->start_sigrenderer;
|
||||
|
||||
if (proc) {
|
||||
duh->signal[sig] = NULL;
|
||||
sigrenderer->sigrenderer = (*proc)(duh, signal->sigdata, n_channels, pos);
|
||||
duh->signal[sig] = signal;
|
||||
|
||||
if (!sigrenderer->sigrenderer) {
|
||||
free(sigrenderer);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
sigrenderer->sigrenderer = NULL;
|
||||
|
||||
sigrenderer->n_channels = n_channels;
|
||||
|
||||
sigrenderer->pos = pos;
|
||||
sigrenderer->subpos = 0;
|
||||
|
||||
sigrenderer->callback = NULL;
|
||||
|
||||
return sigrenderer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
void duh_sigrenderer_set_callback(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
DUH_SIGRENDERER_CALLBACK callback, void *data
|
||||
)
|
||||
{
|
||||
(void)sigrenderer;
|
||||
(void)callback;
|
||||
(void)data;
|
||||
fprintf(stderr,
|
||||
"Call to deprecated function duh_sigrenderer_set_callback(). The callback\n"
|
||||
"was not installed. See dumb/docs/deprec.txt for how to fix this.\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_sigrenderer_set_analyser_callback(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data
|
||||
)
|
||||
{
|
||||
(void)sigrenderer;
|
||||
(void)callback;
|
||||
(void)data;
|
||||
fprintf(stderr,
|
||||
"Call to deprecated function duh_sigrenderer_set_analyser_callback(). The\n"
|
||||
"callback was not installed. See dumb/docs/deprec.txt for how to fix this.\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_sigrenderer_set_sample_analyser_callback(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data
|
||||
)
|
||||
{
|
||||
if (sigrenderer) {
|
||||
sigrenderer->callback = callback;
|
||||
sigrenderer->callback_data = data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer)
|
||||
{
|
||||
return sigrenderer ? sigrenderer->n_channels : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer)
|
||||
{
|
||||
return sigrenderer ? sigrenderer->pos : -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_sigrenderer_set_sigparam(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
unsigned char id, long value
|
||||
)
|
||||
{
|
||||
DUH_SIGRENDERER_SET_SIGPARAM proc;
|
||||
|
||||
if (!sigrenderer) return;
|
||||
|
||||
proc = sigrenderer->desc->sigrenderer_set_sigparam;
|
||||
if (proc)
|
||||
(*proc)(sigrenderer->sigrenderer, id, value);
|
||||
else
|
||||
TRACE("Parameter #%d = %ld for signal %c%c%c%c, which does not take parameters.\n",
|
||||
(int)id,
|
||||
value,
|
||||
(int)(sigrenderer->desc->type >> 24),
|
||||
(int)(sigrenderer->desc->type >> 16),
|
||||
(int)(sigrenderer->desc->type >> 8),
|
||||
(int)(sigrenderer->desc->type));
|
||||
}
|
||||
|
||||
|
||||
|
||||
long duh_sigrenderer_generate_samples(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
float volume, float delta,
|
||||
long size, sample_t **samples
|
||||
)
|
||||
{
|
||||
long rendered;
|
||||
LONG_LONG t;
|
||||
|
||||
if (!sigrenderer) return 0;
|
||||
|
||||
rendered = (*sigrenderer->desc->sigrenderer_generate_samples)
|
||||
(sigrenderer->sigrenderer, volume, delta, size, samples);
|
||||
|
||||
if (rendered) {
|
||||
if (sigrenderer->callback)
|
||||
(*sigrenderer->callback)(sigrenderer->callback_data,
|
||||
(const sample_t *const *)samples, sigrenderer->n_channels, rendered);
|
||||
|
||||
t = sigrenderer->subpos + (LONG_LONG)(delta * 65536.0 + 0.5) * rendered;
|
||||
|
||||
sigrenderer->pos += (long)(t >> 16);
|
||||
sigrenderer->subpos = (int)t & 65535;
|
||||
}
|
||||
|
||||
return rendered;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
long duh_sigrenderer_get_samples(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
float volume, float delta,
|
||||
long size, sample_t **samples
|
||||
)
|
||||
{
|
||||
sample_t **s;
|
||||
long rendered;
|
||||
long i;
|
||||
int j;
|
||||
if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL);
|
||||
s = allocate_sample_buffer(sigrenderer->n_channels, size);
|
||||
if (!s) return 0;
|
||||
dumb_silence(s[0], sigrenderer->n_channels * size);
|
||||
rendered = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, s);
|
||||
for (j = 0; j < sigrenderer->n_channels; j++)
|
||||
for (i = 0; i < rendered; i++)
|
||||
samples[j][i] += s[0][i*sigrenderer->n_channels+j];
|
||||
destroy_sample_buffer(s);
|
||||
return rendered;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
long duh_render_signal(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
float volume, float delta,
|
||||
long size, sample_t **samples
|
||||
)
|
||||
{
|
||||
sample_t **s;
|
||||
long rendered;
|
||||
long i;
|
||||
int j;
|
||||
if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL);
|
||||
s = allocate_sample_buffer(sigrenderer->n_channels, size);
|
||||
if (!s) return 0;
|
||||
dumb_silence(s[0], sigrenderer->n_channels * size);
|
||||
rendered = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, s);
|
||||
for (j = 0; j < sigrenderer->n_channels; j++)
|
||||
for (i = 0; i < rendered; i++)
|
||||
samples[j][i] += s[0][i*sigrenderer->n_channels+j] >> 8;
|
||||
destroy_sample_buffer(s);
|
||||
return rendered;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples)
|
||||
{
|
||||
if (sigrenderer)
|
||||
(*sigrenderer->desc->sigrenderer_get_current_sample)(sigrenderer->sigrenderer, volume, samples);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer)
|
||||
{
|
||||
if (sigrenderer) {
|
||||
if (sigrenderer->desc->end_sigrenderer)
|
||||
if (sigrenderer->sigrenderer)
|
||||
(*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
|
||||
|
||||
free(sigrenderer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos)
|
||||
{
|
||||
DUH_SIGRENDERER *sigrenderer;
|
||||
|
||||
if (desc->start_sigrenderer && !vsigrenderer) return NULL;
|
||||
|
||||
sigrenderer = malloc(sizeof(*sigrenderer));
|
||||
if (!sigrenderer) {
|
||||
if (desc->end_sigrenderer)
|
||||
if (vsigrenderer)
|
||||
(*desc->end_sigrenderer)(vsigrenderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigrenderer->desc = desc;
|
||||
sigrenderer->sigrenderer = vsigrenderer;
|
||||
|
||||
sigrenderer->n_channels = n_channels;
|
||||
|
||||
sigrenderer->pos = pos;
|
||||
sigrenderer->subpos = 0;
|
||||
|
||||
sigrenderer->callback = NULL;
|
||||
|
||||
return sigrenderer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
|
||||
{
|
||||
if (sigrenderer && sigrenderer->desc->type == type)
|
||||
return sigrenderer->sigrenderer;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
// This function is disabled because we don't know whether we want to destroy
|
||||
// the sigrenderer if the type doesn't match. We don't even know if we need
|
||||
// the function at all. Who would want to keep an IT_SIGRENDERER (for
|
||||
// instance) without keeping the DUH_SIGRENDERER?
|
||||
sigrenderer_t *duh_decompose_to_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
|
||||
{
|
||||
if (sigrenderer && sigrenderer->desc->type == type) {
|
||||
|
||||
|
||||
|
||||
if (sigrenderer) {
|
||||
if (sigrenderer->desc->end_sigrenderer)
|
||||
if (sigrenderer->sigrenderer)
|
||||
(*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
|
||||
|
||||
free(sigrenderer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return sigrenderer->sigrenderer;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* rendsig.c - Wrappers to render samples from / / \ \
|
||||
* the signals in a DUH. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
struct DUH_SIGRENDERER
|
||||
{
|
||||
DUH_SIGTYPE_DESC *desc;
|
||||
|
||||
sigrenderer_t *sigrenderer;
|
||||
|
||||
int n_channels;
|
||||
|
||||
long pos;
|
||||
int subpos;
|
||||
|
||||
DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback;
|
||||
void *callback_data;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos)
|
||||
{
|
||||
DUH_SIGRENDERER *sigrenderer;
|
||||
|
||||
DUH_SIGNAL *signal;
|
||||
DUH_START_SIGRENDERER proc;
|
||||
|
||||
if (!duh)
|
||||
return NULL;
|
||||
|
||||
if ((unsigned int)sig >= (unsigned int)duh->n_signals)
|
||||
return NULL;
|
||||
|
||||
signal = duh->signal[sig];
|
||||
if (!signal)
|
||||
return NULL;
|
||||
|
||||
sigrenderer = malloc(sizeof(*sigrenderer));
|
||||
if (!sigrenderer)
|
||||
return NULL;
|
||||
|
||||
sigrenderer->desc = signal->desc;
|
||||
|
||||
proc = sigrenderer->desc->start_sigrenderer;
|
||||
|
||||
if (proc) {
|
||||
duh->signal[sig] = NULL;
|
||||
sigrenderer->sigrenderer = (*proc)(duh, signal->sigdata, n_channels, pos);
|
||||
duh->signal[sig] = signal;
|
||||
|
||||
if (!sigrenderer->sigrenderer) {
|
||||
free(sigrenderer);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
sigrenderer->sigrenderer = NULL;
|
||||
|
||||
sigrenderer->n_channels = n_channels;
|
||||
|
||||
sigrenderer->pos = pos;
|
||||
sigrenderer->subpos = 0;
|
||||
|
||||
sigrenderer->callback = NULL;
|
||||
|
||||
return sigrenderer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
void duh_sigrenderer_set_callback(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
DUH_SIGRENDERER_CALLBACK callback, void *data
|
||||
)
|
||||
{
|
||||
(void)sigrenderer;
|
||||
(void)callback;
|
||||
(void)data;
|
||||
/*fprintf(stderr,
|
||||
"Call to deprecated function duh_sigrenderer_set_callback(). The callback\n"
|
||||
"was not installed. See dumb/docs/deprec.txt for how to fix this.\n");*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_sigrenderer_set_analyser_callback(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data
|
||||
)
|
||||
{
|
||||
(void)sigrenderer;
|
||||
(void)callback;
|
||||
(void)data;
|
||||
fprintf(stderr,
|
||||
"Call to deprecated function duh_sigrenderer_set_analyser_callback(). The\n"
|
||||
"callback was not installed. See dumb/docs/deprec.txt for how to fix this.\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_sigrenderer_set_sample_analyser_callback(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data
|
||||
)
|
||||
{
|
||||
if (sigrenderer) {
|
||||
sigrenderer->callback = callback;
|
||||
sigrenderer->callback_data = data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer)
|
||||
{
|
||||
return sigrenderer ? sigrenderer->n_channels : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer)
|
||||
{
|
||||
DUH_SIGRENDERER_GET_POSITION proc;
|
||||
|
||||
if (!sigrenderer) return -1;
|
||||
|
||||
proc = sigrenderer->desc->sigrenderer_get_position;
|
||||
if (proc)
|
||||
return (*proc)(sigrenderer->sigrenderer);
|
||||
else
|
||||
return sigrenderer->pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_sigrenderer_set_sigparam(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
unsigned char id, long value
|
||||
)
|
||||
{
|
||||
DUH_SIGRENDERER_SET_SIGPARAM proc;
|
||||
|
||||
if (!sigrenderer) return;
|
||||
|
||||
proc = sigrenderer->desc->sigrenderer_set_sigparam;
|
||||
if (proc)
|
||||
(*proc)(sigrenderer->sigrenderer, id, value);
|
||||
else
|
||||
TRACE("Parameter #%d = %ld for signal %c%c%c%c, which does not take parameters.\n",
|
||||
(int)id,
|
||||
value,
|
||||
(int)(sigrenderer->desc->type >> 24),
|
||||
(int)(sigrenderer->desc->type >> 16),
|
||||
(int)(sigrenderer->desc->type >> 8),
|
||||
(int)(sigrenderer->desc->type));
|
||||
}
|
||||
|
||||
|
||||
|
||||
long duh_sigrenderer_generate_samples(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
float volume, float delta,
|
||||
long size, sample_t **samples
|
||||
)
|
||||
{
|
||||
long rendered;
|
||||
LONG_LONG t;
|
||||
|
||||
if (!sigrenderer) return 0;
|
||||
|
||||
rendered = (*sigrenderer->desc->sigrenderer_generate_samples)
|
||||
(sigrenderer->sigrenderer, volume, delta, size, samples);
|
||||
|
||||
if (rendered) {
|
||||
if (sigrenderer->callback)
|
||||
(*sigrenderer->callback)(sigrenderer->callback_data,
|
||||
(const sample_t *const *)samples, sigrenderer->n_channels, rendered);
|
||||
|
||||
t = sigrenderer->subpos + (LONG_LONG)(delta * 65536.0 + 0.5) * rendered;
|
||||
|
||||
sigrenderer->pos += (long)(t >> 16);
|
||||
sigrenderer->subpos = (int)t & 65535;
|
||||
}
|
||||
|
||||
return rendered;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
long duh_sigrenderer_get_samples(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
float volume, float delta,
|
||||
long size, sample_t **samples
|
||||
)
|
||||
{
|
||||
sample_t **s;
|
||||
long rendered;
|
||||
long i;
|
||||
int j;
|
||||
if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL);
|
||||
s = allocate_sample_buffer(sigrenderer->n_channels, size);
|
||||
if (!s) return 0;
|
||||
dumb_silence(s[0], sigrenderer->n_channels * size);
|
||||
rendered = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, s);
|
||||
for (j = 0; j < sigrenderer->n_channels; j++)
|
||||
for (i = 0; i < rendered; i++)
|
||||
samples[j][i] += s[0][i*sigrenderer->n_channels+j];
|
||||
destroy_sample_buffer(s);
|
||||
return rendered;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
long duh_render_signal(
|
||||
DUH_SIGRENDERER *sigrenderer,
|
||||
float volume, float delta,
|
||||
long size, sample_t **samples
|
||||
)
|
||||
{
|
||||
sample_t **s;
|
||||
long rendered;
|
||||
long i;
|
||||
int j;
|
||||
if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL);
|
||||
s = allocate_sample_buffer(sigrenderer->n_channels, size);
|
||||
if (!s) return 0;
|
||||
dumb_silence(s[0], sigrenderer->n_channels * size);
|
||||
rendered = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, s);
|
||||
for (j = 0; j < sigrenderer->n_channels; j++)
|
||||
for (i = 0; i < rendered; i++)
|
||||
samples[j][i] += s[0][i*sigrenderer->n_channels+j] >> 8;
|
||||
destroy_sample_buffer(s);
|
||||
return rendered;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples)
|
||||
{
|
||||
if (sigrenderer)
|
||||
(*sigrenderer->desc->sigrenderer_get_current_sample)(sigrenderer->sigrenderer, volume, samples);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer)
|
||||
{
|
||||
if (sigrenderer) {
|
||||
if (sigrenderer->desc->end_sigrenderer)
|
||||
if (sigrenderer->sigrenderer)
|
||||
(*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
|
||||
|
||||
free(sigrenderer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos)
|
||||
{
|
||||
DUH_SIGRENDERER *sigrenderer;
|
||||
|
||||
if (desc->start_sigrenderer && !vsigrenderer) return NULL;
|
||||
|
||||
sigrenderer = malloc(sizeof(*sigrenderer));
|
||||
if (!sigrenderer) {
|
||||
if (desc->end_sigrenderer)
|
||||
if (vsigrenderer)
|
||||
(*desc->end_sigrenderer)(vsigrenderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigrenderer->desc = desc;
|
||||
sigrenderer->sigrenderer = vsigrenderer;
|
||||
|
||||
sigrenderer->n_channels = n_channels;
|
||||
|
||||
sigrenderer->pos = pos;
|
||||
sigrenderer->subpos = 0;
|
||||
|
||||
sigrenderer->callback = NULL;
|
||||
|
||||
return sigrenderer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
|
||||
{
|
||||
if (sigrenderer && sigrenderer->desc->type == type)
|
||||
return sigrenderer->sigrenderer;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
// This function is disabled because we don't know whether we want to destroy
|
||||
// the sigrenderer if the type doesn't match. We don't even know if we need
|
||||
// the function at all. Who would want to keep an IT_SIGRENDERER (for
|
||||
// instance) without keeping the DUH_SIGRENDERER?
|
||||
sigrenderer_t *duh_decompose_to_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
|
||||
{
|
||||
if (sigrenderer && sigrenderer->desc->type == type) {
|
||||
|
||||
|
||||
|
||||
if (sigrenderer) {
|
||||
if (sigrenderer->desc->end_sigrenderer)
|
||||
if (sigrenderer->sigrenderer)
|
||||
(*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
|
||||
|
||||
free(sigrenderer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return sigrenderer->sigrenderer;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,64 +1,64 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* unload.c - Code to free a DUH from memory. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
static void destroy_signal(DUH_SIGNAL *signal)
|
||||
{
|
||||
if (signal) {
|
||||
if (signal->desc)
|
||||
if (signal->desc->unload_sigdata)
|
||||
if (signal->sigdata)
|
||||
(*signal->desc->unload_sigdata)(signal->sigdata);
|
||||
|
||||
free(signal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* unload_duh(): destroys a DUH struct. You must call this for every DUH
|
||||
* struct created, when you've finished with it.
|
||||
*/
|
||||
void unload_duh(DUH *duh)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (duh) {
|
||||
if (duh->signal) {
|
||||
for (i = 0; i < duh->n_signals; i++)
|
||||
destroy_signal(duh->signal[i]);
|
||||
|
||||
free(duh->signal);
|
||||
}
|
||||
|
||||
if (duh->tag) {
|
||||
if (duh->tag[0][0])
|
||||
free(duh->tag[0][0]);
|
||||
free(duh->tag);
|
||||
}
|
||||
|
||||
free(duh);
|
||||
}
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* unload.c - Code to free a DUH from memory. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
|
||||
|
||||
|
||||
static void destroy_signal(DUH_SIGNAL *signal)
|
||||
{
|
||||
if (signal) {
|
||||
if (signal->desc)
|
||||
if (signal->desc->unload_sigdata)
|
||||
if (signal->sigdata)
|
||||
(*signal->desc->unload_sigdata)(signal->sigdata);
|
||||
|
||||
free(signal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* unload_duh(): destroys a DUH struct. You must call this for every DUH
|
||||
* struct created, when you've finished with it.
|
||||
*/
|
||||
void unload_duh(DUH *duh)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (duh) {
|
||||
if (duh->signal) {
|
||||
for (i = 0; i < duh->n_signals; i++)
|
||||
destroy_signal(duh->signal[i]);
|
||||
|
||||
free(duh->signal);
|
||||
}
|
||||
|
||||
if (duh->tag) {
|
||||
if (duh->tag[0][0])
|
||||
free(duh->tag[0][0]);
|
||||
free(duh->tag);
|
||||
}
|
||||
|
||||
free(duh);
|
||||
}
|
||||
}
|
||||
|
|
159
Frameworks/Dumb/dumb/src/helpers/barray.c
Normal file
159
Frameworks/Dumb/dumb/src/helpers/barray.c
Normal file
|
@ -0,0 +1,159 @@
|
|||
#include "internal/barray.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
void * bit_array_create(size_t size)
|
||||
{
|
||||
size_t bsize = ((size + 7) >> 3) + sizeof(size_t);
|
||||
void * ret = calloc(1, bsize);
|
||||
if (ret) *(size_t *)ret = size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bit_array_destroy(void * array)
|
||||
{
|
||||
if (array) free(array);
|
||||
}
|
||||
|
||||
void * bit_array_dup(void * array)
|
||||
{
|
||||
if (array)
|
||||
{
|
||||
size_t * size = (size_t *) array;
|
||||
size_t bsize = ((*size + 7) >> 3) + sizeof(*size);
|
||||
void * ret = malloc(bsize);
|
||||
if (ret) memcpy(ret, array, bsize);
|
||||
return ret;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bit_array_reset(void * array)
|
||||
{
|
||||
if (array)
|
||||
{
|
||||
size_t * size = (size_t *) array;
|
||||
size_t bsize = (*size + 7) >> 3;
|
||||
memset(size + 1, 0, bsize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bit_array_set(void * array, size_t bit)
|
||||
{
|
||||
if (array)
|
||||
{
|
||||
size_t * size = (size_t *) array;
|
||||
if (bit < *size)
|
||||
{
|
||||
unsigned char * ptr = (unsigned char *)(size + 1);
|
||||
ptr[bit >> 3] |= (1U << (bit & 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int bit_array_test(void * array, size_t bit)
|
||||
{
|
||||
if (array)
|
||||
{
|
||||
size_t * size = (size_t *) array;
|
||||
if (bit < *size)
|
||||
{
|
||||
unsigned char * ptr = (unsigned char *)(size + 1);
|
||||
if (ptr[bit >> 3] & (1U << (bit & 7)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bit_array_test_range(void * array, size_t bit, size_t count)
|
||||
{
|
||||
if (array)
|
||||
{
|
||||
size_t * size = (size_t *) array;
|
||||
if (bit < *size)
|
||||
{
|
||||
unsigned char * ptr = (unsigned char *)(size + 1);
|
||||
if ((bit & 7) && (count > 8))
|
||||
{
|
||||
while ((bit < *size) && count && (bit & 7))
|
||||
{
|
||||
if (ptr[bit >> 3] & (1U << (bit & 7))) return 1;
|
||||
bit++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
if (!(bit & 7))
|
||||
{
|
||||
while (((*size - bit) >= 8) && (count >= 8))
|
||||
{
|
||||
if (ptr[bit >> 3]) return 1;
|
||||
bit += 8;
|
||||
count -= 8;
|
||||
}
|
||||
}
|
||||
while ((bit < *size) && count)
|
||||
{
|
||||
if (ptr[bit >> 3] & (1U << (bit & 7))) return 1;
|
||||
bit++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bit_array_clear(void * array, size_t bit)
|
||||
{
|
||||
if (array)
|
||||
{
|
||||
size_t * size = (size_t *) array;
|
||||
if (bit < *size)
|
||||
{
|
||||
unsigned char * ptr = (unsigned char *)(size + 1);
|
||||
ptr[bit >> 3] &= ~(1U << (bit & 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bit_array_merge(void * dest, void * source, size_t offset)
|
||||
{
|
||||
if (dest && source)
|
||||
{
|
||||
size_t * dsize = (size_t *) dest;
|
||||
size_t * ssize = (size_t *) source;
|
||||
size_t soffset = 0;
|
||||
while (offset < *dsize && soffset < *ssize)
|
||||
{
|
||||
if (bit_array_test(source, soffset))
|
||||
{
|
||||
bit_array_set(dest, offset);
|
||||
}
|
||||
soffset++;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bit_array_mask(void * dest, void * source, size_t offset)
|
||||
{
|
||||
if (dest && source)
|
||||
{
|
||||
size_t * dsize = (size_t *) dest;
|
||||
size_t * ssize = (size_t *) source;
|
||||
size_t soffset = 0;
|
||||
while (offset < *dsize && soffset < *ssize)
|
||||
{
|
||||
if (bit_array_test(source, soffset))
|
||||
{
|
||||
bit_array_clear(dest, offset);
|
||||
}
|
||||
soffset++;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
354
Frameworks/Dumb/dumb/src/helpers/blip_buf.c
Normal file
354
Frameworks/Dumb/dumb/src/helpers/blip_buf.c
Normal file
|
@ -0,0 +1,354 @@
|
|||
/* blip_buf 1.1.0. http://www.slack.net/~ant/ */
|
||||
|
||||
#include "internal/blip_buf.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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 blip_t
|
||||
{
|
||||
fixed_t factor;
|
||||
fixed_t offset;
|
||||
int avail;
|
||||
int size;
|
||||
int 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( blip_max_ratio <= time_unit );
|
||||
assert( blip_max_frame <= (fixed_t) -1 >> time_bits );
|
||||
}
|
||||
|
||||
blip_t* blip_new( int size )
|
||||
{
|
||||
blip_t* m;
|
||||
assert( size >= 0 );
|
||||
|
||||
m = (blip_t*) malloc( sizeof *m + (size + buf_extra) * sizeof (buf_t) );
|
||||
if ( m )
|
||||
{
|
||||
m->factor = time_unit / blip_max_ratio;
|
||||
m->size = size;
|
||||
blip_clear( m );
|
||||
check_assumptions();
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
blip_t* blip_dup( blip_t* m )
|
||||
{
|
||||
size_t size = sizeof *m + (m->size + buf_extra) * sizeof(buf_t);
|
||||
blip_t* r = (blip_t*) malloc( size );
|
||||
if ( r ) memcpy( r, m, size );
|
||||
return r;
|
||||
}
|
||||
|
||||
void blip_delete( blip_t* m )
|
||||
{
|
||||
if ( m != NULL )
|
||||
{
|
||||
/* Clear fields in case user tries to use after freeing */
|
||||
memset( m, 0, sizeof *m );
|
||||
free( m );
|
||||
}
|
||||
}
|
||||
|
||||
void blip_set_rates( 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 blip_clear( 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 blip_clocks_needed( const 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 blip_end_frame( 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 blip_samples_avail( const blip_t* m )
|
||||
{
|
||||
return m->avail;
|
||||
}
|
||||
|
||||
static void remove_samples( 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 blip_read_samples( blip_t* m, int out [], int count )
|
||||
{
|
||||
assert( count >= 0 );
|
||||
|
||||
if ( count > m->avail )
|
||||
count = m->avail;
|
||||
|
||||
if ( count )
|
||||
{
|
||||
buf_t const* in = SAMPLES( m );
|
||||
buf_t const* end = in + count;
|
||||
int sum = m->integrator;
|
||||
do
|
||||
{
|
||||
/* Eliminate fraction */
|
||||
int s = ARITH_SHIFT( sum, delta_bits - 8 );
|
||||
|
||||
sum += *in++;
|
||||
|
||||
*out = s;
|
||||
out++;
|
||||
|
||||
/* High-pass filter */
|
||||
sum -= s >> (8 - (delta_bits - bass_shift)); //<< (delta_bits - bass_shift - 8);
|
||||
}
|
||||
while ( in != end );
|
||||
m->integrator = sum;
|
||||
|
||||
remove_samples( m, count );
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int blip_peek_sample( blip_t* m )
|
||||
{
|
||||
return ARITH_SHIFT( m->integrator, delta_bits - 8 );
|
||||
}
|
||||
|
||||
/* 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 blip_add_delta( 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 blip_add_delta_fast( 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;
|
||||
}
|
|
@ -1,281 +1,281 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* clickrem.c - Click removal helpers. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
typedef struct DUMB_CLICK DUMB_CLICK;
|
||||
|
||||
|
||||
struct DUMB_CLICK_REMOVER
|
||||
{
|
||||
DUMB_CLICK *click;
|
||||
int n_clicks;
|
||||
|
||||
int offset;
|
||||
};
|
||||
|
||||
|
||||
struct DUMB_CLICK
|
||||
{
|
||||
DUMB_CLICK *next;
|
||||
long pos;
|
||||
sample_t step;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DUMB_CLICK_REMOVER *dumb_create_click_remover(void)
|
||||
{
|
||||
DUMB_CLICK_REMOVER *cr = malloc(sizeof(*cr));
|
||||
if (!cr) return NULL;
|
||||
|
||||
cr->click = NULL;
|
||||
cr->n_clicks = 0;
|
||||
|
||||
cr->offset = 0;
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step)
|
||||
{
|
||||
DUMB_CLICK *click;
|
||||
|
||||
ASSERT(pos >= 0);
|
||||
|
||||
if (!cr || !step) return;
|
||||
|
||||
if (pos == 0) {
|
||||
cr->offset -= step;
|
||||
return;
|
||||
}
|
||||
|
||||
click = malloc(sizeof(*click));
|
||||
if (!click) return;
|
||||
|
||||
click->pos = pos;
|
||||
click->step = step;
|
||||
|
||||
click->next = cr->click;
|
||||
cr->click = click;
|
||||
cr->n_clicks++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks)
|
||||
{
|
||||
int i;
|
||||
DUMB_CLICK *c1, *c2, **cp;
|
||||
|
||||
if (n_clicks <= 1) return click;
|
||||
|
||||
/* Split the list into two */
|
||||
c1 = click;
|
||||
cp = &c1;
|
||||
for (i = 0; i < n_clicks; i += 2) cp = &(*cp)->next;
|
||||
c2 = *cp;
|
||||
*cp = NULL;
|
||||
|
||||
/* Sort the sublists */
|
||||
c1 = dumb_click_mergesort(c1, (n_clicks + 1) >> 1);
|
||||
c2 = dumb_click_mergesort(c2, n_clicks >> 1);
|
||||
|
||||
/* Merge them */
|
||||
cp = &click;
|
||||
while (c1 && c2) {
|
||||
if (c1->pos > c2->pos) {
|
||||
*cp = c2;
|
||||
c2 = c2->next;
|
||||
} else {
|
||||
*cp = c1;
|
||||
c1 = c1->next;
|
||||
}
|
||||
cp = &(*cp)->next;
|
||||
}
|
||||
if (c2)
|
||||
*cp = c2;
|
||||
else
|
||||
*cp = c1;
|
||||
|
||||
return click;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, int step, float halflife)
|
||||
{
|
||||
DUMB_CLICK *click;
|
||||
long pos = 0;
|
||||
int offset;
|
||||
int factor;
|
||||
|
||||
if (!cr) return;
|
||||
|
||||
factor = (int)floor(pow(0.5, 1.0/halflife) * (1U << 31));
|
||||
|
||||
click = dumb_click_mergesort(cr->click, cr->n_clicks);
|
||||
cr->click = NULL;
|
||||
cr->n_clicks = 0;
|
||||
|
||||
length *= step;
|
||||
|
||||
while (click) {
|
||||
DUMB_CLICK *next = click->next;
|
||||
int end = click->pos * step;
|
||||
ASSERT(end <= length);
|
||||
offset = cr->offset;
|
||||
if (offset < 0) {
|
||||
offset = -offset;
|
||||
while (pos < end) {
|
||||
samples[pos] -= offset;
|
||||
offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
|
||||
pos += step;
|
||||
}
|
||||
offset = -offset;
|
||||
} else {
|
||||
while (pos < end) {
|
||||
samples[pos] += offset;
|
||||
offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
|
||||
pos += step;
|
||||
}
|
||||
}
|
||||
cr->offset = offset - click->step;
|
||||
free(click);
|
||||
click = next;
|
||||
}
|
||||
|
||||
offset = cr->offset;
|
||||
if (offset < 0) {
|
||||
offset = -offset;
|
||||
while (pos < length) {
|
||||
samples[pos] -= offset;
|
||||
offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
|
||||
pos += step;
|
||||
}
|
||||
offset = -offset;
|
||||
} else {
|
||||
while (pos < length) {
|
||||
samples[pos] += offset;
|
||||
offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
|
||||
pos += step;
|
||||
}
|
||||
}
|
||||
cr->offset = offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr)
|
||||
{
|
||||
return cr ? cr->offset : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr)
|
||||
{
|
||||
if (cr) {
|
||||
DUMB_CLICK *click = cr->click;
|
||||
while (click) {
|
||||
DUMB_CLICK *next = click->next;
|
||||
free(click);
|
||||
click = next;
|
||||
}
|
||||
free(cr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n)
|
||||
{
|
||||
int i;
|
||||
DUMB_CLICK_REMOVER **cr;
|
||||
if (n <= 0) return NULL;
|
||||
cr = malloc(n * sizeof(*cr));
|
||||
if (!cr) return NULL;
|
||||
for (i = 0; i < n; i++) cr[i] = dumb_create_click_remover();
|
||||
return cr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
|
||||
{
|
||||
if (cr) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
dumb_record_click(cr[i], pos, step[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
|
||||
{
|
||||
if (cr) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
dumb_record_click(cr[i], pos, -step[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife)
|
||||
{
|
||||
if (cr) {
|
||||
int i;
|
||||
for (i = 0; i < n >> 1; i++) {
|
||||
dumb_remove_clicks(cr[i << 1], samples[i], length, 2, halflife);
|
||||
dumb_remove_clicks(cr[(i << 1) + 1], samples[i] + 1, length, 2, halflife);
|
||||
}
|
||||
if (n & 1)
|
||||
dumb_remove_clicks(cr[i << 1], samples[i], length, 1, halflife);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset)
|
||||
{
|
||||
if (cr) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
if (cr[i]) offset[i] += cr[i]->offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr)
|
||||
{
|
||||
if (cr) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++) dumb_destroy_click_remover(cr[i]);
|
||||
free(cr);
|
||||
}
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* clickrem.c - Click removal helpers. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
typedef struct DUMB_CLICK DUMB_CLICK;
|
||||
|
||||
|
||||
struct DUMB_CLICK_REMOVER
|
||||
{
|
||||
DUMB_CLICK *click;
|
||||
int n_clicks;
|
||||
|
||||
int offset;
|
||||
};
|
||||
|
||||
|
||||
struct DUMB_CLICK
|
||||
{
|
||||
DUMB_CLICK *next;
|
||||
long pos;
|
||||
sample_t step;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DUMB_CLICK_REMOVER *dumb_create_click_remover(void)
|
||||
{
|
||||
DUMB_CLICK_REMOVER *cr = malloc(sizeof(*cr));
|
||||
if (!cr) return NULL;
|
||||
|
||||
cr->click = NULL;
|
||||
cr->n_clicks = 0;
|
||||
|
||||
cr->offset = 0;
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step)
|
||||
{
|
||||
DUMB_CLICK *click;
|
||||
|
||||
ASSERT(pos >= 0);
|
||||
|
||||
if (!cr || !step) return;
|
||||
|
||||
if (pos == 0) {
|
||||
cr->offset -= step;
|
||||
return;
|
||||
}
|
||||
|
||||
click = malloc(sizeof(*click));
|
||||
if (!click) return;
|
||||
|
||||
click->pos = pos;
|
||||
click->step = step;
|
||||
|
||||
click->next = cr->click;
|
||||
cr->click = click;
|
||||
cr->n_clicks++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks)
|
||||
{
|
||||
int i;
|
||||
DUMB_CLICK *c1, *c2, **cp;
|
||||
|
||||
if (n_clicks <= 1) return click;
|
||||
|
||||
/* Split the list into two */
|
||||
c1 = click;
|
||||
cp = &c1;
|
||||
for (i = 0; i < n_clicks; i += 2) cp = &(*cp)->next;
|
||||
c2 = *cp;
|
||||
*cp = NULL;
|
||||
|
||||
/* Sort the sublists */
|
||||
c1 = dumb_click_mergesort(c1, (n_clicks + 1) >> 1);
|
||||
c2 = dumb_click_mergesort(c2, n_clicks >> 1);
|
||||
|
||||
/* Merge them */
|
||||
cp = &click;
|
||||
while (c1 && c2) {
|
||||
if (c1->pos > c2->pos) {
|
||||
*cp = c2;
|
||||
c2 = c2->next;
|
||||
} else {
|
||||
*cp = c1;
|
||||
c1 = c1->next;
|
||||
}
|
||||
cp = &(*cp)->next;
|
||||
}
|
||||
if (c2)
|
||||
*cp = c2;
|
||||
else
|
||||
*cp = c1;
|
||||
|
||||
return click;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, int step, float halflife)
|
||||
{
|
||||
DUMB_CLICK *click;
|
||||
long pos = 0;
|
||||
int offset;
|
||||
int factor;
|
||||
|
||||
if (!cr) return;
|
||||
|
||||
factor = (int)floor(pow(0.5, 1.0/halflife) * (1U << 31));
|
||||
|
||||
click = dumb_click_mergesort(cr->click, cr->n_clicks);
|
||||
cr->click = NULL;
|
||||
cr->n_clicks = 0;
|
||||
|
||||
length *= step;
|
||||
|
||||
while (click) {
|
||||
DUMB_CLICK *next = click->next;
|
||||
int end = click->pos * step;
|
||||
ASSERT(end <= length);
|
||||
offset = cr->offset;
|
||||
if (offset < 0) {
|
||||
offset = -offset;
|
||||
while (pos < end) {
|
||||
samples[pos] -= offset;
|
||||
offset = (int)(((LONG_LONG)(offset << 1) * factor) >> 32);
|
||||
pos += step;
|
||||
}
|
||||
offset = -offset;
|
||||
} else {
|
||||
while (pos < end) {
|
||||
samples[pos] += offset;
|
||||
offset = (int)(((LONG_LONG)(offset << 1) * factor) >> 32);
|
||||
pos += step;
|
||||
}
|
||||
}
|
||||
cr->offset = offset - click->step;
|
||||
free(click);
|
||||
click = next;
|
||||
}
|
||||
|
||||
offset = cr->offset;
|
||||
if (offset < 0) {
|
||||
offset = -offset;
|
||||
while (pos < length) {
|
||||
samples[pos] -= offset;
|
||||
offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
|
||||
pos += step;
|
||||
}
|
||||
offset = -offset;
|
||||
} else {
|
||||
while (pos < length) {
|
||||
samples[pos] += offset;
|
||||
offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
|
||||
pos += step;
|
||||
}
|
||||
}
|
||||
cr->offset = offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr)
|
||||
{
|
||||
return cr ? cr->offset : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr)
|
||||
{
|
||||
if (cr) {
|
||||
DUMB_CLICK *click = cr->click;
|
||||
while (click) {
|
||||
DUMB_CLICK *next = click->next;
|
||||
free(click);
|
||||
click = next;
|
||||
}
|
||||
free(cr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n)
|
||||
{
|
||||
int i;
|
||||
DUMB_CLICK_REMOVER **cr;
|
||||
if (n <= 0) return NULL;
|
||||
cr = malloc(n * sizeof(*cr));
|
||||
if (!cr) return NULL;
|
||||
for (i = 0; i < n; i++) cr[i] = dumb_create_click_remover();
|
||||
return cr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
|
||||
{
|
||||
if (cr) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
dumb_record_click(cr[i], pos, step[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
|
||||
{
|
||||
if (cr) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
dumb_record_click(cr[i], pos, -step[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife)
|
||||
{
|
||||
if (cr) {
|
||||
int i;
|
||||
for (i = 0; i < n >> 1; i++) {
|
||||
dumb_remove_clicks(cr[i << 1], samples[i], length, 2, halflife);
|
||||
dumb_remove_clicks(cr[(i << 1) + 1], samples[i] + 1, length, 2, halflife);
|
||||
}
|
||||
if (n & 1)
|
||||
dumb_remove_clicks(cr[i << 1], samples[i], length, 1, halflife);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset)
|
||||
{
|
||||
if (cr) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
if (cr[i]) offset[i] += cr[i]->offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr)
|
||||
{
|
||||
if (cr) {
|
||||
int i;
|
||||
for (i = 0; i < n; i++) dumb_destroy_click_remover(cr[i]);
|
||||
free(cr);
|
||||
}
|
||||
}
|
||||
|
|
281
Frameworks/Dumb/dumb/src/helpers/fir_resampler.c
Normal file
281
Frameworks/Dumb/dumb/src/helpers/fir_resampler.c
Normal file
|
@ -0,0 +1,281 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "internal/fir_resampler.h"
|
||||
|
||||
enum { fir_width = 16 };
|
||||
|
||||
enum { fir_max_res = 1024 };
|
||||
enum { fir_min_width = (fir_width < 4 ? 4 : fir_width) };
|
||||
enum { fir_adj_width = fir_min_width / 4 * 4 + 2 };
|
||||
enum { fir_stereo = 1 }; /* channel count, not boolean value */
|
||||
enum { fir_write_offset = fir_adj_width * fir_stereo };
|
||||
|
||||
enum { fir_buffer_size = fir_width * 2 };
|
||||
|
||||
typedef short fir_impulse[fir_adj_width];
|
||||
|
||||
/* exp slope to 31/32 of ln(8) */
|
||||
static const double fir_ratios[32] = {
|
||||
1.000, 1.067, 1.139, 1.215, 1.297, 1.384, 1.477, 1.576,
|
||||
1.682, 1.795, 1.915, 2.044, 2.181, 2.327, 2.484, 2.650,
|
||||
2.828, 3.018, 3.221, 3.437, 3.668, 3.914, 4.177, 4.458,
|
||||
4.757, 5.076, 5.417, 5.781, 6.169, 6.583, 7.025, 7.497
|
||||
};
|
||||
|
||||
static fir_impulse fir_impulses[32][fir_max_res];
|
||||
|
||||
#undef PI
|
||||
#define PI 3.1415926535897932384626433832795029
|
||||
|
||||
static void gen_sinc( double rolloff, int width, double offset, double spacing, double scale,
|
||||
int count, short* out )
|
||||
{
|
||||
double const maxh = 256;
|
||||
double const step = PI / maxh * spacing;
|
||||
double const to_w = maxh * 2 / width;
|
||||
double const pow_a_n = pow( rolloff, maxh );
|
||||
|
||||
double angle = (count / 2 - 1 + offset) * -step;
|
||||
|
||||
scale /= maxh * 2;
|
||||
|
||||
while ( count-- )
|
||||
{
|
||||
double w;
|
||||
*out++ = 0;
|
||||
w = angle * to_w;
|
||||
if ( fabs( w ) < PI )
|
||||
{
|
||||
double rolloff_cos_a = rolloff * cos( angle );
|
||||
double num = 1 - rolloff_cos_a -
|
||||
pow_a_n * cos( maxh * angle ) +
|
||||
pow_a_n * rolloff * cos( (maxh - 1) * angle );
|
||||
double den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
|
||||
double sinc = scale * num / den - scale;
|
||||
|
||||
out [-1] = (short) (cos( w ) * sinc + sinc);
|
||||
}
|
||||
angle += step;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct fir_resampler
|
||||
{
|
||||
int write_pos, write_filled;
|
||||
int read_pos, read_filled;
|
||||
unsigned short phase;
|
||||
unsigned int phase_inc;
|
||||
unsigned int ratio_set;
|
||||
int buffer_in[fir_buffer_size * 2];
|
||||
int buffer_out[fir_buffer_size];
|
||||
} fir_resampler;
|
||||
|
||||
void * fir_resampler_create()
|
||||
{
|
||||
fir_resampler * r = ( fir_resampler * ) malloc( sizeof(fir_resampler) );
|
||||
if ( !r ) return 0;
|
||||
|
||||
r->write_pos = 0;
|
||||
r->write_filled = 0;
|
||||
r->read_pos = 0;
|
||||
r->read_filled = 0;
|
||||
r->phase = 0;
|
||||
r->phase_inc = 0;
|
||||
r->ratio_set = 0;
|
||||
memset( r->buffer_in, 0, sizeof(r->buffer_in) );
|
||||
memset( r->buffer_out, 0, sizeof(r->buffer_out) );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void fir_resampler_delete(void * _r)
|
||||
{
|
||||
free( _r );
|
||||
}
|
||||
|
||||
void * fir_resampler_dup(void * _r)
|
||||
{
|
||||
fir_resampler * r_in = ( fir_resampler * ) _r;
|
||||
fir_resampler * r_out = ( fir_resampler * ) malloc( sizeof(fir_resampler) );
|
||||
if ( !r_out ) return 0;
|
||||
|
||||
r_out->write_pos = r_in->write_pos;
|
||||
r_out->write_filled = r_in->write_filled;
|
||||
r_out->read_pos = r_in->read_pos;
|
||||
r_out->read_filled = r_in->read_filled;
|
||||
r_out->phase = r_in->phase;
|
||||
r_out->phase_inc = r_in->phase_inc;
|
||||
r_out->ratio_set = r_in->ratio_set;
|
||||
memcpy( r_out->buffer_in, r_in->buffer_in, sizeof(r_in->buffer_in) );
|
||||
memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) );
|
||||
|
||||
return r_out;
|
||||
}
|
||||
|
||||
int fir_resampler_get_free_count(void *_r)
|
||||
{
|
||||
fir_resampler * r = ( fir_resampler * ) _r;
|
||||
return fir_buffer_size - r->write_filled;
|
||||
}
|
||||
|
||||
int fir_resampler_ready(void *_r)
|
||||
{
|
||||
fir_resampler * r = ( fir_resampler * ) _r;
|
||||
return r->write_filled > fir_adj_width;
|
||||
}
|
||||
|
||||
void fir_resampler_clear(void *_r)
|
||||
{
|
||||
fir_resampler * r = ( fir_resampler * ) _r;
|
||||
r->write_pos = 0;
|
||||
r->write_filled = 0;
|
||||
r->read_pos = 0;
|
||||
r->read_filled = 0;
|
||||
r->phase = 0;
|
||||
memset( r->buffer_in, 0, sizeof(r->buffer_in) );
|
||||
}
|
||||
|
||||
void fir_resampler_set_rate(void *_r, double new_factor)
|
||||
{
|
||||
fir_resampler * r = ( fir_resampler * ) _r;
|
||||
r->phase_inc = (int)( new_factor * 65536.0 );
|
||||
r->ratio_set = 0;
|
||||
while ( r->ratio_set < 31 && new_factor > fir_ratios[ r->ratio_set ] ) r->ratio_set++;
|
||||
}
|
||||
|
||||
void fir_resampler_write_sample(void *_r, short s)
|
||||
{
|
||||
fir_resampler * r = ( fir_resampler * ) _r;
|
||||
|
||||
if ( r->write_filled < fir_buffer_size )
|
||||
{
|
||||
int s32 = s;
|
||||
|
||||
r->buffer_in[ r->write_pos ] = s32;
|
||||
r->buffer_in[ r->write_pos + fir_buffer_size ] = s32;
|
||||
|
||||
++r->write_filled;
|
||||
|
||||
r->write_pos = ( r->write_pos + 1 ) % fir_buffer_size;
|
||||
}
|
||||
}
|
||||
|
||||
void fir_init()
|
||||
{
|
||||
double const rolloff = 0.999;
|
||||
double const gain = 1.0;
|
||||
|
||||
int const res = fir_max_res;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
double const ratio_ = fir_ratios[ i ];
|
||||
|
||||
double fraction = 1.0 / (double)fir_max_res;
|
||||
|
||||
double const filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_;
|
||||
double pos = 0.0;
|
||||
short* out = (short*) fir_impulses[ i ];
|
||||
int n;
|
||||
for ( n = res; --n >= 0; )
|
||||
{
|
||||
gen_sinc( rolloff, (int) (fir_adj_width * filter + 1) & ~1, pos, filter,
|
||||
(double) (0x7FFF * gain * filter), (int) fir_adj_width, out );
|
||||
out += fir_adj_width;
|
||||
|
||||
pos += fraction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int fir_resampler_run(void *_r, int ** out_, int * out_end)
|
||||
{
|
||||
fir_resampler * r = ( fir_resampler * ) _r;
|
||||
int in_size = r->write_filled;
|
||||
int const* in_ = r->buffer_in + fir_buffer_size + r->write_pos - r->write_filled;
|
||||
int used = 0;
|
||||
in_size -= fir_write_offset;
|
||||
if ( in_size > 0 )
|
||||
{
|
||||
int* out = *out_;
|
||||
int const* in = in_;
|
||||
int const* const in_end = in + in_size;
|
||||
int phase = r->phase;
|
||||
int phase_inc = r->phase_inc;
|
||||
int ratio_set = r->ratio_set;
|
||||
|
||||
do
|
||||
{
|
||||
// accumulate in extended precision
|
||||
short const* imp = fir_impulses[ratio_set][(phase & 0xFFC0) >> 6];
|
||||
int pt = imp [0];
|
||||
int s = pt * in [0];
|
||||
int n;
|
||||
if ( out >= out_end )
|
||||
break;
|
||||
for ( n = (fir_adj_width - 2) / 2; n; --n )
|
||||
{
|
||||
pt = imp [1];
|
||||
s += pt * in [1];
|
||||
|
||||
// pre-increment more efficient on some RISC processors
|
||||
imp += 2;
|
||||
pt = imp [0];
|
||||
in += 2;
|
||||
s += pt * in [0];
|
||||
}
|
||||
pt = imp [1];
|
||||
s += pt * in [1];
|
||||
|
||||
phase += phase_inc;
|
||||
|
||||
in += (phase >> 16) - fir_adj_width + 2;
|
||||
|
||||
phase &= 65535;
|
||||
|
||||
*out++ = (int) (s >> 7);
|
||||
}
|
||||
while ( in < in_end );
|
||||
|
||||
r->phase = phase;
|
||||
*out_ = out;
|
||||
|
||||
used = in - in_;
|
||||
|
||||
r->write_filled -= used;
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
int fir_resampler_get_sample(void *_r)
|
||||
{
|
||||
fir_resampler * r = ( fir_resampler * ) _r;
|
||||
if ( r->read_filled < 1 )
|
||||
{
|
||||
int write_pos = ( r->read_pos + r->read_filled ) % fir_buffer_size;
|
||||
int write_size = fir_buffer_size - write_pos;
|
||||
int * out = r->buffer_out + write_pos;
|
||||
if ( write_size > ( fir_buffer_size - r->read_filled ) )
|
||||
write_size = fir_buffer_size - r->read_filled;
|
||||
fir_resampler_run( r, &out, out + write_size );
|
||||
r->read_filled += out - r->buffer_out - write_pos;
|
||||
}
|
||||
if ( r->read_filled < 1 )
|
||||
return 0;
|
||||
return r->buffer_out[ r->read_pos ];
|
||||
}
|
||||
|
||||
void fir_resampler_remove_sample(void *_r)
|
||||
{
|
||||
fir_resampler * r = ( fir_resampler * ) _r;
|
||||
if ( r->read_filled > 0 )
|
||||
{
|
||||
--r->read_filled;
|
||||
r->read_pos = ( r->read_pos + 1 ) % fir_buffer_size;
|
||||
}
|
||||
}
|
229
Frameworks/Dumb/dumb/src/helpers/lanczos_resampler.c
Normal file
229
Frameworks/Dumb/dumb/src/helpers/lanczos_resampler.c
Normal file
|
@ -0,0 +1,229 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#include "internal/lanczos_resampler.h"
|
||||
|
||||
enum { LANCZOS_RESOLUTION = 8192 };
|
||||
enum { LANCZOS_WIDTH = 8 };
|
||||
enum { LANCZOS_SAMPLES = LANCZOS_RESOLUTION * LANCZOS_WIDTH };
|
||||
|
||||
static double lanczos_lut[LANCZOS_SAMPLES + 1];
|
||||
|
||||
enum { lanczos_buffer_size = LANCZOS_WIDTH * 4 };
|
||||
|
||||
int fEqual(const double b, const double a)
|
||||
{
|
||||
return fabs(a - b) < 1.0e-6;
|
||||
}
|
||||
|
||||
static double sinc(double x)
|
||||
{
|
||||
return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI);
|
||||
}
|
||||
|
||||
void lanczos_init()
|
||||
{
|
||||
unsigned i;
|
||||
double dx = (double)(LANCZOS_WIDTH) / LANCZOS_SAMPLES, x = 0.0;
|
||||
for (i = 0; i < LANCZOS_SAMPLES + 1; ++i, x += dx)
|
||||
lanczos_lut[i] = abs(x) < LANCZOS_WIDTH ? sinc(x) * sinc(x / LANCZOS_WIDTH) : 0.0;
|
||||
}
|
||||
|
||||
typedef struct lanczos_resampler
|
||||
{
|
||||
int write_pos, write_filled;
|
||||
int read_pos, read_filled;
|
||||
unsigned short phase;
|
||||
unsigned int phase_inc;
|
||||
float buffer_in[lanczos_buffer_size * 2];
|
||||
int buffer_out[lanczos_buffer_size];
|
||||
} lanczos_resampler;
|
||||
|
||||
void * lanczos_resampler_create()
|
||||
{
|
||||
lanczos_resampler * r = ( lanczos_resampler * ) malloc( sizeof(lanczos_resampler) );
|
||||
if ( !r ) return 0;
|
||||
|
||||
r->write_pos = 0;
|
||||
r->write_filled = 0;
|
||||
r->read_pos = 0;
|
||||
r->read_filled = 0;
|
||||
r->phase = 0;
|
||||
r->phase_inc = 0;
|
||||
memset( r->buffer_in, 0, sizeof(r->buffer_in) );
|
||||
memset( r->buffer_out, 0, sizeof(r->buffer_out) );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void lanczos_resampler_delete(void * _r)
|
||||
{
|
||||
free( _r );
|
||||
}
|
||||
|
||||
void * lanczos_resampler_dup(void * _r)
|
||||
{
|
||||
lanczos_resampler * r_in = ( lanczos_resampler * ) _r;
|
||||
lanczos_resampler * r_out = ( lanczos_resampler * ) malloc( sizeof(lanczos_resampler) );
|
||||
if ( !r_out ) return 0;
|
||||
|
||||
r_out->write_pos = r_in->write_pos;
|
||||
r_out->write_filled = r_in->write_filled;
|
||||
r_out->read_pos = r_in->read_pos;
|
||||
r_out->read_filled = r_in->read_filled;
|
||||
r_out->phase = r_in->phase;
|
||||
r_out->phase_inc = r_in->phase_inc;
|
||||
memcpy( r_out->buffer_in, r_in->buffer_in, sizeof(r_in->buffer_in) );
|
||||
memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) );
|
||||
|
||||
return r_out;
|
||||
}
|
||||
|
||||
int lanczos_resampler_get_free_count(void *_r)
|
||||
{
|
||||
lanczos_resampler * r = ( lanczos_resampler * ) _r;
|
||||
return lanczos_buffer_size - r->write_filled;
|
||||
}
|
||||
|
||||
int lanczos_resampler_ready(void *_r)
|
||||
{
|
||||
lanczos_resampler * r = ( lanczos_resampler * ) _r;
|
||||
return r->write_filled > (LANCZOS_WIDTH * 2);
|
||||
}
|
||||
|
||||
void lanczos_resampler_clear(void *_r)
|
||||
{
|
||||
lanczos_resampler * r = ( lanczos_resampler * ) _r;
|
||||
r->write_pos = 0;
|
||||
r->write_filled = 0;
|
||||
r->read_pos = 0;
|
||||
r->read_filled = 0;
|
||||
r->phase = 0;
|
||||
}
|
||||
|
||||
void lanczos_resampler_set_rate(void *_r, double new_factor)
|
||||
{
|
||||
lanczos_resampler * r = ( lanczos_resampler * ) _r;
|
||||
r->phase_inc = (int)( new_factor * LANCZOS_RESOLUTION );
|
||||
}
|
||||
|
||||
void lanczos_resampler_write_sample(void *_r, short s)
|
||||
{
|
||||
lanczos_resampler * r = ( lanczos_resampler * ) _r;
|
||||
|
||||
if ( r->write_filled < lanczos_buffer_size )
|
||||
{
|
||||
float s32 = s;
|
||||
|
||||
r->buffer_in[ r->write_pos ] = s32;
|
||||
r->buffer_in[ r->write_pos + lanczos_buffer_size ] = s32;
|
||||
|
||||
++r->write_filled;
|
||||
|
||||
r->write_pos = ( r->write_pos + 1 ) % lanczos_buffer_size;
|
||||
}
|
||||
}
|
||||
|
||||
static int lanczos_resampler_run(lanczos_resampler * r, int ** out_, int * out_end)
|
||||
{
|
||||
int in_size = r->write_filled;
|
||||
float const* in_ = r->buffer_in + lanczos_buffer_size + r->write_pos - r->write_filled;
|
||||
int used = 0;
|
||||
in_size -= LANCZOS_WIDTH * 2;
|
||||
if ( in_size > 0 )
|
||||
{
|
||||
int* out = *out_;
|
||||
float const* in = in_;
|
||||
float const* const in_end = in + in_size;
|
||||
int phase = r->phase;
|
||||
int phase_inc = r->phase_inc;
|
||||
|
||||
int step = phase_inc > LANCZOS_RESOLUTION ? LANCZOS_RESOLUTION * LANCZOS_RESOLUTION / phase_inc : LANCZOS_RESOLUTION;
|
||||
|
||||
do
|
||||
{
|
||||
// accumulate in extended precision
|
||||
double kernel[LANCZOS_WIDTH * 2], kernel_sum = 0.0;
|
||||
int i = LANCZOS_WIDTH;
|
||||
int phase_adj = phase * step / LANCZOS_RESOLUTION;
|
||||
double sample;
|
||||
|
||||
if ( out >= out_end )
|
||||
break;
|
||||
|
||||
for (; i >= -LANCZOS_WIDTH + 1; --i)
|
||||
{
|
||||
int pos = i * step;
|
||||
kernel_sum += kernel[i + LANCZOS_WIDTH - 1] = lanczos_lut[abs(phase_adj - pos)];
|
||||
}
|
||||
for (sample = 0, i = 0; i < LANCZOS_WIDTH * 2; ++i)
|
||||
sample += in[i] * kernel[i];
|
||||
*out++ = (int) (sample / kernel_sum * 256.0);
|
||||
|
||||
phase += phase_inc;
|
||||
|
||||
in += phase >> 13;
|
||||
|
||||
phase &= 8191;
|
||||
}
|
||||
while ( in < in_end );
|
||||
|
||||
r->phase = phase;
|
||||
*out_ = out;
|
||||
|
||||
used = in - in_;
|
||||
|
||||
r->write_filled -= used;
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
static void lanczos_resampler_fill(lanczos_resampler * r)
|
||||
{
|
||||
while ( r->write_filled > (LANCZOS_WIDTH * 2) &&
|
||||
r->read_filled < lanczos_buffer_size )
|
||||
{
|
||||
int write_pos = ( r->read_pos + r->read_filled ) % lanczos_buffer_size;
|
||||
int write_size = lanczos_buffer_size - write_pos;
|
||||
int * out = r->buffer_out + write_pos;
|
||||
if ( write_size > ( lanczos_buffer_size - r->read_filled ) )
|
||||
write_size = lanczos_buffer_size - r->read_filled;
|
||||
lanczos_resampler_run( r, &out, out + write_size );
|
||||
r->read_filled += out - r->buffer_out - write_pos;
|
||||
}
|
||||
}
|
||||
|
||||
int lanczos_resampler_get_sample_count(void *_r)
|
||||
{
|
||||
lanczos_resampler * r = ( lanczos_resampler * ) _r;
|
||||
if ( r->read_filled < 1 )
|
||||
lanczos_resampler_fill( r );
|
||||
return r->read_filled;
|
||||
}
|
||||
|
||||
int lanczos_resampler_get_sample(void *_r)
|
||||
{
|
||||
lanczos_resampler * r = ( lanczos_resampler * ) _r;
|
||||
if ( r->read_filled < 1 )
|
||||
lanczos_resampler_fill( r );
|
||||
if ( r->read_filled < 1 )
|
||||
return 0;
|
||||
return r->buffer_out[ r->read_pos ];
|
||||
}
|
||||
|
||||
void lanczos_resampler_remove_sample(void *_r)
|
||||
{
|
||||
lanczos_resampler * r = ( lanczos_resampler * ) _r;
|
||||
if ( r->read_filled > 0 )
|
||||
{
|
||||
--r->read_filled;
|
||||
r->read_pos = ( r->read_pos + 1 ) % lanczos_buffer_size;
|
||||
}
|
||||
}
|
320
Frameworks/Dumb/dumb/src/helpers/lpc.c
Normal file
320
Frameworks/Dumb/dumb/src/helpers/lpc.c
Normal file
|
@ -0,0 +1,320 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LPC low level routines
|
||||
last mod: $Id: lpc.c 16227 2009-07-08 06:58:46Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* Some of these routines (autocorrelator, LPC coefficient estimator)
|
||||
are derived from code written by Jutta Degener and Carsten Bormann;
|
||||
thus we include their copyright below. The entirety of this file
|
||||
is freely redistributable on the condition that both of these
|
||||
copyright notices are preserved without modification. */
|
||||
|
||||
/* Preserved Copyright: *********************************************/
|
||||
|
||||
/* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
|
||||
Technische Universita"t Berlin
|
||||
|
||||
Any use of this software is permitted provided that this notice is not
|
||||
removed and that neither the authors nor the Technische Universita"t
|
||||
Berlin are deemed to have made any representations as to the
|
||||
suitability of this software for any purpose nor are held responsible
|
||||
for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
|
||||
THIS SOFTWARE.
|
||||
|
||||
As a matter of courtesy, the authors request to be informed about uses
|
||||
this software has found, about bugs in this software, and about any
|
||||
improvements that may be of general interest.
|
||||
|
||||
Berlin, 28.11.1994
|
||||
Jutta Degener
|
||||
Carsten Bormann
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "internal/stack_alloc.h"
|
||||
#include "internal/lpc.h"
|
||||
|
||||
/* Autocorrelation LPC coeff generation algorithm invented by
|
||||
N. Levinson in 1947, modified by J. Durbin in 1959. */
|
||||
|
||||
/* Input : n elements of time doamin data
|
||||
Output: m lpc coefficients, excitation energy */
|
||||
|
||||
float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
|
||||
double *aut=alloca(sizeof(*aut)*(m+1));
|
||||
double *lpc=alloca(sizeof(*lpc)*(m));
|
||||
double error;
|
||||
double epsilon;
|
||||
int i,j;
|
||||
|
||||
/* autocorrelation, p+1 lag coefficients */
|
||||
j=m+1;
|
||||
while(j--){
|
||||
double d=0; /* double needed for accumulator depth */
|
||||
for(i=j;i<n;i++)d+=(double)data[i]*data[(i-j)];
|
||||
aut[j]=d;
|
||||
}
|
||||
|
||||
/* Generate lpc coefficients from autocorr values */
|
||||
|
||||
/* set our noise floor to about -100dB */
|
||||
error=aut[0] * (1. + 1e-10);
|
||||
epsilon=1e-9*aut[0]+1e-10;
|
||||
|
||||
for(i=0;i<m;i++){
|
||||
double r= -aut[i+1];
|
||||
|
||||
if(error<epsilon){
|
||||
memset(lpc+i,0,(m-i)*sizeof(*lpc));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Sum up this iteration's reflection coefficient; note that in
|
||||
Vorbis we don't save it. If anyone wants to recycle this code
|
||||
and needs reflection coefficients, save the results of 'r' from
|
||||
each iteration. */
|
||||
|
||||
for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
|
||||
r/=error;
|
||||
|
||||
/* Update LPC coefficients and total error */
|
||||
|
||||
lpc[i]=r;
|
||||
for(j=0;j<i/2;j++){
|
||||
double tmp=lpc[j];
|
||||
|
||||
lpc[j]+=r*lpc[i-1-j];
|
||||
lpc[i-1-j]+=r*tmp;
|
||||
}
|
||||
if(i&1)lpc[j]+=lpc[j]*r;
|
||||
|
||||
error*=1.-r*r;
|
||||
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
/* slightly damp the filter */
|
||||
{
|
||||
double g = .99;
|
||||
double damp = g;
|
||||
for(j=0;j<m;j++){
|
||||
lpc[j]*=damp;
|
||||
damp*=g;
|
||||
}
|
||||
}
|
||||
|
||||
for(j=0;j<m;j++)lpci[j]=(float)lpc[j];
|
||||
|
||||
/* we need the error value to know how big an impulse to hit the
|
||||
filter with later */
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void vorbis_lpc_predict(float *coeff,float *prime,int m,
|
||||
float *data,long n){
|
||||
|
||||
/* in: coeff[0...m-1] LPC coefficients
|
||||
prime[0...m-1] initial values (allocated size of n+m-1)
|
||||
out: data[0...n-1] data samples */
|
||||
|
||||
long i,j,o,p;
|
||||
float y;
|
||||
float *work=alloca(sizeof(*work)*(m+n));
|
||||
|
||||
if(!prime)
|
||||
for(i=0;i<m;i++)
|
||||
work[i]=0.f;
|
||||
else
|
||||
for(i=0;i<m;i++)
|
||||
work[i]=prime[i];
|
||||
|
||||
for(i=0;i<n;i++){
|
||||
y=0;
|
||||
o=i;
|
||||
p=m;
|
||||
for(j=0;j<m;j++)
|
||||
y-=work[o++]*coeff[--p];
|
||||
|
||||
data[i]=work[o]=y;
|
||||
}
|
||||
}
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
enum { lpc_max = 256 }; /* Maximum number of input samples to train the function */
|
||||
enum { lpc_order = 32 }; /* Order of the filter */
|
||||
enum { lpc_extra = 64 }; /* How many samples of padding to predict or silence */
|
||||
|
||||
|
||||
/* This extra sample padding is really only needed by the FIR resampler, but it helps the other resamplers as well. */
|
||||
|
||||
void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
|
||||
float lpc[lpc_order * 2];
|
||||
float lpc_input[lpc_max * 2];
|
||||
float lpc_output[lpc_extra * 2];
|
||||
|
||||
signed char * s8;
|
||||
signed short * s16;
|
||||
|
||||
int n, o, offset, lpc_samples;
|
||||
|
||||
for ( n = 0; n < sigdata->n_samples; n++ ) {
|
||||
IT_SAMPLE * sample = sigdata->sample + n;
|
||||
if ( ( sample->flags & ( IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP) ) == IT_SAMPLE_EXISTS ) {
|
||||
/* If we have enough sample data to train the filter, use the filter to generate the padding */
|
||||
if ( sample->length >= lpc_order ) {
|
||||
lpc_samples = sample->length;
|
||||
if (lpc_samples > lpc_max) lpc_samples = lpc_max;
|
||||
offset = sample->length - lpc_samples;
|
||||
|
||||
if ( sample->flags & IT_SAMPLE_STEREO )
|
||||
{
|
||||
if ( sample->flags & IT_SAMPLE_16BIT )
|
||||
{
|
||||
s16 = ( signed short * ) sample->data;
|
||||
s16 += offset * 2;
|
||||
for ( o = 0; o < lpc_samples; o++ )
|
||||
{
|
||||
lpc_input[ o ] = s16[ o * 2 + 0 ];
|
||||
lpc_input[ o + lpc_max ] = s16[ o * 2 + 1 ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s8 = ( signed char * ) sample->data;
|
||||
s8 += offset * 2;
|
||||
for ( o = 0; o < lpc_samples; o++ )
|
||||
{
|
||||
lpc_input[ o ] = s8[ o * 2 + 0 ];
|
||||
lpc_input[ o + lpc_max ] = s8[ o * 2 + 1 ];
|
||||
}
|
||||
}
|
||||
|
||||
vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order );
|
||||
vorbis_lpc_from_data( lpc_input + lpc_max, lpc + lpc_order, lpc_samples, lpc_order );
|
||||
|
||||
vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra );
|
||||
vorbis_lpc_predict( lpc + lpc_order, lpc_input + lpc_max + lpc_samples - lpc_order, lpc_order, lpc_output + lpc_extra, lpc_extra );
|
||||
|
||||
if ( sample->flags & IT_SAMPLE_16BIT )
|
||||
{
|
||||
s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 * sizeof(short) );
|
||||
sample->data = s16;
|
||||
|
||||
s16 += sample->length * 2;
|
||||
sample->length += lpc_extra;
|
||||
|
||||
for ( o = 0; o < lpc_extra; o++ )
|
||||
{
|
||||
s16[ o * 2 + 0 ] = lpc_output[ o ];
|
||||
s16[ o * 2 + 1 ] = lpc_output[ o + lpc_extra ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s8 = ( signed char * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 );
|
||||
sample->data = s8;
|
||||
|
||||
s8 += sample->length * 2;
|
||||
sample->length += lpc_extra;
|
||||
|
||||
for ( o = 0; o < lpc_extra; o++ )
|
||||
{
|
||||
s8[ o * 2 + 0 ] = lpc_output[ o ];
|
||||
s8[ o * 2 + 1 ] = lpc_output[ o + lpc_extra ];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( sample->flags & IT_SAMPLE_16BIT )
|
||||
{
|
||||
s16 = ( signed short * ) sample->data;
|
||||
s16 += offset;
|
||||
for ( o = 0; o < lpc_samples; o++ )
|
||||
{
|
||||
lpc_input[ o ] = s16[ o ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s8 = ( signed char * ) sample->data;
|
||||
s8 += offset;
|
||||
for ( o = 0; o < lpc_samples; o++ )
|
||||
{
|
||||
lpc_input[ o ] = s8[ o ];
|
||||
}
|
||||
}
|
||||
|
||||
vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order );
|
||||
|
||||
vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra );
|
||||
|
||||
if ( sample->flags & IT_SAMPLE_16BIT )
|
||||
{
|
||||
s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * sizeof(short) );
|
||||
sample->data = s16;
|
||||
|
||||
s16 += sample->length;
|
||||
sample->length += lpc_extra;
|
||||
|
||||
for ( o = 0; o < lpc_extra; o++ )
|
||||
{
|
||||
s16[ o ] = lpc_output[ o ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s8 = ( signed char * ) realloc( sample->data, sample->length + lpc_extra );
|
||||
sample->data = s8;
|
||||
|
||||
s8 += sample->length;
|
||||
sample->length += lpc_extra;
|
||||
|
||||
for ( o = 0; o < lpc_extra; o++ )
|
||||
{
|
||||
s8[ o ] = lpc_output[ o ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Otherwise, pad with silence. */
|
||||
{
|
||||
offset = sample->length;
|
||||
lpc_samples = lpc_extra;
|
||||
|
||||
sample->length += lpc_samples;
|
||||
|
||||
n = 1;
|
||||
if ( sample->flags & IT_SAMPLE_STEREO ) n *= 2;
|
||||
if ( sample->flags & IT_SAMPLE_16BIT ) n *= 2;
|
||||
|
||||
offset *= n;
|
||||
lpc_samples *= n;
|
||||
|
||||
sample->data = realloc( sample->data, offset + lpc_samples );
|
||||
memset( (char*)sample->data + offset, 0, lpc_samples );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,96 +1,117 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* memfile.c - Module for reading data from / / \ \
|
||||
* memory using a DUMBFILE. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
typedef struct MEMFILE MEMFILE;
|
||||
|
||||
struct MEMFILE
|
||||
{
|
||||
const char *ptr;
|
||||
long left;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int dumb_memfile_skip(void *f, long n)
|
||||
{
|
||||
MEMFILE *m = f;
|
||||
if (n > m->left) return -1;
|
||||
m->ptr += n;
|
||||
m->left -= n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dumb_memfile_getc(void *f)
|
||||
{
|
||||
MEMFILE *m = f;
|
||||
if (m->left <= 0) return -1;
|
||||
m->left--;
|
||||
return *(const unsigned char *)m->ptr++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long dumb_memfile_getnc(char *ptr, long n, void *f)
|
||||
{
|
||||
MEMFILE *m = f;
|
||||
if (n > m->left) n = m->left;
|
||||
memcpy(ptr, m->ptr, n);
|
||||
m->ptr += n;
|
||||
m->left -= n;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void dumb_memfile_close(void *f)
|
||||
{
|
||||
free(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static DUMBFILE_SYSTEM memfile_dfs = {
|
||||
NULL,
|
||||
&dumb_memfile_skip,
|
||||
&dumb_memfile_getc,
|
||||
&dumb_memfile_getnc,
|
||||
&dumb_memfile_close
|
||||
};
|
||||
|
||||
|
||||
|
||||
DUMBFILE *dumbfile_open_memory(const char *data, long size)
|
||||
{
|
||||
MEMFILE *m = malloc(sizeof(*m));
|
||||
if (!m) return NULL;
|
||||
|
||||
m->ptr = data;
|
||||
m->left = size;
|
||||
|
||||
return dumbfile_open_ex(m, &memfile_dfs);
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* memfile.c - Module for reading data from / / \ \
|
||||
* memory using a DUMBFILE. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
typedef struct MEMFILE MEMFILE;
|
||||
|
||||
struct MEMFILE
|
||||
{
|
||||
const char *ptr, *ptr_begin;
|
||||
long left, size;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int dumb_memfile_skip(void *f, long n)
|
||||
{
|
||||
MEMFILE *m = f;
|
||||
if (n > m->left) return -1;
|
||||
m->ptr += n;
|
||||
m->left -= n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dumb_memfile_getc(void *f)
|
||||
{
|
||||
MEMFILE *m = f;
|
||||
if (m->left <= 0) return -1;
|
||||
m->left--;
|
||||
return *(const unsigned char *)m->ptr++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long dumb_memfile_getnc(char *ptr, long n, void *f)
|
||||
{
|
||||
MEMFILE *m = f;
|
||||
if (n > m->left) n = m->left;
|
||||
memcpy(ptr, m->ptr, n);
|
||||
m->ptr += n;
|
||||
m->left -= n;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void dumb_memfile_close(void *f)
|
||||
{
|
||||
free(f);
|
||||
}
|
||||
|
||||
|
||||
static int dumb_memfile_seek(void *f, long n)
|
||||
{
|
||||
MEMFILE *m = f;
|
||||
|
||||
m->ptr = m->ptr_begin + n;
|
||||
m->left = m->size - n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long dumb_memfile_get_size(void *f)
|
||||
{
|
||||
MEMFILE *m = f;
|
||||
return m->size;
|
||||
}
|
||||
|
||||
|
||||
static const DUMBFILE_SYSTEM memfile_dfs = {
|
||||
NULL,
|
||||
&dumb_memfile_skip,
|
||||
&dumb_memfile_getc,
|
||||
&dumb_memfile_getnc,
|
||||
&dumb_memfile_close,
|
||||
&dumb_memfile_seek,
|
||||
&dumb_memfile_get_size
|
||||
};
|
||||
|
||||
|
||||
|
||||
DUMBFILE *dumbfile_open_memory(const char *data, long size)
|
||||
{
|
||||
MEMFILE *m = malloc(sizeof(*m));
|
||||
if (!m) return NULL;
|
||||
|
||||
m->ptr_begin = data;
|
||||
m->ptr = data;
|
||||
m->left = size;
|
||||
m->size = size;
|
||||
|
||||
return dumbfile_open_ex(m, &memfile_dfs);
|
||||
}
|
||||
|
|
|
@ -1,134 +1,179 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* resamp2.inc - Resampling helper template. / / \ \
|
||||
* | < / \_
|
||||
* By Bob and entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* In order to find a good trade-off between | \ / /
|
||||
* speed and accuracy in this code, some tests | ' /
|
||||
* were carried out regarding the behaviour of \__/
|
||||
* long long ints with gcc. The following code
|
||||
* was tested:
|
||||
*
|
||||
* int a, b, c;
|
||||
* c = ((long long)a * b) >> 16;
|
||||
*
|
||||
* DJGPP GCC Version 3.0.3 generated the following assembly language code for
|
||||
* the multiplication and scaling, leaving the 32-bit result in EAX.
|
||||
*
|
||||
* movl -8(%ebp), %eax ; read one int into EAX
|
||||
* imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
|
||||
* shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
|
||||
*
|
||||
* Note that a 32*32->64 multiplication is performed, allowing for high
|
||||
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
|
||||
* so it is a minor concern when four multiplications are being performed
|
||||
* (the cubic resampler). On the Pentium MMX and earlier, it takes four or
|
||||
* more cycles, so this method is unsuitable for use in the low-quality
|
||||
* resamplers.
|
||||
*
|
||||
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
|
||||
* defined in dumb.h. We may investigate later what code MSVC generates, but
|
||||
* if it seems too slow then we suggest you use a good compiler.
|
||||
*
|
||||
* FIXME: these comments are somewhat out of date now.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#define SUFFIX3 _1
|
||||
|
||||
/* For convenience, returns nonzero on stop. */
|
||||
static int process_pickup(DUMB_RESAMPLER *resampler)
|
||||
{
|
||||
if (resampler->overshot < 0) {
|
||||
resampler->overshot = 0;
|
||||
dumb_resample(resampler, NULL, 2, MONO_DEST_VOLUME_ZEROS, 1.0f); /* Doesn't matter which SUFFIX3. */
|
||||
COPYSRC(resampler->X, 0, resampler->X, 1);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
SRCTYPE *src = resampler->src;
|
||||
|
||||
if (resampler->dir < 0) {
|
||||
if (resampler->overshot >= 3 && resampler->pos+3 >= resampler->start) COPYSRC(resampler->X, 0, src, resampler->pos+3);
|
||||
if (resampler->overshot >= 2 && resampler->pos+2 >= resampler->start) COPYSRC(resampler->X, 1, src, resampler->pos+2);
|
||||
if (resampler->overshot >= 1 && resampler->pos+1 >= resampler->start) COPYSRC(resampler->X, 2, src, resampler->pos+1);
|
||||
resampler->overshot = resampler->start - resampler->pos - 1;
|
||||
} else {
|
||||
if (resampler->overshot >= 3 && resampler->pos-3 < resampler->end) COPYSRC(resampler->X, 0, src, resampler->pos-3);
|
||||
if (resampler->overshot >= 2 && resampler->pos-2 < resampler->end) COPYSRC(resampler->X, 1, src, resampler->pos-2);
|
||||
if (resampler->overshot >= 1 && resampler->pos-1 < resampler->end) COPYSRC(resampler->X, 2, src, resampler->pos-1);
|
||||
resampler->overshot = resampler->pos - resampler->end;
|
||||
}
|
||||
|
||||
if (resampler->overshot < 0) {
|
||||
resampler->overshot = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!resampler->pickup) {
|
||||
resampler->dir = 0;
|
||||
return 1;
|
||||
}
|
||||
(*resampler->pickup)(resampler, resampler->pickup_data);
|
||||
if (resampler->dir == 0) return 1;
|
||||
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Create mono destination resampler. */
|
||||
/* SUFFIX3 was set above. */
|
||||
#define VOLUME_PARAMETERS MONO_DEST_VOLUME_PARAMETERS
|
||||
#define VOLUME_VARIABLES MONO_DEST_VOLUME_VARIABLES
|
||||
#define SET_VOLUME_VARIABLES SET_MONO_DEST_VOLUME_VARIABLES
|
||||
#define VOLUMES_ARE_ZERO MONO_DEST_VOLUMES_ARE_ZERO
|
||||
#define MIX_ALIAS(op, offset) MONO_DEST_MIX_ALIAS(op, offset)
|
||||
#define MIX_LINEAR(op, o0, o1) MONO_DEST_MIX_LINEAR(op, o0, o1)
|
||||
#define MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) MONO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3)
|
||||
#define MIX_ZEROS(op) *dst++ op 0
|
||||
#include "resamp3.inc"
|
||||
|
||||
/* Create stereo destination resampler. */
|
||||
#define SUFFIX3 _2
|
||||
#define VOLUME_PARAMETERS float volume_left, float volume_right
|
||||
#define VOLUME_VARIABLES lvol, rvol
|
||||
#define SET_VOLUME_VARIABLES { \
|
||||
lvol = (int)floor(volume_left * 65536.0 + 0.5); \
|
||||
rvol = (int)floor(volume_right * 65536.0 + 0.5); \
|
||||
}
|
||||
#define VOLUMES_ARE_ZERO (lvol == 0 && rvol == 0)
|
||||
#define MIX_ALIAS(op, offset) STEREO_DEST_MIX_ALIAS(op, offset)
|
||||
#define MIX_LINEAR(op, o0, o1) STEREO_DEST_MIX_LINEAR(op, o0, o1)
|
||||
#define MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) STEREO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3)
|
||||
#define MIX_ZEROS(op) { *dst++ op 0; *dst++ op 0; }
|
||||
#include "resamp3.inc"
|
||||
|
||||
|
||||
|
||||
#undef STEREO_DEST_MIX_CUBIC
|
||||
#undef MONO_DEST_MIX_CUBIC
|
||||
#undef STEREO_DEST_MIX_LINEAR
|
||||
#undef MONO_DEST_MIX_LINEAR
|
||||
#undef STEREO_DEST_MIX_ALIAS
|
||||
#undef MONO_DEST_MIX_ALIAS
|
||||
#undef MONO_DEST_VOLUMES_ARE_ZERO
|
||||
#undef SET_MONO_DEST_VOLUME_VARIABLES
|
||||
#undef MONO_DEST_VOLUME_ZEROS
|
||||
#undef MONO_DEST_VOLUME_VARIABLES
|
||||
#undef MONO_DEST_VOLUME_PARAMETERS
|
||||
#undef COPYSRC2
|
||||
#undef COPYSRC
|
||||
#undef DIVIDE_BY_SRC_CHANNELS
|
||||
#undef SRC_CHANNELS
|
||||
#undef SUFFIX2
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* resamp2.inc - Resampling helper template. / / \ \
|
||||
* | < / \_
|
||||
* By Bob and entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* In order to find a good trade-off between | \ / /
|
||||
* speed and accuracy in this code, some tests | ' /
|
||||
* were carried out regarding the behaviour of \__/
|
||||
* long long ints with gcc. The following code
|
||||
* was tested:
|
||||
*
|
||||
* int a, b, c;
|
||||
* c = ((long long)a * b) >> 16;
|
||||
*
|
||||
* DJGPP GCC Version 3.0.3 generated the following assembly language code for
|
||||
* the multiplication and scaling, leaving the 32-bit result in EAX.
|
||||
*
|
||||
* movl -8(%ebp), %eax ; read one int into EAX
|
||||
* imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
|
||||
* shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
|
||||
*
|
||||
* Note that a 32*32->64 multiplication is performed, allowing for high
|
||||
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
|
||||
* so it is a minor concern when four multiplications are being performed
|
||||
* (the cubic resampler). On the Pentium MMX and earlier, it takes four or
|
||||
* more cycles, so this method is unsuitable for use in the low-quality
|
||||
* resamplers.
|
||||
*
|
||||
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
|
||||
* defined in dumb.h. We may investigate later what code MSVC generates, but
|
||||
* if it seems too slow then we suggest you use a good compiler.
|
||||
*
|
||||
* FIXME: these comments are somewhat out of date now.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#define SUFFIX3 _1
|
||||
|
||||
/* For convenience, returns nonzero on stop. */
|
||||
static int process_pickup(DUMB_RESAMPLER *resampler)
|
||||
{
|
||||
if (resampler->overshot < 0) {
|
||||
resampler->overshot = 0;
|
||||
dumb_resample(resampler, NULL, 2, MONO_DEST_VOLUME_ZEROS, 1.0f); /* Doesn't matter which SUFFIX3. */
|
||||
COPYSRC(resampler->X, 0, resampler->X, 1);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
SRCTYPE *src = resampler->src;
|
||||
|
||||
if (resampler->dir < 0) {
|
||||
if (resampler->overshot >= 3 && resampler->pos+3 >= resampler->start) COPYSRC(resampler->X, 0, src, resampler->pos+3);
|
||||
if (resampler->overshot >= 2 && resampler->pos+2 >= resampler->start) COPYSRC(resampler->X, 1, src, resampler->pos+2);
|
||||
if (resampler->overshot >= 1 && resampler->pos+1 >= resampler->start) COPYSRC(resampler->X, 2, src, resampler->pos+1);
|
||||
resampler->overshot = resampler->start - resampler->pos - 1;
|
||||
} else {
|
||||
if (resampler->overshot >= 3 && resampler->pos-3 < resampler->end) COPYSRC(resampler->X, 0, src, resampler->pos-3);
|
||||
if (resampler->overshot >= 2 && resampler->pos-2 < resampler->end) COPYSRC(resampler->X, 1, src, resampler->pos-2);
|
||||
if (resampler->overshot >= 1 && resampler->pos-1 < resampler->end) COPYSRC(resampler->X, 2, src, resampler->pos-1);
|
||||
resampler->overshot = resampler->pos - resampler->end;
|
||||
}
|
||||
|
||||
if (resampler->overshot < 0) {
|
||||
resampler->overshot = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!resampler->pickup) {
|
||||
resampler->dir = 0;
|
||||
return 1;
|
||||
}
|
||||
(*resampler->pickup)(resampler, resampler->pickup_data);
|
||||
if (resampler->dir == 0) return 1;
|
||||
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Create mono destination resampler. */
|
||||
/* SUFFIX3 was set above. */
|
||||
#define VOLUME_PARAMETERS MONO_DEST_VOLUME_PARAMETERS
|
||||
#define VOLUME_VARIABLES MONO_DEST_VOLUME_VARIABLES
|
||||
#define SET_VOLUME_VARIABLES SET_MONO_DEST_VOLUME_VARIABLES
|
||||
#define RETURN_VOLUME_VARIABLES RETURN_MONO_DEST_VOLUME_VARIABLES
|
||||
#define VOLUMES_ARE_ZERO MONO_DEST_VOLUMES_ARE_ZERO
|
||||
#define MIX_ALIAS(count) MONO_DEST_MIX_ALIAS(count)
|
||||
#define PEEK_ALIAS MONO_DEST_PEEK_ALIAS
|
||||
#define PEEK_FIR MONO_DEST_PEEK_FIR
|
||||
#define MIX_FIR MONO_DEST_MIX_FIR
|
||||
#define MIX_LINEAR(op, upd, o0, o1) MONO_DEST_MIX_LINEAR(op, upd, o0, o1)
|
||||
#define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) MONO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
|
||||
#define MIX_ZEROS(op) *dst++ op 0
|
||||
#include "resamp3.inc"
|
||||
|
||||
/* Create stereo destination resampler. */
|
||||
#define SUFFIX3 _2
|
||||
#define VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right
|
||||
#define VOLUME_VARIABLES lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm
|
||||
#define SET_VOLUME_VARIABLES { \
|
||||
if ( volume_left ) { \
|
||||
lvolr = (int)(volume_left->volume * 16777216.0); \
|
||||
lvold = (int)(volume_left->delta * 16777216.0); \
|
||||
lvolt = (int)(volume_left->target * 16777216.0); \
|
||||
lvolm = (int)(volume_left->mix * 16777216.0); \
|
||||
lvol = MULSCV( lvolr, lvolm ); \
|
||||
if ( lvolr == lvolt ) volume_left = NULL; \
|
||||
} else { \
|
||||
lvol = 0; \
|
||||
lvold = 0; \
|
||||
lvolt = 0; \
|
||||
lvolm = 0; \
|
||||
} \
|
||||
if ( volume_right ) { \
|
||||
rvolr = (int)(volume_right->volume * 16777216.0); \
|
||||
rvold = (int)(volume_right->delta * 16777216.0); \
|
||||
rvolt = (int)(volume_right->target * 16777216.0); \
|
||||
rvolm = (int)(volume_right->mix * 16777216.0); \
|
||||
rvol = MULSCV( rvolr, rvolm ); \
|
||||
if ( rvolr == rvolt ) volume_right = NULL; \
|
||||
} else { \
|
||||
rvol = 0; \
|
||||
rvold = 0; \
|
||||
rvolt = 0; \
|
||||
rvolm = 0; \
|
||||
} \
|
||||
}
|
||||
#define RETURN_VOLUME_VARIABLES { \
|
||||
if ( volume_left ) volume_left->volume = (float)lvolr / 16777216.0f; \
|
||||
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
||||
}
|
||||
#define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
||||
#define MIX_ALIAS(count) STEREO_DEST_MIX_ALIAS(count)
|
||||
#define PEEK_ALIAS STEREO_DEST_PEEK_ALIAS
|
||||
#define PEEK_FIR STEREO_DEST_PEEK_FIR
|
||||
#define MIX_FIR STEREO_DEST_MIX_FIR
|
||||
#define MIX_LINEAR(op, upd, o0, o1) STEREO_DEST_MIX_LINEAR(op, upd, o0, o1)
|
||||
#define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) STEREO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
|
||||
#define MIX_ZEROS(op) { *dst++ op 0; *dst++ op 0; }
|
||||
#include "resamp3.inc"
|
||||
|
||||
|
||||
|
||||
#undef STEREO_DEST_MIX_CUBIC
|
||||
#undef MONO_DEST_MIX_CUBIC
|
||||
#undef STEREO_DEST_MIX_LINEAR
|
||||
#undef MONO_DEST_MIX_LINEAR
|
||||
#undef STEREO_DEST_MIX_ALIAS
|
||||
#undef MONO_DEST_MIX_ALIAS
|
||||
#undef MONO_DEST_VOLUMES_ARE_ZERO
|
||||
#undef SET_MONO_DEST_VOLUME_VARIABLES
|
||||
#undef RETURN_MONO_DEST_VOLUME_VARIABLES
|
||||
#undef MONO_DEST_VOLUME_ZEROS
|
||||
#undef MONO_DEST_VOLUME_VARIABLES
|
||||
#undef MONO_DEST_VOLUME_PARAMETERS
|
||||
#undef STEREO_DEST_PEEK_ALIAS
|
||||
#undef MONO_DEST_PEEK_ALIAS
|
||||
#undef POKE_ALIAS
|
||||
#undef MONO_DEST_PEEK_FIR
|
||||
#undef STEREO_DEST_PEEK_FIR
|
||||
#undef MONO_DEST_MIX_FIR
|
||||
#undef STEREO_DEST_MIX_FIR
|
||||
#undef ADVANCE_FIR
|
||||
#undef POKE_FIR
|
||||
#undef COPYSRC2
|
||||
#undef COPYSRC
|
||||
#undef DIVIDE_BY_SRC_CHANNELS
|
||||
#undef SRC_CHANNELS
|
||||
#undef SUFFIX2
|
||||
|
|
|
@ -1,371 +1,441 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* resamp3.inc - Resampling helper template. / / \ \
|
||||
* | < / \_
|
||||
* By Bob and entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* In order to find a good trade-off between | \ / /
|
||||
* speed and accuracy in this code, some tests | ' /
|
||||
* were carried out regarding the behaviour of \__/
|
||||
* long long ints with gcc. The following code
|
||||
* was tested:
|
||||
*
|
||||
* int a, b, c;
|
||||
* c = ((long long)a * b) >> 16;
|
||||
*
|
||||
* DJGPP GCC Version 3.0.3 generated the following assembly language code for
|
||||
* the multiplication and scaling, leaving the 32-bit result in EAX.
|
||||
*
|
||||
* movl -8(%ebp), %eax ; read one int into EAX
|
||||
* imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
|
||||
* shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
|
||||
*
|
||||
* Note that a 32*32->64 multiplication is performed, allowing for high
|
||||
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
|
||||
* so it is a minor concern when four multiplications are being performed
|
||||
* (the cubic resampler). On the Pentium MMX and earlier, it takes four or
|
||||
* more cycles, so this method is unsuitable for use in the low-quality
|
||||
* resamplers.
|
||||
*
|
||||
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
|
||||
* defined in dumb.h. We may investigate later what code MSVC generates, but
|
||||
* if it seems too slow then we suggest you use a good compiler.
|
||||
*
|
||||
* FIXME: these comments are somewhat out of date now.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLUME_PARAMETERS, float delta)
|
||||
{
|
||||
int dt;
|
||||
int VOLUME_VARIABLES;
|
||||
long done;
|
||||
long todo;
|
||||
int quality;
|
||||
|
||||
if (!resampler || resampler->dir == 0) return 0;
|
||||
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
||||
|
||||
done = 0;
|
||||
dt = (int)(delta * 65536.0 + 0.5);
|
||||
SET_VOLUME_VARIABLES;
|
||||
|
||||
if (VOLUMES_ARE_ZERO) dst = NULL;
|
||||
|
||||
init_cubic();
|
||||
|
||||
quality = dumb_resampling_quality;
|
||||
if (quality > resampler->max_quality) quality = resampler->max_quality;
|
||||
else if (quality < resampler->min_quality) quality = resampler->min_quality;
|
||||
|
||||
while (done < dst_size) {
|
||||
if (process_pickup(resampler)) return done;
|
||||
|
||||
if ((resampler->dir ^ dt) < 0)
|
||||
dt = -dt;
|
||||
|
||||
if (resampler->dir < 0)
|
||||
todo = (long)((((LONG_LONG)(resampler->pos - resampler->start) << 16) + resampler->subpos - dt) / -dt);
|
||||
else
|
||||
todo = (long)((((LONG_LONG)(resampler->end - resampler->pos) << 16) - resampler->subpos - 1 + dt) / dt);
|
||||
|
||||
if (todo < 0)
|
||||
todo = 0;
|
||||
else if (todo > dst_size - done)
|
||||
todo = dst_size - done;
|
||||
|
||||
done += todo;
|
||||
|
||||
{
|
||||
SRCTYPE *src = resampler->src;
|
||||
long pos = resampler->pos;
|
||||
int subpos = resampler->subpos;
|
||||
long diff = pos;
|
||||
long overshot;
|
||||
if (resampler->dir < 0) {
|
||||
if (!dst) {
|
||||
/* Silence or simulation */
|
||||
LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo;
|
||||
pos += (long)(new_subpos >> 16);
|
||||
subpos = (long)new_subpos & 65535;
|
||||
} else if (quality <= DUMB_RQ_ALIASING) {
|
||||
/* Aliasing, backwards */
|
||||
SRCTYPE xbuf[2*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[0];
|
||||
SRCTYPE *xstart;
|
||||
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||
while (todo && x < &xbuf[2*SRC_CHANNELS]) {
|
||||
// TODO: check what happens when multiple tempo slides occur per row
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
MIX_ALIAS(+=, 0);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x -= (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
todo--;
|
||||
}
|
||||
x = xstart = &src[pos*SRC_CHANNELS];
|
||||
LOOP4(todo,
|
||||
MIX_ALIAS(+=, 2);
|
||||
subpos += dt;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
);
|
||||
pos += DIVIDE_BY_SRC_CHANNELS(x - xstart);
|
||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||
/* Linear interpolation, backwards */
|
||||
SRCTYPE xbuf[3*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[1*SRC_CHANNELS];
|
||||
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||
COPYSRC(xbuf, 2, src, pos);
|
||||
while (todo && x < &xbuf[3*SRC_CHANNELS]) {
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
MIX_LINEAR(+=, 0, -1);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x -= (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
todo--;
|
||||
}
|
||||
// TODO: use xstart for others too
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
LOOP4(todo,
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
MIX_LINEAR(+=, 1, 2);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
);
|
||||
} else {
|
||||
/* Cubic interpolation, backwards */
|
||||
SRCTYPE xbuf[6*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[3*SRC_CHANNELS];
|
||||
COPYSRC(xbuf, 0, resampler->X, 0);
|
||||
COPYSRC(xbuf, 1, resampler->X, 1);
|
||||
COPYSRC(xbuf, 2, resampler->X, 2);
|
||||
COPYSRC(xbuf, 3, src, pos);
|
||||
if (pos-1 >= resampler->start) COPYSRC(xbuf, 4, src, pos-1);
|
||||
if (pos-2 >= resampler->start) COPYSRC(xbuf, 5, src, pos-2);
|
||||
while (todo && x < &xbuf[6*SRC_CHANNELS]) {
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
MIX_CUBIC(+=, x, x, 0, -1, -2, -3);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x -= (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
todo--;
|
||||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
LOOP4(todo,
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
MIX_CUBIC(+=, x, x, 0, 1, 2, 3);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
);
|
||||
}
|
||||
diff = diff - pos;
|
||||
overshot = resampler->start - pos - 1;
|
||||
if (diff >= 3) {
|
||||
COPYSRC2(resampler->X, 0, overshot < 3, src, pos+3);
|
||||
COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
|
||||
} else if (diff >= 2) {
|
||||
COPYSRC(resampler->X, 0, resampler->X, 2);
|
||||
COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
|
||||
} else if (diff >= 1) {
|
||||
COPYSRC(resampler->X, 0, resampler->X, 1);
|
||||
COPYSRC(resampler->X, 1, resampler->X, 2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
|
||||
}
|
||||
} else {
|
||||
if (!dst) {
|
||||
/* Silence or simulation */
|
||||
LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo;
|
||||
pos += (long)(new_subpos >> 16);
|
||||
subpos = (long)new_subpos & 65535;
|
||||
} else if (dumb_resampling_quality <= DUMB_RQ_ALIASING) {
|
||||
/* Aliasing, forwards */
|
||||
SRCTYPE xbuf[2*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[0];
|
||||
SRCTYPE *xstart;
|
||||
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||
while (todo && x < &xbuf[2*SRC_CHANNELS]) {
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
MIX_ALIAS(+=, 0);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
todo--;
|
||||
}
|
||||
x = xstart = &src[pos*SRC_CHANNELS];
|
||||
LOOP4(todo,
|
||||
MIX_ALIAS(+=, -2);
|
||||
subpos += dt;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
);
|
||||
pos += DIVIDE_BY_SRC_CHANNELS(x - xstart);
|
||||
} else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) {
|
||||
/* Linear interpolation, forwards */
|
||||
SRCTYPE xbuf[3*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[1*SRC_CHANNELS];
|
||||
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||
COPYSRC(xbuf, 2, src, pos);
|
||||
while (todo && x < &xbuf[3*SRC_CHANNELS]) {
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
MIX_LINEAR(+=, -1, 0);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
todo--;
|
||||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
LOOP4(todo,
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
MIX_LINEAR(+=, -2, -1);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
);
|
||||
} else {
|
||||
/* Cubic interpolation, forwards */
|
||||
SRCTYPE xbuf[6*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[3*SRC_CHANNELS];
|
||||
COPYSRC(xbuf, 0, resampler->X, 0);
|
||||
COPYSRC(xbuf, 1, resampler->X, 1);
|
||||
COPYSRC(xbuf, 2, resampler->X, 2);
|
||||
COPYSRC(xbuf, 3, src, pos);
|
||||
if (pos+1 < resampler->end) COPYSRC(xbuf, 4, src, pos+1);
|
||||
if (pos+2 < resampler->end) COPYSRC(xbuf, 5, src, pos+2);
|
||||
while (todo && x < &xbuf[6*SRC_CHANNELS]) {
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
MIX_CUBIC(+=, x, x, -3, -2, -1, 0);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
todo--;
|
||||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
LOOP4(todo,
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
MIX_CUBIC(+=, x, x, -3, -2, -1, 0);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
);
|
||||
}
|
||||
diff = pos - diff;
|
||||
overshot = pos - resampler->end;
|
||||
if (diff >= 3) {
|
||||
COPYSRC2(resampler->X, 0, overshot < 3, src, pos-3);
|
||||
COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
|
||||
} else if (diff >= 2) {
|
||||
COPYSRC(resampler->X, 0, resampler->X, 2);
|
||||
COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
|
||||
} else if (diff >= 1) {
|
||||
COPYSRC(resampler->X, 0, resampler->X, 1);
|
||||
COPYSRC(resampler->X, 1, resampler->X, 2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
|
||||
}
|
||||
}
|
||||
resampler->pos = pos;
|
||||
resampler->subpos = subpos;
|
||||
}
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETERS, sample_t *dst)
|
||||
{
|
||||
int VOLUME_VARIABLES;
|
||||
SRCTYPE *src;
|
||||
long pos;
|
||||
int subpos;
|
||||
int quality;
|
||||
SRCTYPE *x;
|
||||
|
||||
if (!resampler || resampler->dir == 0) { MIX_ZEROS(=); return; }
|
||||
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
||||
|
||||
if (process_pickup(resampler)) { MIX_ZEROS(=); return; }
|
||||
|
||||
SET_VOLUME_VARIABLES;
|
||||
|
||||
if (VOLUMES_ARE_ZERO) { MIX_ZEROS(=); return; }
|
||||
|
||||
init_cubic();
|
||||
|
||||
quality = dumb_resampling_quality;
|
||||
if (quality > resampler->max_quality) quality = resampler->max_quality;
|
||||
else if (quality < resampler->min_quality) quality = resampler->min_quality;
|
||||
|
||||
src = resampler->src;
|
||||
pos = resampler->pos;
|
||||
subpos = resampler->subpos;
|
||||
x = resampler->X;
|
||||
|
||||
if (resampler->dir < 0) {
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
if (dumb_resampling_quality <= 0) {
|
||||
/* Aliasing, backwards */
|
||||
MIX_ALIAS(=, 1);
|
||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||
/* Linear interpolation, backwards */
|
||||
MIX_LINEAR(=, 2, 1);
|
||||
} else {
|
||||
/* Cubic interpolation, backwards */
|
||||
MIX_CUBIC(=, src, x, pos, 2, 1, 0);
|
||||
}
|
||||
} else {
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
if (dumb_resampling_quality <= 0) {
|
||||
/* Aliasing */
|
||||
MIX_ALIAS(=, 1);
|
||||
} else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) {
|
||||
/* Linear interpolation, forwards */
|
||||
MIX_LINEAR(=, 1, 2);
|
||||
} else {
|
||||
/* Cubic interpolation, forwards */
|
||||
MIX_CUBIC(=, x, src, 0, 1, 2, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef MIX_ZEROS
|
||||
#undef MIX_CUBIC
|
||||
#undef MIX_LINEAR
|
||||
#undef MIX_ALIAS
|
||||
#undef VOLUMES_ARE_ZERO
|
||||
#undef SET_VOLUME_VARIABLES
|
||||
#undef VOLUME_VARIABLES
|
||||
#undef VOLUME_PARAMETERS
|
||||
#undef SUFFIX3
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* resamp3.inc - Resampling helper template. / / \ \
|
||||
* | < / \_
|
||||
* By Bob and entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* In order to find a good trade-off between | \ / /
|
||||
* speed and accuracy in this code, some tests | ' /
|
||||
* were carried out regarding the behaviour of \__/
|
||||
* long long ints with gcc. The following code
|
||||
* was tested:
|
||||
*
|
||||
* int a, b, c;
|
||||
* c = ((long long)a * b) >> 16;
|
||||
*
|
||||
* DJGPP GCC Version 3.0.3 generated the following assembly language code for
|
||||
* the multiplication and scaling, leaving the 32-bit result in EAX.
|
||||
*
|
||||
* movl -8(%ebp), %eax ; read one int into EAX
|
||||
* imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
|
||||
* shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
|
||||
*
|
||||
* Note that a 32*32->64 multiplication is performed, allowing for high
|
||||
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
|
||||
* so it is a minor concern when four multiplications are being performed
|
||||
* (the cubic resampler). On the Pentium MMX and earlier, it takes four or
|
||||
* more cycles, so this method is unsuitable for use in the low-quality
|
||||
* resamplers.
|
||||
*
|
||||
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
|
||||
* defined in dumb.h. We may investigate later what code MSVC generates, but
|
||||
* if it seems too slow then we suggest you use a good compiler.
|
||||
*
|
||||
* FIXME: these comments are somewhat out of date now.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLUME_PARAMETERS, float delta)
|
||||
{
|
||||
int dt, inv_dt;
|
||||
int VOLUME_VARIABLES;
|
||||
long done;
|
||||
long todo;
|
||||
LONG_LONG todo64;
|
||||
int quality;
|
||||
int blip_samples[256*SRC_CHANNELS];
|
||||
|
||||
if (!resampler || resampler->dir == 0) return 0;
|
||||
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
||||
|
||||
done = 0;
|
||||
dt = (int)(delta * 65536.0 + 0.5);
|
||||
if (dt == 0 || dt == (int)-0x80000000) return 0;
|
||||
inv_dt = (int)(1.0 / delta * 65536.0 + 0.5);
|
||||
SET_VOLUME_VARIABLES;
|
||||
|
||||
if (VOLUMES_ARE_ZERO) dst = NULL;
|
||||
|
||||
init_cubic();
|
||||
|
||||
quality = resampler->quality;
|
||||
|
||||
while (done < dst_size) {
|
||||
if (process_pickup(resampler)) {
|
||||
RETURN_VOLUME_VARIABLES;
|
||||
return done;
|
||||
}
|
||||
|
||||
if ((resampler->dir ^ dt) < 0)
|
||||
dt = -dt;
|
||||
|
||||
if (resampler->dir < 0)
|
||||
todo64 = ((((LONG_LONG)(resampler->pos - resampler->start) << 16) + resampler->subpos - dt) / -dt);
|
||||
else
|
||||
todo64 = ((((LONG_LONG)(resampler->end - resampler->pos) << 16) - resampler->subpos - 1 + dt) / dt);
|
||||
|
||||
if (todo64 < 0)
|
||||
todo = 0;
|
||||
else if (todo64 > dst_size - done)
|
||||
todo = dst_size - done;
|
||||
else
|
||||
todo = (long) todo64;
|
||||
|
||||
done += todo;
|
||||
|
||||
{
|
||||
SRCTYPE *src = resampler->src;
|
||||
long pos = resampler->pos;
|
||||
int subpos = resampler->subpos;
|
||||
long diff = pos;
|
||||
long overshot;
|
||||
if (resampler->dir < 0) {
|
||||
if (!dst) {
|
||||
/* Silence or simulation */
|
||||
LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo;
|
||||
pos += (long)(new_subpos >> 16);
|
||||
subpos = (long)new_subpos & 65535;
|
||||
} else if (quality <= DUMB_RQ_ALIASING) {
|
||||
/* Aliasing, backwards */
|
||||
int todo_clocks = todo << 16, todo_clocks_set = todo_clocks;
|
||||
SRCTYPE xbuf[2*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[0];
|
||||
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||
while (resampler->last_clock < todo_clocks_set && x < &xbuf[2*SRC_CHANNELS]) {
|
||||
// TODO: check what happens when multiple tempo slides occur per row
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
POKE_ALIAS(0);
|
||||
pos--;
|
||||
x += SRC_CHANNELS;
|
||||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
while ( todo_clocks ) {
|
||||
todo_clocks_set = todo_clocks;
|
||||
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||
todo_clocks -= todo_clocks_set;
|
||||
while ( resampler->last_clock < todo_clocks_set )
|
||||
{
|
||||
POKE_ALIAS(2);
|
||||
pos--;
|
||||
x -= SRC_CHANNELS;
|
||||
}
|
||||
todo = todo_clocks_set >> 16;
|
||||
MIX_ALIAS( todo );
|
||||
}
|
||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||
/* Linear interpolation, backwards */
|
||||
SRCTYPE xbuf[3*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[1*SRC_CHANNELS];
|
||||
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||
COPYSRC(xbuf, 2, src, pos);
|
||||
while (todo && x < &xbuf[3*SRC_CHANNELS]) {
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
MIX_LINEAR(+=, 1, 0, -1);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x -= (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
todo--;
|
||||
}
|
||||
// TODO: use xstart for others too
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
LOOP4(todo,
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
MIX_LINEAR(+=, 1, 1, 2);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
);
|
||||
} else if (quality <= DUMB_RQ_CUBIC) {
|
||||
/* Cubic interpolation, backwards */
|
||||
SRCTYPE xbuf[6*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[3*SRC_CHANNELS];
|
||||
COPYSRC(xbuf, 0, resampler->X, 0);
|
||||
COPYSRC(xbuf, 1, resampler->X, 1);
|
||||
COPYSRC(xbuf, 2, resampler->X, 2);
|
||||
COPYSRC(xbuf, 3, src, pos);
|
||||
if (pos-1 >= resampler->start) COPYSRC(xbuf, 4, src, pos-1);
|
||||
if (pos-2 >= resampler->start) COPYSRC(xbuf, 5, src, pos-2);
|
||||
while (todo && x < &xbuf[6*SRC_CHANNELS]) {
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
MIX_CUBIC(+=, 1, x, x, 0, -1, -2, -3);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x -= (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
todo--;
|
||||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
LOOP4(todo,
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
MIX_CUBIC(+=, 1, x, x, 0, 1, 2, 3);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
);
|
||||
} else {
|
||||
/* FIR resampling, backwards */
|
||||
SRCTYPE *x;
|
||||
if ( resampler->fir_resampler_ratio != delta ) {
|
||||
lanczos_resampler_set_rate( resampler->fir_resampler[0], delta );
|
||||
lanczos_resampler_set_rate( resampler->fir_resampler[1], delta );
|
||||
resampler->fir_resampler_ratio = delta;
|
||||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
while ( todo ) {
|
||||
while ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
|
||||
pos >= resampler->start )
|
||||
{
|
||||
POKE_FIR(0);
|
||||
pos--;
|
||||
x -= SRC_CHANNELS;
|
||||
}
|
||||
if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
|
||||
MIX_FIR;
|
||||
ADVANCE_FIR;
|
||||
--todo;
|
||||
}
|
||||
done -= todo;
|
||||
}
|
||||
diff = diff - pos;
|
||||
overshot = resampler->start - pos - 1;
|
||||
if (diff >= 3) {
|
||||
COPYSRC2(resampler->X, 0, overshot < 3, src, pos+3);
|
||||
COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
|
||||
} else if (diff >= 2) {
|
||||
COPYSRC(resampler->X, 0, resampler->X, 2);
|
||||
COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
|
||||
} else if (diff >= 1) {
|
||||
COPYSRC(resampler->X, 0, resampler->X, 1);
|
||||
COPYSRC(resampler->X, 1, resampler->X, 2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
|
||||
}
|
||||
} else {
|
||||
if (!dst) {
|
||||
/* Silence or simulation */
|
||||
LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo;
|
||||
pos += (long)(new_subpos >> 16);
|
||||
subpos = (long)new_subpos & 65535;
|
||||
} else if (quality <= DUMB_RQ_ALIASING) {
|
||||
/* Aliasing, forwards */
|
||||
int todo_clocks = todo << 16, todo_clocks_set = todo_clocks;
|
||||
SRCTYPE xbuf[2*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[0];
|
||||
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||
while (resampler->last_clock < todo_clocks_set && x < &xbuf[2*SRC_CHANNELS]) {
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
POKE_ALIAS(0);
|
||||
pos++;
|
||||
x += SRC_CHANNELS;
|
||||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
while ( todo_clocks ) {
|
||||
todo_clocks_set = todo_clocks;
|
||||
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||
todo_clocks -= todo_clocks_set;
|
||||
while ( resampler->last_clock < todo_clocks_set )
|
||||
{
|
||||
POKE_ALIAS(-2);
|
||||
pos++;
|
||||
x += SRC_CHANNELS;
|
||||
}
|
||||
todo = todo_clocks_set >> 16;
|
||||
MIX_ALIAS( todo );
|
||||
}
|
||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||
/* Linear interpolation, forwards */
|
||||
SRCTYPE xbuf[3*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[1*SRC_CHANNELS];
|
||||
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||
COPYSRC(xbuf, 2, src, pos);
|
||||
while (todo && x < &xbuf[3*SRC_CHANNELS]) {
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
MIX_LINEAR(+=, 1, -1, 0);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
todo--;
|
||||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
LOOP4(todo,
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
MIX_LINEAR(+=, 1, -2, -1);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
);
|
||||
} else if (quality <= DUMB_RQ_CUBIC) {
|
||||
/* Cubic interpolation, forwards */
|
||||
SRCTYPE xbuf[6*SRC_CHANNELS];
|
||||
SRCTYPE *x = &xbuf[3*SRC_CHANNELS];
|
||||
COPYSRC(xbuf, 0, resampler->X, 0);
|
||||
COPYSRC(xbuf, 1, resampler->X, 1);
|
||||
COPYSRC(xbuf, 2, resampler->X, 2);
|
||||
COPYSRC(xbuf, 3, src, pos);
|
||||
if (pos+1 < resampler->end) COPYSRC(xbuf, 4, src, pos+1);
|
||||
if (pos+2 < resampler->end) COPYSRC(xbuf, 5, src, pos+2);
|
||||
while (todo && x < &xbuf[6*SRC_CHANNELS]) {
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
MIX_CUBIC(+=, 1, x, x, -3, -2, -1, 0);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
todo--;
|
||||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
LOOP4(todo,
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
MIX_CUBIC(+=, 1, x, x, -3, -2, -1, 0);
|
||||
subpos += dt;
|
||||
pos += subpos >> 16;
|
||||
x += (subpos >> 16) * SRC_CHANNELS;
|
||||
subpos &= 65535;
|
||||
);
|
||||
} else {
|
||||
/* FIR resampling, forwards */
|
||||
SRCTYPE *x;
|
||||
if ( resampler->fir_resampler_ratio != delta ) {
|
||||
lanczos_resampler_set_rate( resampler->fir_resampler[0], delta );
|
||||
lanczos_resampler_set_rate( resampler->fir_resampler[1], delta );
|
||||
resampler->fir_resampler_ratio = delta;
|
||||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
while ( todo ) {
|
||||
while ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
|
||||
pos < resampler->end )
|
||||
{
|
||||
POKE_FIR(0);
|
||||
pos++;
|
||||
x += SRC_CHANNELS;
|
||||
}
|
||||
if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
|
||||
MIX_FIR;
|
||||
ADVANCE_FIR;
|
||||
--todo;
|
||||
}
|
||||
done -= todo;
|
||||
}
|
||||
diff = pos - diff;
|
||||
overshot = pos - resampler->end;
|
||||
if (diff >= 3) {
|
||||
COPYSRC2(resampler->X, 0, overshot < 3, src, pos-3);
|
||||
COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
|
||||
} else if (diff >= 2) {
|
||||
COPYSRC(resampler->X, 0, resampler->X, 2);
|
||||
COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
|
||||
} else if (diff >= 1) {
|
||||
COPYSRC(resampler->X, 0, resampler->X, 1);
|
||||
COPYSRC(resampler->X, 1, resampler->X, 2);
|
||||
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
|
||||
}
|
||||
}
|
||||
resampler->pos = pos;
|
||||
resampler->subpos = subpos;
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_VOLUME_VARIABLES;
|
||||
return done;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETERS, sample_t *dst)
|
||||
{
|
||||
int VOLUME_VARIABLES;
|
||||
SRCTYPE *src;
|
||||
long pos;
|
||||
int subpos;
|
||||
int quality;
|
||||
SRCTYPE *x;
|
||||
|
||||
if (!resampler || resampler->dir == 0) { MIX_ZEROS(=); return; }
|
||||
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
||||
|
||||
if (process_pickup(resampler)) { MIX_ZEROS(=); return; }
|
||||
|
||||
SET_VOLUME_VARIABLES;
|
||||
|
||||
if (VOLUMES_ARE_ZERO) { MIX_ZEROS(=); return; }
|
||||
|
||||
init_cubic();
|
||||
|
||||
quality = resampler->quality;
|
||||
|
||||
src = resampler->src;
|
||||
pos = resampler->pos;
|
||||
subpos = resampler->subpos;
|
||||
x = resampler->X;
|
||||
|
||||
if (resampler->dir < 0) {
|
||||
HEAVYASSERT(pos >= resampler->start);
|
||||
if (quality <= DUMB_RQ_ALIASING) {
|
||||
/* Aliasing, backwards */
|
||||
PEEK_ALIAS;
|
||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||
/* Linear interpolation, backwards */
|
||||
MIX_LINEAR(=, 0, 2, 1);
|
||||
} else if (quality <= DUMB_RQ_CUBIC) {
|
||||
/* Cubic interpolation, backwards */
|
||||
MIX_CUBIC(=, 0, src, x, pos, 2, 1, 0);
|
||||
} else {
|
||||
/* FIR resampling, backwards */
|
||||
PEEK_FIR;
|
||||
}
|
||||
} else {
|
||||
HEAVYASSERT(pos < resampler->end);
|
||||
if (quality <= DUMB_RQ_ALIASING) {
|
||||
/* Aliasing */
|
||||
PEEK_ALIAS;
|
||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||
/* Linear interpolation, forwards */
|
||||
MIX_LINEAR(=, 0, 1, 2);
|
||||
} else if (quality <= DUMB_RQ_CUBIC) {
|
||||
/* Cubic interpolation, forwards */
|
||||
MIX_CUBIC(=, 0, x, src, 0, 1, 2, pos);
|
||||
} else {
|
||||
/* FIR resampling, forwards */
|
||||
PEEK_FIR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef MIX_ZEROS
|
||||
#undef MIX_CUBIC
|
||||
#undef MIX_LINEAR
|
||||
#undef MIX_ALIAS
|
||||
#undef MIX_FIR
|
||||
#undef PEEK_ALIAS
|
||||
#undef PEEK_FIR
|
||||
#undef VOLUMES_ARE_ZERO
|
||||
#undef SET_VOLUME_VARIABLES
|
||||
#undef RETURN_VOLUME_VARIABLES
|
||||
#undef VOLUME_VARIABLES
|
||||
#undef VOLUME_PARAMETERS
|
||||
#undef SUFFIX3
|
||||
|
|
|
@ -1,385 +1,410 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* resample.c - Resampling helpers. / / \ \
|
||||
* | < / \_
|
||||
* By Bob and entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* In order to find a good trade-off between | \ / /
|
||||
* speed and accuracy in this code, some tests | ' /
|
||||
* were carried out regarding the behaviour of \__/
|
||||
* long long ints with gcc. The following code
|
||||
* was tested:
|
||||
*
|
||||
* int a, b, c;
|
||||
* c = ((long long)a * b) >> 16;
|
||||
*
|
||||
* DJGPP GCC Version 3.0.3 generated the following assembly language code for
|
||||
* the multiplication and scaling, leaving the 32-bit result in EAX.
|
||||
*
|
||||
* movl -8(%ebp), %eax ; read one int into EAX
|
||||
* imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
|
||||
* shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
|
||||
*
|
||||
* Note that a 32*32->64 multiplication is performed, allowing for high
|
||||
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
|
||||
* so it is a minor concern when four multiplications are being performed
|
||||
* (the cubic resampler). On the Pentium MMX and earlier, it takes four or
|
||||
* more cycles, so this method is unsuitable for use in the low-quality
|
||||
* resamplers.
|
||||
*
|
||||
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
|
||||
* defined in dumb.h. We may investigate later what code MSVC generates, but
|
||||
* if it seems too slow then we suggest you use a good compiler.
|
||||
*
|
||||
* FIXME: these comments are somewhat out of date now.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
/* Compile with -DHEAVYDEBUG if you want to make sure the pick-up function is
|
||||
* called when it should be. There will be a considerable performance hit,
|
||||
* since at least one condition has to be tested for every sample generated.
|
||||
*/
|
||||
#ifdef HEAVYDEBUG
|
||||
#define HEAVYASSERT(cond) ASSERT(cond)
|
||||
#else
|
||||
#define HEAVYASSERT(cond)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* A global variable for controlling resampling quality wherever a local
|
||||
* specification doesn't override it. The following values are valid:
|
||||
*
|
||||
* 0 - DUMB_RQ_ALIASING - fastest
|
||||
* 1 - DUMB_RQ_LINEAR
|
||||
* 2 - DUMB_RQ_CUBIC - nicest
|
||||
*
|
||||
* Values outside the range 0-2 will behave the same as the nearest
|
||||
* value within the range.
|
||||
*/
|
||||
int dumb_resampling_quality = DUMB_RQ_CUBIC;
|
||||
|
||||
|
||||
|
||||
//#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16))
|
||||
//#define MULSC(a, b) ((a) * ((b) >> 2) >> 14)
|
||||
#define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32))
|
||||
#define MULSC16(a, b) ((int)((LONG_LONG)((a) << 12) * ((b) << 12) >> 32))
|
||||
|
||||
|
||||
|
||||
/* Executes the content 'iterator' times.
|
||||
* Clobbers the 'iterator' variable.
|
||||
* The loop is unrolled by four.
|
||||
*/
|
||||
#define LOOP4(iterator, CONTENT) \
|
||||
{ \
|
||||
if ((iterator) & 2) { \
|
||||
CONTENT; \
|
||||
CONTENT; \
|
||||
} \
|
||||
if ((iterator) & 1) { \
|
||||
CONTENT; \
|
||||
} \
|
||||
(iterator) >>= 2; \
|
||||
while (iterator) { \
|
||||
CONTENT; \
|
||||
CONTENT; \
|
||||
CONTENT; \
|
||||
CONTENT; \
|
||||
(iterator)--; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define PASTERAW(a, b) a ## b /* This does not expand macros in b ... */
|
||||
#define PASTE(a, b) PASTERAW(a, b) /* ... but b is expanded during this substitution. */
|
||||
|
||||
#define X PASTE(x.x, SRCBITS)
|
||||
|
||||
|
||||
|
||||
/* Cubic resampler: look-up tables
|
||||
*
|
||||
* a = 1.5*x1 - 1.5*x2 + 0.5*x3 - 0.5*x0
|
||||
* b = 2*x2 + x0 - 2.5*x1 - 0.5*x3
|
||||
* c = 0.5*x2 - 0.5*x0
|
||||
* d = x1
|
||||
*
|
||||
* x = a*t*t*t + b*t*t + c*t + d
|
||||
* = (-0.5*x0 + 1.5*x1 - 1.5*x2 + 0.5*x3) * t*t*t +
|
||||
* ( 1*x0 - 2.5*x1 + 2 *x2 - 0.5*x3) * t*t +
|
||||
* (-0.5*x0 + 0.5*x2 ) * t +
|
||||
* ( 1*x1 )
|
||||
* = (-0.5*t*t*t + 1 *t*t - 0.5*t ) * x0 +
|
||||
* ( 1.5*t*t*t - 2.5*t*t + 1) * x1 +
|
||||
* (-1.5*t*t*t + 2 *t*t + 0.5*t ) * x2 +
|
||||
* ( 0.5*t*t*t - 0.5*t*t ) * x3
|
||||
* = A0(t) * x0 + A1(t) * x1 + A2(t) * x2 + A3(t) * x3
|
||||
*
|
||||
* A0, A1, A2 and A3 stay within the range [-1,1].
|
||||
* In the tables, they are scaled with 14 fractional bits.
|
||||
*
|
||||
* Turns out we don't need to store A2 and A3; they are symmetrical to A1 and A0.
|
||||
*
|
||||
* TODO: A0 and A3 stay very small indeed. Consider different scale/resolution?
|
||||
*/
|
||||
|
||||
static short cubicA0[1025], cubicA1[1025];
|
||||
|
||||
static void init_cubic(void)
|
||||
{
|
||||
unsigned int t; /* 3*1024*1024*1024 is within range if it's unsigned */
|
||||
static int done = 0;
|
||||
if (done) return;
|
||||
done = 1;
|
||||
for (t = 0; t < 1025; t++) {
|
||||
/* int casts to pacify warnings about negating unsigned values */
|
||||
cubicA0[t] = -(int)( t*t*t >> 17) + (int)( t*t >> 6) - (int)(t << 3);
|
||||
cubicA1[t] = (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Create resamplers for 24-in-32-bit source samples. */
|
||||
|
||||
/* #define SUFFIX
|
||||
* MSVC warns if we try to paste a null SUFFIX, so instead we define
|
||||
* special macros for the function names that don't bother doing the
|
||||
* corresponding paste. The more generic definitions are further down.
|
||||
*/
|
||||
#define process_pickup PASTE(process_pickup, SUFFIX2)
|
||||
#define dumb_resample PASTE(PASTE(dumb_resample, SUFFIX2), SUFFIX3)
|
||||
#define dumb_resample_get_current_sample PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX2), SUFFIX3)
|
||||
|
||||
#define SRCTYPE sample_t
|
||||
#define SRCBITS 24
|
||||
#define ALIAS(x, vol) MULSC(x, vol)
|
||||
#define LINEAR(x0, x1) (x0 + MULSC(x1 - x0, subpos))
|
||||
/*
|
||||
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
||||
a = (3 * (x1 - x2) + (x3 - x0)) >> 1; \
|
||||
b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) >> 1; \
|
||||
c = (x2 - x0) >> 1; \
|
||||
}
|
||||
#define CUBIC(d) MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + d, vol)
|
||||
*/
|
||||
#define CUBIC(x0, x1, x2, x3) ( \
|
||||
MULSC(x0, cubicA0[subpos >> 6] << 2) + \
|
||||
MULSC(x1, cubicA1[subpos >> 6] << 2) + \
|
||||
MULSC(x2, cubicA1[1 + (subpos >> 6 ^ 1023)] << 2) + \
|
||||
MULSC(x3, cubicA0[1 + (subpos >> 6 ^ 1023)] << 2))
|
||||
#define CUBICVOL(x, vol) MULSC(x, vol)
|
||||
#include "resample.inc"
|
||||
|
||||
/* Undefine the simplified macros. */
|
||||
#undef dumb_resample_get_current_sample
|
||||
#undef dumb_resample
|
||||
#undef process_pickup
|
||||
|
||||
|
||||
/* Now define the proper ones that use SUFFIX. */
|
||||
#define dumb_reset_resampler PASTE(dumb_reset_resampler, SUFFIX)
|
||||
#define dumb_start_resampler PASTE(dumb_start_resampler, SUFFIX)
|
||||
#define process_pickup PASTE(PASTE(process_pickup, SUFFIX), SUFFIX2)
|
||||
#define dumb_resample PASTE(PASTE(PASTE(dumb_resample, SUFFIX), SUFFIX2), SUFFIX3)
|
||||
#define dumb_resample_get_current_sample PASTE(PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX), SUFFIX2), SUFFIX3)
|
||||
#define dumb_end_resampler PASTE(dumb_end_resampler, SUFFIX)
|
||||
|
||||
/* Create resamplers for 16-bit source samples. */
|
||||
#define SUFFIX _16
|
||||
#define SRCTYPE short
|
||||
#define SRCBITS 16
|
||||
#define ALIAS(x, vol) (x * vol >> 8)
|
||||
#define LINEAR(x0, x1) ((x0 << 8) + MULSC16(x1 - x0, subpos))
|
||||
/*
|
||||
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
||||
a = (3 * (x1 - x2) + (x3 - x0)) << 7; \
|
||||
b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) << 7; \
|
||||
c = (x2 - x0) << 7; \
|
||||
}
|
||||
#define CUBIC(d) MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + (d << 8), vol)
|
||||
*/
|
||||
#define CUBIC(x0, x1, x2, x3) ( \
|
||||
x0 * cubicA0[subpos >> 6] + \
|
||||
x1 * cubicA1[subpos >> 6] + \
|
||||
x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
|
||||
x3 * cubicA0[1 + (subpos >> 6 ^ 1023)])
|
||||
#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 10) >> 32)
|
||||
#include "resample.inc"
|
||||
|
||||
/* Create resamplers for 8-bit source samples. */
|
||||
#define SUFFIX _8
|
||||
#define SRCTYPE signed char
|
||||
#define SRCBITS 8
|
||||
#define ALIAS(x, vol) (x * vol)
|
||||
#define LINEAR(x0, x1) ((x0 << 16) + (x1 - x0) * subpos)
|
||||
/*
|
||||
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
||||
a = 3 * (x1 - x2) + (x3 - x0); \
|
||||
b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) << 15; \
|
||||
c = (x2 - x0) << 15; \
|
||||
}
|
||||
#define CUBIC(d) MULSC(MULSC(MULSC((a * subpos >> 1) + b, subpos) + c, subpos) + (d << 16), vol)
|
||||
*/
|
||||
#define CUBIC(x0, x1, x2, x3) (( \
|
||||
x0 * cubicA0[subpos >> 6] + \
|
||||
x1 * cubicA1[subpos >> 6] + \
|
||||
x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
|
||||
x3 * cubicA0[1 + (subpos >> 6 ^ 1023)]) << 6)
|
||||
#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 12) >> 32)
|
||||
#include "resample.inc"
|
||||
|
||||
|
||||
#undef dumb_reset_resampler
|
||||
#undef dumb_start_resampler
|
||||
#undef process_pickup
|
||||
#undef dumb_resample
|
||||
#undef dumb_resample_get_current_sample
|
||||
#undef dumb_end_resampler
|
||||
|
||||
|
||||
|
||||
void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src, int src_channels, long pos, long start, long end)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_reset_resampler_8(resampler, src, src_channels, pos, start, end);
|
||||
else if (n == 16)
|
||||
dumb_reset_resampler_16(resampler, src, src_channels, pos, start, end);
|
||||
else
|
||||
dumb_reset_resampler(resampler, src, src_channels, pos, start, end);
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels, long pos, long start, long end)
|
||||
{
|
||||
if (n == 8)
|
||||
return dumb_start_resampler_8(src, src_channels, pos, start, end);
|
||||
else if (n == 16)
|
||||
return dumb_start_resampler_16(src, src_channels, pos, start, end);
|
||||
else
|
||||
return dumb_start_resampler(src, src_channels, pos, start, end);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta)
|
||||
{
|
||||
if (n == 8)
|
||||
return dumb_resample_8_1_1(resampler, dst, dst_size, volume, delta);
|
||||
else if (n == 16)
|
||||
return dumb_resample_16_1_1(resampler, dst, dst_size, volume, delta);
|
||||
else
|
||||
return dumb_resample_1_1(resampler, dst, dst_size, volume, delta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumb_resample_n_1_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta)
|
||||
{
|
||||
if (n == 8)
|
||||
return dumb_resample_8_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else if (n == 16)
|
||||
return dumb_resample_16_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else
|
||||
return dumb_resample_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumb_resample_n_2_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta)
|
||||
{
|
||||
if (n == 8)
|
||||
return dumb_resample_8_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else if (n == 16)
|
||||
return dumb_resample_16_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else
|
||||
return dumb_resample_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumb_resample_n_2_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta)
|
||||
{
|
||||
if (n == 8)
|
||||
return dumb_resample_8_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else if (n == 16)
|
||||
return dumb_resample_16_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else
|
||||
return dumb_resample_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler, float volume, sample_t *dst)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_resample_get_current_sample_8_1_1(resampler, volume, dst);
|
||||
else if (n == 16)
|
||||
dumb_resample_get_current_sample_16_1_1(resampler, volume, dst);
|
||||
else
|
||||
dumb_resample_get_current_sample_1_1(resampler, volume, dst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_resample_get_current_sample_8_1_2(resampler, volume_left, volume_right, dst);
|
||||
else if (n == 16)
|
||||
dumb_resample_get_current_sample_16_1_2(resampler, volume_left, volume_right, dst);
|
||||
else
|
||||
dumb_resample_get_current_sample_1_2(resampler, volume_left, volume_right, dst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_resample_get_current_sample_8_2_1(resampler, volume_left, volume_right, dst);
|
||||
else if (n == 16)
|
||||
dumb_resample_get_current_sample_16_2_1(resampler, volume_left, volume_right, dst);
|
||||
else
|
||||
dumb_resample_get_current_sample_2_1(resampler, volume_left, volume_right, dst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_resample_get_current_sample_8_2_2(resampler, volume_left, volume_right, dst);
|
||||
else if (n == 16)
|
||||
dumb_resample_get_current_sample_16_2_2(resampler, volume_left, volume_right, dst);
|
||||
else
|
||||
dumb_resample_get_current_sample_2_2(resampler, volume_left, volume_right, dst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_end_resampler_8(resampler);
|
||||
else if (n == 16)
|
||||
dumb_end_resampler_16(resampler);
|
||||
else
|
||||
dumb_end_resampler(resampler);
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* resample.c - Resampling helpers. / / \ \
|
||||
* | < / \_
|
||||
* By Bob and entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* In order to find a good trade-off between | \ / /
|
||||
* speed and accuracy in this code, some tests | ' /
|
||||
* were carried out regarding the behaviour of \__/
|
||||
* long long ints with gcc. The following code
|
||||
* was tested:
|
||||
*
|
||||
* int a, b, c;
|
||||
* c = ((long long)a * b) >> 16;
|
||||
*
|
||||
* DJGPP GCC Version 3.0.3 generated the following assembly language code for
|
||||
* the multiplication and scaling, leaving the 32-bit result in EAX.
|
||||
*
|
||||
* movl -8(%ebp), %eax ; read one int into EAX
|
||||
* imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
|
||||
* shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
|
||||
*
|
||||
* Note that a 32*32->64 multiplication is performed, allowing for high
|
||||
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
|
||||
* so it is a minor concern when four multiplications are being performed
|
||||
* (the cubic resampler). On the Pentium MMX and earlier, it takes four or
|
||||
* more cycles, so this method is unsuitable for use in the low-quality
|
||||
* resamplers.
|
||||
*
|
||||
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
|
||||
* defined in dumb.h. We may investigate later what code MSVC generates, but
|
||||
* if it seems too slow then we suggest you use a good compiler.
|
||||
*
|
||||
* FIXME: these comments are somewhat out of date now.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "dumb.h"
|
||||
|
||||
#include "internal/blip_buf.h"
|
||||
#include "internal/lanczos_resampler.h"
|
||||
|
||||
|
||||
|
||||
/* Compile with -DHEAVYDEBUG if you want to make sure the pick-up function is
|
||||
* called when it should be. There will be a considerable performance hit,
|
||||
* since at least one condition has to be tested for every sample generated.
|
||||
*/
|
||||
#ifdef HEAVYDEBUG
|
||||
#define HEAVYASSERT(cond) ASSERT(cond)
|
||||
#else
|
||||
#define HEAVYASSERT(cond)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Make MSVC shut the hell up about if ( upd ) UPDATE_VOLUME() conditions being constant */
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4127 4701)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* A global variable for controlling resampling quality wherever a local
|
||||
* specification doesn't override it. The following values are valid:
|
||||
*
|
||||
* 0 - DUMB_RQ_ALIASING - fastest
|
||||
* 1 - DUMB_RQ_LINEAR
|
||||
* 2 - DUMB_RQ_CUBIC
|
||||
* 3 - DUMB_RQ_FIR - nicest
|
||||
*
|
||||
* Values outside the range 0-3 will behave the same as the nearest
|
||||
* value within the range.
|
||||
*/
|
||||
int dumb_resampling_quality = DUMB_RQ_CUBIC;
|
||||
|
||||
|
||||
|
||||
//#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16))
|
||||
//#define MULSC(a, b) ((a) * ((b) >> 2) >> 14)
|
||||
#define MULSCV(a, b) ((int)((LONG_LONG)(a) * (b) >> 32))
|
||||
#define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32))
|
||||
#define MULSC16(a, b) ((int)((LONG_LONG)((a) << 12) * ((b) << 12) >> 32))
|
||||
|
||||
|
||||
|
||||
/* Executes the content 'iterator' times.
|
||||
* Clobbers the 'iterator' variable.
|
||||
* The loop is unrolled by four.
|
||||
*/
|
||||
#if 0
|
||||
#define LOOP4(iterator, CONTENT) \
|
||||
{ \
|
||||
if ((iterator) & 2) { \
|
||||
CONTENT; \
|
||||
CONTENT; \
|
||||
} \
|
||||
if ((iterator) & 1) { \
|
||||
CONTENT; \
|
||||
} \
|
||||
(iterator) >>= 2; \
|
||||
while (iterator) { \
|
||||
CONTENT; \
|
||||
CONTENT; \
|
||||
CONTENT; \
|
||||
CONTENT; \
|
||||
(iterator)--; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LOOP4(iterator, CONTENT) \
|
||||
{ \
|
||||
while ( (iterator)-- ) \
|
||||
{ \
|
||||
CONTENT; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define PASTERAW(a, b) a ## b /* This does not expand macros in b ... */
|
||||
#define PASTE(a, b) PASTERAW(a, b) /* ... but b is expanded during this substitution. */
|
||||
|
||||
#define X PASTE(x.x, SRCBITS)
|
||||
|
||||
|
||||
|
||||
/* Cubic resampler: look-up tables
|
||||
*
|
||||
* a = 1.5*x1 - 1.5*x2 + 0.5*x3 - 0.5*x0
|
||||
* b = 2*x2 + x0 - 2.5*x1 - 0.5*x3
|
||||
* c = 0.5*x2 - 0.5*x0
|
||||
* d = x1
|
||||
*
|
||||
* x = a*t*t*t + b*t*t + c*t + d
|
||||
* = (-0.5*x0 + 1.5*x1 - 1.5*x2 + 0.5*x3) * t*t*t +
|
||||
* ( 1*x0 - 2.5*x1 + 2 *x2 - 0.5*x3) * t*t +
|
||||
* (-0.5*x0 + 0.5*x2 ) * t +
|
||||
* ( 1*x1 )
|
||||
* = (-0.5*t*t*t + 1 *t*t - 0.5*t ) * x0 +
|
||||
* ( 1.5*t*t*t - 2.5*t*t + 1) * x1 +
|
||||
* (-1.5*t*t*t + 2 *t*t + 0.5*t ) * x2 +
|
||||
* ( 0.5*t*t*t - 0.5*t*t ) * x3
|
||||
* = A0(t) * x0 + A1(t) * x1 + A2(t) * x2 + A3(t) * x3
|
||||
*
|
||||
* A0, A1, A2 and A3 stay within the range [-1,1].
|
||||
* In the tables, they are scaled with 14 fractional bits.
|
||||
*
|
||||
* Turns out we don't need to store A2 and A3; they are symmetrical to A1 and A0.
|
||||
*
|
||||
* TODO: A0 and A3 stay very small indeed. Consider different scale/resolution?
|
||||
*/
|
||||
|
||||
static short cubicA0[1025], cubicA1[1025];
|
||||
|
||||
/*static*/ void init_cubic(void)
|
||||
{
|
||||
unsigned int t; /* 3*1024*1024*1024 is within range if it's unsigned */
|
||||
static int done = 0;
|
||||
if (done) return;
|
||||
done = 1;
|
||||
for (t = 0; t < 1025; t++) {
|
||||
/* int casts to pacify warnings about negating unsigned values */
|
||||
cubicA0[t] = -(int)( t*t*t >> 17) + (int)( t*t >> 6) - (int)(t << 3);
|
||||
cubicA1[t] = (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14);
|
||||
}
|
||||
|
||||
lanczos_init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Create resamplers for 24-in-32-bit source samples. */
|
||||
|
||||
/* #define SUFFIX
|
||||
* MSVC warns if we try to paste a null SUFFIX, so instead we define
|
||||
* special macros for the function names that don't bother doing the
|
||||
* corresponding paste. The more generic definitions are further down.
|
||||
*/
|
||||
#define process_pickup PASTE(process_pickup, SUFFIX2)
|
||||
#define dumb_resample PASTE(PASTE(dumb_resample, SUFFIX2), SUFFIX3)
|
||||
#define dumb_resample_get_current_sample PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX2), SUFFIX3)
|
||||
|
||||
#define SRCTYPE sample_t
|
||||
#define SRCBITS 24
|
||||
#define ALIAS(x) (x >> 8)
|
||||
#define FIR(x) (x >> 8)
|
||||
#define LINEAR(x0, x1) (x0 + MULSC(x1 - x0, subpos))
|
||||
/*
|
||||
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
||||
a = (3 * (x1 - x2) + (x3 - x0)) >> 1; \
|
||||
b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) >> 1; \
|
||||
c = (x2 - x0) >> 1; \
|
||||
}
|
||||
#define CUBIC(d) MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + d, vol)
|
||||
*/
|
||||
#define CUBIC(x0, x1, x2, x3) ( \
|
||||
MULSC(x0, cubicA0[subpos >> 6] << 2) + \
|
||||
MULSC(x1, cubicA1[subpos >> 6] << 2) + \
|
||||
MULSC(x2, cubicA1[1 + (subpos >> 6 ^ 1023)] << 2) + \
|
||||
MULSC(x3, cubicA0[1 + (subpos >> 6 ^ 1023)] << 2))
|
||||
#define CUBICVOL(x, vol) MULSC(x, vol)
|
||||
#include "resample.inc"
|
||||
|
||||
/* Undefine the simplified macros. */
|
||||
#undef dumb_resample_get_current_sample
|
||||
#undef dumb_resample
|
||||
#undef process_pickup
|
||||
|
||||
|
||||
/* Now define the proper ones that use SUFFIX. */
|
||||
#define dumb_reset_resampler PASTE(dumb_reset_resampler, SUFFIX)
|
||||
#define dumb_start_resampler PASTE(dumb_start_resampler, SUFFIX)
|
||||
#define process_pickup PASTE(PASTE(process_pickup, SUFFIX), SUFFIX2)
|
||||
#define dumb_resample PASTE(PASTE(PASTE(dumb_resample, SUFFIX), SUFFIX2), SUFFIX3)
|
||||
#define dumb_resample_get_current_sample PASTE(PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX), SUFFIX2), SUFFIX3)
|
||||
#define dumb_end_resampler PASTE(dumb_end_resampler, SUFFIX)
|
||||
|
||||
/* Create resamplers for 16-bit source samples. */
|
||||
#define SUFFIX _16
|
||||
#define SRCTYPE short
|
||||
#define SRCBITS 16
|
||||
#define ALIAS(x) (x)
|
||||
#define FIR(x) (x)
|
||||
#define LINEAR(x0, x1) ((x0 << 8) + MULSC16(x1 - x0, subpos))
|
||||
/*
|
||||
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
||||
a = (3 * (x1 - x2) + (x3 - x0)) << 7; \
|
||||
b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) << 7; \
|
||||
c = (x2 - x0) << 7; \
|
||||
}
|
||||
#define CUBIC(d) MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + (d << 8), vol)
|
||||
*/
|
||||
#define CUBIC(x0, x1, x2, x3) ( \
|
||||
x0 * cubicA0[subpos >> 6] + \
|
||||
x1 * cubicA1[subpos >> 6] + \
|
||||
x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
|
||||
x3 * cubicA0[1 + (subpos >> 6 ^ 1023)])
|
||||
#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 10) >> 32)
|
||||
#include "resample.inc"
|
||||
|
||||
/* Create resamplers for 8-bit source samples. */
|
||||
#define SUFFIX _8
|
||||
#define SRCTYPE signed char
|
||||
#define SRCBITS 8
|
||||
#define ALIAS(x) (x << 8)
|
||||
#define FIR(x) (x << 8)
|
||||
#define LINEAR(x0, x1) ((x0 << 16) + (x1 - x0) * subpos)
|
||||
/*
|
||||
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
||||
a = 3 * (x1 - x2) + (x3 - x0); \
|
||||
b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) << 15; \
|
||||
c = (x2 - x0) << 15; \
|
||||
}
|
||||
#define CUBIC(d) MULSC(MULSC(MULSC((a * subpos >> 1) + b, subpos) + c, subpos) + (d << 16), vol)
|
||||
*/
|
||||
#define CUBIC(x0, x1, x2, x3) (( \
|
||||
x0 * cubicA0[subpos >> 6] + \
|
||||
x1 * cubicA1[subpos >> 6] + \
|
||||
x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
|
||||
x3 * cubicA0[1 + (subpos >> 6 ^ 1023)]) << 6)
|
||||
#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 12) >> 32)
|
||||
#include "resample.inc"
|
||||
|
||||
|
||||
#undef dumb_reset_resampler
|
||||
#undef dumb_start_resampler
|
||||
#undef process_pickup
|
||||
#undef dumb_resample
|
||||
#undef dumb_resample_get_current_sample
|
||||
#undef dumb_end_resampler
|
||||
|
||||
|
||||
|
||||
void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src, int src_channels, long pos, long start, long end, int quality)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_reset_resampler_8(resampler, src, src_channels, pos, start, end, quality);
|
||||
else if (n == 16)
|
||||
dumb_reset_resampler_16(resampler, src, src_channels, pos, start, end, quality);
|
||||
else
|
||||
dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels, long pos, long start, long end, int quality)
|
||||
{
|
||||
if (n == 8)
|
||||
return dumb_start_resampler_8(src, src_channels, pos, start, end, quality);
|
||||
else if (n == 16)
|
||||
return dumb_start_resampler_16(src, src_channels, pos, start, end, quality);
|
||||
else
|
||||
return dumb_start_resampler(src, src_channels, pos, start, end, quality);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta)
|
||||
{
|
||||
if (n == 8)
|
||||
return dumb_resample_8_1_1(resampler, dst, dst_size, volume, delta);
|
||||
else if (n == 16)
|
||||
return dumb_resample_16_1_1(resampler, dst, dst_size, volume, delta);
|
||||
else
|
||||
return dumb_resample_1_1(resampler, dst, dst_size, volume, delta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumb_resample_n_1_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta)
|
||||
{
|
||||
if (n == 8)
|
||||
return dumb_resample_8_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else if (n == 16)
|
||||
return dumb_resample_16_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else
|
||||
return dumb_resample_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumb_resample_n_2_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta)
|
||||
{
|
||||
if (n == 8)
|
||||
return dumb_resample_8_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else if (n == 16)
|
||||
return dumb_resample_16_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else
|
||||
return dumb_resample_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
long dumb_resample_n_2_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta)
|
||||
{
|
||||
if (n == 8)
|
||||
return dumb_resample_8_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else if (n == 16)
|
||||
return dumb_resample_16_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
else
|
||||
return dumb_resample_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_resample_get_current_sample_8_1_1(resampler, volume, dst);
|
||||
else if (n == 16)
|
||||
dumb_resample_get_current_sample_16_1_1(resampler, volume, dst);
|
||||
else
|
||||
dumb_resample_get_current_sample_1_1(resampler, volume, dst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_resample_get_current_sample_8_1_2(resampler, volume_left, volume_right, dst);
|
||||
else if (n == 16)
|
||||
dumb_resample_get_current_sample_16_1_2(resampler, volume_left, volume_right, dst);
|
||||
else
|
||||
dumb_resample_get_current_sample_1_2(resampler, volume_left, volume_right, dst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_resample_get_current_sample_8_2_1(resampler, volume_left, volume_right, dst);
|
||||
else if (n == 16)
|
||||
dumb_resample_get_current_sample_16_2_1(resampler, volume_left, volume_right, dst);
|
||||
else
|
||||
dumb_resample_get_current_sample_2_1(resampler, volume_left, volume_right, dst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_resample_get_current_sample_8_2_2(resampler, volume_left, volume_right, dst);
|
||||
else if (n == 16)
|
||||
dumb_resample_get_current_sample_16_2_2(resampler, volume_left, volume_right, dst);
|
||||
else
|
||||
dumb_resample_get_current_sample_2_2(resampler, volume_left, volume_right, dst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler)
|
||||
{
|
||||
if (n == 8)
|
||||
dumb_end_resampler_8(resampler);
|
||||
else if (n == 16)
|
||||
dumb_end_resampler_16(resampler);
|
||||
else
|
||||
dumb_end_resampler(resampler);
|
||||
}
|
||||
|
|
|
@ -1,167 +1,403 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* resample.inc - Resampling helper template. / / \ \
|
||||
* | < / \_
|
||||
* By Bob and entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* In order to find a good trade-off between | \ / /
|
||||
* speed and accuracy in this code, some tests | ' /
|
||||
* were carried out regarding the behaviour of \__/
|
||||
* long long ints with gcc. The following code
|
||||
* was tested:
|
||||
*
|
||||
* int a, b, c;
|
||||
* c = ((long long)a * b) >> 16;
|
||||
*
|
||||
* DJGPP GCC Version 3.0.3 generated the following assembly language code for
|
||||
* the multiplication and scaling, leaving the 32-bit result in EAX.
|
||||
*
|
||||
* movl -8(%ebp), %eax ; read one int into EAX
|
||||
* imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
|
||||
* shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
|
||||
*
|
||||
* Note that a 32*32->64 multiplication is performed, allowing for high
|
||||
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
|
||||
* so it is a minor concern when four multiplications are being performed
|
||||
* (the cubic resampler). On the Pentium MMX and earlier, it takes four or
|
||||
* more cycles, so this method is unsuitable for use in the low-quality
|
||||
* resamplers.
|
||||
*
|
||||
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
|
||||
* defined in dumb.h. We may investigate later what code MSVC generates, but
|
||||
* if it seems too slow then we suggest you use a good compiler.
|
||||
*
|
||||
* FIXME: these comments are somewhat out of date now.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_channels, long pos, long start, long end)
|
||||
{
|
||||
int i;
|
||||
resampler->src = src;
|
||||
resampler->pos = pos;
|
||||
resampler->subpos = 0;
|
||||
resampler->start = start;
|
||||
resampler->end = end;
|
||||
resampler->dir = 1;
|
||||
resampler->pickup = NULL;
|
||||
resampler->pickup_data = NULL;
|
||||
resampler->min_quality = 0;
|
||||
resampler->max_quality = DUMB_RQ_N_LEVELS - 1;
|
||||
for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
|
||||
resampler->overshot = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, long start, long end)
|
||||
{
|
||||
DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
|
||||
if (!resampler) return NULL;
|
||||
dumb_reset_resampler(resampler, src, src_channels, pos, start, end);
|
||||
return resampler;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Create mono source resampler. */
|
||||
#define SUFFIX2 _1
|
||||
#define SRC_CHANNELS 1
|
||||
#define DIVIDE_BY_SRC_CHANNELS(x) (x)
|
||||
#define COPYSRC(dstarray, dstindex, srcarray, srcindex) (dstarray)[dstindex] = (srcarray)[srcindex]
|
||||
#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) (dstarray)[dstindex] = condition ? (srcarray)[srcindex] : 0
|
||||
#define MONO_DEST_VOLUME_PARAMETERS float volume
|
||||
#define MONO_DEST_VOLUME_VARIABLES vol
|
||||
#define MONO_DEST_VOLUME_ZEROS 0
|
||||
#define SET_MONO_DEST_VOLUME_VARIABLES vol = (int)floor(volume * 65536.0 + 0.5)
|
||||
#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0)
|
||||
#define MONO_DEST_MIX_ALIAS(op, offset) *dst++ op ALIAS(x[offset], vol)
|
||||
#define STEREO_DEST_MIX_ALIAS(op, offset) { \
|
||||
int xm = x[offset]; \
|
||||
*dst++ op ALIAS(xm, lvol); \
|
||||
*dst++ op ALIAS(xm, rvol); \
|
||||
}
|
||||
#define MONO_DEST_MIX_LINEAR(op, o0, o1) *dst++ op MULSC(LINEAR(x[o0], x[o1]), vol)
|
||||
#define STEREO_DEST_MIX_LINEAR(op, o0, o1) { \
|
||||
int xm = LINEAR(x[o0], x[o1]); \
|
||||
*dst++ op MULSC(xm, lvol); \
|
||||
*dst++ op MULSC(xm, rvol); \
|
||||
}
|
||||
#define MONO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) *dst++ op CUBICVOL(CUBIC(x0[o0], x[o1], x[o2], x3[o3]), vol)
|
||||
#define STEREO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) { \
|
||||
int xm = CUBIC(x0[o0], x[o1], x[o2], x3[o3]); \
|
||||
*dst++ op CUBICVOL(xm, lvol); \
|
||||
*dst++ op CUBICVOL(xm, rvol); \
|
||||
}
|
||||
#include "resamp2.inc"
|
||||
|
||||
/* Create stereo source resampler. */
|
||||
#define SUFFIX2 _2
|
||||
#define SRC_CHANNELS 2
|
||||
#define DIVIDE_BY_SRC_CHANNELS(x) ((x) >> 1)
|
||||
#define COPYSRC(dstarray, dstindex, srcarray, srcindex) { \
|
||||
(dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \
|
||||
(dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \
|
||||
}
|
||||
#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) { \
|
||||
if (condition) { \
|
||||
(dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \
|
||||
(dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \
|
||||
} else { \
|
||||
(dstarray)[(dstindex)*2] = 0; \
|
||||
(dstarray)[(dstindex)*2+1] = 0; \
|
||||
} \
|
||||
}
|
||||
#define MONO_DEST_VOLUME_PARAMETERS float volume_left, float volume_right
|
||||
#define MONO_DEST_VOLUME_VARIABLES lvol, rvol
|
||||
#define MONO_DEST_VOLUME_ZEROS 0, 0
|
||||
#define SET_MONO_DEST_VOLUME_VARIABLES { \
|
||||
lvol = (int)floor(volume_left * 65536.0 + 0.5); \
|
||||
rvol = (int)floor(volume_right * 65536.0 + 0.5); \
|
||||
}
|
||||
#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && rvol == 0)
|
||||
#define MONO_DEST_MIX_ALIAS(op, offset) *dst++ op ALIAS(x[(offset)*2], lvol) + ALIAS(x[(offset)*2+1], rvol)
|
||||
#define STEREO_DEST_MIX_ALIAS(op, offset) { \
|
||||
*dst++ op ALIAS(x[(offset)*2], lvol); \
|
||||
*dst++ op ALIAS(x[(offset)*2+1], rvol); \
|
||||
}
|
||||
#define MONO_DEST_MIX_LINEAR(op, o0, o1) *dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol) + MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol)
|
||||
#define STEREO_DEST_MIX_LINEAR(op, o0, o1) { \
|
||||
*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol); \
|
||||
*dst++ op MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \
|
||||
}
|
||||
#define MONO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) *dst++ op \
|
||||
CUBICVOL(CUBIC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x3[(o3)*2]), lvol) + \
|
||||
CUBICVOL(CUBIC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x3[(o3)*2+1]), rvol)
|
||||
#define STEREO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) { \
|
||||
*dst++ op CUBICVOL(CUBIC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x3[(o3)*2]), lvol); \
|
||||
*dst++ op CUBICVOL(CUBIC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x3[(o3)*2+1]), rvol); \
|
||||
}
|
||||
#include "resamp2.inc"
|
||||
|
||||
|
||||
|
||||
void dumb_end_resampler(DUMB_RESAMPLER *resampler)
|
||||
{
|
||||
if (resampler)
|
||||
free(resampler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef CUBICVOL
|
||||
#undef CUBIC
|
||||
#undef LINEAR
|
||||
#undef ALIAS
|
||||
#undef SRCBITS
|
||||
#undef SRCTYPE
|
||||
#undef SUFFIX
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* resample.inc - Resampling helper template. / / \ \
|
||||
* | < / \_
|
||||
* By Bob and entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* In order to find a good trade-off between | \ / /
|
||||
* speed and accuracy in this code, some tests | ' /
|
||||
* were carried out regarding the behaviour of \__/
|
||||
* long long ints with gcc. The following code
|
||||
* was tested:
|
||||
*
|
||||
* int a, b, c;
|
||||
* c = ((long long)a * b) >> 16;
|
||||
*
|
||||
* DJGPP GCC Version 3.0.3 generated the following assembly language code for
|
||||
* the multiplication and scaling, leaving the 32-bit result in EAX.
|
||||
*
|
||||
* movl -8(%ebp), %eax ; read one int into EAX
|
||||
* imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
|
||||
* shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
|
||||
*
|
||||
* Note that a 32*32->64 multiplication is performed, allowing for high
|
||||
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
|
||||
* so it is a minor concern when four multiplications are being performed
|
||||
* (the cubic resampler). On the Pentium MMX and earlier, it takes four or
|
||||
* more cycles, so this method is unsuitable for use in the low-quality
|
||||
* resamplers.
|
||||
*
|
||||
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
|
||||
* defined in dumb.h. We may investigate later what code MSVC generates, but
|
||||
* if it seems too slow then we suggest you use a good compiler.
|
||||
*
|
||||
* FIXME: these comments are somewhat out of date now.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_channels, long pos, long start, long end, int quality)
|
||||
{
|
||||
int i;
|
||||
resampler->src = src;
|
||||
resampler->pos = pos;
|
||||
resampler->subpos = 0;
|
||||
resampler->start = start;
|
||||
resampler->end = end;
|
||||
resampler->dir = 1;
|
||||
resampler->pickup = NULL;
|
||||
resampler->pickup_data = NULL;
|
||||
if (quality < 0)
|
||||
{
|
||||
resampler->quality = 0;
|
||||
}
|
||||
else if (quality > DUMB_RQ_N_LEVELS - 1)
|
||||
{
|
||||
resampler->quality = DUMB_RQ_N_LEVELS - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
resampler->quality = quality;
|
||||
}
|
||||
for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
|
||||
resampler->overshot = -1;
|
||||
resampler->last_clock = 0;
|
||||
resampler->last_amp[0] = 0;
|
||||
resampler->last_amp[1] = 0;
|
||||
blip_clear(resampler->blip_buffer[0]);
|
||||
blip_clear(resampler->blip_buffer[1]);
|
||||
resampler->fir_resampler_ratio = 0;
|
||||
lanczos_resampler_clear(resampler->fir_resampler[0]);
|
||||
lanczos_resampler_clear(resampler->fir_resampler[1]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, long start, long end, int quality)
|
||||
{
|
||||
DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
|
||||
if (!resampler) return NULL;
|
||||
resampler->blip_buffer[0] = blip_new( 256 );
|
||||
if (!resampler->blip_buffer[0])
|
||||
{
|
||||
free(resampler);
|
||||
return NULL;
|
||||
}
|
||||
resampler->blip_buffer[1] = blip_new( 256 );
|
||||
if (!resampler->blip_buffer[1])
|
||||
{
|
||||
free(resampler->blip_buffer[0]);
|
||||
free(resampler);
|
||||
return NULL;
|
||||
}
|
||||
blip_set_rates(resampler->blip_buffer[0], 65536, 1);
|
||||
blip_set_rates(resampler->blip_buffer[1], 65536, 1);
|
||||
dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
|
||||
return resampler;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define UPDATE_VOLUME( pvol, vol ) { \
|
||||
if (pvol) { \
|
||||
vol##r += vol##d; \
|
||||
if ((vol##d < 0 && vol##r <= vol##t) || \
|
||||
(vol##d > 0 && vol##r >= vol##t)) { \
|
||||
pvol->volume = pvol->target; \
|
||||
pvol = NULL; \
|
||||
vol = MULSCV( vol##t, vol##m ); \
|
||||
} else { \
|
||||
vol = MULSCV( vol##r, vol##m ); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Create mono source resampler. */
|
||||
#define SUFFIX2 _1
|
||||
#define SRC_CHANNELS 1
|
||||
#define DIVIDE_BY_SRC_CHANNELS(x) (x)
|
||||
#define COPYSRC(dstarray, dstindex, srcarray, srcindex) (dstarray)[dstindex] = (srcarray)[srcindex]
|
||||
#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) (dstarray)[dstindex] = condition ? (srcarray)[srcindex] : 0
|
||||
#define MONO_DEST_VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO * volume
|
||||
#define MONO_DEST_VOLUME_VARIABLES vol, volr, vold, volt, volm
|
||||
#define MONO_DEST_VOLUME_ZEROS 0
|
||||
#define SET_MONO_DEST_VOLUME_VARIABLES { \
|
||||
if ( volume ) { \
|
||||
volr = (int)(volume->volume * 16777216.0); \
|
||||
vold = (int)(volume->delta * 16777216.0); \
|
||||
volt = (int)(volume->target * 16777216.0); \
|
||||
volm = (int)(volume->mix * 16777216.0); \
|
||||
vol = MULSCV( volr, volm ); \
|
||||
if ( volr == volt ) volume = NULL; \
|
||||
} else { \
|
||||
vol = 0; \
|
||||
vold = 0; \
|
||||
volt = 0; \
|
||||
volm = 0; \
|
||||
} \
|
||||
}
|
||||
#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = (float)volr / 16777216.0f
|
||||
#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)
|
||||
#define POKE_ALIAS(offset) { \
|
||||
int delta = ALIAS(x[offset]) - resampler->last_amp[0]; \
|
||||
resampler->last_amp[0] += delta; \
|
||||
if ( delta ) blip_add_delta( resampler->blip_buffer[0], resampler->last_clock, delta ); \
|
||||
resampler->last_clock += inv_dt; \
|
||||
}
|
||||
#define POKE_FIR(offset) { \
|
||||
lanczos_resampler_write_sample( resampler->fir_resampler[0], FIR(x[offset]) ); \
|
||||
}
|
||||
#define MONO_DEST_PEEK_ALIAS *dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), vol )
|
||||
#define MONO_DEST_PEEK_FIR *dst = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), vol )
|
||||
#define MONO_DEST_MIX_FIR { \
|
||||
*dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
|
||||
UPDATE_VOLUME( volume, vol ); \
|
||||
}
|
||||
#define ADVANCE_FIR lanczos_resampler_remove_sample( resampler->fir_resampler[0] )
|
||||
#define MONO_DEST_MIX_ALIAS(count) { \
|
||||
int n = 0; \
|
||||
resampler->last_clock -= count * 65536; \
|
||||
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||
LOOP4( count, \
|
||||
*dst++ += MULSC( blip_samples[n], vol ); \
|
||||
n++; \
|
||||
UPDATE_VOLUME( volume, vol ); \
|
||||
); \
|
||||
}
|
||||
#define STEREO_DEST_PEEK_ALIAS { \
|
||||
int sample = blip_peek_sample( resampler->blip_buffer[0] ); \
|
||||
*dst++ = MULSC( sample, lvol ); \
|
||||
*dst++ = MULSC( sample, rvol ); \
|
||||
}
|
||||
#define STEREO_DEST_PEEK_FIR { \
|
||||
int sample = lanczos_resampler_get_sample( resampler->fir_resampler[0] ); \
|
||||
*dst++ = MULSC( sample, lvol ); \
|
||||
*dst++ = MULSC( sample, rvol ); \
|
||||
}
|
||||
#define STEREO_DEST_MIX_FIR { \
|
||||
int sample = lanczos_resampler_get_sample( resampler->fir_resampler[0] ); \
|
||||
*dst++ += MULSC( sample, lvol ); \
|
||||
*dst++ += MULSC( sample, rvol ); \
|
||||
UPDATE_VOLUME( volume_left, lvol ); \
|
||||
UPDATE_VOLUME( volume_right, rvol ); \
|
||||
}
|
||||
#define STEREO_DEST_MIX_ALIAS(count) { \
|
||||
int sample, n = 0; \
|
||||
resampler->last_clock -= count * 65536; \
|
||||
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||
LOOP4( count, \
|
||||
sample = blip_samples[n++]; \
|
||||
*dst++ += MULSC( sample, lvol ); \
|
||||
*dst++ += MULSC( sample, rvol ); \
|
||||
UPDATE_VOLUME( volume_left, lvol ); \
|
||||
UPDATE_VOLUME( volume_right, rvol ); \
|
||||
); \
|
||||
}
|
||||
#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
||||
*dst++ op MULSC(LINEAR(x[o0], x[o1]), vol); \
|
||||
if ( upd ) UPDATE_VOLUME( volume, vol ); \
|
||||
}
|
||||
#define STEREO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
||||
int xm = LINEAR(x[o0], x[o1]); \
|
||||
*dst++ op MULSC(xm, lvol); \
|
||||
*dst++ op MULSC(xm, rvol); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
|
||||
}
|
||||
#define MONO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) { \
|
||||
*dst++ op CUBICVOL(CUBIC(x0[o0], x[o1], x[o2], x3[o3]), vol); \
|
||||
if ( upd ) UPDATE_VOLUME( volume, vol ); \
|
||||
}
|
||||
#define STEREO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) { \
|
||||
int xm = CUBIC(x0[o0], x[o1], x[o2], x3[o3]); \
|
||||
*dst++ op CUBICVOL(xm, lvol); \
|
||||
*dst++ op CUBICVOL(xm, rvol); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
|
||||
}
|
||||
#include "resamp2.inc"
|
||||
|
||||
/* Create stereo source resampler. */
|
||||
#define SUFFIX2 _2
|
||||
#define SRC_CHANNELS 2
|
||||
#define DIVIDE_BY_SRC_CHANNELS(x) ((x) >> 1)
|
||||
#define COPYSRC(dstarray, dstindex, srcarray, srcindex) { \
|
||||
(dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \
|
||||
(dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \
|
||||
}
|
||||
#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) { \
|
||||
if (condition) { \
|
||||
(dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \
|
||||
(dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \
|
||||
} else { \
|
||||
(dstarray)[(dstindex)*2] = 0; \
|
||||
(dstarray)[(dstindex)*2+1] = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MONO_DEST_VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right
|
||||
#define MONO_DEST_VOLUME_VARIABLES lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm
|
||||
#define MONO_DEST_VOLUME_ZEROS 0, 0
|
||||
#define SET_MONO_DEST_VOLUME_VARIABLES { \
|
||||
if ( volume_left ) { \
|
||||
lvolr = (int)(volume_left->volume * 16777216.0); \
|
||||
lvold = (int)(volume_left->delta * 16777216.0); \
|
||||
lvolt = (int)(volume_left->target * 16777216.0); \
|
||||
lvolm = (int)(volume_left->mix * 16777216.0); \
|
||||
lvol = MULSCV( lvolr, lvolm ); \
|
||||
if ( lvolr == lvolt ) volume_left = NULL; \
|
||||
} else { \
|
||||
lvol = 0; \
|
||||
lvold = 0; \
|
||||
lvolt = 0; \
|
||||
lvolm = 0; \
|
||||
} \
|
||||
if ( volume_right ) { \
|
||||
rvolr = (int)(volume_right->volume * 16777216.0); \
|
||||
rvold = (int)(volume_right->delta * 16777216.0); \
|
||||
rvolt = (int)(volume_right->target * 16777216.0); \
|
||||
rvolm = (int)(volume_right->mix * 16777216.0); \
|
||||
rvol = MULSCV( rvolr, rvolm ); \
|
||||
if ( rvolr == rvolt ) volume_right = NULL; \
|
||||
} else { \
|
||||
rvol = 0; \
|
||||
rvold = 0; \
|
||||
rvolt = 0; \
|
||||
rvolm = 0; \
|
||||
} \
|
||||
}
|
||||
#define RETURN_MONO_DEST_VOLUME_VARIABLES { \
|
||||
if ( volume_left ) volume_left->volume = (float)lvolr / 16777216.0f; \
|
||||
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
||||
}
|
||||
#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
||||
#define POKE_ALIAS(offset) { \
|
||||
int deltal = ALIAS(x[(offset)*2+0]) - resampler->last_amp[0]; \
|
||||
int deltar = ALIAS(x[(offset)*2+1]) - resampler->last_amp[1]; \
|
||||
resampler->last_amp[0] += deltal; \
|
||||
resampler->last_amp[1] += deltar; \
|
||||
if ( deltal ) blip_add_delta( resampler->blip_buffer[0], resampler->last_clock, deltal ); \
|
||||
if ( deltar ) blip_add_delta( resampler->blip_buffer[1], resampler->last_clock, deltar ); \
|
||||
resampler->last_clock += inv_dt; \
|
||||
}
|
||||
#define POKE_FIR(offset) { \
|
||||
lanczos_resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \
|
||||
lanczos_resampler_write_sample( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \
|
||||
}
|
||||
#define MONO_DEST_PEEK_ALIAS { \
|
||||
*dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ) + \
|
||||
MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
|
||||
}
|
||||
#define MONO_DEST_PEEK_FIR { \
|
||||
*dst = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
|
||||
MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
||||
}
|
||||
#define MONO_DEST_MIX_FIR { \
|
||||
*dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
|
||||
MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
||||
UPDATE_VOLUME( volume_left, lvol ); \
|
||||
UPDATE_VOLUME( volume_right, rvol ); \
|
||||
}
|
||||
#define ADVANCE_FIR { \
|
||||
lanczos_resampler_remove_sample( resampler->fir_resampler[0] ); \
|
||||
lanczos_resampler_remove_sample( resampler->fir_resampler[1] ); \
|
||||
}
|
||||
#define MONO_DEST_MIX_ALIAS(count) { \
|
||||
int n = 0; \
|
||||
resampler->last_clock -= count * 65536; \
|
||||
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||
blip_end_frame( resampler->blip_buffer[1], count * 65536 ); \
|
||||
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||
blip_read_samples( resampler->blip_buffer[1], blip_samples + 256, count ); \
|
||||
LOOP4( count, \
|
||||
*dst++ += MULSC( blip_samples[n], lvol ) + MULSC( blip_samples[256+n], rvol ); \
|
||||
n++; \
|
||||
UPDATE_VOLUME( volume_left, lvol ); \
|
||||
UPDATE_VOLUME( volume_right, rvol ); \
|
||||
); \
|
||||
}
|
||||
#define STEREO_DEST_PEEK_ALIAS { \
|
||||
*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ); \
|
||||
*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
|
||||
}
|
||||
#define STEREO_DEST_PEEK_FIR { \
|
||||
*dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
|
||||
*dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
||||
}
|
||||
#define STEREO_DEST_MIX_FIR { \
|
||||
*dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
|
||||
*dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
||||
UPDATE_VOLUME( volume_left, lvol ); \
|
||||
UPDATE_VOLUME( volume_right, rvol ); \
|
||||
}
|
||||
#define STEREO_DEST_MIX_ALIAS(count) { \
|
||||
int n = 0; \
|
||||
resampler->last_clock -= count * 65536; \
|
||||
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||
blip_end_frame( resampler->blip_buffer[1], count * 65536 ); \
|
||||
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||
blip_read_samples( resampler->blip_buffer[1], blip_samples + 256, count ); \
|
||||
LOOP4( count, \
|
||||
*dst++ += MULSC( blip_samples[n], lvol); \
|
||||
*dst++ += MULSC( blip_samples[256+n], rvol); \
|
||||
n++; \
|
||||
UPDATE_VOLUME( volume_left, lvol ); \
|
||||
UPDATE_VOLUME( volume_right, rvol ); \
|
||||
); \
|
||||
}
|
||||
#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
||||
*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol) + MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
|
||||
}
|
||||
#define STEREO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
||||
*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol); \
|
||||
*dst++ op MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
|
||||
}
|
||||
#define MONO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) { \
|
||||
*dst++ op \
|
||||
CUBICVOL(CUBIC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x3[(o3)*2]), lvol) + \
|
||||
CUBICVOL(CUBIC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x3[(o3)*2+1]), rvol); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
|
||||
}
|
||||
#define STEREO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) { \
|
||||
*dst++ op CUBICVOL(CUBIC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x3[(o3)*2]), lvol); \
|
||||
*dst++ op CUBICVOL(CUBIC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x3[(o3)*2+1]), rvol); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
||||
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
|
||||
}
|
||||
#include "resamp2.inc"
|
||||
|
||||
|
||||
|
||||
void dumb_end_resampler(DUMB_RESAMPLER *resampler)
|
||||
{
|
||||
if (resampler)
|
||||
free(resampler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef CUBICVOL
|
||||
#undef CUBIC
|
||||
#undef LINEAR
|
||||
#undef ALIAS
|
||||
#undef FIR
|
||||
#undef SRCBITS
|
||||
#undef SRCTYPE
|
||||
#undef SUFFIX
|
||||
|
|
85
Frameworks/Dumb/dumb/src/helpers/riff.c
Normal file
85
Frameworks/Dumb/dumb/src/helpers/riff.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include "dumb.h"
|
||||
#include "internal/riff.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
struct riff * riff_parse( DUMBFILE * f, long offset, long size, unsigned proper )
|
||||
{
|
||||
unsigned stream_size;
|
||||
struct riff * stream;
|
||||
|
||||
if ( size < 8 ) return 0;
|
||||
|
||||
if ( dumbfile_seek(f, offset, DFS_SEEK_SET) ) return 0;
|
||||
if ( dumbfile_mgetl(f) != DUMB_ID('R','I','F','F') ) return 0;
|
||||
|
||||
stream_size = dumbfile_igetl(f);
|
||||
if ( stream_size + 8 > size ) return 0;
|
||||
if ( stream_size < 4 ) return 0;
|
||||
|
||||
stream = (struct riff *) malloc( sizeof( struct riff ) );
|
||||
if ( ! stream ) return 0;
|
||||
|
||||
stream->type = dumbfile_mgetl(f);
|
||||
stream->chunk_count = 0;
|
||||
stream->chunks = 0;
|
||||
|
||||
stream_size -= 4;
|
||||
|
||||
while ( stream_size && !dumbfile_error(f) )
|
||||
{
|
||||
struct riff_chunk * chunk;
|
||||
if ( stream_size < 8 ) break;
|
||||
stream->chunks = ( struct riff_chunk * ) realloc( stream->chunks, ( stream->chunk_count + 1 ) * sizeof( struct riff_chunk ) );
|
||||
if ( ! stream->chunks ) break;
|
||||
chunk = stream->chunks + stream->chunk_count;
|
||||
chunk->type = dumbfile_mgetl(f);
|
||||
chunk->size = dumbfile_igetl(f);
|
||||
chunk->offset = dumbfile_pos(f);
|
||||
stream_size -= 8;
|
||||
if ( stream_size < chunk->size ) break;
|
||||
if ( chunk->type == DUMB_ID('R','I','F','F') )
|
||||
{
|
||||
chunk->nested = riff_parse( f, chunk->offset - 8, chunk->size + 8, proper );
|
||||
if ( ! chunk->nested ) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk->nested = 0;
|
||||
}
|
||||
dumbfile_seek(f, chunk->offset + chunk->size, DFS_SEEK_SET);
|
||||
stream_size -= chunk->size;
|
||||
if ( proper && ( chunk->size & 1 ) )
|
||||
{
|
||||
dumbfile_skip(f, 1);
|
||||
-- stream_size;
|
||||
}
|
||||
++stream->chunk_count;
|
||||
}
|
||||
|
||||
if ( stream_size )
|
||||
{
|
||||
riff_free( stream );
|
||||
stream = 0;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void riff_free( struct riff * stream )
|
||||
{
|
||||
if ( stream )
|
||||
{
|
||||
if ( stream->chunks )
|
||||
{
|
||||
unsigned i;
|
||||
for ( i = 0; i < stream->chunk_count; ++i )
|
||||
{
|
||||
struct riff_chunk * chunk = stream->chunks + i;
|
||||
if ( chunk->nested ) riff_free( chunk->nested );
|
||||
}
|
||||
free( stream->chunks );
|
||||
}
|
||||
free( stream );
|
||||
}
|
||||
}
|
|
@ -1,64 +1,64 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* sampbuf.c - Helper for allocating sample / / \ \
|
||||
* buffers. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
sample_t **create_sample_buffer(int n_channels, long length)
|
||||
{
|
||||
int i;
|
||||
sample_t **samples = malloc(n_channels * sizeof(*samples));
|
||||
if (!samples) return NULL;
|
||||
samples[0] = malloc(n_channels * length * sizeof(*samples[0]));
|
||||
if (!samples[0]) {
|
||||
free(samples);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 1; i < n_channels; i++) samples[i] = samples[i-1] + length;
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sample_t **allocate_sample_buffer(int n_channels, long length)
|
||||
{
|
||||
int i;
|
||||
sample_t **samples = malloc(((n_channels + 1) >> 1) * sizeof(*samples));
|
||||
if (!samples) return NULL;
|
||||
samples[0] = malloc(n_channels * length * sizeof(*samples[0]));
|
||||
if (!samples[0]) {
|
||||
free(samples);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 1; i < (n_channels + 1) >> 1; i++) samples[i] = samples[i-1] + length*2;
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void destroy_sample_buffer(sample_t **samples)
|
||||
{
|
||||
if (samples) {
|
||||
free(samples[0]);
|
||||
free(samples);
|
||||
}
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* sampbuf.c - Helper for allocating sample / / \ \
|
||||
* buffers. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
/* DEPRECATED */
|
||||
sample_t **create_sample_buffer(int n_channels, long length)
|
||||
{
|
||||
int i;
|
||||
sample_t **samples = malloc(n_channels * sizeof(*samples));
|
||||
if (!samples) return NULL;
|
||||
samples[0] = malloc(n_channels * length * sizeof(*samples[0]));
|
||||
if (!samples[0]) {
|
||||
free(samples);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 1; i < n_channels; i++) samples[i] = samples[i-1] + length;
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sample_t **allocate_sample_buffer(int n_channels, long length)
|
||||
{
|
||||
int i;
|
||||
sample_t **samples = malloc(((n_channels + 1) >> 1) * sizeof(*samples));
|
||||
if (!samples) return NULL;
|
||||
samples[0] = malloc(n_channels * length * sizeof(*samples[0]));
|
||||
if (!samples[0]) {
|
||||
free(samples);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 1; i < (n_channels + 1) >> 1; i++) samples[i] = samples[i-1] + length*2;
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void destroy_sample_buffer(sample_t **samples)
|
||||
{
|
||||
if (samples) {
|
||||
free(samples[0]);
|
||||
free(samples);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* silence.c - Silencing helper. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
void dumb_silence(sample_t *samples, long length)
|
||||
{
|
||||
memset(samples, 0, length * sizeof(*samples));
|
||||
}
|
||||
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* silence.c - Silencing helper. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
void dumb_silence(sample_t *samples, long length)
|
||||
{
|
||||
memset(samples, 0, length * sizeof(*samples));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,93 +1,146 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* stdfile.c - stdio file input module. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
static void *dumb_stdfile_open(const char *filename)
|
||||
{
|
||||
return fopen(filename, "rb");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dumb_stdfile_skip(void *f, long n)
|
||||
{
|
||||
return fseek(f, n, SEEK_CUR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dumb_stdfile_getc(void *f)
|
||||
{
|
||||
return fgetc(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long dumb_stdfile_getnc(char *ptr, long n, void *f)
|
||||
{
|
||||
return fread(ptr, 1, n, f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void dumb_stdfile_close(void *f)
|
||||
{
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static DUMBFILE_SYSTEM stdfile_dfs = {
|
||||
&dumb_stdfile_open,
|
||||
&dumb_stdfile_skip,
|
||||
&dumb_stdfile_getc,
|
||||
&dumb_stdfile_getnc,
|
||||
&dumb_stdfile_close
|
||||
};
|
||||
|
||||
|
||||
|
||||
void dumb_register_stdfiles(void)
|
||||
{
|
||||
register_dumbfile_system(&stdfile_dfs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static DUMBFILE_SYSTEM stdfile_dfs_leave_open = {
|
||||
NULL,
|
||||
&dumb_stdfile_skip,
|
||||
&dumb_stdfile_getc,
|
||||
&dumb_stdfile_getnc,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
DUMBFILE *dumbfile_open_stdfile(FILE *p)
|
||||
{
|
||||
DUMBFILE *d = dumbfile_open_ex(p, &stdfile_dfs_leave_open);
|
||||
|
||||
return d;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* stdfile.c - stdio file input module. / / \ \
|
||||
* | < / \_
|
||||
* By entheh. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
typedef struct dumb_stdfile
|
||||
{
|
||||
FILE * file;
|
||||
long size;
|
||||
} dumb_stdfile;
|
||||
|
||||
|
||||
|
||||
static void *dumb_stdfile_open(const char *filename)
|
||||
{
|
||||
dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
|
||||
if ( !file ) return 0;
|
||||
file->file = fopen(filename, "rb");
|
||||
fseek(file->file, 0, SEEK_END);
|
||||
file->size = ftell(file->file);
|
||||
fseek(file->file, 0, SEEK_SET);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dumb_stdfile_skip(void *f, long n)
|
||||
{
|
||||
dumb_stdfile * file = ( dumb_stdfile * ) f;
|
||||
return fseek(file->file, n, SEEK_CUR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dumb_stdfile_getc(void *f)
|
||||
{
|
||||
dumb_stdfile * file = ( dumb_stdfile * ) f;
|
||||
return fgetc(file->file);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long dumb_stdfile_getnc(char *ptr, long n, void *f)
|
||||
{
|
||||
dumb_stdfile * file = ( dumb_stdfile * ) f;
|
||||
return fread(ptr, 1, n, file->file);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void dumb_stdfile_close(void *f)
|
||||
{
|
||||
dumb_stdfile * file = ( dumb_stdfile * ) f;
|
||||
fclose(file->file);
|
||||
free(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void dumb_stdfile_noclose(void *f)
|
||||
{
|
||||
free(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dumb_stdfile_seek(void *f, long n)
|
||||
{
|
||||
dumb_stdfile * file = ( dumb_stdfile * ) f;
|
||||
return fseek(file->file, n, SEEK_SET);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long dumb_stdfile_get_size(void *f)
|
||||
{
|
||||
dumb_stdfile * file = ( dumb_stdfile * ) f;
|
||||
return file->size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const DUMBFILE_SYSTEM stdfile_dfs = {
|
||||
&dumb_stdfile_open,
|
||||
&dumb_stdfile_skip,
|
||||
&dumb_stdfile_getc,
|
||||
&dumb_stdfile_getnc,
|
||||
&dumb_stdfile_close,
|
||||
&dumb_stdfile_seek,
|
||||
&dumb_stdfile_get_size
|
||||
};
|
||||
|
||||
|
||||
|
||||
void dumb_register_stdfiles(void)
|
||||
{
|
||||
register_dumbfile_system(&stdfile_dfs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const DUMBFILE_SYSTEM stdfile_dfs_leave_open = {
|
||||
NULL,
|
||||
&dumb_stdfile_skip,
|
||||
&dumb_stdfile_getc,
|
||||
&dumb_stdfile_getnc,
|
||||
&dumb_stdfile_noclose,
|
||||
&dumb_stdfile_seek,
|
||||
&dumb_stdfile_get_size
|
||||
};
|
||||
|
||||
|
||||
|
||||
DUMBFILE *dumbfile_open_stdfile(FILE *p)
|
||||
{
|
||||
dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
|
||||
DUMBFILE *d;
|
||||
if ( !file ) return 0;
|
||||
file->file = p;
|
||||
fseek(p, 0, SEEK_END);
|
||||
file->size = ftell(p);
|
||||
fseek(p, 0, SEEK_SET);
|
||||
d = dumbfile_open_ex(file, &stdfile_dfs_leave_open);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
|
175
Frameworks/Dumb/dumb/src/helpers/tarray.c
Normal file
175
Frameworks/Dumb/dumb/src/helpers/tarray.c
Normal file
|
@ -0,0 +1,175 @@
|
|||
#include "internal/tarray.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
Structures which contain the play times of each pattern and row combination in the song,
|
||||
not guaranteed to be valid for the whole song until the loop status is no longer zero.
|
||||
The initial count and restart count will both be zero on song start, then both will be
|
||||
incremented until the song loops. Restart count will be reset to zero on loop for all
|
||||
rows which have a time equal to or greater than the loop start point, so time keeping
|
||||
functions will know which timestamp the song is currently located at.
|
||||
|
||||
Timestamp lists are guaranteed to be allocated in blocks of 16 timestamps at a time.
|
||||
*/
|
||||
|
||||
/*
|
||||
We don't need full timekeeping because the player loop only wants the first play time
|
||||
of the loop start order/row. We also don't really want full timekeeping because it
|
||||
involves a lot of memory allocations, which is also slow.
|
||||
*/
|
||||
|
||||
#undef FULL_TIMEKEEPING
|
||||
|
||||
typedef struct DUMB_IT_ROW_TIME
|
||||
{
|
||||
unsigned int count, restart_count;
|
||||
#ifndef FULL_TIMEKEEPING
|
||||
LONG_LONG first_time;
|
||||
#else
|
||||
LONG_LONG * times;
|
||||
#endif
|
||||
} DUMB_IT_ROW_TIME;
|
||||
|
||||
void * timekeeping_array_create(size_t size)
|
||||
{
|
||||
size_t * _size = (size_t *) calloc( 1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * size );
|
||||
if ( _size ) {
|
||||
*_size = size;
|
||||
}
|
||||
return _size;
|
||||
}
|
||||
|
||||
void timekeeping_array_destroy(void * array)
|
||||
{
|
||||
#ifdef FULL_TIMEKEEPING
|
||||
size_t i;
|
||||
size_t * size = (size_t *) array;
|
||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
||||
|
||||
for (i = 0; i < *size; i++) {
|
||||
if (s[i].times) free(s[i].times);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(array);
|
||||
}
|
||||
|
||||
void * timekeeping_array_dup(void * array)
|
||||
{
|
||||
size_t i;
|
||||
size_t * size = (size_t *) array;
|
||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
||||
size_t * new_size = (size_t *) calloc( 1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * *size );
|
||||
if ( new_size ) {
|
||||
DUMB_IT_ROW_TIME * new_s = (DUMB_IT_ROW_TIME *)(new_size + 1);
|
||||
|
||||
*new_size = *size;
|
||||
|
||||
for (i = 0; i < *size; i++) {
|
||||
new_s[i].count = s[i].count;
|
||||
new_s[i].restart_count = s[i].restart_count;
|
||||
|
||||
#ifndef FULL_TIMEKEEPING
|
||||
new_s[i].first_time = s[i].first_time;
|
||||
#else
|
||||
if ( s[i].times ) {
|
||||
size_t time_count = ( s[i].count + 15 ) & ~15;
|
||||
new_s[i].times = (LONG_LONG *) malloc( sizeof(LONG_LONG) * time_count );
|
||||
if ( new_s[i].times == (void *)0 ) {
|
||||
timekeeping_array_destroy( new_size );
|
||||
return (void *) 0;
|
||||
}
|
||||
memcpy( new_s[i].times, s[i].times, sizeof(LONG_LONG) * s[i].count );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return new_size;
|
||||
}
|
||||
|
||||
void timekeeping_array_reset(void * array, size_t loop_start)
|
||||
{
|
||||
size_t i;
|
||||
size_t * size = (size_t *) array;
|
||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
||||
|
||||
DUMB_IT_ROW_TIME * s_loop_start = s + loop_start;
|
||||
LONG_LONG loop_start_time;
|
||||
|
||||
if ( loop_start >= *size || s_loop_start->count < 1 ) return;
|
||||
|
||||
#ifndef FULL_TIMEKEEPING
|
||||
loop_start_time = s_loop_start->first_time;
|
||||
#else
|
||||
loop_start_time = s_loop_start->times[0];
|
||||
#endif
|
||||
|
||||
for ( i = 0; i < *size; i++ ) {
|
||||
#ifndef FULL_TIMEKEEPING
|
||||
if ( s[i].count && s[i].first_time >= loop_start_time ) {
|
||||
#else
|
||||
if ( s[i].count && s[i].times[0] >= loop_start_time ) {
|
||||
#endif
|
||||
s[i].restart_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void timekeeping_array_push(void * array, size_t index, LONG_LONG time)
|
||||
{
|
||||
#ifdef FULL_TIMEKEEPING
|
||||
size_t i;
|
||||
size_t time_count;
|
||||
#endif
|
||||
size_t * size = (size_t *) array;
|
||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
||||
|
||||
if (index >= *size) return;
|
||||
|
||||
#ifndef FULL_TIMEKEEPING
|
||||
if ( !s[index].count++ )
|
||||
s[index].first_time = time;
|
||||
#else
|
||||
time_count = ( s[index].count + 16 ) & ~15;
|
||||
|
||||
s[index].times = (LONG_LONG *) realloc( s[index].times, sizeof(LONG_LONG) * time_count );
|
||||
|
||||
s[index].times[s[index].count++] = time;
|
||||
#endif
|
||||
}
|
||||
|
||||
void timekeeping_array_bump(void * array, size_t index)
|
||||
{
|
||||
size_t * size = (size_t *) array;
|
||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
||||
|
||||
if (index >= *size) return;
|
||||
|
||||
s[index].restart_count++;
|
||||
}
|
||||
|
||||
unsigned int timekeeping_array_get_count(void * array, size_t index)
|
||||
{
|
||||
size_t * size = (size_t *) array;
|
||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
||||
|
||||
if (index >= *size) return 0;
|
||||
|
||||
return s[index].count;
|
||||
}
|
||||
|
||||
LONG_LONG timekeeping_array_get_item(void * array, size_t index)
|
||||
{
|
||||
size_t * size = (size_t *) array;
|
||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
||||
|
||||
if (index >= *size || s[index].restart_count >= s[index].count) return 0;
|
||||
|
||||
#ifndef FULL_TIMEKEEPING
|
||||
return s[index].first_time;
|
||||
#else
|
||||
return s[index].times[s[index].restart_count];
|
||||
#endif
|
||||
}
|
|
@ -1,42 +1,43 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itload.c - Code to read an Impulse Tracker / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. Don't worry Bob, you're credited | \ / /
|
||||
* in itread.c! | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_it_quick(): loads an IT file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must pass
|
||||
* the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_it_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_it_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itload.c - Code to read an Impulse Tracker / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. Don't worry Bob, you're credited | \ / /
|
||||
* in itread.c! | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_it_quick(): loads an IT file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must pass
|
||||
* the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_it_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_it_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itload2.c - Function to read an Impulse Tracker / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* Split off from itload.c by entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_it(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_it_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itload2.c - Function to read an Impulse Tracker / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* Split off from itload.c by entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_it(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_it_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
|
|
|
@ -1,247 +1,247 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itmisc.c - Miscellaneous functions relating / / \ \
|
||||
* to module files. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh)
|
||||
{
|
||||
return duh_get_raw_sigdata(duh, 0, SIGTYPE_IT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const unsigned char *dumb_it_sd_get_song_message(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->song_message : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->n_orders : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_n_samples(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->n_samples : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_n_instruments(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->n_instruments : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const unsigned char *dumb_it_sd_get_sample_name(DUMB_IT_SIGDATA *sd, int i)
|
||||
{
|
||||
ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples);
|
||||
return sd->sample[i].name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const unsigned char *dumb_it_sd_get_sample_filename(DUMB_IT_SIGDATA *sd, int i)
|
||||
{
|
||||
ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples);
|
||||
return sd->sample[i].filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const unsigned char *dumb_it_sd_get_instrument_name(DUMB_IT_SIGDATA *sd, int i)
|
||||
{
|
||||
ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments);
|
||||
return sd->instrument[i].name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const unsigned char *dumb_it_sd_get_instrument_filename(DUMB_IT_SIGDATA *sd, int i)
|
||||
{
|
||||
ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments);
|
||||
return sd->instrument[i].filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->global_volume : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv)
|
||||
{
|
||||
if (sd) sd->global_volume = gv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->mixing_volume : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv)
|
||||
{
|
||||
if (sd) sd->mixing_volume = mv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->speed : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed)
|
||||
{
|
||||
if (sd) sd->speed = speed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->tempo : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo)
|
||||
{
|
||||
if (sd) sd->tempo = tempo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel)
|
||||
{
|
||||
ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
|
||||
return sd ? sd->channel_volume[channel] : 0;
|
||||
}
|
||||
|
||||
void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume)
|
||||
{
|
||||
ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
|
||||
if (sd) sd->channel_volume[channel] = volume;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr)
|
||||
{
|
||||
return sr ? sr->order : -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr)
|
||||
{
|
||||
return sr ? sr->row : -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr)
|
||||
{
|
||||
return sr ? sr->globalvolume : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv)
|
||||
{
|
||||
if (sr) sr->globalvolume = gv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr)
|
||||
{
|
||||
return sr ? sr->tempo : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo)
|
||||
{
|
||||
if (sr) sr->tempo = tempo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr)
|
||||
{
|
||||
return sr ? sr->speed : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed)
|
||||
{
|
||||
if (sr) sr->speed = speed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel)
|
||||
{
|
||||
return sr ? sr->channel[channel].channelvolume : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume)
|
||||
{
|
||||
if (sr) sr->channel[channel].channelvolume = volume;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel, int muted)
|
||||
{
|
||||
if (sr) {
|
||||
if (muted)
|
||||
sr->channel[channel].flags |= IT_CHANNEL_MUTED;
|
||||
else
|
||||
sr->channel[channel].flags &= ~IT_CHANNEL_MUTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel)
|
||||
{
|
||||
return sr ? (sr->channel[channel].flags & IT_CHANNEL_MUTED) != 0 : 0;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itmisc.c - Miscellaneous functions relating / / \ \
|
||||
* to module files. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh)
|
||||
{
|
||||
return duh_get_raw_sigdata(duh, -1, SIGTYPE_IT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const unsigned char *dumb_it_sd_get_song_message(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->song_message : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->n_orders : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_n_samples(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->n_samples : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_n_instruments(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->n_instruments : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const unsigned char *dumb_it_sd_get_sample_name(DUMB_IT_SIGDATA *sd, int i)
|
||||
{
|
||||
ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples);
|
||||
return sd->sample[i].name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const unsigned char *dumb_it_sd_get_sample_filename(DUMB_IT_SIGDATA *sd, int i)
|
||||
{
|
||||
ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples);
|
||||
return sd->sample[i].filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const unsigned char *dumb_it_sd_get_instrument_name(DUMB_IT_SIGDATA *sd, int i)
|
||||
{
|
||||
ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments);
|
||||
return sd->instrument[i].name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const unsigned char *dumb_it_sd_get_instrument_filename(DUMB_IT_SIGDATA *sd, int i)
|
||||
{
|
||||
ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments);
|
||||
return sd->instrument[i].filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->global_volume : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv)
|
||||
{
|
||||
if (sd) sd->global_volume = gv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->mixing_volume : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv)
|
||||
{
|
||||
if (sd) sd->mixing_volume = mv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->speed : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed)
|
||||
{
|
||||
if (sd) sd->speed = speed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd)
|
||||
{
|
||||
return sd ? sd->tempo : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo)
|
||||
{
|
||||
if (sd) sd->tempo = tempo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel)
|
||||
{
|
||||
ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
|
||||
return sd ? sd->channel_volume[channel] : 0;
|
||||
}
|
||||
|
||||
void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume)
|
||||
{
|
||||
ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
|
||||
if (sd) sd->channel_volume[channel] = volume;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr)
|
||||
{
|
||||
return sr ? sr->order : -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr)
|
||||
{
|
||||
return sr ? sr->row : -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr)
|
||||
{
|
||||
return sr ? sr->globalvolume : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv)
|
||||
{
|
||||
if (sr) sr->globalvolume = gv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr)
|
||||
{
|
||||
return sr ? sr->tempo : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo)
|
||||
{
|
||||
if (sr) sr->tempo = tempo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr)
|
||||
{
|
||||
return sr ? sr->speed : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed)
|
||||
{
|
||||
if (sr) sr->speed = speed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel)
|
||||
{
|
||||
return sr ? sr->channel[channel].channelvolume : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume)
|
||||
{
|
||||
if (sr) sr->channel[channel].channelvolume = volume;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel, int muted)
|
||||
{
|
||||
if (sr) {
|
||||
if (muted)
|
||||
sr->channel[channel].flags |= IT_CHANNEL_MUTED;
|
||||
else
|
||||
sr->channel[channel].flags &= ~IT_CHANNEL_MUTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel)
|
||||
{
|
||||
return sr ? (sr->channel[channel].flags & IT_CHANNEL_MUTED) != 0 : 0;
|
||||
}
|
||||
|
|
|
@ -1,63 +1,63 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itorder.c - Code to fix invalid patterns in / / \ \
|
||||
* the pattern table. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Julien Cugniere. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* This function ensures that any pattern mentioned in the order table but
|
||||
* not present in the pattern table is treated as an empty 64 rows pattern.
|
||||
* This is done by adding such a dummy pattern at the end of the pattern
|
||||
* table, and redirect invalid orders to it.
|
||||
* Patterns 254 and 255 are left untouched, unless the signal is an XM.
|
||||
*/
|
||||
int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata)
|
||||
{
|
||||
int i;
|
||||
int found_some = 0;
|
||||
|
||||
int first_invalid = sigdata->n_patterns;
|
||||
int last_invalid = (sigdata->flags & IT_WAS_AN_XM) ? 255 : 253;
|
||||
|
||||
for (i = 0; i < sigdata->n_orders; i++) {
|
||||
if (sigdata->order[i] >= first_invalid && sigdata->order[i] <= last_invalid) {
|
||||
sigdata->order[i] = sigdata->n_patterns;
|
||||
found_some = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_some) {
|
||||
IT_PATTERN *new_pattern = realloc(sigdata->pattern, sizeof(*sigdata->pattern) * (sigdata->n_patterns + 1));
|
||||
if (!new_pattern)
|
||||
return -1;
|
||||
|
||||
new_pattern[sigdata->n_patterns].n_rows = 64;
|
||||
new_pattern[sigdata->n_patterns].n_entries = 0;
|
||||
new_pattern[sigdata->n_patterns].entry = NULL;
|
||||
sigdata->pattern = new_pattern;
|
||||
sigdata->n_patterns++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itorder.c - Code to fix invalid patterns in / / \ \
|
||||
* the pattern table. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Julien Cugniere. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* This function ensures that any pattern mentioned in the order table but
|
||||
* not present in the pattern table is treated as an empty 64 rows pattern.
|
||||
* This is done by adding such a dummy pattern at the end of the pattern
|
||||
* table, and redirect invalid orders to it.
|
||||
* Patterns 254 and 255 are left untouched, unless the signal is an XM.
|
||||
*/
|
||||
int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata)
|
||||
{
|
||||
int i;
|
||||
int found_some = 0;
|
||||
|
||||
int first_invalid = sigdata->n_patterns;
|
||||
int last_invalid = (sigdata->flags & IT_WAS_AN_XM) ? 255 : 253;
|
||||
|
||||
for (i = 0; i < sigdata->n_orders; i++) {
|
||||
if (sigdata->order[i] >= first_invalid && sigdata->order[i] <= last_invalid) {
|
||||
sigdata->order[i] = sigdata->n_patterns;
|
||||
found_some = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_some) {
|
||||
IT_PATTERN *new_pattern = realloc(sigdata->pattern, sizeof(*sigdata->pattern) * (sigdata->n_patterns + 1));
|
||||
if (!new_pattern)
|
||||
return -1;
|
||||
|
||||
new_pattern[sigdata->n_patterns].n_rows = 64;
|
||||
new_pattern[sigdata->n_patterns].n_entries = 0;
|
||||
new_pattern[sigdata->n_patterns].entry = NULL;
|
||||
sigdata->pattern = new_pattern;
|
||||
sigdata->n_patterns++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,29 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itread2.c - Function to read an Impulse Tracker / / \ \
|
||||
* module from an open file and do an | < / \_
|
||||
* initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* Split off from itread.c by entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_it(DUMBFILE *f)
|
||||
{
|
||||
DUH *duh = dumb_read_it_quick(f);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itread2.c - Function to read an Impulse Tracker / / \ \
|
||||
* module from an open file and do an | < / \_
|
||||
* initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* Split off from itread.c by entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_it(DUMBFILE *f)
|
||||
{
|
||||
DUH *duh = dumb_read_it_quick(f);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,72 +1,72 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itunload.c - Code to free an Impulse Tracker / / \ \
|
||||
* module from memory. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
void _dumb_it_unload_sigdata(sigdata_t *vsigdata)
|
||||
{
|
||||
if (vsigdata) {
|
||||
DUMB_IT_SIGDATA *sigdata = vsigdata;
|
||||
int n;
|
||||
|
||||
if (sigdata->song_message)
|
||||
free(sigdata->song_message);
|
||||
|
||||
if (sigdata->order)
|
||||
free(sigdata->order);
|
||||
|
||||
if (sigdata->instrument)
|
||||
free(sigdata->instrument);
|
||||
|
||||
if (sigdata->sample) {
|
||||
for (n = 0; n < sigdata->n_samples; n++)
|
||||
if (sigdata->sample[n].data)
|
||||
free(sigdata->sample[n].data);
|
||||
|
||||
free(sigdata->sample);
|
||||
}
|
||||
|
||||
if (sigdata->pattern) {
|
||||
for (n = 0; n < sigdata->n_patterns; n++)
|
||||
if (sigdata->pattern[n].entry)
|
||||
free(sigdata->pattern[n].entry);
|
||||
free(sigdata->pattern);
|
||||
}
|
||||
|
||||
if (sigdata->midi)
|
||||
free(sigdata->midi);
|
||||
|
||||
{
|
||||
IT_CHECKPOINT *checkpoint = sigdata->checkpoint;
|
||||
while (checkpoint) {
|
||||
IT_CHECKPOINT *next = checkpoint->next;
|
||||
_dumb_it_end_sigrenderer(checkpoint->sigrenderer);
|
||||
free(checkpoint);
|
||||
checkpoint = next;
|
||||
}
|
||||
}
|
||||
|
||||
free(vsigdata);
|
||||
}
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* itunload.c - Code to free an Impulse Tracker / / \ \
|
||||
* module from memory. | < / \_
|
||||
* | \/ /\ /
|
||||
* By entheh. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
void _dumb_it_unload_sigdata(sigdata_t *vsigdata)
|
||||
{
|
||||
if (vsigdata) {
|
||||
DUMB_IT_SIGDATA *sigdata = vsigdata;
|
||||
int n;
|
||||
|
||||
if (sigdata->song_message)
|
||||
free(sigdata->song_message);
|
||||
|
||||
if (sigdata->order)
|
||||
free(sigdata->order);
|
||||
|
||||
if (sigdata->instrument)
|
||||
free(sigdata->instrument);
|
||||
|
||||
if (sigdata->sample) {
|
||||
for (n = 0; n < sigdata->n_samples; n++)
|
||||
if (sigdata->sample[n].data)
|
||||
free(sigdata->sample[n].data);
|
||||
|
||||
free(sigdata->sample);
|
||||
}
|
||||
|
||||
if (sigdata->pattern) {
|
||||
for (n = 0; n < sigdata->n_patterns; n++)
|
||||
if (sigdata->pattern[n].entry)
|
||||
free(sigdata->pattern[n].entry);
|
||||
free(sigdata->pattern);
|
||||
}
|
||||
|
||||
if (sigdata->midi)
|
||||
free(sigdata->midi);
|
||||
|
||||
{
|
||||
IT_CHECKPOINT *checkpoint = sigdata->checkpoint;
|
||||
while (checkpoint) {
|
||||
IT_CHECKPOINT *next = checkpoint->next;
|
||||
_dumb_it_end_sigrenderer(checkpoint->sigrenderer);
|
||||
free(checkpoint);
|
||||
checkpoint = next;
|
||||
}
|
||||
}
|
||||
|
||||
free(vsigdata);
|
||||
}
|
||||
}
|
||||
|
|
42
Frameworks/Dumb/dumb/src/it/load669.c
Normal file
42
Frameworks/Dumb/dumb/src/it/load669.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadmod.c - Code to read a 669 Composer module / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_669_quick(): loads a 669 file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_669_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_669_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
34
Frameworks/Dumb/dumb/src/it/load6692.c
Normal file
34
Frameworks/Dumb/dumb/src/it/load6692.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadmod2.c - Code to read a 669 Composer module / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_669(): loads a 669 file into a DUH struct, returning a pointer
|
||||
* to the DUH struct. When you have finished with it, you must pass the
|
||||
* pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_669(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_669_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
42
Frameworks/Dumb/dumb/src/it/loadamf.c
Normal file
42
Frameworks/Dumb/dumb/src/it/loadamf.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadamf.c - Code to read a DSMI AMF module file, / / \ \
|
||||
* opening and closing it for you. | < / \_
|
||||
* | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_amf_quick(): loads a AMF file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_amf_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_amf_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
34
Frameworks/Dumb/dumb/src/it/loadamf2.c
Normal file
34
Frameworks/Dumb/dumb/src/it/loadamf2.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadamf2.c - Code to read a DSMI AMF module file, / / \ \
|
||||
* opening and closing it for you, and | < / \_
|
||||
* do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* By Chris Moeller. | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_amf(): loads a AMF file into a DUH struct, returning a pointer
|
||||
* to the DUH struct. When you have finished with it, you must pass the
|
||||
* pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_amf(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_amf_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
38
Frameworks/Dumb/dumb/src/it/loadany.c
Normal file
38
Frameworks/Dumb/dumb/src/it/loadany.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadany.c - Code to detect and read any of the / / \ \
|
||||
* module formats supported by DUMB, | < / \_
|
||||
* opening and closing the file for you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_any_quick(const char *filename, int restrict_, int subsong)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_any_quick(f, restrict_, subsong);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
29
Frameworks/Dumb/dumb/src/it/loadany2.c
Normal file
29
Frameworks/Dumb/dumb/src/it/loadany2.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadany2.c - Code to detect and read any of the / / \ \
|
||||
* module formats supported by DUMB, | < / \_
|
||||
* opening and closing the file for | \/ /\ /
|
||||
* you, and do an initial run-through. \_ / > /
|
||||
* | \ / /
|
||||
* by Chris Moeller. | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_any(const char *filename, int restrict_, int subsong)
|
||||
{
|
||||
DUH *duh = dumb_load_any_quick(filename, restrict_, subsong);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
42
Frameworks/Dumb/dumb/src/it/loadasy.c
Normal file
42
Frameworks/Dumb/dumb/src/it/loadasy.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadasy.c - Code to read an ASYLUM Music Format / / \ \
|
||||
* module file, opening and closing it | < / \_
|
||||
* for you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_asy_quick(): loads a AMF file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_asy_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_asy_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
34
Frameworks/Dumb/dumb/src/it/loadasy2.c
Normal file
34
Frameworks/Dumb/dumb/src/it/loadasy2.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadasy2.c - Code to read an ASYLUM Music Format / / \ \
|
||||
* module file, opening and closing it | < / \_
|
||||
* for you, and do an initial run- | \/ /\ /
|
||||
* through. \_ / > /
|
||||
* | \ / /
|
||||
* By Chris Moeller. | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_asy(): loads a AMF file into a DUH struct, returning a pointer
|
||||
* to the DUH struct. When you have finished with it, you must pass the
|
||||
* pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_asy(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_asy_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
|
@ -1,42 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadmod.c - Code to read a good old-fashioned / / \ \
|
||||
* Amiga module file, opening and | < / \_
|
||||
* closing it for you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_mod_quick(): loads a MOD file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_mod_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_mod_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadmod.c - Code to read a good old-fashioned / / \ \
|
||||
* Amiga module file, opening and | < / \_
|
||||
* closing it for you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_mod_quick(): loads a MOD file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_mod_quick(const char *filename, int restrict_)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_mod_quick(f, restrict_);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadmod2.c - Function to read a good old- / / \ \
|
||||
* fashioned Amiga module file, | < / \_
|
||||
* opening and closing it for you, | \/ /\ /
|
||||
* and do an initial run-through. \_ / > /
|
||||
* | \ / /
|
||||
* Split off from loadmod.c by entheh. | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_mod(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_mod_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadmod2.c - Function to read a good old- / / \ \
|
||||
* fashioned Amiga module file, | < / \_
|
||||
* opening and closing it for you, | \/ /\ /
|
||||
* and do an initial run-through. \_ / > /
|
||||
* | \ / /
|
||||
* Split off from loadmod.c by entheh. | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_mod(const char *filename, int restrict_)
|
||||
{
|
||||
DUH *duh = dumb_load_mod_quick(filename, restrict_);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
|
|
42
Frameworks/Dumb/dumb/src/it/loadmtm.c
Normal file
42
Frameworks/Dumb/dumb/src/it/loadmtm.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadmtm.c - Code to read a MultiTracker Module / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_mtm_quick(): loads a MTM file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_mtm_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_mtm_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
34
Frameworks/Dumb/dumb/src/it/loadmtm2.c
Normal file
34
Frameworks/Dumb/dumb/src/it/loadmtm2.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadmtm2.c - Code to read a MultiTracker Module / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_mtm(): loads a MTM file into a DUH struct, returning a pointer
|
||||
* to the DUH struct. When you have finished with it, you must pass the
|
||||
* pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_mtm(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_mtm_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
42
Frameworks/Dumb/dumb/src/it/loadokt.c
Normal file
42
Frameworks/Dumb/dumb/src/it/loadokt.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadokt.c - Code to read an Oktalyzer module / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_okt_quick(): loads an OKT file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_okt_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_okt_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
29
Frameworks/Dumb/dumb/src/it/loadokt2.c
Normal file
29
Frameworks/Dumb/dumb/src/it/loadokt2.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadokt2.c - Function to read an Oktalyzer / / \ \
|
||||
* module file, opening and closing | < / \_
|
||||
* it for you, and do an initial run- | \/ /\ /
|
||||
* through. \_ / > /
|
||||
* | \ / /
|
||||
* By Chris Moeller. | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_okt(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_okt_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
43
Frameworks/Dumb/dumb/src/it/loadoldpsm.c
Normal file
43
Frameworks/Dumb/dumb/src/it/loadoldpsm.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadoldpsm.c - Code to read a ProTracker Studio / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_old_psm_quick(): loads an old PSM file into a DUH struct,
|
||||
* returning a pointer to the DUH struct. When you have finished with it,
|
||||
* you must pass the pointer to unload_duh() so that the memory can be
|
||||
* freed.
|
||||
*/
|
||||
DUH *dumb_load_old_psm_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_old_psm_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
34
Frameworks/Dumb/dumb/src/it/loadoldpsm2.c
Normal file
34
Frameworks/Dumb/dumb/src/it/loadoldpsm2.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadoldpsm2.c - Code to read a ProTracker Studio / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run- | \/ /\ /
|
||||
* through. \_ / > /
|
||||
* | \ / /
|
||||
* By Chris Moeller. | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_old_psm(): loads an old PSM file into a DUH struct, returning
|
||||
* a pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_old_psm(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_old_psm_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
42
Frameworks/Dumb/dumb/src/it/loadpsm.c
Normal file
42
Frameworks/Dumb/dumb/src/it/loadpsm.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadpsm.c - Code to read a ProTracker Studio / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_psm_quick(): loads a PSM file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_psm_quick(const char *filename, int subsong)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_psm_quick(f, subsong);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
34
Frameworks/Dumb/dumb/src/it/loadpsm2.c
Normal file
34
Frameworks/Dumb/dumb/src/it/loadpsm2.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadpsm2.c - Code to read a ProTracker Studio / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_psm(): loads a PSM file into a DUH struct, returning a pointer
|
||||
* to the DUH struct. When you have finished with it, you must pass the
|
||||
* pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_psm(const char *filename, int subsong)
|
||||
{
|
||||
DUH *duh = dumb_load_psm_quick(filename, subsong);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
42
Frameworks/Dumb/dumb/src/it/loadptm.c
Normal file
42
Frameworks/Dumb/dumb/src/it/loadptm.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadptm.c - Code to read a Poly Tracker v2.03 / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_ptm_quick(): loads a PTM file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_ptm_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_ptm_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
34
Frameworks/Dumb/dumb/src/it/loadptm2.c
Normal file
34
Frameworks/Dumb/dumb/src/it/loadptm2.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadptm2.c - Code to read a Poly Tracker v2.03 / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_ptm(): loads a PTM file into a DUH struct, returning a pointer
|
||||
* to the DUH struct. When you have finished with it, you must pass the
|
||||
* pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_ptm(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_ptm_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
42
Frameworks/Dumb/dumb/src/it/loadriff.c
Normal file
42
Frameworks/Dumb/dumb/src/it/loadriff.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadriff.c - Code to read a RIFF module file / / \ \
|
||||
* opening and closing it for you. | < / \_
|
||||
* | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_riff_quick(): loads a RIFF file into a DUH struct, returning
|
||||
* a pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH * dumb_load_riff_quick( const char *filename )
|
||||
{
|
||||
DUH * duh;
|
||||
DUMBFILE * f = dumbfile_open( filename );
|
||||
|
||||
if ( ! f )
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_riff_quick( f );
|
||||
|
||||
dumbfile_close( f );
|
||||
|
||||
return duh;
|
||||
}
|
29
Frameworks/Dumb/dumb/src/it/loadriff2.c
Normal file
29
Frameworks/Dumb/dumb/src/it/loadriff2.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadriff2.c - Code to read a RIFF module file / / \ \
|
||||
* opening and closing it for you, | < / \_
|
||||
* and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_riff(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_riff_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
|
@ -1,42 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loads3m.c - Code to read a ScreamTracker 3 / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_s3m_quick(): loads an S3M file into a DUH struct, returning
|
||||
* a pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_s3m_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_s3m_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loads3m.c - Code to read a ScreamTracker 3 / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_s3m_quick(): loads an S3M file into a DUH struct, returning
|
||||
* a pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_s3m_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_s3m_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loads3m2.c - Function to read a ScreamTracker 3 / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* Split off from loads3m.c by entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_s3m(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_s3m_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loads3m2.c - Function to read a ScreamTracker 3 / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* Split off from loads3m.c by entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_s3m(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_s3m_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
|
|
42
Frameworks/Dumb/dumb/src/it/loadstm.c
Normal file
42
Frameworks/Dumb/dumb/src/it/loadstm.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadstm.c - Code to read a ScreamTracker 2 / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_stm_quick(): loads an STM file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_stm_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_stm_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
29
Frameworks/Dumb/dumb/src/it/loadstm2.c
Normal file
29
Frameworks/Dumb/dumb/src/it/loadstm2.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadstm2.c - Function to read a ScreamTracker 2 / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By Chris Moeller. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_stm(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_stm_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
|
@ -1,42 +1,42 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadxm.c - Code to read a Fast Tracker II / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_xm_quick(): loads an XM file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_xm_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_xm_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadxm.c - Code to read a Fast Tracker II / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you. | \/ /\ /
|
||||
* \_ / > /
|
||||
* By entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
/* dumb_load_xm_quick(): loads an XM file into a DUH struct, returning a
|
||||
* pointer to the DUH struct. When you have finished with it, you must
|
||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||
*/
|
||||
DUH *dumb_load_xm_quick(const char *filename)
|
||||
{
|
||||
DUH *duh;
|
||||
DUMBFILE *f = dumbfile_open(filename);
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
duh = dumb_read_xm_quick(f);
|
||||
|
||||
dumbfile_close(f);
|
||||
|
||||
return duh;
|
||||
}
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadxm2.c - Function to read a Fast Tracker II / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* Split off from loadxm.c by entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_xm(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_xm_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* loadxm2.c - Function to read a Fast Tracker II / / \ \
|
||||
* file, opening and closing it for | < / \_
|
||||
* you, and do an initial run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* Split off from loadxm.c by entheh. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_load_xm(const char *filename)
|
||||
{
|
||||
DUH *duh = dumb_load_xm_quick(filename);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
|
|
125
Frameworks/Dumb/dumb/src/it/ptmeffect.c
Normal file
125
Frameworks/Dumb/dumb/src/it/ptmeffect.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* ptmeffect.c - Code for converting PTM / / \ \
|
||||
* effects to IT effects. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Chris Moeller. Based on xmeffect.c \_ / > /
|
||||
* by Julien Cugniere. | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
void _dumb_it_ptm_convert_effect(int effect, int value, IT_ENTRY *entry)
|
||||
{
|
||||
if (effect >= PTM_N_EFFECTS)
|
||||
return;
|
||||
|
||||
/* Linearisation of the effect number... */
|
||||
if (effect == PTM_E) {
|
||||
effect = PTM_EBASE + HIGH(value);
|
||||
value = LOW(value);
|
||||
}
|
||||
|
||||
/* convert effect */
|
||||
entry->mask |= IT_ENTRY_EFFECT;
|
||||
switch (effect) {
|
||||
|
||||
case PTM_APPREGIO: effect = IT_ARPEGGIO; break;
|
||||
case PTM_PORTAMENTO_UP: effect = IT_PORTAMENTO_UP; break;
|
||||
case PTM_PORTAMENTO_DOWN: effect = IT_PORTAMENTO_DOWN; break;
|
||||
case PTM_TONE_PORTAMENTO: effect = IT_TONE_PORTAMENTO; break;
|
||||
case PTM_VIBRATO: effect = IT_VIBRATO; break;
|
||||
case PTM_VOLSLIDE_TONEPORTA: effect = IT_VOLSLIDE_TONEPORTA; break;
|
||||
case PTM_VOLSLIDE_VIBRATO: effect = IT_VOLSLIDE_VIBRATO; break;
|
||||
case PTM_TREMOLO: effect = IT_TREMOLO; break;
|
||||
case PTM_SAMPLE_OFFSET: effect = IT_SET_SAMPLE_OFFSET; break;
|
||||
case PTM_VOLUME_SLIDE: effect = IT_VOLUME_SLIDE; break;
|
||||
case PTM_POSITION_JUMP: effect = IT_JUMP_TO_ORDER; break;
|
||||
case PTM_SET_CHANNEL_VOLUME: effect = IT_SET_CHANNEL_VOLUME; break;
|
||||
case PTM_PATTERN_BREAK: effect = IT_BREAK_TO_ROW; break;
|
||||
case PTM_SET_GLOBAL_VOLUME: effect = IT_SET_GLOBAL_VOLUME; break;
|
||||
case PTM_RETRIGGER: effect = IT_RETRIGGER_NOTE; break;
|
||||
case PTM_FINE_VIBRATO: effect = IT_FINE_VIBRATO; break;
|
||||
|
||||
/* TODO properly */
|
||||
case PTM_NOTE_SLIDE_UP: effect = IT_PTM_NOTE_SLIDE_UP; break;
|
||||
case PTM_NOTE_SLIDE_DOWN: effect = IT_PTM_NOTE_SLIDE_DOWN; break;
|
||||
case PTM_NOTE_SLIDE_UP_RETRIG: effect = IT_PTM_NOTE_SLIDE_UP_RETRIG; break;
|
||||
case PTM_NOTE_SLIDE_DOWN_RETRIG: effect = IT_PTM_NOTE_SLIDE_DOWN_RETRIG; break;
|
||||
|
||||
case PTM_SET_TEMPO_BPM:
|
||||
effect = (value < 0x20) ? (IT_SET_SPEED) : (IT_SET_SONG_TEMPO);
|
||||
break;
|
||||
|
||||
case PTM_EBASE+PTM_E_SET_FINETUNE: effect = SBASE+IT_S_FINETUNE; break; /** TODO */
|
||||
case PTM_EBASE+PTM_E_SET_LOOP: effect = SBASE+IT_S_PATTERN_LOOP; break;
|
||||
case PTM_EBASE+PTM_E_NOTE_CUT: effect = SBASE+IT_S_DELAYED_NOTE_CUT; break;
|
||||
case PTM_EBASE+PTM_E_NOTE_DELAY: effect = SBASE+IT_S_NOTE_DELAY; break;
|
||||
case PTM_EBASE+PTM_E_PATTERN_DELAY: effect = SBASE+IT_S_PATTERN_DELAY; break;
|
||||
case PTM_EBASE+PTM_E_SET_PANNING: effect = SBASE+IT_S_SET_PAN; break;
|
||||
|
||||
case PTM_EBASE+PTM_E_FINE_VOLSLIDE_UP:
|
||||
effect = IT_VOLUME_SLIDE;
|
||||
value = EFFECT_VALUE(value, 0xF);
|
||||
break;
|
||||
|
||||
case PTM_EBASE + PTM_E_FINE_VOLSLIDE_DOWN:
|
||||
effect = IT_VOLUME_SLIDE;
|
||||
value = EFFECT_VALUE(0xF, value);
|
||||
break;
|
||||
|
||||
case PTM_EBASE + PTM_E_FINE_PORTA_UP:
|
||||
effect = IT_PORTAMENTO_UP;
|
||||
value = EFFECT_VALUE(0xF, value);
|
||||
break;
|
||||
|
||||
case PTM_EBASE + PTM_E_FINE_PORTA_DOWN:
|
||||
effect = IT_PORTAMENTO_DOWN;
|
||||
value = EFFECT_VALUE(0xF, value);
|
||||
break;
|
||||
|
||||
case PTM_EBASE + PTM_E_RETRIG_NOTE:
|
||||
effect = IT_XM_RETRIGGER_NOTE;
|
||||
value = EFFECT_VALUE(0, value);
|
||||
break;
|
||||
|
||||
case PTM_EBASE + PTM_E_SET_VIBRATO_CONTROL:
|
||||
effect = SBASE+IT_S_SET_VIBRATO_WAVEFORM;
|
||||
value &= ~4; /** TODO: value&4 -> don't retrig wave */
|
||||
break;
|
||||
|
||||
case PTM_EBASE + PTM_E_SET_TREMOLO_CONTROL:
|
||||
effect = SBASE+IT_S_SET_TREMOLO_WAVEFORM;
|
||||
value &= ~4; /** TODO: value&4 -> don't retrig wave */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* user effect (often used in demos for synchronisation) */
|
||||
entry->mask &= ~IT_ENTRY_EFFECT;
|
||||
}
|
||||
|
||||
/* Inverse linearisation... */
|
||||
if (effect >= SBASE && effect < SBASE+16) {
|
||||
value = EFFECT_VALUE(effect-SBASE, value);
|
||||
effect = IT_S;
|
||||
}
|
||||
|
||||
entry->effect = effect;
|
||||
entry->effectvalue = value;
|
||||
}
|
447
Frameworks/Dumb/dumb/src/it/read669.c
Normal file
447
Frameworks/Dumb/dumb/src/it/read669.c
Normal file
|
@ -0,0 +1,447 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* read669.c - Code to read a 669 Composer module / / \ \
|
||||
* from an open file. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Chris Moeller. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
static int it_669_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int tempo, int breakpoint, unsigned char *buffer, int * used_channels)
|
||||
{
|
||||
int pos;
|
||||
int channel;
|
||||
int row;
|
||||
IT_ENTRY *entry;
|
||||
|
||||
pattern->n_rows = 64;
|
||||
|
||||
if (dumbfile_getnc((char *)buffer, 64 * 3 * 8, f) < 64 * 3 * 8)
|
||||
return -1;
|
||||
|
||||
/* compute number of entries */
|
||||
pattern->n_entries = 64 + 1; /* Account for the row end markers, speed command */
|
||||
if (breakpoint < 63) pattern->n_entries++; /* and break to row 0 */
|
||||
|
||||
pos = 0;
|
||||
for (row = 0; row < 64; row++) {
|
||||
for (channel = 0; channel < 8; channel++) {
|
||||
if (buffer[pos+0] != 0xFF || buffer[pos+2] != 0xFF)
|
||||
pattern->n_entries++;
|
||||
pos += 3;
|
||||
}
|
||||
}
|
||||
|
||||
pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
|
||||
if (!pattern->entry)
|
||||
return -1;
|
||||
|
||||
if (breakpoint == 63) breakpoint++;
|
||||
|
||||
entry = pattern->entry;
|
||||
|
||||
entry->channel = 8;
|
||||
entry->mask = IT_ENTRY_EFFECT;
|
||||
entry->effect = IT_SET_SPEED;
|
||||
entry->effectvalue = tempo;
|
||||
entry++;
|
||||
|
||||
pos = 0;
|
||||
for (row = 0; row < 64; row++) {
|
||||
|
||||
if (row == breakpoint) {
|
||||
entry->channel = 8;
|
||||
entry->mask = IT_ENTRY_EFFECT;
|
||||
entry->effect = IT_BREAK_TO_ROW;
|
||||
entry->effectvalue = 0;
|
||||
entry++;
|
||||
}
|
||||
|
||||
for (channel = 0; channel < 8; channel++) {
|
||||
if (buffer[pos+0] != 0xFF || buffer[pos+2] != 0xFF) {
|
||||
entry->channel = channel;
|
||||
entry->mask = 0;
|
||||
|
||||
if (buffer[pos+0] < 0xFE) {
|
||||
entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT;
|
||||
entry->note = (buffer[pos+0] >> 2) + 36;
|
||||
entry->instrument = (((buffer[pos+0] << 4) | (buffer[pos+1] >> 4)) & 0x3F) + 1;
|
||||
}
|
||||
if (buffer[pos+0] <= 0xFE) {
|
||||
entry->mask |= IT_ENTRY_VOLPAN;
|
||||
entry->volpan = ((buffer[pos+1] & 15) << 6) / 15;
|
||||
if (*used_channels < channel + 1) *used_channels = channel + 1;
|
||||
}
|
||||
if (buffer[pos+2] != 0xFF) {
|
||||
entry->mask |= IT_ENTRY_EFFECT;
|
||||
entry->effectvalue = buffer[pos+2] & 15;
|
||||
switch (buffer[pos+2] >> 4) {
|
||||
case 0:
|
||||
entry->effect = IT_PORTAMENTO_UP;
|
||||
break;
|
||||
case 1:
|
||||
entry->effect = IT_PORTAMENTO_DOWN;
|
||||
break;
|
||||
case 2:
|
||||
entry->effect = IT_TONE_PORTAMENTO;
|
||||
break;
|
||||
case 3:
|
||||
entry->effect = IT_S;
|
||||
entry->effectvalue += IT_S_FINETUNE * 16 + 8;
|
||||
break;
|
||||
case 4:
|
||||
entry->effect = IT_VIBRATO;
|
||||
// XXX speed unknown
|
||||
entry->effectvalue |= 0x10;
|
||||
break;
|
||||
case 5:
|
||||
if (entry->effectvalue) {
|
||||
entry->effect = IT_SET_SPEED;
|
||||
} else {
|
||||
entry->mask &= ~IT_ENTRY_EFFECT;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
/* dunno about this, really... */
|
||||
case 6:
|
||||
if (entry->effectvalue == 0) {
|
||||
entry->effect = IT_PANNING_SLIDE;
|
||||
entry->effectvalue = 0xFE;
|
||||
} else if (entry->effectvalue == 1) {
|
||||
entry->effect = IT_PANNING_SLIDE;
|
||||
entry->effectvalue = 0xEF;
|
||||
} else {
|
||||
entry->mask &= ~IT_ENTRY_EFFECT;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
entry->mask &= ~IT_ENTRY_EFFECT;
|
||||
break;
|
||||
}
|
||||
if (*used_channels < channel + 1) *used_channels = channel + 1;
|
||||
}
|
||||
|
||||
entry++;
|
||||
}
|
||||
pos += 3;
|
||||
}
|
||||
IT_SET_END_ROW(entry);
|
||||
entry++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int it_669_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
|
||||
{
|
||||
dumbfile_getnc((char *)sample->name, 13, f);
|
||||
sample->name[13] = 0;
|
||||
|
||||
sample->filename[0] = 0;
|
||||
|
||||
sample->length = dumbfile_igetl(f);
|
||||
sample->loop_start = dumbfile_igetl(f);
|
||||
sample->loop_end = dumbfile_igetl(f);
|
||||
|
||||
if (dumbfile_error(f))
|
||||
return -1;
|
||||
|
||||
if (sample->length <= 0) {
|
||||
sample->flags = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sample->flags = IT_SAMPLE_EXISTS;
|
||||
|
||||
sample->global_volume = 64;
|
||||
sample->default_volume = 64;
|
||||
|
||||
sample->default_pan = 0;
|
||||
sample->C5_speed = 8363;
|
||||
// the above line might be wrong
|
||||
|
||||
if ((sample->loop_end > sample->length) && !(sample->loop_start))
|
||||
sample->loop_end = 0;
|
||||
|
||||
if (sample->loop_end > sample->length)
|
||||
sample->loop_end = sample->length;
|
||||
|
||||
if (sample->loop_end - sample->loop_start > 2)
|
||||
sample->flags |= IT_SAMPLE_LOOP;
|
||||
|
||||
sample->vibrato_speed = 0;
|
||||
sample->vibrato_depth = 0;
|
||||
sample->vibrato_rate = 0;
|
||||
sample->vibrato_waveform = 0; // do we have to set _all_ these?
|
||||
sample->finetune = 0;
|
||||
sample->max_resampling_quality = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int it_669_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
|
||||
{
|
||||
long i;
|
||||
long truncated_size;
|
||||
|
||||
/* let's get rid of the sample data coming after the end of the loop */
|
||||
if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) {
|
||||
truncated_size = sample->length - sample->loop_end;
|
||||
sample->length = sample->loop_end;
|
||||
} else {
|
||||
truncated_size = 0;
|
||||
}
|
||||
|
||||
sample->data = malloc(sample->length);
|
||||
|
||||
if (!sample->data)
|
||||
return -1;
|
||||
|
||||
if (sample->length)
|
||||
{
|
||||
i = dumbfile_getnc(sample->data, sample->length, f);
|
||||
|
||||
if (i < sample->length) {
|
||||
//return -1;
|
||||
// ficking truncated files
|
||||
if (i <= 0) {
|
||||
sample->flags = 0;
|
||||
return 0;
|
||||
}
|
||||
sample->length = i;
|
||||
if (sample->loop_end > i) sample->loop_end = i;
|
||||
} else {
|
||||
/* skip truncated data */
|
||||
dumbfile_skip(f, truncated_size);
|
||||
// Should we be truncating it?
|
||||
if (dumbfile_error(f))
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < sample->length; i++)
|
||||
((signed char *)sample->data)[i] ^= 0x80;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
|
||||
{
|
||||
DUMB_IT_SIGDATA *sigdata;
|
||||
int n_channels;
|
||||
int i;
|
||||
unsigned char tempolist[128];
|
||||
unsigned char breaklist[128];
|
||||
|
||||
i = dumbfile_igetw(f);
|
||||
if (i != 0x6669 && i != 0x4E4A) return NULL;
|
||||
|
||||
*ext = (i == 0x4E4A);
|
||||
|
||||
sigdata = malloc(sizeof(*sigdata));
|
||||
if (!sigdata) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dumbfile_getnc((char *)sigdata->name, 36, f) < 36) {
|
||||
free(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
sigdata->name[36] = 0;
|
||||
|
||||
sigdata->order = NULL;
|
||||
sigdata->instrument = NULL;
|
||||
sigdata->pattern = NULL;
|
||||
sigdata->midi = NULL;
|
||||
sigdata->checkpoint = NULL;
|
||||
sigdata->sample = NULL;
|
||||
|
||||
sigdata->n_instruments = 0;
|
||||
|
||||
sigdata->song_message = malloc(72 + 2 + 1);
|
||||
if (!sigdata->song_message) {
|
||||
free(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
if (dumbfile_getnc((char *)sigdata->song_message, 36, f) < 36) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
sigdata->song_message[36] = 13;
|
||||
sigdata->song_message[36 + 1] = 10;
|
||||
if (dumbfile_getnc((char *)sigdata->song_message + 38, 36, f) < 36) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
sigdata->song_message[38 + 36] = 0;
|
||||
|
||||
sigdata->n_samples = dumbfile_getc(f);
|
||||
sigdata->n_patterns = dumbfile_getc(f);
|
||||
sigdata->restart_position = dumbfile_getc(f);
|
||||
|
||||
if ((sigdata->n_samples) > 64 || (sigdata->n_patterns > 128)) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->order = malloc(128); /* We may need to scan the extra ones! */
|
||||
if (!sigdata->order) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
if (dumbfile_getnc((char *)sigdata->order, 128, f) < 128) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 128; i++) {
|
||||
if (sigdata->order[i] == 255) break;
|
||||
if (sigdata->order[i] >= sigdata->n_patterns) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (!i) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
sigdata->n_orders = i;
|
||||
|
||||
if (dumbfile_getnc((char *)tempolist, 128, f) < 128) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dumbfile_getnc((char *)breaklist, 128, f) < 128) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
|
||||
if (!sigdata->sample) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < sigdata->n_samples; i++)
|
||||
sigdata->sample[i].data = NULL;
|
||||
|
||||
for (i = 0; i < sigdata->n_samples; i++) {
|
||||
if (it_669_read_sample_header(&sigdata->sample[i], f)) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* May as well try to save a tiny bit of memory. */
|
||||
if (sigdata->n_orders < 128) {
|
||||
unsigned char *order = realloc(sigdata->order, sigdata->n_orders);
|
||||
if (order) sigdata->order = order;
|
||||
}
|
||||
|
||||
sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
|
||||
if (!sigdata->pattern) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < sigdata->n_patterns; i++)
|
||||
sigdata->pattern[i].entry = NULL;
|
||||
|
||||
n_channels = 0;
|
||||
|
||||
/* Read in the patterns */
|
||||
{
|
||||
unsigned char *buffer = malloc(64 * 3 * 8); /* 64 rows * 3 bytes * 8 channels */
|
||||
if (!buffer) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < sigdata->n_patterns; i++) {
|
||||
if (it_669_read_pattern(&sigdata->pattern[i], f, tempolist[i], breaklist[i], buffer, &n_channels) != 0) {
|
||||
free(buffer);
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
sigdata->n_pchannels = n_channels;
|
||||
|
||||
/* And finally, the sample data */
|
||||
for (i = 0; i < sigdata->n_samples; i++) {
|
||||
if (it_669_read_sample_data(&sigdata->sample[i], f)) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now let's initialise the remaining variables, and we're done! */
|
||||
sigdata->flags = IT_OLD_EFFECTS | IT_LINEAR_SLIDES | IT_STEREO | IT_WAS_A_669;
|
||||
|
||||
sigdata->global_volume = 128;
|
||||
sigdata->mixing_volume = 48;
|
||||
sigdata->speed = 4;
|
||||
sigdata->tempo = 78;
|
||||
sigdata->pan_separation = 128;
|
||||
|
||||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (i = 0; i < DUMB_IT_N_CHANNELS; i += 2) {
|
||||
sigdata->channel_pan[i+0] = 48;
|
||||
sigdata->channel_pan[i+1] = 16;
|
||||
}
|
||||
|
||||
_dumb_it_fix_invalid_orders(sigdata);
|
||||
|
||||
return sigdata;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_669_quick(DUMBFILE *f)
|
||||
{
|
||||
sigdata_t *sigdata;
|
||||
int ext;
|
||||
|
||||
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||
|
||||
sigdata = it_669_load_sigdata(f, &ext);
|
||||
|
||||
if (!sigdata)
|
||||
return NULL;
|
||||
|
||||
{
|
||||
const char *tag[2][2];
|
||||
tag[0][0] = "TITLE";
|
||||
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
|
||||
tag[1][0] = "FORMAT";
|
||||
tag[1][1] = ext ? "669 Extended" : "669";
|
||||
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
|
||||
}
|
||||
}
|
29
Frameworks/Dumb/dumb/src/it/read6692.c
Normal file
29
Frameworks/Dumb/dumb/src/it/read6692.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* read6692.c - Code to read a 669 Composer module / / \ \
|
||||
* from an open file, and do an initial | < / \_
|
||||
* run-through. | \/ /\ /
|
||||
* By Chris Moeller. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_669(DUMBFILE *f)
|
||||
{
|
||||
DUH *duh = dumb_read_669_quick(f);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
787
Frameworks/Dumb/dumb/src/it/readam.c
Normal file
787
Frameworks/Dumb/dumb/src/it/readam.c
Normal file
|
@ -0,0 +1,787 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readam.c - Code to read a RIFF AM module / / \ \
|
||||
* from a parsed RIFF structure. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Chris Moeller. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
#include "internal/riff.h"
|
||||
|
||||
static int it_riff_am_process_sample( IT_SAMPLE * sample, DUMBFILE * f, int len, int ver )
|
||||
{
|
||||
int header_length;
|
||||
int default_pan;
|
||||
int default_volume;
|
||||
int flags;
|
||||
int length;
|
||||
int length_bytes;
|
||||
int loop_start;
|
||||
int loop_end;
|
||||
int sample_rate;
|
||||
|
||||
long start = dumbfile_pos( f );
|
||||
|
||||
if ( ver == 0 )
|
||||
{
|
||||
if ( len < 0x38 )
|
||||
return -1;
|
||||
|
||||
header_length = 0x38;
|
||||
|
||||
dumbfile_getnc( (char *) sample->name, 28, f );
|
||||
sample->name[ 28 ] = 0;
|
||||
|
||||
default_pan = dumbfile_getc( f );
|
||||
default_volume = dumbfile_getc( f );
|
||||
flags = dumbfile_igetw( f );
|
||||
length = dumbfile_igetl( f );
|
||||
loop_start = dumbfile_igetl( f );
|
||||
loop_end = dumbfile_igetl( f );
|
||||
sample_rate = dumbfile_igetl( f );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len < 4) return -1;
|
||||
|
||||
header_length = dumbfile_igetl( f );
|
||||
if ( header_length < 0x40 )
|
||||
return -1;
|
||||
if ( header_length + 4 > len )
|
||||
return -1;
|
||||
|
||||
start += 4;
|
||||
len -= 4;
|
||||
|
||||
dumbfile_getnc( (char *) sample->name, 32, f );
|
||||
|
||||
default_pan = dumbfile_igetw( f );
|
||||
default_volume = dumbfile_igetw( f );
|
||||
flags = dumbfile_igetw( f );
|
||||
dumbfile_skip( f, 2 );
|
||||
length = dumbfile_igetl( f );
|
||||
loop_start = dumbfile_igetl( f );
|
||||
loop_end = dumbfile_igetl( f );
|
||||
sample_rate = dumbfile_igetl( f );
|
||||
|
||||
if ( default_pan > 0x7FFF || default_volume > 0x7FFF )
|
||||
return -1;
|
||||
|
||||
default_pan = default_pan * 64 / 32767;
|
||||
default_volume = default_volume * 64 / 32767;
|
||||
}
|
||||
|
||||
if ( ! length ) {
|
||||
sample->flags &= ~IT_SAMPLE_EXISTS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( flags & ~( 0x8000 | 0x80 | 0x20 | 0x10 | 0x08 | 0x04 ) )
|
||||
return -1;
|
||||
|
||||
length_bytes = length << ( ( flags & 0x04 ) >> 2 );
|
||||
|
||||
if ( length_bytes + header_length > len )
|
||||
return -1;
|
||||
|
||||
sample->flags = 0;
|
||||
|
||||
if ( flags & 0x80 ) sample->flags |= IT_SAMPLE_EXISTS;
|
||||
if ( flags & 0x04 ) sample->flags |= IT_SAMPLE_16BIT;
|
||||
|
||||
sample->length = length;
|
||||
sample->loop_start = loop_start;
|
||||
sample->loop_end = loop_end;
|
||||
sample->C5_speed = sample_rate;
|
||||
sample->default_volume = default_volume;
|
||||
sample->default_pan = default_pan | ( ( flags & 0x20 ) << 2 );
|
||||
sample->filename[0] = 0;
|
||||
sample->global_volume = 64;
|
||||
sample->vibrato_speed = 0;
|
||||
sample->vibrato_depth = 0;
|
||||
sample->vibrato_rate = 0;
|
||||
sample->vibrato_waveform = IT_VIBRATO_SINE;
|
||||
sample->finetune = 0;
|
||||
sample->max_resampling_quality = -1;
|
||||
|
||||
if ( flags & 0x08 )
|
||||
{
|
||||
if (((unsigned int)sample->loop_end <= (unsigned int)sample->length) &&
|
||||
((unsigned int)sample->loop_start < (unsigned int)sample->loop_end))
|
||||
{
|
||||
sample->length = sample->loop_end;
|
||||
sample->flags |= IT_SAMPLE_LOOP;
|
||||
if ( flags & 0x10 ) sample->flags |= IT_SAMPLE_PINGPONG_LOOP;
|
||||
}
|
||||
}
|
||||
|
||||
length_bytes = sample->length << ( ( flags & 0x04 ) >> 2 );
|
||||
|
||||
sample->data = malloc( length_bytes );
|
||||
if ( ! sample->data )
|
||||
return -1;
|
||||
|
||||
if ( dumbfile_seek( f, start + header_length, DFS_SEEK_SET ) )
|
||||
return -1;
|
||||
|
||||
dumbfile_getnc( sample->data, length_bytes, f );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int it_riff_am_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int len, int ver )
|
||||
{
|
||||
int nrows, row;
|
||||
long start, end;
|
||||
unsigned flags;
|
||||
int p, q, r;
|
||||
IT_ENTRY * entry;
|
||||
|
||||
nrows = dumbfile_getc( f ) + 1;
|
||||
|
||||
pattern->n_rows = nrows;
|
||||
|
||||
len -= 1;
|
||||
|
||||
pattern->n_entries = 0;
|
||||
|
||||
row = 0;
|
||||
|
||||
start = dumbfile_pos( f );
|
||||
end = start + len;
|
||||
|
||||
while ( (row < nrows) && !dumbfile_error( f ) && (dumbfile_pos( f ) < end) ) {
|
||||
p = dumbfile_getc( f );
|
||||
if ( ! p ) {
|
||||
++ row;
|
||||
continue;
|
||||
}
|
||||
|
||||
flags = p & 0xE0;
|
||||
|
||||
if (flags) {
|
||||
++ pattern->n_entries;
|
||||
if (flags & 0x80) dumbfile_skip( f, 2 );
|
||||
if (flags & 0x40) dumbfile_skip( f, 2 );
|
||||
if (flags & 0x20) dumbfile_skip( f, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! pattern->n_entries ) return 0;
|
||||
|
||||
pattern->n_entries += nrows;
|
||||
|
||||
pattern->entry = malloc( pattern->n_entries * sizeof( * pattern->entry ) );
|
||||
if ( ! pattern->entry ) return -1;
|
||||
|
||||
entry = pattern->entry;
|
||||
|
||||
row = 0;
|
||||
|
||||
dumbfile_seek( f, start, DFS_SEEK_SET );
|
||||
|
||||
while ( ( row < nrows ) && !dumbfile_error( f ) && ( dumbfile_pos( f ) < end ) )
|
||||
{
|
||||
p = dumbfile_getc( f );
|
||||
|
||||
if ( ! p )
|
||||
{
|
||||
IT_SET_END_ROW( entry );
|
||||
++ entry;
|
||||
++ row;
|
||||
continue;
|
||||
}
|
||||
|
||||
flags = p;
|
||||
entry->channel = flags & 0x1F;
|
||||
entry->mask = 0;
|
||||
|
||||
if (flags & 0xE0)
|
||||
{
|
||||
if ( flags & 0x80 )
|
||||
{
|
||||
q = dumbfile_getc( f );
|
||||
r = dumbfile_getc( f );
|
||||
_dumb_it_xm_convert_effect( r, q, entry, 0 );
|
||||
}
|
||||
|
||||
if ( flags & 0x40 )
|
||||
{
|
||||
q = dumbfile_getc( f );
|
||||
r = dumbfile_getc( f );
|
||||
if ( q )
|
||||
{
|
||||
entry->mask |= IT_ENTRY_INSTRUMENT;
|
||||
entry->instrument = q;
|
||||
}
|
||||
if ( r )
|
||||
{
|
||||
entry->mask |= IT_ENTRY_NOTE;
|
||||
entry->note = r - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( flags & 0x20 )
|
||||
{
|
||||
q = dumbfile_getc( f );
|
||||
entry->mask |= IT_ENTRY_VOLPAN;
|
||||
if ( ver == 0 ) entry->volpan = q;
|
||||
else entry->volpan = q * 64 / 127;
|
||||
}
|
||||
|
||||
if (entry->mask) entry++;
|
||||
}
|
||||
}
|
||||
|
||||
while ( row < nrows )
|
||||
{
|
||||
IT_SET_END_ROW( entry );
|
||||
++ entry;
|
||||
++ row;
|
||||
}
|
||||
|
||||
pattern->n_entries = entry - pattern->entry;
|
||||
if ( ! pattern->n_entries ) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DUMB_IT_SIGDATA *it_riff_amff_load_sigdata( DUMBFILE * f, struct riff * stream )
|
||||
{
|
||||
DUMB_IT_SIGDATA *sigdata;
|
||||
|
||||
int n, o, p, found;
|
||||
|
||||
if ( ! stream ) goto error;
|
||||
|
||||
if ( stream->type != DUMB_ID( 'A', 'M', 'F', 'F' ) ) goto error;
|
||||
|
||||
sigdata = malloc( sizeof( *sigdata ) );
|
||||
if ( ! sigdata ) goto error;
|
||||
|
||||
sigdata->n_patterns = 0;
|
||||
sigdata->n_samples = 0;
|
||||
sigdata->name[0] = 0;
|
||||
|
||||
found = 0;
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
{
|
||||
struct riff_chunk * c = stream->chunks + n;
|
||||
switch( c->type )
|
||||
{
|
||||
case DUMB_ID( 'M', 'A', 'I', 'N' ):
|
||||
/* initialization data */
|
||||
if ( ( found & 1 ) || ( c->size < 0x48 ) ) goto error_sd;
|
||||
found |= 1;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'O', 'R', 'D', 'R' ):
|
||||
if ( ( found & 2 ) || ( c->size < 1 ) ) goto error_sd;
|
||||
found |= 2;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'P', 'A', 'T', 'T' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_sd;
|
||||
o = dumbfile_getc( f );
|
||||
if ( o >= sigdata->n_patterns ) sigdata->n_patterns = o + 1;
|
||||
o = dumbfile_igetl( f );
|
||||
if ( (unsigned)o + 5 > c->size ) goto error_sd;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'I', 'N', 'S', 'T' ):
|
||||
{
|
||||
if ( c->size < 0xE1 ) goto error_sd;
|
||||
if ( dumbfile_seek( f, c->offset + 1, DFS_SEEK_SET ) ) goto error_sd;
|
||||
o = dumbfile_getc( f );
|
||||
if ( o >= sigdata->n_samples ) sigdata->n_samples = o + 1;
|
||||
if ( c->size >= 0x121 )
|
||||
{
|
||||
if ( dumbfile_seek( f, c->offset + 0xE1, DFS_SEEK_SET ) ) goto error_sd;
|
||||
if ( dumbfile_mgetl( f ) == DUMB_ID('S','A','M','P') )
|
||||
{
|
||||
unsigned size = dumbfile_igetl( f );
|
||||
if ( size + 0xE1 + 8 > c->size ) goto error_sd;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( found != 3 || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd;
|
||||
|
||||
if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd;
|
||||
|
||||
sigdata->song_message = NULL;
|
||||
sigdata->order = NULL;
|
||||
sigdata->instrument = NULL;
|
||||
sigdata->sample = NULL;
|
||||
sigdata->pattern = NULL;
|
||||
sigdata->midi = NULL;
|
||||
sigdata->checkpoint = NULL;
|
||||
|
||||
sigdata->mixing_volume = 48;
|
||||
sigdata->pan_separation = 128;
|
||||
|
||||
sigdata->n_instruments = 0;
|
||||
sigdata->n_orders = 0;
|
||||
sigdata->restart_position = 0;
|
||||
|
||||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
|
||||
sigdata->channel_pan[n ] = 16;
|
||||
sigdata->channel_pan[n+1] = 48;
|
||||
sigdata->channel_pan[n+2] = 48;
|
||||
sigdata->channel_pan[n+3] = 16;
|
||||
}
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
{
|
||||
struct riff_chunk * c = stream->chunks + n;
|
||||
switch ( c->type )
|
||||
{
|
||||
case DUMB_ID( 'M', 'A', 'I', 'N' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
|
||||
dumbfile_getnc( (char *) sigdata->name, 64, f );
|
||||
sigdata->name[ 64 ] = 0;
|
||||
sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_AN_S3M;
|
||||
o = dumbfile_getc( f );
|
||||
if ( ! ( o & 1 ) ) sigdata->flags |= IT_LINEAR_SLIDES;
|
||||
if ( ( o & ~3 ) || ! ( o & 2 ) ) goto error_usd; // unknown flags
|
||||
sigdata->n_pchannels = dumbfile_getc( f );
|
||||
sigdata->speed = dumbfile_getc( f );
|
||||
sigdata->tempo = dumbfile_getc( f );
|
||||
|
||||
dumbfile_skip( f, 4 );
|
||||
|
||||
sigdata->global_volume = dumbfile_getc( f );
|
||||
|
||||
if ( c->size < 0x48 + (unsigned)sigdata->n_pchannels ) goto error_usd;
|
||||
|
||||
for ( o = 0; o < sigdata->n_pchannels; ++o )
|
||||
{
|
||||
p = dumbfile_getc( f );
|
||||
sigdata->channel_pan[ o ] = p;
|
||||
if ( p >= 128 )
|
||||
{
|
||||
sigdata->channel_volume[ o ] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
|
||||
if ( ! sigdata->pattern ) goto error_usd;
|
||||
for ( n = 0; n < sigdata->n_patterns; ++n )
|
||||
sigdata->pattern[ n ].entry = NULL;
|
||||
|
||||
sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
|
||||
if ( ! sigdata->sample ) goto error_usd;
|
||||
for ( n = 0; n < sigdata->n_samples; ++n )
|
||||
{
|
||||
IT_SAMPLE * sample = sigdata->sample + n;
|
||||
sample->data = NULL;
|
||||
sample->flags = 0;
|
||||
sample->name[ 0 ] = 0;
|
||||
}
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
{
|
||||
struct riff_chunk * c = stream->chunks + n;
|
||||
switch ( c->type )
|
||||
{
|
||||
case DUMB_ID( 'O', 'R', 'D', 'R' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
|
||||
sigdata->n_orders = dumbfile_getc( f ) + 1;
|
||||
if ( (unsigned)sigdata->n_orders + 1 > c->size ) goto error_usd;
|
||||
sigdata->order = malloc( sigdata->n_orders );
|
||||
if ( ! sigdata->order ) goto error_usd;
|
||||
dumbfile_getnc( (char *) sigdata->order, sigdata->n_orders, f );
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'P', 'A', 'T', 'T' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
|
||||
o = dumbfile_getc( f );
|
||||
p = dumbfile_igetl( f );
|
||||
if ( it_riff_am_process_pattern( sigdata->pattern + o, f, p, 0 ) ) goto error_usd;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'I', 'N', 'S', 'T' ):
|
||||
{
|
||||
IT_SAMPLE * sample;
|
||||
if ( dumbfile_seek( f, c->offset + 1, DFS_SEEK_SET ) ) goto error_usd;
|
||||
sample = sigdata->sample + dumbfile_getc( f );
|
||||
if ( c->size >= 0x121 )
|
||||
{
|
||||
if ( dumbfile_seek( f, c->offset + 0xE1, DFS_SEEK_SET ) ) goto error_usd;
|
||||
if ( dumbfile_mgetl( f ) == DUMB_ID('S','A','M','P') )
|
||||
{
|
||||
unsigned size = dumbfile_igetl( f );
|
||||
if ( it_riff_am_process_sample( sample, f, size, 0 ) ) goto error_usd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dumbfile_seek( f, c->offset + 2, DFS_SEEK_SET );
|
||||
dumbfile_getnc( (char *) sample->name, 28, f );
|
||||
sample->name[ 28 ] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_dumb_it_fix_invalid_orders( sigdata );
|
||||
|
||||
return sigdata;
|
||||
|
||||
error_usd:
|
||||
_dumb_it_unload_sigdata( sigdata );
|
||||
goto error;
|
||||
error_sd:
|
||||
free( sigdata );
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DUMB_IT_SIGDATA *it_riff_am_load_sigdata( DUMBFILE * f, struct riff * stream )
|
||||
{
|
||||
DUMB_IT_SIGDATA *sigdata;
|
||||
|
||||
int n, o, p, found;
|
||||
|
||||
if ( ! f || ! stream ) goto error;
|
||||
|
||||
if ( stream->type != DUMB_ID( 'A', 'M', ' ', ' ' ) ) goto error;
|
||||
|
||||
sigdata = malloc(sizeof(*sigdata));
|
||||
if ( ! sigdata ) goto error;
|
||||
|
||||
sigdata->n_patterns = 0;
|
||||
sigdata->n_samples = 0;
|
||||
sigdata->name[0] = 0;
|
||||
|
||||
found = 0;
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
{
|
||||
struct riff_chunk * c = stream->chunks + n;
|
||||
switch( c->type )
|
||||
{
|
||||
case DUMB_ID( 'I' ,'N' ,'I' ,'T' ):
|
||||
/* initialization data */
|
||||
if ( ( found & 1 ) || ( c->size < 0x48 ) ) goto error_sd;
|
||||
found |= 1;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'O', 'R', 'D', 'R' ):
|
||||
if ( ( found & 2 ) || ( c->size < 1 ) ) goto error_sd;
|
||||
found |= 2;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'P', 'A', 'T', 'T' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_sd;
|
||||
o = dumbfile_getc( f );
|
||||
if ( o >= sigdata->n_patterns ) sigdata->n_patterns = o + 1;
|
||||
o = dumbfile_igetl( f );
|
||||
if ( (unsigned)o + 5 > c->size ) goto error_sd;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'R', 'I', 'F', 'F' ):
|
||||
{
|
||||
struct riff * str = c->nested;
|
||||
switch ( str->type )
|
||||
{
|
||||
case DUMB_ID( 'A', 'I', ' ', ' ' ):
|
||||
for ( o = 0; (unsigned)o < str->chunk_count; ++o )
|
||||
{
|
||||
struct riff_chunk * chk = str->chunks + o;
|
||||
switch( chk->type )
|
||||
{
|
||||
case DUMB_ID( 'I', 'N', 'S', 'T' ):
|
||||
{
|
||||
struct riff * temp;
|
||||
unsigned size;
|
||||
unsigned sample_found;
|
||||
if ( dumbfile_seek( f, chk->offset, DFS_SEEK_SET ) ) goto error_sd;
|
||||
size = dumbfile_igetl( f );
|
||||
if ( size < 0x142 ) goto error_sd;
|
||||
sample_found = 0;
|
||||
dumbfile_skip( f, 1 );
|
||||
p = dumbfile_getc( f );
|
||||
if ( p >= sigdata->n_samples ) sigdata->n_samples = p + 1;
|
||||
temp = riff_parse( f, chk->offset + 4 + size, chk->size - size - 4, 1 );
|
||||
if ( temp )
|
||||
{
|
||||
if ( temp->type == DUMB_ID( 'A', 'S', ' ', ' ' ) )
|
||||
{
|
||||
for ( p = 0; (unsigned)p < temp->chunk_count; ++p )
|
||||
{
|
||||
if ( temp->chunks[ p ].type == DUMB_ID( 'S', 'A', 'M', 'P' ) )
|
||||
{
|
||||
if ( sample_found )
|
||||
{
|
||||
riff_free( temp );
|
||||
goto error_sd;
|
||||
}
|
||||
sample_found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
riff_free( temp );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( found != 3 || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd;
|
||||
|
||||
if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd;
|
||||
|
||||
sigdata->song_message = NULL;
|
||||
sigdata->order = NULL;
|
||||
sigdata->instrument = NULL;
|
||||
sigdata->sample = NULL;
|
||||
sigdata->pattern = NULL;
|
||||
sigdata->midi = NULL;
|
||||
sigdata->checkpoint = NULL;
|
||||
|
||||
sigdata->mixing_volume = 48;
|
||||
sigdata->pan_separation = 128;
|
||||
|
||||
sigdata->n_instruments = 0;
|
||||
sigdata->n_orders = 0;
|
||||
sigdata->restart_position = 0;
|
||||
|
||||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
|
||||
sigdata->channel_pan[n ] = 16;
|
||||
sigdata->channel_pan[n+1] = 48;
|
||||
sigdata->channel_pan[n+2] = 48;
|
||||
sigdata->channel_pan[n+3] = 16;
|
||||
}
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
{
|
||||
struct riff_chunk * c = stream->chunks + n;
|
||||
switch ( c->type )
|
||||
{
|
||||
case DUMB_ID( 'I', 'N', 'I', 'T' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
|
||||
dumbfile_getnc( (char *) sigdata->name, 64, f );
|
||||
sigdata->name[ 64 ] = 0;
|
||||
sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_AN_S3M;
|
||||
o = dumbfile_getc( f );
|
||||
if ( ! ( o & 1 ) ) sigdata->flags |= IT_LINEAR_SLIDES;
|
||||
if ( ( o & ~3 ) || ! ( o & 2 ) ) goto error_usd; // unknown flags
|
||||
sigdata->n_pchannels = dumbfile_getc( f );
|
||||
sigdata->speed = dumbfile_getc( f );
|
||||
sigdata->tempo = dumbfile_getc( f );
|
||||
|
||||
dumbfile_skip( f, 4 );
|
||||
|
||||
sigdata->global_volume = dumbfile_getc( f );
|
||||
|
||||
if ( c->size < 0x48 + (unsigned)sigdata->n_pchannels ) goto error_usd;
|
||||
|
||||
for ( o = 0; o < sigdata->n_pchannels; ++o )
|
||||
{
|
||||
p = dumbfile_getc( f );
|
||||
if ( p <= 128 )
|
||||
{
|
||||
sigdata->channel_pan[ o ] = p / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
sigdata->channel_volume[ o ] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
|
||||
if ( ! sigdata->pattern ) goto error_usd;
|
||||
for ( n = 0; n < sigdata->n_patterns; ++n )
|
||||
sigdata->pattern[ n ].entry = NULL;
|
||||
|
||||
sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
|
||||
if ( ! sigdata->sample ) goto error_usd;
|
||||
for ( n = 0; n < sigdata->n_samples; ++n )
|
||||
{
|
||||
IT_SAMPLE * sample = sigdata->sample + n;
|
||||
sample->data = NULL;
|
||||
sample->flags = 0;
|
||||
sample->name[ 0 ] = 0;
|
||||
}
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
{
|
||||
struct riff_chunk * c = stream->chunks + n;
|
||||
switch ( c->type )
|
||||
{
|
||||
case DUMB_ID( 'O', 'R', 'D', 'R' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
|
||||
sigdata->n_orders = dumbfile_getc( f ) + 1;
|
||||
if ( (unsigned)sigdata->n_orders + 1 > c->size ) goto error_usd;
|
||||
sigdata->order = malloc( sigdata->n_orders );
|
||||
if ( ! sigdata->order ) goto error_usd;
|
||||
dumbfile_getnc( (char *) sigdata->order, sigdata->n_orders, f );
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'P', 'A', 'T', 'T' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
|
||||
o = dumbfile_getc( f );
|
||||
p = dumbfile_igetl( f );
|
||||
if ( it_riff_am_process_pattern( sigdata->pattern + o, f, p, 1 ) ) goto error_usd;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'R', 'I', 'F', 'F' ):
|
||||
{
|
||||
struct riff * str = c->nested;
|
||||
switch ( str->type )
|
||||
{
|
||||
case DUMB_ID('A', 'I', ' ', ' '):
|
||||
for ( o = 0; (unsigned)o < str->chunk_count; ++o )
|
||||
{
|
||||
struct riff_chunk * chk = str->chunks + o;
|
||||
switch( chk->type )
|
||||
{
|
||||
case DUMB_ID( 'I', 'N', 'S', 'T' ):
|
||||
{
|
||||
struct riff * temp;
|
||||
unsigned size;
|
||||
unsigned sample_found;
|
||||
IT_SAMPLE * sample;
|
||||
if ( dumbfile_seek( f, chk->offset, DFS_SEEK_SET ) ) goto error_usd;
|
||||
size = dumbfile_igetl( f );
|
||||
dumbfile_skip( f, 1 );
|
||||
p = dumbfile_getc( f );
|
||||
temp = riff_parse( f, chk->offset + 4 + size, chk->size - size - 4, 1 );
|
||||
sample_found = 0;
|
||||
sample = sigdata->sample + p;
|
||||
if ( temp )
|
||||
{
|
||||
if ( temp->type == DUMB_ID( 'A', 'S', ' ', ' ' ) )
|
||||
{
|
||||
for ( p = 0; (unsigned)p < temp->chunk_count; ++p )
|
||||
{
|
||||
struct riff_chunk * c = temp->chunks + p;
|
||||
if ( c->type == DUMB_ID( 'S', 'A', 'M', 'P' ) )
|
||||
{
|
||||
if ( sample_found )
|
||||
{
|
||||
riff_free( temp );
|
||||
goto error_usd;
|
||||
}
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) )
|
||||
{
|
||||
riff_free( temp );
|
||||
goto error_usd;
|
||||
}
|
||||
if ( it_riff_am_process_sample( sample, f, c->size, 1 ) )
|
||||
{
|
||||
riff_free( temp );
|
||||
goto error_usd;
|
||||
}
|
||||
sample_found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
riff_free( temp );
|
||||
}
|
||||
if ( ! sample_found )
|
||||
{
|
||||
dumbfile_seek( f, chk->offset + 6, DFS_SEEK_SET );
|
||||
dumbfile_getnc( (char *) sample->name, 32, f );
|
||||
sample->name[ 32 ] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_dumb_it_fix_invalid_orders( sigdata );
|
||||
|
||||
return sigdata;
|
||||
|
||||
error_usd:
|
||||
_dumb_it_unload_sigdata( sigdata );
|
||||
goto error;
|
||||
error_sd:
|
||||
free( sigdata );
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DUH *dumb_read_riff_amff( DUMBFILE * f, struct riff * stream )
|
||||
{
|
||||
sigdata_t *sigdata;
|
||||
long length;
|
||||
|
||||
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||
|
||||
sigdata = it_riff_amff_load_sigdata( f, stream );
|
||||
|
||||
if (!sigdata)
|
||||
return NULL;
|
||||
|
||||
length = 0;/*_dumb_it_build_checkpoints(sigdata, 0);*/
|
||||
|
||||
{
|
||||
const char *tag[2][2];
|
||||
tag[0][0] = "TITLE";
|
||||
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
|
||||
tag[1][0] = "FORMAT";
|
||||
tag[1][1] = "RIFF AMFF";
|
||||
return make_duh( length, 2, ( const char * const (*) [ 2 ] ) tag, 1, & descptr, & sigdata );
|
||||
}
|
||||
}
|
||||
|
||||
DUH *dumb_read_riff_am( DUMBFILE * f, struct riff * stream )
|
||||
{
|
||||
sigdata_t *sigdata;
|
||||
|
||||
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||
|
||||
sigdata = it_riff_am_load_sigdata( f, stream );
|
||||
|
||||
if (!sigdata)
|
||||
return NULL;
|
||||
|
||||
{
|
||||
const char *tag[2][2];
|
||||
tag[0][0] = "TITLE";
|
||||
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
|
||||
tag[1][0] = "FORMAT";
|
||||
tag[1][1] = "RIFF AM";
|
||||
return make_duh( -1, 2, ( const char * const (*) [ 2 ] ) tag, 1, & descptr, & sigdata );
|
||||
}
|
||||
}
|
523
Frameworks/Dumb/dumb/src/it/readamf.c
Normal file
523
Frameworks/Dumb/dumb/src/it/readamf.c
Normal file
|
@ -0,0 +1,523 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readamf.c - Code to read a DSMI AMF module from / / \ \
|
||||
* an open file. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Chris Moeller. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
static void it_amf_process_track( IT_ENTRY *entry_table, unsigned char *track, int rows, int channels )
|
||||
{
|
||||
int last_instrument = 0;
|
||||
int tracksize = track[ 0 ] + ( track[ 1 ] << 8 ) + ( track[ 2 ] << 16 );
|
||||
track += 3;
|
||||
while ( tracksize-- ) {
|
||||
unsigned int row = track[ 0 ];
|
||||
unsigned int command = track[ 1 ];
|
||||
unsigned int argument = track[ 2 ];
|
||||
IT_ENTRY * entry = entry_table + row * channels;
|
||||
if ( row >= ( unsigned int ) rows ) break;
|
||||
if ( command < 0x7F ) {
|
||||
entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT | IT_ENTRY_VOLPAN;
|
||||
entry->note = command;
|
||||
if ( ! entry->instrument ) entry->instrument = last_instrument;
|
||||
entry->volpan = argument;
|
||||
}
|
||||
else if ( command == 0x7F ) {
|
||||
signed char row_delta = ( signed char ) argument;
|
||||
int row_source = ( int ) row + ( int ) row_delta;
|
||||
if ( row_source >= 0 && row_source < ( int ) rows ) {
|
||||
*entry = entry_table[ row_source * channels ];
|
||||
}
|
||||
}
|
||||
else if ( command == 0x80 ) {
|
||||
entry->mask |= IT_ENTRY_INSTRUMENT;
|
||||
last_instrument = argument + 1;
|
||||
entry->instrument = last_instrument;
|
||||
}
|
||||
else if ( command == 0x83 ) {
|
||||
entry->mask |= IT_ENTRY_VOLPAN;
|
||||
entry->volpan = argument;
|
||||
}
|
||||
else {
|
||||
unsigned int effect = command & 0x7F;
|
||||
unsigned int effectvalue = argument;
|
||||
switch (effect) {
|
||||
case 0x01: effect = IT_SET_SPEED; break;
|
||||
|
||||
case 0x02: effect = IT_VOLUME_SLIDE;
|
||||
case 0x0A: if ( effect == 0x0A ) effect = IT_VOLSLIDE_TONEPORTA;
|
||||
case 0x0B: if ( effect == 0x0B ) effect = IT_VOLSLIDE_VIBRATO;
|
||||
if ( effectvalue & 0x80 ) effectvalue = ( -( signed char ) effectvalue ) & 0x0F;
|
||||
else effectvalue = ( effectvalue & 0x0F ) << 4;
|
||||
break;
|
||||
|
||||
case 0x04: if ( effectvalue & 0x80 ) { effect = IT_PORTAMENTO_UP; effectvalue = ( -( signed char ) effectvalue ) & 0x7F; }
|
||||
else { effect = IT_PORTAMENTO_DOWN; }
|
||||
break;
|
||||
|
||||
case 0x06: effect = IT_TONE_PORTAMENTO; break;
|
||||
|
||||
case 0x07: effect = IT_TREMOR; break;
|
||||
|
||||
case 0x08: effect = IT_ARPEGGIO; break;
|
||||
|
||||
case 0x09: effect = IT_VIBRATO; break;
|
||||
|
||||
case 0x0C: effect = IT_BREAK_TO_ROW; break;
|
||||
|
||||
case 0x0D: effect = IT_JUMP_TO_ORDER; break;
|
||||
|
||||
case 0x0F: effect = IT_RETRIGGER_NOTE; break;
|
||||
|
||||
case 0x10: effect = IT_SET_SAMPLE_OFFSET; break;
|
||||
|
||||
case 0x11: if ( effectvalue ) { effect = IT_VOLUME_SLIDE;
|
||||
if ( effectvalue & 0x80 ) effectvalue = 0xF0 | ( ( -( signed char ) effectvalue ) & 0x0F );
|
||||
else effectvalue = 0x0F | ( ( effectvalue & 0x0F ) << 4 );
|
||||
} else effect = 0;
|
||||
break;
|
||||
|
||||
case 0x12:
|
||||
case 0x16: if ( effectvalue ) { int mask = ( effect == 0x16 ) ? 0xE0 : 0xF0;
|
||||
effect = ( effectvalue & 0x80 ) ? IT_PORTAMENTO_UP : IT_PORTAMENTO_DOWN;
|
||||
if ( effectvalue & 0x80 ) effectvalue = mask | ( ( -( signed char ) effectvalue ) & 0x0F );
|
||||
else effectvalue = mask | ( effectvalue & 0x0F );
|
||||
} else effect = 0;
|
||||
break;
|
||||
|
||||
case 0x13: effect = IT_S; effectvalue = EFFECT_VALUE( IT_S_NOTE_DELAY, effectvalue & 0x0F ); break;
|
||||
|
||||
case 0x14: effect = IT_S; effectvalue = EFFECT_VALUE( IT_S_DELAYED_NOTE_CUT, effectvalue & 0x0F ); break;
|
||||
|
||||
case 0x15: effect = IT_SET_SONG_TEMPO; break;
|
||||
|
||||
case 0x17: effectvalue = ( effectvalue + 64 ) & 0x7F;
|
||||
if ( entry->mask & IT_ENTRY_EFFECT ) { if ( !( entry->mask & IT_ENTRY_VOLPAN ) ) { entry->volpan = ( effectvalue / 2 ) + 128; } effect = 0; }
|
||||
else { effect = IT_SET_PANNING; }
|
||||
break;
|
||||
|
||||
default: effect = effectvalue = 0;
|
||||
}
|
||||
if ( effect ) {
|
||||
entry->mask |= IT_ENTRY_EFFECT;
|
||||
entry->effect = effect;
|
||||
entry->effectvalue = effectvalue;
|
||||
}
|
||||
}
|
||||
track += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static int it_amf_process_pattern( IT_PATTERN *pattern, IT_ENTRY *entry_table, int rows, int channels )
|
||||
{
|
||||
int i, j;
|
||||
int n_entries = rows;
|
||||
IT_ENTRY * entry;
|
||||
|
||||
pattern->n_rows = rows;
|
||||
|
||||
for ( i = 0, j = channels * rows; i < j; i++ ) {
|
||||
if ( entry_table[ i ].mask ) {
|
||||
n_entries++;
|
||||
}
|
||||
}
|
||||
|
||||
pattern->n_entries = n_entries;
|
||||
|
||||
pattern->entry = entry = malloc( n_entries * sizeof( IT_ENTRY ) );
|
||||
if ( !entry ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for ( i = 0; i < rows; i++ ) {
|
||||
for ( j = 0; j < channels; j++ ) {
|
||||
if ( entry_table[ i * channels + j ].mask ) {
|
||||
*entry = entry_table[ i * channels + j ];
|
||||
entry->channel = j;
|
||||
entry++;
|
||||
}
|
||||
}
|
||||
IT_SET_END_ROW( entry );
|
||||
entry++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int it_amf_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f, int * offset, int ver )
|
||||
{
|
||||
int exists;
|
||||
|
||||
exists = dumbfile_getc( f );
|
||||
|
||||
dumbfile_getnc( (char *) sample->name, 32, f );
|
||||
sample->name[32] = 0;
|
||||
|
||||
dumbfile_getnc( (char *) sample->filename, 13, f );
|
||||
sample->filename[13] = 0;
|
||||
|
||||
*offset = dumbfile_igetl( f );
|
||||
sample->length = dumbfile_igetl( f );
|
||||
sample->C5_speed = dumbfile_igetw( f );
|
||||
sample->default_volume = dumbfile_getc( f );
|
||||
sample->global_volume = 64;
|
||||
if ( sample->default_volume > 64 ) sample->default_volume = 64;
|
||||
|
||||
if ( ver >= 11 ) {
|
||||
sample->loop_start = dumbfile_igetl( f );
|
||||
sample->loop_end = dumbfile_igetl( f );
|
||||
} else {
|
||||
sample->loop_start = dumbfile_igetw( f );
|
||||
sample->loop_end = sample->length;
|
||||
}
|
||||
|
||||
if ( sample->length <= 0 ) {
|
||||
sample->flags = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sample->flags = exists == 1 ? IT_SAMPLE_EXISTS : 0;
|
||||
|
||||
sample->default_pan = 0;
|
||||
sample->finetune = 0;
|
||||
|
||||
if ( sample->loop_start != 0 )
|
||||
sample->flags |= IT_SAMPLE_LOOP;
|
||||
|
||||
sample->vibrato_speed = 0;
|
||||
sample->vibrato_depth = 0;
|
||||
sample->vibrato_rate = 0;
|
||||
sample->vibrato_waveform = 0; // do we have to set _all_ these?
|
||||
sample->max_resampling_quality = -1;
|
||||
|
||||
return dumbfile_error(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int it_amf_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
|
||||
{
|
||||
int i, read_length = 0;
|
||||
|
||||
sample->data = malloc( sample->length );
|
||||
|
||||
if ( !sample->data )
|
||||
return -1;
|
||||
|
||||
if ( sample->length )
|
||||
read_length = dumbfile_getnc( sample->data, sample->length, f );
|
||||
|
||||
for ( i = 0; i < read_length; i++ ) {
|
||||
( ( char * ) sample->data )[ i ] ^= 0x80;
|
||||
}
|
||||
|
||||
for ( i = read_length; i < sample->length; i++ ) {
|
||||
( ( char * ) sample->data )[ i ] = 0;
|
||||
}
|
||||
|
||||
return 0; /* Sometimes the last sample is truncated :( */
|
||||
}
|
||||
|
||||
static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
|
||||
{
|
||||
DUMB_IT_SIGDATA *sigdata;
|
||||
int i, j, ver, ntracks, realntracks, nchannels;
|
||||
|
||||
int maxsampleseekpos = 0;
|
||||
int sampleseekpos[256];
|
||||
|
||||
unsigned short *orderstotracks;
|
||||
unsigned short *trackmap;
|
||||
unsigned int tracksize[256];
|
||||
|
||||
unsigned char **track;
|
||||
|
||||
static const char sig[] = "AMF";
|
||||
|
||||
char signature [3];
|
||||
|
||||
if ( dumbfile_getnc( signature, 3, f ) != 3 ||
|
||||
memcmp( signature, sig, 3 ) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*version = ver = dumbfile_getc( f );
|
||||
if ( ver < 10 || ver > 14) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata = malloc(sizeof(*sigdata));
|
||||
if (!sigdata) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dumbfile_getnc( (char *) sigdata->name, 32, f );
|
||||
sigdata->name[ 32 ] = 0;
|
||||
sigdata->n_samples = dumbfile_getc( f );
|
||||
sigdata->n_orders = dumbfile_getc( f );
|
||||
ntracks = dumbfile_igetw( f );
|
||||
nchannels = dumbfile_getc( f );
|
||||
|
||||
if ( dumbfile_error( f ) ||
|
||||
sigdata->n_samples < 1 || sigdata->n_samples > 255 ||
|
||||
sigdata->n_orders < 1 || sigdata->n_orders > 255 ||
|
||||
! ntracks ||
|
||||
nchannels < 1 || nchannels > 32 ) {
|
||||
free( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS );
|
||||
|
||||
if ( ver >= 11 ) {
|
||||
int nchannels = ( ver >= 13 ) ? 32 : 16;
|
||||
for ( i = 0; i < nchannels; i++ ) {
|
||||
signed char panpos = dumbfile_getc( f );
|
||||
int pan = ( panpos + 64 ) / 2;
|
||||
if ( pan < 0 ) pan = 0;
|
||||
else if ( pan > 64 ) pan = IT_SURROUND;
|
||||
sigdata->channel_pan[ i ] = pan;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for ( i = 0; i < 16; i++ ) {
|
||||
sigdata->channel_pan[ i ] = ( dumbfile_getc( f ) & 1 ) ? 16 : 48;
|
||||
}
|
||||
}
|
||||
|
||||
sigdata->tempo = 125;
|
||||
sigdata->speed = 6;
|
||||
if ( ver >= 13 ) {
|
||||
i = dumbfile_getc( f );
|
||||
if ( i >= 32 ) sigdata->tempo = i;
|
||||
i = dumbfile_getc( f );
|
||||
if ( i <= 32 ) sigdata->speed = i;
|
||||
}
|
||||
|
||||
sigdata->order = malloc( sigdata->n_orders );
|
||||
if ( !sigdata->order ) {
|
||||
free( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
orderstotracks = malloc( sigdata->n_orders * nchannels * sizeof( unsigned short ) );
|
||||
if ( !orderstotracks ) {
|
||||
free( sigdata->order );
|
||||
free( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for ( i = 0; i < sigdata->n_orders; i++ ) {
|
||||
sigdata->order[ i ] = i;
|
||||
tracksize[ i ] = 64;
|
||||
if ( ver >= 14 ) {
|
||||
tracksize[ i ] = dumbfile_igetw( f );
|
||||
}
|
||||
for ( j = 0; j < nchannels; j++ ) {
|
||||
orderstotracks[ i * nchannels + j ] = dumbfile_igetw( f );
|
||||
}
|
||||
}
|
||||
|
||||
if ( dumbfile_error( f ) ) {
|
||||
free( orderstotracks );
|
||||
free( sigdata->order );
|
||||
free( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
|
||||
if ( !sigdata->sample ) {
|
||||
free( orderstotracks );
|
||||
free( sigdata->order );
|
||||
free( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->restart_position = 0;
|
||||
|
||||
sigdata->song_message = NULL;
|
||||
sigdata->instrument = NULL;
|
||||
sigdata->pattern = NULL;
|
||||
sigdata->midi = NULL;
|
||||
sigdata->checkpoint = NULL;
|
||||
|
||||
sigdata->n_instruments = 0;
|
||||
|
||||
for ( i = 0; i < sigdata->n_samples; ++i )
|
||||
sigdata->sample[i].data = NULL;
|
||||
|
||||
for ( i = 0; i < sigdata->n_samples; ++i ) {
|
||||
int offset;
|
||||
if ( it_amf_read_sample_header( &sigdata->sample[i], f, &offset, ver ) ) {
|
||||
goto error_ott;
|
||||
}
|
||||
sampleseekpos[ i ] = offset;
|
||||
if ( offset > maxsampleseekpos ) maxsampleseekpos = offset;
|
||||
}
|
||||
|
||||
sigdata->n_patterns = sigdata->n_orders;
|
||||
|
||||
sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
|
||||
if ( !sigdata->pattern ) {
|
||||
goto error_ott;
|
||||
}
|
||||
for (i = 0; i < sigdata->n_patterns; ++i)
|
||||
sigdata->pattern[i].entry = NULL;
|
||||
|
||||
trackmap = malloc( ntracks * sizeof( unsigned short ) );
|
||||
if ( !trackmap ) {
|
||||
goto error_ott;
|
||||
}
|
||||
|
||||
if ( dumbfile_getnc( ( char * ) trackmap, ntracks * sizeof( unsigned short ), f ) != (long)(ntracks * sizeof( unsigned short )) ) {
|
||||
goto error_tm;
|
||||
}
|
||||
|
||||
realntracks = 0;
|
||||
|
||||
for ( i = 0; i < ntracks; i++ ) {
|
||||
if ( trackmap[ i ] > realntracks ) realntracks = trackmap[ i ];
|
||||
}
|
||||
|
||||
track = calloc( realntracks, sizeof( unsigned char * ) );
|
||||
if ( !track ) {
|
||||
goto error_tm;
|
||||
}
|
||||
|
||||
for ( i = 0; i < realntracks; i++ ) {
|
||||
int tracksize = dumbfile_igetw( f );
|
||||
tracksize += dumbfile_getc( f ) << 16;
|
||||
track[ i ] = malloc( tracksize * 3 + 3 );
|
||||
if ( !track[ i ] ) {
|
||||
goto error_all;
|
||||
}
|
||||
track[ i ][ 0 ] = tracksize & 255;
|
||||
track[ i ][ 1 ] = ( tracksize >> 8 ) & 255;
|
||||
track[ i ][ 2 ] = ( tracksize >> 16 ) & 255;
|
||||
if ( dumbfile_getnc( (char *) track[ i ] + 3, tracksize * 3, f ) != tracksize * 3 ) {
|
||||
goto error_all;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 1; i <= maxsampleseekpos; i++ ) {
|
||||
for ( j = 0; j < sigdata->n_samples; j++ ) {
|
||||
if ( sampleseekpos[ j ] == i ) {
|
||||
if ( it_amf_read_sample_data( &sigdata->sample[ j ], f ) ) {
|
||||
goto error_all;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Process tracks into patterns */
|
||||
for ( i = 0; i < sigdata->n_patterns; i++ ) {
|
||||
IT_ENTRY * entry_table = calloc( tracksize[ i ] * nchannels, sizeof( IT_ENTRY ) );
|
||||
if ( !entry_table ) {
|
||||
goto error_all;
|
||||
}
|
||||
for ( j = 0; j < nchannels; j++ ) {
|
||||
int ntrack = orderstotracks[ i * nchannels + j ];
|
||||
if ( ntrack && ntrack <= ntracks ) {
|
||||
int realtrack = trackmap[ ntrack - 1 ];
|
||||
if ( realtrack ) {
|
||||
realtrack--;
|
||||
if ( realtrack < realntracks && track[ realtrack ] ) {
|
||||
it_amf_process_track( entry_table + j, track[ realtrack ], tracksize[ i ], nchannels );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( it_amf_process_pattern( &sigdata->pattern[ i ], entry_table, tracksize[ i ], nchannels ) ) {
|
||||
free( entry_table );
|
||||
goto error_all;
|
||||
}
|
||||
free( entry_table );
|
||||
}
|
||||
|
||||
/* Now let's initialise the remaining variables, and we're done! */
|
||||
sigdata->flags = IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
|
||||
|
||||
sigdata->global_volume = 128;
|
||||
sigdata->mixing_volume = 48;
|
||||
sigdata->pan_separation = 128;
|
||||
|
||||
_dumb_it_fix_invalid_orders(sigdata);
|
||||
|
||||
for ( i = 0; i < realntracks; i++ ) {
|
||||
if ( track[ i ] ) {
|
||||
free( track[ i ] );
|
||||
}
|
||||
}
|
||||
free( track );
|
||||
free( trackmap );
|
||||
free( orderstotracks );
|
||||
|
||||
return sigdata;
|
||||
|
||||
error_all:
|
||||
for ( i = 0; i < realntracks; i++ ) {
|
||||
if ( track[ i ] ) {
|
||||
free( track[ i ] );
|
||||
}
|
||||
}
|
||||
free( track );
|
||||
error_tm:
|
||||
free( trackmap );
|
||||
error_ott:
|
||||
free( orderstotracks );
|
||||
_dumb_it_unload_sigdata( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_amf_quick(DUMBFILE *f)
|
||||
{
|
||||
sigdata_t *sigdata;
|
||||
|
||||
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||
|
||||
int version;
|
||||
|
||||
sigdata = it_amf_load_sigdata(f, &version);
|
||||
|
||||
if (!sigdata)
|
||||
return NULL;
|
||||
|
||||
{
|
||||
const char *tag[2][2];
|
||||
char ver_string[14];
|
||||
tag[0][0] = "TITLE";
|
||||
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
|
||||
tag[1][0] = "FORMAT";
|
||||
memcpy( ver_string, "DSMI AMF v", 10 );
|
||||
ver_string[10] = '0' + version / 10;
|
||||
ver_string[11] = '.';
|
||||
ver_string[12] = '0' + version % 10;
|
||||
ver_string[13] = 0;
|
||||
tag[1][1] = ver_string;
|
||||
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
|
||||
}
|
||||
}
|
29
Frameworks/Dumb/dumb/src/it/readamf2.c
Normal file
29
Frameworks/Dumb/dumb/src/it/readamf2.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readamf2.c - Function to read a DSMI AMF module / / \ \
|
||||
* from an open file and do an initial | < / \_
|
||||
* run-through. | \/ /\ /
|
||||
* \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_amf(DUMBFILE *f)
|
||||
{
|
||||
DUH *duh = dumb_read_amf_quick(f);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
132
Frameworks/Dumb/dumb/src/it/readany.c
Normal file
132
Frameworks/Dumb/dumb/src/it/readany.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readany.c - Code to detect and read any of the / / \ \
|
||||
* module formats supported by DUMB. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Chris Moeller. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strnicmp _strnicmp
|
||||
#else
|
||||
#if defined(unix) || defined(__unix__) || defined(__unix)
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#define strnicmp strncasecmp
|
||||
#endif
|
||||
|
||||
enum { maximum_signature_size = 0x30 };
|
||||
|
||||
DUH *dumb_read_any_quick(DUMBFILE *f, int restrict_, int subsong)
|
||||
{
|
||||
unsigned char signature[ maximum_signature_size ];
|
||||
unsigned long signature_size;
|
||||
DUH * duh = NULL;
|
||||
|
||||
signature_size = dumbfile_get_size(f);
|
||||
|
||||
signature_size = dumbfile_getnc( (char *)signature, maximum_signature_size, f );
|
||||
dumbfile_seek( f, 0, DFS_SEEK_SET );
|
||||
|
||||
if (signature_size >= 4 &&
|
||||
signature[0] == 'I' && signature[1] == 'M' &&
|
||||
signature[2] == 'P' && signature[3] == 'M')
|
||||
{
|
||||
duh = dumb_read_it_quick( f );
|
||||
}
|
||||
else if (signature_size >= 17 && !memcmp(signature, "Extended Module: ", 17))
|
||||
{
|
||||
duh = dumb_read_xm_quick( f );
|
||||
}
|
||||
else if (signature_size >= 0x30 &&
|
||||
signature[0x2C] == 'S' && signature[0x2D] == 'C' &&
|
||||
signature[0x2E] == 'R' && signature[0x2F] == 'M')
|
||||
{
|
||||
duh = dumb_read_s3m_quick( f );
|
||||
}
|
||||
else if (signature_size >= 30 &&
|
||||
/*signature[28] == 0x1A &&*/ signature[29] == 2 &&
|
||||
( ! strnicmp( ( const char * ) signature + 20, "!Scream!", 8 ) ||
|
||||
! strnicmp( ( const char * ) signature + 20, "BMOD2STM", 8 ) ||
|
||||
! strnicmp( ( const char * ) signature + 20, "WUZAMOD!", 8 ) ) )
|
||||
{
|
||||
duh = dumb_read_stm_quick( f );
|
||||
}
|
||||
else if (signature_size >= 2 &&
|
||||
((signature[0] == 0x69 && signature[1] == 0x66) ||
|
||||
(signature[0] == 0x4A && signature[1] == 0x4E)))
|
||||
{
|
||||
duh = dumb_read_669_quick( f );
|
||||
}
|
||||
else if (signature_size >= 0x30 &&
|
||||
signature[0x2C] == 'P' && signature[0x2D] == 'T' &&
|
||||
signature[0x2E] == 'M' && signature[0x2F] == 'F')
|
||||
{
|
||||
duh = dumb_read_ptm_quick( f );
|
||||
}
|
||||
else if (signature_size >= 4 &&
|
||||
signature[0] == 'P' && signature[1] == 'S' &&
|
||||
signature[2] == 'M' && signature[3] == ' ')
|
||||
{
|
||||
duh = dumb_read_psm_quick( f, subsong );
|
||||
}
|
||||
else if (signature_size >= 4 &&
|
||||
signature[0] == 'P' && signature[1] == 'S' &&
|
||||
signature[2] == 'M' && signature[3] == 254)
|
||||
{
|
||||
duh = dumb_read_old_psm_quick( f );
|
||||
}
|
||||
else if (signature_size >= 3 &&
|
||||
signature[0] == 'M' && signature[1] == 'T' &&
|
||||
signature[2] == 'M')
|
||||
{
|
||||
duh = dumb_read_mtm_quick( f );
|
||||
}
|
||||
else if ( signature_size >= 4 &&
|
||||
signature[0] == 'R' && signature[1] == 'I' &&
|
||||
signature[2] == 'F' && signature[3] == 'F')
|
||||
{
|
||||
duh = dumb_read_riff_quick( f );
|
||||
}
|
||||
else if ( signature_size >= 24 &&
|
||||
!memcmp( signature, "ASYLUM Music Format", 19 ) &&
|
||||
!memcmp( signature + 19, " V1.0", 5 ) )
|
||||
{
|
||||
duh = dumb_read_asy_quick( f );
|
||||
}
|
||||
else if ( signature_size >= 3 &&
|
||||
signature[0] == 'A' && signature[1] == 'M' &&
|
||||
signature[2] == 'F')
|
||||
{
|
||||
duh = dumb_read_amf_quick( f );
|
||||
}
|
||||
else if ( signature_size >= 8 &&
|
||||
!memcmp( signature, "OKTASONG", 8 ) )
|
||||
{
|
||||
duh = dumb_read_okt_quick( f );
|
||||
}
|
||||
|
||||
if ( !duh )
|
||||
{
|
||||
dumbfile_seek( f, 0, DFS_SEEK_SET );
|
||||
duh = dumb_read_mod_quick( f, restrict_ );
|
||||
}
|
||||
|
||||
return duh;
|
||||
}
|
29
Frameworks/Dumb/dumb/src/it/readany2.c
Normal file
29
Frameworks/Dumb/dumb/src/it/readany2.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readany2.c - Code to detect and read any of the / / \ \
|
||||
* module formats supported by DUMB | < / \_
|
||||
* from an open file and do an initial | \/ /\ /
|
||||
* run-through. \_ / > /
|
||||
* | \ / /
|
||||
* by Chris Moeller. | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_any(DUMBFILE *f, int restrict_, int subsong)
|
||||
{
|
||||
DUH *duh = dumb_read_any_quick(f, restrict_, subsong);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
331
Frameworks/Dumb/dumb/src/it/readasy.c
Normal file
331
Frameworks/Dumb/dumb/src/it/readasy.c
Normal file
|
@ -0,0 +1,331 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readasy.c - Code to read an ASYLUM Music Format / / \ \
|
||||
* module from an open file. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Chris Moeller. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
static int it_asy_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer )
|
||||
{
|
||||
int pos;
|
||||
int channel;
|
||||
int row;
|
||||
IT_ENTRY *entry;
|
||||
|
||||
pattern->n_rows = 64;
|
||||
|
||||
if ( dumbfile_getnc( (char *) buffer, 64 * 8 * 4, f ) != 64 * 8 * 4 )
|
||||
return -1;
|
||||
|
||||
/* compute number of entries */
|
||||
pattern->n_entries = 64; /* Account for the row end markers */
|
||||
pos = 0;
|
||||
for ( row = 0; row < 64; ++row ) {
|
||||
for ( channel = 0; channel < 8; ++channel ) {
|
||||
if ( buffer[ pos + 0 ] | buffer[ pos + 1 ] | buffer[ pos + 2 ] | buffer[ pos + 3 ] )
|
||||
++pattern->n_entries;
|
||||
pos += 4;
|
||||
}
|
||||
}
|
||||
|
||||
pattern->entry = malloc( pattern->n_entries * sizeof( *pattern->entry ) );
|
||||
if ( !pattern->entry )
|
||||
return -1;
|
||||
|
||||
entry = pattern->entry;
|
||||
pos = 0;
|
||||
for ( row = 0; row < 64; ++row ) {
|
||||
for ( channel = 0; channel < 8; ++channel ) {
|
||||
if ( buffer[ pos + 0 ] | buffer[ pos + 1 ] | buffer[ pos + 2 ] | buffer[ pos + 3 ] ) {
|
||||
entry->channel = channel;
|
||||
entry->mask = 0;
|
||||
|
||||
if ( buffer[ pos + 0 ] && buffer[ pos + 0 ] < 96 ) {
|
||||
entry->note = buffer[ pos + 0 ];
|
||||
entry->mask |= IT_ENTRY_NOTE;
|
||||
}
|
||||
|
||||
if ( buffer[ pos + 1 ] && buffer[ pos + 1 ] <= 64 ) {
|
||||
entry->instrument = buffer[ pos + 1 ];
|
||||
entry->mask |= IT_ENTRY_INSTRUMENT;
|
||||
}
|
||||
|
||||
_dumb_it_xm_convert_effect( buffer[ pos + 2 ], buffer[ pos + 3 ], entry, 1 );
|
||||
|
||||
if ( entry->mask ) ++entry;
|
||||
}
|
||||
pos += 4;
|
||||
}
|
||||
IT_SET_END_ROW( entry );
|
||||
++entry;
|
||||
}
|
||||
|
||||
pattern->n_entries = entry - pattern->entry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int it_asy_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f )
|
||||
{
|
||||
int finetune, key_offset;
|
||||
|
||||
/**
|
||||
21 22 Chars Sample 1 name. If the name is not a full
|
||||
22 chars in length, it will be null
|
||||
terminated.
|
||||
|
||||
If
|
||||
the sample name begins with a '#' character (ASCII $23 (35)) then this is
|
||||
assumed not to be an instrument name, and is probably a message.
|
||||
*/
|
||||
dumbfile_getnc( (char *) sample->name, 22, f );
|
||||
sample->name[22] = 0;
|
||||
|
||||
sample->filename[0] = 0;
|
||||
|
||||
/** Each finetune step changes the note 1/8th of a semitone. */
|
||||
finetune = ( signed char ) ( dumbfile_getc( f ) << 4 ) >> 4; /* signed nibble */
|
||||
sample->default_volume = dumbfile_getc( f ); // Should we be setting global_volume to this instead?
|
||||
sample->global_volume = 64;
|
||||
if ( sample->default_volume > 64 ) sample->default_volume = 64;
|
||||
key_offset = ( signed char ) dumbfile_getc( f ); /* base key offset */
|
||||
sample->length = dumbfile_igetl( f );
|
||||
sample->loop_start = dumbfile_igetl( f );
|
||||
sample->loop_end = sample->loop_start + dumbfile_igetl( f );
|
||||
|
||||
if ( sample->length <= 0 ) {
|
||||
sample->flags = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sample->flags = IT_SAMPLE_EXISTS;
|
||||
|
||||
sample->default_pan = 0;
|
||||
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 * pow( DUMB_SEMITONE_BASE, key_offset ) );//( long )( 16726.0 * pow( DUMB_PITCH_BASE, finetune * 32 ) );
|
||||
sample->finetune = finetune * 32;
|
||||
// the above line might be wrong
|
||||
|
||||
if ( ( sample->loop_end - sample->loop_start > 2 ) && ( sample->loop_end <= sample->length ) )
|
||||
sample->flags |= IT_SAMPLE_LOOP;
|
||||
|
||||
sample->vibrato_speed = 0;
|
||||
sample->vibrato_depth = 0;
|
||||
sample->vibrato_rate = 0;
|
||||
sample->vibrato_waveform = 0; // do we have to set _all_ these?
|
||||
sample->max_resampling_quality = -1;
|
||||
|
||||
return dumbfile_error(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int it_asy_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
|
||||
{
|
||||
long truncated_size;
|
||||
|
||||
/* let's get rid of the sample data coming after the end of the loop */
|
||||
if ( ( sample->flags & IT_SAMPLE_LOOP ) && sample->loop_end < sample->length ) {
|
||||
truncated_size = sample->length - sample->loop_end;
|
||||
sample->length = sample->loop_end;
|
||||
} else {
|
||||
truncated_size = 0;
|
||||
}
|
||||
|
||||
sample->data = malloc( sample->length );
|
||||
|
||||
if ( !sample->data )
|
||||
return -1;
|
||||
|
||||
if ( sample->length )
|
||||
dumbfile_getnc( sample->data, sample->length, f );
|
||||
|
||||
dumbfile_skip( f, truncated_size );
|
||||
|
||||
return dumbfile_error( f );
|
||||
}
|
||||
|
||||
|
||||
|
||||
static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f)
|
||||
{
|
||||
DUMB_IT_SIGDATA *sigdata;
|
||||
int i;
|
||||
|
||||
static const char sig_part[] = "ASYLUM Music Format";
|
||||
static const char sig_rest[] = " V1.0"; /* whee, string space optimization with format type below */
|
||||
|
||||
char signature [32];
|
||||
|
||||
if ( dumbfile_getnc( signature, 32, f ) != 32 ||
|
||||
memcmp( signature, sig_part, 19 ) ||
|
||||
memcmp( signature + 19, sig_rest, 5 ) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata = malloc(sizeof(*sigdata));
|
||||
if (!sigdata) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->speed = dumbfile_getc( f ); /* XXX seems to fit the files I have */
|
||||
sigdata->tempo = dumbfile_getc( f ); /* ditto */
|
||||
sigdata->n_samples = dumbfile_getc( f ); /* ditto */
|
||||
sigdata->n_patterns = dumbfile_getc( f );
|
||||
sigdata->n_orders = dumbfile_getc( f );
|
||||
sigdata->restart_position = dumbfile_getc( f );
|
||||
|
||||
if ( dumbfile_error( f ) || !sigdata->n_samples || sigdata->n_samples > 64 || !sigdata->n_patterns ||
|
||||
!sigdata->n_orders ) {
|
||||
free( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( sigdata->restart_position > sigdata->n_orders ) /* XXX */
|
||||
sigdata->restart_position = 0;
|
||||
|
||||
sigdata->order = malloc( sigdata->n_orders );
|
||||
if ( !sigdata->order ) {
|
||||
free( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( dumbfile_getnc( (char *) sigdata->order, sigdata->n_orders, f ) != sigdata->n_orders ||
|
||||
dumbfile_skip( f, 256 - sigdata->n_orders ) ) {
|
||||
free( sigdata->order );
|
||||
free( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
|
||||
if ( !sigdata->sample ) {
|
||||
free( sigdata->order );
|
||||
free( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->song_message = NULL;
|
||||
sigdata->instrument = NULL;
|
||||
sigdata->pattern = NULL;
|
||||
sigdata->midi = NULL;
|
||||
sigdata->checkpoint = NULL;
|
||||
|
||||
sigdata->n_instruments = 0;
|
||||
|
||||
for ( i = 0; i < sigdata->n_samples; ++i )
|
||||
sigdata->sample[i].data = NULL;
|
||||
|
||||
for ( i = 0; i < sigdata->n_samples; ++i ) {
|
||||
if ( it_asy_read_sample_header( &sigdata->sample[i], f ) ) {
|
||||
_dumb_it_unload_sigdata( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( dumbfile_skip( f, 37 * ( 64 - sigdata->n_samples ) ) ) {
|
||||
_dumb_it_unload_sigdata( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
|
||||
if ( !sigdata->pattern ) {
|
||||
_dumb_it_unload_sigdata( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < sigdata->n_patterns; ++i)
|
||||
sigdata->pattern[i].entry = NULL;
|
||||
|
||||
/* Read in the patterns */
|
||||
{
|
||||
unsigned char *buffer = malloc( 64 * 8 * 4 ); /* 64 rows * 8 channels * 4 bytes */
|
||||
if ( !buffer ) {
|
||||
_dumb_it_unload_sigdata( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
for ( i = 0; i < sigdata->n_patterns; ++i ) {
|
||||
if ( it_asy_read_pattern( &sigdata->pattern[i], f, buffer ) != 0 ) {
|
||||
free( buffer );
|
||||
_dumb_it_unload_sigdata( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
free( buffer );
|
||||
}
|
||||
|
||||
/* And finally, the sample data */
|
||||
for ( i = 0; i < sigdata->n_samples; ++i ) {
|
||||
if ( it_asy_read_sample_data( &sigdata->sample[i], f ) ) {
|
||||
_dumb_it_unload_sigdata( sigdata );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now let's initialise the remaining variables, and we're done! */
|
||||
sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
|
||||
|
||||
sigdata->global_volume = 128;
|
||||
sigdata->mixing_volume = 48;
|
||||
sigdata->pan_separation = 128;
|
||||
|
||||
sigdata->n_pchannels = 8;
|
||||
|
||||
sigdata->name[0] = 0;
|
||||
|
||||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) {
|
||||
sigdata->channel_pan[i+0] = 16;
|
||||
sigdata->channel_pan[i+1] = 48;
|
||||
sigdata->channel_pan[i+2] = 48;
|
||||
sigdata->channel_pan[i+3] = 16;
|
||||
}
|
||||
|
||||
_dumb_it_fix_invalid_orders(sigdata);
|
||||
|
||||
return sigdata;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_asy_quick(DUMBFILE *f)
|
||||
{
|
||||
sigdata_t *sigdata;
|
||||
|
||||
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||
|
||||
sigdata = it_asy_load_sigdata(f);
|
||||
|
||||
if (!sigdata)
|
||||
return NULL;
|
||||
|
||||
{
|
||||
const char *tag[2][2];
|
||||
tag[0][0] = "TITLE";
|
||||
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
|
||||
tag[1][0] = "FORMAT";
|
||||
tag[1][1] = "ASYLUM Music Format";
|
||||
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
|
||||
}
|
||||
}
|
382
Frameworks/Dumb/dumb/src/it/readdsmf.c
Normal file
382
Frameworks/Dumb/dumb/src/it/readdsmf.c
Normal file
|
@ -0,0 +1,382 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readam.c - Code to read a RIFF DSMF module / / \ \
|
||||
* from a parsed RIFF structure. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Chris Moeller. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
#include "internal/riff.h"
|
||||
|
||||
static int it_riff_dsmf_process_sample( IT_SAMPLE * sample, DUMBFILE * f, int len )
|
||||
{
|
||||
int flags;
|
||||
|
||||
dumbfile_getnc( (char *) sample->filename, 13, f );
|
||||
sample->filename[ 14 ] = 0;
|
||||
|
||||
flags = dumbfile_igetw( f );
|
||||
sample->default_volume = dumbfile_getc( f );
|
||||
sample->length = dumbfile_igetl( f );
|
||||
sample->loop_start = dumbfile_igetl( f );
|
||||
sample->loop_end = dumbfile_igetl( f );
|
||||
dumbfile_skip( f, 32 - 28 );
|
||||
sample->C5_speed = dumbfile_igetw( f ) * 2;
|
||||
dumbfile_skip( f, 36 - 34 );
|
||||
dumbfile_getnc( (char *) sample->name, 28, f );
|
||||
sample->name[ 28 ] = 0;
|
||||
|
||||
/*if ( data[ 0x38 ] || data[ 0x39 ] || data[ 0x3A ] || data[ 0x3B ] )
|
||||
return -1;*/
|
||||
|
||||
if ( ! sample->length ) {
|
||||
sample->flags &= ~IT_SAMPLE_EXISTS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*if ( flags & ~( 2 | 1 ) )
|
||||
return -1;*/
|
||||
|
||||
if ( sample->length + 64 > len )
|
||||
return -1;
|
||||
|
||||
sample->flags = IT_SAMPLE_EXISTS;
|
||||
|
||||
sample->default_pan = 0;
|
||||
sample->global_volume = 64;
|
||||
sample->vibrato_speed = 0;
|
||||
sample->vibrato_depth = 0;
|
||||
sample->vibrato_rate = 0;
|
||||
sample->vibrato_waveform = IT_VIBRATO_SINE;
|
||||
sample->finetune = 0;
|
||||
sample->max_resampling_quality = -1;
|
||||
|
||||
if ( flags & 1 )
|
||||
{
|
||||
if (((unsigned int)sample->loop_end <= (unsigned int)sample->length) &&
|
||||
((unsigned int)sample->loop_start < (unsigned int)sample->loop_end))
|
||||
{
|
||||
sample->length = sample->loop_end;
|
||||
sample->flags |= IT_SAMPLE_LOOP;
|
||||
if ( flags & 0x10 ) sample->flags |= IT_SAMPLE_PINGPONG_LOOP;
|
||||
}
|
||||
}
|
||||
|
||||
sample->data = malloc( sample->length );
|
||||
if ( ! sample->data )
|
||||
return -1;
|
||||
|
||||
dumbfile_getnc( sample->data, sample->length, f );
|
||||
|
||||
if ( ! ( flags & 2 ) )
|
||||
{
|
||||
for ( flags = 0; flags < sample->length; ++flags )
|
||||
( ( signed char * ) sample->data ) [ flags ] ^= 0x80;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int it_riff_dsmf_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int len )
|
||||
{
|
||||
int length, row;
|
||||
unsigned flags;
|
||||
long start, end;
|
||||
int p, q, r;
|
||||
IT_ENTRY * entry;
|
||||
|
||||
length = dumbfile_igetw( f );
|
||||
if ( length > len ) return -1;
|
||||
|
||||
len = length - 2;
|
||||
|
||||
pattern->n_rows = 64;
|
||||
pattern->n_entries = 64;
|
||||
|
||||
row = 0;
|
||||
|
||||
start = dumbfile_pos( f );
|
||||
end = start + len;
|
||||
|
||||
while ( (row < 64) && !dumbfile_error( f ) && (dumbfile_pos( f ) < end) ) {
|
||||
p = dumbfile_getc( f );
|
||||
if ( ! p ) {
|
||||
++ row;
|
||||
continue;
|
||||
}
|
||||
|
||||
flags = p & 0xF0;
|
||||
|
||||
if (flags) {
|
||||
++ pattern->n_entries;
|
||||
if (flags & 0x80) dumbfile_skip( f, 1 );
|
||||
if (flags & 0x40) dumbfile_skip( f, 1 );
|
||||
if (flags & 0x20) dumbfile_skip( f, 1 );
|
||||
if (flags & 0x10) dumbfile_skip( f, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( pattern->n_entries == 64 ) return 0;
|
||||
|
||||
pattern->entry = malloc( pattern->n_entries * sizeof( * pattern->entry ) );
|
||||
if ( ! pattern->entry ) return -1;
|
||||
|
||||
entry = pattern->entry;
|
||||
|
||||
row = 0;
|
||||
|
||||
if ( dumbfile_seek( f, start, DFS_SEEK_SET ) ) return -1;
|
||||
|
||||
while ( ( row < 64 ) && !dumbfile_error( f ) && ( dumbfile_pos( f ) < end ) )
|
||||
{
|
||||
p = dumbfile_getc( f );
|
||||
if ( ! p )
|
||||
{
|
||||
IT_SET_END_ROW( entry );
|
||||
++ entry;
|
||||
++ row;
|
||||
continue;
|
||||
}
|
||||
|
||||
flags = p;
|
||||
entry->channel = flags & 0x0F;
|
||||
entry->mask = 0;
|
||||
|
||||
if ( flags & 0xF0 )
|
||||
{
|
||||
if ( flags & 0x80 )
|
||||
{
|
||||
q = dumbfile_getc( f );
|
||||
if ( q )
|
||||
{
|
||||
entry->mask |= IT_ENTRY_NOTE;
|
||||
entry->note = q - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( flags & 0x40 )
|
||||
{
|
||||
q = dumbfile_getc( f );
|
||||
if ( q )
|
||||
{
|
||||
entry->mask |= IT_ENTRY_INSTRUMENT;
|
||||
entry->instrument = q;
|
||||
}
|
||||
}
|
||||
|
||||
if ( flags & 0x20 )
|
||||
{
|
||||
entry->mask |= IT_ENTRY_VOLPAN;
|
||||
entry->volpan = dumbfile_getc( f );
|
||||
}
|
||||
|
||||
if ( flags & 0x10 )
|
||||
{
|
||||
q = dumbfile_getc( f );
|
||||
r = dumbfile_getc( f );
|
||||
_dumb_it_xm_convert_effect( q, r, entry, 0 );
|
||||
}
|
||||
|
||||
if (entry->mask) entry++;
|
||||
}
|
||||
}
|
||||
|
||||
while ( row < 64 )
|
||||
{
|
||||
IT_SET_END_ROW( entry );
|
||||
++ entry;
|
||||
++ row;
|
||||
}
|
||||
|
||||
pattern->n_entries = entry - pattern->entry;
|
||||
if ( ! pattern->n_entries ) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( DUMBFILE * f, struct riff * stream )
|
||||
{
|
||||
DUMB_IT_SIGDATA *sigdata;
|
||||
|
||||
int n, o, found;
|
||||
|
||||
if ( ! stream ) goto error;
|
||||
|
||||
if ( stream->type != DUMB_ID( 'D', 'S', 'M', 'F' ) ) goto error;
|
||||
|
||||
sigdata = malloc(sizeof(*sigdata));
|
||||
if ( ! sigdata ) goto error;
|
||||
|
||||
sigdata->n_patterns = 0;
|
||||
sigdata->n_samples = 0;
|
||||
sigdata->name[0] = 0;
|
||||
|
||||
found = 0;
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
{
|
||||
struct riff_chunk * c = stream->chunks + n;
|
||||
switch( c->type )
|
||||
{
|
||||
case DUMB_ID( 'S' ,'O' ,'N' ,'G' ):
|
||||
/* initialization data */
|
||||
if ( ( found ) || ( c->size < 192 ) ) goto error_sd;
|
||||
found = 1;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'P', 'A', 'T', 'T' ):
|
||||
++ sigdata->n_patterns;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'I', 'N', 'S', 'T' ):
|
||||
++ sigdata->n_samples;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !found || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd;
|
||||
|
||||
if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd;
|
||||
|
||||
sigdata->song_message = NULL;
|
||||
sigdata->order = NULL;
|
||||
sigdata->instrument = NULL;
|
||||
sigdata->sample = NULL;
|
||||
sigdata->pattern = NULL;
|
||||
sigdata->midi = NULL;
|
||||
sigdata->checkpoint = NULL;
|
||||
|
||||
sigdata->mixing_volume = 48;
|
||||
sigdata->pan_separation = 128;
|
||||
|
||||
sigdata->n_instruments = 0;
|
||||
sigdata->n_orders = 0;
|
||||
sigdata->restart_position = 0;
|
||||
|
||||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
|
||||
sigdata->channel_pan[n ] = 16;
|
||||
sigdata->channel_pan[n+1] = 48;
|
||||
sigdata->channel_pan[n+2] = 48;
|
||||
sigdata->channel_pan[n+3] = 16;
|
||||
}
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
{
|
||||
struct riff_chunk * c = stream->chunks + n;
|
||||
switch ( c->type )
|
||||
{
|
||||
case DUMB_ID( 'S', 'O', 'N', 'G' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
|
||||
dumbfile_getnc( (char *) sigdata->name, 28, f );
|
||||
sigdata->name[ 28 ] = 0;
|
||||
sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
|
||||
dumbfile_skip( f, 36 - 28 );
|
||||
sigdata->n_orders = dumbfile_igetw( f );
|
||||
//sigdata->n_samples = ptr[ 38 ] | ( ptr[ 39 ] << 8 ); // whatever
|
||||
//sigdata->n_patterns = ptr[ 40 ] | ( ptr[ 41 ] << 8 );
|
||||
dumbfile_skip( f, 42 - 38 );
|
||||
sigdata->n_pchannels = dumbfile_igetw( f );
|
||||
sigdata->global_volume = dumbfile_getc( f );
|
||||
sigdata->mixing_volume = dumbfile_getc( f );
|
||||
sigdata->speed = dumbfile_getc( f );
|
||||
sigdata->tempo = dumbfile_getc( f );
|
||||
|
||||
for ( o = 0; o < 16; ++o )
|
||||
{
|
||||
sigdata->channel_pan[ o ] = dumbfile_getc( f ) / 2;
|
||||
}
|
||||
|
||||
sigdata->order = malloc( 128 );
|
||||
if ( ! sigdata->order ) goto error_usd;
|
||||
dumbfile_getnc( (char *) sigdata->order, 128, f );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
|
||||
if ( ! sigdata->pattern ) goto error_usd;
|
||||
for ( n = 0; n < sigdata->n_patterns; ++n )
|
||||
sigdata->pattern[ n ].entry = NULL;
|
||||
|
||||
sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
|
||||
if ( ! sigdata->sample ) goto error_usd;
|
||||
for ( n = 0; n < sigdata->n_samples; ++n )
|
||||
{
|
||||
IT_SAMPLE * sample = sigdata->sample + n;
|
||||
sample->data = NULL;
|
||||
}
|
||||
|
||||
sigdata->n_samples = 0;
|
||||
sigdata->n_patterns = 0;
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
{
|
||||
struct riff_chunk * c = stream->chunks + n;
|
||||
switch ( c->type )
|
||||
{
|
||||
case DUMB_ID( 'P', 'A', 'T', 'T' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
|
||||
if ( it_riff_dsmf_process_pattern( sigdata->pattern + sigdata->n_patterns, f, c->size ) ) goto error_usd;
|
||||
++ sigdata->n_patterns;
|
||||
break;
|
||||
|
||||
case DUMB_ID( 'I', 'N', 'S', 'T' ):
|
||||
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
|
||||
if ( it_riff_dsmf_process_sample( sigdata->sample + sigdata->n_samples, f, c->size ) ) goto error_usd;
|
||||
++ sigdata->n_samples;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_dumb_it_fix_invalid_orders( sigdata );
|
||||
|
||||
return sigdata;
|
||||
|
||||
error_usd:
|
||||
_dumb_it_unload_sigdata( sigdata );
|
||||
goto error;
|
||||
error_sd:
|
||||
free( sigdata );
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DUH *dumb_read_riff_dsmf( DUMBFILE * f, struct riff * stream )
|
||||
{
|
||||
sigdata_t *sigdata;
|
||||
|
||||
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||
|
||||
sigdata = it_riff_dsmf_load_sigdata( f, stream );
|
||||
|
||||
if (!sigdata)
|
||||
return NULL;
|
||||
|
||||
{
|
||||
const char *tag[2][2];
|
||||
tag[0][0] = "TITLE";
|
||||
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
|
||||
tag[1][0] = "FORMAT";
|
||||
tag[1][1] = "RIFF DSMF";
|
||||
return make_duh( -1, 2, ( const char * const (*) [ 2 ] ) tag, 1, & descptr, & sigdata );
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,29 +1,29 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readmod2.c - Function to read a good old- / / \ \
|
||||
* fashioned Amiga module from an | < / \_
|
||||
* open file and do an initial | \/ /\ /
|
||||
* run-through. \_ / > /
|
||||
* | \ / /
|
||||
* Split off from readmod.c by entheh. | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_mod(DUMBFILE *f)
|
||||
{
|
||||
DUH *duh = dumb_read_mod_quick(f);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readmod2.c - Function to read a good old- / / \ \
|
||||
* fashioned Amiga module from an | < / \_
|
||||
* open file and do an initial | \/ /\ /
|
||||
* run-through. \_ / > /
|
||||
* | \ / /
|
||||
* Split off from readmod.c by entheh. | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include "dumb.h"
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_mod(DUMBFILE *f, int restrict_)
|
||||
{
|
||||
DUH *duh = dumb_read_mod_quick(f, restrict_);
|
||||
dumb_it_do_initial_runthrough(duh);
|
||||
return duh;
|
||||
}
|
||||
|
|
412
Frameworks/Dumb/dumb/src/it/readmtm.c
Normal file
412
Frameworks/Dumb/dumb/src/it/readmtm.c
Normal file
|
@ -0,0 +1,412 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readmtm.c - Code to read a MultiTracker Module / / \ \
|
||||
* from an open file. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Chris Moeller. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
size_t strlen_max(const char * ptr, size_t max)
|
||||
{
|
||||
const char * end, * start;
|
||||
if (ptr==0) return 0;
|
||||
start = ptr;
|
||||
end = ptr + max;
|
||||
while(*ptr && ptr < end) ptr++;
|
||||
return ptr - start;
|
||||
}
|
||||
|
||||
static int it_mtm_assemble_pattern(IT_PATTERN *pattern, const unsigned char * track, const unsigned short * sequence, int n_rows)
|
||||
{
|
||||
int n, o, note, sample;
|
||||
const unsigned char * t;
|
||||
IT_ENTRY * entry;
|
||||
|
||||
pattern->n_rows = n_rows;
|
||||
pattern->n_entries = n_rows;
|
||||
|
||||
for (n = 0; n < 32; n++) {
|
||||
if (sequence[n]) {
|
||||
t = &track[192 * (sequence[n] - 1)];
|
||||
for (o = 0; o < n_rows; o++) {
|
||||
if (t[0] || t[1] || t[2]) pattern->n_entries++;
|
||||
t += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entry = malloc(pattern->n_entries * sizeof(*entry));
|
||||
if (!entry) return -1;
|
||||
pattern->entry = entry;
|
||||
|
||||
for (n = 0; n < n_rows; n++) {
|
||||
for (o = 0; o < 32; o++) {
|
||||
if (sequence[o]) {
|
||||
t = &track[192 * (sequence[o] - 1) + (n * 3)];
|
||||
if (t[0] || t[1] || t[2]) {
|
||||
entry->channel = o;
|
||||
entry->mask = 0;
|
||||
note = t[0] >> 2;
|
||||
sample = ((t[0] << 4) | (t[1] >> 4)) & 0x3F;
|
||||
|
||||
if (note) {
|
||||
entry->mask |= IT_ENTRY_NOTE;
|
||||
entry->note = note + 24;
|
||||
}
|
||||
|
||||
if (sample) {
|
||||
entry->mask |= IT_ENTRY_INSTRUMENT;
|
||||
entry->instrument = sample;
|
||||
}
|
||||
|
||||
_dumb_it_xm_convert_effect(t[1] & 0xF, t[2], entry, 1);
|
||||
|
||||
if (entry->mask) entry++;
|
||||
}
|
||||
}
|
||||
}
|
||||
IT_SET_END_ROW(entry);
|
||||
entry++;
|
||||
}
|
||||
|
||||
pattern->n_entries = entry - pattern->entry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
|
||||
{
|
||||
int finetune, flags;
|
||||
|
||||
dumbfile_getnc((char *)sample->name, 22, f);
|
||||
sample->name[22] = 0;
|
||||
|
||||
sample->filename[0] = 0;
|
||||
|
||||
sample->length = dumbfile_igetl(f);
|
||||
sample->loop_start = dumbfile_igetl(f);
|
||||
sample->loop_end = dumbfile_igetl(f);
|
||||
finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */
|
||||
sample->global_volume = 64;
|
||||
sample->default_volume = dumbfile_getc(f);
|
||||
|
||||
flags = dumbfile_getc(f);
|
||||
|
||||
if (sample->length <= 0) {
|
||||
sample->flags = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sample->flags = IT_SAMPLE_EXISTS;
|
||||
|
||||
if (flags & 1) {
|
||||
sample->flags |= IT_SAMPLE_16BIT;
|
||||
sample->length >>= 1;
|
||||
sample->loop_start >>= 1;
|
||||
sample->loop_end >>= 1;
|
||||
}
|
||||
|
||||
sample->default_pan = 0;
|
||||
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 );//(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
|
||||
sample->finetune = finetune * 32;
|
||||
// the above line might be wrong
|
||||
|
||||
if (sample->loop_end > sample->length)
|
||||
sample->loop_end = sample->length;
|
||||
|
||||
if (sample->loop_end - sample->loop_start > 2)
|
||||
sample->flags |= IT_SAMPLE_LOOP;
|
||||
|
||||
sample->vibrato_speed = 0;
|
||||
sample->vibrato_depth = 0;
|
||||
sample->vibrato_rate = 0;
|
||||
sample->vibrato_waveform = 0; // do we have to set _all_ these?
|
||||
sample->max_resampling_quality = -1;
|
||||
|
||||
return dumbfile_error(f);
|
||||
}
|
||||
|
||||
static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
|
||||
{
|
||||
long i;
|
||||
long truncated_size;
|
||||
|
||||
/* let's get rid of the sample data coming after the end of the loop */
|
||||
if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) {
|
||||
truncated_size = sample->length - sample->loop_end;
|
||||
sample->length = sample->loop_end;
|
||||
} else {
|
||||
truncated_size = 0;
|
||||
}
|
||||
|
||||
sample->data = malloc(sample->length);
|
||||
|
||||
if (!sample->data)
|
||||
return -1;
|
||||
|
||||
dumbfile_getnc((char *)sample->data, sample->length, f);
|
||||
dumbfile_skip(f, truncated_size);
|
||||
|
||||
if (dumbfile_error(f))
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < sample->length; i++)
|
||||
((signed char *)sample->data)[i] ^= 0x80;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
|
||||
{
|
||||
DUMB_IT_SIGDATA *sigdata;
|
||||
|
||||
int n, o, n_tracks, l_comment, n_rows, n_channels;
|
||||
|
||||
unsigned char * track;
|
||||
|
||||
unsigned short * sequence;
|
||||
|
||||
char * comment;
|
||||
|
||||
if (dumbfile_getc(f) != 'M' ||
|
||||
dumbfile_getc(f) != 'T' ||
|
||||
dumbfile_getc(f) != 'M') goto error;
|
||||
|
||||
*version = dumbfile_getc(f);
|
||||
|
||||
sigdata = malloc(sizeof(*sigdata));
|
||||
if (!sigdata) goto error;
|
||||
|
||||
dumbfile_getnc((char *)sigdata->name, 20, f);
|
||||
sigdata->name[20] = 0;
|
||||
|
||||
n_tracks = dumbfile_igetw(f);
|
||||
sigdata->n_patterns = dumbfile_getc(f) + 1;
|
||||
sigdata->n_orders = dumbfile_getc(f) + 1;
|
||||
l_comment = dumbfile_igetw(f);
|
||||
sigdata->n_samples = dumbfile_getc(f);
|
||||
//if (dumbfile_getc(f)) goto error_sd;
|
||||
dumbfile_getc(f);
|
||||
n_rows = dumbfile_getc(f);
|
||||
n_channels = dumbfile_getc(f);
|
||||
|
||||
if (dumbfile_error(f) ||
|
||||
(n_tracks <= 0) ||
|
||||
(sigdata->n_samples <= 0) ||
|
||||
(n_rows <= 0 || n_rows > 64) ||
|
||||
(n_channels <= 0 || n_channels > 32)) goto error_sd;
|
||||
|
||||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
if (dumbfile_getnc((char *)sigdata->channel_pan, 32, f) < 32) goto error_sd;
|
||||
|
||||
for (n = 0; n < 32; n++) {
|
||||
if (sigdata->channel_pan[n] <= 15) {
|
||||
sigdata->channel_pan[n] -= (sigdata->channel_pan[n] & 8) >> 3;
|
||||
sigdata->channel_pan[n] = (sigdata->channel_pan[n] * 32) / 7;
|
||||
} else {
|
||||
sigdata->channel_volume[n] = 0;
|
||||
sigdata->channel_pan[n] = 7;
|
||||
}
|
||||
}
|
||||
|
||||
for (n = 32; n < DUMB_IT_N_CHANNELS; n += 4) {
|
||||
sigdata->channel_pan[n ] = 16;
|
||||
sigdata->channel_pan[n+1] = 48;
|
||||
sigdata->channel_pan[n+2] = 48;
|
||||
sigdata->channel_pan[n+3] = 16;
|
||||
}
|
||||
|
||||
sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
|
||||
if (!sigdata->sample) goto error_sd;
|
||||
|
||||
sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
|
||||
|
||||
sigdata->global_volume = 128;
|
||||
sigdata->mixing_volume = 48;
|
||||
sigdata->speed = 6;
|
||||
sigdata->tempo = 125;
|
||||
sigdata->pan_separation = 128;
|
||||
|
||||
sigdata->song_message = NULL;
|
||||
sigdata->order = NULL;
|
||||
sigdata->instrument = NULL;
|
||||
sigdata->pattern = NULL;
|
||||
sigdata->midi = NULL;
|
||||
sigdata->checkpoint = NULL;
|
||||
|
||||
sigdata->n_instruments = 0;
|
||||
|
||||
sigdata->restart_position = 0;
|
||||
sigdata->n_pchannels = n_channels;
|
||||
|
||||
for (n = 0; n < sigdata->n_samples; n++)
|
||||
sigdata->sample[n].data = NULL;
|
||||
|
||||
for (n = 0; n < sigdata->n_samples; n++) {
|
||||
if (it_mtm_read_sample_header(&sigdata->sample[n], f)) goto error_usd;
|
||||
}
|
||||
|
||||
sigdata->order = malloc(sigdata->n_orders);
|
||||
if (!sigdata->order) goto error_usd;
|
||||
|
||||
if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders) goto error_usd;
|
||||
if (sigdata->n_orders < 128)
|
||||
if (dumbfile_skip(f, 128 - sigdata->n_orders)) goto error_usd;
|
||||
|
||||
track = malloc(192 * n_tracks);
|
||||
if (!track) goto error_usd;
|
||||
|
||||
if (dumbfile_getnc((char *)track, 192 * n_tracks, f) < 192 * n_tracks) goto error_ft;
|
||||
|
||||
sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
|
||||
if (!sigdata->pattern) goto error_ft;
|
||||
for (n = 0; n < sigdata->n_patterns; n++)
|
||||
sigdata->pattern[n].entry = NULL;
|
||||
|
||||
sequence = malloc(sigdata->n_patterns * 32 * sizeof(*sequence));
|
||||
if (!sequence) goto error_ft;
|
||||
|
||||
for (n = 0; n < sigdata->n_patterns; n++) {
|
||||
for (o = 0; o < 32; o++) {
|
||||
sequence[(n * 32) + o] = dumbfile_igetw(f);
|
||||
if (sequence[(n * 32) + o] > n_tracks)
|
||||
{
|
||||
//goto error_fs;
|
||||
// illegal track number, silence instead of rejecting the file
|
||||
sequence[(n * 32) + o] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (n = 0; n < sigdata->n_patterns; n++) {
|
||||
if (it_mtm_assemble_pattern(&sigdata->pattern[n], track, &sequence[n * 32], n_rows)) goto error_fs;
|
||||
}
|
||||
|
||||
if (l_comment) {
|
||||
comment = malloc(l_comment);
|
||||
if (!comment) goto error_fs;
|
||||
if (dumbfile_getnc(comment, l_comment, f) < l_comment) goto error_fc;
|
||||
|
||||
/* Time for annoying "logic", yes. We want each line which has text,
|
||||
* and each blank line in between all the valid lines.
|
||||
*/
|
||||
|
||||
/* Find last actual line. */
|
||||
for (o = -1, n = 0; n < l_comment; n += 40) {
|
||||
if (comment[n]) o = n;
|
||||
}
|
||||
|
||||
if (o >= 0) {
|
||||
|
||||
int l, m;
|
||||
|
||||
for (l = 0, n = 0; n <= o; n += 40) {
|
||||
l += strlen_max(&comment[n], 40) + 2;
|
||||
}
|
||||
|
||||
l -= 1;
|
||||
|
||||
sigdata->song_message = malloc(l);
|
||||
if (!sigdata->song_message) goto error_fc;
|
||||
|
||||
for (m = 0, n = 0; n <= o; n += 40) {
|
||||
int p = strlen_max(&comment[n], 40);
|
||||
if (p) {
|
||||
memcpy(sigdata->song_message + m, &comment[n], p);
|
||||
m += p;
|
||||
}
|
||||
if (l - m > 1) {
|
||||
sigdata->song_message[m++] = 13;
|
||||
sigdata->song_message[m++] = 10;
|
||||
}
|
||||
}
|
||||
|
||||
sigdata->song_message[m] = 0;
|
||||
}
|
||||
|
||||
free(comment);
|
||||
}
|
||||
|
||||
for (n = 0; n < sigdata->n_samples; n++) {
|
||||
if (it_mtm_read_sample_data(&sigdata->sample[n], f)) goto error_fs;
|
||||
}
|
||||
|
||||
_dumb_it_fix_invalid_orders(sigdata);
|
||||
|
||||
free(sequence);
|
||||
free(track);
|
||||
|
||||
return sigdata;
|
||||
|
||||
error_fc:
|
||||
free(comment);
|
||||
error_fs:
|
||||
free(sequence);
|
||||
error_ft:
|
||||
free(track);
|
||||
error_usd:
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
|
||||
error_sd:
|
||||
free(sigdata);
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char hexdigit(int in)
|
||||
{
|
||||
if (in < 10) return in + '0';
|
||||
else return in + 'A' - 10;
|
||||
}
|
||||
|
||||
DUH *dumb_read_mtm_quick(DUMBFILE *f)
|
||||
{
|
||||
sigdata_t *sigdata;
|
||||
int ver;
|
||||
|
||||
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||
|
||||
sigdata = it_mtm_load_sigdata(f, &ver);
|
||||
|
||||
if (!sigdata)
|
||||
return NULL;
|
||||
|
||||
{
|
||||
char version[16];
|
||||
const char *tag[2][2];
|
||||
tag[0][0] = "TITLE";
|
||||
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
|
||||
tag[1][0] = "FORMAT";
|
||||
version[0] = 'M';
|
||||
version[1] = 'T';
|
||||
version[2] = 'M';
|
||||
version[3] = ' ';
|
||||
version[4] = 'v';
|
||||
version[5] = hexdigit(ver >> 4);
|
||||
version[6] = '.';
|
||||
version[7] = hexdigit(ver & 15);
|
||||
version[8] = 0;
|
||||
tag[1][1] = (const char *) &version;
|
||||
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
|
||||
}
|
||||
}
|
558
Frameworks/Dumb/dumb/src/it/readokt.c
Normal file
558
Frameworks/Dumb/dumb/src/it/readokt.c
Normal file
|
@ -0,0 +1,558 @@
|
|||
/* _______ ____ __ ___ ___
|
||||
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||
* | | \ \ | | || | \/ | . .
|
||||
* | | | | | | || ||\ /| |
|
||||
* | | | | | | || || \/ | | ' ' '
|
||||
* | | | | | | || || | | . .
|
||||
* | |_/ / \ \__// || | |
|
||||
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||
* / \
|
||||
* / . \
|
||||
* readokt.c - Code to read an Oktalyzer module / / \ \
|
||||
* from an open file. | < / \_
|
||||
* | \/ /\ /
|
||||
* By Chris Moeller. \_ / > /
|
||||
* | \ / /
|
||||
* | ' /
|
||||
* \__/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "dumb.h"
|
||||
#include "internal/it.h"
|
||||
|
||||
|
||||
|
||||
static int it_okt_read_pattern(IT_PATTERN *pattern, const unsigned char *data, int length, int n_channels)
|
||||
{
|
||||
int pos;
|
||||
int channel;
|
||||
int row;
|
||||
int n_rows;
|
||||
IT_ENTRY *entry;
|
||||
|
||||
if (length < 2) return -1;
|
||||
|
||||
n_rows = (data[0] << 8) | data[1];
|
||||
if (!n_rows) n_rows = 64;
|
||||
|
||||
if (length < 2 + (n_rows * n_channels * 4)) return -1;
|
||||
|
||||
pattern->n_rows = n_rows;
|
||||
|
||||
/* compute number of entries */
|
||||
pattern->n_entries = n_rows; /* Account for the row end markers */
|
||||
pos = 2;
|
||||
for (row = 0; row < pattern->n_rows; row++) {
|
||||
for (channel = 0; channel < n_channels; channel++) {
|
||||
if (data[pos+0] | data[pos+2])
|
||||
pattern->n_entries++;
|
||||
pos += 4;
|
||||
}
|
||||
}
|
||||
|
||||
pattern->entry = (IT_ENTRY *) malloc(pattern->n_entries * sizeof(*pattern->entry));
|
||||
if (!pattern->entry)
|
||||
return -1;
|
||||
|
||||
entry = pattern->entry;
|
||||
pos = 2;
|
||||
for (row = 0; row < n_rows; row++) {
|
||||
for (channel = 0; channel < n_channels; channel++) {
|
||||
if (data[pos+0] | data[pos+2]) {
|
||||
entry->channel = channel;
|
||||
entry->mask = 0;
|
||||
|
||||
if (data[pos+0] > 0 && data[pos+0] <= 36) {
|
||||
entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT;
|
||||
|
||||
entry->note = data[pos+0] + 35;
|
||||
entry->instrument = data[pos+1] + 1;
|
||||
}
|
||||
|
||||
entry->effect = 0;
|
||||
entry->effectvalue = data[pos+3];
|
||||
|
||||
switch (data[pos+2]) {
|
||||
case 2: if (data[pos+3]) entry->effect = IT_PORTAMENTO_DOWN; break; // XXX code calls this rs_portu, but it's adding to the period, which decreases the pitch
|
||||
case 13: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_DOWN; break;
|
||||
case 21: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_DOWN_ROW; break;
|
||||
|
||||
case 1: if (data[pos+3]) entry->effect = IT_PORTAMENTO_UP; break; // XXX same deal here, increasing the pitch
|
||||
case 17: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_UP; break;
|
||||
case 30: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_UP_ROW; break;
|
||||
|
||||
case 10: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_3; break;
|
||||
case 11: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_4; break;
|
||||
case 12: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_5; break;
|
||||
|
||||
case 15: entry->effect = IT_S; entry->effectvalue = EFFECT_VALUE(IT_S_SET_FILTER, data[pos+3] & 0x0F); break;
|
||||
|
||||
case 25: entry->effect = IT_JUMP_TO_ORDER; break;
|
||||
|
||||
case 27: entry->note = IT_NOTE_OFF; entry->mask |= IT_ENTRY_NOTE; break;
|
||||
|
||||
case 28: entry->effect = IT_SET_SPEED; break;
|
||||
|
||||
case 31:
|
||||
if ( data[pos+3] <= 0x40 ) entry->effect = IT_SET_CHANNEL_VOLUME;
|
||||
else if ( data[pos+3] <= 0x50 ) { entry->effect = IT_OKT_VOLUME_SLIDE_DOWN; entry->effectvalue = data[pos+3] - 0x40; }
|
||||
else if ( data[pos+3] <= 0x60 ) { entry->effect = IT_OKT_VOLUME_SLIDE_UP; entry->effectvalue = data[pos+3] - 0x50; }
|
||||
else if ( data[pos+3] <= 0x70 ) { entry->effect = IT_OKT_VOLUME_SLIDE_DOWN; entry->effectvalue = data[pos+3] - 0x50; }
|
||||
else if ( data[pos+3] <= 0x80 ) { entry->effect = IT_OKT_VOLUME_SLIDE_UP; entry->effectvalue = data[pos+3] - 0x60; }
|
||||
break;
|
||||
}
|
||||
|
||||
if ( entry->effect ) entry->mask |= IT_ENTRY_EFFECT;
|
||||
|
||||
entry++;
|
||||
}
|
||||
pos += 4;
|
||||
}
|
||||
IT_SET_END_ROW(entry);
|
||||
entry++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void it_okt_read_sample_header(IT_SAMPLE *sample, const unsigned char * data)
|
||||
{
|
||||
int loop_start, loop_length;
|
||||
|
||||
memcpy(sample->name, data, 20);
|
||||
sample->name[20] = 0;
|
||||
|
||||
sample->filename[0] = 0;
|
||||
|
||||
sample->length = (data[20] << 24) | (data[21] << 16) | (data[22] << 8) | data[23];
|
||||
sample->global_volume = 64;
|
||||
sample->default_volume = data[29];
|
||||
loop_start = ((data[24] << 8) | data[25]) << 1;
|
||||
loop_length = ((data[26] << 8) | data[27]) << 1;
|
||||
sample->sus_loop_start = loop_start;
|
||||
sample->sus_loop_end = loop_start + loop_length;
|
||||
|
||||
if (sample->length <= 0) {
|
||||
sample->flags = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
sample->flags = IT_SAMPLE_EXISTS;
|
||||
|
||||
sample->default_pan = 0;
|
||||
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 ); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
|
||||
sample->finetune = 0;
|
||||
|
||||
if (sample->sus_loop_end > sample->length)
|
||||
sample->sus_loop_end = sample->length;
|
||||
|
||||
if (loop_length > 2)
|
||||
sample->flags |= IT_SAMPLE_SUS_LOOP;
|
||||
|
||||
sample->vibrato_speed = 0;
|
||||
sample->vibrato_depth = 0;
|
||||
sample->vibrato_rate = 0;
|
||||
sample->vibrato_waveform = 0; // do we have to set _all_ these?
|
||||
sample->max_resampling_quality = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int it_okt_read_sample_data(IT_SAMPLE *sample, const char * data, int length)
|
||||
{
|
||||
if (length && sample->length) {
|
||||
if (length < sample->length) {
|
||||
sample->length = length;
|
||||
if (length < sample->sus_loop_end) sample->sus_loop_end = length;
|
||||
}
|
||||
|
||||
sample->data = malloc(length);
|
||||
|
||||
if (!sample->data)
|
||||
return -1;
|
||||
|
||||
memcpy(sample->data, data, length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct IFF_CHUNK IFF_CHUNK;
|
||||
typedef struct IFF_CHUNKED IFF_CHUNKED;
|
||||
|
||||
struct IFF_CHUNK
|
||||
{
|
||||
unsigned type;
|
||||
unsigned char * data;
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
struct IFF_CHUNKED
|
||||
{
|
||||
unsigned chunk_count;
|
||||
IFF_CHUNK * chunks;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static IFF_CHUNKED *dumbfile_read_okt(DUMBFILE *f)
|
||||
{
|
||||
IFF_CHUNKED *mod = (IFF_CHUNKED *) malloc(sizeof(*mod));
|
||||
if (!mod) return NULL;
|
||||
|
||||
mod->chunk_count = 0;
|
||||
mod->chunks = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
long bytes_read;
|
||||
IFF_CHUNK * chunk = ( IFF_CHUNK * ) realloc( mod->chunks, ( mod->chunk_count + 1 ) * sizeof( IFF_CHUNK ) );
|
||||
if ( !chunk )
|
||||
{
|
||||
if ( mod->chunks ) free( mod->chunks );
|
||||
free( mod );
|
||||
return NULL;
|
||||
}
|
||||
mod->chunks = chunk;
|
||||
chunk += mod->chunk_count;
|
||||
|
||||
bytes_read = dumbfile_mgetl( f );
|
||||
if ( bytes_read < 0 ) break;
|
||||
|
||||
chunk->type = bytes_read;
|
||||
chunk->size = dumbfile_mgetl( f );
|
||||
|
||||
if ( dumbfile_error( f ) ) break;
|
||||
|
||||
chunk->data = (unsigned char *) malloc( chunk->size );
|
||||
if ( !chunk->data )
|
||||
{
|
||||
free( mod->chunks );
|
||||
free( mod );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytes_read = dumbfile_getnc( ( char * ) chunk->data, chunk->size, f );
|
||||
if ( bytes_read < chunk->size )
|
||||
{
|
||||
if ( bytes_read <= 0 ) {
|
||||
free( chunk->data );
|
||||
break;
|
||||
} else {
|
||||
chunk->size = bytes_read;
|
||||
mod->chunk_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mod->chunk_count++;
|
||||
}
|
||||
|
||||
if ( !mod->chunk_count ) {
|
||||
if ( mod->chunks ) free(mod->chunks);
|
||||
free(mod);
|
||||
mod = NULL;
|
||||
}
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
void free_okt(IFF_CHUNKED * mod)
|
||||
{
|
||||
unsigned i;
|
||||
if (mod)
|
||||
{
|
||||
if (mod->chunks)
|
||||
{
|
||||
for (i = 0; i < mod->chunk_count; i++)
|
||||
{
|
||||
if (mod->chunks[i].data) free(mod->chunks[i].data);
|
||||
}
|
||||
free(mod->chunks);
|
||||
}
|
||||
free(mod);
|
||||
}
|
||||
}
|
||||
|
||||
const IFF_CHUNK * get_chunk_by_type(IFF_CHUNKED * mod, unsigned type, unsigned offset)
|
||||
{
|
||||
unsigned i;
|
||||
if (mod)
|
||||
{
|
||||
if (mod->chunks)
|
||||
{
|
||||
for (i = 0; i < mod->chunk_count; i++)
|
||||
{
|
||||
if (mod->chunks[i].type == type)
|
||||
{
|
||||
if (!offset) return &mod->chunks[i];
|
||||
else offset--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned get_chunk_count(IFF_CHUNKED *mod, unsigned type)
|
||||
{
|
||||
unsigned i, count = 0;
|
||||
if (mod)
|
||||
{
|
||||
if (mod->chunks)
|
||||
{
|
||||
for (i = 0; i < mod->chunk_count; i++)
|
||||
{
|
||||
if (mod->chunks[i].type == type) count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
|
||||
{
|
||||
DUMB_IT_SIGDATA *sigdata;
|
||||
int n_channels;
|
||||
int i, j, k, l;
|
||||
IFF_CHUNKED *mod;
|
||||
const IFF_CHUNK *chunk;
|
||||
|
||||
char signature[8];
|
||||
|
||||
if (dumbfile_getnc(signature, 8, f) < 8 ||
|
||||
memcmp(signature, "OKTASONG", 8)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mod = dumbfile_read_okt(f);
|
||||
if (!mod)
|
||||
return NULL;
|
||||
|
||||
sigdata = (DUMB_IT_SIGDATA *) malloc(sizeof(*sigdata));
|
||||
if (!sigdata) {
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->name[0] = 0;
|
||||
|
||||
chunk = get_chunk_by_type(mod, DUMB_ID('S','P','E','E'), 0);
|
||||
if (!chunk || chunk->size < 2) {
|
||||
free(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->speed = (chunk->data[0] << 8) | chunk->data[1];
|
||||
|
||||
chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0);
|
||||
if (!chunk || chunk->size < 32) {
|
||||
free(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->n_samples = chunk->size / 32;
|
||||
|
||||
chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0);
|
||||
if (!chunk || chunk->size < 8) {
|
||||
free(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n_channels = 0;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
j = (chunk->data[i * 2] << 8) | chunk->data[i * 2 + 1];
|
||||
if (!j) n_channels++;
|
||||
else if (j == 1) n_channels += 2;
|
||||
}
|
||||
|
||||
if (!n_channels) {
|
||||
free(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->n_pchannels = n_channels;
|
||||
|
||||
sigdata->sample = (IT_SAMPLE *) malloc(sigdata->n_samples * sizeof(*sigdata->sample));
|
||||
if (!sigdata->sample) {
|
||||
free(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->song_message = NULL;
|
||||
sigdata->order = NULL;
|
||||
sigdata->instrument = NULL;
|
||||
sigdata->pattern = NULL;
|
||||
sigdata->midi = NULL;
|
||||
sigdata->checkpoint = NULL;
|
||||
|
||||
sigdata->n_instruments = 0;
|
||||
|
||||
for (i = 0; i < sigdata->n_samples; i++)
|
||||
sigdata->sample[i].data = NULL;
|
||||
|
||||
chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0);
|
||||
|
||||
for (i = 0; i < sigdata->n_samples; i++) {
|
||||
it_okt_read_sample_header(&sigdata->sample[i], chunk->data + 32 * i);
|
||||
}
|
||||
|
||||
sigdata->restart_position = 0;
|
||||
|
||||
chunk = get_chunk_by_type(mod, DUMB_ID('P','L','E','N'), 0);
|
||||
if (!chunk || chunk->size < 2) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->n_orders = (chunk->data[0] << 8) | chunk->data[1];
|
||||
// what if this is > 128?
|
||||
|
||||
if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chunk = get_chunk_by_type(mod, DUMB_ID('P','A','T','T'), 0);
|
||||
if (!chunk || chunk->size < (unsigned)sigdata->n_orders) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->order = (unsigned char *) malloc(sigdata->n_orders);
|
||||
if (!sigdata->order) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(sigdata->order, chunk->data, sigdata->n_orders);
|
||||
|
||||
/* Work out how many patterns there are. */
|
||||
chunk = get_chunk_by_type(mod, DUMB_ID('S','L','E','N'), 0);
|
||||
if (!chunk || chunk->size < 2) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->n_patterns = (chunk->data[0] << 8) | chunk->data[1];
|
||||
|
||||
j = get_chunk_count(mod, DUMB_ID('P','B','O','D'));
|
||||
if (sigdata->n_patterns > j) sigdata->n_patterns = j;
|
||||
|
||||
if (!sigdata->n_patterns) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigdata->pattern = (IT_PATTERN *) malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
|
||||
if (!sigdata->pattern) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < sigdata->n_patterns; i++)
|
||||
sigdata->pattern[i].entry = NULL;
|
||||
|
||||
/* Read in the patterns */
|
||||
for (i = 0; i < sigdata->n_patterns; i++) {
|
||||
chunk = get_chunk_by_type(mod, DUMB_ID('P','B','O','D'), i);
|
||||
if (it_okt_read_pattern(&sigdata->pattern[i], chunk->data, chunk->size, n_channels) != 0) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* And finally, the sample data */
|
||||
k = get_chunk_count(mod, DUMB_ID('S','B','O','D'));
|
||||
for (i = 0, j = 0; i < sigdata->n_samples && j < k; i++) {
|
||||
if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) {
|
||||
chunk = get_chunk_by_type(mod, DUMB_ID('S','B','O','D'), j);
|
||||
if (it_okt_read_sample_data(&sigdata->sample[i], (const char *)chunk->data, chunk->size)) {
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
free_okt(mod);
|
||||
return NULL;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
for (; i < sigdata->n_samples; i++) {
|
||||
sigdata->sample[i].flags = 0;
|
||||
}
|
||||
|
||||
chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0);
|
||||
|
||||
for (i = 0, j = 0; i < n_channels && j < 4; j++) {
|
||||
k = (chunk->data[j * 2] << 8) | chunk->data[j * 2 + 1];
|
||||
l = (j == 1 || j == 2) ? 48 : 16;
|
||||
if (k == 0) {
|
||||
sigdata->channel_pan[i++] = l;
|
||||
}
|
||||
else if (k == 1) {
|
||||
sigdata->channel_pan[i++] = l;
|
||||
sigdata->channel_pan[i++] = l;
|
||||
}
|
||||
}
|
||||
|
||||
free_okt(mod);
|
||||
|
||||
/* Now let's initialise the remaining variables, and we're done! */
|
||||
sigdata->flags = IT_WAS_AN_OKT | IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
|
||||
|
||||
sigdata->global_volume = 128;
|
||||
sigdata->mixing_volume = 48;
|
||||
/* We want 50 ticks per second; 50/6 row advances per second;
|
||||
* 50*10=500 row advances per minute; 500/4=125 beats per minute.
|
||||
*/
|
||||
sigdata->tempo = 125;
|
||||
sigdata->pan_separation = 128;
|
||||
|
||||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
memset(sigdata->channel_pan + n_channels, 32, DUMB_IT_N_CHANNELS - n_channels);
|
||||
|
||||
_dumb_it_fix_invalid_orders(sigdata);
|
||||
|
||||
return sigdata;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DUH *dumb_read_okt_quick(DUMBFILE *f)
|
||||
{
|
||||
sigdata_t *sigdata;
|
||||
|
||||
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||
|
||||
sigdata = it_okt_load_sigdata(f);
|
||||
|
||||
if (!sigdata)
|
||||
return NULL;
|
||||
|
||||
{
|
||||
const char *tag[1][2];
|
||||
tag[0][0] = "FORMAT";
|
||||
tag[0][1] = "Oktalyzer";
|
||||
return make_duh(-1, 1, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue