EmuSC experiment goes here
This is mostly working, but kind of buggy. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
e7779278bd
commit
e233a95c2a
12 changed files with 1277 additions and 205 deletions
|
@ -23,6 +23,13 @@
|
|||
8356BCD527B354050074E50C /* libbasswv.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8356BCCD27B353E30074E50C /* libbasswv.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
83686AAC1C5C69D400671C7A /* AUPlayerView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83686AAB1C5C69D400671C7A /* AUPlayerView.mm */; };
|
||||
83686AB11C5C783000671C7A /* CoreAudioKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83686AB01C5C783000671C7A /* CoreAudioKit.framework */; };
|
||||
836E66962D854D5700B62C38 /* SCPlayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 836E66952D854D5600B62C38 /* SCPlayer.mm */; };
|
||||
836E66992D855A7500B62C38 /* libemusc.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 836E66982D855A7500B62C38 /* libemusc.0.dylib */; };
|
||||
836E669E2D855AC600B62C38 /* r00233567_control.bin in Resources */ = {isa = PBXBuildFile; fileRef = 836E669A2D855AAF00B62C38 /* r00233567_control.bin */; };
|
||||
836E669F2D855AC800B62C38 /* r15199858_main_mcu.bin in Resources */ = {isa = PBXBuildFile; fileRef = 836E669B2D855AAF00B62C38 /* r15199858_main_mcu.bin */; };
|
||||
836E66A02D855ACA00B62C38 /* r15209359_pcm_1.bin in Resources */ = {isa = PBXBuildFile; fileRef = 836E669C2D855AAF00B62C38 /* r15209359_pcm_1.bin */; };
|
||||
836E66A12D855ACC00B62C38 /* r15279813_pcm_2.bin in Resources */ = {isa = PBXBuildFile; fileRef = 836E669D2D855AAF00B62C38 /* r15279813_pcm_2.bin */; };
|
||||
836E66A22D855B2700B62C38 /* libemusc.0.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836E66982D855A7500B62C38 /* libemusc.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
8398F2E01C438C7D00EB9639 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8398F2DF1C438C7D00EB9639 /* AudioUnit.framework */; };
|
||||
839CA224180D902100553DBA /* midi_processing.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83B066E0180D56BA008E3612 /* midi_processing.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
83A09F621CFA83F2001E7D2D /* i_oplmusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83A09F561CFA83F2001E7D2D /* i_oplmusic.cpp */; };
|
||||
|
@ -66,6 +73,7 @@
|
|||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
839CA224180D902100553DBA /* midi_processing.framework in CopyFiles */,
|
||||
836E66A22D855B2700B62C38 /* libemusc.0.dylib in CopyFiles */,
|
||||
83EA54232A6A6CF400CD0580 /* libbass_mpc.dylib in CopyFiles */,
|
||||
8356BCD127B353F60074E50C /* libbass.dylib in CopyFiles */,
|
||||
8356BCD227B353F90074E50C /* libbassmidi.dylib in CopyFiles */,
|
||||
|
@ -115,6 +123,13 @@
|
|||
83686AAD1C5C6A2700671C7A /* AUPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AUPlayerView.h; sourceTree = "<group>"; };
|
||||
83686AAE1C5C780500671C7A /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
|
||||
83686AB01C5C783000671C7A /* CoreAudioKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudioKit.framework; path = System/Library/Frameworks/CoreAudioKit.framework; sourceTree = SDKROOT; };
|
||||
836E66942D854D5600B62C38 /* SCPlayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SCPlayer.h; sourceTree = "<group>"; };
|
||||
836E66952D854D5600B62C38 /* SCPlayer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SCPlayer.mm; sourceTree = "<group>"; };
|
||||
836E66982D855A7500B62C38 /* libemusc.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libemusc.0.dylib; path = /Users/chris/Source/Repos/cog/ThirdParty/libemusc/lib/libemusc.0.dylib; sourceTree = "<absolute>"; };
|
||||
836E669A2D855AAF00B62C38 /* r00233567_control.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = r00233567_control.bin; sourceTree = "<group>"; };
|
||||
836E669B2D855AAF00B62C38 /* r15199858_main_mcu.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = r15199858_main_mcu.bin; sourceTree = "<group>"; };
|
||||
836E669C2D855AAF00B62C38 /* r15209359_pcm_1.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = r15209359_pcm_1.bin; sourceTree = "<group>"; };
|
||||
836E669D2D855AAF00B62C38 /* r15279813_pcm_2.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = r15279813_pcm_2.bin; sourceTree = "<group>"; };
|
||||
83747C222862DB7F0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
838EE8CA29A8600C00CD0580 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
8398F2DF1C438C7D00EB9639 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; };
|
||||
|
@ -171,6 +186,7 @@
|
|||
8398F2E01C438C7D00EB9639 /* AudioUnit.framework in Frameworks */,
|
||||
83686AB11C5C783000671C7A /* CoreAudioKit.framework in Frameworks */,
|
||||
83B06701180D5747008E3612 /* midi_processing.framework in Frameworks */,
|
||||
836E66992D855A7500B62C38 /* libemusc.0.dylib in Frameworks */,
|
||||
8356BCCA27B353CB0074E50C /* libbassmidi.dylib in Frameworks */,
|
||||
8356BCC927B353CB0074E50C /* libbass.dylib in Frameworks */,
|
||||
83B0668B180D5668008E3612 /* Cocoa.framework in Frameworks */,
|
||||
|
@ -206,6 +222,17 @@
|
|||
path = ../../../ThirdParty/json;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
836E66972D855A2600B62C38 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
836E669A2D855AAF00B62C38 /* r00233567_control.bin */,
|
||||
836E669B2D855AAF00B62C38 /* r15199858_main_mcu.bin */,
|
||||
836E669C2D855AAF00B62C38 /* r15209359_pcm_1.bin */,
|
||||
836E669D2D855AAF00B62C38 /* r15279813_pcm_2.bin */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83747C212862DB7F0021245F /* Xcode-config */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -263,6 +290,7 @@
|
|||
83B0667E180D5668008E3612 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
836E66972D855A2600B62C38 /* Resources */,
|
||||
83747C212862DB7F0021245F /* Xcode-config */,
|
||||
83B06690180D5668008E3612 /* MIDI */,
|
||||
83B06689180D5668008E3612 /* Frameworks */,
|
||||
|
@ -295,6 +323,7 @@
|
|||
83B0668C180D5668008E3612 /* Other Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
836E66982D855A7500B62C38 /* libemusc.0.dylib */,
|
||||
83EA54212A6A6CE200CD0580 /* libbass_mpc.dylib */,
|
||||
8356BCC727B353CB0074E50C /* libbass.dylib */,
|
||||
8356BCC827B353CB0074E50C /* libbassmidi.dylib */,
|
||||
|
@ -311,6 +340,8 @@
|
|||
83B06690180D5668008E3612 /* MIDI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
836E66942D854D5600B62C38 /* SCPlayer.h */,
|
||||
836E66952D854D5600B62C38 /* SCPlayer.mm */,
|
||||
834A42BC287AFC7F00EB9D9B /* AudioChunk.h */,
|
||||
8307D31E28607377000FF8EB /* SandboxBroker.h */,
|
||||
831E2A9127B4B2FA006F1C86 /* json */,
|
||||
|
@ -445,6 +476,10 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
83B06695180D5668008E3612 /* InfoPlist.strings in Resources */,
|
||||
836E669E2D855AC600B62C38 /* r00233567_control.bin in Resources */,
|
||||
836E669F2D855AC800B62C38 /* r15199858_main_mcu.bin in Resources */,
|
||||
836E66A02D855ACA00B62C38 /* r15209359_pcm_1.bin in Resources */,
|
||||
836E66A12D855ACC00B62C38 /* r15279813_pcm_2.bin in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -471,6 +506,7 @@
|
|||
83A09F651CFA83F2001E7D2D /* opl3class.cpp in Sources */,
|
||||
83C35705180EDD1C007E9DF0 /* MIDIMetadataReader.mm in Sources */,
|
||||
834BE91B1DE407CB00A07DCD /* resampler.c in Sources */,
|
||||
836E66962D854D5700B62C38 /* SCPlayer.mm in Sources */,
|
||||
83A09F641CFA83F2001E7D2D /* opl3.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -623,6 +659,7 @@
|
|||
HEADER_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/../../ThirdParty/BASS",
|
||||
"$(SRCROOT)/../../ThirdParty/json",
|
||||
"$(SRCROOT)/../../ThirdParty/libemusc/include",
|
||||
);
|
||||
INFOPLIST_FILE = "MIDI/MIDI-Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
|
||||
|
@ -630,6 +667,8 @@
|
|||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/../../ThirdParty/BASS",
|
||||
"$(PROJECT_DIR)/../../ThirdParty/libemusc/lib",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.kode54.midi;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -649,6 +688,7 @@
|
|||
HEADER_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/../../ThirdParty/BASS",
|
||||
"$(SRCROOT)/../../ThirdParty/json",
|
||||
"$(SRCROOT)/../../ThirdParty/libemusc/include",
|
||||
);
|
||||
INFOPLIST_FILE = "MIDI/MIDI-Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
|
||||
|
@ -656,6 +696,8 @@
|
|||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/../../ThirdParty/BASS",
|
||||
"$(PROJECT_DIR)/../../ThirdParty/libemusc/lib",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.kode54.midi;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#import "AUPlayer.h"
|
||||
#import "BMPlayer.h"
|
||||
#import "MSPlayer.h"
|
||||
#import "SCPlayer.h"
|
||||
|
||||
#import "Logging.h"
|
||||
|
||||
|
@ -244,14 +245,19 @@ static OSType getOSType(const char *in_) {
|
|||
} else if([[plugin substringToIndex:5] isEqualToString:@"OPL3W"]) {
|
||||
MSPlayer *msplayer = new MSPlayer;
|
||||
player = msplayer;
|
||||
|
||||
|
||||
msplayer->set_synth(1);
|
||||
|
||||
|
||||
msplayer->set_bank([[plugin substringFromIndex:5] intValue]);
|
||||
|
||||
|
||||
msplayer->set_extp(1);
|
||||
|
||||
|
||||
msplayer->setSampleRate(sampleRate);
|
||||
} else if([plugin isEqualToString:@"emusc"]) {
|
||||
SCPlayer *scplayer = new SCPlayer;
|
||||
player = scplayer;
|
||||
|
||||
scplayer->setSampleRate(sampleRate);
|
||||
} else {
|
||||
const char *cplugin = [plugin UTF8String];
|
||||
OSType componentSubType;
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "synth.h"
|
||||
|
||||
class SCPlayer : public MIDIPlayer {
|
||||
public:
|
||||
// zero variables
|
||||
|
@ -22,9 +24,6 @@ class SCPlayer : public MIDIPlayer {
|
|||
virtual void shutdown();
|
||||
virtual bool startup();
|
||||
|
||||
virtual void send_event_time(uint32_t b, unsigned int time);
|
||||
virtual void send_sysex_time(const uint8_t* event, size_t size, size_t port, unsigned int time);
|
||||
|
||||
private:
|
||||
bool LoadCore();
|
||||
|
||||
|
@ -45,10 +44,9 @@ class SCPlayer : public MIDIPlayer {
|
|||
void process_write_code(uint32_t port, uint32_t code);
|
||||
void process_write_bytes(uint32_t port, const void* buffer, uint32_t size);
|
||||
|
||||
bool bTerminating[3];
|
||||
NSTask* hProcess[3];
|
||||
NSPipe* hChildStd_IN[3];
|
||||
NSPipe* hChildStd_OUT[3];
|
||||
EmuSC::ControlRom *_controlROM;
|
||||
EmuSC::PcmRom *_pcmROM;
|
||||
EmuSC::Synth *_synth[3];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,134 +2,13 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
static uint16_t getwordle(uint8_t *pData) {
|
||||
return (uint16_t)(pData[0] | (((uint16_t)pData[1]) << 8));
|
||||
}
|
||||
|
||||
static uint32_t getdwordle(uint8_t *pData) {
|
||||
return pData[0] | (((uint32_t)pData[1]) << 8) | (((uint32_t)pData[2]) << 16) | (((uint32_t)pData[3]) << 24);
|
||||
}
|
||||
|
||||
bool SCPlayer::LoadCore() {
|
||||
bool rval = process_create(0);
|
||||
if(rval) rval = process_create(1);
|
||||
if(rval) rval = process_create(2);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool SCPlayer::process_create(uint32_t port) {
|
||||
bTerminating[port] = false;
|
||||
|
||||
hChildStd_IN[port] = [[NSPipe alloc] init];
|
||||
hChildStd_OUT[port] = [[NSPipe alloc] init];
|
||||
|
||||
NSURL *launcherUrl = [[NSBundle mainBundle] URLForResource:@"scpipe" withExtension:@""];
|
||||
NSURL *coreUrl = [[NSBundle mainBundle] URLForResource:@"IIAM" withExtension:@"bin"];
|
||||
|
||||
hProcess[port] = [[NSTask alloc] init];
|
||||
[hProcess[port] setExecutableURL:launcherUrl];
|
||||
[hProcess[port] setArguments:@[[coreUrl path]]];
|
||||
[hProcess[port] setStandardInput:hChildStd_IN[port]];
|
||||
[hProcess[port] setStandardOutput:hChildStd_OUT[port]];
|
||||
|
||||
NSError *error = nil;
|
||||
if(![hProcess[port] launchAndReturnError:&error] || error != nil) {
|
||||
process_terminate(port);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t code = process_read_code(port);
|
||||
|
||||
if(code != 0) {
|
||||
process_terminate(port);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SCPlayer::process_terminate(uint32_t port) {
|
||||
if(bTerminating[port]) return;
|
||||
|
||||
bTerminating[port] = true;
|
||||
|
||||
if(hProcess[port]) {
|
||||
process_write_code(port, 0);
|
||||
[hProcess[port] interrupt];
|
||||
[hProcess[port] waitUntilExit];
|
||||
[hProcess[port] terminate];
|
||||
hProcess[port] = nil;
|
||||
}
|
||||
if(hChildStd_IN[port]) {
|
||||
hChildStd_IN[port] = nil;
|
||||
}
|
||||
if(hChildStd_OUT[port]) {
|
||||
hChildStd_OUT[port] = nil;
|
||||
}
|
||||
|
||||
bTerminating[port] = false;
|
||||
}
|
||||
|
||||
bool SCPlayer::process_running(uint32_t port) {
|
||||
if(hProcess[port] && [hProcess[port] isRunning]) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t SCPlayer::process_read_bytes_pass(uint32_t port, void *out, uint32_t size) {
|
||||
NSError *error = nil;
|
||||
NSData *data = [[hChildStd_OUT[port] fileHandleForReading] readDataUpToLength:size error:&error];
|
||||
if(!data || error) return 0;
|
||||
NSUInteger bytesDone = [data length];
|
||||
memcpy(out, [data bytes], bytesDone);
|
||||
return bytesDone;
|
||||
}
|
||||
|
||||
void SCPlayer::process_read_bytes(uint32_t port, void *out, uint32_t size) {
|
||||
if(process_running(port) && size) {
|
||||
uint8_t *ptr = (uint8_t *)out;
|
||||
uint32_t done = 0;
|
||||
while(done < size) {
|
||||
uint32_t delta = process_read_bytes_pass(port, ptr + done, size - done);
|
||||
if(delta == 0) {
|
||||
memset(out, 0xFF, size);
|
||||
break;
|
||||
}
|
||||
done += delta;
|
||||
}
|
||||
} else
|
||||
memset(out, 0xFF, size);
|
||||
}
|
||||
|
||||
uint32_t SCPlayer::process_read_code(uint32_t port) {
|
||||
uint32_t code;
|
||||
process_read_bytes(port, &code, sizeof(code));
|
||||
return code;
|
||||
}
|
||||
|
||||
void SCPlayer::process_write_bytes(uint32_t port, const void *in, uint32_t size) {
|
||||
if(process_running(port)) {
|
||||
if(size == 0) return;
|
||||
NSError *error = nil;
|
||||
NSData *data = [NSData dataWithBytes:in length:size];
|
||||
if(![[hChildStd_IN[port] fileHandleForWriting] writeData:data error:&error] || error) {
|
||||
process_terminate(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SCPlayer::process_write_code(uint32_t port, uint32_t code) {
|
||||
process_write_bytes(port, &code, sizeof(code));
|
||||
}
|
||||
|
||||
SCPlayer::SCPlayer()
|
||||
: MIDIPlayer() {
|
||||
initialized = false;
|
||||
_controlROM = NULL;
|
||||
_pcmROM = NULL;
|
||||
for(unsigned int i = 0; i < 3; ++i) {
|
||||
bTerminating[i] = false;
|
||||
hProcess[i] = nil;
|
||||
hChildStd_IN[i] = nil;
|
||||
hChildStd_OUT[i] = nil;
|
||||
_synth[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,95 +19,57 @@ SCPlayer::~SCPlayer() {
|
|||
void SCPlayer::send_event(uint32_t b) {
|
||||
uint32_t port = (b >> 24) & 0xFF;
|
||||
if(port > 2) port = 0;
|
||||
process_write_code(port, 2);
|
||||
process_write_code(port, b & 0xFFFFFF);
|
||||
if(process_read_code(port) != 0)
|
||||
process_terminate(port);
|
||||
_synth[port]->midi_input(b & 0xFF, (b >> 8) & 0xFF, (b >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
void SCPlayer::send_sysex(const uint8_t *event, size_t size, size_t port) {
|
||||
process_write_code(port, 3);
|
||||
process_write_code(port, (uint32_t)size);
|
||||
process_write_bytes(port, event, size);
|
||||
if(process_read_code(port) != 0)
|
||||
process_terminate(port);
|
||||
if(port == 0) {
|
||||
send_sysex(event, size, 1);
|
||||
send_sysex(event, size, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void SCPlayer::send_event_time(uint32_t b, unsigned int time) {
|
||||
uint32_t port = (b >> 24) & 0xFF;
|
||||
if(port > 2) port = 0;
|
||||
process_write_code(port, 6);
|
||||
process_write_code(port, b & 0xFFFFFF);
|
||||
process_write_code(port, time);
|
||||
if(process_read_code(port) != 0)
|
||||
process_terminate(port);
|
||||
}
|
||||
|
||||
void SCPlayer::send_sysex_time(const uint8_t *event, size_t size, size_t port, unsigned int time) {
|
||||
process_write_code(port, 7);
|
||||
process_write_code(port, size);
|
||||
process_write_code(port, time);
|
||||
process_write_bytes(port, event, size);
|
||||
if(process_read_code(port) != 0)
|
||||
process_terminate(port);
|
||||
if(port == 0) {
|
||||
send_sysex_time(event, size, 1, time);
|
||||
send_sysex_time(event, size, 2, time);
|
||||
}
|
||||
}
|
||||
|
||||
void SCPlayer::render_port(uint32_t port, float *out, uint32_t count) {
|
||||
process_write_code(port, 4);
|
||||
process_write_code(port, count);
|
||||
if(process_read_code(port) != 0) {
|
||||
process_terminate(port);
|
||||
memset(out, 0, count * sizeof(float) * 2);
|
||||
return;
|
||||
}
|
||||
process_read_bytes(port, out, count * sizeof(float) * 2);
|
||||
_synth[0]->midi_input_sysex(event, size);
|
||||
_synth[1]->midi_input_sysex(event, size);
|
||||
_synth[2]->midi_input_sysex(event, size);
|
||||
}
|
||||
|
||||
void SCPlayer::render(float *out, unsigned long count) {
|
||||
memset(out, 0, count * sizeof(float) * 2);
|
||||
while(count) {
|
||||
unsigned long todo = count > 4096 ? 4096 : count;
|
||||
float buffer[4096 * 2];
|
||||
for(unsigned long i = 0; i < 3; ++i) {
|
||||
render_port(i, buffer, todo);
|
||||
|
||||
for(unsigned long j = 0; j < todo; ++j) {
|
||||
out[j * 2 + 0] += buffer[j * 2 + 0];
|
||||
out[j * 2 + 1] += buffer[j * 2 + 1];
|
||||
}
|
||||
}
|
||||
out += todo * 2;
|
||||
count -= todo;
|
||||
for(unsigned long i = 0; i < count; ++i) {
|
||||
float sampleOut[6];
|
||||
_synth[0]->get_next_sample(sampleOut + 0);
|
||||
_synth[1]->get_next_sample(sampleOut + 2);
|
||||
_synth[2]->get_next_sample(sampleOut + 4);
|
||||
out[0] = sampleOut[0] + sampleOut[2] + sampleOut[4];
|
||||
out[1] = sampleOut[1] + sampleOut[3] + sampleOut[5];
|
||||
out += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void SCPlayer::shutdown() {
|
||||
for(int i = 0; i < 3; i++) {
|
||||
process_terminate(i);
|
||||
delete _synth[i];
|
||||
_synth[i] = NULL;
|
||||
}
|
||||
delete _pcmROM;
|
||||
_pcmROM = NULL;
|
||||
delete _controlROM;
|
||||
_controlROM = NULL;
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
bool SCPlayer::startup() {
|
||||
if(initialized) return true;
|
||||
|
||||
if(!LoadCore())
|
||||
return false;
|
||||
NSBundle *bundle = [NSBundle bundleWithIdentifier:@"net.kode54.midi"];
|
||||
NSString *controlROMPath = [bundle pathForResource:@"r00233567_control" ofType:@"bin"];
|
||||
NSString *cpuROMPath = [bundle pathForResource:@"r15199858_main_mcu" ofType:@"bin"];
|
||||
NSString *pcmROMPath0 = [bundle pathForResource:@"r15209359_pcm_1" ofType:@"bin"];
|
||||
NSString *pcmROMPath1 = [bundle pathForResource:@"r15279813_pcm_2" ofType:@"bin"];
|
||||
|
||||
_controlROM = new EmuSC::ControlRom(std::string([controlROMPath UTF8String]), std::string([cpuROMPath UTF8String]));
|
||||
_pcmROM = new EmuSC::PcmRom({ std::string([pcmROMPath0 UTF8String]), std::string([pcmROMPath1 UTF8String]) }, *_controlROM);
|
||||
|
||||
for(int i = 0; i < 3; i++) {
|
||||
process_write_code(i, 1);
|
||||
process_write_code(i, sizeof(uint32_t));
|
||||
process_write_code(i, uSampleRate);
|
||||
if(process_read_code(i) != 0)
|
||||
return false;
|
||||
_synth[i] = new EmuSC::Synth(*_controlROM, *_pcmROM);
|
||||
_synth[i]->set_audio_format(uSampleRate, 2);
|
||||
if(i > 0) {
|
||||
_synth[i]->set_param(EmuSC::SystemParam::DeviceID, (uint8_t)(17 + i));
|
||||
}
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
|
@ -239,5 +80,5 @@ bool SCPlayer::startup() {
|
|||
}
|
||||
|
||||
unsigned int SCPlayer::send_event_needs_time() {
|
||||
return 0; // 4096; This doesn't work for some reason
|
||||
return 0;
|
||||
}
|
||||
|
|
0
Plugins/MIDI/Resources/unzip-sc55mk2.zip-here.txt
Normal file
0
Plugins/MIDI/Resources/unzip-sc55mk2.zip-here.txt
Normal file
|
@ -68,6 +68,8 @@ static void enumCallback(void *context, OSType uSubType, OSType uManufacturer, c
|
|||
|
||||
[self addObject:@{@"name": @"BASSMIDI", @"preference": @"BASSMIDI"}];
|
||||
|
||||
[self addObject:@{@"name": @"EmuSC", @"preference": @"emusc"}];
|
||||
|
||||
[self addObject:@{@"name": @"DMX Generic", @"preference": @"DOOM0000"}];
|
||||
[self addObject:@{@"name": @"DMX Doom 1", @"preference": @"DOOM0001"}];
|
||||
[self addObject:@{@"name": @"DMX Doom 2", @"preference": @"DOOM0002"}];
|
||||
|
|
385
ThirdParty/libemusc/include/control_rom.h
vendored
Normal file
385
ThirdParty/libemusc/include/control_rom.h
vendored
Normal file
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
* This file is part of libEmuSC, a Sound Canvas emulator library
|
||||
* Copyright (C) 2022-2024 Håkon Skjelten
|
||||
*
|
||||
* libEmuSC 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libEmuSC 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 General Public License
|
||||
* along with libEmuSC. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Control ROM decoding is based on the SC55_Soundfont generator written by
|
||||
// Kitrinx and NewRisingSun [ https://github.com/Kitrinx/SC55_Soundfont ]
|
||||
|
||||
|
||||
#ifndef __CONTROL_ROM_H__
|
||||
#define __CONTROL_ROM_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace EmuSC {
|
||||
|
||||
class ControlRom
|
||||
{
|
||||
public:
|
||||
ControlRom(std::string romPath, std::string cpuRomPath);
|
||||
~ControlRom();
|
||||
|
||||
// Internal data structures extracted from the control ROM file
|
||||
|
||||
struct Sample { // 16 bytes
|
||||
uint8_t volume; // Volume attenuation (0x7f - 0)
|
||||
uint32_t address; // Offset on vsc, bank + scrambled address on SC55.
|
||||
// Bits above 20 are wave bank.
|
||||
uint16_t attackEnd; // boundry between attack and decay? Unconfirmed.
|
||||
uint16_t sampleLen; // Sample Size
|
||||
uint16_t loopLen; // Loop point, used as sample_len - loop_len - 1
|
||||
uint8_t loopMode; // 2 if not a looping sound, 1 forward then back,
|
||||
// 0 forward only.
|
||||
uint8_t rootKey; // Base pitch of the sample
|
||||
uint16_t pitch; // Fine pitch adjustment, 2048 to 0. Pos. incr. pitch.
|
||||
uint16_t fineVolume; // Always 0x400 on VSC, appears to be 1000ths of a
|
||||
// decibel. Positive is higher volume.
|
||||
};
|
||||
|
||||
struct Partial { // 48 bytes in total
|
||||
std::string name;
|
||||
uint8_t breaks[16]; // Note breakpoints corresponding to sample addresses
|
||||
uint16_t samples[16]; // Set of addresses to the sample table. 0 is default
|
||||
}; // and above corresponds to breakpoints
|
||||
|
||||
struct InstPartial { // 92 bytes in total
|
||||
uint8_t LFO2Waveform;
|
||||
uint8_t LFO2Rate; // LFO frequency
|
||||
uint8_t LFO2Delay; // LFO delay before LFO Fade starts
|
||||
uint8_t LFO2Fade; // LFO fade in, linear increase
|
||||
|
||||
uint16_t partialIndex; // Partial table index, 0xFFFF for unused
|
||||
int8_t panpot; // [-64, 64]. Default 0x40 (0-127)
|
||||
int8_t coarsePitch; // Shifts pitch in semitones. Default 0x40
|
||||
int8_t finePitch; // Shifts pitch in cents. Default 0x40
|
||||
int8_t randPitch;
|
||||
|
||||
int8_t pitchKeyFlw;
|
||||
|
||||
uint8_t TVPLFO1Depth;
|
||||
uint8_t TVPLFO2Depth;
|
||||
uint8_t pitchEnvDepth;
|
||||
uint8_t pitchEnvL0; // Pitch Envelope L0
|
||||
uint8_t pitchEnvL1; // Pitch Envelope L1
|
||||
uint8_t pitchEnvL2; // Pitch Envelope L2
|
||||
uint8_t pitchEnvL3; // Pitch Envelope L3 (L4 = 0)
|
||||
uint8_t pitchEnvL5; // Pitch Envelope L5
|
||||
uint8_t pitchEnvT1; // Pitch Envelope T1 (Attack1)
|
||||
uint8_t pitchEnvT2; // Pitch Envelope T2 (Attack2)
|
||||
uint8_t pitchEnvT3; // Pitch Envelope T3 (Decay1)
|
||||
uint8_t pitchEnvT4; // Pitch Envelope T4 (Decay2)
|
||||
uint8_t pitchEnvT5; // Pitch Envelope T5 (Release)
|
||||
|
||||
uint8_t pitchETKeyF14; // Pitch Envelope Time Key Follow (T1 - T4)
|
||||
uint8_t pitchETKeyF5; // Pitch Envelope Time Key Follow (T5)
|
||||
|
||||
uint8_t TVFCOFVelCur; // TVF Cutoff Velocity Curve
|
||||
int8_t TVFBaseFlt;
|
||||
int8_t TVFResonance;
|
||||
int8_t TVFType; // TVF Type [ low pass | high pass | disabled ]
|
||||
|
||||
uint8_t TVFCFKeyFlw; // TVF Cutoff Frequency Key Follow
|
||||
uint8_t TVFCFKeyFlwC; // TVF Cutoff Frequency Key Follow Curves
|
||||
|
||||
uint8_t TVFLFO1Depth;
|
||||
uint8_t TVFLFO2Depth;
|
||||
uint8_t TVFEnvDepth;
|
||||
uint8_t TVFEnvL1; // TVF Envelope L1 (L0 = 0)
|
||||
uint8_t TVFEnvL2; // TVF Envelope L2
|
||||
uint8_t TVFEnvL3; // TVF Envelope L3
|
||||
uint8_t TVFEnvL4; // TVF Envelope L4
|
||||
uint8_t TVFEnvL5; // TVF Envelope L5
|
||||
uint8_t TVFEnvT1; // TVF Envelope T1
|
||||
uint8_t TVFEnvT2; // TVF Envelope T2
|
||||
uint8_t TVFEnvT3; // TVF Envelope T3
|
||||
uint8_t TVFEnvT4; // TVF Envelope T4
|
||||
uint8_t TVFEnvT5; // TVF Envelope T5
|
||||
|
||||
uint8_t TVFETKeyF14; // TVF Envelope Time Key Follow (T1 - T4)
|
||||
uint8_t TVFETKeyF5; // TVF Envelope Time Key Follow (T5)
|
||||
|
||||
uint8_t TVALvlVelCur;
|
||||
int8_t volume; // Volume attenuation (0x7f - 0)
|
||||
uint8_t TVABiasPoint; // TVA Bias Point, 0=V shape, 1=key>85, 2=flat curve
|
||||
uint8_t TVABiasLevel;
|
||||
uint8_t TVALFO1Depth;
|
||||
uint8_t TVALFO2Depth;
|
||||
uint8_t TVAEnvL1; // TVA Envelope L1 (L0 = 0)
|
||||
uint8_t TVAEnvL2; // TVA Envelope L2
|
||||
uint8_t TVAEnvL3; // TVA Envelope L3
|
||||
uint8_t TVAEnvL4; // TVA Envelope L4 (L5 = 0)
|
||||
uint8_t TVAEnvT1; // TVA Envelope T1 (Attack1)
|
||||
uint8_t TVAEnvT2; // TVA Envelope T2 (Attack2)
|
||||
uint8_t TVAEnvT3; // TVA Envelope T3 (Decay1)
|
||||
uint8_t TVAEnvT4; // TVA Envelope T4 (Decay2)
|
||||
uint8_t TVAEnvT5; // TVA Envelope T5 (Release)
|
||||
|
||||
uint8_t TVAETKeyP14; // TVA Envelope Time Key Presets (T1 - T4)
|
||||
uint8_t TVAETKeyP5; // TVA Envelope Time Key Presets (T5)
|
||||
uint8_t TVAETKeyF14; // TVA Envelope Time Key Follow (T1 - T4)
|
||||
uint8_t TVAETKeyF5; // TVA Envelope Time Key Follow (T5)
|
||||
uint8_t TVAETVSens14; // TVA Envelope Time Velocity Sensitivity (T1 - T4)
|
||||
uint8_t TVAETVSens5; // TVA Envelope Time Velocity Sensitivity (T5)
|
||||
};
|
||||
|
||||
struct Instrument { // 204 bytes in total
|
||||
std::string name;
|
||||
|
||||
uint8_t volume; // Volume attenuation (0x7f - 0)
|
||||
uint8_t LFO1Waveform;
|
||||
uint8_t LFO1Rate; // LFO frequency
|
||||
uint8_t LFO1Delay;
|
||||
uint8_t LFO1Fade;
|
||||
uint8_t partialsUsed; // Bit 0 & 1 => which of the two partials are in use
|
||||
uint8_t pitchCurve;
|
||||
|
||||
struct InstPartial partials[2];
|
||||
};
|
||||
|
||||
struct DrumSet { // 1164 bytes
|
||||
uint16_t preset[128];
|
||||
uint8_t volume[128];
|
||||
uint8_t key[128];
|
||||
uint8_t assignGroup[128];// AKA exclusive class
|
||||
uint8_t panpot[128];
|
||||
uint8_t reverb[128];
|
||||
uint8_t chorus[128];
|
||||
uint8_t flags[128]; // 0x10 -> accept note on, 0x01 -> accept note off
|
||||
std::string name; // 12 chars
|
||||
};
|
||||
|
||||
struct LookupTables {
|
||||
// PROGROM
|
||||
std::array<uint8_t, 128> VelocityCurve0;
|
||||
std::array<uint8_t, 128> VelocityCurve1;
|
||||
std::array<uint8_t, 128> VelocityCurve2;
|
||||
std::array<uint8_t, 128> VelocityCurve3;
|
||||
std::array<uint8_t, 128> VelocityCurve4;
|
||||
std::array<uint8_t, 128> VelocityCurve5;
|
||||
std::array<uint8_t, 128> VelocityCurve6;
|
||||
std::array<uint8_t, 128> VelocityCurve7;
|
||||
std::array<uint8_t, 128> VelocityCurve8;
|
||||
std::array<uint8_t, 128> VelocityCurve9;
|
||||
std::array<uint8_t, 128> mul2;
|
||||
std::array<uint8_t, 128> mul2From85;
|
||||
std::array<uint8_t, 128> TVABiasPoint1;
|
||||
std::array<uint8_t, 128> TVAEnvTKFP1T14Index;
|
||||
std::array<uint8_t, 128> TVAEnvTKFP1T5Index;
|
||||
// std::array<int, 128> mul256;
|
||||
// std::array<int, 128> mul256From60;
|
||||
// std::array<int, 128> mul256From96;
|
||||
// std::array<int, 128> mul256Upto96;
|
||||
std::array<int, 128> PitchScale1;
|
||||
std::array<int, 128> PitchScale2;
|
||||
std::array<int, 128> PitchScale3;
|
||||
|
||||
// CPUROM
|
||||
std::array<uint8_t, 21> TimeKeyFollowDiv;
|
||||
std::array<int, 256> TimeKeyFollow;
|
||||
std::array<int, 128> envelopeTime;
|
||||
std::array<int, 128> LFORate;
|
||||
std::array<int, 128> LFODelayTime;
|
||||
std::array<int, 128> LFOTVFDepth;
|
||||
std::array<int, 128> LFOTVPDepth;
|
||||
std::array<uint8_t, 128> LFOSine;
|
||||
std::array<int, 128> TVFEnvDepth;
|
||||
std::array<int, 128> TVFCutoffFreq;
|
||||
std::array<uint8_t, 256> TVFResonanceFreq;
|
||||
std::array<uint8_t, 128> TVFResonance;
|
||||
std::array<int, 128> PitchEnvDepth;
|
||||
std::array<uint8_t, 64> TVFEnvScale;
|
||||
std::array<int, 256> TVAEnvExpChange;
|
||||
std::array<uint8_t, 129> TVABiasLevel;
|
||||
std::array<uint8_t, 128> TVAPanpot;
|
||||
std::array<uint8_t, 128> TVALevelIndex;
|
||||
std::array<uint8_t, 256> TVALevel;
|
||||
};
|
||||
struct LookupTables lookupTables;
|
||||
|
||||
enum class SynthGen {
|
||||
SC55 = 0,
|
||||
SC55mk2 = 1,
|
||||
SC88 = 2,
|
||||
SC88Pro = 3
|
||||
};
|
||||
|
||||
int dump_demo_songs(std::string path);
|
||||
bool intro_anim_available(void);
|
||||
std::vector<uint8_t> get_intro_anim(int animIndex = 0);
|
||||
|
||||
std::string model(void) { return _model; }
|
||||
std::string version(void) { return _version; }
|
||||
std::string date(void) { return _date; }
|
||||
enum SynthGen generation(void) { return _synthGeneration; }
|
||||
|
||||
const std::array<uint8_t, 128>& get_drum_sets_LUT(void) { return _drumSetsLUT; }
|
||||
const uint8_t max_polyphony(void);
|
||||
|
||||
std::vector<std::vector<std::string>> get_instruments_list(void);
|
||||
std::vector<std::vector<std::string>> get_partials_list(void);
|
||||
std::vector<std::vector<std::string>> get_samples_list(void);
|
||||
std::vector<std::vector<std::string>> get_variations_list(void);
|
||||
std::vector<std::string> get_drum_sets_list(void);
|
||||
|
||||
inline struct Instrument& instrument(int i) { return _instruments[i]; }
|
||||
inline struct Partial& partial(int p) { return _partials[p]; }
|
||||
inline struct Sample& sample(int s) { return _samples[s]; }
|
||||
inline struct DrumSet& drumSet(int ds) { return _drumSets[ds]; }
|
||||
inline const std::array<uint16_t, 128>& variation(int v) const { return _variations[v]; }
|
||||
|
||||
inline int numSampleSets(void) { return _samples.size(); }
|
||||
inline int numInstruments(void) { return _instruments.size(); }
|
||||
|
||||
inline std::vector<DrumSet> &get_drumsets_ref(void) { return _drumSets; }
|
||||
|
||||
private:
|
||||
std::string _romPath;
|
||||
|
||||
std::string _model;
|
||||
std::string _version;
|
||||
std::string _date;
|
||||
|
||||
enum SynthModel {
|
||||
sm_SC55, // Original Sound Canvas
|
||||
sm_SC55mkII, // Upgraded model
|
||||
sm_SCC1, // ISA card version
|
||||
sm_SC88,
|
||||
sm_SC88Pro,
|
||||
};
|
||||
enum SynthModel _synthModel;
|
||||
|
||||
enum SynthGen _synthGeneration;
|
||||
|
||||
static constexpr uint8_t _maxPolyphonySC55 = 24;
|
||||
static constexpr uint8_t _maxPolyphonySC55mkII = 28;
|
||||
static constexpr uint8_t _maxPolyphonySC88 = 64;
|
||||
|
||||
static const std::vector<uint32_t> _banksSC55;
|
||||
|
||||
// Only a placeholder, SC-88 layout is currently unkown
|
||||
static const std::vector<uint32_t> _banksSC88;
|
||||
|
||||
struct _ProgMemoryMapLUT {
|
||||
int VelocityCurve0;
|
||||
int VelocityCurve1;
|
||||
int VelocityCurve2;
|
||||
int VelocityCurve3;
|
||||
int VelocityCurve4;
|
||||
int VelocityCurve5;
|
||||
int VelocityCurve6;
|
||||
int VelocityCurve7;
|
||||
int VelocityCurve8;
|
||||
int VelocityCurve9;
|
||||
int mul2;
|
||||
int mul2From85;
|
||||
int TVABiasPoint1;
|
||||
int TVAEnvTKFP1T14Index;
|
||||
int TVAEnvTKFP1T5Index;
|
||||
// int mul256;
|
||||
// int mul256From60;
|
||||
// int mul256From96;
|
||||
// int mul256Upto96;
|
||||
int PitchScale1;
|
||||
int PitchScale2;
|
||||
int PitchScale3;
|
||||
};
|
||||
|
||||
const _ProgMemoryMapLUT SC55_1_21_Prog_LUT {
|
||||
0x3d1e8, 0x3d268, 0x3d2e8, 0x3d368, 0x3d3e8, 0x3d468, 0x3d4e8, 0x3d568,
|
||||
0x3d5e8, 0x3d668, 0x3dd82, 0x3de02, 0x3de02, 0x3df82, 0x3e102, 0x3e982,
|
||||
0x3ea82, 0x3eb82 };
|
||||
const _ProgMemoryMapLUT SC55mkII_1_01_Prog_LUT {
|
||||
0x3d1e8, 0x3d268, 0x3d2e8, 0x3d368, 0x3d3e8, 0x3d468, 0x3d4e8, 0x3d568,
|
||||
0x3d5e8, 0x3d668, 0x3de8c, 0x3df0c, 0x3df0c, 0x3e10c, 0x3e30c, 0x3ee0c,
|
||||
0x3ef0c, 0x3f00c };
|
||||
|
||||
struct _CPUMemoryMapLUT {
|
||||
int TimeKeyFollowDiv;
|
||||
int TimeKeyFollow;
|
||||
int EnvelopeTime;
|
||||
int LFORate;
|
||||
int LFODelayTime;
|
||||
int LFOTVFDepth;
|
||||
int LFOTVPDepth;
|
||||
int LFOSine;
|
||||
int TVFEnvDepth;
|
||||
int TVFCutoffFreq;
|
||||
int TVFResonanceFreq;
|
||||
int TVFResonance;
|
||||
int PitchEnvDepth;
|
||||
int TVFEnvScale;
|
||||
int TVAEnvExpChange;
|
||||
int TVABiasLevel;
|
||||
int TVAPanpot;
|
||||
int TVALevelIndex;
|
||||
int TVALevel;
|
||||
};
|
||||
|
||||
const _CPUMemoryMapLUT SC55_1_21_CPU_LUT {
|
||||
0x679a, 0x67c6, 0x6f12, 0x7012, 0x7112, 0x7212, 0x7312, 0x7412,
|
||||
0x7512, 0x7612, 0x7715, 0x7816, 0x78f2, 0x79f2, 0x6d10, 0x69c6,
|
||||
0x6c8f, 0x6b0f, 0x6b8f };
|
||||
const _CPUMemoryMapLUT SC55mkII_1_01_CPU_LUT {
|
||||
0x650e, 0x653a, 0x6c86, 0x6486, 0x6e86, 0x6f86, 0x7086, 0x7186,
|
||||
0x7286, 0x7386, 0x7489, 0x758a, 0x7765, 0x7766, 0x6a84, 0x673a,
|
||||
0x6a03, 0x6883, 0x6903 };
|
||||
|
||||
int _read_lookup_tables_progrom(std::ifstream &romFile);
|
||||
int _read_lookup_tables_cpurom(std::ifstream &romFile);
|
||||
int _read_lut_16bit(std::ifstream &ifs, int pos, std::array<int, 128> &lut);
|
||||
int _read_lut_16bit(std::ifstream &ifs, int pos, std::array<int, 129> &lut);
|
||||
int _read_lut_16bit(std::ifstream &ifs, int pos, std::array<int, 256> &lut);
|
||||
|
||||
int _identify_model(std::ifstream &romFile);
|
||||
const std::vector<uint32_t> &_banks(void);
|
||||
|
||||
// To be replaced with std::endian::native from C++20
|
||||
inline bool _le_native(void) { uint16_t n = 1; return (*(uint8_t *) & n); }
|
||||
|
||||
uint16_t _native_endian_uint16(uint8_t *ptr);
|
||||
uint32_t _native_endian_3bytes_uint32(uint8_t *ptr);
|
||||
uint32_t _native_endian_4bytes_uint32(uint8_t *ptr);
|
||||
|
||||
int _read_instruments(std::ifstream &romFile);
|
||||
int _read_partials(std::ifstream &romFile);
|
||||
int _read_variations(std::ifstream &romFile);
|
||||
int _read_samples(std::ifstream &romFile);
|
||||
int _read_drum_sets(std::ifstream &romFile);
|
||||
|
||||
std::array<uint8_t, 128> _drumSetsLUT;
|
||||
|
||||
std::vector<Instrument> _instruments;
|
||||
std::vector<Partial> _partials;
|
||||
std::vector<Sample> _samples;
|
||||
std::vector<DrumSet> _drumSets;
|
||||
// TODO: define constants for variation table dimensions
|
||||
std::array<std::array<uint16_t, 128>, 128> _variations;
|
||||
|
||||
ControlRom();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __CONTROL_ROM_H__
|
380
ThirdParty/libemusc/include/params.h
vendored
Normal file
380
ThirdParty/libemusc/include/params.h
vendored
Normal file
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
* This file is part of libEmuSC, a Sound Canvas emulator library
|
||||
* Copyright (C) 2023-2024 Håkon Skjelten
|
||||
*
|
||||
* libEmuSC 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libEmuSC 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 General Public License
|
||||
* along with libEmuSC. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __PARAMS_H__
|
||||
#define __PARAMS_H__
|
||||
|
||||
|
||||
namespace EmuSC {
|
||||
|
||||
|
||||
// All variables for master settings as defined by the Sound Canvas lineup
|
||||
enum class SystemParam : int {
|
||||
|
||||
// Part 1: Settings defined by SysEx chart
|
||||
// These settings can be both requested and modified by SysEx messages
|
||||
Tune = 0x0000, // 4B: [0x0014 - 0x07e8 : 0x0400]-100.0-100.0
|
||||
Tune1 = 0x0001,
|
||||
Tune2 = 0x0002,
|
||||
Tune3 = 0x0003,
|
||||
Volume = 0x0004, // [0x00 - 0x7f : 0x7f]
|
||||
KeyShift = 0x0005, // [0x28 - 0x58 : 0x40]
|
||||
Pan = 0x0006, // [0x01 - 0x7f : 0x40]
|
||||
|
||||
ResetGSstandardMode = 0x007f, // No data stored, but triggers a reset event
|
||||
|
||||
// Part 2: Settings outside SysEx chart
|
||||
RxSysEx = 0x0090, // [0 - 1 : 1]
|
||||
RxGMOn = 0x0091, // [0 - 1 : 1]
|
||||
RxGSReset = 0x0092, // [0 - 1 : 1]
|
||||
RxInstrumentChange = 0x0093, // [0 - 1 : 1]
|
||||
RxFunctionControl = 0x0094, // [0 - 1 : 1]
|
||||
DeviceID = 0x0095, // [1 - 32 : 17]
|
||||
|
||||
};
|
||||
|
||||
|
||||
enum class PatchParam : int {
|
||||
|
||||
// Part 1: Settings defined by SysEx chart
|
||||
// =======================================
|
||||
// These settings can be both requested and modified by SysEx messages
|
||||
|
||||
PatchName = 0x0100,
|
||||
PartialReserve = 0x0110,
|
||||
|
||||
ReverbMacro = 0x0130, // [0x00 - 0x07 : 0x04]
|
||||
ReverbCharacter = 0x0131, // [0x00 - 0x07 : 0x04]
|
||||
ReverbPreLPF = 0x0132, // [0x00 - 0x7f : 0x00]
|
||||
ReverbLevel = 0x0133, // [0x00 - 0x7f : 0x40]
|
||||
ReverbTime = 0x0134, // [0x00 - 0x7f : 0x40]
|
||||
ReverbDelayFeedback = 0x0135, // [0x00 - 0x7f : 0x00]
|
||||
ReverbPreDelayTime = 0x0137, // SC-88
|
||||
|
||||
ChorusMacro = 0x0138, // [0x00 - 0x07 : 0x02]
|
||||
ChorusPreLPF = 0x0139, // [0x00 - 0x07 : 0x00]
|
||||
ChorusLevel = 0x013a, // [0x00 - 0x7f : 0x40]
|
||||
ChorusFeedback = 0x013b, // [0x00 - 0x7f : 0x08]
|
||||
ChorusDelay = 0x013c, // [0x00 - 0x7f : 0x50]
|
||||
ChorusRate = 0x013d, // [0x00 - 0x7f : 0x03]
|
||||
ChorusDepth = 0x013e, // [0x00 - 0x7f : 0x13]
|
||||
ChorusSendToReverb = 0x013f, // [0x00 - 0x7f : 0x00]
|
||||
|
||||
// The remaining patch paramters have separate values for each part
|
||||
// All addresses are either 0x1PXX or 0x2PXX, where P = part number
|
||||
|
||||
ToneNumber = 0x1000, // 2B: Byte 1 = CtrlChg, Byte 2 = ProgChg
|
||||
ToneNumber2 = 0x1001, // Only helper for easy access 2nd. byte
|
||||
RxChannel = 0x1002, // [1 - 17] X = Part number, 17 = Off
|
||||
RxPitchBend = 0x1003, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxChPressure = 0x1004, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxProgramChange = 0x1005, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxControlChange = 0x1006, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxPolyPressure = 0x1007, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxNoteMessage = 0x1008, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxRPN = 0x1009, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxNRPN = 0x100a, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
// Note: Set to Off if mode is set to 'GM'
|
||||
RxModulation = 0x100b, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxVolume = 0x100c, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxPanpot = 0x100d, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxExpression = 0x100e, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxHold1 = 0x100f, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxPortamento = 0x1010, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxSostenuto = 0x1011, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
RxSoft = 0x1012, // [0 - 1 : 1] 0 = Off, 1 = On
|
||||
PolyMode = 0x1013, // [0 (Mono) | 1 (Poly) : 1]
|
||||
AssignMode = 0x1014, // [0 - 2] 0 = Single, 1 = Limited-Multi,
|
||||
// 2 = Full-Multi
|
||||
UseForRhythm = 0x1015, // [0 - 3] 0 = Off, 1 = Map1, 2 = Map2
|
||||
PitchKeyShift = 0x1016, // [0x28 - 0x58 : 0x40] -24 - 24 semitone
|
||||
PitchOffsetFine = 0x1017, // 2B [0x08 - 0xf8 : 0x0800] -12.0 - 12.0 Hz
|
||||
PitchOffsetFine2 = 0x1018,
|
||||
PartLevel = 0x1019, // [0x00 - 0x7f : 0x64]
|
||||
VelocitySenseDepth = 0x101a, // [0x00 - 0x7f : 0x40]
|
||||
VelocitySenseOffset = 0x101b, // [0x00 - 0x7f : 0x40]
|
||||
PartPanpot = 0x101c, // [0x00 - 0x7f : 0x40] 0 = rnd, left > right
|
||||
KeyRangeLow = 0x101d, // [0x00 - 0x7f : 0x00]
|
||||
KeyRangeHigh = 0x101e, // [0x00 - 0x7f : 0x7f]
|
||||
CC1ControllerNumber = 0x101f, // [0x00 - 0x5f : 0x40]
|
||||
CC2ControllerNumber = 0x1020, // [0x00 - 0x5f : 0x40]
|
||||
ChorusSendLevel = 0x1021, // [0x00 - 0x7f : 0x00] (CC# 93)
|
||||
ReverbSendLevel = 0x1022, // [0x00 - 0x7f : 0x28] (CC# 91)
|
||||
RxBankSelect = 0x1023, // [0 - 1 : 1] Note: Missing from SC-55 OM,
|
||||
// but present on SC-55mkII and onwards
|
||||
RxBankSelectLSB = 0x1024, // (SC88+)
|
||||
PitchFineTune = 0x102a, // [SC88+][0x0000 - 0x7f7f : 0x400] (14 bit)
|
||||
PitchFineTune2 = 0x102b, // Also RPN #1 so used for that on SC-55
|
||||
DelaySendLevel = 0x102c, // (SC88+)
|
||||
|
||||
// Tone modify
|
||||
// Note: SC-55 has [0x0e - 0x72 : 0x40] for all tone modify parameters
|
||||
// SC-88 has [0x00 - 0x7f : 0x40] for all tone modify parameters
|
||||
VibratoRate = 0x1030, // NRPN# 8
|
||||
VibratoDepth = 0x1031, // NRPN# 9
|
||||
TVFCutoffFreq = 0x1032, // NRPN# 32
|
||||
TVFResonance = 0x1033, // NRPN# 33
|
||||
TVFAEnvAttack = 0x1034, // NRPN# 99
|
||||
TVFAEnvDecay = 0x1035, // NRPN# 100
|
||||
TVFAEnvRelease = 0x1036, // NRPN# 102
|
||||
VibratoDelay = 0x1037, // NRPN# 10
|
||||
|
||||
// Scale tuning
|
||||
ScaleTuningC = 0x1040, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningC_ = 0x1041, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningD = 0x1042, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningD_ = 0x1043, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningE = 0x1044, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningF = 0x1045, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningF_ = 0x1046, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningG = 0x1047, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningG_ = 0x1048, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningA = 0x1049, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningA_ = 0x104a, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
ScaleTuningB = 0x104b, // [0x00 - 0x7f : 0x40], -63 - 63 cent
|
||||
|
||||
// Controller setttings (0x41 0x2P 0xXX)
|
||||
// These settings contains the current value for each controller parameter.
|
||||
|
||||
// Modulator
|
||||
MOD_PitchControl = 0x2000, // [0x20 - 0x58 : 0x40], -24 - +24 semitones
|
||||
MOD_TVFCutoffControl= 0x2001, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
MOD_AmplitudeControl= 0x2002, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
MOD_LFO1RateControl = 0x2003, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
MOD_LFO1PitchDepth = 0x2004, // [0x00 - 0x7f : 0x0a], 0 - 600 cent
|
||||
MOD_LFO1TVFDepth = 0x2005, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
MOD_LFO1TVADepth = 0x2006, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
MOD_LFO2RateControl = 0x2007, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
MOD_LFO2PitchDepth = 0x2008, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
MOD_LFO2TVFDepth = 0x2009, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
MOD_LFO2TVADepth = 0x200a, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// Pitch Bend
|
||||
PB_PitchControl = 0x2010, // [0x40 - 0x58 : 0x40], 0 - +24 semitones
|
||||
PB_TVFCutoffControl = 0x2011, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
PB_AmplitudeControl = 0x2012, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
PB_LFO1RateControl = 0x2013, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
PB_LFO1PitchDepth = 0x2014, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
PB_LFO1TVFDepth = 0x2015, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
PB_LFO1TVADepth = 0x2016, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
PB_LFO2RateControl = 0x2017, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
PB_LFO2PitchDepth = 0x2018, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
PB_LFO2TVFDepth = 0x2019, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
PB_LFO2TVADepth = 0x201a, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// Channel Aftertouch
|
||||
CAf_PitchControl = 0x2020, // [0x20 - 0x58 : 0x40], -24 - +24 semitones
|
||||
CAf_TVFCutoffControl= 0x2021, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
CAf_AmplitudeControl= 0x2022, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
CAf_LFO1RateControl = 0x2023, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CAf_LFO1PitchDepth = 0x2024, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CAf_LFO1TVFDepth = 0x2025, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CAf_LFO1TVADepth = 0x2026, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
CAf_LFO2RateControl = 0x2027, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CAf_LFO2PitchDepth = 0x2028, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CAf_LFO2TVFDepth = 0x2029, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CAf_LFO2TVADepth = 0x202a, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// Poly Aftertouch
|
||||
PAf_PitchControl = 0x2030, // [0x20 - 0x58 : 0x40], -24 - +24 semitones
|
||||
PAf_TVFCutoffControl= 0x2031, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
PAf_AmplitudeControl= 0x2032, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
PAf_LFO1RateControl = 0x2033, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
PAf_LFO1PitchDepth = 0x2034, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
PAf_LFO1TVFDepth = 0x2035, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
PAf_LFO1TVADepth = 0x2036, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
PAf_LFO2RateControl = 0x2037, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
PAf_LFO2PitchDepth = 0x2038, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
PAf_LFO2TVFDepth = 0x2039, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
PAf_LFO2TVADepth = 0x203a, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// CC#1
|
||||
CC1_PitchControl = 0x2040, // [0x20 - 0x58 : 0x40], -24 - +24 semitones
|
||||
CC1_TVFCutoffControl= 0x2041, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
CC1_AmplitudeControl= 0x2042, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
CC1_LFO1RateControl = 0x2043, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CC1_LFO1PitchDepth = 0x2044, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CC1_LFO1TVFDepth = 0x2045, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CC1_LFO1TVADepth = 0x2046, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
CC1_LFO2RateControl = 0x2047, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CC1_LFO2PitchDepth = 0x2048, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CC1_LFO2TVFDepth = 0x2049, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CC1_LFO2TVADepth = 0x204a, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// CC#2
|
||||
CC2_PitchControl = 0x2050, // [0x20 - 0x58 : 0x40], -24 - 24 semitones
|
||||
CC2_TVFCutoffControl= 0x2051, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
CC2_AmplitudeControl= 0x2052, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
CC2_LFO1RateControl = 0x2053, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CC2_LFO1PitchDepth = 0x2054, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CC2_LFO1TVFDepth = 0x2055, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CC2_LFO1TVADepth = 0x2056, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
CC2_LFO2RateControl = 0x2057, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CC2_LFO2PitchDepth = 0x2058, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CC2_LFO2TVFDepth = 0x2059, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CC2_LFO2TVADepth = 0x205a, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// SC-88 only additions TODO: FIX
|
||||
// ToneMapNumber = 0x4000, // [SC-88Pro]
|
||||
// ToneMap0Number = 0x4001, // [SC-88Pro]
|
||||
// EqOnOff = 0x4020, // [SC-88]
|
||||
// OutputAssign = 0x4021, // [SC-88Pro]
|
||||
// PartEfxAssign = 0x4022, // [SC-88Pro]
|
||||
|
||||
|
||||
// Part 2: Settings outside SysEx chart
|
||||
// ====================================
|
||||
// The following settings contains the latest controller inputs. These
|
||||
// values are controller parameter states multiplied with controller value.
|
||||
// The values of these controller inputs are updated whenever a controller
|
||||
// changes value.
|
||||
|
||||
// Modulator
|
||||
CtM_PitchControl = 0x2060, // [0x20 - 0x58 : 0x40], -24 - +24 semitones
|
||||
CtM_TVFCutoffControl= 0x2061, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
CtM_AmplitudeControl= 0x2062, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
CtM_LFO1RateControl = 0x2063, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CtM_LFO1PitchDepth = 0x2064, // [0x00 - 0x7f : 0x0a], 0 - 600 cent
|
||||
CtM_LFO1TVFDepth = 0x2065, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CtM_LFO1TVADepth = 0x2066, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
CtM_LFO2RateControl = 0x2067, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CtM_LFO2PitchDepth = 0x2068, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CtM_LFO2TVFDepth = 0x2069, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CtM_LFO2TVADepth = 0x206a, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// Pitch Bend
|
||||
CtB_PitchControl = 0x2070, // [0x40 - 0x58 : 0x40], 0 - +24 semitones 2B
|
||||
CtB_TVFCutoffControl= 0x2071, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
CtB_AmplitudeControl= 0x2072, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
CtB_LFO1RateControl = 0x2073, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CtB_LFO1PitchDepth = 0x2074, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CtB_LFO1TVFDepth = 0x2075, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CtB_LFO1TVADepth = 0x2076, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
CtB_LFO2RateControl = 0x2077, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CtB_LFO2PitchDepth = 0x2078, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CtB_LFO2TVFDepth = 0x2079, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CtB_LFO2TVADepth = 0x207a, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// Channel Aftertouch
|
||||
CtC_PitchControl = 0x2080, // [0x20 - 0x58 : 0x40], -24 - +24 semitones
|
||||
CtC_TVFCutoffControl= 0x2081, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
CtC_AmplitudeControl= 0x2082, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
CtC_LFO1RateControl = 0x2083, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CtC_LFO1PitchDepth = 0x2084, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CtC_LFO1TVFDepth = 0x2085, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CtC_LFO1TVADepth = 0x2086, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
CtC_LFO2RateControl = 0x2087, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CtC_LFO2PitchDepth = 0x2088, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CtC_LFO2TVFDepth = 0x2089, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CtC_LFO2TVADepth = 0x208a, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// Poly Aftertouch
|
||||
CtP_PitchControl = 0x2090, // [0x20 - 0x58 : 0x40], -24 - +24 semitones
|
||||
CtP_TVFCutoffControl= 0x2091, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
CtP_AmplitudeControl= 0x2092, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
CtP_LFO1RateControl = 0x2093, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CtP_LFO1PitchDepth = 0x2094, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CtP_LFO1TVFDepth = 0x2095, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CtP_LFO1TVADepth = 0x2096, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
CtP_LFO2RateControl = 0x2097, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
CtP_LFO2PitchDepth = 0x2098, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
CtP_LFO2TVFDepth = 0x2099, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
CtP_LFO2TVADepth = 0x209a, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// CC#1
|
||||
Ct1_PitchControl = 0x20a0, // [0x20 - 0x58 : 0x40], -24 - +24 semitones
|
||||
Ct1_TVFCutoffControl= 0x20a1, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
Ct1_AmplitudeControl= 0x20a2, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
Ct1_LFO1RateControl = 0x20a3, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
Ct1_LFO1PitchDepth = 0x20a4, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
Ct1_LFO1TVFDepth = 0x20a5, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
Ct1_LFO1TVADepth = 0x20a6, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
Ct1_LFO2RateControl = 0x20a7, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
Ct1_LFO2PitchDepth = 0x20a8, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
Ct1_LFO2TVFDepth = 0x20a9, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
Ct1_LFO2TVADepth = 0x20aa, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// CC#2
|
||||
Ct2_PitchControl = 0x20b0, // [0x20 - 0x58 : 0x40], -24 - 24 semitones
|
||||
Ct2_TVFCutoffControl= 0x20b1, // [0x00 - 0x7f : 0x40], -9600 - 9600 cent
|
||||
Ct2_AmplitudeControl= 0x20b2, // [0x00 - 0x7f : 0x40], -100.0 - 100.0 %
|
||||
Ct2_LFO1RateControl = 0x20b3, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
Ct2_LFO1PitchDepth = 0x20b4, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
Ct2_LFO1TVFDepth = 0x20b5, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
Ct2_LFO1TVADepth = 0x20b6, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
Ct2_LFO2RateControl = 0x20b7, // [0x00 - 0x7f : 0x40], -10.0 - 10.0 Hz
|
||||
Ct2_LFO2PitchDepth = 0x20b8, // [0x00 - 0x7f : 0x00], 0 - 600 cent
|
||||
Ct2_LFO2TVFDepth = 0x20b9, // [0x00 - 0x7f : 0x00], 0 - 2400 cent
|
||||
Ct2_LFO2TVADepth = 0x20ba, // [0x00 - 0x7f : 0x00], 0 - 100.0 %
|
||||
|
||||
// And finally a list of controller parameters that contains accumulated
|
||||
// values from all 6 controllers. Updated at the same time as the controller
|
||||
// inputs above, i.e. whenever a controller changes value.
|
||||
Acc_PitchControl = 0x20f0, // [0x0000 - 0x7f7f : 0x4000], Note: 2 Bytes
|
||||
Acc_TVFCutoffControl= 0x20f2, // [0x00 - 0x7f : 0x40]
|
||||
Acc_AmplitudeControl= 0x20f3, // [0x00 - 0x7f : 0x40]
|
||||
Acc_LFO1RateControl = 0x20f4, // [0x00 - 0x7f : 0x40]
|
||||
Acc_LFO1PitchDepth = 0x20f5, // [0x00 - 0x7f : 0x00]
|
||||
Acc_LFO1TVFDepth = 0x20f6, // [0x00 - 0x7f : 0x00]
|
||||
Acc_LFO1TVADepth = 0x20f7, // [0x00 - 0x7f : 0x00]
|
||||
Acc_LFO2RateControl = 0x20f8, // [0x00 - 0x7f : 0x40]
|
||||
Acc_LFO2PitchDepth = 0x20f9, // [0x00 - 0x7f : 0x00]
|
||||
Acc_LFO2TVFDepth = 0x20fa, // [0x00 - 0x7f : 0x00]
|
||||
Acc_LFO2TVADepth = 0x20fb, // [0x00 - 0x7f : 0x00]
|
||||
|
||||
// Controller state values
|
||||
Modulation = 0x1080, // [0x00 - 0x7f]
|
||||
PitchBend = 0x1081, // [0x00 - 0x4000 : 0x2000] Note: 2 Bytes!
|
||||
ChannelPressure = 0x1083, // [0x00 - 0x7f : 0]
|
||||
PolyKeyPressure = 0x1084, // [0x00 - 0x7f : 0] pr. key. Need an array?
|
||||
CC1Controller = 0x1085, // [0x00 - 0x7f : 0]
|
||||
CC2Controller = 0x1086, // [0x00 - 0x7f : 0]
|
||||
Hold1 = 0x1087, // [0x00 - 0x7f : 0] 0-63: OFF, 64-127: ON
|
||||
Sostenuto = 0x1088, // [0x00 - 0x7f : 0] 0-63: OFF, 64-127: ON
|
||||
Soft = 0x1089, // [0x00 - 0x7f : 0] 0-63: OFF, 64-127: ON
|
||||
Expression = 0x108a, // [0x00 - 0x7f : 0xff]
|
||||
Portamento = 0x108b, // [0 - 1 : 0]
|
||||
PortamentoTime = 0x108c, // [0x00 - 0x7f : 0]
|
||||
|
||||
// Current RPN and NRPN
|
||||
RPN_LSB = 0x1090, // [0x00 - 0x7f : 0]
|
||||
RPN_MSB = 0x1091, // [0x00 - 0x7f : 0]
|
||||
NRPN_LSB = 0x1092, // [0x00 - 0x7f : 0]
|
||||
NRPN_MSB = 0x1093, // [0x00 - 0x7f : 0]
|
||||
|
||||
// Other patch parameters from CC / RPN / NRPN / menu
|
||||
PitchCoarseTune = 0x1094 // [0x28 - 0x58 : 0x40] -24 - 24 semit. RPN#2
|
||||
};
|
||||
|
||||
// All variables for individual parts as defined by the Sound Canvas lineup
|
||||
enum class DrumParam : int {
|
||||
DrumsMapName = 0x0000, // 12B ASCII
|
||||
PlayKeyNumber = 0x0100, // [0x00 - 0x7f] semitones
|
||||
Level = 0x0200, // [0x00 - 0x7f]
|
||||
AssignGroupNumber = 0x0300, // [0x00 - 0x7f]
|
||||
Panpot = 0x0400, // [0x00 - 0x7f]
|
||||
ReverbDepth = 0x0500, // [0x00 - 0x7f]
|
||||
ChorusDepth = 0x0600, // [0x00 - 0x7f]
|
||||
RxNoteOff = 0x0700, // [0 - 1]
|
||||
RxNoteOn = 0x0800 // [0 - 1]
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __PARAMS_H__
|
72
ThirdParty/libemusc/include/pcm_rom.h
vendored
Normal file
72
ThirdParty/libemusc/include/pcm_rom.h
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* This file is part of libEmuSC, a Sound Canvas emulator library
|
||||
* Copyright (C) 2022-2024 Håkon Skjelten
|
||||
*
|
||||
* libEmuSC 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libEmuSC 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 General Public License
|
||||
* along with libEmuSC. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// PCM ROM decoding is based on the SC55_Soundfont generator written by
|
||||
// Kitrinx and NewRisingSun [ https://github.com/Kitrinx/SC55_Soundfont ]
|
||||
|
||||
|
||||
#ifndef __PCM_ROM_H__
|
||||
#define __PCM_ROM_H__
|
||||
|
||||
|
||||
#include "control_rom.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace EmuSC {
|
||||
|
||||
class PcmRom
|
||||
{
|
||||
private:
|
||||
std::string _version;
|
||||
std::string _date;
|
||||
|
||||
struct Samples {
|
||||
// std::vector<int32_t> samplesI; // All samples stored in 24 bit 32kHz mono
|
||||
std::vector<float> samplesF; // 32 bit float, 32kHz, mono
|
||||
};
|
||||
std::vector<struct Samples> _sampleSets;
|
||||
|
||||
uint32_t _unscramble_address(uint32_t address);
|
||||
int8_t _unscramble_data(int8_t byte);
|
||||
|
||||
uint32_t _find_samples_rom_address(uint32_t address,
|
||||
enum ControlRom::SynthGen synthGen);
|
||||
int _read_samples(std::vector<char> &rom,
|
||||
struct ControlRom::Sample &ctrlSample,
|
||||
enum ControlRom::SynthGen synthGen);
|
||||
|
||||
PcmRom();
|
||||
|
||||
public:
|
||||
PcmRom(std::vector<std::string> romPath, ControlRom &ctrlRom);
|
||||
~PcmRom();
|
||||
|
||||
inline struct Samples& samples(uint16_t ss) { return _sampleSets[ss]; }
|
||||
|
||||
std::string version(void) { return _version; }
|
||||
std::string date(void) { return _date; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __PCM_ROM_H__
|
161
ThirdParty/libemusc/include/settings.h
vendored
Normal file
161
ThirdParty/libemusc/include/settings.h
vendored
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* This file is part of libEmuSC, a Sound Canvas emulator library
|
||||
* Copyright (C) 2023-2024 Håkon Skjelten
|
||||
*
|
||||
* libEmuSC 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libEmuSC 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 General Public License
|
||||
* along with libEmuSC. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SETTINGS_H__
|
||||
#define __SETTINGS_H__
|
||||
|
||||
|
||||
#include "control_rom.h"
|
||||
#include "params.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace EmuSC {
|
||||
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
Settings(ControlRom & ctrlRom);
|
||||
~Settings();
|
||||
|
||||
// Sound Canvas modes
|
||||
enum class Mode {
|
||||
GS, // Standard GS mode. Default.
|
||||
MT32, // MT32 mode
|
||||
SC55 // SC-55 mode for SC-88 TODO
|
||||
|
||||
// TODO: What about GM mode?
|
||||
};
|
||||
|
||||
// Interpolation modes
|
||||
enum class InterpMode {
|
||||
Nearest = 0,
|
||||
Linear = 1,
|
||||
Cubic = 2
|
||||
};
|
||||
|
||||
// Retrieve settings from Config paramters
|
||||
uint8_t get_param(enum SystemParam sp);
|
||||
uint8_t* get_param_ptr(enum SystemParam sp);
|
||||
uint32_t get_param_uint32(enum SystemParam sp);
|
||||
uint16_t get_param_32nib(enum SystemParam sp);
|
||||
uint8_t get_param(enum PatchParam pp, int8_t part = -1);
|
||||
uint8_t* get_param_ptr(enum PatchParam pp, int8_t part = -1);
|
||||
uint16_t get_param_uint14(enum PatchParam pp, int8_t part = -1);
|
||||
uint16_t get_param_uint16(enum PatchParam pp, int8_t part = -1);
|
||||
uint8_t get_param_nib16(enum PatchParam pp, int8_t part = -1);
|
||||
uint8_t get_patch_param(uint16_t address, int8_t part = -1);
|
||||
uint8_t get_param(enum DrumParam, uint8_t map, uint8_t key);
|
||||
int8_t* get_param_ptr(enum DrumParam, uint8_t map);
|
||||
|
||||
// Set settings from Config paramters
|
||||
void set_param(enum SystemParam sp, uint8_t value);
|
||||
void set_param(enum SystemParam sp, const uint8_t *data, uint8_t size);
|
||||
void set_param_uint32(enum SystemParam sp, uint32_t value);
|
||||
void set_param_32nib(enum SystemParam sp, uint16_t value);
|
||||
void set_system_param(uint16_t address, const uint8_t *data, uint8_t size = 1);
|
||||
|
||||
void set_param(enum PatchParam pp, uint8_t value, int8_t part = -1);
|
||||
void set_param(enum PatchParam pp, const uint8_t *data, uint8_t size = 1,
|
||||
int8_t part = -1);
|
||||
void set_param_uint14(enum PatchParam pp, uint16_t value, int8_t part = -1);
|
||||
void set_param_nib16(enum PatchParam pp, uint8_t value, int8_t part = -1);
|
||||
void set_patch_param(uint16_t address, const uint8_t *data, uint8_t size = 1);
|
||||
void set_patch_param(uint16_t address, uint8_t value, int8_t part = -1);
|
||||
void set_param(enum DrumParam dp, uint8_t map, uint8_t key, uint8_t value);
|
||||
void set_param(enum DrumParam dp, uint8_t map, const uint8_t *data, uint8_t length);
|
||||
void set_drum_param(uint16_t address, const uint8_t *data, uint8_t size = 1);
|
||||
|
||||
int update_drum_set(uint8_t map, uint8_t bank);
|
||||
|
||||
// Store settings paramters to file (aka battery backup)
|
||||
bool load(std::string filePath);
|
||||
bool save(std::string filePath);
|
||||
|
||||
// Reset all settings to default GS mode
|
||||
void reset();
|
||||
void set_gm_mode(void);
|
||||
void set_map_mt32(void);
|
||||
|
||||
// Temporary solution
|
||||
// Figure out the need for a common way with all controllers
|
||||
void update_pitchBend_factor(int8_t part);
|
||||
float get_pitchBend_factor(int8_t part) { return _PBController[part]; }
|
||||
|
||||
static int8_t convert_from_roland_part_id(int8_t part);
|
||||
|
||||
void set_sample_rate(int sampleRate) { _sampleRate = sampleRate; }
|
||||
inline int sample_rate(void) { return _sampleRate; }
|
||||
|
||||
void set_channels(int channels) { _channels = channels; }
|
||||
inline int channels(void) { return _channels; }
|
||||
|
||||
void set_interpolation_mode(enum InterpMode im) { _interpMode = im; }
|
||||
inline enum InterpMode interpolation_mode(void) { return _interpMode; }
|
||||
|
||||
private:
|
||||
std::array<uint8_t, 0x0100> _systemParams; // Both SysEx and non-SysEx data
|
||||
std::array<uint8_t, 0x4000> _patchParams;
|
||||
std::array<uint8_t, 0x2000> _drumParams;
|
||||
|
||||
ControlRom &_ctrlRom;
|
||||
|
||||
// Non-native parameters
|
||||
int _sampleRate;
|
||||
int _channels;
|
||||
InterpMode _interpMode;
|
||||
|
||||
void _initialize_system_params(enum Mode = Mode::GS);
|
||||
void _initialize_patch_params(enum Mode = Mode::GS);
|
||||
void _initialize_drumSet_params();
|
||||
|
||||
// BE / LE conversion
|
||||
inline bool _le_native(void) { uint16_t n = 1; return (*(const uint8_t *) & n); }
|
||||
uint8_t _to_native_endian_nib16(const uint8_t *ptr);
|
||||
uint16_t _to_native_endian_uint14(const uint8_t *ptr);
|
||||
uint16_t _to_native_endian_uint16(const uint8_t *ptr);
|
||||
uint32_t _to_native_endian_uint32(const uint8_t *ptr);
|
||||
|
||||
// Macros for certain settings
|
||||
void _run_macro_chorus(uint8_t value);
|
||||
void _run_macro_reverb(uint8_t value);
|
||||
|
||||
// Update accumulated controller inputs
|
||||
void _update_controller_input(enum PatchParam pp, uint8_t value, int8_t part);
|
||||
void _update_controller_input_acc(enum PatchParam pp, int8_t part);
|
||||
void _accumulate_controller_values(enum PatchParam ctm, enum PatchParam acc,
|
||||
int8_t partm, int min, int max, bool center);
|
||||
|
||||
// Temporary storage for pitchbend
|
||||
float _PBController[16];
|
||||
|
||||
static constexpr std::array<uint8_t, 16> _convert_to_roland_part_id_LUT =
|
||||
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 14, 15 };
|
||||
static constexpr std::array<uint8_t, 16> _convert_from_roland_part_id_LUT =
|
||||
{ 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15 };
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __SETTINGS_H__
|
185
ThirdParty/libemusc/include/synth.h
vendored
Normal file
185
ThirdParty/libemusc/include/synth.h
vendored
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* This file is part of libEmuSC, a Sound Canvas emulator library
|
||||
* Copyright (C) 2022-2024 Håkon Skjelten
|
||||
*
|
||||
* libEmuSC 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libEmuSC 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 General Public License
|
||||
* along with libEmuSC. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SYNTH_H__
|
||||
#define __SYNTH_H__
|
||||
|
||||
|
||||
#include "control_rom.h"
|
||||
#include "params.h"
|
||||
#include "pcm_rom.h"
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
/* Public API for libEmuSC
|
||||
*
|
||||
* This Synth class is responsible for receiving MIDI events from client,
|
||||
* process the event based on information in Control and PCM ROMS, and
|
||||
* finally responding to audio buffer requests.
|
||||
*
|
||||
* Synth class constructor depends on a valid Control Rom and PCM ROM.
|
||||
*
|
||||
* MIDI events is sent to the emulator via the midi_input() method using the
|
||||
* three bytes from raw MIDI events.
|
||||
*
|
||||
* Audio samples are extracted by calling the get_next_sample() method. This
|
||||
* is typically done from a callback function triggered by the OS audio
|
||||
* driver when the audio buffer is running low.
|
||||
*
|
||||
* All settings are configured through the Settings class.
|
||||
*/
|
||||
|
||||
|
||||
namespace EmuSC {
|
||||
|
||||
class Part;
|
||||
class Settings;
|
||||
|
||||
class Synth
|
||||
{
|
||||
public:
|
||||
|
||||
enum class SoundMap {
|
||||
GS, // Default GS settings
|
||||
GS_GM, // GS settings in GM mode (available on SC55mk2+)
|
||||
MT32 // MT32 arrangement
|
||||
};
|
||||
|
||||
Synth(ControlRom &cRom, PcmRom &pRom, SoundMap map = SoundMap::GS);
|
||||
~Synth();
|
||||
|
||||
// Add start() and stop()? Won't start if sampleRate is not set?
|
||||
|
||||
void midi_input(uint8_t status, uint8_t data1, uint8_t data2);
|
||||
void midi_input_sysex(const uint8_t *data, uint16_t length);
|
||||
|
||||
int get_next_sample(int16_t *sample);
|
||||
int get_next_sample(float *sample);
|
||||
std::array<float, 16> get_parts_last_peak_sample(void);
|
||||
|
||||
// Setting audio properties (default is 44100, 2)
|
||||
void set_audio_format(uint32_t sampleRate, uint8_t channels);
|
||||
void set_interpolation_mode(int mode);
|
||||
|
||||
void reset(SoundMap sm, bool resetParts = false);
|
||||
|
||||
void panic(void);
|
||||
|
||||
// Mute all parts. Similar to push MUTE-button on real hardware
|
||||
void mute(void);
|
||||
|
||||
// Unmute all parts. Similar to push MUTE-button on real hardware
|
||||
void unmute(void);
|
||||
|
||||
// Mute 1-n parts
|
||||
void mute_parts(std::vector<uint8_t> parts);
|
||||
|
||||
// Unute all parts
|
||||
void unmute_parts(std::vector<uint8_t> parts);
|
||||
|
||||
// Returns libEmuSC version as a string
|
||||
static std::string version(void);
|
||||
|
||||
// REMOVE!
|
||||
bool get_part_mute(uint8_t partId);
|
||||
uint8_t get_part_instrument(uint8_t partId, uint8_t &bank);
|
||||
void set_part_mute(uint8_t partId, bool mute);
|
||||
void set_part_instrument(uint8_t partId, uint8_t index, uint8_t bank);
|
||||
|
||||
void add_part_midi_mod_callback(std::function<void(const int)> callback);
|
||||
void clear_part_midi_mod_callback(void);
|
||||
|
||||
void set_part_envelope_callback(int partId,
|
||||
std::function<void(const float, const float,
|
||||
const float, const float,
|
||||
const float, const float)> callback);
|
||||
void clear_part_envelope_callback(int partId);
|
||||
void set_part_lfo_callback(int partId,
|
||||
std::function<void(const float, const float,
|
||||
const float)> callback);
|
||||
void clear_part_lfo_callback(int partId);
|
||||
|
||||
// EmuSC clients methods for getting synth paramters
|
||||
uint8_t get_param(enum SystemParam sp);
|
||||
uint8_t* get_param_ptr(enum SystemParam sp);
|
||||
uint16_t get_param_32nib(enum SystemParam sp);
|
||||
uint8_t get_param(enum PatchParam pp, int8_t part = -1);
|
||||
uint8_t* get_param_ptr(enum PatchParam pp, int8_t part = -1);
|
||||
uint16_t get_param_uint14(enum PatchParam pp, int8_t part = -1);
|
||||
uint8_t get_param_nib16(enum PatchParam pp, int8_t part = -1);
|
||||
uint8_t get_patch_param(uint16_t address, int8_t part = -1);
|
||||
uint8_t get_param(enum DrumParam, uint8_t map, uint8_t key);
|
||||
int8_t* get_param_ptr(enum DrumParam, uint8_t map);
|
||||
|
||||
// EmuSC clients methods for setting synth paramters
|
||||
void set_param(enum SystemParam sp, uint8_t value);
|
||||
void set_param(enum SystemParam sp, uint32_t value);
|
||||
void set_param(enum SystemParam sp, const uint8_t *data, uint8_t size = 1);
|
||||
void set_param_32nib(enum SystemParam sp, uint16_t value);
|
||||
void set_param(enum PatchParam pp, uint8_t value, int8_t part = -1);
|
||||
void set_param(enum PatchParam sp, const uint8_t *data, uint8_t size = 1,
|
||||
int8_t part = -1);
|
||||
void set_param_uint14(enum PatchParam pp, uint16_t value, int8_t part = -1);
|
||||
void set_param_nib16(enum PatchParam pp, uint8_t value, int8_t part = -1);
|
||||
void set_patch_param(uint16_t address, uint8_t value, int8_t part = 1);
|
||||
void set_param(enum DrumParam dp, uint8_t map, uint8_t key, uint8_t value);
|
||||
void set_param(enum DrumParam dp, uint8_t map, const uint8_t *data, uint8_t length);
|
||||
|
||||
/* End of public API. Below are internal data structures only */
|
||||
|
||||
private:
|
||||
Settings *_settings;
|
||||
|
||||
uint32_t _sampleRate;
|
||||
uint8_t _channels;
|
||||
|
||||
std::mutex midiMutex;
|
||||
|
||||
struct std::vector<Part> _parts;
|
||||
std::vector<std::function<void(const int)>> _partMidiModCallbacks;
|
||||
|
||||
ControlRom &_ctrlRom;
|
||||
PcmRom &_pcmRom;
|
||||
|
||||
// MIDI message types
|
||||
static const uint8_t midi_NoteOff = 0x80;
|
||||
static const uint8_t midi_NoteOn = 0x90;
|
||||
static const uint8_t midi_PolyKeyPressure = 0xa0;
|
||||
static const uint8_t midi_CtrlChange = 0xb0;
|
||||
static const uint8_t midi_PrgChange = 0xc0;
|
||||
static const uint8_t midi_ChPressure = 0xd0;
|
||||
static const uint8_t midi_PitchBend = 0xe0;
|
||||
|
||||
void _init_parts(void);
|
||||
// int _export_sample_24(std::vector<int32_t> &sampleSet, std::string filename);
|
||||
void _add_note(uint8_t midiChannel, uint8_t key, uint8_t velocity);
|
||||
|
||||
void _midi_input_sysex_DT1(uint8_t model, const uint8_t *data, uint16_t length);
|
||||
|
||||
Synth();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __SYNTH_H__
|
BIN
ThirdParty/libemusc/lib/libemusc.0.dylib
vendored
Executable file
BIN
ThirdParty/libemusc/lib/libemusc.0.dylib
vendored
Executable file
Binary file not shown.
Loading…
Reference in a new issue