From ad1167f562d210e6f1e1faa0b5bad2499c0e75de Mon Sep 17 00:00:00 2001 From: bruce Date: Wed, 11 Sep 2013 01:30:05 +0800 Subject: [PATCH] Now supports setting frequency multipliers and attenuation levels. --- Source/PluginProcessor.cpp | 43 ++++++++++++++++------ Source/hiopl.cpp | 75 +++++++++++++++++++++++++++++++++----- Source/hiopl.h | 14 +++++-- 3 files changed, 108 insertions(+), 24 deletions(-) diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 89fc782..304064f 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -1,13 +1,3 @@ -/* - ============================================================================== - - This file was auto-generated! - - It contains the basic startup code for a Juce application. - - ============================================================================== -*/ - #include "PluginProcessor.h" #include "PluginEditor.h" #include "EnumFloatParameter.h" @@ -23,6 +13,22 @@ JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor() params.push_back(new EnumFloatParameter("Modulator Wave", StringArray(waveforms, sizeof(waveforms)/sizeof(String))) ); + 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))) + ); + params.push_back(new EnumFloatParameter("Modulator Attenuation", + StringArray(levels, sizeof(levels)/sizeof(String))) + ); + const String frq_multipliers[] = { + "x0.5", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x10", "x12", "x12", "x15", "x15" + }; + params.push_back(new EnumFloatParameter("Carrier Frequency Multiplier", + StringArray(frq_multipliers, sizeof(frq_multipliers)/sizeof(String))) + ); + params.push_back(new EnumFloatParameter("Modulator Frequency Multiplier", + StringArray(frq_multipliers, sizeof(frq_multipliers)/sizeof(String))) + ); } JuceOplvstiAudioProcessor::~JuceOplvstiAudioProcessor() @@ -47,7 +53,22 @@ float JuceOplvstiAudioProcessor::getParameter (int index) void JuceOplvstiAudioProcessor::setParameter (int index, float newValue) { - params[index]->setParameter(newValue); + FloatParameter* p = params[index]; + p->setParameter(newValue); + String name = p->getName(); + if (name == "Carrier Wave") { + Opl->SetWaveform(1, 1, (Waveform)((EnumFloatParameter*)p)->getParameterIndex()); + } else if (name == "Modulator Wave") { + Opl->SetWaveform(1, 2, (Waveform)((EnumFloatParameter*)p)->getParameterIndex()); + } else if (name == "Modulator Attenuation") { + Opl->SetAttenuation(1, 1, 0x1<<((EnumFloatParameter*)p)->getParameterIndex()); + } else if (name == "Carrier Attenuation") { + Opl->SetAttenuation(1, 2, 0x1<<((EnumFloatParameter*)p)->getParameterIndex()); + } else if (name == "Carrier Frequency Multiplier") { + Opl->SetFrequencyMultiple(1, 1, (FreqMultiple)((EnumFloatParameter*)p)->getParameterIndex()); + } else if (name == "Modulator Frequency Multiplier") { + Opl->SetFrequencyMultiple(1, 2, (FreqMultiple)((EnumFloatParameter*)p)->getParameterIndex()); + } } const String JuceOplvstiAudioProcessor::getParameterName (int index) diff --git a/Source/hiopl.cpp b/Source/hiopl.cpp index f8bc30d..80de66e 100644 --- a/Source/hiopl.cpp +++ b/Source/hiopl.cpp @@ -1,12 +1,36 @@ #include "Hiopl.h" #include +#include "../JuceLibraryCode/JuceHeader.h" // A higher level wrapper around the DOSBox OPL emulator. Hiopl::Hiopl(int buflen) { adlib = new DBOPL::Handler(); Buf32 = new Bit32s[buflen]; + _op1offset[1] = 0x0; + _op1offset[2] = 0x1; + _op1offset[3] = 0x2; + _op1offset[4] = 0x8; + _op1offset[5] = 0x9; + _op1offset[6] = 0xa; + _op1offset[7] = 0x10; + _op1offset[8] = 0x11; + _op1offset[9] = 0x12; + + _op2offset[1] = 0x3; + _op2offset[2] = 0x4; + _op2offset[3] = 0x5; + _op2offset[4] = 0xb; + _op2offset[5] = 0xc; + _op2offset[6] = 0xd; + _op2offset[7] = 0x13; + _op2offset[8] = 0x14; + _op2offset[9] = 0x15; + + for (int i = 0; i < 256; i++) { + _WriteReg(i, 0); + } } void Hiopl::Generate(int length, short* buffer) { @@ -23,24 +47,40 @@ void Hiopl::Generate(int length, float* buffer) { for (int i = 0; i < length; i++) { buffer[i] = (float)(Buf32[i])/32768.0f; } + /* + AudioData::ConverterInstance< + AudioData::Pointer , + AudioData::Pointer + >converter; + converter.convertSamples(buffer, 0, Buf32, 0, length); + */ } 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(0x40,0x1a); // modulator attenuation + _WriteReg(0x43,0x09); // carrier attenuation _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 + //_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, Bit8u mask) { + if (mask > 0) { + value = (regCache[reg] & (~mask)) | (value & mask); + } adlib->WriteReg(reg, value); regCache[reg] = value; } @@ -50,8 +90,8 @@ void Hiopl::_ClearRegBits(Bit32u reg, Bit8u mask) { } void Hiopl::SetWaveform(int ch, int osc, Waveform wave) { - assert(_CheckParams(ch, osc)); - _WriteReg(0xe0+2*ch+osc, (Bit8u)wave); + int offset = this->_GetOffset(ch, osc); + _WriteReg(0xe0+offset, (Bit8u)wave); } Waveform Hiopl::GetWaveform(int ch, int osc) { @@ -59,6 +99,16 @@ Waveform Hiopl::GetWaveform(int ch, int osc) { return static_cast(regCache[0xe0+2*ch+osc]); } +void Hiopl::SetAttenuation(int ch, int osc, int level) { + int offset = this->_GetOffset(ch, osc); + _WriteReg(0x40+offset, (Bit8u)level, 0x3f); +} + +void Hiopl::SetFrequencyMultiple(int ch, int osc, FreqMultiple mult) { + int offset = this->_GetOffset(ch, osc); + _WriteReg(0x20+offset, (Bit8u)mult);//, 0xf); +} + void Hiopl::KeyOn(int ch, float frqHz) { unsigned int fnum, block; _milliHertzToFnum((unsigned int)(frqHz * 1000.0), &fnum, &block); @@ -115,5 +165,10 @@ Hiopl::~Hiopl() { }; bool Hiopl::_CheckParams(int ch, int osc) { - return ch >= 0 && ch < CHANNELS && osc >= 0 && osc < OSCILLATORS; -} \ No newline at end of file + return ch > 0 && ch <= CHANNELS && osc > 0 && osc <= OSCILLATORS; +} + +int Hiopl::_GetOffset(int ch, int osc) { + assert(_CheckParams(ch, osc)); + return (1 == osc) ? _op1offset[ch] : _op2offset[ch]; +} diff --git a/Source/hiopl.h b/Source/hiopl.h index 92e0f30..3d939df 100644 --- a/Source/hiopl.h +++ b/Source/hiopl.h @@ -1,3 +1,5 @@ +#include + #include "adlib.h" #include "dbopl.h" @@ -6,11 +8,12 @@ enum Waveform SIN = 0, HALF_SIN = 1, ABS_SIN = 2, QUART_SIN = 3 }; -enum Oscillator +enum FreqMultiple { - CAR = 0, MOD = 1 + xHALF=0, x1=1, x2=2, x3=3, x4=4, x5=5, x6=6, x7=7, x8=8, x9=9, x10=10, x12=12, x15=15 }; + const int CHANNELS = 9; const int OSCILLATORS = 2; @@ -22,9 +25,11 @@ class Hiopl { void SetSampleRate(int hz); 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 KeyOn(int ch, float frqHz); void KeyOff(int ch); - void _WriteReg(Bit32u reg, Bit8u value); + void _WriteReg(Bit32u reg, Bit8u value, Bit8u mask=0x0); void _ClearRegBits(Bit32u reg, Bit8u mask); ~Hiopl(); private: @@ -32,5 +37,8 @@ class Hiopl { Bit8u regCache[256]; Bit32s *Buf32; bool _CheckParams(int ch, int osc); + int _GetOffset(int ch, int osc); void _milliHertzToFnum(unsigned int milliHertz, unsigned int *fnum, unsigned int *block, unsigned int conversionFactor=49716); + std::map _op1offset; + std::map _op2offset; };