Skip to content

Commit 0fd17f8

Browse files
committed
Initial commit
0 parents  commit 0fd17f8

33 files changed

+3894
-0
lines changed

README.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
About ESFM bank editor
2+
======================
3+
4+
[ESS](https://en.wikipedia.org/wiki/ESS_Technology) PCI Soundcards like
5+
the ES1969 (Solo1), ES1946, Allegro PCI etc. have their own 4-channel
6+
synthesizer which is more capable than [OPL3](https://moddingwiki.shikadi.net/wiki/OPL_chip),
7+
which these card also are capable of emulating.
8+
Their synthesizer is called ESFM and due to its enhanced capabilities, the
9+
driver has its own Patches-table which takes into account the 4 oeprators with
10+
individual frequency offsets, something the basic OPL is not capable of.
11+
The Patches-table is embedded within the driver, but I reverse-engineeres the
12+
ES1969 driver and ported it to also support 64bit, which is available
13+
[here](https://github.com/leecher1337/es1969).
14+
This copy of the driver also allows you to load your custom patch set from a file
15+
so that you can adjust the instrument tables according to your needs and maybe
16+
implement some additional effects that can again then be ported back into
17+
the driver.
18+
19+
As it is not convenient to edit the table with a hex-editor to experiment with
20+
it, ESFM bank editor has been created. It runs on 32bit and 64bit Windows and
21+
allows you to load and save the patches table and also test you settings by
22+
playing an instrument note on the ESFM card (supported ESFM card required).
23+
24+
Installation
25+
============
26+
Depending on the Windows version you have, either download the 32bit or 64bit
27+
package from the "Releases" link on the right side.
28+
Unpack all files to a directory and run esfmbank.exe
29+
30+
How to use
31+
==========
32+
The release package ships with the default patch set that gets used by all
33+
drivers (including i.e. Allegro DOS sound system) except the NT4 driver
34+
which has a slightly different patch set.
35+
Both patch sets can be obtained from
36+
[ESSplaymid repository](https://github.com/pachuco/ESSPlayMid/tree/master/bin).
37+
38+
When opening the application, the default patch set is loaded when available.
39+
The user interface is pretty similar to that of
40+
[OPL3BankEditor](https://github.com/Wohlstand/OPL3BankEditor).
41+
To the left, you can choose between General Midi Melodic (0-127) and
42+
Percussion (128-255) instruments.
43+
When clicking on an instrument, its parameters are shown to the right side.
44+
If an instrument has a second voice, the check box `[x] Second voice`
45+
needs to be checked, otherwise the Tab with the second voice will be readonly.
46+
Per voice, there are the 4 Operators that can be tuned accordingly.
47+
For an explanation on all the settings and values, please see the
48+
[ESFM documentation](https://github.com/jwt27/esfm).
49+
When you change a parameter for an instrument, the change will not be applied,
50+
unless you click on the "Apply" button.
51+
52+
An exception to that rule are the "Play note" etc. buttons on the right which
53+
temporarily apply your settings when playing the note so that you can
54+
experiment with the parameters.
55+
Use "Reset" button to reset the parameters to the state of the last click
56+
on "Apply" (or to initial state if there was no "Apply" click yet).
57+
Apply/Reset are per operator.
58+
For testing the chord, as mentioned, use the buttons under "Testing" tab.
59+
For them to be enabled and to work properly, you need to connect to your
60+
ESS soundcard and for this, you need to know the correct base address of the
61+
SB base port. The application tries to already fill in the correct port,
62+
if you have the ESS soundcard driver installed.
63+
Look under "Soundcard connection" frame for it. In the dropdown menu, you
64+
can select your ESFM soundcard and the correct port should be filled in,
65+
so you just have to click onto "Connect" button to connect to your soundcard.
66+
Be aware that chosing a wrong port can have unforseen consequences for the
67+
stability of you machine, so ensure that you are not using a random port there!
68+
69+
The "MIDI input" tab acts as a possibility to play a MIDI file with the current
70+
patchset from an external MIDI player. In order to make use of it, you need
71+
the [loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html) driver
72+
and create a virtual MIDI cable.
73+
Than connect to the loopMIDI MIDI input in the "MIDI input" tab and press
74+
"Connect". On the other end of the "loopMIDI" cable, attach your MIDI player.
75+
I recommend
76+
[TMIDI: (Tom's MIDI Player)](https://www.grandgent.com/tom/projects/tmidi/)
77+
for that purpose.
78+
ESFM bank editor takes the MIDI data from the player, uses the current
79+
bank settings (which need to be applied) for MIDI playback and sends the
80+
signals to the Soundcard.
81+
82+
Patch table format
83+
==================
84+
The format of the patch table is pretty straightforward:
85+
Check out [ESFM docs](https://github.com/jwt27/esfm) for register definitions.
86+
87+
The patch file starts with 128 USHORTs that specify the offset of the 128
88+
programs defined by [General Midi](https://de.wikipedia.org/wiki/General_MIDI).
89+
90+
Then follows the table with 128 USHORTs that specify the offset of the
91+
General midi Percussion instruments also defined by general midi.
92+
93+
Afterwards the actual patch definitions start, consisting of:
94+
95+
Byte 0
96+
------
97+
```
98+
╔═══════╦═══════╤═══════╤═══════╤═══════╤═══════╤═══════╤═══════╤═══════╗
99+
║ R↓ B→ ║ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 ║
100+
╠═══════╬═══════╪═══════╪═══════╪═══════╪═══════╪═══════╧═══════╪═══════╣
101+
║ ║ FP4 │ FP3 │ FP2 │ FP1 │ ? │ Operation │ PAT16 ║
102+
╚═══════╩═══════╧═══════╧═══════╧═══════╧═══════╧═══════════════╧═══════╝
103+
```
104+
105+
PAT16: Use Patch16?
106+
Operation:
107+
0 - Only use voice 1
108+
1 - Also use second voice, if set
109+
2 - Also use second voice, if not set, steal voice
110+
FP1..FP4: Set fixed pitch for operator 1-4
111+
112+
Byte 3
113+
------
114+
Relative velocity for operator 1-4
115+
```
116+
╔═══════╦═══════╤═══════╤═══════╤═══════╤═══════╤═══════╤═══════╤═══════╗
117+
║ R↓ B→ ║ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 ║
118+
╠═══════╬═══════╧═══════╪═══════╧═══════╪═══════╧═══════╪═══════╧═══════╣
119+
║ ║ Rel.veloc. 4 │ Rel.veloc. 3 │ Rel.veloc. 2 │ Rel.veloc. 1 ║
120+
╚═══════╩═══════════════╧═══════════════╧═══════════════╧═══════════════╝
121+
```
122+
123+
Byte 4-11,12-19,20-27,28-35
124+
---------------------------
125+
Registers to set for each operator as documented under "Operator registers"
126+
in ESFM documentation.
127+
128+
If `Operation` in Byte 0 is > 0 then data for the second voice follows
129+
(Starting with byte 0 from above again).
130+
131+
Compiling
132+
=========
133+
The application has been developed and compile with Microsoft Visual
134+
Studio 6 and it contains a .dsp file for it, but you should also be able
135+
to compile it with newer versions of Visual Studio.
136+
137+
References
138+
==========
139+
[ES1969 Windows driver](https://github.com/leecher1337/es1969)
140+
141+
[ESFM documentation](https://github.com/jwt27/esfm)
142+
143+
Author
144+
======
145+
(c)oded by leecher@dose.0wnz.at
146+
For support use the issue tracker on the project's page:
147+
https://github.com/leecher1337/esfmbank

bin/x64/bnk_common.bin

8.09 KB
Binary file not shown.

bin/x64/inpoutx64.dll

40.5 KB
Binary file not shown.

bin/x86/bnk_common.bin

8.09 KB
Binary file not shown.

bin/x86/inpout32.dll

52.5 KB
Binary file not shown.

src/NATV.H

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
VOID FAR PASCAL fmwrite (WORD wAddress, BYTE bValue);
2+
void FAR PASCAL fmreset();
3+
4+
SHORT NATV_CalcBend(USHORT detune, USHORT iBend, USHORT iBendRange);
5+
BYTE NATV_CalcVolume(BYTE reg1, BYTE bVelocity, BYTE bChannel);
6+
void NATV_CalcNewVolume(BYTE bChannel);
7+
8+
void note_on(BYTE bChannel, BYTE bNote, BYTE bVelocity);
9+
void note_off(BYTE bChannel, BYTE bNote);
10+
11+
void voice_on(int voiceNr);
12+
void voice_off(int voiceNr);
13+
14+
void hold_controller(BYTE bChannel, BYTE bVelocity);
15+
void find_voice(BOOL patch1617_allowed_voice1, BOOL patch1617_allowed_voice2, BYTE bChannel, BYTE bNote);
16+
void setup_voice(int voicenr, int offset, int bChannel, int bNote, int bVelocity);
17+
int steal_voice(int patch1617_allowed);
18+
19+
VOID MidiAllNotesOff(void);
20+
WORD NEAR PASCAL MidiCalcFAndB (DWORD dwPitch, BYTE bBlock);
21+
VOID NEAR PASCAL MidiPitchBend (BYTE bChannel, USHORT iBend);
22+
VOID NEAR PASCAL MidiMessage (DWORD dwData);
23+

src/esdev.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/******************************************************************
2+
3+
esdev.c - Functions to find ES1969 sound card IO port address
4+
5+
ESFM Bank editor
6+
7+
Copyright (c) 2023, leecher@dose.0wnz.at All Rights Reserved.
8+
9+
*******************************************************************/
10+
#define WIN32_LEAN_AND_MEAN
11+
#include <windows.h>
12+
#include <setupapi.h>
13+
#include <cfgmgr32.h>
14+
#include "esdev.h"
15+
16+
#ifdef _MSC_VER
17+
#pragma comment(lib, "Setupapi.lib")
18+
#endif
19+
20+
// ks.h
21+
#define KSCATEGORY_RENDER {0x65E8773EL, 0x8F56, 0x11D0, 0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
22+
23+
24+
DWORD EnumESSDevices(HWND hWnd, void (*EnumCB)(ESS_DEVCFG *pCfg, void *pUser), void *pUser)
25+
{
26+
GUID render = KSCATEGORY_RENDER;
27+
HDEVINFO hDevInfo;
28+
SP_DEVINFO_DATA infoData={0};
29+
LOG_CONF hFirstLogConf;
30+
CONFIGRET rcCm;
31+
ESS_DEVCFG devCfg;
32+
DWORD i, n, ret = 0;
33+
34+
hDevInfo = SetupDiGetClassDevsW(&render, NULL, hWnd, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
35+
if (hDevInfo == INVALID_HANDLE_VALUE) return 0;
36+
37+
infoData.cbSize = sizeof(SP_DEVINFO_DATA);
38+
for (n = 0; SetupDiEnumDeviceInfo(hDevInfo, n, &infoData); ++n)
39+
{
40+
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &infoData, SPDRP_DEVICEDESC, NULL, devCfg.szDevName, sizeof(devCfg.szDevName), NULL))
41+
{
42+
rcCm = CM_Get_First_Log_Conf(&hFirstLogConf, infoData.DevInst, ALLOC_LOG_CONF);
43+
if (rcCm != CR_SUCCESS)
44+
rcCm = CM_Get_First_Log_Conf(&hFirstLogConf, infoData.DevInst, BOOT_LOG_CONF);
45+
if (rcCm == CR_SUCCESS)
46+
{
47+
/* Get the first resource descriptor handle. */
48+
LOG_CONF hCurLogConf = 0;
49+
rcCm = CM_Get_Next_Res_Des(&hCurLogConf, hFirstLogConf, ResType_IO, 0, 0);
50+
if (rcCm == CR_SUCCESS)
51+
{
52+
for (i=0;i<sizeof(devCfg.Ports)/sizeof(devCfg.Ports[0]);i++)
53+
{
54+
ULONG cbData;
55+
IO_DES *pIoDesc;
56+
RES_DES hFreeResDesc;
57+
58+
rcCm = CM_Get_Res_Des_Data_Size(&cbData, hCurLogConf, 0);
59+
if (rcCm != CR_SUCCESS)
60+
cbData = 0;
61+
cbData = max(cbData, sizeof(IO_DES));
62+
pIoDesc = (IO_DES *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbData);
63+
if (pIoDesc)
64+
{
65+
rcCm = CM_Get_Res_Des_Data(hCurLogConf, pIoDesc, cbData, 0L);
66+
if (rcCm == CR_SUCCESS)
67+
{
68+
/*
69+
printf("drvHostParallelGetWinHostIoPortsSub: Count=%d Type=%x Base=%I64x End=%I64x Flags=%x\n",
70+
pIoDesc->IOD_Count, pIoDesc->IOD_Type, pIoDesc->IOD_Alloc_Base,
71+
pIoDesc->IOD_Alloc_End, pIoDesc->IOD_DesFlags);*/
72+
devCfg.Ports[i] = (USHORT)pIoDesc->IOD_Alloc_Base;
73+
}
74+
HeapFree(GetProcessHeap(), 0, pIoDesc);
75+
}
76+
77+
/* Next */
78+
hFreeResDesc = hCurLogConf;
79+
rcCm = CM_Get_Next_Res_Des(&hCurLogConf, hCurLogConf, ResType_IO, 0, 0);
80+
CM_Free_Res_Des_Handle(hFreeResDesc);
81+
if (rcCm != CR_SUCCESS)
82+
break;
83+
}
84+
if (i == sizeof(devCfg.Ports)/sizeof(devCfg.Ports[0])-1)
85+
{
86+
EnumCB(&devCfg, pUser);
87+
ret++;
88+
}
89+
}
90+
CM_Free_Log_Conf_Handle(hFirstLogConf);
91+
}
92+
}
93+
}
94+
return ret;
95+
}
96+

src/esdev.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/******************************************************************
2+
3+
esdev.h - Functions to find ES1969 sound card IO port address
4+
5+
ESFM Bank editor
6+
7+
Copyright (c) 2023, leecher@dose.0wnz.at All Rights Reserved.
8+
9+
*******************************************************************/
10+
enum
11+
{
12+
ESSPortIO = 0,
13+
ESSPortSB = 1,
14+
ESSPortVc = 2,
15+
ESSPortMPU = 3,
16+
ESSPortGP = 4
17+
};
18+
19+
typedef struct
20+
{
21+
char szDevName[128];
22+
USHORT Ports[5];
23+
} ESS_DEVCFG;
24+
25+
DWORD EnumESSDevices(HWND hWnd, void (*EnumCB)(ESS_DEVCFG *pCfg, void *pUser), void *pUser);

0 commit comments

Comments
 (0)