2
0
Fork 0

More work in progress on DRO output. Updated readme.

This commit is contained in:
bsutherland 2015-02-22 11:58:06 +09:00
parent 2482447f98
commit d6f3f7eef9
3 changed files with 59 additions and 31 deletions

View file

@ -75,7 +75,7 @@
<JUCEOPTIONS JUCE_QUICKTIME="disabled"/> <JUCEOPTIONS JUCE_QUICKTIME="disabled"/>
<EXPORTFORMATS> <EXPORTFORMATS>
<VS2013 targetFolder="Builds/VisualStudio2013" vstFolder="C:\code\audio\vstsdk2.4" <VS2013 targetFolder="Builds/VisualStudio2013" vstFolder="C:\code\audio\vstsdk2.4"
externalLibraries="" toolset="v120_xp"> externalLibraries="" toolset="">
<CONFIGURATIONS> <CONFIGURATIONS>
<CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit" <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit"
isDebug="1" optimisation="1" targetName="JuceOPLVSTi"/> isDebug="1" optimisation="1" targetName="JuceOPLVSTi"/>

View file

@ -66,7 +66,7 @@ static Bit32u CHANNEL_OFFSETS[15]= {
// bass drum uses two operators. // bass drum uses two operators.
// others use either modulator or carrier. // others use either modulator or carrier.
static Bit32u PERCUSSION_OPERATORS[5][2] = { static Bit32u PERCUSSION_OFFSETS[5][2] = {
{ 0x13, 0x10 }, // bd { 0x13, 0x10 }, // bd
{ 0x00, 0x14 }, // sd { 0x00, 0x14 }, // sd
{ 0x12, 0x00 }, // tt { 0x12, 0x00 }, // tt
@ -114,7 +114,7 @@ void DROMultiplexer::_CopyOplPercussionSettings(Hiopl* opl, int pIdx) {
Bit32u inAddr; Bit32u inAddr;
Bit32u outAddr; Bit32u outAddr;
Bit32u* outOff = PERCUSSION_OPERATORS[pIdx]; Bit32u* outOff = PERCUSSION_OFFSETS[pIdx];
// waveform select // waveform select
int base = 0xe0; int base = 0xe0;
if (outOff[0]) { if (outOff[0]) {
@ -185,6 +185,7 @@ void DROMultiplexer::TwoOpMelodicNoteOn(Hiopl* opl, int inCh) {
// find a free channel and mark it as used // find a free channel and mark it as used
char addr[16]; char addr[16];
int outCh = _FindFreeChannel(opl, inCh); int outCh = _FindFreeChannel(opl, inCh);
if (outCh >= 0) {
_DebugOut(" <- "); _DebugOut(" <- ");
_DebugOut(itoa((int)opl, addr, 16)); _DebugOut(itoa((int)opl, addr, 16));
_DebugOut(" "); _DebugOut(" ");
@ -205,8 +206,10 @@ void DROMultiplexer::TwoOpMelodicNoteOn(Hiopl* opl, int inCh) {
inAddr = 0xb0 + chInOff; inAddr = 0xb0 + chInOff;
outAddr = 0xb0 + CHANNEL_OFFSETS[outCh]; outAddr = 0xb0 + CHANNEL_OFFSETS[outCh];
_CaptureRegWrite(outAddr, opl->_ReadReg(inAddr)); _CaptureRegWrite(outAddr, opl->_ReadReg(inAddr));
_DebugOut(" ");
_DebugOut(itoa(opl->_ReadReg(inAddr), addr, 16)); _DebugOut(itoa(opl->_ReadReg(inAddr), addr, 16));
_DebugOut("\n"); _DebugOut("\n");
}
} }
void DROMultiplexer::TwoOpMelodicNoteOff(Hiopl* opl, int ch) { void DROMultiplexer::TwoOpMelodicNoteOff(Hiopl* opl, int ch) {
@ -248,8 +251,21 @@ int DROMultiplexer::_FindFreeChannel(Hiopl* opl, int inCh) {
} }
i += 1; i += 1;
} }
// fall back to a released channel for same opl instance
i = 0;
while (i < MELODIC_CHANNELS) {
if (opl == channels[i].opl && 'R' == opl->GetState(channels[i].ch)[0]) {
channels[i].opl = opl;
channels[i].ch = inCh;
channelMap[channels[i]] = i;
char n[8];
_DebugOut(itoa(i, n, 16));
return i;
}
i += 1;
}
_DebugOut("Could not find free channel!"); _DebugOut("Could not find free channel!");
return 0; return -1;
} }
void DROMultiplexer::PercussionChange(Hiopl* opl, int pIdx) { void DROMultiplexer::PercussionChange(Hiopl* opl, int pIdx) {
@ -260,6 +276,17 @@ void DROMultiplexer::PercussionChange(Hiopl* opl, int pIdx) {
if (0 == (val & maskOut)) { // note-off if (0 == (val & maskOut)) { // note-off
_CaptureRegWriteWithDelay(0xbd, 0xBD & (0xe0 | ~maskOut)); _CaptureRegWriteWithDelay(0xbd, 0xBD & (0xe0 | ~maskOut));
} else { // note-on } else { // note-on
char addr[16];
// note frequency
for (int i = 0; i < i; i++) {
Bit32u outOff = PERCUSSION_OFFSETS[pIdx][i];
if (0x0 != outOff) {
int inAddr = 0xa0 + opl->_GetOffset(1); // any channel is fine, they should have all been written
int outAddr = 0xa0 + outOff;
_CaptureRegWrite(outAddr, opl->_ReadReg(inAddr));
_DebugOut(itoa(opl->_ReadReg(inAddr), addr, 16));
}
}
_CaptureRegWriteWithDelay(0xbd, OxBD | maskOut); _CaptureRegWriteWithDelay(0xbd, OxBD | maskOut);
} }
} }

View file

@ -2,11 +2,11 @@
This VST instrument provides an emulated OPL sound chip. It provides all features of the OPL2, and some features of the OPL3. This VST instrument provides an emulated OPL sound chip. It provides all features of the OPL2, and some features of the OPL3.
See here for Windows binaries, screenshots etc: http://bsutherland.github.io/JuceOPLVSTi/ See here for binaries, screenshots etc: http://bsutherland.github.io/JuceOPLVSTi/
## What's an OPL? ## ## What's an OPL? ##
The OPL is a digital sound synthesis chip developed by Yamaha in the mid 1980s. Among other products, it was used in sound cards for PC, including the Adlib card. The OPL is a digital sound synthesis chip developed by Yamaha in the mid 1980s. Among other products, it was used in sound cards for PC, including the Ad Lib card and early Sound Blaster series.
At a technical level: the emulator has channels comprised of 2 oscillators each. Each pair of oscillators is usually combined via phase modulation (basically frequency modulation). Each oscillator can produce one of eight waveforms (sine, half sine, absolute sine, quarter sine, alternating sine, camel sine, square, logarithmic sawtooth), and has an ADSR envelope controlling its amplitude. The unusual waveforms give it a characteristic sound. At a technical level: the emulator has channels comprised of 2 oscillators each. Each pair of oscillators is usually combined via phase modulation (basically frequency modulation). Each oscillator can produce one of eight waveforms (sine, half sine, absolute sine, quarter sine, alternating sine, camel sine, square, logarithmic sawtooth), and has an ADSR envelope controlling its amplitude. The unusual waveforms give it a characteristic sound.
@ -20,6 +20,7 @@ Each instance of the plugin emulates an entire OPL chip, but polyphony is implem
Some documentation which may be useful: Some documentation which may be useful:
- [Introduction to FM Synthesis](https://www.youtube.com/watch?v=ziFv00PegJg) (not specific to the OPL, but a great primer)
- [OPL2 on Wikipedia](http://en.wikipedia.org/wiki/Yamaha_YM3812) - [OPL2 on Wikipedia](http://en.wikipedia.org/wiki/Yamaha_YM3812)
- [Original Yamaha datasheet](http://www.alldatasheet.com/datasheet-pdf/pdf/84281/YAMAHA/YM3812.html) - [Original Yamaha datasheet](http://www.alldatasheet.com/datasheet-pdf/pdf/84281/YAMAHA/YM3812.html)
- [AdLib programming guide](http://www.shipbrook.net/jeff/sb.html) Dates back to 1991! - [AdLib programming guide](http://www.shipbrook.net/jeff/sb.html) Dates back to 1991!
@ -35,9 +36,9 @@ Percussion mode is now supported! This mode is not very well documented, even in
- Cymbal: Uses carrier settings. Half-sine recommended. - Cymbal: Uses carrier settings. Half-sine recommended.
- Hi-hat: Uses modulator settings. Half-sine recommended. - Hi-hat: Uses modulator settings. Half-sine recommended.
Also, a link to some much more detailed notes on percussion mode based on experimentation with real hardware! Also, some [much more detailed notes](http://midibox.org/forums/topic/18625-opl3-percussion-mode-map/) on percussion mode based on experimentation with real hardware!
http://midibox.org/forums/topic/18625-opl3-percussion-mode-map/
## How did you create the instrument programs? ## ## How did you create the instrument programs? ##
@ -55,7 +56,7 @@ The code I wrote is essentially a device driver for the emulated OPL, implementi
## Building ## ## Building ##
So far I've only built under Windows. Thanks to Juce, it should be possible to build under OSX and Linux too. **Volunteers to build OSX/Linux releases would be appreciated** (XCode required for OSX). So far I've only built under Windows. Thanks to the hard work of others, OSX and Linux builds should be coming very soon!
### Windows Build Instructions ### ### Windows Build Instructions ###