2
0
Fork 0

Basic note on/off triggering from MIDI working.

This commit is contained in:
bruce 2013-09-04 23:36:55 +08:00
parent f160931d6f
commit c428892c56
5 changed files with 111 additions and 32 deletions

View file

@ -11,6 +11,14 @@
#include "PluginProcessor.h" #include "PluginProcessor.h"
#include "PluginEditor.h" #include "PluginEditor.h"
enum
{
// Parameters Tags
pOsc1Wave = 0,
pOsc2Wave,
pNumParams
};
//============================================================================== //==============================================================================
JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor() JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor()
@ -30,7 +38,7 @@ const String JuceOplvstiAudioProcessor::getName() const
int JuceOplvstiAudioProcessor::getNumParameters() int JuceOplvstiAudioProcessor::getNumParameters()
{ {
return 0; return pNumParams;
} }
float JuceOplvstiAudioProcessor::getParameter (int index) float JuceOplvstiAudioProcessor::getParameter (int index)
@ -40,10 +48,22 @@ float JuceOplvstiAudioProcessor::getParameter (int index)
void JuceOplvstiAudioProcessor::setParameter (int index, float newValue) void JuceOplvstiAudioProcessor::setParameter (int index, float newValue)
{ {
switch (index) {
case pOsc1Wave:
break;
case pOsc2Wave:
break;
}
} }
const String JuceOplvstiAudioProcessor::getParameterName (int index) const String JuceOplvstiAudioProcessor::getParameterName (int index)
{ {
switch (index) {
case pOsc1Wave:
return "Carrier waveform";
case pOsc2Wave:
return "Modulator waveform";
}
return String::empty; return String::empty;
} }
@ -126,36 +146,9 @@ void JuceOplvstiAudioProcessor::changeProgramName (int index, const String& newN
//============================================================================== //==============================================================================
void JuceOplvstiAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) void JuceOplvstiAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{ {
Opl->SetSampleRate(sampleRate); Opl->SetSampleRate((int)sampleRate);
// Use this method as the place to do any pre-playback // Use this method as the place to do any pre-playback
// initialisation that you need.. // initialisation that you need..
Opl->_WriteReg(0x20,0x32);
Opl->_WriteReg(0x23,0x21);
Opl->_WriteReg(0x40,0x1a);
Opl->_WriteReg(0x43,0x09);
Opl->_WriteReg(0x60,0x84);
Opl->_WriteReg(0x63,0x84);
Opl->_WriteReg(0x80,0x29);
Opl->_WriteReg(0x83,0x44);
Opl->_WriteReg(0xe3,0x00);
Opl->_WriteReg(0xe0,0x02);
Opl->_WriteReg(0xc0,0x06);
Opl->_WriteReg(0xa0,0x8b);
Opl->_WriteReg(0xb0,0x26);
Opl->_WriteReg(0x21,0x32);
Opl->_WriteReg(0x24,0x21);
Opl->_WriteReg(0x41,0x1a);
Opl->_WriteReg(0x44,0x09);
Opl->_WriteReg(0x61,0x84);
Opl->_WriteReg(0x64,0x84);
Opl->_WriteReg(0x81,0x29);
Opl->_WriteReg(0x84,0x44);
Opl->_WriteReg(0xe4,0x00);
Opl->_WriteReg(0xe1,0x02);
Opl->_WriteReg(0xc1,0x06);
Opl->_WriteReg(0xa1,0x8b);
Opl->_WriteReg(0xb1,0x2a);
} }
void JuceOplvstiAudioProcessor::releaseResources() void JuceOplvstiAudioProcessor::releaseResources()
@ -167,6 +160,21 @@ void JuceOplvstiAudioProcessor::releaseResources()
void JuceOplvstiAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) void JuceOplvstiAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{ {
buffer.clear(0, 0, buffer.getNumSamples()); buffer.clear(0, 0, buffer.getNumSamples());
MidiBuffer::Iterator midi_buffer_iterator(midiMessages);
MidiMessage midi_message(0);
int sample_number;
while (midi_buffer_iterator.getNextEvent(midi_message,sample_number)) {
if (midi_message.isNoteOn()) {
//note on at sample_number samples after
//the begining of the current buffer
float noteHz = MidiMessage::getMidiNoteInHertz(midi_message.getNoteNumber());
Opl->KeyOn(0, noteHz);
}
else if (midi_message.isNoteOff()) {
Opl->KeyOff(0);
}
}
Opl->Generate(buffer.getNumSamples(), buffer.getSampleData(0)); Opl->Generate(buffer.getNumSamples(), buffer.getSampleData(0));
} }

View file

@ -41,6 +41,9 @@
#include "dosbox.h" #include "dosbox.h"
#include "dbopl.h" #include "dbopl.h"
#ifdef _MSC_VER
#pragma warning ( disable: 4244 4127 )
#endif
#ifndef PI #ifndef PI
#define PI 3.14159265358979323846 #define PI 3.14159265358979323846

View file

