2
0
Fork 0

Progress on channel assignment in DRO output.

This commit is contained in:
Bruce Sutherland 2015-01-09 14:20:19 +09:00
parent a16025e39c
commit 454fbdfde5
6 changed files with 105 additions and 51 deletions

View file

@ -1,11 +1,14 @@
#include "DROMultiplexer.h"
#include "JuceHeader.h"
#include <Windows.h>
// Used by the first recording instance to claim master status
// TODO: develop the logic for recording data from other (non-master) plugins
DROMultiplexer* DROMultiplexer::master = NULL;
// Mutex between plugin instances
CriticalSection DROMultiplexer::lock;
static Bit8u dro_header[] = {
'D', 'B', 'R', 'A', /* 0x00, Bit32u ID */
'W', 'O', 'P', 'L', /* 0x04, Bit32u ID */
@ -68,32 +71,51 @@ INLINE void host_writed(Bit8u *off, Bit32u val) {
off[3] = (Bit8u)(val >> 24);
};
HANDLE conout;
DROMultiplexer::DROMultiplexer()
{
for (int i = 0; i < MELODIC_CHANNELS; ++i) {
for (int i = 0; i < MELODIC_CHANNELS; i++) {
channels[i].opl = NULL;
channels[i].ch = -1;
}
#ifdef _DEBUG
AllocConsole();
conout = GetStdHandle(STD_OUTPUT_HANDLE);
#endif
}
DROMultiplexer::~DROMultiplexer()
{
#ifdef _DEBUG
FreeConsole();
#endif
}
DROMultiplexer* DROMultiplexer::GetMaster() {
return DROMultiplexer::master;
}
void DROMultiplexer::TwoOpMelodicNoteOn(Hiopl* opl, int ch) {
void DROMultiplexer::TwoOpMelodicNoteOn(Hiopl* opl, int inCh) {
const ScopedLock sl(lock);
for (int i = 1; i <= Hiopl::CHANNELS; i++) {
char s[2];
s[0] = opl->GetState(i);
s[1] = '\0';
_DebugOut(s);
}
_DebugOut(" ");
// find a free channel and mark it as used
int outCh = _FindFreeChannel();
channels[outCh].opl = opl;
channels[outCh].ch = ch;
channelMap[channels[outCh]] = outCh;
char addr[16];
int outCh = _FindFreeChannel(opl, inCh);
_DebugOut(" <- ");
_DebugOut(itoa((int)opl, addr, 16));
_DebugOut("\n");
// read all instrument settings and write them all to the file
int op1Off = opl->_GetOffset(ch, 1);
int op2Off = opl->_GetOffset(ch, 2);
int op1Off = opl->_GetOffset(inCh, 1);
int op2Off = opl->_GetOffset(inCh, 2);
Bit32u inAddr;
Bit32u outAddr;
// waveform select
@ -115,7 +137,7 @@ void DROMultiplexer::TwoOpMelodicNoteOn(Hiopl* opl, int ch) {
}
// channel wide settings
int chInOff = opl->_GetOffset(ch);
int chInOff = opl->_GetOffset(inCh);
inAddr = 0xc0 + chInOff;
outAddr = 0xc0 + CHANNEL_OFFSETS[outCh];
_CaptureRegWrite(outAddr, 0x30 | opl->_ReadReg(inAddr));
@ -127,10 +149,11 @@ void DROMultiplexer::TwoOpMelodicNoteOn(Hiopl* opl, int ch) {
inAddr = 0xb0 + chInOff;
outAddr = 0xb0 + CHANNEL_OFFSETS[outCh];
_CaptureRegWrite(outAddr, opl->_ReadReg(inAddr));
}
void DROMultiplexer::TwoOpMelodicNoteOff(Hiopl* opl, int ch) {
const ScopedLock sl(lock);
int chOff = opl->_GetOffset(ch);
OplCh_t key;
key.opl = opl;
@ -143,20 +166,33 @@ void DROMultiplexer::TwoOpMelodicNoteOff(Hiopl* opl, int ch) {
_CaptureRegWriteWithDelay(outAddr, opl->_ReadReg(inAddr));
}
int DROMultiplexer::_FindFreeChannel() {
void DROMultiplexer::_DebugOut(char* str) {
#ifdef _DEBUG
DWORD count;
count = strlen(str);
WriteConsole(conout, str, count, &count, NULL);
#endif
}
int DROMultiplexer::_FindFreeChannel(Hiopl* opl, int inCh) {
int i = 0;
while (i < MELODIC_CHANNELS) {
Hiopl* opl = channels[i].opl;
if (NULL == opl || !opl->IsActive(channels[i].ch)) {
if (NULL == channels[i].opl || !channels[i].opl->IsActive(channels[i].ch)) {
channels[i].opl = opl;
channels[i].ch = inCh;
channelMap[channels[i]] = i;
char n[8];
_DebugOut(itoa(i, n, 10));
return i;
}
i += 1;
}
// TODO: handle the fact that there are no free channels :(
_DebugOut("Could not find free channel!");
return 0;
}
void DROMultiplexer::PercussionHit(Hiopl* opl) {
const ScopedLock sl(lock);
}
@ -165,38 +201,42 @@ void DROMultiplexer::InitCaptureVariables() {
captureLengthBytes = 0;
lastWrite = -1;
captureStart = -1;
// channelMap.clear();
}
void DROMultiplexer::StartCapture(const char* filepath, Hiopl *opl) {
DROMultiplexer::master = this;
lastWrite = -1;
captureLengthBytes = 0;
captureStart = Time::currentTimeMillis();
bool DROMultiplexer::StartCapture(const char* filepath, Hiopl *opl) {
captureHandle = fopen(filepath, "wb");
fwrite(dro_header, 1, sizeof(dro_header), captureHandle);
for (int i = 0; i <= 0xff; i++) {
_CaptureRegWrite(i, 0);
}
_CaptureOpl3Enable();
for (Bit8u i = 0x20; i <= 0x35; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i));
}
for (Bit8u i = 0x40; i <= 0x55; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i));
}
for (Bit8u i = 0x60; i <= 0x75; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i));
}
for (Bit8u i = 0x80; i <= 0x95; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i));
}
_CaptureRegWrite(0xbd, opl->_ReadReg(0xbd));
for (Bit8u i = 0xc0; i <= 0xc8; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i) | 0x30); // enable L + R channels
}
for (Bit8u i = 0xe0; i <= 0xf5; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i));
if (captureHandle) {
DROMultiplexer::master = this;
lastWrite = -1;
captureLengthBytes = 0;
captureStart = Time::currentTimeMillis();
fwrite(dro_header, 1, sizeof(dro_header), captureHandle);
for (int i = 0; i <= 0xff; i++) {
_CaptureRegWrite(i, 0);
}
_CaptureOpl3Enable();
for (Bit8u i = 0x20; i <= 0x35; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i));
}
for (Bit8u i = 0x40; i <= 0x55; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i));
}
for (Bit8u i = 0x60; i <= 0x75; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i));
}
for (Bit8u i = 0x80; i <= 0x95; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i));
}
_CaptureRegWrite(0xbd, opl->_ReadReg(0xbd));
for (Bit8u i = 0xc0; i <= 0xc8; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i) | 0x30); // enable L + R channels
}
for (Bit8u i = 0xe0; i <= 0xf5; i++) {
_CaptureRegWrite(i, opl->_ReadReg(i));
}
}
return (NULL != captureHandle);
}
void DROMultiplexer::StopCapture() {

View file

@ -1,6 +1,7 @@
#pragma once
#include <map>
#include "hiopl.h"
#include "../JuceLibraryCode/JuceHeader.h"
class DROMultiplexer
{
@ -17,7 +18,7 @@ public:
void InitCaptureVariables();
bool IsAnInstanceRecording();
bool IsAnotherInstanceRecording();
void StartCapture(const char* filepath, Hiopl* opl);
bool StartCapture(const char* filepath, Hiopl* opl);
void StopCapture();
static DROMultiplexer* GetMaster();
@ -26,13 +27,15 @@ private:
void _CaptureRegWriteWithDelay(Bit32u reg, Bit8u value);
void _CaptureRegWrite(Bit32u reg, Bit8u value);
void _CaptureOpl3Enable();
int _FindFreeChannel();
int _FindFreeChannel(Hiopl* opl, int inCh);
void _DebugOut(char* str);
static DROMultiplexer* master;
FILE* captureHandle;
Bit64s captureStart;
Bit64s lastWrite;
Bit32u captureLengthBytes;
static CriticalSection lock;
typedef struct oplch {
Hiopl* opl;

View file

@ -152,7 +152,9 @@ bool JuceOplvstiAudioProcessor::isAnyInstanceRecording() {
void JuceOplvstiAudioProcessor::startRecording(File *outputFile) {
recordingFile = outputFile;
dro->StartCapture(outputFile->getFullPathName().toUTF8(), Opl);
if (!dro->StartCapture(outputFile->getFullPathName().toUTF8(), Opl)) {
juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::InfoIcon, "Could not open specified file for writing!", "OK");
}
}
void JuceOplvstiAudioProcessor::stopRecording() {
@ -447,8 +449,8 @@ JuceOplvstiAudioProcessor::~JuceOplvstiAudioProcessor()
{
for (unsigned int i=0; i < params.size(); ++i)
delete params[i];
//delete Opl;
//delete dro;
delete Opl;
delete dro;
}
//==============================================================================

View file

@ -529,9 +529,6 @@ void Operator::WriteE0( const Chip* chip, Bit8u val ) {
INLINE void Operator::SetState( Bit8u s ) {
state = s;
volHandler = VolumeHandlerTable[ s ];
if (OFF == s) {
// TODO: callback
}
}
INLINE bool Operator::Silent() const {

View file

@ -190,6 +190,17 @@ void Hiopl::KeyOff(int ch) {
_ClearRegBits(0xb0+offset, 0x20);
}
static const char STATE[] = {
'-',
'R',
'S',
'D',
'A',
};
char Hiopl::GetState(int ch) {
return STATE[adlib->chip.chan[ch - 1].op[1].state];
}
bool Hiopl::IsActive(int ch) {
// check carrier envelope state
return DBOPL::Operator::State::OFF != adlib->chip.chan[ch - 1].op[1].state;

View file

@ -68,6 +68,7 @@ class Hiopl {
void KeyOff(int ch);
// Return false if no note is active on the channel (ie release is complete)
bool IsActive(int ch);
char GetState(int ch);
void SetFrequency(int ch, float frqHz, bool keyOn=false);
void _WriteReg(Bit32u reg, Bit8u value, Bit8u mask=0x0);
void _ClearRegBits(Bit32u reg, Bit8u mask);