From 65f893822a1ce1431f68934d4199f4d046837d12 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Fri, 8 Apr 2022 04:34:39 -0500 Subject: [PATCH] dev79 - wave synth data storage also wave synth works on swan and X1-010 now however it's untested on X1 because i wrote it in bed --- papers/format.md | 14 ++++++++++++ src/engine/engine.h | 4 ++-- src/engine/instrument.cpp | 28 +++++++++++++++++++++++ src/engine/instrument.h | 4 +--- src/engine/platform/swan.cpp | 42 ++++++++++++++++------------------ src/engine/platform/swan.h | 2 ++ src/engine/platform/x1_010.cpp | 34 ++++++++++++++++----------- src/engine/platform/x1_010.h | 2 ++ 8 files changed, 90 insertions(+), 40 deletions(-) diff --git a/papers/format.md b/papers/format.md index 005345755..9ce20d2d7 100644 --- a/papers/format.md +++ b/papers/format.md @@ -29,6 +29,7 @@ furthermore, an `or reserved` indicates this field is always present, but is res the format versions are: +- 79: Furnace dev79 - 78: Furnace dev78 - 77: Furnace dev77 - 76: Furnace dev76 @@ -579,6 +580,19 @@ size | description --- | **OPZ instrument extra data** (>=77) 1 | fms2 1 | ams2 + --- | **wavetable synth data** (>=79) + 4 | first wave + 4 | second wave + 1 | rate divider + 1 | effect + | - bit 7: single or dual effect + 1 | enabled + 1 | global + 1 | speed (+1) + 1 | parameter 1 + 1 | parameter 2 + 1 | parameter 3 + 1 | parameter 4 ``` # wavetable diff --git a/src/engine/engine.h b/src/engine/engine.h index e5240ab9e..677cdeaaa 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -42,8 +42,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev78" -#define DIV_ENGINE_VERSION 78 +#define DIV_VERSION "dev79" +#define DIV_ENGINE_VERSION 79 // for imports #define DIV_VERSION_MOD 0xff01 diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index 1299cdec8..60ce6810b 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -467,6 +467,19 @@ void DivInstrument::putInsData(SafeWriter* w) { // OPZ w->writeC(fm.fms2); w->writeC(fm.ams2); + + // wave synth + w->writeI(ws.wave1); + w->writeI(ws.wave2); + w->writeC(ws.rateDivider); + w->writeC(ws.effect); + w->writeC(ws.enabled); + w->writeC(ws.global); + w->writeC(ws.speed); + w->writeC(ws.param1); + w->writeC(ws.param2); + w->writeC(ws.param3); + w->writeC(ws.param4); } DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) { @@ -895,6 +908,21 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) { fm.fms2=reader.readC(); fm.ams2=reader.readC(); } + + // wave synth + if (version>=79) { + ws.wave1=reader.readI(); + ws.wave2=reader.readI(); + ws.rateDivider=reader.readC(); + ws.effect=reader.readC(); + ws.enabled=reader.readC(); + ws.global=reader.readC(); + ws.speed=reader.readC(); + ws.param1=reader.readC(); + ws.param2=reader.readC(); + ws.param3=reader.readC(); + ws.param4=reader.readC(); + } return DIV_DATA_SUCCESS; } diff --git a/src/engine/instrument.h b/src/engine/instrument.h index c56319119..8109030ed 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -502,7 +502,7 @@ enum DivWaveSynthEffects { struct DivInstrumentWaveSynth { int wave1, wave2; - unsigned char rateDivider, width, height; + unsigned char rateDivider; unsigned char effect; bool oneShot, enabled, global; unsigned char speed, param1, param2, param3, param4; @@ -510,8 +510,6 @@ struct DivInstrumentWaveSynth { wave1(0), wave2(0), rateDivider(1), - width(32), - height(32), effect(DIV_WS_NONE), oneShot(false), enabled(false), diff --git a/src/engine/platform/swan.cpp b/src/engine/platform/swan.cpp index 0f32e9a08..6966a2d1c 100644 --- a/src/engine/platform/swan.cpp +++ b/src/engine/platform/swan.cpp @@ -111,22 +111,11 @@ void DivPlatformSwan::acquire(short* bufL, short* bufR, size_t start, size_t len } void DivPlatformSwan::updateWave(int ch) { - DivWavetable* wt=parent->getWave(chan[ch].wave); unsigned char addr=0x40+ch*16; - if (wt->max<1 || wt->len<1) { - for (int i=0; i<16; i++) { - rWrite(addr+i,0); - } - } else { - for (int i=0; i<16; i++) { - int nibble1=(wt->data[(i*2)*wt->len/32]*15)/wt->max; - int nibble2=(wt->data[(1+i*2)*wt->len/32]*15)/wt->max; - if (nibble1<0) nibble1=0; - if (nibble1>15) nibble1=15; - if (nibble2<0) nibble2=0; - if (nibble2>15) nibble2=15; - rWrite(addr+i,nibble1|(nibble2<<4)); - } + for (int i=0; i<16; i++) { + int nibble1=chan[ch].ws.output[i<<1]; + int nibble2=chan[ch].ws.output[1+(i<<1)]; + rWrite(addr+i,nibble1|(nibble2<<4)); } } @@ -179,13 +168,16 @@ void DivPlatformSwan::tick() { } } if (chan[i].std.hadWave && !(i==1 && pcm)) { - if (chan[i].wave!=chan[i].std.wave) { + if (chan[i].wave!=chan[i].std.wave || chan[i].ws.activeChanged()) { chan[i].wave=chan[i].std.wave; - updateWave(i); + chan[i].ws.changeWave1(chan[i].wave); } } if (chan[i].active) { sndCtrl|=(1<calcFreq(chan[i].baseFreq,chan[i].pitch,true); @@ -211,10 +203,6 @@ void DivPlatformSwan::tick() { if (!chan[i].std.willVol) { calcAndWriteOutVol(i,15); } - if (chan[i].wave<0) { - chan[i].wave=0; - updateWave(i); - } chan[i].keyOn=false; } if (chan[i].keyOff) { @@ -300,6 +288,12 @@ int DivPlatformSwan::dispatch(DivCommand c) { chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].std.init(ins); + if (chan[c.chan].wave<0) { + chan[c.chan].wave=0; + chan[c.chan].ws.changeWave1(chan[c.chan].wave); + } + chan[c.chan].ws.init(ins,32,15,chan[c.chan].insChanged); + chan[c.chan].insChanged=false; break; } case DIV_CMD_NOTE_OFF: @@ -319,6 +313,7 @@ int DivPlatformSwan::dispatch(DivCommand c) { case DIV_CMD_INSTRUMENT: if (chan[c.chan].ins!=c.value || c.value2==1) { chan[c.chan].ins=c.value; + chan[c.chan].insChanged=true; } break; case DIV_CMD_VOLUME: @@ -338,7 +333,7 @@ int DivPlatformSwan::dispatch(DivCommand c) { break; case DIV_CMD_WAVE: chan[c.chan].wave=c.value; - updateWave(c.chan); + chan[c.chan].ws.changeWave1(chan[c.chan].wave); chan[c.chan].keyOn=true; break; case DIV_CMD_WS_SWEEP_TIME: @@ -458,6 +453,8 @@ void DivPlatformSwan::reset() { chan[i]=Channel(); chan[i].vol=15; chan[i].pan=0xff; + chan[i].ws.setEngine(parent); + chan[i].ws.init(NULL,32,15,false); rWrite(0x08+i,0xff); } if (dumpWrites) { @@ -484,6 +481,7 @@ bool DivPlatformSwan::isStereo() { void DivPlatformSwan::notifyWaveChange(int wave) { for (int i=0; i<4; i++) { if (chan[i].wave==wave) { + chan[i].ws.changeWave1(wave); updateWave(i); } } diff --git a/src/engine/platform/swan.h b/src/engine/platform/swan.h index 47470f57b..610884b00 100644 --- a/src/engine/platform/swan.h +++ b/src/engine/platform/swan.h @@ -22,6 +22,7 @@ #include "../dispatch.h" #include "../macroInt.h" +#include "../waveSynth.h" #include "sound/swan.h" #include @@ -32,6 +33,7 @@ class DivPlatformSwan: public DivDispatch { bool active, insChanged, freqChanged, keyOn, keyOff, inPorta; int vol, outVol, wave; DivMacroInt std; + DivWaveSynth ws; Channel(): freq(0), baseFreq(0), diff --git a/src/engine/platform/x1_010.cpp b/src/engine/platform/x1_010.cpp index 6834986f6..68f6db297 100644 --- a/src/engine/platform/x1_010.cpp +++ b/src/engine/platform/x1_010.cpp @@ -274,19 +274,12 @@ double DivPlatformX1_010::NoteX1_010(int ch, int note) { } void DivPlatformX1_010::updateWave(int ch) { - DivWavetable* wt=parent->getWave(chan[ch].wave); if (chan[ch].active) { - chan[ch].waveBank ^= 1; + chan[ch].waveBank^=1; } for (int i=0; i<128; i++) { - if (wt->max<1 || wt->len<1) { - waveWrite(ch,i,0); - } else { - int data=wt->data[i*wt->len/128]*255/wt->max; - if (data<0) data=0; - if (data>255) data=255; - waveWrite(ch,i,data); - } + int data=chan[ch].ws.output[i]; + waveWrite(ch,i,data); } if (!chan[ch].pcm) { chWrite(ch,1,(chan[ch].waveBank<<4)|(ch&0xf)); @@ -371,10 +364,10 @@ void DivPlatformX1_010::tick() { } } if (chan[i].std.hadWave && !chan[i].pcm) { - if (chan[i].wave!=chan[i].std.wave) { + if (chan[i].wave!=chan[i].std.wave || chan[i].ws.activeChanged()) { chan[i].wave=chan[i].std.wave; if (!chan[i].pcm) { - updateWave(i); + chan[i].ws.changeWave1(chan[i].wave); if (!chan[i].keyOff) chan[i].keyOn=true; } } @@ -458,6 +451,11 @@ void DivPlatformX1_010::tick() { if (!chan[i].std.willEx3) chan[i].autoEnvNum=1; } } + if (chan[i].active) { + if (chan[i].ws.tick()) { + updateWave(i); + } + } if (chan[i].envChanged) { chan[i].lvol=isMuted[i]?0:(((chan[i].outVol&0xf)*((chan[i].pan>>4)&0xf))/15); chan[i].rvol=isMuted[i]?0:(((chan[i].outVol&0xf)*((chan[i].pan>>0)&0xf))/15); @@ -575,6 +573,12 @@ int DivPlatformX1_010::dispatch(DivCommand c) { chan[c.chan].keyOn=true; chan[c.chan].envChanged=true; chan[c.chan].std.init(ins); + if (chan[c.chan].wave<0) { + chan[c.chan].wave=0; + chan[c.chan].ws.changeWave1(chan[c.chan].wave); + } + chan[c.chan].ws.init(ins,128,255,chan[c.chan].insChanged); + chan[c.chan].insChanged=false; refreshControl(c.chan); break; } @@ -591,6 +595,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) { case DIV_CMD_INSTRUMENT: if (chan[c.chan].ins!=c.value || c.value2==1) { chan[c.chan].ins=c.value; + chan[c.chan].insChanged=true; } break; case DIV_CMD_VOLUME: @@ -618,7 +623,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) { break; case DIV_CMD_WAVE: chan[c.chan].wave=c.value; - updateWave(c.chan); + chan[c.chan].ws.changeWave1(chan[c.chan].wave); chan[c.chan].keyOn=true; break; case DIV_CMD_X1_010_ENVELOPE_SHAPE: @@ -813,6 +818,8 @@ void DivPlatformX1_010::reset() { for (int i=0; i<16; i++) { chan[i]=DivPlatformX1_010::Channel(); chan[i].reset(); + chan[i].ws.setEngine(parent); + chan[i].ws.init(NULL,128,255,false); } x1_010->reset(); sampleBank=0; @@ -833,6 +840,7 @@ bool DivPlatformX1_010::keyOffAffectsArp(int ch) { void DivPlatformX1_010::notifyWaveChange(int wave) { for (int i=0; i<16; i++) { if (chan[i].wave==wave) { + chan[i].ws.changeWave1(wave); updateWave(i); } } diff --git a/src/engine/platform/x1_010.h b/src/engine/platform/x1_010.h index 389fa7bf7..2bfb78cc9 100644 --- a/src/engine/platform/x1_010.h +++ b/src/engine/platform/x1_010.h @@ -23,6 +23,7 @@ #include "../dispatch.h" #include "../engine.h" #include "../macroInt.h" +#include "../waveSynth.h" #include "sound/x1_010/x1_010.hpp" class DivX1_010Interface: public x1_010_mem_intf { @@ -86,6 +87,7 @@ class DivPlatformX1_010: public DivDispatch { unsigned char waveBank; Envelope env; DivMacroInt std; + DivWaveSynth ws; void reset() { freq = baseFreq = pitch = note = 0; wave = sample = ins = -1;