Add some quick and dirty MIDI pitch wheel control.
This commit is contained in:
parent
de9f8732a7
commit
1ce43da7ac
4 changed files with 32 additions and 5 deletions
|
@ -120,6 +120,7 @@ JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor()
|
||||||
for (int i = 0; i < Hiopl::CHANNELS+1; i++) {
|
for (int i = 0; i < Hiopl::CHANNELS+1; i++) {
|
||||||
active_notes[i] = NO_NOTE;
|
active_notes[i] = NO_NOTE;
|
||||||
}
|
}
|
||||||
|
currentScaledBend = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JuceOplvstiAudioProcessor::initPrograms()
|
void JuceOplvstiAudioProcessor::initPrograms()
|
||||||
|
@ -366,6 +367,17 @@ void JuceOplvstiAudioProcessor::initPrograms()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JuceOplvstiAudioProcessor::applyPitchBend()
|
||||||
|
{ // apply the currently configured pitch bend to all active notes.
|
||||||
|
for (int i = 1; i <= Hiopl::CHANNELS; i++) {
|
||||||
|
if (NO_NOTE != active_notes[i]) {
|
||||||
|
float f = (float)MidiMessage::getMidiNoteInHertz(active_notes[i]);
|
||||||
|
f *= currentScaledBend;
|
||||||
|
Opl->SetFrequency(i, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JuceOplvstiAudioProcessor::~JuceOplvstiAudioProcessor()
|
JuceOplvstiAudioProcessor::~JuceOplvstiAudioProcessor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -658,6 +670,7 @@ void JuceOplvstiAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuf
|
||||||
}
|
}
|
||||||
Opl->KeyOn(ch, noteHz);
|
Opl->KeyOn(ch, noteHz);
|
||||||
active_notes[ch] = n;
|
active_notes[ch] = n;
|
||||||
|
applyPitchBend();
|
||||||
}
|
}
|
||||||
else if (midi_message.isNoteOff()) {
|
else if (midi_message.isNoteOff()) {
|
||||||
int n = midi_message.getNoteNumber();
|
int n = midi_message.getNoteNumber();
|
||||||
|
@ -668,6 +681,12 @@ void JuceOplvstiAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuf
|
||||||
Opl->KeyOff(ch);
|
Opl->KeyOff(ch);
|
||||||
active_notes[ch] = NO_NOTE;
|
active_notes[ch] = NO_NOTE;
|
||||||
}
|
}
|
||||||
|
else if (midi_message.isPitchWheel()) {
|
||||||
|
int bend = midi_message.getPitchWheelValue() - 0x2000; // range -8192 to 8191
|
||||||
|
// 1.05946309436 == (2^(1/1200))^100 == 1 semitone == 100 cents
|
||||||
|
currentScaledBend = 1.0f + bend * .05775f / 8192;
|
||||||
|
applyPitchBend();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Opl->Generate(buffer.getNumSamples(), buffer.getSampleData(0));
|
Opl->Generate(buffer.getNumSamples(), buffer.getSampleData(0));
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
JuceOplvstiAudioProcessor();
|
JuceOplvstiAudioProcessor();
|
||||||
void initPrograms();
|
void initPrograms();
|
||||||
|
void applyPitchBend();
|
||||||
~JuceOplvstiAudioProcessor();
|
~JuceOplvstiAudioProcessor();
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
@ -88,6 +89,7 @@ private:
|
||||||
bool velocity;
|
bool velocity;
|
||||||
static const int NO_NOTE=-1;
|
static const int NO_NOTE=-1;
|
||||||
int active_notes[Hiopl::CHANNELS+1]; // keyed by channel
|
int active_notes[Hiopl::CHANNELS+1]; // keyed by channel
|
||||||
|
float currentScaledBend;
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceOplvstiAudioProcessor)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceOplvstiAudioProcessor)
|
||||||
|
|
|
@ -160,11 +160,7 @@ void Hiopl::SetModulatorFeedback(int ch, int level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hiopl::KeyOn(int ch, float frqHz) {
|
void Hiopl::KeyOn(int ch, float frqHz) {
|
||||||
unsigned int fnum, block;
|
Hiopl::SetFrequency(ch, frqHz, true);
|
||||||
int offset = this->_GetOffset(ch);
|
|
||||||
_milliHertzToFnum((unsigned int)(frqHz * 1000.0), &fnum, &block);
|
|
||||||
_WriteReg(0xa0+offset, fnum % 0x100);
|
|
||||||
_WriteReg(0xb0+offset, 0x20|((block&0x7)<<2)|(0x3&(fnum/0x100)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hiopl::KeyOff(int ch) {
|
void Hiopl::KeyOff(int ch) {
|
||||||
|
@ -172,6 +168,15 @@ void Hiopl::KeyOff(int ch) {
|
||||||
_ClearRegBits(0xb0+offset, 0x20);
|
_ClearRegBits(0xb0+offset, 0x20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Hiopl::SetFrequency(int ch, float frqHz, bool keyOn) {
|
||||||
|
unsigned int fnum, block;
|
||||||
|
int offset = this->_GetOffset(ch);
|
||||||
|
_milliHertzToFnum((unsigned int)(frqHz * 1000.0), &fnum, &block);
|
||||||
|
_WriteReg(0xa0+offset, fnum % 0x100);
|
||||||
|
uint8 trig = (regCache[0xb0+offset] & 0x20) | (keyOn ? 0x20 : 0x00);
|
||||||
|
_WriteReg(0xb0+offset, trig|((block&0x7)<<2)|(0x3&(fnum/0x100)));
|
||||||
|
}
|
||||||
|
|
||||||
// from libgamemusic, opl-util.cpp
|
// from libgamemusic, opl-util.cpp
|
||||||
void Hiopl::_milliHertzToFnum(unsigned int milliHertz,
|
void Hiopl::_milliHertzToFnum(unsigned int milliHertz,
|
||||||
unsigned int *fnum, unsigned int *block, unsigned int conversionFactor)
|
unsigned int *fnum, unsigned int *block, unsigned int conversionFactor)
|
||||||
|
|
|
@ -46,6 +46,7 @@ class Hiopl {
|
||||||
void SetModulatorFeedback(int ch, int level);
|
void SetModulatorFeedback(int ch, int level);
|
||||||
void KeyOn(int ch, float frqHz);
|
void KeyOn(int ch, float frqHz);
|
||||||
void KeyOff(int ch);
|
void KeyOff(int ch);
|
||||||
|
void SetFrequency(int ch, float frqHz, bool keyOn=false);
|
||||||
void _WriteReg(Bit32u reg, Bit8u value, Bit8u mask=0x0);
|
void _WriteReg(Bit32u reg, Bit8u value, Bit8u mask=0x0);
|
||||||
void _ClearRegBits(Bit32u reg, Bit8u mask);
|
void _ClearRegBits(Bit32u reg, Bit8u mask);
|
||||||
~Hiopl();
|
~Hiopl();
|
||||||
|
|
Loading…
Reference in a new issue