Skip to content

Commit

Permalink
Version 14.8.2
Browse files Browse the repository at this point in the history
  • Loading branch information
bribi5940 committed Jun 26, 2023
1 parent eba0fa5 commit 4000f9b
Show file tree
Hide file tree
Showing 10 changed files with 332 additions and 248 deletions.
142 changes: 96 additions & 46 deletions OmniMIDI/BufferSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,68 +114,129 @@ void __inline SendLongMIDIFeedback(LPMIDIHDR mHDR, UINT Size) {
}
}

void __inline SendToBASSMIDI(DWORD dwParam1) {
DWORD len = 3;
bool __inline SendToBASSMIDI(unsigned int ev) {
/*
For more info about how an event is structured, read this doc from Microsoft:
https://learn.microsoft.com/en-us/windows/win32/api/mmeapi/nf-mmeapi-midioutshortmsg
-
TL;DR is here though:
Let's assume that we have an event coming through, of value 0x007F7F95.
MIDI events are ALWAYS big endian.
The high-order byte of the high word is ignored.
// PrintEventToDebugLog(dwParam1);
The low-order of the high word contains the first part of the data, which, for
a NoteOn event, is the key number (from 0 to 127).
The high-order of the low word contains the second part of the data, which, for
a NoteOn event, is the velocity of the key (again, from 0 to 127).
The low-order byte of the low word contains two nibbles combined into one.
The first nibble contains the type of event (1001 is 0x9, which is a NoteOn),
while the second nibble contains the channel (0101 is 0x5, which is the 5th channel).
So, in short, we can read it as follows:
0x957F7F should press the 128th key on the keyboard at full velocity, on MIDI channel 5.
But hey! We can also receive events with a long running status, which means there's no status byte!
That event, if we consider the same example from before, will look like this: 0x00007F7F
Such event will only work if the driver receives a status event, which will be stored in memory.
So, in a sequence of data like this:
..
1. 0x00044A90 (NoteOn on key 75 at velocity 10)
2. 0x00007F7F (... then on key 128 at velocity 127)
3. 0x00006031 (... then on key 50 at velocity 96)
4. 0x0000605F (... and finally on key 95 at velocity 96)
..
The same status from event 1 will be applied to all the status-less events from 2 and onwards.
-
INFO: ev will be recasted as char in some parts of the code, since those parts
do not require the high-word part of the unsigned int.
*/

switch (dwParam1 & 0xFF) {
unsigned int tev = ev;

if (CHKLRS(GETSTATUS(tev)) != 0) LastRunningStatus = GETSTATUS(tev);
else tev = ev << 8 | LastRunningStatus;

unsigned int ch = tev & 0xF;
unsigned int evt = 0;
unsigned int param = GETFP(tev);

unsigned int cmd = GETCMD(tev);
unsigned int len = 3;
bool ok = true;

switch (LastRunningStatus) {
// Handle 0xFF (GS reset) first!
case 0xFF:
for (int i = 0; i < 16; i++) {
_BMSE(OMStream, i, MIDI_EVENT_SYSTEM, MIDI_SYSTEM_DEFAULT);
if (!BASS_MIDI_StreamEvent(OMStream, i, MIDI_EVENT_SOUNDOFF, 0))
ok = false;

if (!BASS_MIDI_StreamEvent(OMStream, i, MIDI_EVENT_NOTESOFF, 0))
ok = false;

if (!BASS_MIDI_StreamEvent(OMStream, i, MIDI_EVENT_SYSTEM, MIDI_SYSTEM_DEFAULT))
ok = false;
}
return;
return ok;

default:
switch (GETCMD(dwParam1)) {
switch (GETCMD(ev)) {
case MIDI_NOTEON:
_BMSE(OMStream, dwParam1 & 0xF, MIDI_EVENT_NOTE, dwParam1 >> 8);
return;
evt = MIDI_EVENT_NOTE;
break;
case MIDI_NOTEOFF:
_BMSE(OMStream, dwParam1 & 0xF, MIDI_EVENT_NOTE, (BYTE)(dwParam1 >> 8));
return;
evt = MIDI_EVENT_NOTE;
param = (char)param;
break;
case MIDI_POLYAFTER:
_BMSE(OMStream, dwParam1 & 0xF, MIDI_EVENT_KEYPRES, dwParam1 >> 8);
return;
evt = MIDI_EVENT_KEYPRES;
break;
case MIDI_PROGCHAN:
_BMSE(OMStream, dwParam1 & 0xF, MIDI_EVENT_PROGRAM, (BYTE)(dwParam1 >> 8));
return;
evt = MIDI_EVENT_PROGRAM;
param = (char)param;
break;
case MIDI_CHANAFTER:
_BMSE(OMStream, dwParam1 & 0xF, MIDI_EVENT_CHANPRES, (BYTE)(dwParam1 >> 8));
return;
evt = MIDI_EVENT_CHANPRES;
param = (char)param;
break;
default:
if (!(dwParam1 - 0x80 & 0xC0))
{
_BMSEs(OMStream, BASS_MIDI_EVENTS_RAW, &dwParam1, 3);
return;
}
// Some events do not have a specific counter part on BASSMIDI's side, so they have
// to be directly fed to the library by using the BASS_MIDI_EVENTS_RAW flag.
if (!(ev - 0x80 & 0xC0))
return _BMSEs(OMStream, BASS_MIDI_EVENTS_RAW, &tev, 3);

if (!((dwParam1 - 0xC0) & 0xE0)) len = 2;
else if ((dwParam1 & 0xF0) == 0xF0)
if (!((ev - 0xC0) & 0xE0)) len = 2;
else if (GETCMD(ev) == 0xF0)
{
switch (dwParam1 & 0xF)
switch (ev & 0xF)
{
case 3:
len = 2;
break;
default:
// Not supported by OmniMIDI!
return;
return false;
}
}

_BMSEs(OMStream, BMSEsRAWFlags, &dwParam1, len);
return;
return _BMSEs(OMStream, BASS_MIDI_EVENTS_RAW, &tev, len);
}
}

return _BMSE(OMStream, ch, evt, param);
}

void __inline PrepareForBASSMIDI(DWORD LastRunningStatus, DWORD dwParam1) {
void __inline PrepareForBASSMIDI(DWORD dwParam1) {
BASS_MIDI_EVENT Evs[2];

if (!(dwParam1 & 0x80))
dwParam1 = dwParam1 << 8 | LastRunningStatus;

if (ManagedSettings.FullVelocityMode || ManagedSettings.TransposeValue != 0x7F)
dwParam1 = ReturnEditedEvent(dwParam1);

Expand Down Expand Up @@ -207,10 +268,7 @@ void __inline PrepareForBASSMIDI(DWORD LastRunningStatus, DWORD dwParam1) {
SendToBASSMIDI(dwParam1);
}

void __inline PrepareForBASSMIDIHyper(DWORD LastRunningStatus, DWORD dwParam1) {
if (!(dwParam1 & 0x80))
dwParam1 = dwParam1 << 8 | LastRunningStatus;

void __inline PrepareForBASSMIDIHyper(DWORD dwParam1) {
SendToBASSMIDI(dwParam1);
}

Expand All @@ -229,12 +287,10 @@ void __inline SendLongToBASSMIDI(LPMIDIHDR IIMidiHdr) {
// and can not be skipped
void __inline PBufData(void) {
DWORD dwParam1 = EVBuffer.Buffer[EVBuffer.ReadHead].Event;
if (dwParam1 & 0x80)
LastRunningStatus = (BYTE)dwParam1;

if (++EVBuffer.ReadHead >= EVBuffer.BufSize) EVBuffer.ReadHead = 0;

_PforBASSMIDI(LastRunningStatus, dwParam1);
_PforBASSMIDI(dwParam1);
}

void __inline PSmallBufData(void)
Expand All @@ -254,13 +310,7 @@ void __inline PSmallBufData(void)

EVBuffer.ReadHead = HeadPos;

if (~dwParam1)
{
if (dwParam1 & 0x80)
LastRunningStatus = (BYTE)dwParam1;

_PforBASSMIDI(LastRunningStatus, dwParam1);
}
if (~dwParam1) _PforBASSMIDI(dwParam1);
else return;

if (HeadPos == HeadStart) return;
Expand Down
33 changes: 31 additions & 2 deletions OmniMIDI/Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ OmniMIDI debug functions
#define PRINT_FLOAT 4
#define PRINT_BOOL 5
#define PRINT_WCHAR 6
#define PRINT_CHAR 7

#define CurrentError(Message, Error, Text) case Error: sprintf_s(Message, NTFS_MAX_PATH, "Error %s:\n%s", #Error, #Text); break
#define DefError(Message, Error, Text) sprintf_s(Message, NTFS_MAX_PATH, "Error %s:\n%s", #Error, #Text); break
Expand Down Expand Up @@ -152,6 +153,27 @@ void PrintCurrentTimeW() {
stime.wDay, stime.wMonth, stime.wYear, stime.wHour, stime.wMinute, stime.wSecond, stime.wMilliseconds);
}

void PrintHexToDebugLog(DWORD_PTR a, DWORD_PTR b) {
if (ManagedSettings.DebugMode) {
char* Msg = (char*)malloc(sizeof(char) * NTFS_MAX_PATH);

// Debug log is busy now
std::lock_guard<std::mutex> lock(DebugMutex);

// Print to log
PrintCurrentTime();
sprintf(Msg, "Stage <<BM>> | noLRS-> %x, LRS-> %x", a, b);

fprintf(DebugLog, Msg);
OutputDebugStringA(Msg);

free(Msg);

// Flush buffer
fflush(DebugLog);
}
}

void PrintMMToDebugLog(UINT uDID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
if (ManagedSettings.DebugMode) {
char* Msg = (char*)malloc(sizeof(char) * NTFS_MAX_PATH);
Expand Down Expand Up @@ -364,7 +386,7 @@ void PrintVarToDebugLog(LPCSTR Stage, LPCSTR ValueName, void* Var, int Type) {
case PRINT_FLOAT:
{
float FVar = *(float*)Var;
sprintf(AMsg, "Stage <<%s>> | %s: %f (float)\n", Stage, ValueName, *(float*)Var);
sprintf(AMsg, "Stage <<%s>> | %s: %f (float)\n", Stage, ValueName, FVar);
fprintf(DebugLog, AMsg);
OutputDebugStringA(AMsg);
break;
Expand All @@ -377,9 +399,16 @@ void PrintVarToDebugLog(LPCSTR Stage, LPCSTR ValueName, void* Var, int Type) {
OutputDebugStringA(AMsg);
break;
}
case PRINT_CHAR:
{
sprintf(AMsg, "Stage <<%s>> | %s: %s (char)\n", Stage, ValueName, Var);
fprintf(DebugLog, AMsg);
OutputDebugStringA(AMsg);
break;
}
case PRINT_WCHAR:
{
swprintf(WMsg, L"Stage <<%S>> | %S: %s (wchar_t)\n", Stage, ValueName, (wchar_t*)Var);
swprintf(WMsg, L"Stage <<%S>> | %S: %s (wchar_t)\n", Stage, ValueName, Var);
fwprintf(DebugLog, WMsg);
OutputDebugStringW(WMsg);
break;
Expand Down
23 changes: 13 additions & 10 deletions OmniMIDI/DriverInit.h
Original file line number Diff line number Diff line change
Expand Up @@ -516,20 +516,23 @@ void InitializeBASSVST() {
PathAppend(LoudMax, _T("\\OmniMIDI\\LoudMax\\LoudMax32.dll"));
#endif

#ifndef _M_ARM64
// If the DLL exists, begin the loading process
if (PathFileExists(LoudMax)) {
// Initialize BASS_VST
if (LoadDriverModule(&BASS_VST, L"bass_vst.dll")) {
LOADLIBFUNCTION(BASS_VST.Lib, BASS_VST_ChannelSetDSP);
LOADLIBFUNCTION(BASS_VST.Lib, BASS_VST_ChannelFree);
LOADLIBFUNCTION(BASS_VST.Lib, BASS_VST_ChannelCreate);
LOADLIBFUNCTION(BASS_VST.Lib, BASS_VST_ProcessEvent);
LOADLIBFUNCTION(BASS_VST.Lib, BASS_VST_ProcessEventRaw);

BASS_VST_ChannelSetDSP(OMStream, LoudMax, BASS_UNICODE, 1);
if (!BASS_VST.Initialized) {
if (!LoadLib(&BASS_VST))
return;
}
else { /* Nothing, probably on ARM64 */ }
// Initialize BASS_VST
LoadFuncM(BASS_VST, BASS_VST_ChannelSetDSP);
LoadFuncM(BASS_VST, BASS_VST_ChannelFree);
LoadFuncM(BASS_VST, BASS_VST_ChannelCreate);
LoadFuncM(BASS_VST, BASS_VST_ProcessEvent);
LoadFuncM(BASS_VST, BASS_VST_ProcessEventRaw);

BASS_VST_ChannelSetDSP(OMStream, LoudMax, BASS_UNICODE, 1);
}
#endif
}

BOOL InitializeStream(INT32 mixfreq) {
Expand Down
Binary file modified OmniMIDI/Resource.aps
Binary file not shown.
Binary file modified OmniMIDI/Resource.rc
Binary file not shown.
27 changes: 17 additions & 10 deletions OmniMIDI/Values.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@
// Things
UINT CPUThreadsAvailable = 0;

#define LOADLIBFUNCTION(l, f) *((void**)&f)=GetProcAddress(l,#f)
#define fv2fn(f) (#f)
#define SetPath(f) if (!f.Path) f.Path = L#f
#define LoadFuncM(l, f) *((void**)&f) = GetProcAddress(l.Lib,#f)

#define GETCMD(f) f & 0xF0
#define GETSP(f) (f >> 16) & 0xFF
#define GETFP(f) (f >> 8) & 0xFF
#define GETCHANNEL(f) f & 0xF
#define CHKLRS(f) (f & 0x80)
#define GETCMD(f) (f & 0xF0)
#define GETCHANNEL(f) (f & 0xF)
#define GETSTATUS(f) (f & 0xFF)
#define GETSP(f) (f >> 16)
#define GETFP(f) (f >> 8)

#define SETVELOCITY(f, nf) f = (f & 0xFF00FFFF) | ((DWORD(nf) & 0xFF) << 16)
#define SETNOTE(f, nf) f = (f & 0xFFFF00FF) | ((DWORD(nf) & 0xFF) << 8)
Expand Down Expand Up @@ -58,15 +62,18 @@ typedef struct EventsBuffer {

// The buffer's structure
EventsBuffer EVBuffer; // The buffer
ULONG LastRunningStatus = 0; // Last running status
unsigned char LastRunningStatus = 0; // Last running status
ULONGLONG EvBufferSize = 4096;
ULONG EvBufferMultRatio = 1;
ULONG GetEvBuffSizeFromRAM = 0;

// BASS lib
typedef struct OMLib {
HMODULE Lib = NULL;
BOOL AppOwnDLL = FALSE;
const wchar_t* Path;
HMODULE Lib = nullptr;
bool AppOwnDLL = false;
bool LoadFailed = false;
bool Initialized = false;
};
OMLib BASS = {}, BASSWASAPI = {}, BASSASIO = {}, BASSENC = {}, BASSMIDI = {}, BASS_VST = {};
HPLUGIN bassflac = NULL, basswv = NULL, bassopus = NULL;
Expand Down Expand Up @@ -329,7 +336,7 @@ DDP DefDriverProcImp = 0;

// Critical sections but handled by OmniMIDI functions because f**k Windows
void DummyPlayBufData() noexcept { return; };
void DummyPrepareForBASSMIDI(DWORD, DWORD) noexcept { return; };
void DummyPrepareForBASSMIDI(DWORD) noexcept { return; };
void DummyParseData(DWORD_PTR) noexcept { return; };
void DummyShortMsg(DWORD) noexcept { return; };
void DummyLongMsg(LPMIDIHDR, UINT) noexcept { return; };
Expand All @@ -340,7 +347,7 @@ DWORD CALLBACK DummyProcData(void*, DWORD, void*) noexcept { return 0; };
// Hyper switch
BOOL HyperMode = 0;
void(*_PrsData)(DWORD_PTR dwParam1) = DummyParseData;
void(*_PforBASSMIDI)(DWORD LastRunningStatus, DWORD dwParam1) = DummyPrepareForBASSMIDI;
void(*_PforBASSMIDI)(DWORD dwParam1) = DummyPrepareForBASSMIDI;
void(*_PlayBufData)(void) = DummyPlayBufData;
void(*_PlayBufDataChk)(void) = DummyPlayBufData;
void(*_FeedbackShortMsg)(DWORD) = DummyShortMsg;
Expand Down
3 changes: 3 additions & 0 deletions OmniMIDI/WDMInstall.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ static RegisterDriverResult registerDriver(const bool wow64Process, int& entryIx
MessageBoxA(NULL, CANNOT_OPEN_REGISTRY_ERR, REGISTRY_ERROR_TITLE, MB_OK | MB_ICONEXCLAMATION);
return RegisterDriverResult_FAILED;
}

MidiRegistryEntryName entryName;
if (!findFreeMidiRegEntry(entryIx, hReg, entryName)) {
RegCloseKey(hReg);
Expand All @@ -230,6 +231,7 @@ static RegisterDriverResult registerDriver(const bool wow64Process, int& entryIx
}
return RegisterDriverResult_ALREADY_EXISTS;
}

const char* freeEntryName = entryName.withIndex(entryIx)->toCString();
LSTATUS res = RegSetValueExA(hReg, freeEntryName, NULL, REG_SZ, (LPBYTE)OMNIMIDI_DRIVER_NAME, sizeof(OMNIMIDI_DRIVER_NAME));
RegCloseKey(hReg);
Expand All @@ -240,6 +242,7 @@ static RegisterDriverResult registerDriver(const bool wow64Process, int& entryIx
if (wow64Process && !registerDriverInWow(freeEntryName)) {
return RegisterDriverResult_FAILED;
}

return RegisterDriverResult_OK;
}

Expand Down
Loading

0 comments on commit 4000f9b

Please sign in to comment.