2
0
Fork 0

Now supports setting frequency multipliers and attenuation levels.

This commit is contained in:
bruce 2013-09-11 01:30:05 +08:00
parent 7fe1775859
commit ad1167f562
3 changed files with 108 additions and 24 deletions

View file

@ -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)

View file

@ -1,12 +1,36 @@
#include "Hiopl.h"
#include <assert.h>
#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::Int16,
AudioData::NativeEndian,
AudioData::Interleaved,
AudioData::Const>,
AudioData::Pointer <AudioData::Float32,
AudioData::NativeEndian,
AudioData::NonInterleaved,
AudioData::NonConst>
>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<Waveform>(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;
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];
}

View file

@ -1,3 +1,5 @@
#include <map>
#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<int, int> _op1offset;
std::map<int, int> _op2offset;
};