@ -27,6 +27,17 @@ void Hiopl::Generate(int length, float* buffer) {
void Hiopl::SetSampleRate(int hz) { void Hiopl::SetSampleRate(int hz) {
adlib->Init(hz); adlib->Init(hz);
_WriteReg(0x20,0x32); // modulator multiplier 2
_WriteReg(0x23,0x21); // carrier multiplier 1
_WriteReg(0x40,0x1a); // modulator level
_WriteReg(0x43,0x09); // carrier level
_WriteReg(0x60,0x84); // AD
_WriteReg(0x63,0x84); // AD
_WriteReg(0x80,0x29); // SR
_WriteReg(0x83,0x44); // SR
_WriteReg(0xe3,0x00); // wave select
_WriteReg(0xe0,0x02); // wave select
_WriteReg(0xc0,0x06); // carrier self-feedback level
} }
void Hiopl::_WriteReg(Bit32u reg, Bit8u value) { void Hiopl::_WriteReg(Bit32u reg, Bit8u value) {
@ -34,9 +45,13 @@ void Hiopl::_WriteReg(Bit32u reg, Bit8u value) {
regCache[reg] = value; regCache[reg] = value;
} }
void Hiopl::_ClearRegBits(Bit32u reg, Bit8u mask) {
_WriteReg(reg, regCache[reg] & ~mask);
}
void Hiopl::SetWaveform(int ch, int osc, Waveform wave) { void Hiopl::SetWaveform(int ch, int osc, Waveform wave) {
assert(_CheckParams(ch, osc)); assert(_CheckParams(ch, osc));
_WriteReg(0xe0+2*ch+osc, wave); _WriteReg(0xe0+2*ch+osc, (Bit8u)wave);
} }
Waveform Hiopl::GetWaveform(int ch, int osc) { Waveform Hiopl::GetWaveform(int ch, int osc) {
@ -44,8 +59,55 @@ Waveform Hiopl::GetWaveform(int ch, int osc) {
return static_cast<Waveform>(regCache[0xe0+2*ch+osc]); return static_cast<Waveform>(regCache[0xe0+2*ch+osc]);
} }
void Hiopl::KeyOn(int ch, int frq) { void Hiopl::KeyOn(int ch, float frqHz) {
unsigned int fnum, block;
_milliHertzToFnum((unsigned int)(frqHz * 1000.0), &fnum, &block);
_WriteReg(0xa0, fnum % 0x100);
_WriteReg(0xb0, 0x20|((block&0x7)<<2)|(0x3&(fnum/0x100)));
//_WriteReg(0xa0, 0x8b);
//_WriteReg(0xb0, 0x26);
}
void Hiopl::KeyOff(int ch) {
_ClearRegBits(0xb0, 0x20);
}
// from libgamemusic, opl-util.cpp
void Hiopl::_milliHertzToFnum(unsigned int milliHertz,
unsigned int *fnum, unsigned int *block, unsigned int conversionFactor)
{
// Special case to avoid divide by zero
if (milliHertz == 0) {
*block = 0; // actually any block will work
*fnum = 0;
return;
}
// Special case for frequencies too high to produce
if (milliHertz > 6208431) {
*block = 7;
*fnum = 1023;
return;
}
// This is a bit more efficient and doesn't need log2() from math.h
if (milliHertz > 3104215) *block = 7;
else if (milliHertz > 1552107) *block = 6;
else if (milliHertz > 776053) *block = 5;
else if (milliHertz > 388026) *block = 4;
else if (milliHertz > 194013) *block = 3;
else if (milliHertz > 97006) *block = 2;
else if (milliHertz > 48503) *block = 1;
else *block = 0;
// Slightly more efficient version
*fnum = ((unsigned long long)milliHertz << (20 - *block)) / (conversionFactor * 1000.0) + 0.5;
if ((*block == 7) && (*fnum > 1023)) {
// frequency out of range, clipping to maximum value.
*fnum = 1023;
}
assert(*block <= 7);
assert(*fnum < 1024);
return;
} }
Hiopl::~Hiopl() { Hiopl::~Hiopl() {

View file

@ -22,12 +22,15 @@ class Hiopl {
void SetSampleRate(int hz); void SetSampleRate(int hz);
void SetWaveform(int ch, int osc, Waveform wave); void SetWaveform(int ch, int osc, Waveform wave);
Waveform GetWaveform(int ch, int osc); Waveform GetWaveform(int ch, int osc);
void Hiopl::KeyOn(int ch, int frq); void KeyOn(int ch, float frqHz);
void KeyOff(int ch);
void _WriteReg(Bit32u reg, Bit8u value); void _WriteReg(Bit32u reg, Bit8u value);
void _ClearRegBits(Bit32u reg, Bit8u mask);
~Hiopl(); ~Hiopl();
private: private:
Adlib::Handler *adlib; Adlib::Handler *adlib;
Bit8u regCache[256]; Bit8u regCache[256];
Bit32s *Buf32; Bit32s *Buf32;
bool _CheckParams(int ch, int osc); bool _CheckParams(int ch, int osc);
void _milliHertzToFnum(unsigned int milliHertz, unsigned int *fnum, unsigned int *block, unsigned int conversionFactor=49716);
}; };

View file

@ -24,6 +24,9 @@
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning ( disable : 4786 ) #pragma warning ( disable : 4786 )
#pragma warning ( disable : 4290 ) #pragma warning ( disable : 4290 )
#pragma warning ( disable : 4512 ) // assignment operator could not be generated
#pragma warning ( disable : 4100 ) // unreferenced parameter
#endif #endif