Updated DUMB

This commit is contained in:
Chris Moeller 2013-09-27 20:24:23 -07:00
parent d969f5a6a7
commit 17682d4397
256 changed files with 47317 additions and 35807 deletions

View file

@ -350,9 +350,15 @@
/* Begin PBXProject section */ /* Begin PBXProject section */
0867D690FE84028FC02AAC07 /* Project object */ = { 0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = {
};
buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "CogAudio" */; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "CogAudio" */;
compatibilityVersion = "Xcode 3.0"; compatibilityVersion = "Xcode 3.0";
developmentRegion = English;
hasScannedForEncodings = 1; hasScannedForEncodings = 1;
knownRegions = (
en,
);
mainGroup = 0867D691FE84028FC02AAC07 /* CogAudio */; mainGroup = 0867D691FE84028FC02AAC07 /* CogAudio */;
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -405,6 +411,7 @@
1DEB91AE08733DA50010E9CD /* Debug */ = { 1DEB91AE08733DA50010E9CD /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ARCHS = "$(ARCHS_STANDARD)";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1; DYLIB_CURRENT_VERSION = 1;
@ -421,6 +428,7 @@
INSTALL_PATH = "@executable_path/../Frameworks"; INSTALL_PATH = "@executable_path/../Frameworks";
OTHER_LDFLAGS = ""; OTHER_LDFLAGS = "";
PRODUCT_NAME = CogAudio; PRODUCT_NAME = CogAudio;
SDKROOT = macosx10.6;
WARNING_LDFLAGS = ""; WARNING_LDFLAGS = "";
WRAPPER_EXTENSION = framework; WRAPPER_EXTENSION = framework;
ZERO_LINK = YES; ZERO_LINK = YES;
@ -431,8 +439,8 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ARCHS = ( ARCHS = (
ppc,
i386, i386,
ppc,
); );
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1; DYLIB_CURRENT_VERSION = 1;
@ -447,6 +455,7 @@
INSTALL_PATH = "@executable_path/../Frameworks"; INSTALL_PATH = "@executable_path/../Frameworks";
OTHER_LDFLAGS = ""; OTHER_LDFLAGS = "";
PRODUCT_NAME = CogAudio; PRODUCT_NAME = CogAudio;
SDKROOT = macosx10.6;
WARNING_LDFLAGS = ""; WARNING_LDFLAGS = "";
WRAPPER_EXTENSION = framework; WRAPPER_EXTENSION = framework;
}; };

View file

@ -87,7 +87,6 @@
17A8F6860D6A7FCA0095DA13 /* repeat_none.png in Resources */ = {isa = PBXBuildFile; fileRef = 17A8F6830D6A7FCA0095DA13 /* repeat_none.png */; }; 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 */; }; 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 */; }; 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 */; }; 17B7CF5C0F5A05EE00A47027 /* pauseBadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 17B7CF590F5A05EE00A47027 /* pauseBadge.png */; };
17B7CF5D0F5A05EE00A47027 /* playBadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 17B7CF5A0F5A05EE00A47027 /* playBadge.png */; }; 17B7CF5D0F5A05EE00A47027 /* playBadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 17B7CF5A0F5A05EE00A47027 /* playBadge.png */; };
17B7CF5E0F5A05EE00A47027 /* stopBadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 17B7CF5B0F5A05EE00A47027 /* stopBadge.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 */; }; 17BB5CFA0B8A86350009ACB1 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CF70B8A86350009ACB1 /* CoreAudio.framework */; };
17BB5CFB0B8A86350009ACB1 /* CoreAudioKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CF80B8A86350009ACB1 /* CoreAudioKit.framework */; }; 17BB5CFB0B8A86350009ACB1 /* CoreAudioKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CF80B8A86350009ACB1 /* CoreAudioKit.framework */; };
17BB5EA60B8A87850009ACB1 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5EA50B8A87850009ACB1 /* IOKit.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 */; }; 17C809910C3BD201005707C4 /* WavPack.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C808C80C3BD1DD005707C4 /* WavPack.bundle */; };
17C809920C3BD206005707C4 /* Vorbis.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C808BF0C3BD1D2005707C4 /* Vorbis.bundle */; }; 17C809920C3BD206005707C4 /* Vorbis.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C808BF0C3BD1D2005707C4 /* Vorbis.bundle */; };
17C809930C3BD21D005707C4 /* TagLib.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C808B60C3BD1C5005707C4 /* TagLib.bundle */; }; 17C809930C3BD21D005707C4 /* TagLib.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C808B60C3BD1C5005707C4 /* TagLib.bundle */; };
@ -193,20 +191,6 @@
remoteGlobalIDString = 8D5B49AC048680CD000E48DA; remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
remoteInfo = "AudioOverload Plugin"; 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 */ = { 17C808780C3BD167005707C4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
containerPortal = 17C808710C3BD167005707C4 /* FileSource.xcodeproj */; containerPortal = 17C808710C3BD167005707C4 /* FileSource.xcodeproj */;
@ -518,7 +502,6 @@
dstPath = ""; dstPath = "";
dstSubfolderSpec = 10; dstSubfolderSpec = 10;
files = ( files = (
17B6FA7F0D48225300C3BEF1 /* Sparkle.framework in CopyFiles */,
17F561400C3BD4F30019975C /* CogAudio.framework in CopyFiles */, 17F561400C3BD4F30019975C /* CogAudio.framework in CopyFiles */,
170680840B950164006BA573 /* Growl.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>"; }; 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>"; }; 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>"; }; 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; }; 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>"; }; 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>"; }; 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; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
17BF2B280CDD7802007E1295 /* Sparkle.framework in Frameworks */,
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
8E6889240AAA403C00AD3950 /* Carbon.framework in Frameworks */, 8E6889240AAA403C00AD3950 /* Carbon.framework in Frameworks */,
17BB5CED0B8A86010009ACB1 /* AudioToolbox.framework in Frameworks */, 17BB5CED0B8A86010009ACB1 /* AudioToolbox.framework in Frameworks */,
@ -826,7 +807,6 @@
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
17BF2B1F0CDD77EB007E1295 /* Sparkle.xcodeproj */,
17F5612A0C3BD4DC0019975C /* CogAudio.xcodeproj */, 17F5612A0C3BD4DC0019975C /* CogAudio.xcodeproj */,
170680620B950158006BA573 /* Growl.framework */, 170680620B950158006BA573 /* Growl.framework */,
8E6889230AAA403C00AD3950 /* Carbon.framework */, 8E6889230AAA403C00AD3950 /* Carbon.framework */,
@ -1036,14 +1016,6 @@
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
17BF2B200CDD77EB007E1295 /* Products */ = {
isa = PBXGroup;
children = (
17BF2B270CDD77EB007E1295 /* Sparkle.framework */,
);
name = Products;
sourceTree = "<group>";
};
17C808720C3BD167005707C4 /* Products */ = { 17C808720C3BD167005707C4 /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1511,7 +1483,6 @@
17F3BB8B0CBC566200864489 /* PBXTargetDependency */, 17F3BB8B0CBC566200864489 /* PBXTargetDependency */,
17C8F44C0CBEDD37008D969D /* PBXTargetDependency */, 17C8F44C0CBEDD37008D969D /* PBXTargetDependency */,
17C8F7DA0CBEF3F9008D969D /* PBXTargetDependency */, 17C8F7DA0CBEF3F9008D969D /* PBXTargetDependency */,
17BF2B3A0CDD7827007E1295 /* PBXTargetDependency */,
17643CBC0D5BD44900F0A9FE /* PBXTargetDependency */, 17643CBC0D5BD44900F0A9FE /* PBXTargetDependency */,
17B7CF960F5A0A3700A47027 /* PBXTargetDependency */, 17B7CF960F5A0A3700A47027 /* PBXTargetDependency */,
); );
@ -1526,8 +1497,11 @@
/* Begin PBXProject section */ /* Begin PBXProject section */
29B97313FDCFA39411CA2CEA /* Project object */ = { 29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = {
};
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Cog" */; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Cog" */;
compatibilityVersion = "Xcode 3.0"; compatibilityVersion = "Xcode 3.0";
developmentRegion = English;
hasScannedForEncodings = 1; hasScannedForEncodings = 1;
knownRegions = ( knownRegions = (
English, English,
@ -1610,10 +1584,6 @@
ProductGroup = 17C808A80C3BD1BA005707C4 /* Products */; ProductGroup = 17C808A80C3BD1BA005707C4 /* Products */;
ProjectRef = 17C808A70C3BD1BA005707C4 /* Shorten.xcodeproj */; ProjectRef = 17C808A70C3BD1BA005707C4 /* Shorten.xcodeproj */;
}, },
{
ProductGroup = 17BF2B200CDD77EB007E1295 /* Products */;
ProjectRef = 17BF2B1F0CDD77EB007E1295 /* Sparkle.xcodeproj */;
},
{ {
ProductGroup = 17C808B10C3BD1C5005707C4 /* Products */; ProductGroup = 17C808B10C3BD1C5005707C4 /* Products */;
ProjectRef = 17C808B00C3BD1C5005707C4 /* TagLib.xcodeproj */; ProjectRef = 17C808B00C3BD1C5005707C4 /* TagLib.xcodeproj */;
@ -1646,13 +1616,6 @@
remoteRef = 17B7CF7B0F5A09FD00A47027 /* PBXContainerItemProxy */; remoteRef = 17B7CF7B0F5A09FD00A47027 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR; 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 */ = { 17C808790C3BD167005707C4 /* FileSource.bundle */ = {
isa = PBXReferenceProxy; isa = PBXReferenceProxy;
fileType = wrapper.cfbundle; fileType = wrapper.cfbundle;
@ -1958,11 +1921,6 @@
name = "AudioOverload Plugin"; name = "AudioOverload Plugin";
targetProxy = 17B7CF950F5A0A3700A47027 /* PBXContainerItemProxy */; targetProxy = 17B7CF950F5A0A3700A47027 /* PBXContainerItemProxy */;
}; };
17BF2B3A0CDD7827007E1295 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = Sparkle;
targetProxy = 17BF2B390CDD7827007E1295 /* PBXContainerItemProxy */;
};
17C8097E0C3BD1F5005707C4 /* PBXTargetDependency */ = { 17C8097E0C3BD1F5005707C4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency; isa = PBXTargetDependency;
name = Musepack; name = Musepack;
@ -2166,9 +2124,11 @@
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
CogAudio, CogAudio,
"-undefined",
dynamic_lookup,
); );
PRODUCT_NAME = Cog; PRODUCT_NAME = Cog;
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; SDKROOT = macosx10.6;
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
ZERO_LINK = NO; ZERO_LINK = NO;
}; };
@ -2202,9 +2162,11 @@
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
CogAudio, CogAudio,
"-undefined",
dynamic_lookup,
); );
PRODUCT_NAME = Cog; PRODUCT_NAME = Cog;
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; SDKROOT = macosx10.6;
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
}; };
name = Release; name = Release;

View file

@ -441,9 +441,15 @@
/* Begin PBXProject section */ /* Begin PBXProject section */
0867D690FE84028FC02AAC07 /* Project object */ = { 0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = {
};
buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "AudioOverload" */; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "AudioOverload" */;
compatibilityVersion = "Xcode 3.1"; compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 1; hasScannedForEncodings = 1;
knownRegions = (
en,
);
mainGroup = 0867D691FE84028FC02AAC07 /* AudioOverload */; mainGroup = 0867D691FE84028FC02AAC07 /* AudioOverload */;
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -522,6 +528,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD)";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1; DYLIB_CURRENT_VERSION = 1;
@ -545,6 +552,7 @@
INFOPLIST_FILE = Info.plist; INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "@loader_path/../Frameworks"; INSTALL_PATH = "@loader_path/../Frameworks";
PRODUCT_NAME = AudioOverload; PRODUCT_NAME = AudioOverload;
SDKROOT = macosx10.6;
USE_HEADERMAP = NO; USE_HEADERMAP = NO;
WRAPPER_EXTENSION = framework; WRAPPER_EXTENSION = framework;
}; };
@ -554,6 +562,10 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
i386,
ppc,
);
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1; DYLIB_CURRENT_VERSION = 1;
@ -574,6 +586,7 @@
INFOPLIST_FILE = Info.plist; INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "@loader_path/../Frameworks"; INSTALL_PATH = "@loader_path/../Frameworks";
PRODUCT_NAME = AudioOverload; PRODUCT_NAME = AudioOverload;
SDKROOT = macosx10.6;
USE_HEADERMAP = NO; USE_HEADERMAP = NO;
WRAPPER_EXTENSION = framework; WRAPPER_EXTENSION = framework;
}; };
@ -589,7 +602,7 @@
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PREBINDING = NO; PREBINDING = NO;
SDKROOT = macosx10.5; SDKROOT = macosx10.6;
SYMROOT = ../../build; SYMROOT = ../../build;
}; };
name = Debug; name = Debug;
@ -602,7 +615,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO; PREBINDING = NO;
SDKROOT = macosx10.5; SDKROOT = macosx10.6;
SYMROOT = ../../build; SYMROOT = ../../build;
}; };
name = Release; name = Release;

View file

@ -540,7 +540,7 @@ static void *MAINThread(int samp2run)
lastch=ch; lastch=ch;
// lastns=ns; // changemeback // lastns=ns; // changemeback
return; return 0;
} }
} }

View file

