Basic note on/off triggering from MIDI working.
This commit is contained in:
parent
f160931d6f
commit
c428892c56
5 changed files with 111 additions and 32 deletions
|
@ -11,6 +11,14 @@
|
|||
#include "PluginProcessor.h"
|
||||
#include "PluginEditor.h"
|
||||
|
||||
enum
|
||||
{
|
||||
// Parameters Tags
|
||||
pOsc1Wave = 0,
|
||||
pOsc2Wave,
|
||||
|
||||
pNumParams
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor()
|
||||
|
@ -30,7 +38,7 @@ const String JuceOplvstiAudioProcessor::getName() const
|
|||
|
||||
int JuceOplvstiAudioProcessor::getNumParameters()
|
||||
{
|
||||
return 0;
|
||||
return pNumParams;
|
||||
}
|
||||
|
||||
float JuceOplvstiAudioProcessor::getParameter (int index)
|
||||
|
@ -40,10 +48,22 @@ float JuceOplvstiAudioProcessor::getParameter (int index)
|
|||
|
||||
void JuceOplvstiAudioProcessor::setParameter (int index, float newValue)
|
||||
{
|
||||
switch (index) {
|
||||
case pOsc1Wave:
|
||||
break;
|
||||
case pOsc2Wave:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const String JuceOplvstiAudioProcessor::getParameterName (int index)
|
||||
{
|
||||
switch (index) {
|
||||
case pOsc1Wave:
|
||||
return "Carrier waveform";
|
||||
case pOsc2Wave:
|
||||
return "Modulator waveform";
|
||||
}
|
||||
return String::empty;
|
||||
}
|
||||
|
||||
|
@ -126,36 +146,9 @@ void JuceOplvstiAudioProcessor::changeProgramName (int index, const String& newN
|
|||
//==============================================================================
|
||||
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
|
||||
// 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()
|
||||
|
@ -167,6 +160,21 @@ void JuceOplvstiAudioProcessor::releaseResources()
|
|||
void JuceOplvstiAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,9 @@
|
|||
#include "dosbox.h"
|
||||
#include "dbopl.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning ( disable: 4244 4127 )
|
||||
#endif
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846
|
||||
|
|
|
@ -27,6 +27,17 @@ void Hiopl::Generate(int length, float* buffer) {
|
|||
|
||||
void Hiopl::SetSampleRate(int 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) {
|
||||
|
@ -34,9 +45,13 @@ void Hiopl::_WriteReg(Bit32u reg, Bit8u 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) {
|
||||
assert(_CheckParams(ch, osc));
|
||||
_WriteReg(0xe0+2*ch+osc, wave);
|
||||
_WriteReg(0xe0+2*ch+osc, (Bit8u)wave);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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() {
|
||||
|
|
|
@ -22,12 +22,15 @@ class Hiopl {
|
|||
void SetSampleRate(int hz);
|
||||
void SetWaveform(int ch, int osc, Waveform wave);
|
||||
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 _ClearRegBits(Bit32u reg, Bit8u mask);
|
||||
~Hiopl();
|
||||
private:
|
||||
Adlib::Handler *adlib;
|
||||
Bit8u regCache[256];
|
||||
Bit32s *Buf32;
|
||||
bool _CheckParams(int ch, int osc);
|
||||
void _milliHertzToFnum(unsigned int milliHertz, unsigned int *fnum, unsigned int *block, unsigned int conversionFactor=49716);
|
||||
};
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#ifdef _MSC_VER
|
||||
#pragma warning ( disable : 4786 )
|
||||
#pragma warning ( disable : 4290 )
|
||||
#pragma warning ( disable : 4512 ) // assignment operator could not be generated
|
||||
#pragma warning ( disable : 4100 ) // unreferenced parameter
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue