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
This commit is contained in:
tildearrow 2022-04-08 04:34:39 -05:00
parent 26dca41b63
commit 65f893822a
8 changed files with 90 additions and 40 deletions

View file

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

View file

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

View file

@ -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;
}

View file

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

View file

@ -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<<i);
if (chan[i].ws.tick()) {
updateWave(i);
}
}
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->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);
}
}

View file

@ -22,6 +22,7 @@
#include "../dispatch.h"
#include "../macroInt.h"
#include "../waveSynth.h"
#include "sound/swan.h"
#include <queue>
@ -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),

View file

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

View file

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