@ -9,7 +9,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
17C8F63E0CBEE797008D969D /* dumb.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C8F60C0CBEE797008D969D /* dumb.h */; settings = {ATTRIBUTES = (Public, ); }; }; 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 */; }; 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 */; }; 17C8F6410CBEE797008D969D /* atexit.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F6120CBEE797008D969D /* atexit.c */; };
17C8F6420CBEE797008D969D /* duhlen.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F6130CBEE797008D969D /* duhlen.c */; }; 17C8F6420CBEE797008D969D /* duhlen.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F6130CBEE797008D969D /* duhlen.c */; };
17C8F6430CBEE797008D969D /* duhtag.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F6140CBEE797008D969D /* duhtag.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 */; }; 17C8F6680CBEE797008D969D /* readxm.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F63B0CBEE797008D969D /* readxm.c */; };
17C8F6690CBEE797008D969D /* readxm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F63C0CBEE797008D969D /* readxm2.c */; }; 17C8F6690CBEE797008D969D /* readxm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F63C0CBEE797008D969D /* readxm2.c */; };
17C8F66A0CBEE797008D969D /* xmeffect.c in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F63D0CBEE797008D969D /* xmeffect.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 */; }; 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; }; 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -103,6 +158,61 @@
17C8F63B0CBEE797008D969D /* readxm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = readxm.c; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; }; 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; }; 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>"; }; 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 */ = { 17C8F60D0CBEE797008D969D /* internal */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( 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 */, 17C8F60E0CBEE797008D969D /* dumb.h */,
17C8F60F0CBEE797008D969D /* it.h */, 17C8F60F0CBEE797008D969D /* it.h */,
); );
@ -236,6 +354,12 @@
17C8F61E0CBEE797008D969D /* helpers */ = { 17C8F61E0CBEE797008D969D /* helpers */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
8370B62E17F61001001A4D7A /* barray.c */,
8370B62F17F61001001A4D7A /* blip_buf.c */,
8370B63017F61001001A4D7A /* lanczos_resampler.c */,
8370B63117F61001001A4D7A /* lpc.c */,
8370B63217F61001001A4D7A /* riff.c */,
8370B63317F61001001A4D7A /* tarray.c */,
17C8F61F0CBEE797008D969D /* clickrem.c */, 17C8F61F0CBEE797008D969D /* clickrem.c */,
17C8F6200CBEE797008D969D /* memfile.c */, 17C8F6200CBEE797008D969D /* memfile.c */,
17C8F6210CBEE797008D969D /* resamp2.inc */, 17C8F6210CBEE797008D969D /* resamp2.inc */,
@ -252,6 +376,47 @@
17C8F6280CBEE797008D969D /* it */ = { 17C8F6280CBEE797008D969D /* it */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( 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 */, 17C8F6290CBEE797008D969D /* itload.c */,
17C8F62A0CBEE797008D969D /* itload2.c */, 17C8F62A0CBEE797008D969D /* itload2.c */,
17C8F62B0CBEE797008D969D /* itmisc.c */, 17C8F62B0CBEE797008D969D /* itmisc.c */,
@ -285,8 +450,16 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
17C8F63E0CBEE797008D969D /* dumb.h in Headers */, 17C8F63E0CBEE797008D969D /* dumb.h in Headers */,
17C8F63F0CBEE797008D969D /* dumb.h in Headers */,
17C8F6400CBEE797008D969D /* it.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; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -317,9 +490,15 @@
/* Begin PBXProject section */ /* Begin PBXProject section */
0867D690FE84028FC02AAC07 /* Project object */ = { 0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = {
};
buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Dumb" */; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Dumb" */;
compatibilityVersion = "Xcode 2.4"; compatibilityVersion = "Xcode 2.4";
developmentRegion = English;
hasScannedForEncodings = 1; hasScannedForEncodings = 1;
knownRegions = (
en,
);
mainGroup = 0867D691FE84028FC02AAC07 /* Dumb */; mainGroup = 0867D691FE84028FC02AAC07 /* Dumb */;
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -346,29 +525,56 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
8370B66D17F61038001A4D7A /* loadokt.c in Sources */,
8370B68A17F61038001A4D7A /* readstm.c in Sources */,
17C8F6410CBEE797008D969D /* atexit.c in Sources */, 17C8F6410CBEE797008D969D /* atexit.c in Sources */,
17C8F6420CBEE797008D969D /* duhlen.c in Sources */, 17C8F6420CBEE797008D969D /* duhlen.c in Sources */,
8370B66E17F61038001A4D7A /* loadokt2.c in Sources */,
8370B63817F61001001A4D7A /* riff.c in Sources */,
17C8F6430CBEE797008D969D /* duhtag.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 */, 17C8F6440CBEE797008D969D /* dumbfile.c in Sources */,
8370B68317F61038001A4D7A /* readmtm.c in Sources */,
17C8F6450CBEE797008D969D /* loadduh.c in Sources */, 17C8F6450CBEE797008D969D /* loadduh.c in Sources */,
8370B67D17F61038001A4D7A /* readamf.c in Sources */,
8370B63717F61001001A4D7A /* lpc.c in Sources */,
17C8F6460CBEE797008D969D /* makeduh.c in Sources */, 17C8F6460CBEE797008D969D /* makeduh.c in Sources */,
17C8F6470CBEE797008D969D /* rawsig.c in Sources */, 17C8F6470CBEE797008D969D /* rawsig.c in Sources */,
17C8F6480CBEE797008D969D /* readduh.c in Sources */, 17C8F6480CBEE797008D969D /* readduh.c in Sources */,
8370B67917F61038001A4D7A /* ptmeffect.c in Sources */,
17C8F6490CBEE797008D969D /* register.c in Sources */, 17C8F6490CBEE797008D969D /* register.c in Sources */,
8370B67C17F61038001A4D7A /* readam.c in Sources */,
17C8F64A0CBEE797008D969D /* rendduh.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 */, 17C8F64B0CBEE797008D969D /* rendsig.c in Sources */,
17C8F64C0CBEE797008D969D /* unload.c in Sources */, 17C8F64C0CBEE797008D969D /* unload.c in Sources */,
17C8F64D0CBEE797008D969D /* clickrem.c in Sources */, 17C8F64D0CBEE797008D969D /* clickrem.c in Sources */,
17C8F64E0CBEE797008D969D /* memfile.c in Sources */, 17C8F64E0CBEE797008D969D /* memfile.c in Sources */,
17C8F6510CBEE797008D969D /* resample.c in Sources */, 17C8F6510CBEE797008D969D /* resample.c in Sources */,
8370B66F17F61038001A4D7A /* loadoldpsm.c in Sources */,
17C8F6530CBEE797008D969D /* sampbuf.c in Sources */, 17C8F6530CBEE797008D969D /* sampbuf.c in Sources */,
17C8F6540CBEE797008D969D /* silence.c in Sources */, 17C8F6540CBEE797008D969D /* silence.c in Sources */,
17C8F6550CBEE797008D969D /* stdfile.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 */, 17C8F6560CBEE797008D969D /* itload.c in Sources */,
17C8F6570CBEE797008D969D /* itload2.c in Sources */, 17C8F6570CBEE797008D969D /* itload2.c in Sources */,
8370B63617F61001001A4D7A /* lanczos_resampler.c in Sources */,
17C8F6580CBEE797008D969D /* itmisc.c in Sources */, 17C8F6580CBEE797008D969D /* itmisc.c in Sources */,
8370B67517F61038001A4D7A /* loadriff.c in Sources */,
8370B66917F61038001A4D7A /* loadasy.c in Sources */,
17C8F6590CBEE797008D969D /* itorder.c in Sources */, 17C8F6590CBEE797008D969D /* itorder.c in Sources */,
8370B66317F61038001A4D7A /* load669.c in Sources */,
17C8F65A0CBEE797008D969D /* itread.c in Sources */, 17C8F65A0CBEE797008D969D /* itread.c in Sources */,
8370B68B17F61038001A4D7A /* readstm2.c in Sources */,
17C8F65B0CBEE797008D969D /* itread2.c in Sources */, 17C8F65B0CBEE797008D969D /* itread2.c in Sources */,
17C8F65C0CBEE797008D969D /* itrender.c in Sources */, 17C8F65C0CBEE797008D969D /* itrender.c in Sources */,
17C8F65D0CBEE797008D969D /* itunload.c in Sources */, 17C8F65D0CBEE797008D969D /* itunload.c in Sources */,
@ -376,14 +582,34 @@
17C8F65F0CBEE797008D969D /* loadmod2.c in Sources */, 17C8F65F0CBEE797008D969D /* loadmod2.c in Sources */,
17C8F6600CBEE797008D969D /* loads3m.c in Sources */, 17C8F6600CBEE797008D969D /* loads3m.c in Sources */,
17C8F6610CBEE797008D969D /* loads3m2.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 */, 17C8F6620CBEE797008D969D /* loadxm.c in Sources */,
17C8F6630CBEE797008D969D /* loadxm2.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 */, 17C8F6640CBEE797008D969D /* readmod.c in Sources */,
8370B67017F61038001A4D7A /* loadoldpsm2.c in Sources */,
8370B68217F61038001A4D7A /* readdsmf.c in Sources */,
17C8F6650CBEE797008D969D /* readmod2.c in Sources */, 17C8F6650CBEE797008D969D /* readmod2.c in Sources */,
8370B68617F61038001A4D7A /* readoldpsm.c in Sources */,
17C8F6660CBEE797008D969D /* reads3m.c in Sources */, 17C8F6660CBEE797008D969D /* reads3m.c in Sources */,
17C8F6670CBEE797008D969D /* reads3m2.c in Sources */, 17C8F6670CBEE797008D969D /* reads3m2.c in Sources */,
17C8F6680CBEE797008D969D /* readxm.c in Sources */, 17C8F6680CBEE797008D969D /* readxm.c in Sources */,
8370B68917F61038001A4D7A /* readriff.c in Sources */,
17C8F6690CBEE797008D969D /* readxm2.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 */, 17C8F66A0CBEE797008D969D /* xmeffect.c in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -421,6 +647,7 @@
OBJROOT = ../../build; OBJROOT = ../../build;
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
PRODUCT_NAME = Dumb; PRODUCT_NAME = Dumb;
SDKROOT = macosx10.6;
SHARED_PRECOMPS_DIR = ""; SHARED_PRECOMPS_DIR = "";
SYMROOT = ../../build; SYMROOT = ../../build;
WRAPPER_EXTENSION = framework; WRAPPER_EXTENSION = framework;
@ -448,6 +675,7 @@
OBJROOT = ../../build; OBJROOT = ../../build;
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
PRODUCT_NAME = Dumb; PRODUCT_NAME = Dumb;
SDKROOT = macosx10.6;
SHARED_PRECOMPS_DIR = ""; SHARED_PRECOMPS_DIR = "";
SYMROOT = ../../build; SYMROOT = ../../build;
WRAPPER_EXTENSION = framework; WRAPPER_EXTENSION = framework;

View file

@ -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>

View file

@ -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

View 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 */

View 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

View 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

View file

@ -1,61 +1,61 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* internal/dumb.h - DUMB's internal declarations. / / \ \ * internal/dumb.h - DUMB's internal declarations. / / \ \
* | < / \_ * | < / \_
* This header file provides access to the | \/ /\ / * This header file provides access to the | \/ /\ /
* internal structure of DUMB, and is liable \_ / > / * internal structure of DUMB, and is liable \_ / > /
* to change, mutate or cease to exist at any | \ / / * to change, mutate or cease to exist at any | \ / /
* moment. Include it at your own peril. | ' / * moment. Include it at your own peril. | ' /
* \__/ * \__/
* ... * ...
* *
* Seriously. You don't need access to anything in this file. All right, you * 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 * 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 * 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. * contact the authors so that we can provide a public API for what you need.
*/ */
#ifndef INTERNAL_DUMB_H #ifndef INTERNAL_DUMB_H
#define INTERNAL_DUMB_H #define INTERNAL_DUMB_H
typedef struct DUH_SIGTYPE_DESC_LINK typedef struct DUH_SIGTYPE_DESC_LINK
{ {
struct DUH_SIGTYPE_DESC_LINK *next; struct DUH_SIGTYPE_DESC_LINK *next;
DUH_SIGTYPE_DESC *desc; DUH_SIGTYPE_DESC *desc;
} }
DUH_SIGTYPE_DESC_LINK; DUH_SIGTYPE_DESC_LINK;
typedef struct DUH_SIGNAL typedef struct DUH_SIGNAL
{ {
sigdata_t *sigdata; sigdata_t *sigdata;
DUH_SIGTYPE_DESC *desc; DUH_SIGTYPE_DESC *desc;
} }
DUH_SIGNAL; DUH_SIGNAL;
struct DUH struct DUH
{ {
long length; long length;
int n_tags; int n_tags;
char *(*tag)[2]; char *(*tag)[2];
int n_signals; int n_signals;
DUH_SIGNAL **signal; DUH_SIGNAL **signal;
}; };
DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type); DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type);
#endif /* INTERNAL_DUMB_H */ #endif /* INTERNAL_DUMB_H */

View 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

View 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

View 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

View 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

View 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

View 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

View 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
View file

@ -0,0 +1,3 @@
dumb-build-Desktop-Release
dumb-build-Desktop-Debug
*.user

View 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

View file

@ -1,71 +1,71 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* atexit.c - Library Clean-up Management. / / \ \ * atexit.c - Library Clean-up Management. / / \ \
* | < / \_ * | < / \_
* By entheh. | \/ /\ / * By entheh. | \/ /\ /
* \_ / > / * \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
typedef struct DUMB_ATEXIT_PROC typedef struct DUMB_ATEXIT_PROC
{ {
struct DUMB_ATEXIT_PROC *next; struct DUMB_ATEXIT_PROC *next;
void (*proc)(void); void (*proc)(void);
} }
DUMB_ATEXIT_PROC; DUMB_ATEXIT_PROC;
static DUMB_ATEXIT_PROC *dumb_atexit_proc = NULL; static DUMB_ATEXIT_PROC *dumb_atexit_proc = NULL;
int dumb_atexit(void (*proc)(void)) int dumb_atexit(void (*proc)(void))
{ {
DUMB_ATEXIT_PROC *dap = dumb_atexit_proc; DUMB_ATEXIT_PROC *dap = dumb_atexit_proc;
while (dap) { while (dap) {
if (dap->proc == proc) return 0; if (dap->proc == proc) return 0;
dap = dap->next; dap = dap->next;
} }
dap = malloc(sizeof(*dap)); dap = malloc(sizeof(*dap));
if (!dap) if (!dap)
return -1; return -1;
dap->next = dumb_atexit_proc; dap->next = dumb_atexit_proc;
dap->proc = proc; dap->proc = proc;
dumb_atexit_proc = dap; dumb_atexit_proc = dap;
return 0; return 0;
} }
void dumb_exit(void) void dumb_exit(void)
{ {
while (dumb_atexit_proc) { while (dumb_atexit_proc) {
DUMB_ATEXIT_PROC *next = dumb_atexit_proc->next; DUMB_ATEXIT_PROC *next = dumb_atexit_proc->next;
(*dumb_atexit_proc->proc)(); (*dumb_atexit_proc->proc)();
free(dumb_atexit_proc); free(dumb_atexit_proc);
dumb_atexit_proc = next; dumb_atexit_proc = next;
} }
} }

View file

@ -1,42 +1,42 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* duhlen.c - Functions to set and return the / / \ \ * duhlen.c - Functions to set and return the / / \ \
* length of a DUH. | < / \_ * length of a DUH. | < / \_
* | \/ /\ / * | \/ /\ /
* By entheh. \_ / > / * By entheh. \_ / > /
* | \ / / * | \ / /
* Note that the length of a DUH is a constant | ' / * Note that the length of a DUH is a constant | ' /
* stored in the DUH struct and in the DUH disk \__/ * stored in the DUH struct and in the DUH disk \__/
* format. It will be calculated on loading for * format. It will be calculated on loading for
* other formats in which the length is not explicitly stored. Also note that * 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 * 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 * 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 * such as Winamp to stop, and in any good DUH it will allow for any final
* flourish to fade out and be appreciated. * flourish to fade out and be appreciated.
*/ */
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
long duh_get_length(DUH *duh) long duh_get_length(DUH *duh)
{ {
return duh ? duh->length : 0; return duh ? duh->length : 0;
} }
void duh_set_length(DUH *duh, long length) void duh_set_length(DUH *duh, long length)
{ {
if (duh) if (duh)
duh->length = length; duh->length = length;
} }

View file

@ -1,38 +1,38 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* duhtag.c - Function to return the tags stored / / \ \ * duhtag.c - Function to return the tags stored / / \ \
* in a DUH struct (typically author | < / \_ * in a DUH struct (typically author | < / \_
* information). | \/ /\ / * information). | \/ /\ /
* \_ / > / * \_ / > /
* By entheh. | \ / / * By entheh. | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <string.h> #include <string.h>
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
const char *duh_get_tag(DUH *duh, const char *key) const char *duh_get_tag(DUH *duh, const char *key)
{ {
int i; int i;
ASSERT(key); ASSERT(key);
if (!duh || !duh->tag) return NULL; if (!duh || !duh->tag) return NULL;
for (i = 0; i < duh->n_tags; i++) for (i = 0; i < duh->n_tags; i++)
if (strcmp(key, duh->tag[i][0]) == 0) if (strcmp(key, duh->tag[i][0]) == 0)
return duh->tag[i][1]; return duh->tag[i][1];
return NULL; return NULL;
} }

View file

@ -1,401 +1,418 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* dumbfile.c - Hookable, strictly sequential / / \ \ * dumbfile.c - Hookable, strictly sequential / / \ \
* file input functions. | < / \_ * file input functions. | < / \_
* | \/ /\ / * | \/ /\ /
* By entheh. \_ / > / * By entheh. \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
static DUMBFILE_SYSTEM *the_dfs = NULL; static const DUMBFILE_SYSTEM *the_dfs = NULL;
void register_dumbfile_system(DUMBFILE_SYSTEM *dfs) void register_dumbfile_system(const DUMBFILE_SYSTEM *dfs)
{ {
ASSERT(dfs); ASSERT(dfs);
ASSERT(dfs->open); ASSERT(dfs->open);
ASSERT(dfs->getc); ASSERT(dfs->getc);
ASSERT(dfs->close); ASSERT(dfs->close);
the_dfs = dfs; ASSERT(dfs->seek);
} ASSERT(dfs->get_size);
the_dfs = dfs;
}
struct DUMBFILE
{
DUMBFILE_SYSTEM *dfs; #include "internal/dumbfile.h"
void *file;
long pos;
};
DUMBFILE *dumbfile_open(const char *filename)
{
DUMBFILE *f;
DUMBFILE *dumbfile_open(const char *filename)
{ ASSERT(the_dfs);
DUMBFILE *f;
f = (DUMBFILE *) malloc(sizeof(*f));
ASSERT(the_dfs);
if (!f)
f = malloc(sizeof(*f)); return NULL;
if (!f) f->dfs = the_dfs;
return NULL;
f->file = (*the_dfs->open)(filename);
f->dfs = the_dfs;
if (!f->file) {
f->file = (*the_dfs->open)(filename); free(f);
return NULL;
if (!f->file) { }
free(f);
return NULL; f->pos = 0;
}
return f;
f->pos = 0; }
return f;
}
DUMBFILE *dumbfile_open_ex(void *file, const DUMBFILE_SYSTEM *dfs)
{
DUMBFILE *f;
DUMBFILE *dumbfile_open_ex(void *file, DUMBFILE_SYSTEM *dfs)
{ ASSERT(dfs);
DUMBFILE *f; ASSERT(dfs->getc);
ASSERT(file);
ASSERT(dfs);
ASSERT(dfs->getc); f = (DUMBFILE *) malloc(sizeof(*f));
ASSERT(file);
if (!f) {
f = malloc(sizeof(*f)); if (dfs->close)
(*dfs->close)(file);
if (!f) { return NULL;
if (dfs->close) }
(*dfs->close)(file);
return NULL; f->dfs = dfs;
} f->file = file;
f->dfs = dfs; f->pos = 0;
f->file = file;
return f;
f->pos = 0; }
return f;
}
long dumbfile_pos(DUMBFILE *f)
{
ASSERT(f);
long dumbfile_pos(DUMBFILE *f)
{ return f->pos;
ASSERT(f); }
return f->pos;
}
int dumbfile_skip(DUMBFILE *f, long n)
{
int rv;
int dumbfile_skip(DUMBFILE *f, long n)
{ ASSERT(f);
int rv; ASSERT(n >= 0);
ASSERT(f); if (f->pos < 0)
ASSERT(n >= 0); return -1;
if (f->pos < 0) f->pos += n;
return -1;
if (f->dfs->skip) {
f->pos += n; rv = (*f->dfs->skip)(f->file, n);
if (rv) {
if (f->dfs->skip) { f->pos = -1;
rv = (*f->dfs->skip)(f->file, n); return rv;
if (rv) { }
f->pos = -1; } else {
return rv; while (n) {
} rv = (*f->dfs->getc)(f->file);
} else { if (rv < 0) {
while (n) { f->pos = -1;
rv = (*f->dfs->getc)(f->file); return rv;
if (rv < 0) { }
f->pos = -1; n--;
return rv; }
} }
n--;
} return 0;
} }
return 0;
}
int dumbfile_getc(DUMBFILE *f)
{
int rv;
int dumbfile_getc(DUMBFILE *f)
{ ASSERT(f);
int rv;
if (f->pos < 0)
ASSERT(f); return -1;
if (f->pos < 0) rv = (*f->dfs->getc)(f->file);
return -1;
if (rv < 0) {
rv = (*f->dfs->getc)(f->file); f->pos = -1;
return rv;
if (rv < 0) { }
f->pos = -1;
return rv; f->pos++;
}
return rv;
f->pos++; }
return rv;
}
int dumbfile_igetw(DUMBFILE *f)
{
int l, h;
int dumbfile_igetw(DUMBFILE *f)
{ ASSERT(f);
int l, h;
if (f->pos < 0)
ASSERT(f); return -1;
if (f->pos < 0) l = (*f->dfs->getc)(f->file);
return -1; if (l < 0) {
f->pos = -1;
l = (*f->dfs->getc)(f->file); return l;
if (l < 0) { }
f->pos = -1;
return l; h = (*f->dfs->getc)(f->file);
} if (h < 0) {
f->pos = -1;
h = (*f->dfs->getc)(f->file); return h;
if (h < 0) { }
f->pos = -1;
return h; f->pos += 2;
}
return l | (h << 8);
f->pos += 2; }
return l | (h << 8);
}
int dumbfile_mgetw(DUMBFILE *f)
{
int l, h;
int dumbfile_mgetw(DUMBFILE *f)
{ ASSERT(f);
int l, h;
if (f->pos < 0)
ASSERT(f); return -1;
if (f->pos < 0) h = (*f->dfs->getc)(f->file);
return -1; if (h < 0) {
f->pos = -1;
h = (*f->dfs->getc)(f->file); return h;
if (h < 0) { }
f->pos = -1;
return h; l = (*f->dfs->getc)(f->file);
} if (l < 0) {
f->pos = -1;
l = (*f->dfs->getc)(f->file); return l;
if (l < 0) { }
f->pos = -1;
return l; f->pos += 2;
}
return l | (h << 8);
f->pos += 2; }
return l | (h << 8);
}
long dumbfile_igetl(DUMBFILE *f)
{
unsigned long rv, b;
long dumbfile_igetl(DUMBFILE *f)
{ ASSERT(f);
unsigned long rv, b;
if (f->pos < 0)
ASSERT(f); return -1;
if (f->pos < 0) rv = (*f->dfs->getc)(f->file);
return -1; if ((signed long)rv < 0) {
f->pos = -1;
rv = (*f->dfs->getc)(f->file); return rv;
if ((signed long)rv < 0) { }
f->pos = -1;
return rv; b = (*f->dfs->getc)(f->file);
} if ((signed long)b < 0) {
f->pos = -1;
b = (*f->dfs->getc)(f->file); return b;
if ((signed long)b < 0) { }
f->pos = -1; rv |= b << 8;
return b;
} b = (*f->dfs->getc)(f->file);
rv |= b << 8; if ((signed long)b < 0) {
f->pos = -1;
b = (*f->dfs->getc)(f->file); return b;
if ((signed long)b < 0) { }
f->pos = -1; rv |= b << 16;
return b;
} b = (*f->dfs->getc)(f->file);
rv |= b << 16; if ((signed long)b < 0) {
f->pos = -1;
b = (*f->dfs->getc)(f->file); return b;
if ((signed long)b < 0) { }
f->pos = -1; rv |= b << 24;
return b;
} f->pos += 4;
rv |= b << 24;
return rv;
f->pos += 4; }
return rv;
}
long dumbfile_mgetl(DUMBFILE *f)
{
unsigned long rv, b;
long dumbfile_mgetl(DUMBFILE *f)
{ ASSERT(f);
unsigned long rv, b;
if (f->pos < 0)
ASSERT(f); return -1;
if (f->pos < 0) rv = (*f->dfs->getc)(f->file);
return -1; if ((signed long)rv < 0) {
f->pos = -1;
rv = (*f->dfs->getc)(f->file); return rv;
if ((signed long)rv < 0) { }
f->pos = -1; rv <<= 24;
return rv;
} b = (*f->dfs->getc)(f->file);
rv <<= 24; if ((signed long)b < 0) {
f->pos = -1;
b = (*f->dfs->getc)(f->file); return b;
if ((signed long)b < 0) { }
f->pos = -1; rv |= b << 16;
return b;
} b = (*f->dfs->getc)(f->file);
rv |= b << 16; if ((signed long)b < 0) {
f->pos = -1;
b = (*f->dfs->getc)(f->file); return b;
if ((signed long)b < 0) { }
f->pos = -1; rv |= b << 8;
return b;
} b = (*f->dfs->getc)(f->file);
rv |= b << 8; if ((signed long)b < 0) {
f->pos = -1;
b = (*f->dfs->getc)(f->file); return b;
if ((signed long)b < 0) { }
f->pos = -1; rv |= b;
return b;
} f->pos += 4;
rv |= b;
return rv;
f->pos += 4; }
return rv;
}
unsigned long dumbfile_cgetul(DUMBFILE *f)
{
unsigned long rv = 0;
unsigned long dumbfile_cgetul(DUMBFILE *f) int v;
{
unsigned long rv = 0; do {
int v; v = dumbfile_getc(f);
do { if (v < 0)
v = dumbfile_getc(f); return v;
if (v < 0) rv <<= 7;
return v; rv |= v & 0x7F;
} while (v & 0x80);
rv <<= 7;
rv |= v & 0x7F; return rv;
} while (v & 0x80); }
return rv;
}
signed long dumbfile_cgetsl(DUMBFILE *f)
{
unsigned long rv = dumbfile_cgetul(f);
signed long dumbfile_cgetsl(DUMBFILE *f)
{ if (f->pos < 0)
unsigned long rv = dumbfile_cgetul(f); return rv;
if (f->pos < 0) return (rv >> 1) | (rv << 31);
return rv; }
return (rv >> 1) | (rv << 31);
}
long dumbfile_getnc(char *ptr, long n, DUMBFILE *f)
{
long rv;
long dumbfile_getnc(char *ptr, long n, DUMBFILE *f)
{ ASSERT(f);
long rv; ASSERT(n >= 0);
ASSERT(f); if (f->pos < 0)
ASSERT(n >= 0); return -1;
if (f->pos < 0) if (f->dfs->getnc) {
return -1; rv = (*f->dfs->getnc)(ptr, n, f->file);
if (rv < n) {
if (f->dfs->getnc) { f->pos = -1;
rv = (*f->dfs->getnc)(ptr, n, f->file); return MAX(rv, 0);
if (rv < n) { }
f->pos = -1; } else {
return MAX(rv, 0); for (rv = 0; rv < n; rv++) {
} int c = (*f->dfs->getc)(f->file);
} else { if (c < 0) {
for (rv = 0; rv < n; rv++) { f->pos = -1;
int c = (*f->dfs->getc)(f->file); return rv;
if (c < 0) { }
f->pos = -1; *ptr++ = c;
return rv; }
} }
*ptr++ = c;
} f->pos += rv;
}
return rv;
f->pos += rv; }
return rv;
}
int dumbfile_seek(DUMBFILE *f, long n, int origin)
{
switch ( origin )
int dumbfile_error(DUMBFILE *f) {
{ case DFS_SEEK_CUR: n += f->pos; break;
ASSERT(f); case DFS_SEEK_END: n += (*f->dfs->get_size)(f->file); break;
}
return f->pos < 0; f->pos = n;
} return (*f->dfs->seek)(f->file, n);
}
int dumbfile_close(DUMBFILE *f)
{ long dumbfile_get_size(DUMBFILE *f)
int rv; {
return (*f->dfs->get_size)(f->file);
ASSERT(f); }
rv = f->pos < 0;
if (f->dfs->close) int dumbfile_error(DUMBFILE *f)
(*f->dfs->close)(f->file); {
ASSERT(f);
free(f);
return f->pos < 0;
return rv; }
}
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;
}

View file

@ -1,42 +1,42 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* loadduh.c - Code to read a DUH from a file, / / \ \ * loadduh.c - Code to read a DUH from a file, / / \ \
* opening and closing the file for | < / \_ * opening and closing the file for | < / \_
* you. | \/ /\ / * you. | \/ /\ /
* \_ / > / * \_ / > /
* By entheh. | \ / / * By entheh. | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
/* load_duh(): loads a .duh file, returning a pointer to a DUH struct. /* 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() * When you have finished with it, you must pass the pointer to unload_duh()
* so that the memory can be freed. * so that the memory can be freed.
*/ */
DUH *load_duh(const char *filename) DUH *load_duh(const char *filename)
{ {
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);
if (!f) if (!f)
return NULL; return NULL;
duh = read_duh(f); duh = read_duh(f);
dumbfile_close(f); dumbfile_close(f);
return duh; return duh;
} }

View file

@ -1,132 +1,151 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* makeduh.c - Function to construct a DUH from / / \ \ * makeduh.c - Function to construct a DUH from / / \ \
* its components. | < / \_ * its components. | < / \_
* | \/ /\ / * | \/ /\ /
* By entheh. \_ / > / * By entheh. \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
static DUH_SIGNAL *make_signal(DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata) static DUH_SIGNAL *make_signal(DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata)
{ {
DUH_SIGNAL *signal; DUH_SIGNAL *signal;
ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer)); ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer));
ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample); ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample);
signal = malloc(sizeof(*signal)); signal = malloc(sizeof(*signal));
if (!signal) { if (!signal) {
if (desc->unload_sigdata) if (desc->unload_sigdata)
if (sigdata) if (sigdata)
(*desc->unload_sigdata)(sigdata); (*desc->unload_sigdata)(sigdata);
return NULL; return NULL;
} }
signal->desc = desc; signal->desc = desc;
signal->sigdata = sigdata; signal->sigdata = sigdata;
return signal; return signal;
} }
DUH *make_duh( DUH *make_duh(
long length, long length,
int n_tags, int n_tags,
const char *const tags[][2], const char *const tags[][2],
int n_signals, int n_signals,
DUH_SIGTYPE_DESC *desc[], DUH_SIGTYPE_DESC *desc[],
sigdata_t *sigdata[] sigdata_t *sigdata[]
) )
{ {
DUH *duh = malloc(sizeof(*duh)); DUH *duh = malloc(sizeof(*duh));
int i; int i;
int fail; int fail;
if (duh) { if (duh) {
duh->n_signals = n_signals; duh->n_signals = n_signals;
duh->signal = malloc(n_signals * sizeof(*duh->signal)); duh->signal = malloc(n_signals * sizeof(*duh->signal));
if (!duh->signal) { if (!duh->signal) {
free(duh); free(duh);
duh = NULL; duh = NULL;
} }
} }
if (!duh) { if (!duh) {
for (i = 0; i < n_signals; i++) for (i = 0; i < n_signals; i++)
if (desc[i]->unload_sigdata) if (desc[i]->unload_sigdata)
if (sigdata[i]) if (sigdata[i])
(*desc[i]->unload_sigdata)(sigdata[i]); (*desc[i]->unload_sigdata)(sigdata[i]);
return NULL; return NULL;
} }
duh->n_tags = 0; duh->n_tags = 0;
duh->tag = NULL; duh->tag = NULL;
fail = 0; fail = 0;
for (i = 0; i < n_signals; i++) { for (i = 0; i < n_signals; i++) {
duh->signal[i] = make_signal(desc[i], sigdata[i]); duh->signal[i] = make_signal(desc[i], sigdata[i]);
if (!duh->signal[i]) if (!duh->signal[i])
fail = 1; fail = 1;
} }
if (fail) { if (fail) {
unload_duh(duh); unload_duh(duh);
return NULL; return NULL;
} }
duh->length = length; duh->length = length;
{ {
int mem = n_tags * 2; /* account for NUL terminators here */ int mem = n_tags * 2; /* account for NUL terminators here */
char *ptr; char *ptr;
for (i = 0; i < n_tags; i++) for (i = 0; i < n_tags; i++)
mem += strlen(tags[i][0]) + strlen(tags[i][1]); mem += strlen(tags[i][0]) + strlen(tags[i][1]);
if (mem <= 0) return duh; if (mem <= 0) return duh;
duh->tag = malloc(n_tags * sizeof(*duh->tag)); duh->tag = malloc(n_tags * sizeof(*duh->tag));
if (!duh->tag) return duh; if (!duh->tag) return duh;
duh->tag[0][0] = malloc(mem); duh->tag[0][0] = malloc(mem);
if (!duh->tag[0][0]) { if (!duh->tag[0][0]) {
free(duh->tag); free(duh->tag);
duh->tag = NULL; duh->tag = NULL;
return duh; return duh;
} }
duh->n_tags = n_tags; duh->n_tags = n_tags;
ptr = duh->tag[0][0]; ptr = duh->tag[0][0];
for (i = 0; i < n_tags; i++) { for (i = 0; i < n_tags; i++) {
duh->tag[i][0] = ptr; duh->tag[i][0] = ptr;
strcpy(ptr, tags[i][0]); strcpy(ptr, tags[i][0]);
ptr += strlen(tags[i][0]) + 1; ptr += strlen(tags[i][0]) + 1;
duh->tag[i][1] = ptr; duh->tag[i][1] = ptr;
strcpy(ptr, tags[i][1]); strcpy(ptr, tags[i][1]);
ptr += strlen(tags[i][1]) + 1; ptr += strlen(tags[i][1]) + 1;
} }
} }
return duh; 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;
}

View file

@ -1,44 +1,58 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* rawsig.c - Function to retrieve raw signal / / \ \ * rawsig.c - Function to retrieve raw signal / / \ \
* data from a DUH provided you know | < / \_ * data from a DUH provided you know | < / \_
* what type of signal it is. | \/ /\ / * what type of signal it is. | \/ /\ /
* \_ / > / * \_ / > /
* By entheh. | \ / / * By entheh. | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
/* You have to specify the type of sigdata, proving you know what to do with /* 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. * the pointer. If you get it wrong, you can expect NULL back.
*/ */
sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type) sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type)
{ {
DUH_SIGNAL *signal; int i;
DUH_SIGNAL *signal;
if (!duh) return NULL;
if (!duh) return NULL;
if ((unsigned int)sig >= (unsigned int)duh->n_signals) return NULL;
if ( sig >= 0 )
signal = duh->signal[sig]; {
if ((unsigned int)sig >= (unsigned int)duh->n_signals) return NULL;
if (signal && signal->desc->type == type)
return signal->sigdata; signal = duh->signal[sig];
return NULL; 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;
}

View file

@ -1,107 +1,107 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* readduh.c - Code to read a DUH from an open / / \ \ * readduh.c - Code to read a DUH from an open / / \ \
* file. | < / \_ * file. | < / \_
* | \/ /\ / * | \/ /\ /
* By entheh. \_ / > / * By entheh. \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
static DUH_SIGNAL *read_signal(DUH *duh, DUMBFILE *f) static DUH_SIGNAL *read_signal(DUH *duh, DUMBFILE *f)
{ {
DUH_SIGNAL *signal; DUH_SIGNAL *signal;
long type; long type;
signal = malloc(sizeof(*signal)); signal = malloc(sizeof(*signal));
if (!signal) if (!signal)
return NULL; return NULL;
type = dumbfile_mgetl(f); type = dumbfile_mgetl(f);
if (dumbfile_error(f)) { if (dumbfile_error(f)) {
free(signal); free(signal);
return NULL; return NULL;
} }
signal->desc = _dumb_get_sigtype_desc(type); signal->desc = _dumb_get_sigtype_desc(type);
if (!signal->desc) { if (!signal->desc) {
free(signal); free(signal);
return NULL; return NULL;
} }
if (signal->desc->load_sigdata) { if (signal->desc->load_sigdata) {
signal->sigdata = (*signal->desc->load_sigdata)(duh, f); signal->sigdata = (*signal->desc->load_sigdata)(duh, f);
if (!signal->sigdata) { if (!signal->sigdata) {
free(signal); free(signal);
return NULL; return NULL;
} }
} else } else
signal->sigdata = NULL; signal->sigdata = NULL;
return signal; return signal;
} }
/* read_duh(): reads a DUH from an already open DUMBFILE, and returns its /* read_duh(): reads a DUH from an already open DUMBFILE, and returns its
* pointer, or null on error. The file is not closed. * pointer, or null on error. The file is not closed.
*/ */
DUH *read_duh(DUMBFILE *f) DUH *read_duh(DUMBFILE *f)
{ {
DUH *duh; DUH *duh;
int i; int i;
if (dumbfile_mgetl(f) != DUH_SIGNATURE) if (dumbfile_mgetl(f) != DUH_SIGNATURE)
return NULL; return NULL;
duh = malloc(sizeof(*duh)); duh = malloc(sizeof(*duh));
if (!duh) if (!duh)
return NULL; return NULL;
duh->length = dumbfile_igetl(f); duh->length = dumbfile_igetl(f);
if (dumbfile_error(f) || duh->length <= 0) { if (dumbfile_error(f) || duh->length <= 0) {
free(duh); free(duh);
return NULL; return NULL;
} }
duh->n_signals = dumbfile_igetl(f); duh->n_signals = dumbfile_igetl(f);
if (dumbfile_error(f) || duh->n_signals <= 0) { if (dumbfile_error(f) || duh->n_signals <= 0) {
free(duh); free(duh);
return NULL; return NULL;
} }
duh->signal = malloc(sizeof(*duh->signal) * duh->n_signals); duh->signal = malloc(sizeof(*duh->signal) * duh->n_signals);
if (!duh->signal) { if (!duh->signal) {
free(duh); free(duh);
return NULL; return NULL;
} }
for (i = 0; i < duh->n_signals; i++) for (i = 0; i < duh->n_signals; i++)
duh->signal[i] = NULL; duh->signal[i] = NULL;
for (i = 0; i < duh->n_signals; i++) { for (i = 0; i < duh->n_signals; i++) {
if (!(duh->signal[i] = read_signal(duh, f))) { if (!(duh->signal[i] = read_signal(duh, f))) {
unload_duh(duh); unload_duh(duh);
return NULL; return NULL;
} }
} }
return duh; return duh;
} }

View file

@ -1,104 +1,104 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* register.c - Signal type registration. / / \ \ * register.c - Signal type registration. / / \ \
* | < / \_ * | < / \_
* By entheh. | \/ /\ / * By entheh. | \/ /\ /
* \_ / > / * \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
static DUH_SIGTYPE_DESC_LINK *sigtype_desc = NULL; static DUH_SIGTYPE_DESC_LINK *sigtype_desc = NULL;
static DUH_SIGTYPE_DESC_LINK **sigtype_desc_tail = &sigtype_desc; static DUH_SIGTYPE_DESC_LINK **sigtype_desc_tail = &sigtype_desc;
/* destroy_sigtypes(): frees all memory allocated while registering signal /* destroy_sigtypes(): frees all memory allocated while registering signal
* types. This function is set up to be called by dumb_exit(). * types. This function is set up to be called by dumb_exit().
*/ */
static void destroy_sigtypes(void) static void destroy_sigtypes(void)
{ {
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc, *next; DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc, *next;
sigtype_desc = NULL; sigtype_desc = NULL;
sigtype_desc_tail = &sigtype_desc; sigtype_desc_tail = &sigtype_desc;
while (desc_link) { while (desc_link) {
next = desc_link->next; next = desc_link->next;
free(desc_link); free(desc_link);
desc_link = next; desc_link = next;
} }
} }
/* dumb_register_sigtype(): registers a new signal type with DUMB. The signal /* 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 * 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 * 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 * signal's behaviour is defined by four functions, whose pointers you pass
* here. See the documentation for details. * here. See the documentation for details.
* *
* If a DUH tries to use a signal that has not been registered using this * 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. * function, then the library will fail to load the DUH.
*/ */
void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc) void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc)
{ {
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc; DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc;
ASSERT((desc->load_sigdata && desc->unload_sigdata) || (!desc->load_sigdata && !desc->unload_sigdata)); 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->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer));
ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample); ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample);
if (desc_link) { if (desc_link) {
do { do {
if (desc_link->desc->type == desc->type) { if (desc_link->desc->type == desc->type) {
desc_link->desc = desc; desc_link->desc = desc;
return; return;
} }
desc_link = desc_link->next; desc_link = desc_link->next;
} while (desc_link); } while (desc_link);
} else } else
dumb_atexit(&destroy_sigtypes); dumb_atexit(&destroy_sigtypes);
desc_link = *sigtype_desc_tail = malloc(sizeof(DUH_SIGTYPE_DESC_LINK)); desc_link = *sigtype_desc_tail = malloc(sizeof(DUH_SIGTYPE_DESC_LINK));
if (!desc_link) if (!desc_link)
return; return;
desc_link->next = NULL; desc_link->next = NULL;
sigtype_desc_tail = &desc_link->next; sigtype_desc_tail = &desc_link->next;
desc_link->desc = desc; desc_link->desc = desc;
} }
/* _dumb_get_sigtype_desc(): searches the registered functions for a signal /* _dumb_get_sigtype_desc(): searches the registered functions for a signal
* type matching the parameter. If such a sigtype is found, it returns a * type matching the parameter. If such a sigtype is found, it returns a
* pointer to a sigtype descriptor containing the necessary functions to * pointer to a sigtype descriptor containing the necessary functions to
* manage the signal. If none is found, it returns NULL. * manage the signal. If none is found, it returns NULL.
*/ */
DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type) DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type)
{ {
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc; DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc;
while (desc_link && desc_link->desc->type != type) while (desc_link && desc_link->desc->type != type)
desc_link = desc_link->next; desc_link = desc_link->next;
return desc_link ? desc_link->desc : NULL; return desc_link ? desc_link->desc : NULL;
} }

View file

@ -1,184 +1,184 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* rendduh.c - Functions for rendering a DUH into / / \ \ * rendduh.c - Functions for rendering a DUH into / / \ \
* an end-user sample format. | < / \_ * an end-user sample format. | < / \_
* | \/ /\ / * | \/ /\ /
* By entheh. \_ / > / * By entheh. \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
/* On the x86, we can use some tricks to speed stuff up */ /* On the x86, we can use some tricks to speed stuff up */
#if (defined _MSC_VER) || (defined __DJGPP__) || (defined __MINGW__) #if (defined _MSC_VER) || (defined __DJGPP__) || (defined __MINGW__)
// Can't we detect Linux and other x86 platforms here? :/ // Can't we detect Linux and other x86 platforms here? :/
#define FAST_MID(var, min, max) { \ #define FAST_MID(var, min, max) { \
var -= (min); \ var -= (min); \
var &= (~var) >> (sizeof(var) * CHAR_BIT - 1); \ var &= (~var) >> (sizeof(var) * CHAR_BIT - 1); \
var += (min); \ var += (min); \
var -= (max); \ var -= (max); \
var &= var >> (sizeof(var) * CHAR_BIT - 1); \ var &= var >> (sizeof(var) * CHAR_BIT - 1); \
var += (max); \ var += (max); \
} }
#define CONVERT8(src, pos, signconv) { \ #define CONVERT8(src, pos, signconv) { \
signed int f = (src + 0x8000) >> 16; \ signed int f = (src + 0x8000) >> 16; \
FAST_MID(f, -128, 127); \ FAST_MID(f, -128, 127); \
((char*)sptr)[pos] = (char)f ^ signconv; \ ((char*)sptr)[pos] = (char)f ^ signconv; \
} }
#define CONVERT16(src, pos, signconv) { \ #define CONVERT16(src, pos, signconv) { \
signed int f = (src + 0x80) >> 8; \ signed int f = (src + 0x80) >> 8; \
FAST_MID(f, -32768, 32767); \ FAST_MID(f, -32768, 32767); \
((short*)sptr)[pos] = (short)(f ^ signconv); \ ((short*)sptr)[pos] = (short)(f ^ signconv); \
} }
#else #else
#define CONVERT8(src, pos, signconv) \ #define CONVERT8(src, pos, signconv) \
{ \ { \
signed int f = (src + 0x8000) >> 16; \ signed int f = (src + 0x8000) >> 16; \
f = MID(-128, f, 127); \ f = MID(-128, f, 127); \
((char *)sptr)[pos] = (char)f ^ signconv; \ ((char *)sptr)[pos] = (char)f ^ signconv; \
} }
#define CONVERT16(src, pos, signconv) \ #define CONVERT16(src, pos, signconv) \
{ \ { \
signed int f = (src + 0x80) >> 8; \ signed int f = (src + 0x80) >> 8; \
f = MID(-32768, f, 32767); \ f = MID(-32768, f, 32767); \
((short *)sptr)[pos] = (short)(f ^ signconv); \ ((short *)sptr)[pos] = (short)(f ^ signconv); \
} }
#endif #endif
/* DEPRECATED */ /* DEPRECATED */
DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos) DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos)
{ {
return duh_start_sigrenderer(duh, 0, n_channels, pos); return duh_start_sigrenderer(duh, 0, n_channels, pos);
} }
long duh_render( long duh_render(
DUH_SIGRENDERER *sigrenderer, DUH_SIGRENDERER *sigrenderer,
int bits, int unsign, int bits, int unsign,
float volume, float delta, float volume, float delta,
long size, void *sptr long size, void *sptr
) )
{ {
long n; long n;
sample_t **sampptr; sample_t **sampptr;
int n_channels; int n_channels;
ASSERT(bits == 8 || bits == 16); ASSERT(bits == 8 || bits == 16);
ASSERT(sptr); ASSERT(sptr);
if (!sigrenderer) if (!sigrenderer)
return 0; return 0;
n_channels = duh_sigrenderer_get_n_channels(sigrenderer); n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
ASSERT(n_channels > 0); ASSERT(n_channels > 0);
/* This restriction will be removed when need be. At the moment, tightly /* This restriction will be removed when need be. At the moment, tightly
* optimised loops exist for exactly one or two channels. * optimised loops exist for exactly one or two channels.
*/ */
ASSERT(n_channels <= 2); ASSERT(n_channels <= 2);
sampptr = allocate_sample_buffer(n_channels, size); sampptr = allocate_sample_buffer(n_channels, size);
if (!sampptr) if (!sampptr)
return 0; return 0;
dumb_silence(sampptr[0], n_channels * size); dumb_silence(sampptr[0], n_channels * size);
size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr); size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
if (bits == 16) { if (bits == 16) {
int signconv = unsign ? 0x8000 : 0x0000; int signconv = unsign ? 0x8000 : 0x0000;
for (n = 0; n < size * n_channels; n++) { for (n = 0; n < size * n_channels; n++) {
CONVERT16(sampptr[0][n], n, signconv); CONVERT16(sampptr[0][n], n, signconv);
} }
} else { } else {
char signconv = unsign ? 0x80 : 0x00; char signconv = unsign ? 0x80 : 0x00;
for (n = 0; n < size * n_channels; n++) { for (n = 0; n < size * n_channels; n++) {
CONVERT8(sampptr[0][n], n, signconv); CONVERT8(sampptr[0][n], n, signconv);
} }
} }
destroy_sample_buffer(sampptr); destroy_sample_buffer(sampptr);
return size; return size;
} }
/* DEPRECATED */ /* DEPRECATED */
int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr) int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr)
{ {
return duh_sigrenderer_get_n_channels(dr); return duh_sigrenderer_get_n_channels(dr);
} }
/* DEPRECATED */ /* DEPRECATED */
long duh_renderer_get_position(DUH_SIGRENDERER *dr) long duh_renderer_get_position(DUH_SIGRENDERER *dr)
{ {
return duh_sigrenderer_get_position(dr); return duh_sigrenderer_get_position(dr);
} }
/* DEPRECATED */ /* DEPRECATED */
void duh_end_renderer(DUH_SIGRENDERER *dr) void duh_end_renderer(DUH_SIGRENDERER *dr)
{ {
duh_end_sigrenderer(dr); duh_end_sigrenderer(dr);
} }
/* DEPRECATED */ /* DEPRECATED */
DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer) DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer)
{ {
return sigrenderer; return sigrenderer;
} }
/* DEPRECATED */ /* DEPRECATED */
DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr) DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr)
{ {
return dr; return dr;
} }
/* DEPRECATED */ /* DEPRECATED */
DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr) DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr)
{ {
return dr; return dr;
} }

View file

@ -1,344 +1,352 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* rendsig.c - Wrappers to render samples from / / \ \ * rendsig.c - Wrappers to render samples from / / \ \
* the signals in a DUH. | < / \_ * the signals in a DUH. | < / \_
* | \/ /\ / * | \/ /\ /
* By entheh. \_ / > / * By entheh. \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
struct DUH_SIGRENDERER struct DUH_SIGRENDERER
{ {
DUH_SIGTYPE_DESC *desc; DUH_SIGTYPE_DESC *desc;
sigrenderer_t *sigrenderer; sigrenderer_t *sigrenderer;
int n_channels; int n_channels;
long pos; long pos;
int subpos; int subpos;
DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback; DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback;
void *callback_data; void *callback_data;
}; };
DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos) DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos)
{ {
DUH_SIGRENDERER *sigrenderer; DUH_SIGRENDERER *sigrenderer;
DUH_SIGNAL *signal; DUH_SIGNAL *signal;
DUH_START_SIGRENDERER proc; DUH_START_SIGRENDERER proc;
if (!duh) if (!duh)
return NULL; return NULL;
if ((unsigned int)sig >= (unsigned int)duh->n_signals) if ((unsigned int)sig >= (unsigned int)duh->n_signals)
return NULL; return NULL;
signal = duh->signal[sig]; signal = duh->signal[sig];
if (!signal) if (!signal)
return NULL; return NULL;
sigrenderer = malloc(sizeof(*sigrenderer)); sigrenderer = malloc(sizeof(*sigrenderer));
if (!sigrenderer) if (!sigrenderer)
return NULL; return NULL;
sigrenderer->desc = signal->desc; sigrenderer->desc = signal->desc;
proc = sigrenderer->desc->start_sigrenderer; proc = sigrenderer->desc->start_sigrenderer;
if (proc) { if (proc) {
duh->signal[sig] = NULL; duh->signal[sig] = NULL;
sigrenderer->sigrenderer = (*proc)(duh, signal->sigdata, n_channels, pos); sigrenderer->sigrenderer = (*proc)(duh, signal->sigdata, n_channels, pos);
duh->signal[sig] = signal; duh->signal[sig] = signal;
if (!sigrenderer->sigrenderer) { if (!sigrenderer->sigrenderer) {
free(sigrenderer); free(sigrenderer);
return NULL; return NULL;
} }
} else } else
sigrenderer->sigrenderer = NULL; sigrenderer->sigrenderer = NULL;
sigrenderer->n_channels = n_channels; sigrenderer->n_channels = n_channels;
sigrenderer->pos = pos; sigrenderer->pos = pos;
sigrenderer->subpos = 0; sigrenderer->subpos = 0;
sigrenderer->callback = NULL; sigrenderer->callback = NULL;
return sigrenderer; return sigrenderer;
} }
#include <stdio.h> #include <stdio.h>
void duh_sigrenderer_set_callback( void duh_sigrenderer_set_callback(
DUH_SIGRENDERER *sigrenderer, DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER_CALLBACK callback, void *data DUH_SIGRENDERER_CALLBACK callback, void *data
) )
{ {
(void)sigrenderer; (void)sigrenderer;
(void)callback; (void)callback;
(void)data; (void)data;
fprintf(stderr, /*fprintf(stderr,
"Call to deprecated function duh_sigrenderer_set_callback(). The callback\n" "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"); "was not installed. See dumb/docs/deprec.txt for how to fix this.\n");*/
} }
void duh_sigrenderer_set_analyser_callback( void duh_sigrenderer_set_analyser_callback(
DUH_SIGRENDERER *sigrenderer, DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data
) )
{ {
(void)sigrenderer; (void)sigrenderer;
(void)callback; (void)callback;
(void)data; (void)data;
fprintf(stderr, fprintf(stderr,
"Call to deprecated function duh_sigrenderer_set_analyser_callback(). The\n" "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"); "callback was not installed. See dumb/docs/deprec.txt for how to fix this.\n");
} }
void duh_sigrenderer_set_sample_analyser_callback( void duh_sigrenderer_set_sample_analyser_callback(
DUH_SIGRENDERER *sigrenderer, DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data
) )
{ {
if (sigrenderer) { if (sigrenderer) {
sigrenderer->callback = callback; sigrenderer->callback = callback;
sigrenderer->callback_data = data; sigrenderer->callback_data = data;
} }
} }
int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer) int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer)
{ {
return sigrenderer ? sigrenderer->n_channels : 0; return sigrenderer ? sigrenderer->n_channels : 0;
} }
long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer) long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer)
{ {
return sigrenderer ? sigrenderer->pos : -1; DUH_SIGRENDERER_GET_POSITION proc;
}
if (!sigrenderer) return -1;
proc = sigrenderer->desc->sigrenderer_get_position;
void duh_sigrenderer_set_sigparam( if (proc)
DUH_SIGRENDERER *sigrenderer, return (*proc)(sigrenderer->sigrenderer);
unsigned char id, long value else
) return sigrenderer->pos;
{ }
DUH_SIGRENDERER_SET_SIGPARAM proc;
if (!sigrenderer) return;
void duh_sigrenderer_set_sigparam(
proc = sigrenderer->desc->sigrenderer_set_sigparam; DUH_SIGRENDERER *sigrenderer,
if (proc) unsigned char id, long value
(*proc)(sigrenderer->sigrenderer, id, value); )
else {
TRACE("Parameter #%d = %ld for signal %c%c%c%c, which does not take parameters.\n", DUH_SIGRENDERER_SET_SIGPARAM proc;
(int)id,
value, if (!sigrenderer) return;
(int)(sigrenderer->desc->type >> 24),
(int)(sigrenderer->desc->type >> 16), proc = sigrenderer->desc->sigrenderer_set_sigparam;
(int)(sigrenderer->desc->type >> 8), if (proc)
(int)(sigrenderer->desc->type)); (*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,
long duh_sigrenderer_generate_samples( (int)(sigrenderer->desc->type >> 24),
DUH_SIGRENDERER *sigrenderer, (int)(sigrenderer->desc->type >> 16),
float volume, float delta, (int)(sigrenderer->desc->type >> 8),
long size, sample_t **samples (int)(sigrenderer->desc->type));
) }
{
long rendered;
LONG_LONG t;
long duh_sigrenderer_generate_samples(
if (!sigrenderer) return 0; DUH_SIGRENDERER *sigrenderer,
float volume, float delta,
rendered = (*sigrenderer->desc->sigrenderer_generate_samples) long size, sample_t **samples
(sigrenderer->sigrenderer, volume, delta, size, samples); )
{
if (rendered) { long rendered;
if (sigrenderer->callback) LONG_LONG t;
(*sigrenderer->callback)(sigrenderer->callback_data,
(const sample_t *const *)samples, sigrenderer->n_channels, rendered); if (!sigrenderer) return 0;
t = sigrenderer->subpos + (LONG_LONG)(delta * 65536.0 + 0.5) * rendered; rendered = (*sigrenderer->desc->sigrenderer_generate_samples)
(sigrenderer->sigrenderer, volume, delta, size, samples);
sigrenderer->pos += (long)(t >> 16);
sigrenderer->subpos = (int)t & 65535; if (rendered) {
} if (sigrenderer->callback)
(*sigrenderer->callback)(sigrenderer->callback_data,
return rendered; (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);
/* DEPRECATED */ sigrenderer->subpos = (int)t & 65535;
long duh_sigrenderer_get_samples( }
DUH_SIGRENDERER *sigrenderer,
float volume, float delta, return rendered;
long size, sample_t **samples }
)
{
sample_t **s;
long rendered; /* DEPRECATED */
long i; long duh_sigrenderer_get_samples(
int j; DUH_SIGRENDERER *sigrenderer,
if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL); float volume, float delta,
s = allocate_sample_buffer(sigrenderer->n_channels, size); long size, sample_t **samples
if (!s) return 0; )
dumb_silence(s[0], sigrenderer->n_channels * size); {
rendered = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, s); sample_t **s;
for (j = 0; j < sigrenderer->n_channels; j++) long rendered;
for (i = 0; i < rendered; i++) long i;
samples[j][i] += s[0][i*sigrenderer->n_channels+j]; int j;
destroy_sample_buffer(s); if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL);
return rendered; 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++)
/* DEPRECATED */ for (i = 0; i < rendered; i++)
long duh_render_signal( samples[j][i] += s[0][i*sigrenderer->n_channels+j];
DUH_SIGRENDERER *sigrenderer, destroy_sample_buffer(s);
float volume, float delta, return rendered;
long size, sample_t **samples }
)
{
sample_t **s;
long rendered; /* DEPRECATED */
long i; long duh_render_signal(
int j; DUH_SIGRENDERER *sigrenderer,
if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL); float volume, float delta,
s = allocate_sample_buffer(sigrenderer->n_channels, size); long size, sample_t **samples
if (!s) return 0; )
dumb_silence(s[0], sigrenderer->n_channels * size); {
rendered = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, s); sample_t **s;
for (j = 0; j < sigrenderer->n_channels; j++) long rendered;
for (i = 0; i < rendered; i++) long i;
samples[j][i] += s[0][i*sigrenderer->n_channels+j] >> 8; int j;
destroy_sample_buffer(s); if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL);
return rendered; 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++)
void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples) for (i = 0; i < rendered; i++)
{ samples[j][i] += s[0][i*sigrenderer->n_channels+j] >> 8;
if (sigrenderer) destroy_sample_buffer(s);
(*sigrenderer->desc->sigrenderer_get_current_sample)(sigrenderer->sigrenderer, volume, samples); return rendered;
} }
void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer) void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples)
{ {
if (sigrenderer) { if (sigrenderer)
if (sigrenderer->desc->end_sigrenderer) (*sigrenderer->desc->sigrenderer_get_current_sample)(sigrenderer->sigrenderer, volume, samples);
if (sigrenderer->sigrenderer) }
(*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
free(sigrenderer);
} void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer)
} {
if (sigrenderer) {
if (sigrenderer->desc->end_sigrenderer)
if (sigrenderer->sigrenderer)
DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos) (*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
{
DUH_SIGRENDERER *sigrenderer; free(sigrenderer);
}
if (desc->start_sigrenderer && !vsigrenderer) return NULL; }
sigrenderer = malloc(sizeof(*sigrenderer));
if (!sigrenderer) {
if (desc->end_sigrenderer) DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos)
if (vsigrenderer) {
(*desc->end_sigrenderer)(vsigrenderer); DUH_SIGRENDERER *sigrenderer;
return NULL;
} if (desc->start_sigrenderer && !vsigrenderer) return NULL;
sigrenderer->desc = desc; sigrenderer = malloc(sizeof(*sigrenderer));
sigrenderer->sigrenderer = vsigrenderer; if (!sigrenderer) {
if (desc->end_sigrenderer)
sigrenderer->n_channels = n_channels; if (vsigrenderer)
(*desc->end_sigrenderer)(vsigrenderer);
sigrenderer->pos = pos; return NULL;
sigrenderer->subpos = 0; }
sigrenderer->callback = NULL; sigrenderer->desc = desc;
sigrenderer->sigrenderer = vsigrenderer;
return sigrenderer;
} sigrenderer->n_channels = n_channels;
sigrenderer->pos = pos;
sigrenderer->subpos = 0;
sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
{ sigrenderer->callback = NULL;
if (sigrenderer && sigrenderer->desc->type == type)
return sigrenderer->sigrenderer; return sigrenderer;
}
return NULL;
}
sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
{
#if 0 if (sigrenderer && sigrenderer->desc->type == type)
// This function is disabled because we don't know whether we want to destroy return sigrenderer->sigrenderer;
// 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 return NULL;
// 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 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
if (sigrenderer) { // the function at all. Who would want to keep an IT_SIGRENDERER (for
if (sigrenderer->desc->end_sigrenderer) // instance) without keeping the DUH_SIGRENDERER?
if (sigrenderer->sigrenderer) sigrenderer_t *duh_decompose_to_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
(*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer); {
if (sigrenderer && sigrenderer->desc->type == type) {
free(sigrenderer);
}
if (sigrenderer) {
if (sigrenderer->desc->end_sigrenderer)
if (sigrenderer->sigrenderer)
(*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
return sigrenderer->sigrenderer; free(sigrenderer);
} }
return NULL;
}
#endif
return sigrenderer->sigrenderer;
}
return NULL;
}
#endif

View file

@ -1,64 +1,64 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* unload.c - Code to free a DUH from memory. / / \ \ * unload.c - Code to free a DUH from memory. / / \ \
* | < / \_ * | < / \_
* By entheh. | \/ /\ / * By entheh. | \/ /\ /
* \_ / > / * \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
static void destroy_signal(DUH_SIGNAL *signal) static void destroy_signal(DUH_SIGNAL *signal)
{ {
if (signal) { if (signal) {
if (signal->desc) if (signal->desc)
if (signal->desc->unload_sigdata) if (signal->desc->unload_sigdata)
if (signal->sigdata) if (signal->sigdata)
(*signal->desc->unload_sigdata)(signal->sigdata); (*signal->desc->unload_sigdata)(signal->sigdata);
free(signal); free(signal);
} }
} }
/* unload_duh(): destroys a DUH struct. You must call this for every DUH /* unload_duh(): destroys a DUH struct. You must call this for every DUH
* struct created, when you've finished with it. * struct created, when you've finished with it.
*/ */
void unload_duh(DUH *duh) void unload_duh(DUH *duh)
{ {
int i; int i;
if (duh) { if (duh) {
if (duh->signal) { if (duh->signal) {
for (i = 0; i < duh->n_signals; i++) for (i = 0; i < duh->n_signals; i++)
destroy_signal(duh->signal[i]); destroy_signal(duh->signal[i]);
free(duh->signal); free(duh->signal);
} }
if (duh->tag) { if (duh->tag) {
if (duh->tag[0][0]) if (duh->tag[0][0])
free(duh->tag[0][0]); free(duh->tag[0][0]);
free(duh->tag); free(duh->tag);
} }
free(duh); free(duh);
} }
} }

View 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++;
}
}
}

View 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;
}

View file

@ -1,281 +1,281 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* clickrem.c - Click removal helpers. / / \ \ * clickrem.c - Click removal helpers. / / \ \
* | < / \_ * | < / \_
* By entheh. | \/ /\ / * By entheh. | \/ /\ /
* \_ / > / * \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include "dumb.h" #include "dumb.h"
typedef struct DUMB_CLICK DUMB_CLICK; typedef struct DUMB_CLICK DUMB_CLICK;
struct DUMB_CLICK_REMOVER struct DUMB_CLICK_REMOVER
{ {
DUMB_CLICK *click; DUMB_CLICK *click;
int n_clicks; int n_clicks;
int offset; int offset;
}; };
struct DUMB_CLICK struct DUMB_CLICK
{ {
DUMB_CLICK *next; DUMB_CLICK *next;
long pos; long pos;
sample_t step; sample_t step;
}; };
DUMB_CLICK_REMOVER *dumb_create_click_remover(void) DUMB_CLICK_REMOVER *dumb_create_click_remover(void)
{ {
DUMB_CLICK_REMOVER *cr = malloc(sizeof(*cr)); DUMB_CLICK_REMOVER *cr = malloc(sizeof(*cr));
if (!cr) return NULL; if (!cr) return NULL;
cr->click = NULL; cr->click = NULL;
cr->n_clicks = 0; cr->n_clicks = 0;
cr->offset = 0; cr->offset = 0;
return cr; return cr;
} }
void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step) void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step)
{ {
DUMB_CLICK *click; DUMB_CLICK *click;
ASSERT(pos >= 0); ASSERT(pos >= 0);
if (!cr || !step) return; if (!cr || !step) return;
if (pos == 0) { if (pos == 0) {
cr->offset -= step; cr->offset -= step;
return; return;
} }
click = malloc(sizeof(*click)); click = malloc(sizeof(*click));
if (!click) return; if (!click) return;
click->pos = pos; click->pos = pos;
click->step = step; click->step = step;
click->next = cr->click; click->next = cr->click;
cr->click = click; cr->click = click;
cr->n_clicks++; cr->n_clicks++;
} }
static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks) static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks)
{ {
int i; int i;
DUMB_CLICK *c1, *c2, **cp; DUMB_CLICK *c1, *c2, **cp;
if (n_clicks <= 1) return click; if (n_clicks <= 1) return click;
/* Split the list into two */ /* Split the list into two */
c1 = click; c1 = click;
cp = &c1; cp = &c1;
for (i = 0; i < n_clicks; i += 2) cp = &(*cp)->next; for (i = 0; i < n_clicks; i += 2) cp = &(*cp)->next;
c2 = *cp; c2 = *cp;
*cp = NULL; *cp = NULL;
/* Sort the sublists */ /* Sort the sublists */
c1 = dumb_click_mergesort(c1, (n_clicks + 1) >> 1); c1 = dumb_click_mergesort(c1, (n_clicks + 1) >> 1);
c2 = dumb_click_mergesort(c2, n_clicks >> 1); c2 = dumb_click_mergesort(c2, n_clicks >> 1);
/* Merge them */ /* Merge them */
cp = &click; cp = &click;
while (c1 && c2) { while (c1 && c2) {
if (c1->pos > c2->pos) { if (c1->pos > c2->pos) {
*cp = c2; *cp = c2;
c2 = c2->next; c2 = c2->next;
} else { } else {
*cp = c1; *cp = c1;
c1 = c1->next; c1 = c1->next;
} }
cp = &(*cp)->next; cp = &(*cp)->next;
} }
if (c2) if (c2)
*cp = c2; *cp = c2;
else else
*cp = c1; *cp = c1;
return click; return click;
} }
void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, int step, float halflife) void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, int step, float halflife)
{ {
DUMB_CLICK *click; DUMB_CLICK *click;
long pos = 0; long pos = 0;
int offset; int offset;
int factor; int factor;
if (!cr) return; if (!cr) return;
factor = (int)floor(pow(0.5, 1.0/halflife) * (1U << 31)); factor = (int)floor(pow(0.5, 1.0/halflife) * (1U << 31));
click = dumb_click_mergesort(cr->click, cr->n_clicks); click = dumb_click_mergesort(cr->click, cr->n_clicks);
cr->click = NULL; cr->click = NULL;
cr->n_clicks = 0; cr->n_clicks = 0;
length *= step; length *= step;
while (click) { while (click) {
DUMB_CLICK *next = click->next; DUMB_CLICK *next = click->next;
int end = click->pos * step; int end = click->pos * step;
ASSERT(end <= length); ASSERT(end <= length);
offset = cr->offset; offset = cr->offset;
if (offset < 0) { if (offset < 0) {
offset = -offset; offset = -offset;
while (pos < end) { while (pos < end) {
samples[pos] -= offset; samples[pos] -= offset;
offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); offset = (int)(((LONG_LONG)(offset << 1) * factor) >> 32);
pos += step; pos += step;
} }
offset = -offset; offset = -offset;
} else { } else {
while (pos < end) { while (pos < end) {
samples[pos] += offset; samples[pos] += offset;
offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); offset = (int)(((LONG_LONG)(offset << 1) * factor) >> 32);
pos += step; pos += step;
} }
} }
cr->offset = offset - click->step; cr->offset = offset - click->step;
free(click); free(click);
click = next; click = next;
} }
offset = cr->offset; offset = cr->offset;
if (offset < 0) { if (offset < 0) {
offset = -offset; offset = -offset;
while (pos < length) { while (pos < length) {
samples[pos] -= offset; samples[pos] -= offset;
offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
pos += step; pos += step;
} }
offset = -offset; offset = -offset;
} else { } else {
while (pos < length) { while (pos < length) {
samples[pos] += offset; samples[pos] += offset;
offset = (int)((LONG_LONG)(offset << 1) * factor >> 32); offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
pos += step; pos += step;
} }
} }
cr->offset = offset; cr->offset = offset;
} }
sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr) sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr)
{ {
return cr ? cr->offset : 0; return cr ? cr->offset : 0;
} }
void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr) void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr)
{ {
if (cr) { if (cr) {
DUMB_CLICK *click = cr->click; DUMB_CLICK *click = cr->click;
while (click) { while (click) {
DUMB_CLICK *next = click->next; DUMB_CLICK *next = click->next;
free(click); free(click);
click = next; click = next;
} }
free(cr); free(cr);
} }
} }
DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n) DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n)
{ {
int i; int i;
DUMB_CLICK_REMOVER **cr; DUMB_CLICK_REMOVER **cr;
if (n <= 0) return NULL; if (n <= 0) return NULL;
cr = malloc(n * sizeof(*cr)); cr = malloc(n * sizeof(*cr));
if (!cr) return NULL; if (!cr) return NULL;
for (i = 0; i < n; i++) cr[i] = dumb_create_click_remover(); for (i = 0; i < n; i++) cr[i] = dumb_create_click_remover();
return cr; return cr;
} }
void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step) void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
{ {
if (cr) { if (cr) {
int i; int i;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
dumb_record_click(cr[i], pos, step[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) void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
{ {
if (cr) { if (cr) {
int i; int i;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
dumb_record_click(cr[i], pos, -step[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) void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife)
{ {
if (cr) { if (cr) {
int i; int i;
for (i = 0; i < n >> 1; 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], samples[i], length, 2, halflife);
dumb_remove_clicks(cr[(i << 1) + 1], samples[i] + 1, length, 2, halflife); dumb_remove_clicks(cr[(i << 1) + 1], samples[i] + 1, length, 2, halflife);
} }
if (n & 1) if (n & 1)
dumb_remove_clicks(cr[i << 1], samples[i], length, 1, halflife); 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) void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset)
{ {
if (cr) { if (cr) {
int i; int i;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
if (cr[i]) offset[i] += cr[i]->offset; if (cr[i]) offset[i] += cr[i]->offset;
} }
} }
void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr) void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr)
{ {
if (cr) { if (cr) {
int i; int i;
for (i = 0; i < n; i++) dumb_destroy_click_remover(cr[i]); for (i = 0; i < n; i++) dumb_destroy_click_remover(cr[i]);
free(cr); free(cr);
} }
} }

View 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;
}
}

View 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;
}
}

View 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 );
}
}
}
}

View file

