mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-26 22:43:01 +00:00
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:
parent
26dca41b63
commit
65f893822a
8 changed files with 90 additions and 40 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue