Finally get waveform control working, add modulator feedback, fix assorted bugs.
This commit is contained in:
parent
2dc2879064
commit
b3eb3832ad
3 changed files with 43 additions and 17 deletions
|
@ -8,6 +8,7 @@ JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor()
|
|||
{
|
||||
Opl = new Hiopl(44100); // 1 second at 44100
|
||||
Opl->SetSampleRate(44100);
|
||||
Opl->EnableWaveformControl();
|
||||
Opl->EnableSustain(1, 1);
|
||||
Opl->EnableSustain(1, 2);
|
||||
|
||||
|
@ -18,7 +19,7 @@ JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor()
|
|||
params.push_back(new EnumFloatParameter("Modulator Wave",
|
||||
StringArray(waveforms, sizeof(waveforms)/sizeof(String)))
|
||||
); setParameter(params.size()-1,0.0f);
|
||||
|
||||
/*
|
||||
const String levels[] = {"-0.75 dB", "-1.5 dB", "-3 dB", "-6 dB", "-12 dB", "-24 dB"};
|
||||
params.push_back(new EnumFloatParameter("Carrier Attenuation",
|
||||
StringArray(levels, sizeof(levels)/sizeof(String)))
|
||||
|
@ -26,7 +27,12 @@ JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor()
|
|||
params.push_back(new EnumFloatParameter("Modulator Attenuation",
|
||||
StringArray(levels, sizeof(levels)/sizeof(String)))
|
||||
); setParameter(params.size()-1,0.75f);
|
||||
|
||||
*/
|
||||
params.push_back(new IntFloatParameter("Carrier Attenuation", 0, 63));
|
||||
setParameter(params.size()-1,0.0f);
|
||||
params.push_back(new IntFloatParameter("Modulator Attenuation", 0, 63));
|
||||
setParameter(params.size()-1,0.75f);
|
||||
|
||||
const String frq_multipliers[] = {
|
||||
"x0.5", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x10", "x12", "x12", "x15", "x15"
|
||||
};
|
||||
|
@ -36,6 +42,9 @@ JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor()
|
|||
params.push_back(new EnumFloatParameter("Modulator Frequency Multiplier",
|
||||
StringArray(frq_multipliers, sizeof(frq_multipliers)/sizeof(String)))
|
||||
); setParameter(params.size()-1, 0.15f);
|
||||
|
||||
params.push_back(new IntFloatParameter("Modulator Feedback", 0, 7));
|
||||
setParameter(params.size()-1,0.0f);
|
||||
|
||||
params.push_back(new IntFloatParameter("Carrier Attack", 0, 15));
|
||||
setParameter(params.size()-1,0.5f);
|
||||
|
@ -53,6 +62,7 @@ JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor()
|
|||
setParameter(params.size()-1,0.25f);
|
||||
params.push_back(new IntFloatParameter("Modulator Release", 0, 15));
|
||||
setParameter(params.size()-1,0.25f);
|
||||
|
||||
}
|
||||
|
||||
JuceOplvstiAudioProcessor::~JuceOplvstiAudioProcessor()
|
||||
|
@ -87,7 +97,8 @@ void JuceOplvstiAudioProcessor::setParameter (int index, float newValue)
|
|||
if (name.endsWith("Wave")) {
|
||||
Opl->SetWaveform(1, osc, (Waveform)((EnumFloatParameter*)p)->getParameterIndex());
|
||||
} else if (name.endsWith("Attenuation")) {
|
||||
Opl->SetAttenuation(1, osc, 0x1<<((EnumFloatParameter*)p)->getParameterIndex());
|
||||
//Opl->SetAttenuation(1, osc, 0x1<<((EnumFloatParameter*)p)->getParameterIndex());
|
||||
Opl->SetAttenuation(1, osc, ((IntFloatParameter*)p)->getParameterValue());
|
||||
} else if (name.endsWith("Frequency Multiplier")) {
|
||||
Opl->SetFrequencyMultiple(1, osc, (FreqMultiple)((EnumFloatParameter*)p)->getParameterIndex());
|
||||
} else if (name.endsWith("Attack")) {
|
||||
|
@ -98,6 +109,8 @@ void JuceOplvstiAudioProcessor::setParameter (int index, float newValue)
|
|||
Opl->SetEnvelopeSustain(1, osc, ((IntFloatParameter*)p)->getParameterValue());
|
||||
} else if (name.endsWith("Release")) {
|
||||
Opl->SetEnvelopeRelease(1, osc, ((IntFloatParameter*)p)->getParameterValue());
|
||||
} else if (name.endsWith("Feedback")) {
|
||||
Opl->SetModulatorFeedback(1, ((IntFloatParameter*)p)->getParameterValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -209,10 +222,10 @@ void JuceOplvstiAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuf
|
|||
//note on at sample_number samples after
|
||||
//the beginning of the current buffer
|
||||
float noteHz = (float)MidiMessage::getMidiNoteInHertz(midi_message.getNoteNumber());
|
||||
Opl->KeyOn(0, noteHz);
|
||||
Opl->KeyOn(1, noteHz);
|
||||
}
|
||||
else if (midi_message.isNoteOff()) {
|
||||
Opl->KeyOff(0);
|
||||
Opl->KeyOff(1);
|
||||
}
|
||||
}
|
||||
Opl->Generate(buffer.getNumSamples(), buffer.getSampleData(0));
|
||||
|
|
|
@ -78,14 +78,13 @@ void Hiopl::_ClearRegBits(Bit32u reg, Bit8u mask) {
|
|||
_WriteReg(reg, regCache[reg] & ~mask);
|
||||
}
|
||||
|
||||
void Hiopl::SetWaveform(int ch, int osc, Waveform wave) {
|
||||
int offset = this->_GetOffset(ch, osc);
|
||||
_WriteReg(0xe0+offset, (Bit8u)wave);
|
||||
void Hiopl::EnableWaveformControl() {
|
||||
_WriteReg(0x01, 0x20);
|
||||
}
|
||||
|
||||
Waveform Hiopl::GetWaveform(int ch, int osc) {
|
||||
assert(_CheckParams(ch, osc));
|
||||
return static_cast<Waveform>(regCache[0xe0+2*ch+osc]);
|
||||
void Hiopl::SetWaveform(int ch, int osc, Waveform wave) {
|
||||
int offset = this->_GetOffset(ch, osc);
|
||||
_WriteReg(0xe0+offset, (Bit8u)wave, 0x3);
|
||||
}
|
||||
|
||||
void Hiopl::SetAttenuation(int ch, int osc, int level) {
|
||||
|
@ -95,7 +94,7 @@ void Hiopl::SetAttenuation(int ch, int osc, int level) {
|
|||
|
||||
void Hiopl::SetFrequencyMultiple(int ch, int osc, FreqMultiple mult) {
|
||||
int offset = this->_GetOffset(ch, osc);
|
||||
_WriteReg(0x20+offset, (Bit8u)mult);//, 0xf);
|
||||
_WriteReg(0x20+offset, (Bit8u)mult, 0xf);
|
||||
}
|
||||
|
||||
void Hiopl::SetEnvelopeAttack(int ch, int osc, int t) {
|
||||
|
@ -123,15 +122,22 @@ void Hiopl::EnableSustain(int ch, int osc) {
|
|||
_WriteReg(0x20+offset, (Bit8u)0x20, 0x20);
|
||||
}
|
||||
|
||||
void Hiopl::SetModulatorFeedback(int ch, int level) {
|
||||
int offset = this->_GetOffset(ch);
|
||||
_WriteReg(0xc0+offset, (Bit8u)level, 0x0e);
|
||||
}
|
||||
|
||||
void Hiopl::KeyOn(int ch, float frqHz) {
|
||||
unsigned int fnum, block;
|
||||
int offset = this->_GetOffset(ch);
|
||||
_milliHertzToFnum((unsigned int)(frqHz * 1000.0), &fnum, &block);
|
||||
_WriteReg(0xa0, fnum % 0x100);
|
||||
_WriteReg(0xb0, 0x20|((block&0x7)<<2)|(0x3&(fnum/0x100)));
|
||||
_WriteReg(0xa0+offset, fnum % 0x100);
|
||||
_WriteReg(0xb0+offset, 0x20|((block&0x7)<<2)|(0x3&(fnum/0x100)));
|
||||
}
|
||||
|
||||
void Hiopl::KeyOff(int ch) {
|
||||
_ClearRegBits(0xb0, 0x20);
|
||||
int offset = this->_GetOffset(ch);
|
||||
_ClearRegBits(0xb0+offset, 0x20);
|
||||
}
|
||||
|
||||
// from libgamemusic, opl-util.cpp
|
||||
|
@ -176,7 +182,7 @@ Hiopl::~Hiopl() {
|
|||
delete Buf32;
|
||||
};
|
||||
|
||||
bool Hiopl::_CheckParams(int ch, int osc) {
|
||||
bool Hiopl::_CheckParams(int ch, int osc=OSCILLATORS) {
|
||||
return ch > 0 && ch <= CHANNELS && osc > 0 && osc <= OSCILLATORS;
|
||||
}
|
||||
|
||||
|
@ -184,3 +190,8 @@ int Hiopl::_GetOffset(int ch, int osc) {
|
|||
assert(_CheckParams(ch, osc));
|
||||
return (1 == osc) ? _op1offset[ch] : _op2offset[ch];
|
||||
}
|
||||
|
||||
int Hiopl::_GetOffset(int ch) {
|
||||
assert(_CheckParams(ch));
|
||||
return ch - 1;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ class Hiopl {
|
|||
void Generate(int length, short* buffer);
|
||||
void Generate(int length, float* buffer);
|
||||
void SetSampleRate(int hz);
|
||||
void EnableWaveformControl();
|
||||
void SetWaveform(int ch, int osc, Waveform wave);
|
||||
Waveform GetWaveform(int ch, int osc);
|
||||
void SetAttenuation(int ch, int osc, int level);
|
||||
void SetFrequencyMultiple(int ch, int osc, FreqMultiple mult);
|
||||
void SetEnvelopeAttack(int ch, int osc, int t);
|
||||
|
@ -32,6 +32,7 @@ class Hiopl {
|
|||
void SetEnvelopeSustain(int ch, int osc, int level);
|
||||
void SetEnvelopeRelease(int ch, int osc, int t);
|
||||
void EnableSustain(int ch, int osc);
|
||||
void SetModulatorFeedback(int ch, int level);
|
||||
void KeyOn(int ch, float frqHz);
|
||||
void KeyOff(int ch);
|
||||
void _WriteReg(Bit32u reg, Bit8u value, Bit8u mask=0x0);
|
||||
|
@ -43,6 +44,7 @@ class Hiopl {
|
|||
Bit32s *Buf32;
|
||||
bool _CheckParams(int ch, int osc);
|
||||
int _GetOffset(int ch, int osc);
|
||||
int _GetOffset(int ch);
|
||||
void _milliHertzToFnum(unsigned int milliHertz, unsigned int *fnum, unsigned int *block, unsigned int conversionFactor=49716);
|
||||
std::map<int, int> _op1offset;
|
||||
std::map<int, int> _op2offset;
|
||||
|
|
Loading…
Reference in a new issue