@ -1,96 +1,117 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* memfile.c - Module for reading data from / / \ \ * memfile.c - Module for reading data from / / \ \
* memory using a DUMBFILE. | < / \_ * memory using a DUMBFILE. | < / \_
* | \/ /\ / * | \/ /\ /
* By entheh. \_ / > / * By entheh. \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "dumb.h" #include "dumb.h"
typedef struct MEMFILE MEMFILE; typedef struct MEMFILE MEMFILE;
struct MEMFILE struct MEMFILE
{ {
const char *ptr; const char *ptr, *ptr_begin;
long left; long left, size;
}; };
static int dumb_memfile_skip(void *f, long n) static int dumb_memfile_skip(void *f, long n)
{ {
MEMFILE *m = f; MEMFILE *m = f;
if (n > m->left) return -1; if (n > m->left) return -1;
m->ptr += n; m->ptr += n;
m->left -= n; m->left -= n;
return 0; return 0;
} }
static int dumb_memfile_getc(void *f) static int dumb_memfile_getc(void *f)
{ {
MEMFILE *m = f; MEMFILE *m = f;
if (m->left <= 0) return -1; if (m->left <= 0) return -1;
m->left--; m->left--;
return *(const unsigned char *)m->ptr++; return *(const unsigned char *)m->ptr++;
} }
static long dumb_memfile_getnc(char *ptr, long n, void *f) static long dumb_memfile_getnc(char *ptr, long n, void *f)
{ {
MEMFILE *m = f; MEMFILE *m = f;
if (n > m->left) n = m->left; if (n > m->left) n = m->left;
memcpy(ptr, m->ptr, n); memcpy(ptr, m->ptr, n);
m->ptr += n; m->ptr += n;
m->left -= n; m->left -= n;
return n; return n;
} }
static void dumb_memfile_close(void *f) static void dumb_memfile_close(void *f)
{ {
free(f); free(f);
} }
static int dumb_memfile_seek(void *f, long n)
static DUMBFILE_SYSTEM memfile_dfs = { {
NULL, MEMFILE *m = f;
&dumb_memfile_skip,
&dumb_memfile_getc, m->ptr = m->ptr_begin + n;
&dumb_memfile_getnc, m->left = m->size - n;
&dumb_memfile_close
}; return 0;
}
DUMBFILE *dumbfile_open_memory(const char *data, long size) static long dumb_memfile_get_size(void *f)
{ {
MEMFILE *m = malloc(sizeof(*m)); MEMFILE *m = f;
if (!m) return NULL; return m->size;
}
m->ptr = data;
m->left = size;
static const DUMBFILE_SYSTEM memfile_dfs = {
return dumbfile_open_ex(m, &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);
}

View file

@ -1,134 +1,179 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* resamp2.inc - Resampling helper template. / / \ \ * resamp2.inc - Resampling helper template. / / \ \
* | < / \_ * | < / \_
* By Bob and entheh. | \/ /\ / * By Bob and entheh. | \/ /\ /
* \_ / > / * \_ / > /
* In order to find a good trade-off between | \ / / * In order to find a good trade-off between | \ / /
* speed and accuracy in this code, some tests | ' / * speed and accuracy in this code, some tests | ' /
* were carried out regarding the behaviour of \__/ * were carried out regarding the behaviour of \__/
* long long ints with gcc. The following code * long long ints with gcc. The following code
* was tested: * was tested:
* *
* int a, b, c; * int a, b, c;
* c = ((long long)a * b) >> 16; * c = ((long long)a * b) >> 16;
* *
* DJGPP GCC Version 3.0.3 generated the following assembly language code for * DJGPP GCC Version 3.0.3 generated the following assembly language code for
* the multiplication and scaling, leaving the 32-bit result in EAX. * the multiplication and scaling, leaving the 32-bit result in EAX.
* *
* movl -8(%ebp), %eax ; read one int into EAX * movl -8(%ebp), %eax ; read one int into EAX
* imull -4(%ebp) ; multiply by the other; result goes in EDX: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 * 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 * Note that a 32*32->64 multiplication is performed, allowing for high
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally), * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
* so it is a minor concern when four multiplications are being performed * 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 * (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 * more cycles, so this method is unsuitable for use in the low-quality
* resamplers. * resamplers.
* *
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead, * 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 * 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. * if it seems too slow then we suggest you use a good compiler.
* *
* FIXME: these comments are somewhat out of date now. * FIXME: these comments are somewhat out of date now.
*/ */
#define SUFFIX3 _1 #define SUFFIX3 _1
/* For convenience, returns nonzero on stop. */ /* For convenience, returns nonzero on stop. */
static int process_pickup(DUMB_RESAMPLER *resampler) static int process_pickup(DUMB_RESAMPLER *resampler)
{ {
if (resampler->overshot < 0) { if (resampler->overshot < 0) {
resampler->overshot = 0; resampler->overshot = 0;
dumb_resample(resampler, NULL, 2, MONO_DEST_VOLUME_ZEROS, 1.0f); /* Doesn't matter which SUFFIX3. */ dumb_resample(resampler, NULL, 2, MONO_DEST_VOLUME_ZEROS, 1.0f); /* Doesn't matter which SUFFIX3. */
COPYSRC(resampler->X, 0, resampler->X, 1); COPYSRC(resampler->X, 0, resampler->X, 1);
} }
for (;;) { for (;;) {
SRCTYPE *src = resampler->src; SRCTYPE *src = resampler->src;
if (resampler->dir < 0) { if (resampler->dir < 0) {
if (resampler->overshot >= 3 && resampler->pos+3 >= resampler->start) COPYSRC(resampler->X, 0, src, resampler->pos+3); 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 >= 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); if (resampler->overshot >= 1 && resampler->pos+1 >= resampler->start) COPYSRC(resampler->X, 2, src, resampler->pos+1);
resampler->overshot = resampler->start - resampler->pos - 1; resampler->overshot = resampler->start - resampler->pos - 1;
} else { } else {
if (resampler->overshot >= 3 && resampler->pos-3 < resampler->end) COPYSRC(resampler->X, 0, src, resampler->pos-3); 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 >= 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); if (resampler->overshot >= 1 && resampler->pos-1 < resampler->end) COPYSRC(resampler->X, 2, src, resampler->pos-1);
resampler->overshot = resampler->pos - resampler->end; resampler->overshot = resampler->pos - resampler->end;
} }
if (resampler->overshot < 0) { if (resampler->overshot < 0) {
resampler->overshot = 0; resampler->overshot = 0;
return 0; return 0;
} }
if (!resampler->pickup) { if (!resampler->pickup) {
resampler->dir = 0; resampler->dir = 0;
return 1; return 1;
} }
(*resampler->pickup)(resampler, resampler->pickup_data); (*resampler->pickup)(resampler, resampler->pickup_data);
if (resampler->dir == 0) return 1; if (resampler->dir == 0) return 1;
ASSERT(resampler->dir == -1 || resampler->dir == 1); ASSERT(resampler->dir == -1 || resampler->dir == 1);
} }
} }
/* Create mono destination resampler. */ /* Create mono destination resampler. */
/* SUFFIX3 was set above. */ /* SUFFIX3 was set above. */
#define VOLUME_PARAMETERS MONO_DEST_VOLUME_PARAMETERS #define VOLUME_PARAMETERS MONO_DEST_VOLUME_PARAMETERS
#define VOLUME_VARIABLES MONO_DEST_VOLUME_VARIABLES #define VOLUME_VARIABLES MONO_DEST_VOLUME_VARIABLES
#define SET_VOLUME_VARIABLES SET_MONO_DEST_VOLUME_VARIABLES #define SET_VOLUME_VARIABLES SET_MONO_DEST_VOLUME_VARIABLES
#define VOLUMES_ARE_ZERO MONO_DEST_VOLUMES_ARE_ZERO #define RETURN_VOLUME_VARIABLES RETURN_MONO_DEST_VOLUME_VARIABLES
#define MIX_ALIAS(op, offset) MONO_DEST_MIX_ALIAS(op, offset) #define VOLUMES_ARE_ZERO MONO_DEST_VOLUMES_ARE_ZERO
#define MIX_LINEAR(op, o0, o1) MONO_DEST_MIX_LINEAR(op, o0, o1) #define MIX_ALIAS(count) MONO_DEST_MIX_ALIAS(count)
#define MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) MONO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) #define PEEK_ALIAS MONO_DEST_PEEK_ALIAS
#define MIX_ZEROS(op) *dst++ op 0 #define PEEK_FIR MONO_DEST_PEEK_FIR
#include "resamp3.inc" #define MIX_FIR MONO_DEST_MIX_FIR
#define MIX_LINEAR(op, upd, o0, o1) MONO_DEST_MIX_LINEAR(op, upd, o0, o1)
/* Create stereo destination resampler. */ #define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) MONO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
#define SUFFIX3 _2 #define MIX_ZEROS(op) *dst++ op 0
#define VOLUME_PARAMETERS float volume_left, float volume_right #include "resamp3.inc"
#define VOLUME_VARIABLES lvol, rvol
#define SET_VOLUME_VARIABLES { \ /* Create stereo destination resampler. */
lvol = (int)floor(volume_left * 65536.0 + 0.5); \ #define SUFFIX3 _2
rvol = (int)floor(volume_right * 65536.0 + 0.5); \ #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 VOLUMES_ARE_ZERO (lvol == 0 && rvol == 0) #define SET_VOLUME_VARIABLES { \
#define MIX_ALIAS(op, offset) STEREO_DEST_MIX_ALIAS(op, offset) if ( volume_left ) { \
#define MIX_LINEAR(op, o0, o1) STEREO_DEST_MIX_LINEAR(op, o0, o1) lvolr = (int)(volume_left->volume * 16777216.0); \
#define MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) STEREO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) lvold = (int)(volume_left->delta * 16777216.0); \
#define MIX_ZEROS(op) { *dst++ op 0; *dst++ op 0; } lvolt = (int)(volume_left->target * 16777216.0); \
#include "resamp3.inc" lvolm = (int)(volume_left->mix * 16777216.0); \
lvol = MULSCV( lvolr, lvolm ); \
if ( lvolr == lvolt ) volume_left = NULL; \
} else { \
#undef STEREO_DEST_MIX_CUBIC lvol = 0; \
#undef MONO_DEST_MIX_CUBIC lvold = 0; \
#undef STEREO_DEST_MIX_LINEAR lvolt = 0; \
#undef MONO_DEST_MIX_LINEAR lvolm = 0; \
#undef STEREO_DEST_MIX_ALIAS } \
#undef MONO_DEST_MIX_ALIAS if ( volume_right ) { \
#undef MONO_DEST_VOLUMES_ARE_ZERO rvolr = (int)(volume_right->volume * 16777216.0); \
#undef SET_MONO_DEST_VOLUME_VARIABLES rvold = (int)(volume_right->delta * 16777216.0); \
#undef MONO_DEST_VOLUME_ZEROS rvolt = (int)(volume_right->target * 16777216.0); \
#undef MONO_DEST_VOLUME_VARIABLES rvolm = (int)(volume_right->mix * 16777216.0); \
#undef MONO_DEST_VOLUME_PARAMETERS rvol = MULSCV( rvolr, rvolm ); \
#undef COPYSRC2 if ( rvolr == rvolt ) volume_right = NULL; \
#undef COPYSRC } else { \
#undef DIVIDE_BY_SRC_CHANNELS rvol = 0; \
#undef SRC_CHANNELS rvold = 0; \
#undef SUFFIX2 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

View file

@ -1,371 +1,441 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* resamp3.inc - Resampling helper template. / / \ \ * resamp3.inc - Resampling helper template. / / \ \
* | < / \_ * | < / \_
* By Bob and entheh. | \/ /\ / * By Bob and entheh. | \/ /\ /
* \_ / > / * \_ / > /
* In order to find a good trade-off between | \ / / * In order to find a good trade-off between | \ / /
* speed and accuracy in this code, some tests | ' / * speed and accuracy in this code, some tests | ' /
* were carried out regarding the behaviour of \__/ * were carried out regarding the behaviour of \__/
* long long ints with gcc. The following code * long long ints with gcc. The following code
* was tested: * was tested:
* *
* int a, b, c; * int a, b, c;
* c = ((long long)a * b) >> 16; * c = ((long long)a * b) >> 16;
* *
* DJGPP GCC Version 3.0.3 generated the following assembly language code for * DJGPP GCC Version 3.0.3 generated the following assembly language code for
* the multiplication and scaling, leaving the 32-bit result in EAX. * the multiplication and scaling, leaving the 32-bit result in EAX.
* *
* movl -8(%ebp), %eax ; read one int into EAX * movl -8(%ebp), %eax ; read one int into EAX
* imull -4(%ebp) ; multiply by the other; result goes in EDX: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 * 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 * Note that a 32*32->64 multiplication is performed, allowing for high
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally), * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
* so it is a minor concern when four multiplications are being performed * 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 * (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 * more cycles, so this method is unsuitable for use in the low-quality
* resamplers. * resamplers.
* *
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead, * 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 * 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. * if it seems too slow then we suggest you use a good compiler.
* *
* FIXME: these comments are somewhat out of date now. * 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) long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLUME_PARAMETERS, float delta)
{ {
int dt; int dt, inv_dt;
int VOLUME_VARIABLES; int VOLUME_VARIABLES;
long done; long done;
long todo; long todo;
int quality; LONG_LONG todo64;
int quality;
if (!resampler || resampler->dir == 0) return 0; int blip_samples[256*SRC_CHANNELS];
ASSERT(resampler->dir == -1 || resampler->dir == 1);
if (!resampler || resampler->dir == 0) return 0;
done = 0; ASSERT(resampler->dir == -1 || resampler->dir == 1);
dt = (int)(delta * 65536.0 + 0.5);
SET_VOLUME_VARIABLES; done = 0;
dt = (int)(delta * 65536.0 + 0.5);
if (VOLUMES_ARE_ZERO) dst = NULL; if (dt == 0 || dt == (int)-0x80000000) return 0;
inv_dt = (int)(1.0 / delta * 65536.0 + 0.5);
init_cubic(); SET_VOLUME_VARIABLES;
quality = dumb_resampling_quality; if (VOLUMES_ARE_ZERO) dst = NULL;
if (quality > resampler->max_quality) quality = resampler->max_quality;
else if (quality < resampler->min_quality) quality = resampler->min_quality; init_cubic();
while (done < dst_size) { quality = resampler->quality;
if (process_pickup(resampler)) return done;
while (done < dst_size) {
if ((resampler->dir ^ dt) < 0) if (process_pickup(resampler)) {
dt = -dt; RETURN_VOLUME_VARIABLES;
return done;
if (resampler->dir < 0) }
todo = (long)((((LONG_LONG)(resampler->pos - resampler->start) << 16) + resampler->subpos - dt) / -dt);
else if ((resampler->dir ^ dt) < 0)
todo = (long)((((LONG_LONG)(resampler->end - resampler->pos) << 16) - resampler->subpos - 1 + dt) / dt); dt = -dt;
if (todo < 0) if (resampler->dir < 0)
todo = 0; todo64 = ((((LONG_LONG)(resampler->pos - resampler->start) << 16) + resampler->subpos - dt) / -dt);
else if (todo > dst_size - done) else
todo = dst_size - done; todo64 = ((((LONG_LONG)(resampler->end - resampler->pos) << 16) - resampler->subpos - 1 + dt) / dt);
done += todo; if (todo64 < 0)
todo = 0;
{ else if (todo64 > dst_size - done)
SRCTYPE *src = resampler->src; todo = dst_size - done;
long pos = resampler->pos; else
int subpos = resampler->subpos; todo = (long) todo64;
long diff = pos;
long overshot; done += todo;
if (resampler->dir < 0) {
if (!dst) { {
/* Silence or simulation */ SRCTYPE *src = resampler->src;
LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo; long pos = resampler->pos;
pos += (long)(new_subpos >> 16); int subpos = resampler->subpos;
subpos = (long)new_subpos & 65535; long diff = pos;
} else if (quality <= DUMB_RQ_ALIASING) { long overshot;
/* Aliasing, backwards */ if (resampler->dir < 0) {
SRCTYPE xbuf[2*SRC_CHANNELS]; if (!dst) {
SRCTYPE *x = &xbuf[0]; /* Silence or simulation */
SRCTYPE *xstart; LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo;
COPYSRC(xbuf, 0, resampler->X, 1); pos += (long)(new_subpos >> 16);
COPYSRC(xbuf, 1, resampler->X, 2); subpos = (long)new_subpos & 65535;
while (todo && x < &xbuf[2*SRC_CHANNELS]) { } else if (quality <= DUMB_RQ_ALIASING) {
// TODO: check what happens when multiple tempo slides occur per row /* Aliasing, backwards */
HEAVYASSERT(pos >= resampler->start); int todo_clocks = todo << 16, todo_clocks_set = todo_clocks;
MIX_ALIAS(+=, 0); SRCTYPE xbuf[2*SRC_CHANNELS];
subpos += dt; SRCTYPE *x = &xbuf[0];
pos += subpos >> 16; COPYSRC(xbuf, 0, resampler->X, 1);
x -= (subpos >> 16) * SRC_CHANNELS; COPYSRC(xbuf, 1, resampler->X, 2);
subpos &= 65535; if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
todo--; while (resampler->last_clock < todo_clocks_set && x < &xbuf[2*SRC_CHANNELS]) {
} // TODO: check what happens when multiple tempo slides occur per row
x = xstart = &src[pos*SRC_CHANNELS]; HEAVYASSERT(pos >= resampler->start);
LOOP4(todo, POKE_ALIAS(0);
MIX_ALIAS(+=, 2); pos--;
subpos += dt; x += SRC_CHANNELS;
x += (subpos >> 16) * SRC_CHANNELS; }
subpos &= 65535; x = &src[pos*SRC_CHANNELS];
); while ( todo_clocks ) {
pos += DIVIDE_BY_SRC_CHANNELS(x - xstart); todo_clocks_set = todo_clocks;
} else if (quality <= DUMB_RQ_LINEAR) { if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
/* Linear interpolation, backwards */ todo_clocks -= todo_clocks_set;
SRCTYPE xbuf[3*SRC_CHANNELS]; while ( resampler->last_clock < todo_clocks_set )
SRCTYPE *x = &xbuf[1*SRC_CHANNELS]; {
COPYSRC(xbuf, 0, resampler->X, 1); POKE_ALIAS(2);
COPYSRC(xbuf, 1, resampler->X, 2); pos--;
COPYSRC(xbuf, 2, src, pos); x -= SRC_CHANNELS;
while (todo && x < &xbuf[3*SRC_CHANNELS]) { }
HEAVYASSERT(pos >= resampler->start); todo = todo_clocks_set >> 16;
MIX_LINEAR(+=, 0, -1); MIX_ALIAS( todo );
subpos += dt; }
pos += subpos >> 16; } else if (quality <= DUMB_RQ_LINEAR) {
x -= (subpos >> 16) * SRC_CHANNELS; /* Linear interpolation, backwards */
subpos &= 65535; SRCTYPE xbuf[3*SRC_CHANNELS];
todo--; SRCTYPE *x = &xbuf[1*SRC_CHANNELS];
} COPYSRC(xbuf, 0, resampler->X, 1);
// TODO: use xstart for others too COPYSRC(xbuf, 1, resampler->X, 2);
x = &src[pos*SRC_CHANNELS]; COPYSRC(xbuf, 2, src, pos);
LOOP4(todo, while (todo && x < &xbuf[3*SRC_CHANNELS]) {
HEAVYASSERT(pos >= resampler->start); HEAVYASSERT(pos >= resampler->start);
MIX_LINEAR(+=, 1, 2); MIX_LINEAR(+=, 1, 0, -1);
subpos += dt; subpos += dt;
pos += subpos >> 16; pos += subpos >> 16;
x += (subpos >> 16) * SRC_CHANNELS; x -= (subpos >> 16) * SRC_CHANNELS;
subpos &= 65535; subpos &= 65535;
); todo--;
} else { }
/* Cubic interpolation, backwards */ // TODO: use xstart for others too
SRCTYPE xbuf[6*SRC_CHANNELS]; x = &src[pos*SRC_CHANNELS];
SRCTYPE *x = &xbuf[3*SRC_CHANNELS]; LOOP4(todo,
COPYSRC(xbuf, 0, resampler->X, 0); HEAVYASSERT(pos >= resampler->start);
COPYSRC(xbuf, 1, resampler->X, 1); MIX_LINEAR(+=, 1, 1, 2);
COPYSRC(xbuf, 2, resampler->X, 2); subpos += dt;
COPYSRC(xbuf, 3, src, pos); pos += subpos >> 16;
if (pos-1 >= resampler->start) COPYSRC(xbuf, 4, src, pos-1); x += (subpos >> 16) * SRC_CHANNELS;
if (pos-2 >= resampler->start) COPYSRC(xbuf, 5, src, pos-2); subpos &= 65535;
while (todo && x < &xbuf[6*SRC_CHANNELS]) { );
HEAVYASSERT(pos >= resampler->start); } else if (quality <= DUMB_RQ_CUBIC) {
MIX_CUBIC(+=, x, x, 0, -1, -2, -3); /* Cubic interpolation, backwards */
subpos += dt; SRCTYPE xbuf[6*SRC_CHANNELS];
pos += subpos >> 16; SRCTYPE *x = &xbuf[3*SRC_CHANNELS];
x -= (subpos >> 16) * SRC_CHANNELS; COPYSRC(xbuf, 0, resampler->X, 0);
subpos &= 65535; COPYSRC(xbuf, 1, resampler->X, 1);
todo--; COPYSRC(xbuf, 2, resampler->X, 2);
} COPYSRC(xbuf, 3, src, pos);
x = &src[pos*SRC_CHANNELS]; if (pos-1 >= resampler->start) COPYSRC(xbuf, 4, src, pos-1);
LOOP4(todo, if (pos-2 >= resampler->start) COPYSRC(xbuf, 5, src, pos-2);
HEAVYASSERT(pos >= resampler->start); while (todo && x < &xbuf[6*SRC_CHANNELS]) {
MIX_CUBIC(+=, x, x, 0, 1, 2, 3); HEAVYASSERT(pos >= resampler->start);
subpos += dt; MIX_CUBIC(+=, 1, x, x, 0, -1, -2, -3);
pos += subpos >> 16; subpos += dt;
x += (subpos >> 16) * SRC_CHANNELS; pos += subpos >> 16;
subpos &= 65535; x -= (subpos >> 16) * SRC_CHANNELS;
); subpos &= 65535;
} todo--;
diff = diff - pos; }
overshot = resampler->start - pos - 1; x = &src[pos*SRC_CHANNELS];
if (diff >= 3) { LOOP4(todo,
COPYSRC2(resampler->X, 0, overshot < 3, src, pos+3); HEAVYASSERT(pos >= resampler->start);
COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2); MIX_CUBIC(+=, 1, x, x, 0, 1, 2, 3);
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1); subpos += dt;
} else if (diff >= 2) { pos += subpos >> 16;
COPYSRC(resampler->X, 0, resampler->X, 2); x += (subpos >> 16) * SRC_CHANNELS;
COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2); subpos &= 65535;
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1); );
} else if (diff >= 1) { } else {
COPYSRC(resampler->X, 0, resampler->X, 1); /* FIR resampling, backwards */
COPYSRC(resampler->X, 1, resampler->X, 2); SRCTYPE *x;
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1); if ( resampler->fir_resampler_ratio != delta ) {
} lanczos_resampler_set_rate( resampler->fir_resampler[0], delta );
} else { lanczos_resampler_set_rate( resampler->fir_resampler[1], delta );
if (!dst) { resampler->fir_resampler_ratio = delta;
/* Silence or simulation */ }
LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo; x = &src[pos*SRC_CHANNELS];
pos += (long)(new_subpos >> 16); while ( todo ) {
subpos = (long)new_subpos & 65535; while ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
} else if (dumb_resampling_quality <= DUMB_RQ_ALIASING) { pos >= resampler->start )
/* Aliasing, forwards */ {
SRCTYPE xbuf[2*SRC_CHANNELS]; POKE_FIR(0);
SRCTYPE *x = &xbuf[0]; pos--;
SRCTYPE *xstart; x -= SRC_CHANNELS;
COPYSRC(xbuf, 0, resampler->X, 1); }
COPYSRC(xbuf, 1, resampler->X, 2); if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
while (todo && x < &xbuf[2*SRC_CHANNELS]) { MIX_FIR;
HEAVYASSERT(pos < resampler->end); ADVANCE_FIR;
MIX_ALIAS(+=, 0); --todo;
subpos += dt; }
pos += subpos >> 16; done -= todo;
x += (subpos >> 16) * SRC_CHANNELS; }
subpos &= 65535; diff = diff - pos;
todo--; overshot = resampler->start - pos - 1;
} if (diff >= 3) {
x = xstart = &src[pos*SRC_CHANNELS]; COPYSRC2(resampler->X, 0, overshot < 3, src, pos+3);
LOOP4(todo, COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2);
MIX_ALIAS(+=, -2); COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
subpos += dt; } else if (diff >= 2) {
x += (subpos >> 16) * SRC_CHANNELS; COPYSRC(resampler->X, 0, resampler->X, 2);
subpos &= 65535; COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2);
); COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
pos += DIVIDE_BY_SRC_CHANNELS(x - xstart); } else if (diff >= 1) {
} else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) { COPYSRC(resampler->X, 0, resampler->X, 1);
/* Linear interpolation, forwards */ COPYSRC(resampler->X, 1, resampler->X, 2);
SRCTYPE xbuf[3*SRC_CHANNELS]; COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
SRCTYPE *x = &xbuf[1*SRC_CHANNELS]; }
COPYSRC(xbuf, 0, resampler->X, 1); } else {
COPYSRC(xbuf, 1, resampler->X, 2); if (!dst) {
COPYSRC(xbuf, 2, src, pos); /* Silence or simulation */
while (todo && x < &xbuf[3*SRC_CHANNELS]) { LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo;
HEAVYASSERT(pos < resampler->end); pos += (long)(new_subpos >> 16);
MIX_LINEAR(+=, -1, 0); subpos = (long)new_subpos & 65535;
subpos += dt; } else if (quality <= DUMB_RQ_ALIASING) {
pos += subpos >> 16; /* Aliasing, forwards */
x += (subpos >> 16) * SRC_CHANNELS; int todo_clocks = todo << 16, todo_clocks_set = todo_clocks;
subpos &= 65535; SRCTYPE xbuf[2*SRC_CHANNELS];
todo--; SRCTYPE *x = &xbuf[0];
} COPYSRC(xbuf, 0, resampler->X, 1);
x = &src[pos*SRC_CHANNELS]; COPYSRC(xbuf, 1, resampler->X, 2);
LOOP4(todo, if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
HEAVYASSERT(pos < resampler->end); while (resampler->last_clock < todo_clocks_set && x < &xbuf[2*SRC_CHANNELS]) {
MIX_LINEAR(+=, -2, -1); HEAVYASSERT(pos < resampler->end);
subpos += dt; POKE_ALIAS(0);
pos += subpos >> 16; pos++;
x += (subpos >> 16) * SRC_CHANNELS; x += SRC_CHANNELS;
subpos &= 65535; }
); x = &src[pos*SRC_CHANNELS];
} else { while ( todo_clocks ) {
/* Cubic interpolation, forwards */ todo_clocks_set = todo_clocks;
SRCTYPE xbuf[6*SRC_CHANNELS]; if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
SRCTYPE *x = &xbuf[3*SRC_CHANNELS]; todo_clocks -= todo_clocks_set;
COPYSRC(xbuf, 0, resampler->X, 0); while ( resampler->last_clock < todo_clocks_set )
COPYSRC(xbuf, 1, resampler->X, 1); {
COPYSRC(xbuf, 2, resampler->X, 2); POKE_ALIAS(-2);
COPYSRC(xbuf, 3, src, pos); pos++;
if (pos+1 < resampler->end) COPYSRC(xbuf, 4, src, pos+1); x += SRC_CHANNELS;
if (pos+2 < resampler->end) COPYSRC(xbuf, 5, src, pos+2); }
while (todo && x < &xbuf[6*SRC_CHANNELS]) { todo = todo_clocks_set >> 16;
HEAVYASSERT(pos < resampler->end); MIX_ALIAS( todo );
MIX_CUBIC(+=, x, x, -3, -2, -1, 0); }
subpos += dt; } else if (quality <= DUMB_RQ_LINEAR) {
pos += subpos >> 16; /* Linear interpolation, forwards */
x += (subpos >> 16) * SRC_CHANNELS; SRCTYPE xbuf[3*SRC_CHANNELS];
subpos &= 65535; SRCTYPE *x = &xbuf[1*SRC_CHANNELS];
todo--; COPYSRC(xbuf, 0, resampler->X, 1);
} COPYSRC(xbuf, 1, resampler->X, 2);
x = &src[pos*SRC_CHANNELS]; COPYSRC(xbuf, 2, src, pos);
LOOP4(todo, while (todo && x < &xbuf[3*SRC_CHANNELS]) {
HEAVYASSERT(pos < resampler->end); HEAVYASSERT(pos < resampler->end);
MIX_CUBIC(+=, x, x, -3, -2, -1, 0); MIX_LINEAR(+=, 1, -1, 0);
subpos += dt; subpos += dt;
pos += subpos >> 16; pos += subpos >> 16;
x += (subpos >> 16) * SRC_CHANNELS; x += (subpos >> 16) * SRC_CHANNELS;
subpos &= 65535; subpos &= 65535;
); todo--;
} }
diff = pos - diff; x = &src[pos*SRC_CHANNELS];
overshot = pos - resampler->end; LOOP4(todo,
if (diff >= 3) { HEAVYASSERT(pos < resampler->end);
COPYSRC2(resampler->X, 0, overshot < 3, src, pos-3); MIX_LINEAR(+=, 1, -2, -1);
COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2); subpos += dt;
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1); pos += subpos >> 16;
} else if (diff >= 2) { x += (subpos >> 16) * SRC_CHANNELS;
COPYSRC(resampler->X, 0, resampler->X, 2); subpos &= 65535;
COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2); );
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1); } else if (quality <= DUMB_RQ_CUBIC) {
} else if (diff >= 1) { /* Cubic interpolation, forwards */
COPYSRC(resampler->X, 0, resampler->X, 1); SRCTYPE xbuf[6*SRC_CHANNELS];
COPYSRC(resampler->X, 1, resampler->X, 2); SRCTYPE *x = &xbuf[3*SRC_CHANNELS];
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1); COPYSRC(xbuf, 0, resampler->X, 0);
} COPYSRC(xbuf, 1, resampler->X, 1);
} COPYSRC(xbuf, 2, resampler->X, 2);
resampler->pos = pos; COPYSRC(xbuf, 3, src, pos);
resampler->subpos = subpos; 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);
return done; MIX_CUBIC(+=, 1, x, x, -3, -2, -1, 0);
} subpos += dt;
pos += subpos >> 16;
x += (subpos >> 16) * SRC_CHANNELS;
subpos &= 65535;
void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETERS, sample_t *dst) todo--;
{ }
int VOLUME_VARIABLES; x = &src[pos*SRC_CHANNELS];
SRCTYPE *src; LOOP4(todo,
long pos; HEAVYASSERT(pos < resampler->end);
int subpos; MIX_CUBIC(+=, 1, x, x, -3, -2, -1, 0);
int quality; subpos += dt;
SRCTYPE *x; pos += subpos >> 16;
x += (subpos >> 16) * SRC_CHANNELS;
if (!resampler || resampler->dir == 0) { MIX_ZEROS(=); return; } subpos &= 65535;
ASSERT(resampler->dir == -1 || resampler->dir == 1); );
} else {
if (process_pickup(resampler)) { MIX_ZEROS(=); return; } /* FIR resampling, forwards */
SRCTYPE *x;
SET_VOLUME_VARIABLES; if ( resampler->fir_resampler_ratio != delta ) {
lanczos_resampler_set_rate( resampler->fir_resampler[0], delta );
if (VOLUMES_ARE_ZERO) { MIX_ZEROS(=); return; } lanczos_resampler_set_rate( resampler->fir_resampler[1], delta );
resampler->fir_resampler_ratio = delta;
init_cubic(); }
x = &src[pos*SRC_CHANNELS];
quality = dumb_resampling_quality; while ( todo ) {
if (quality > resampler->max_quality) quality = resampler->max_quality; while ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
else if (quality < resampler->min_quality) quality = resampler->min_quality; pos < resampler->end )
{
src = resampler->src; POKE_FIR(0);
pos = resampler->pos; pos++;
subpos = resampler->subpos; x += SRC_CHANNELS;
x = resampler->X; }
if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
if (resampler->dir < 0) { MIX_FIR;
HEAVYASSERT(pos >= resampler->start); ADVANCE_FIR;
if (dumb_resampling_quality <= 0) { --todo;
/* Aliasing, backwards */ }
MIX_ALIAS(=, 1); done -= todo;
} else if (quality <= DUMB_RQ_LINEAR) { }
/* Linear interpolation, backwards */ diff = pos - diff;
MIX_LINEAR(=, 2, 1); overshot = pos - resampler->end;
} else { if (diff >= 3) {
/* Cubic interpolation, backwards */ COPYSRC2(resampler->X, 0, overshot < 3, src, pos-3);
MIX_CUBIC(=, src, x, pos, 2, 1, 0); COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2);
} COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
} else { } else if (diff >= 2) {
HEAVYASSERT(pos < resampler->end); COPYSRC(resampler->X, 0, resampler->X, 2);
if (dumb_resampling_quality <= 0) { COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2);
/* Aliasing */ COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
MIX_ALIAS(=, 1); } else if (diff >= 1) {
} else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) { COPYSRC(resampler->X, 0, resampler->X, 1);
/* Linear interpolation, forwards */ COPYSRC(resampler->X, 1, resampler->X, 2);
MIX_LINEAR(=, 1, 2); COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
} else { }
/* Cubic interpolation, forwards */ }
MIX_CUBIC(=, x, src, 0, 1, 2, pos); resampler->pos = pos;
} resampler->subpos = subpos;
} }
} }
RETURN_VOLUME_VARIABLES;
return done;
#undef MIX_ZEROS }
#undef MIX_CUBIC
#undef MIX_LINEAR
#undef MIX_ALIAS
#undef VOLUMES_ARE_ZERO void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETERS, sample_t *dst)
#undef SET_VOLUME_VARIABLES {
#undef VOLUME_VARIABLES int VOLUME_VARIABLES;
#undef VOLUME_PARAMETERS SRCTYPE *src;
#undef SUFFIX3 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

