Skip to content

Instantly share code, notes, and snippets.

@kode54
Last active October 2, 2021 13:24
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kode54/01929e2f1dfc9ee4f8f1 to your computer and use it in GitHub Desktop.
Save kode54/01929e2f1dfc9ee4f8f1 to your computer and use it in GitHub Desktop.
SCCore00 interface
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include "SCCore.h"
SCCore::SCCore()
{
duped = false;
path = 0;
handle = 0;
TG_initialize = 0;
//TG_terminate = 0;
TG_activate = 0;
TG_deactivate = 0;
TG_setSampleRate = 0;
TG_setMaxBlockSize = 0;
TG_flushMidi = 0;
TG_setInterruptThreadIdAtThisTime = 0;
// TG_PMidiIn = 0;
TG_ShortMidiIn = 0;
TG_LongMidiIn = 0;
// TG_isFatalError = 0;
// TG_getErrorStrings = 0;
TG_XPgetCurTotalRunningVoices = 0;
// TG_XPsetSystemConfig = 0;
// TG_XPgetCurSystemConfig = 0;
TG_Process = 0;
}
SCCore::~SCCore()
{
Unload();
}
void SCCore::Unload()
{
if (handle)
{
dlclose(handle);
handle = 0;
}
if (duped && path)
{
unlink(path);
duped = false;
}
if (path)
{
free(path);
path = 0;
}
}
static const char name_template[] = "/tmp/SCCore.dylib.XXXXXXXX";
bool SCCore::Load(const char * _path, bool dupe)
{
if (dupe)
{
path = (char *) malloc(strlen(name_template) + 1);
strcpy(path, name_template);
mktemp(path);
const char * uniq = path + strlen(path) - 8;
FILE * f = fopen(_path, "rb");
if (!f) return false;
fseek(f, 0, SEEK_END);
size_t fs = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char * buffer = (unsigned char *) malloc(fs);
if (!fs)
{
fclose(f);
return false;
}
fread(buffer, 1, fs, f);
fclose(f);
for (size_t i = 0; i < fs - 14; ++i)
{
if (memcmp(buffer + i, "SCCore00.dylib", 14) == 0)
{
memcpy(buffer + i, uniq, 8);
i += 13;
}
}
duped = true;
f = fopen(path, "wb");
if (!f)
{
free(buffer);
return false;
}
fwrite(buffer, 1, fs, f);
fclose(f);
free(buffer);
}
else
{
path = (char *) malloc(strlen(_path) + 1);
strcpy(path, _path);
}
handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
if (handle)
{
*(void**)&TG_initialize = dlsym(handle, "TG_initialize");
//*(void**)&TG_terminate = dlsym(handle, "TG_terminate");
*(void**)&TG_activate = dlsym(handle, "TG_activate");
*(void**)&TG_deactivate = dlsym(handle, "TG_deactivate");
*(void**)&TG_setSampleRate = dlsym(handle, "TG_setSampleRate");
*(void**)&TG_setMaxBlockSize = dlsym(handle, "TG_setMaxBlockSize");
*(void**)&TG_flushMidi = dlsym(handle, "TG_flushMidi");
*(void**)&TG_setInterruptThreadIdAtThisTime = dlsym(handle, "TG_setInterruptThreadIdAtThisTime");
//*(void**)&TG_PMidiIn = dlsym(handle, "TG_PMidiIn");
*(void**)&TG_ShortMidiIn = dlsym(handle, "TG_ShortMidiIn");
*(void**)&TG_LongMidiIn = dlsym(handle, "TG_LongMidiIn");
//*(void**)&TG_isFatalError = dlsym(handle, "TG_isFatalError");
//*(void**)&TG_getErrorStrings = dlsym(handle, "TG_getErrorStrings");
*(void**)&TG_XPgetCurTotalRunningVoices = dlsym(handle, "TG_XPgetCurTotalRunningVoices");
//*(void**)&TG_XPsetSystemConfig = dlsym(handle, "TG_XPsetSystemConfig");
//*(void**)&TG_XPgetCurSystemConfig = dlsym(handle, "TG_XPgetCurSystemConfig");
*(void**)&TG_Process = dlsym(handle, "TG_Process");
if (TG_initialize && /*TG_terminate &&*/ TG_activate && TG_deactivate &&
TG_setSampleRate && TG_setMaxBlockSize && TG_flushMidi &&
TG_setInterruptThreadIdAtThisTime && /*TG_PMidiIn &&*/
TG_ShortMidiIn && TG_LongMidiIn && /*TG_isFatalError &&
TG_getErrorStrings &&*/ TG_XPgetCurTotalRunningVoices &&
/*TG_XPsetSystemConfig && TG_XPgetCurSystemConfig &&*/
TG_Process)
{
return true;
}
else
{
TG_initialize = 0;
//TG_terminate = 0;
TG_activate = 0;
TG_deactivate = 0;
TG_setSampleRate = 0;
TG_setMaxBlockSize = 0;
TG_flushMidi = 0;
TG_setInterruptThreadIdAtThisTime = 0;
// TG_PMidiIn = 0;
TG_ShortMidiIn = 0;
TG_LongMidiIn = 0;
// TG_isFatalError = 0;
// TG_getErrorStrings = 0;
TG_XPgetCurTotalRunningVoices = 0;
// TG_XPsetSystemConfig = 0;
// TG_XPgetCurSystemConfig = 0;
TG_Process = 0;
dlclose(handle);
handle = 0;
}
}
return false;
}
#ifndef _SCCore_h_
#define _SCCore_h_
// Static single instance - duplicate library to temp path for unique instance
class SCCore
{
bool duped;
char * path;
void * handle;
public:
int (* TG_initialize)(int i); // i = 0, returns negative on failure
//void (* TG_terminate)(); // Unused
void (* TG_activate)(float sampleRate, int blockSize);
void (* TG_deactivate)(); // Unused - hopefully cleans up
void (*TG_setSampleRate)(float sampleRate);
void (*TG_setMaxBlockSize)(unsigned int blockSize);
void (*TG_flushMidi)(); // Called after applying presets
void (*TG_setInterruptThreadIdAtThisTime)();
//void (*TG_PMidiIn)(MpPacket *, int count); // Unknown
void (*TG_ShortMidiIn)(unsigned int eventCode, unsigned int deltaFrames);
void (*TG_LongMidiIn)(const unsigned char * sysEx, unsigned int deltaFrames);
//void (*TG_isFatalError)(int errCode); // Unused
//void (*TG_getErrorStrings)(int errCode); // Unused
unsigned int (*TG_XPgetCurTotalRunningVoices)(); // Unused
//void (*TG_XPsetSystemConfig)();
//void (*TG_XPgetCurSystemConfig)();
void (*TG_Process)(float * left, float * right, unsigned int count);
SCCore();
~SCCore();
bool Load(const char * path, bool dupe);
void Unload();
};
#endif
#include "SCPlayer.h"
SCPlayer::SCPlayer() : MIDIPlayer(), initialized(false)
{
}
SCPlayer::~SCPlayer()
{
shutdown();
}
void SCPlayer::send_event(uint32_t b, uint32_t sample_offset)
{
if (!(b & 0x80000000))
{
unsigned port = (b >> 24) & 0x7F;
if ( port > 2 ) port = 2;
sampler[port].TG_ShortMidiIn(b, sample_offset);
}
else
{
uint32_t n = b & 0xffffff;
const uint8_t * data;
std::size_t size, port;
mSysexMap.get_entry( n, data, size, port );
if ( port > 2 ) port = 2;
sampler[port].TG_LongMidiIn(data, sample_offset);
if ( port == 0 )
{
sampler[1].TG_LongMidiIn(data, sample_offset);
sampler[2].TG_LongMidiIn(data, sample_offset);
}
}
}
void SCPlayer::render_512(float * out)
{
float buffer[2][512];
memset(out, 0, 512 * sizeof(float) * 2);
for (unsigned long i = 0; i < 3; ++i)
{
memset(buffer, 0, sizeof(buffer));
sampler[i].TG_setInterruptThreadIdAtThisTime();
sampler[i].TG_Process(buffer[0], buffer[1], 512);
for (unsigned long j = 0; j < 512; ++j)
{
out[j * 2 + 0] += buffer[0][j];
out[j * 2 + 1] += buffer[1][j];
}
}
}
void SCPlayer::shutdown()
{
for (int i = 0; i < 3; i++)
{
if (sampler[i].TG_deactivate)
sampler[i].TG_deactivate();
sampler[i].Unload();
}
initialized = false;
}
bool SCPlayer::startup()
{
if (initialized) return true;
for (int i = 0; i < 3; i++)
{
if (!sampler[i].Load("SCCore00.dylib", true))
return false;
if (sampler[i].TG_initialize(0) < 0)
return false;
sampler[i].TG_activate(44100.0, 1024);
sampler[i].TG_setMaxBlockSize(256);
sampler[i].TG_setSampleRate((float)uSampleRate);
sampler[i].TG_setSampleRate((float)uSampleRate);
sampler[i].TG_setMaxBlockSize(512);
}
initialized = true;
return true;
}
#ifndef __SCPlayer_h__
#define __SCPlayer_h__
#include "MIDIPlayer.h"
#include "SCCore.h"
class SCPlayer : public MIDIPlayer
{
public:
// zero variables
SCPlayer();
// close, unload
virtual ~SCPlayer();
protected:
virtual void send_event(uint32_t b, uint32_t sample_offset);
virtual void render_512(float * out);
virtual void shutdown();
virtual bool startup();
private:
SCCore sampler[3];
bool initialized;
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment