Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fixed octave for block+fnum systems #2324

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions papers/newIns.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ size | description
1 | |x| ALG |x| FB |
1 | |FMS2 |AMS| FMS |
1 | |AM2|4| LLPatch |
1 | |xxxxxxx| Block | (>=224)
-----|------------------------------------
| **operator data × opCount**
| /7 6 5 4 3 2 1 0|
Expand Down
59 changes: 43 additions & 16 deletions src/engine/bsr.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ static inline int bsr32(unsigned int v) {

static inline int bsr(unsigned short v) {
if (v) {
return 32 - __builtin_clz(v);
return 32-__builtin_clz(v);
} else {
return -1;
}
}

static inline int bsr32(unsigned int v) {
if (v) {
return 32 - __builtin_clz(v);
return 32-__builtin_clz(v);
} else {
return -1;
}
Expand All @@ -61,25 +61,52 @@ static inline int bsr32(unsigned int v) {
#else

static inline int bsr(unsigned short v) {
unsigned short mask = 0x8000;
for (int i = 16; i >= 0; --i) {
if (v&mask)
return i;
mask>>=1;
if (v==0) return -1;
if (v&0x8000) return 16;
int o=16;
if (!(v&0xff00)) {
o-=8;
v<<=8;
if (v&0x8000) return o;
}

return -1;
if (!(v&0xf000)) {
o-=4;
v<<=4;
if (v&0x8000) return o;
}
if (!(v&0xc000)) {
o-=2;
v<<=2;
if (v&0x8000) return o;
}
return (v&0x8000) ? o : o-1;
}

static inline int bsr32(unsigned int v) {
unsigned int mask = 0x80000000;
for (int i = 32; i >= 0; --i) {
if (v&mask)
return i;
mask>>=1;
if (v==0) return -1;
if (v&0x80000000) return 32;
int o=32;
if (!(v&0xffff0000)) {
o-=16;
v<<=16;
if (v&0x80000000) return o;
}

return -1;
if (!(v&0xff000000)) {
o-=8;
v<<=8;
if (v&0x80000000) return o;
}
if (!(v&0xf0000000)) {
o-=4;
v<<=4;
if (v&0x80000000) return o;
}
if (!(v&0xc0000000)) {
o-=2;
v<<=2;
if (v&0x80000000) return o;
}
return (v&0x80000000) ? o : o-1;
}

#endif
Expand Down
2 changes: 1 addition & 1 deletion src/engine/dispatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,7 @@ class DivDispatch {
#define NOTE_FREQUENCY(x) parent->calcBaseFreq(chipClock,CHIP_FREQBASE,x,false)

// this is a special case definition. only use it for f-num/block-based chips.
#define NOTE_FNUM_BLOCK(x,bits) parent->calcBaseFreqFNumBlock(chipClock,CHIP_FREQBASE,x,bits)
#define NOTE_FNUM_BLOCK(x,bits,ins) parent->calcBaseFreqFNumBlock(chipClock,CHIP_FREQBASE,x,bits,parent->getIns(ins)->fm.block)

// this is for volume scaling calculation.
#define VOL_SCALE_LINEAR(x,y,range) ((parent->song.ceilVolumeScaling)?((((x)*(y))+(range-1))/(range)):(((x)*(y))/(range)))
Expand Down
24 changes: 20 additions & 4 deletions src/engine/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1797,15 +1797,27 @@ double DivEngine::calcBaseFreq(double clock, double divider, int note, bool peri
/* logV("f-num: %d block: %d",bf,block); */ \
return bf|(block<<bits);

int DivEngine::calcBaseFreqFNumBlock(double clock, double divider, int note, int bits) {
#define CONVERT_FNUM_FIXEDBLOCK(bf,bits,block) \
bf>>=(block); \
if (bf<0) bf=0; \
if (bf>((1<<(bits))-1)) { \
bf=(1<<(bits))-1; \
} \
return bf|((block)<<(bits));

int DivEngine::calcBaseFreqFNumBlock(double clock, double divider, int note, int bits, int fixedBlock) {
if (song.linearPitch==2) { // full linear
return (note<<7);
}
int bf=calcBaseFreq(clock,divider,note,false);
CONVERT_FNUM_BLOCK(bf,bits,note)
if (fixedBlock>0) {
CONVERT_FNUM_FIXEDBLOCK(bf,bits,fixedBlock-1);
} else {
CONVERT_FNUM_BLOCK(bf,bits,note);
}
}

int DivEngine::calcFreq(int base, int pitch, int arp, bool arpFixed, bool period, int octave, int pitch2, double clock, double divider, int blockBits) {
int DivEngine::calcFreq(int base, int pitch, int arp, bool arpFixed, bool period, int octave, int pitch2, double clock, double divider, int blockBits, int fixedBlock) {
if (song.linearPitch==2) {
// do frequency calculation here
int nbase=base+pitch+pitch2;
Expand All @@ -1821,7 +1833,11 @@ int DivEngine::calcFreq(int base, int pitch, int arp, bool arpFixed, bool period
round((clock/fbase)/divider):
round(fbase*(divider/clock));
if (blockBits>0) {
CONVERT_FNUM_BLOCK(bf,blockBits,nbase>>7)
if (fixedBlock>0) {
CONVERT_FNUM_FIXEDBLOCK(bf,blockBits,fixedBlock-1);
} else {
CONVERT_FNUM_BLOCK(bf,blockBits,nbase>>7);
}
} else {
return bf;
}
Expand Down
8 changes: 4 additions & 4 deletions src/engine/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class DivWorkPool;

#define DIV_UNSTABLE

#define DIV_VERSION "dev223"
#define DIV_ENGINE_VERSION 223
#define DIV_VERSION "dev224"
#define DIV_ENGINE_VERSION 224
// for imports
#define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02
Expand Down Expand Up @@ -805,10 +805,10 @@ class DivEngine {
double calcBaseFreq(double clock, double divider, int note, bool period);

// calculate base frequency in f-num/block format
int calcBaseFreqFNumBlock(double clock, double divider, int note, int bits);
int calcBaseFreqFNumBlock(double clock, double divider, int note, int bits, int fixedBlock);

// calculate frequency/period
int calcFreq(int base, int pitch, int arp, bool arpFixed, bool period=false, int octave=0, int pitch2=0, double clock=1.0, double divider=1.0, int blockBits=0);
int calcFreq(int base, int pitch, int arp, bool arpFixed, bool period=false, int octave=0, int pitch2=0, double clock=1.0, double divider=1.0, int blockBits=0, int fixedBlock=0);

// calculate arpeggio
int calcArp(int note, int arp, int offset=0);
Expand Down
6 changes: 6 additions & 0 deletions src/engine/instrument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ void DivInstrument::writeFeatureFM(SafeWriter* w, bool fui) {
w->writeC(((fm.alg&7)<<4)|(fm.fb&7));
w->writeC(((fm.fms2&7)<<5)|((fm.ams&3)<<3)|(fm.fms&7));
w->writeC(((fm.ams2&3)<<6)|((fm.ops==4)?32:0)|(fm.opllPreset&31));
w->writeC(fm.block&15);

// operator data
for (int i=0; i<opCount; i++) {
Expand Down Expand Up @@ -1741,6 +1742,11 @@ void DivInstrument::readFeatureFM(SafeReader& reader, short version) {
fm.ops=(next&32)?4:2;
fm.opllPreset=next&31;

if (version>=224) {
next=reader.readC();
fm.block=next&15;
}

// read operators
for (int i=0; i<opCount; i++) {
DivInstrumentFM::Operator& op=fm.op[i];
Expand Down
3 changes: 2 additions & 1 deletion src/engine/instrument.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ enum DivMacroTypeOp: unsigned char {
// - WS, DVB = MULT (FINE), DAM = REV, KSL = EGShift, EGT = Fixed

struct DivInstrumentFM {
unsigned char alg, fb, fms, ams, fms2, ams2, ops, opllPreset;
unsigned char alg, fb, fms, ams, fms2, ams2, ops, opllPreset, block;
bool fixedDrums;
unsigned short kickFreq, snareHatFreq, tomTopFreq;

Expand Down Expand Up @@ -216,6 +216,7 @@ struct DivInstrumentFM {
ams2(0),
ops(2),
opllPreset(0),
block(0),
fixedDrums(false),
kickFreq(0x520),
snareHatFreq(0x550),
Expand Down
51 changes: 34 additions & 17 deletions src/engine/platform/esfm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "esfm.h"
#include "../engine.h"
#include "../bsr.h"
#include "../../ta-log.h"
#include <string.h>
#include <stdio.h>
Expand Down Expand Up @@ -291,7 +292,12 @@ void DivPlatformESFM::tick(bool sysTick) {

for (int i=0; i<18; i++) {
if (chan[i].freqChanged) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,octave(chan[i].baseFreq)*2,chan[i].pitch2,chipClock,CHIP_FREQBASE);
int mul=2;
int fixedBlock=parent->getIns(chan[i].ins)->fm.block;
if (parent->song.linearPitch!=2) {
mul=octave(chan[i].baseFreq,fixedBlock)*2;
}
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,mul,chan[i].pitch2,chipClock,CHIP_FREQBASE);
if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>131071) chan[i].freq=131071;

Expand All @@ -314,10 +320,10 @@ void DivPlatformESFM::tick(bool sysTick) {
if(chan[i].opsState[o].hasOpPitch) {
pitch2=chan[i].opsState[o].pitch2+dt;
}
int opFreq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,arp,fixedArp,false,octave(chan[i].baseFreq)*2,pitch2,chipClock,CHIP_FREQBASE);
int opFreq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,arp,fixedArp,false,mul,pitch2,chipClock,CHIP_FREQBASE);
if (opFreq<0) opFreq=0;
if (opFreq>131071) opFreq=131071;
int freqt=toFreq(opFreq);
int freqt=toFreq(opFreq,fixedBlock);
chan[i].freqL[o]=freqt&0xff;
chan[i].freqH[o]=freqt>>8;
}
Expand Down Expand Up @@ -365,22 +371,27 @@ void DivPlatformESFM::tick(bool sysTick) {
}
}

int DivPlatformESFM::octave(int freq) {
int result=1;
while (freq>0x3ff) {
freq>>=1;
result<<=1;
int DivPlatformESFM::octave(int freq, int fixedBlock) {
if (fixedBlock>0) {
return 1<<(fixedBlock-1);
}
if (freq>0x3ff) {
return 1<<(bsr32(freq)-10);
}
return result;
return 1;
}

int DivPlatformESFM::toFreq(int freq) {
int DivPlatformESFM::toFreq(int freq, int fixedBlock) {
int block=0;
while (freq>0x3ff) {
freq>>=1;
block++;
if (fixedBlock>0) {
block=fixedBlock-1;
freq>>=block;
if (freq>0x3ff) freq=0x3ff;
} else if (freq>0x3ff) {
block=bsr32(freq)-10;
freq>>=block;
}
return ((block&7)<<10)|(freq&0x3ff);
return (block<<10)|(freq&0x3ff);
}

void DivPlatformESFM::muteChannel(int ch, bool mute) {
Expand Down Expand Up @@ -513,21 +524,27 @@ int DivPlatformESFM::dispatch(DivCommand c) {
int destFreq=NOTE_FREQUENCY(c.value2);
int newFreq;
bool return2=false;
int mul=1;
int fixedBlock=0;
if (parent->song.linearPitch!=2) {
fixedBlock=parent->getIns(chan[c.chan].ins)->fm.block;
mul=octave(chan[c.chan].baseFreq,fixedBlock);
}
if (destFreq>chan[c.chan].baseFreq) {
newFreq=chan[c.chan].baseFreq+c.value*((parent->song.linearPitch==2)?1:octave(chan[c.chan].baseFreq));
newFreq=chan[c.chan].baseFreq+c.value*mul;
if (newFreq>=destFreq) {
newFreq=destFreq;
return2=true;
}
} else {
newFreq=chan[c.chan].baseFreq-c.value*((parent->song.linearPitch==2)?1:octave(chan[c.chan].baseFreq));
newFreq=chan[c.chan].baseFreq-c.value*mul;
if (newFreq<=destFreq) {
newFreq=destFreq;
return2=true;
}
}
if (!chan[c.chan].portaPause && parent->song.linearPitch!=2) {
if (octave(chan[c.chan].baseFreq)!=octave(newFreq)) {
if (mul!=octave(newFreq,fixedBlock)) {
chan[c.chan].portaPause=true;
break;
}
Expand Down
4 changes: 2 additions & 2 deletions src/engine/platform/esfm.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ class DivPlatformESFM: public DivDispatch {
short oldWrites[ESFM_REG_POOL_SIZE];
short pendingWrites[ESFM_REG_POOL_SIZE];

int octave(int freq);
int toFreq(int freq);
int octave(int freq, int fixedBlock);
int toFreq(int freq, int fixedBlock);
void commitState(int ch, DivInstrument* ins);

friend void putDispatchChip(void*,int);
Expand Down
2 changes: 1 addition & 1 deletion src/engine/platform/fmshared_OPN.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#define PLEASE_HELP_ME(_targetChan) \
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false); \
int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false); \
int destFreq=NOTE_FNUM_BLOCK(c.value2,11); \
int destFreq=NOTE_FNUM_BLOCK(c.value2,11,_targetChan.ins); \
int newFreq; \
bool return2=false; \
if (_targetChan.portaPause) { \
Expand Down
8 changes: 4 additions & 4 deletions src/engine/platform/genesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
chan[i].handleArp();
} else if (chan[i].std.arp.had) {
if (!chan[i].inPorta) {
chan[i].baseFreq=NOTE_FNUM_BLOCK(parent->calcArp(chan[i].note,chan[i].std.arp.val),11);
chan[i].baseFreq=NOTE_FNUM_BLOCK(parent->calcArp(chan[i].note,chan[i].std.arp.val),11,chan[i].ins);
}
chan[i].freqChanged=true;
}
Expand Down Expand Up @@ -838,7 +838,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
if (i==2 && extMode) continue;
if (chan[i].freqChanged) {
if (parent->song.linearPitch==2) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE,11);
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE,11,parent->getIns(chan[i].ins)->fm.block);
} else {
int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE,11);
int block=(chan[i].baseFreq&0xf800)>>11;
Expand Down Expand Up @@ -1084,7 +1084,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
chan[c.chan].insChanged=false;

if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11);
chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11,chan[c.chan].ins);
chan[c.chan].portaPause=false;
chan[c.chan].note=c.value;
chan[c.chan].freqChanged=true;
Expand Down Expand Up @@ -1274,7 +1274,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
commitState(c.chan,ins);
chan[c.chan].insChanged=false;
}
chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11);
chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11,chan[c.chan].ins);
}
chan[c.chan].note=c.value;
chan[c.chan].freqChanged=true;
Expand Down
Loading