View file

@ -1,385 +1,410 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* resample.c - Resampling helpers. / / \ \ * resample.c - Resampling helpers. / / \ \
* | < / \_ * | < / \_
* By Bob and entheh. | \/ /\ / * By Bob and entheh. | \/ /\ /
* \_ / > / * \_ / > /
* In order to find a good trade-off between | \ / / * In order to find a good trade-off between | \ / /
* speed and accuracy in this code, some tests | ' / * speed and accuracy in this code, some tests | ' /
* were carried out regarding the behaviour of \__/ * were carried out regarding the behaviour of \__/
* long long ints with gcc. The following code * long long ints with gcc. The following code
* was tested: * was tested:
* *
* int a, b, c; * int a, b, c;
* c = ((long long)a * b) >> 16; * c = ((long long)a * b) >> 16;
* *
* DJGPP GCC Version 3.0.3 generated the following assembly language code for * DJGPP GCC Version 3.0.3 generated the following assembly language code for
* the multiplication and scaling, leaving the 32-bit result in EAX. * the multiplication and scaling, leaving the 32-bit result in EAX.
* *
* movl -8(%ebp), %eax ; read one int into EAX * movl -8(%ebp), %eax ; read one int into EAX
* imull -4(%ebp) ; multiply by the other; result goes in EDX: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 * 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 * Note that a 32*32->64 multiplication is performed, allowing for high
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally), * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
* so it is a minor concern when four multiplications are being performed * 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 * (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 * more cycles, so this method is unsuitable for use in the low-quality
* resamplers. * resamplers.
* *
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead, * 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 * 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. * if it seems too slow then we suggest you use a good compiler.
* *
* FIXME: these comments are somewhat out of date now. * FIXME: these comments are somewhat out of date now.
*/ */
#include <math.h> #include <math.h>
#include "dumb.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.
*/ /* Compile with -DHEAVYDEBUG if you want to make sure the pick-up function is
#ifdef HEAVYDEBUG * called when it should be. There will be a considerable performance hit,
#define HEAVYASSERT(cond) ASSERT(cond) * since at least one condition has to be tested for every sample generated.
#else */
#define HEAVYASSERT(cond) #ifdef HEAVYDEBUG
#endif #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 /* Make MSVC shut the hell up about if ( upd ) UPDATE_VOLUME() conditions being constant */
* 1 - DUMB_RQ_LINEAR #ifdef _MSC_VER
* 2 - DUMB_RQ_CUBIC - nicest #pragma warning(disable:4127 4701)
* #endif
* Values outside the range 0-2 will behave the same as the nearest
* value within the range.
*/
int dumb_resampling_quality = DUMB_RQ_CUBIC; /* 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
//#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16)) * 1 - DUMB_RQ_LINEAR
//#define MULSC(a, b) ((a) * ((b) >> 2) >> 14) * 2 - DUMB_RQ_CUBIC
#define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32)) * 3 - DUMB_RQ_FIR - nicest
#define MULSC16(a, b) ((int)((LONG_LONG)((a) << 12) * ((b) << 12) >> 32)) *
* Values outside the range 0-3 will behave the same as the nearest
* value within the range.
*/
/* Executes the content 'iterator' times. int dumb_resampling_quality = DUMB_RQ_CUBIC;
* Clobbers the 'iterator' variable.
* The loop is unrolled by four.
*/
#define LOOP4(iterator, CONTENT) \ //#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16))
{ \ //#define MULSC(a, b) ((a) * ((b) >> 2) >> 14)
if ((iterator) & 2) { \ #define MULSCV(a, b) ((int)((LONG_LONG)(a) * (b) >> 32))
CONTENT; \ #define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32))
CONTENT; \ #define MULSC16(a, b) ((int)((LONG_LONG)((a) << 12) * ((b) << 12) >> 32))
} \
if ((iterator) & 1) { \
CONTENT; \
} \ /* Executes the content 'iterator' times.
(iterator) >>= 2; \ * Clobbers the 'iterator' variable.
while (iterator) { \ * The loop is unrolled by four.
CONTENT; \ */
CONTENT; \ #if 0
CONTENT; \ #define LOOP4(iterator, CONTENT) \
CONTENT; \ { \
(iterator)--; \ if ((iterator) & 2) { \
} \ CONTENT; \
} CONTENT; \
} \
if ((iterator) & 1) { \
CONTENT; \
#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. */ (iterator) >>= 2; \
while (iterator) { \
#define X PASTE(x.x, SRCBITS) CONTENT; \
CONTENT; \
CONTENT; \
CONTENT; \
/* Cubic resampler: look-up tables (iterator)--; \
* } \
* a = 1.5*x1 - 1.5*x2 + 0.5*x3 - 0.5*x0 }
* b = 2*x2 + x0 - 2.5*x1 - 0.5*x3 #else
* c = 0.5*x2 - 0.5*x0 #define LOOP4(iterator, CONTENT) \
* d = x1 { \
* while ( (iterator)-- ) \
* 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 + CONTENT; \
* ( 1*x0 - 2.5*x1 + 2 *x2 - 0.5*x3) * t*t + } \
* (-0.5*x0 + 0.5*x2 ) * t + }
* ( 1*x1 ) #endif
* = (-0.5*t*t*t + 1 *t*t - 0.5*t ) * x0 +
* ( 1.5*t*t*t - 2.5*t*t + 1) * x1 + #define PASTERAW(a, b) a ## b /* This does not expand macros in b ... */
* (-1.5*t*t*t + 2 *t*t + 0.5*t ) * x2 + #define PASTE(a, b) PASTERAW(a, b) /* ... but b is expanded during this substitution. */
* ( 0.5*t*t*t - 0.5*t*t ) * x3
* = A0(t) * x0 + A1(t) * x1 + A2(t) * x2 + A3(t) * x3 #define X PASTE(x.x, SRCBITS)
*
* A0, A1, A2 and A3 stay within the range [-1,1].
* In the tables, they are scaled with 14 fractional bits.
* /* Cubic resampler: look-up tables
* Turns out we don't need to store A2 and A3; they are symmetrical to A1 and A0. *
* * a = 1.5*x1 - 1.5*x2 + 0.5*x3 - 0.5*x0
* TODO: A0 and A3 stay very small indeed. Consider different scale/resolution? * b = 2*x2 + x0 - 2.5*x1 - 0.5*x3
*/ * c = 0.5*x2 - 0.5*x0
* d = x1
static short cubicA0[1025], cubicA1[1025]; *
* x = a*t*t*t + b*t*t + c*t + d
static void init_cubic(void) * = (-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 +
unsigned int t; /* 3*1024*1024*1024 is within range if it's unsigned */ * (-0.5*x0 + 0.5*x2 ) * t +
static int done = 0; * ( 1*x1 )
if (done) return; * = (-0.5*t*t*t + 1 *t*t - 0.5*t ) * x0 +
done = 1; * ( 1.5*t*t*t - 2.5*t*t + 1) * x1 +
for (t = 0; t < 1025; t++) { * (-1.5*t*t*t + 2 *t*t + 0.5*t ) * x2 +
/* int casts to pacify warnings about negating unsigned values */ * ( 0.5*t*t*t - 0.5*t*t ) * x3
cubicA0[t] = -(int)( t*t*t >> 17) + (int)( t*t >> 6) - (int)(t << 3); * = A0(t) * x0 + A1(t) * x1 + A2(t) * x2 + A3(t) * x3
cubicA1[t] = (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14); *
} * 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.
*
/* Create resamplers for 24-in-32-bit source samples. */ * TODO: A0 and A3 stay very small indeed. Consider different scale/resolution?
*/
/* #define SUFFIX
* MSVC warns if we try to paste a null SUFFIX, so instead we define static short cubicA0[1025], cubicA1[1025];
* special macros for the function names that don't bother doing the
* corresponding paste. The more generic definitions are further down. /*static*/ void init_cubic(void)
*/ {
#define process_pickup PASTE(process_pickup, SUFFIX2) unsigned int t; /* 3*1024*1024*1024 is within range if it's unsigned */
#define dumb_resample PASTE(PASTE(dumb_resample, SUFFIX2), SUFFIX3) static int done = 0;
#define dumb_resample_get_current_sample PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX2), SUFFIX3) if (done) return;
done = 1;
#define SRCTYPE sample_t for (t = 0; t < 1025; t++) {
#define SRCBITS 24 /* int casts to pacify warnings about negating unsigned values */
#define ALIAS(x, vol) MULSC(x, vol) cubicA0[t] = -(int)( t*t*t >> 17) + (int)( t*t >> 6) - (int)(t << 3);
#define LINEAR(x0, x1) (x0 + MULSC(x1 - x0, subpos)) cubicA1[t] = (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14);
/* }
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
a = (3 * (x1 - x2) + (x3 - x0)) >> 1; \ lanczos_init();
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)
*/ /* Create resamplers for 24-in-32-bit source samples. */
#define CUBIC(x0, x1, x2, x3) ( \
MULSC(x0, cubicA0[subpos >> 6] << 2) + \ /* #define SUFFIX
MULSC(x1, cubicA1[subpos >> 6] << 2) + \ * MSVC warns if we try to paste a null SUFFIX, so instead we define
MULSC(x2, cubicA1[1 + (subpos >> 6 ^ 1023)] << 2) + \ * special macros for the function names that don't bother doing the
MULSC(x3, cubicA0[1 + (subpos >> 6 ^ 1023)] << 2)) * corresponding paste. The more generic definitions are further down.
#define CUBICVOL(x, vol) MULSC(x, vol) */
#include "resample.inc" #define process_pickup PASTE(process_pickup, SUFFIX2)
#define dumb_resample PASTE(PASTE(dumb_resample, SUFFIX2), SUFFIX3)
/* Undefine the simplified macros. */ #define dumb_resample_get_current_sample PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX2), SUFFIX3)
#undef dumb_resample_get_current_sample
#undef dumb_resample #define SRCTYPE sample_t
#undef process_pickup #define SRCBITS 24
#define ALIAS(x) (x >> 8)
#define FIR(x) (x >> 8)
/* Now define the proper ones that use SUFFIX. */ #define LINEAR(x0, x1) (x0 + MULSC(x1 - x0, subpos))
#define dumb_reset_resampler PASTE(dumb_reset_resampler, SUFFIX) /*
#define dumb_start_resampler PASTE(dumb_start_resampler, SUFFIX) #define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
#define process_pickup PASTE(PASTE(process_pickup, SUFFIX), SUFFIX2) a = (3 * (x1 - x2) + (x3 - x0)) >> 1; \
#define dumb_resample PASTE(PASTE(PASTE(dumb_resample, SUFFIX), SUFFIX2), SUFFIX3) b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) >> 1; \
#define dumb_resample_get_current_sample PASTE(PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX), SUFFIX2), SUFFIX3) c = (x2 - x0) >> 1; \
#define dumb_end_resampler PASTE(dumb_end_resampler, SUFFIX) }
#define CUBIC(d) MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + d, vol)
/* Create resamplers for 16-bit source samples. */ */
#define SUFFIX _16 #define CUBIC(x0, x1, x2, x3) ( \
#define SRCTYPE short MULSC(x0, cubicA0[subpos >> 6] << 2) + \
#define SRCBITS 16 MULSC(x1, cubicA1[subpos >> 6] << 2) + \
#define ALIAS(x, vol) (x * vol >> 8) MULSC(x2, cubicA1[1 + (subpos >> 6 ^ 1023)] << 2) + \
#define LINEAR(x0, x1) ((x0 << 8) + MULSC16(x1 - x0, subpos)) MULSC(x3, cubicA0[1 + (subpos >> 6 ^ 1023)] << 2))
/* #define CUBICVOL(x, vol) MULSC(x, vol)
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \ #include "resample.inc"
a = (3 * (x1 - x2) + (x3 - x0)) << 7; \
b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) << 7; \ /* Undefine the simplified macros. */
c = (x2 - x0) << 7; \ #undef dumb_resample_get_current_sample
} #undef dumb_resample
#define CUBIC(d) MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + (d << 8), vol) #undef process_pickup
*/
#define CUBIC(x0, x1, x2, x3) ( \
x0 * cubicA0[subpos >> 6] + \ /* Now define the proper ones that use SUFFIX. */
x1 * cubicA1[subpos >> 6] + \ #define dumb_reset_resampler PASTE(dumb_reset_resampler, SUFFIX)
x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \ #define dumb_start_resampler PASTE(dumb_start_resampler, SUFFIX)
x3 * cubicA0[1 + (subpos >> 6 ^ 1023)]) #define process_pickup PASTE(PASTE(process_pickup, SUFFIX), SUFFIX2)
#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 10) >> 32) #define dumb_resample PASTE(PASTE(PASTE(dumb_resample, SUFFIX), SUFFIX2), SUFFIX3)
#include "resample.inc" #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 8-bit source samples. */
#define SUFFIX _8 /* Create resamplers for 16-bit source samples. */
#define SRCTYPE signed char #define SUFFIX _16
#define SRCBITS 8 #define SRCTYPE short
#define ALIAS(x, vol) (x * vol) #define SRCBITS 16
#define LINEAR(x0, x1) ((x0 << 16) + (x1 - x0) * subpos) #define ALIAS(x) (x)
/* #define FIR(x) (x)
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \ #define LINEAR(x0, x1) ((x0 << 8) + MULSC16(x1 - x0, subpos))
a = 3 * (x1 - x2) + (x3 - x0); \ /*
b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) << 15; \ #define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
c = (x2 - x0) << 15; \ a = (3 * (x1 - x2) + (x3 - x0)) << 7; \
} b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) << 7; \
#define CUBIC(d) MULSC(MULSC(MULSC((a * subpos >> 1) + b, subpos) + c, subpos) + (d << 16), vol) c = (x2 - x0) << 7; \
*/ }
#define CUBIC(x0, x1, x2, x3) (( \ #define CUBIC(d) MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + (d << 8), vol)
x0 * cubicA0[subpos >> 6] + \ */
x1 * cubicA1[subpos >> 6] + \ #define CUBIC(x0, x1, x2, x3) ( \
x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \ x0 * cubicA0[subpos >> 6] + \
x3 * cubicA0[1 + (subpos >> 6 ^ 1023)]) << 6) x1 * cubicA1[subpos >> 6] + \
#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 12) >> 32) x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
#include "resample.inc" x3 * cubicA0[1 + (subpos >> 6 ^ 1023)])
#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 10) >> 32)
#include "resample.inc"
#undef dumb_reset_resampler
#undef dumb_start_resampler /* Create resamplers for 8-bit source samples. */
#undef process_pickup #define SUFFIX _8
#undef dumb_resample #define SRCTYPE signed char
#undef dumb_resample_get_current_sample #define SRCBITS 8
#undef dumb_end_resampler #define ALIAS(x) (x << 8)
#define FIR(x) (x << 8)
#define LINEAR(x0, x1) ((x0 << 16) + (x1 - x0) * subpos)
/*
void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src, int src_channels, long pos, long start, long end) #define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
{ a = 3 * (x1 - x2) + (x3 - x0); \
if (n == 8) b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) << 15; \
dumb_reset_resampler_8(resampler, src, src_channels, pos, start, end); c = (x2 - x0) << 15; \
else if (n == 16) }
dumb_reset_resampler_16(resampler, src, src_channels, pos, start, end); #define CUBIC(d) MULSC(MULSC(MULSC((a * subpos >> 1) + b, subpos) + c, subpos) + (d << 16), vol)
else */
dumb_reset_resampler(resampler, src, src_channels, pos, start, end); #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)
DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels, long pos, long start, long end) #define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 12) >> 32)
{ #include "resample.inc"
if (n == 8)
return dumb_start_resampler_8(src, src_channels, pos, start, end);
else if (n == 16) #undef dumb_reset_resampler
return dumb_start_resampler_16(src, src_channels, pos, start, end); #undef dumb_start_resampler
else #undef process_pickup
return dumb_start_resampler(src, src_channels, pos, start, end); #undef dumb_resample
} #undef dumb_resample_get_current_sample
#undef dumb_end_resampler
long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta)
{ 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) {
return dumb_resample_8_1_1(resampler, dst, dst_size, volume, delta); if (n == 8)
else if (n == 16) dumb_reset_resampler_8(resampler, src, src_channels, pos, start, end, quality);
return dumb_resample_16_1_1(resampler, dst, dst_size, volume, delta); else if (n == 16)
else dumb_reset_resampler_16(resampler, src, src_channels, pos, start, end, quality);
return dumb_resample_1_1(resampler, dst, dst_size, volume, delta); else
} dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
}
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)
{ 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_resample_8_1_2(resampler, dst, dst_size, volume_left, volume_right, delta); if (n == 8)
else if (n == 16) return dumb_start_resampler_8(src, src_channels, pos, start, end, quality);
return dumb_resample_16_1_2(resampler, dst, dst_size, volume_left, volume_right, delta); else if (n == 16)
else return dumb_start_resampler_16(src, src_channels, pos, start, end, quality);
return dumb_resample_1_2(resampler, dst, dst_size, volume_left, volume_right, delta); else
} return dumb_start_resampler(src, src_channels, pos, start, end, quality);
}
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)
{ 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_2_1(resampler, dst, dst_size, volume_left, volume_right, delta); if (n == 8)
else if (n == 16) return dumb_resample_8_1_1(resampler, dst, dst_size, volume, delta);
return dumb_resample_16_2_1(resampler, dst, dst_size, volume_left, volume_right, delta); else if (n == 16)
else return dumb_resample_16_1_1(resampler, dst, dst_size, volume, delta);
return dumb_resample_2_1(resampler, dst, dst_size, volume_left, volume_right, delta); else
} return dumb_resample_1_1(resampler, dst, dst_size, volume, 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)
{ 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_2_2(resampler, dst, dst_size, volume_left, volume_right, delta); if (n == 8)
else if (n == 16) return dumb_resample_8_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
return dumb_resample_16_2_2(resampler, dst, dst_size, volume_left, volume_right, delta); else if (n == 16)
else return dumb_resample_16_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
return dumb_resample_2_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);
}
void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler, float volume, sample_t *dst)
{ 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) {
dumb_resample_get_current_sample_8_1_1(resampler, volume, dst); if (n == 8)
else if (n == 16) return dumb_resample_8_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
dumb_resample_get_current_sample_16_1_1(resampler, volume, dst); else if (n == 16)
else return dumb_resample_16_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
dumb_resample_get_current_sample_1_1(resampler, volume, dst); else
} return dumb_resample_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
}
void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst)
{ 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) {
dumb_resample_get_current_sample_8_1_2(resampler, volume_left, volume_right, dst); if (n == 8)
else if (n == 16) return dumb_resample_8_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
dumb_resample_get_current_sample_16_1_2(resampler, volume_left, volume_right, dst); else if (n == 16)
else return dumb_resample_16_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
dumb_resample_get_current_sample_1_2(resampler, volume_left, volume_right, dst); else
} return dumb_resample_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
}
void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst)
{ 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_2_1(resampler, volume_left, volume_right, dst); if (n == 8)
else if (n == 16) dumb_resample_get_current_sample_8_1_1(resampler, volume, dst);
dumb_resample_get_current_sample_16_2_1(resampler, volume_left, volume_right, dst); else if (n == 16)
else dumb_resample_get_current_sample_16_1_1(resampler, volume, dst);
dumb_resample_get_current_sample_2_1(resampler, volume_left, volume_right, dst); else
} dumb_resample_get_current_sample_1_1(resampler, volume, dst);
}
void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *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_2_2(resampler, volume_left, volume_right, dst); if (n == 8)
else if (n == 16) dumb_resample_get_current_sample_8_1_2(resampler, volume_left, volume_right, dst);
dumb_resample_get_current_sample_16_2_2(resampler, volume_left, volume_right, dst); else if (n == 16)
else dumb_resample_get_current_sample_16_1_2(resampler, volume_left, volume_right, dst);
dumb_resample_get_current_sample_2_2(resampler, volume_left, volume_right, dst); else
} dumb_resample_get_current_sample_1_2(resampler, volume_left, volume_right, dst);
}
void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler)
{ 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_end_resampler_8(resampler); if (n == 8)
else if (n == 16) dumb_resample_get_current_sample_8_2_1(resampler, volume_left, volume_right, dst);
dumb_end_resampler_16(resampler); else if (n == 16)
else dumb_resample_get_current_sample_16_2_1(resampler, volume_left, volume_right, dst);
dumb_end_resampler(resampler); 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);
}

View file

@ -1,167 +1,403 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* resample.inc - Resampling helper template. / / \ \ * resample.inc - Resampling helper template. / / \ \
* | < / \_ * | < / \_
* By Bob and entheh. | \/ /\ / * By Bob and entheh. | \/ /\ /
* \_ / > / * \_ / > /
* In order to find a good trade-off between | \ / / * In order to find a good trade-off between | \ / /
* speed and accuracy in this code, some tests | ' / * speed and accuracy in this code, some tests | ' /
* were carried out regarding the behaviour of \__/ * were carried out regarding the behaviour of \__/
* long long ints with gcc. The following code * long long ints with gcc. The following code
* was tested: * was tested:
* *
* int a, b, c; * int a, b, c;
* c = ((long long)a * b) >> 16; * c = ((long long)a * b) >> 16;
* *
* DJGPP GCC Version 3.0.3 generated the following assembly language code for * DJGPP GCC Version 3.0.3 generated the following assembly language code for
* the multiplication and scaling, leaving the 32-bit result in EAX. * the multiplication and scaling, leaving the 32-bit result in EAX.
* *
* movl -8(%ebp), %eax ; read one int into EAX * movl -8(%ebp), %eax ; read one int into EAX
* imull -4(%ebp) ; multiply by the other; result goes in EDX: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 * 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 * Note that a 32*32->64 multiplication is performed, allowing for high
* accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally), * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
* so it is a minor concern when four multiplications are being performed * 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 * (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 * more cycles, so this method is unsuitable for use in the low-quality
* resamplers. * resamplers.
* *
* Since "long long" is a gcc-specific extension, we use LONG_LONG instead, * 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 * 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. * if it seems too slow then we suggest you use a good compiler.
* *
* FIXME: these comments are somewhat out of date now. * 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) void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_channels, long pos, long start, long end, int quality)
{ {
int i; int i;
resampler->src = src; resampler->src = src;
resampler->pos = pos; resampler->pos = pos;
resampler->subpos = 0; resampler->subpos = 0;
resampler->start = start; resampler->start = start;
resampler->end = end; resampler->end = end;
resampler->dir = 1; resampler->dir = 1;
resampler->pickup = NULL; resampler->pickup = NULL;
resampler->pickup_data = NULL; resampler->pickup_data = NULL;
resampler->min_quality = 0; if (quality < 0)
resampler->max_quality = DUMB_RQ_N_LEVELS - 1; {
for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0; resampler->quality = 0;
resampler->overshot = -1; }
} else if (quality > DUMB_RQ_N_LEVELS - 1)
{
resampler->quality = DUMB_RQ_N_LEVELS - 1;
}
DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, long start, long end) else
{ {
DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler)); resampler->quality = quality;
if (!resampler) return NULL; }
dumb_reset_resampler(resampler, src, src_channels, pos, start, end); for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
return resampler; resampler->overshot = -1;
} resampler->last_clock = 0;
resampler->last_amp[0] = 0;
resampler->last_amp[1] = 0;
blip_clear(resampler->blip_buffer[0]);
/* Create mono source resampler. */ blip_clear(resampler->blip_buffer[1]);
#define SUFFIX2 _1 resampler->fir_resampler_ratio = 0;
#define SRC_CHANNELS 1 lanczos_resampler_clear(resampler->fir_resampler[0]);
#define DIVIDE_BY_SRC_CHANNELS(x) (x) lanczos_resampler_clear(resampler->fir_resampler[1]);
#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 DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, long start, long end, int quality)
#define SET_MONO_DEST_VOLUME_VARIABLES vol = (int)floor(volume * 65536.0 + 0.5) {
#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0) DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
#define MONO_DEST_MIX_ALIAS(op, offset) *dst++ op ALIAS(x[offset], vol) if (!resampler) return NULL;
#define STEREO_DEST_MIX_ALIAS(op, offset) { \ resampler->blip_buffer[0] = blip_new( 256 );
int xm = x[offset]; \ if (!resampler->blip_buffer[0])
*dst++ op ALIAS(xm, lvol); \ {
*dst++ op ALIAS(xm, rvol); \ free(resampler);
} return NULL;
#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) { \ resampler->blip_buffer[1] = blip_new( 256 );
int xm = LINEAR(x[o0], x[o1]); \ if (!resampler->blip_buffer[1])
*dst++ op MULSC(xm, lvol); \ {
*dst++ op MULSC(xm, rvol); \ free(resampler->blip_buffer[0]);
} free(resampler);
#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) return NULL;
#define STEREO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) { \ }
int xm = CUBIC(x0[o0], x[o1], x[o2], x3[o3]); \ blip_set_rates(resampler->blip_buffer[0], 65536, 1);
*dst++ op CUBICVOL(xm, lvol); \ blip_set_rates(resampler->blip_buffer[1], 65536, 1);
*dst++ op CUBICVOL(xm, rvol); \ dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
} return resampler;
#include "resamp2.inc" }
/* Create stereo source resampler. */
#define SUFFIX2 _2
#define SRC_CHANNELS 2 #define UPDATE_VOLUME( pvol, vol ) { \
#define DIVIDE_BY_SRC_CHANNELS(x) ((x) >> 1) if (pvol) { \
#define COPYSRC(dstarray, dstindex, srcarray, srcindex) { \ vol##r += vol##d; \
(dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \ if ((vol##d < 0 && vol##r <= vol##t) || \
(dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \ (vol##d > 0 && vol##r >= vol##t)) { \
} pvol->volume = pvol->target; \
#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) { \ pvol = NULL; \
if (condition) { \ vol = MULSCV( vol##t, vol##m ); \
(dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \ } else { \
(dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \ vol = MULSCV( vol##r, vol##m ); \
} 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 /* Create mono source resampler. */
#define MONO_DEST_VOLUME_ZEROS 0, 0 #define SUFFIX2 _1
#define SET_MONO_DEST_VOLUME_VARIABLES { \ #define SRC_CHANNELS 1
lvol = (int)floor(volume_left * 65536.0 + 0.5); \ #define DIVIDE_BY_SRC_CHANNELS(x) (x)
rvol = (int)floor(volume_right * 65536.0 + 0.5); \ #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_VOLUMES_ARE_ZERO (lvol == 0 && rvol == 0) #define MONO_DEST_VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO * volume
#define MONO_DEST_MIX_ALIAS(op, offset) *dst++ op ALIAS(x[(offset)*2], lvol) + ALIAS(x[(offset)*2+1], rvol) #define MONO_DEST_VOLUME_VARIABLES vol, volr, vold, volt, volm
#define STEREO_DEST_MIX_ALIAS(op, offset) { \ #define MONO_DEST_VOLUME_ZEROS 0
*dst++ op ALIAS(x[(offset)*2], lvol); \ #define SET_MONO_DEST_VOLUME_VARIABLES { \
*dst++ op ALIAS(x[(offset)*2+1], rvol); \ if ( volume ) { \
} volr = (int)(volume->volume * 16777216.0); \
#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) vold = (int)(volume->delta * 16777216.0); \
#define STEREO_DEST_MIX_LINEAR(op, o0, o1) { \ volt = (int)(volume->target * 16777216.0); \
*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol); \ volm = (int)(volume->mix * 16777216.0); \
*dst++ op MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \ vol = MULSCV( volr, volm ); \
} if ( volr == volt ) volume = NULL; \
#define MONO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) *dst++ op \ } else { \
CUBICVOL(CUBIC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x3[(o3)*2]), lvol) + \ vol = 0; \
CUBICVOL(CUBIC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x3[(o3)*2+1]), rvol) vold = 0; \
#define STEREO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) { \ volt = 0; \
*dst++ op CUBICVOL(CUBIC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x3[(o3)*2]), lvol); \ volm = 0; \
*dst++ op CUBICVOL(CUBIC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x3[(o3)*2+1]), rvol); \ } \
} }
#include "resamp2.inc" #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]; \
void dumb_end_resampler(DUMB_RESAMPLER *resampler) resampler->last_amp[0] += delta; \
{ if ( delta ) blip_add_delta( resampler->blip_buffer[0], resampler->last_clock, delta ); \
if (resampler) resampler->last_clock += inv_dt; \
free(resampler); }
} #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 )
#undef CUBICVOL #define MONO_DEST_PEEK_FIR *dst = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), vol )
#undef CUBIC #define MONO_DEST_MIX_FIR { \
#undef LINEAR *dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
#undef ALIAS UPDATE_VOLUME( volume, vol ); \
#undef SRCBITS }
#undef SRCTYPE #define ADVANCE_FIR lanczos_resampler_remove_sample( resampler->fir_resampler[0] )
#undef SUFFIX #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

View 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 );
}
}

View file

@ -1,64 +1,64 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* sampbuf.c - Helper for allocating sample / / \ \ * sampbuf.c - Helper for allocating sample / / \ \
* buffers. | < / \_ * buffers. | < / \_
* | \/ /\ / * | \/ /\ /
* By entheh. \_ / > / * By entheh. \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
/* DEPRECATED */ /* DEPRECATED */
sample_t **create_sample_buffer(int n_channels, long length) sample_t **create_sample_buffer(int n_channels, long length)
{ {
int i; int i;
sample_t **samples = malloc(n_channels * sizeof(*samples)); sample_t **samples = malloc(n_channels * sizeof(*samples));
if (!samples) return NULL; if (!samples) return NULL;
samples[0] = malloc(n_channels * length * sizeof(*samples[0])); samples[0] = malloc(n_channels * length * sizeof(*samples[0]));
if (!samples[0]) { if (!samples[0]) {
free(samples); free(samples);
return NULL; return NULL;
} }
for (i = 1; i < n_channels; i++) samples[i] = samples[i-1] + length; for (i = 1; i < n_channels; i++) samples[i] = samples[i-1] + length;
return samples; return samples;
} }
sample_t **allocate_sample_buffer(int n_channels, long length) sample_t **allocate_sample_buffer(int n_channels, long length)
{ {
int i; int i;
sample_t **samples = malloc(((n_channels + 1) >> 1) * sizeof(*samples)); sample_t **samples = malloc(((n_channels + 1) >> 1) * sizeof(*samples));
if (!samples) return NULL; if (!samples) return NULL;
samples[0] = malloc(n_channels * length * sizeof(*samples[0])); samples[0] = malloc(n_channels * length * sizeof(*samples[0]));
if (!samples[0]) { if (!samples[0]) {
free(samples); free(samples);
return NULL; return NULL;
} }
for (i = 1; i < (n_channels + 1) >> 1; i++) samples[i] = samples[i-1] + length*2; for (i = 1; i < (n_channels + 1) >> 1; i++) samples[i] = samples[i-1] + length*2;
return samples; return samples;
} }
void destroy_sample_buffer(sample_t **samples) void destroy_sample_buffer(sample_t **samples)
{ {
if (samples) { if (samples) {
free(samples[0]); free(samples[0]);
free(samples); free(samples);
} }
} }

View file

@ -1,29 +1,29 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* silence.c - Silencing helper. / / \ \ * silence.c - Silencing helper. / / \ \
* | < / \_ * | < / \_
* By entheh. | \/ /\ / * By entheh. | \/ /\ /
* \_ / > / * \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <string.h> #include <string.h>
#include "dumb.h" #include "dumb.h"
void dumb_silence(sample_t *samples, long length) void dumb_silence(sample_t *samples, long length)
{ {
memset(samples, 0, length * sizeof(*samples)); memset(samples, 0, length * sizeof(*samples));
} }

View file

@ -1,93 +1,146 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* stdfile.c - stdio file input module. / / \ \ * stdfile.c - stdio file input module. / / \ \
* | < / \_ * | < / \_
* By entheh. | \/ /\ / * By entheh. | \/ /\ /
* \_ / > / * \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdio.h> #include <stdio.h>
#include "dumb.h" #include "dumb.h"
static void *dumb_stdfile_open(const char *filename) typedef struct dumb_stdfile
{ {
return fopen(filename, "rb"); FILE * file;
} long size;
} dumb_stdfile;
static int dumb_stdfile_skip(void *f, long n)
{ static void *dumb_stdfile_open(const char *filename)
return fseek(f, n, SEEK_CUR); {
} dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
if ( !file ) return 0;
file->file = fopen(filename, "rb");
fseek(file->file, 0, SEEK_END);
static int dumb_stdfile_getc(void *f) file->size = ftell(file->file);
{ fseek(file->file, 0, SEEK_SET);
return fgetc(f); return file;
} }
static long dumb_stdfile_getnc(char *ptr, long n, void *f) static int dumb_stdfile_skip(void *f, long n)
{ {
return fread(ptr, 1, n, f); dumb_stdfile * file = ( dumb_stdfile * ) f;
} return fseek(file->file, n, SEEK_CUR);
}
static void dumb_stdfile_close(void *f)
{ static int dumb_stdfile_getc(void *f)
fclose(f); {
} dumb_stdfile * file = ( dumb_stdfile * ) f;
return fgetc(file->file);
}
static DUMBFILE_SYSTEM stdfile_dfs = {
&dumb_stdfile_open,
&dumb_stdfile_skip, static long dumb_stdfile_getnc(char *ptr, long n, void *f)
&dumb_stdfile_getc, {
&dumb_stdfile_getnc, dumb_stdfile * file = ( dumb_stdfile * ) f;
&dumb_stdfile_close return fread(ptr, 1, n, file->file);
}; }
void dumb_register_stdfiles(void) static void dumb_stdfile_close(void *f)
{ {
register_dumbfile_system(&stdfile_dfs); dumb_stdfile * file = ( dumb_stdfile * ) f;
} fclose(file->file);
free(f);
}
static DUMBFILE_SYSTEM stdfile_dfs_leave_open = {
NULL,
&dumb_stdfile_skip, static void dumb_stdfile_noclose(void *f)
&dumb_stdfile_getc, {
&dumb_stdfile_getnc, free(f);
NULL }
};
static int dumb_stdfile_seek(void *f, long n)
DUMBFILE *dumbfile_open_stdfile(FILE *p) {
{ dumb_stdfile * file = ( dumb_stdfile * ) f;
DUMBFILE *d = dumbfile_open_ex(p, &stdfile_dfs_leave_open); return fseek(file->file, n, SEEK_SET);
}
return d;
}
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;
}

View 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
}

View file

@ -1,42 +1,43 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* itload.c - Code to read an Impulse Tracker / / \ \ * itload.c - Code to read an Impulse Tracker / / \ \
* file, opening and closing it for | < / \_ * file, opening and closing it for | < / \_
* you. | \/ /\ / * you. | \/ /\ /
* \_ / > / * \_ / > /
* By entheh. Don't worry Bob, you're credited | \ / / * By entheh. Don't worry Bob, you're credited | \ / /
* in itread.c! | ' / * in itread.c! | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_it_quick(): loads an IT file into a DUH struct, returning a /* 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 * 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. * the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_it_quick(const char *filename) DUH *dumb_load_it_quick(const char *filename)
{ {
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);
if (!f) if (!f)
return NULL; return NULL;
duh = dumb_read_it_quick(f); duh = dumb_read_it_quick(f);
dumbfile_close(f); dumbfile_close(f);
return duh; return duh;
} }

View file

@ -1,29 +1,29 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* itload2.c - Function to read an Impulse Tracker / / \ \ * itload2.c - Function to read an Impulse Tracker / / \ \
* file, opening and closing it for | < / \_ * file, opening and closing it for | < / \_
* you, and do an initial run-through. | \/ /\ / * you, and do an initial run-through. | \/ /\ /
* \_ / > / * \_ / > /
* Split off from itload.c by entheh. | \ / / * Split off from itload.c by entheh. | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_it(const char *filename) DUH *dumb_load_it(const char *filename)
{ {
DUH *duh = dumb_load_it_quick(filename); DUH *duh = dumb_load_it_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;
} }

View file

@ -1,247 +1,247 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* itmisc.c - Miscellaneous functions relating / / \ \ * itmisc.c - Miscellaneous functions relating / / \ \
* to module files. | < / \_ * to module files. | < / \_
* | \/ /\ / * | \/ /\ /
* By entheh. \_ / > / * By entheh. \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh) DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh)
{ {
return duh_get_raw_sigdata(duh, 0, SIGTYPE_IT); return duh_get_raw_sigdata(duh, -1, SIGTYPE_IT);
} }
const unsigned char *dumb_it_sd_get_song_message(DUMB_IT_SIGDATA *sd) const unsigned char *dumb_it_sd_get_song_message(DUMB_IT_SIGDATA *sd)
{ {
return sd ? sd->song_message : NULL; return sd ? sd->song_message : NULL;
} }
int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd) int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd)
{ {
return sd ? sd->n_orders : 0; return sd ? sd->n_orders : 0;
} }
int dumb_it_sd_get_n_samples(DUMB_IT_SIGDATA *sd) int dumb_it_sd_get_n_samples(DUMB_IT_SIGDATA *sd)
{ {
return sd ? sd->n_samples : 0; return sd ? sd->n_samples : 0;
} }
int dumb_it_sd_get_n_instruments(DUMB_IT_SIGDATA *sd) int dumb_it_sd_get_n_instruments(DUMB_IT_SIGDATA *sd)
{ {
return sd ? sd->n_instruments : 0; return sd ? sd->n_instruments : 0;
} }
const unsigned char *dumb_it_sd_get_sample_name(DUMB_IT_SIGDATA *sd, int i) 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); ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples);
return sd->sample[i].name; return sd->sample[i].name;
} }
const unsigned char *dumb_it_sd_get_sample_filename(DUMB_IT_SIGDATA *sd, int i) 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); ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples);
return sd->sample[i].filename; return sd->sample[i].filename;
} }
const unsigned char *dumb_it_sd_get_instrument_name(DUMB_IT_SIGDATA *sd, int i) 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); ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments);
return sd->instrument[i].name; return sd->instrument[i].name;
} }
const unsigned char *dumb_it_sd_get_instrument_filename(DUMB_IT_SIGDATA *sd, int i) 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); ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments);
return sd->instrument[i].filename; return sd->instrument[i].filename;
} }
int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd) int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd)
{ {
return sd ? sd->global_volume : 0; return sd ? sd->global_volume : 0;
} }
void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv) void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv)
{ {
if (sd) sd->global_volume = gv; if (sd) sd->global_volume = gv;
} }
int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd) int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd)
{ {
return sd ? sd->mixing_volume : 0; return sd ? sd->mixing_volume : 0;
} }
void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv) void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv)
{ {
if (sd) sd->mixing_volume = mv; if (sd) sd->mixing_volume = mv;
} }
int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd) int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd)
{ {
return sd ? sd->speed : 0; return sd ? sd->speed : 0;
} }
void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed) void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed)
{ {
if (sd) sd->speed = speed; if (sd) sd->speed = speed;
} }
int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd) int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd)
{ {
return sd ? sd->tempo : 0; return sd ? sd->tempo : 0;
} }
void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo) void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo)
{ {
if (sd) sd->tempo = tempo; if (sd) sd->tempo = tempo;
} }
int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel) int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel)
{ {
ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS); ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
return sd ? sd->channel_volume[channel] : 0; return sd ? sd->channel_volume[channel] : 0;
} }
void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume) void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume)
{ {
ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS); ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
if (sd) sd->channel_volume[channel] = volume; if (sd) sd->channel_volume[channel] = volume;
} }
int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr) int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr)
{ {
return sr ? sr->order : -1; return sr ? sr->order : -1;
} }
int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr) int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr)
{ {
return sr ? sr->row : -1; return sr ? sr->row : -1;
} }
int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr) int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr)
{ {
return sr ? sr->globalvolume : 0; return sr ? sr->globalvolume : 0;
} }
void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv) void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv)
{ {
if (sr) sr->globalvolume = gv; if (sr) sr->globalvolume = gv;
} }
int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr) int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr)
{ {
return sr ? sr->tempo : 0; return sr ? sr->tempo : 0;
} }
void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo) void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo)
{ {
if (sr) sr->tempo = tempo; if (sr) sr->tempo = tempo;
} }
int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr) int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr)
{ {
return sr ? sr->speed : 0; return sr ? sr->speed : 0;
} }
void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed) void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed)
{ {
if (sr) sr->speed = speed; if (sr) sr->speed = speed;
} }
int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel) int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel)
{ {
return sr ? sr->channel[channel].channelvolume : 0; return sr ? sr->channel[channel].channelvolume : 0;
} }
void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume) void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume)
{ {
if (sr) sr->channel[channel].channelvolume = volume; if (sr) sr->channel[channel].channelvolume = volume;
} }
void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel, int muted) void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel, int muted)
{ {
if (sr) { if (sr) {
if (muted) if (muted)
sr->channel[channel].flags |= IT_CHANNEL_MUTED; sr->channel[channel].flags |= IT_CHANNEL_MUTED;
else else
sr->channel[channel].flags &= ~IT_CHANNEL_MUTED; sr->channel[channel].flags &= ~IT_CHANNEL_MUTED;
} }
} }
int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel) int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel)
{ {
return sr ? (sr->channel[channel].flags & IT_CHANNEL_MUTED) != 0 : 0; return sr ? (sr->channel[channel].flags & IT_CHANNEL_MUTED) != 0 : 0;
} }

View file

@ -1,63 +1,63 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* itorder.c - Code to fix invalid patterns in / / \ \ * itorder.c - Code to fix invalid patterns in / / \ \
* the pattern table. | < / \_ * the pattern table. | < / \_
* | \/ /\ / * | \/ /\ /
* By Julien Cugniere. \_ / > / * By Julien Cugniere. \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* This function ensures that any pattern mentioned in the order table but /* 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. * 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 * This is done by adding such a dummy pattern at the end of the pattern
* table, and redirect invalid orders to it. * table, and redirect invalid orders to it.
* Patterns 254 and 255 are left untouched, unless the signal is an XM. * Patterns 254 and 255 are left untouched, unless the signal is an XM.
*/ */
int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata) int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata)
{ {
int i; int i;
int found_some = 0; int found_some = 0;
int first_invalid = sigdata->n_patterns; int first_invalid = sigdata->n_patterns;
int last_invalid = (sigdata->flags & IT_WAS_AN_XM) ? 255 : 253; int last_invalid = (sigdata->flags & IT_WAS_AN_XM) ? 255 : 253;
for (i = 0; i < sigdata->n_orders; i++) { for (i = 0; i < sigdata->n_orders; i++) {
if (sigdata->order[i] >= first_invalid && sigdata->order[i] <= last_invalid) { if (sigdata->order[i] >= first_invalid && sigdata->order[i] <= last_invalid) {
sigdata->order[i] = sigdata->n_patterns; sigdata->order[i] = sigdata->n_patterns;
found_some = 1; found_some = 1;
} }
} }
if (found_some) { if (found_some) {
IT_PATTERN *new_pattern = realloc(sigdata->pattern, sizeof(*sigdata->pattern) * (sigdata->n_patterns + 1)); IT_PATTERN *new_pattern = realloc(sigdata->pattern, sizeof(*sigdata->pattern) * (sigdata->n_patterns + 1));
if (!new_pattern) if (!new_pattern)
return -1; return -1;
new_pattern[sigdata->n_patterns].n_rows = 64; new_pattern[sigdata->n_patterns].n_rows = 64;
new_pattern[sigdata->n_patterns].n_entries = 0; new_pattern[sigdata->n_patterns].n_entries = 0;
new_pattern[sigdata->n_patterns].entry = NULL; new_pattern[sigdata->n_patterns].entry = NULL;
sigdata->pattern = new_pattern; sigdata->pattern = new_pattern;
sigdata->n_patterns++; sigdata->n_patterns++;
} }
return 0; return 0;
} }

File diff suppressed because it is too large Load diff

View file

@ -1,29 +1,29 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* itread2.c - Function to read an Impulse Tracker / / \ \ * itread2.c - Function to read an Impulse Tracker / / \ \
* module from an open file and do an | < / \_ * module from an open file and do an | < / \_
* initial run-through. | \/ /\ / * initial run-through. | \/ /\ /
* \_ / > / * \_ / > /
* Split off from itread.c by entheh. | \ / / * Split off from itread.c by entheh. | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
DUH *dumb_read_it(DUMBFILE *f) DUH *dumb_read_it(DUMBFILE *f)
{ {
DUH *duh = dumb_read_it_quick(f); DUH *duh = dumb_read_it_quick(f);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;
} }

File diff suppressed because it is too large Load diff

View file

@ -1,72 +1,72 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* itunload.c - Code to free an Impulse Tracker / / \ \ * itunload.c - Code to free an Impulse Tracker / / \ \
* module from memory. | < / \_ * module from memory. | < / \_
* | \/ /\ / * | \/ /\ /
* By entheh. \_ / > / * By entheh. \_ / > /
* | \ / / * | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
void _dumb_it_unload_sigdata(sigdata_t *vsigdata) void _dumb_it_unload_sigdata(sigdata_t *vsigdata)
{ {
if (vsigdata) { if (vsigdata) {
DUMB_IT_SIGDATA *sigdata = vsigdata; DUMB_IT_SIGDATA *sigdata = vsigdata;
int n; int n;
if (sigdata->song_message) if (sigdata->song_message)
free(sigdata->song_message); free(sigdata->song_message);
if (sigdata->order) if (sigdata->order)
free(sigdata->order); free(sigdata->order);
if (sigdata->instrument) if (sigdata->instrument)
free(sigdata->instrument); free(sigdata->instrument);
if (sigdata->sample) { if (sigdata->sample) {
for (n = 0; n < sigdata->n_samples; n++) for (n = 0; n < sigdata->n_samples; n++)
if (sigdata->sample[n].data) if (sigdata->sample[n].data)
free(sigdata->sample[n].data); free(sigdata->sample[n].data);
free(sigdata->sample); free(sigdata->sample);
} }
if (sigdata->pattern) { if (sigdata->pattern) {
for (n = 0; n < sigdata->n_patterns; n++) for (n = 0; n < sigdata->n_patterns; n++)
if (sigdata->pattern[n].entry) if (sigdata->pattern[n].entry)
free(sigdata->pattern[n].entry); free(sigdata->pattern[n].entry);
free(sigdata->pattern); free(sigdata->pattern);
} }
if (sigdata->midi) if (sigdata->midi)
free(sigdata->midi); free(sigdata->midi);
{ {
IT_CHECKPOINT *checkpoint = sigdata->checkpoint; IT_CHECKPOINT *checkpoint = sigdata->checkpoint;
while (checkpoint) { while (checkpoint) {
IT_CHECKPOINT *next = checkpoint->next; IT_CHECKPOINT *next = checkpoint->next;
_dumb_it_end_sigrenderer(checkpoint->sigrenderer); _dumb_it_end_sigrenderer(checkpoint->sigrenderer);
free(checkpoint); free(checkpoint);
checkpoint = next; checkpoint = next;
} }
} }
free(vsigdata); free(vsigdata);
} }
} }

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View file

@ -1,42 +1,42 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* loadmod.c - Code to read a good old-fashioned / / \ \ * loadmod.c - Code to read a good old-fashioned / / \ \
* Amiga module file, opening and | < / \_ * Amiga module file, opening and | < / \_
* closing it for you. | \/ /\ / * closing it for you. | \/ /\ /
* \_ / > / * \_ / > /
* By entheh. | \ / / * By entheh. | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_mod_quick(): loads a MOD file into a DUH struct, returning a /* 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 * 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. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_mod_quick(const char *filename) DUH *dumb_load_mod_quick(const char *filename, int restrict_)
{ {
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);
if (!f) if (!f)
return NULL; return NULL;
duh = dumb_read_mod_quick(f); duh = dumb_read_mod_quick(f, restrict_);
dumbfile_close(f); dumbfile_close(f);
return duh; return duh;
} }

View file

@ -1,29 +1,29 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* loadmod2.c - Function to read a good old- / / \ \ * loadmod2.c - Function to read a good old- / / \ \
* fashioned Amiga module file, | < / \_ * fashioned Amiga module file, | < / \_
* opening and closing it for you, | \/ /\ / * opening and closing it for you, | \/ /\ /
* and do an initial run-through. \_ / > / * and do an initial run-through. \_ / > /
* | \ / / * | \ / /
* Split off from loadmod.c by entheh. | ' / * Split off from loadmod.c by entheh. | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_mod(const char *filename) DUH *dumb_load_mod(const char *filename, int restrict_)
{ {
DUH *duh = dumb_load_mod_quick(filename); DUH *duh = dumb_load_mod_quick(filename, restrict_);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;
} }

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View file

@ -1,42 +1,42 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* loads3m.c - Code to read a ScreamTracker 3 / / \ \ * loads3m.c - Code to read a ScreamTracker 3 / / \ \
* file, opening and closing it for | < / \_ * file, opening and closing it for | < / \_
* you. | \/ /\ / * you. | \/ /\ /
* \_ / > / * \_ / > /
* By entheh. | \ / / * By entheh. | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_s3m_quick(): loads an S3M file into a DUH struct, returning /* 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 * 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. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_s3m_quick(const char *filename) DUH *dumb_load_s3m_quick(const char *filename)
{ {
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);
if (!f) if (!f)
return NULL; return NULL;
duh = dumb_read_s3m_quick(f); duh = dumb_read_s3m_quick(f);
dumbfile_close(f); dumbfile_close(f);
return duh; return duh;
} }

View file

@ -1,29 +1,29 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* loads3m2.c - Function to read a ScreamTracker 3 / / \ \ * loads3m2.c - Function to read a ScreamTracker 3 / / \ \
* file, opening and closing it for | < / \_ * file, opening and closing it for | < / \_
* you, and do an initial run-through. | \/ /\ / * you, and do an initial run-through. | \/ /\ /
* \_ / > / * \_ / > /
* Split off from loads3m.c by entheh. | \ / / * Split off from loads3m.c by entheh. | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_s3m(const char *filename) DUH *dumb_load_s3m(const char *filename)
{ {
DUH *duh = dumb_load_s3m_quick(filename); DUH *duh = dumb_load_s3m_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;
} }

View 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;
}

View 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;
}

View file

@ -1,42 +1,42 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* loadxm.c - Code to read a Fast Tracker II / / \ \ * loadxm.c - Code to read a Fast Tracker II / / \ \
* file, opening and closing it for | < / \_ * file, opening and closing it for | < / \_
* you. | \/ /\ / * you. | \/ /\ /
* \_ / > / * \_ / > /
* By entheh. | \ / / * By entheh. | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_xm_quick(): loads an XM file into a DUH struct, returning a /* 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 * 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. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_xm_quick(const char *filename) DUH *dumb_load_xm_quick(const char *filename)
{ {
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);
if (!f) if (!f)
return NULL; return NULL;
duh = dumb_read_xm_quick(f); duh = dumb_read_xm_quick(f);
dumbfile_close(f); dumbfile_close(f);
return duh; return duh;
} }

View file

@ -1,29 +1,29 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* loadxm2.c - Function to read a Fast Tracker II / / \ \ * loadxm2.c - Function to read a Fast Tracker II / / \ \
* file, opening and closing it for | < / \_ * file, opening and closing it for | < / \_
* you, and do an initial run-through. | \/ /\ / * you, and do an initial run-through. | \/ /\ /
* \_ / > / * \_ / > /
* Split off from loadxm.c by entheh. | \ / / * Split off from loadxm.c by entheh. | \ / /
* | ' / * | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_xm(const char *filename) DUH *dumb_load_xm(const char *filename)
{ {
DUH *duh = dumb_load_xm_quick(filename); DUH *duh = dumb_load_xm_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;
} }

View 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;
}

View 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);
}
}

View 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;
}

View 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 );
}
}

View 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);
}
}

View 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;
}

View 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;
}

View 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;
}

View 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);
}
}

View 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

View file

@ -1,29 +1,29 @@
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| | * | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' ' * | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . . * | | | | | | || || | | . .
* | |_/ / \ \__// || | | * | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* readmod2.c - Function to read a good old- / / \ \ * readmod2.c - Function to read a good old- / / \ \
* fashioned Amiga module from an | < / \_ * fashioned Amiga module from an | < / \_
* open file and do an initial | \/ /\ / * open file and do an initial | \/ /\ /
* run-through. \_ / > / * run-through. \_ / > /
* | \ / / * | \ / /
* Split off from readmod.c by entheh. | ' / * Split off from readmod.c by entheh. | ' /
* \__/ * \__/
*/ */
#include "dumb.h" #include "dumb.h"
DUH *dumb_read_mod(DUMBFILE *f) DUH *dumb_read_mod(DUMBFILE *f, int restrict_)
{ {
DUH *duh = dumb_read_mod_quick(f); DUH *duh = dumb_read_mod_quick(f, restrict_);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;
} }

View 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);
}
}

View 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