Merge branch 'master' of https://github.com/tildearrow/furnace into nmk112

This commit is contained in:
cam900 2024-01-19 22:30:25 +09:00
commit e5b6f0b373
445 changed files with 8611 additions and 1776 deletions

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -233,6 +233,7 @@ bool DivCSPlayer::tick() {
case DIV_CMD_AMIGA_PM:
case DIV_CMD_MACRO_OFF:
case DIV_CMD_MACRO_ON:
case DIV_CMD_MACRO_RESTART:
arg0=(unsigned char)stream.readC();
break;
case DIV_CMD_FM_TL:

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -153,6 +153,7 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) {
case DIV_CMD_AMIGA_PM:
case DIV_CMD_MACRO_OFF:
case DIV_CMD_MACRO_ON:
case DIV_CMD_MACRO_RESTART:
case DIV_CMD_HINT_ARP_TIME:
w->writeC(1); // length
w->writeC(c.value);
@ -312,8 +313,6 @@ SafeWriter* DivEngine::saveCommand(bool binary) {
for (DivCommand& i: cmdStream) {
switch (i.cmd) {
// strip away hinted/useless commands
case DIV_ALWAYS_SET_VOLUME:
break;
case DIV_CMD_GET_VOLUME:
break;
case DIV_CMD_VOLUME:

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -167,4 +167,8 @@ void DivEngine::setConf(String key, String value) {
bool DivEngine::hasConf(String key) {
return conf.has(key);
}
}
DivConfig& DivEngine::getConfObject() {
return conf;
}

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -243,7 +243,12 @@ enum DivDispatchCmds {
DIV_CMD_C64_AD, // (value)
DIV_CMD_C64_SR, // (value)
DIV_ALWAYS_SET_VOLUME, // () -> alwaysSetVol
DIV_CMD_ESFM_OP_PANNING, // (op, value)
DIV_CMD_ESFM_OUTLVL, // (op, value)
DIV_CMD_ESFM_MODIN, // (op, value)
DIV_CMD_ESFM_ENV_DELAY, // (op, value)
DIV_CMD_MACRO_RESTART, // (which)
DIV_CMD_MAX
};
@ -594,10 +599,10 @@ class DivDispatch {
/**
* map MIDI velocity (from 0 to 127) to chip volume.
* @param ch the chip channel. -1 means N/A.
* @param vel input velocity.
* @param vel input velocity, from 0.0 to 1.0.
* @return output volume.
*/
virtual int mapVelocity(int ch, unsigned char vel);
virtual int mapVelocity(int ch, float vel);
/**
* get the lowest note in a portamento.
@ -606,6 +611,13 @@ class DivDispatch {
*/
virtual int getPortaFloor(int ch);
/**
* check whether to always set volume on volume change (even when same volume).
* only for compatibility purposes!
* @return truth.
*/
virtual bool getLegacyAlwaysSetVolume();
/**
* get the required amplification level of this dispatch's output.
* @return the amplification level.

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -82,6 +82,7 @@
#include "platform/ted.h"
#include "platform/c140.h"
#include "platform/pcmdac.h"
#include "platform/esfm.h"
#include "platform/dummy.h"
#include "../ta-log.h"
#include "song.h"
@ -644,6 +645,9 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
case DIV_SYSTEM_PCM_DAC:
dispatch=new DivPlatformPCMDAC;
break;
case DIV_SYSTEM_ESFM:
dispatch=new DivPlatformESFM;
break;
case DIV_SYSTEM_DUMMY:
dispatch=new DivPlatformDummy;
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -83,7 +83,7 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul
case 0x82:
return "82xx: Set panning (right channel)";
case 0x88:
return "88xx: Set panning (rear channels; x: left; y: right)";
return "88xy: Set panning (rear channels; x: left; y: right)";
break;
case 0x89:
return "89xx: Set panning (rear left channel)";
@ -129,6 +129,8 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul
return "F5xx: Disable macro (see manual)";
case 0xf6:
return "F6xx: Enable macro (see manual)";
case 0xf7:
return "F7xx: Restart macro (see manual)";
case 0xf8:
return "F8xx: Single tick volume slide up";
case 0xf9:
@ -1371,6 +1373,9 @@ DivInstrument* DivEngine::getIns(int index, DivInstrumentType fallbackType) {
case DIV_INS_OPL_DRUMS:
return &song.nullInsOPLDrums;
break;
case DIV_INS_ESFM:
return &song.nullInsESFM;
break;
default:
break;
}
@ -2185,6 +2190,13 @@ int DivEngine::getMaxVolumeChan(int ch) {
return chan[ch].volMax>>8;
}
int DivEngine::mapVelocity(int ch, float vel) {
if (ch<0) return 0;
if (ch>=chans) return 0;
if (disCont[dispatchOfChan[ch]].dispatch==NULL) return 0;
return disCont[dispatchOfChan[ch]].dispatch->mapVelocity(dispatchChanOfChan[ch],vel);
}
unsigned char DivEngine::getOrder() {
return prevOrder;
}
@ -2402,6 +2414,9 @@ int DivEngine::addInstrument(int refChan, DivInstrumentType fallbackType) {
case DIV_INS_OPL_DRUMS:
*ins=song.nullInsOPLDrums;
break;
case DIV_INS_ESFM:
*ins=song.nullInsESFM;
break;
default:
break;
}
@ -3385,6 +3400,14 @@ void DivEngine::setMidiDirect(bool value) {
midiIsDirect=value;
}
void DivEngine::setMidiDirectProgram(bool value) {
midiIsDirectProgram=value;
}
void DivEngine::setMidiVolExp(float value) {
midiVolExp=value;
}
void DivEngine::setMidiCallback(std::function<int(const TAMidiMessage&)> what) {
midiCallback=what;
}
@ -3449,6 +3472,12 @@ void DivEngine::rescanAudioDevices() {
audioDevs.clear();
if (output!=NULL) {
audioDevs=output->listAudioDevices();
}
}
void DivEngine::rescanMidiDevices() {
if (output!=NULL) {
logV("re-scanning midi...");
if (output->midiIn!=NULL) {
midiIns=output->midiIn->listDevices();
}

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -54,8 +54,8 @@ class DivWorkPool;
#define DIV_UNSTABLE
#define DIV_VERSION "dev189"
#define DIV_ENGINE_VERSION 189
#define DIV_VERSION "dev191"
#define DIV_ENGINE_VERSION 191
// for imports
#define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02
@ -176,16 +176,16 @@ struct DivNoteEvent {
signed char channel;
unsigned char ins;
signed char note, volume;
bool on, nop, pad1, pad2;
DivNoteEvent(int c, int i, int n, int v, bool o):
bool on, nop, insChange, fromMIDI;
DivNoteEvent(int c, int i, int n, int v, bool o, bool ic=false, bool fm=false):
channel(c),
ins(i),
note(n),
volume(v),
on(o),
nop(false),
pad1(false),
pad2(false) {}
insChange(ic),
fromMIDI(fm) {}
DivNoteEvent():
channel(-1),
ins(0),
@ -193,8 +193,8 @@ struct DivNoteEvent {
volume(-1),
on(false),
nop(true),
pad1(false),
pad2(false) {}
insChange(false),
fromMIDI(false) {}
};
struct DivDispatchContainer {
@ -415,6 +415,7 @@ class DivEngine {
bool firstTick;
bool skipping;
bool midiIsDirect;
bool midiIsDirectProgram;
bool lowLatency;
bool systemsRegistered;
bool hasLoadedSomething;
@ -423,6 +424,7 @@ class DivEngine {
bool midiOutProgramChange;
int midiOutMode;
int midiOutTimeRate;
float midiVolExp;
int softLockCount;
int subticks, ticks, curRow, curOrder, prevRow, prevOrder, remainingLoops, totalLoops, lastLoopPos, exportLoopCount, nextSpeed, elapsedBars, elapsedBeats, curSpeed;
size_t curSubSongIndex;
@ -700,6 +702,9 @@ class DivEngine {
double getConfDouble(String key, double fallback);
String getConfString(String key, String fallback);
// get config object
DivConfig& getConfObject();
// set a config value
void setConf(String key, bool value);
void setConf(String key, int value);
@ -850,6 +855,9 @@ class DivEngine {
// get channel max volume
int getMaxVolumeChan(int chan);
// map MIDI velocity to volume
int mapVelocity(int ch, float vel);
// get current order
unsigned char getOrder();
@ -946,7 +954,7 @@ class DivEngine {
DivSample* sampleFromFile(const char* path);
// get raw sample
DivSample* sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles);
DivSample* sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles, int rate);
// delete sample
void delSample(int index);
@ -1069,6 +1077,9 @@ class DivEngine {
// rescan audio devices
void rescanAudioDevices();
/** rescan midi devices */
void rescanMidiDevices();
// set the console mode.
void setConsoleMode(bool enable);
@ -1184,6 +1195,12 @@ class DivEngine {
// set MIDI direct channel map
void setMidiDirect(bool value);
// set MIDI direct program change
void setMidiDirectProgram(bool value);
// set MIDI volume curve exponent
void setMidiVolExp(float value);
// set MIDI input callback
// if the specified function returns -2, note feedback will be inhibited.
void setMidiCallback(std::function<int(const TAMidiMessage&)> what);
@ -1253,6 +1270,7 @@ class DivEngine {
firstTick(false),
skipping(false),
midiIsDirect(false),
midiIsDirectProgram(false),
lowLatency(false),
systemsRegistered(false),
hasLoadedSomething(false),
@ -1261,6 +1279,7 @@ class DivEngine {
midiOutProgramChange(false),
midiOutMode(DIV_MIDI_MODE_NOTE),
midiOutTimeRate(0),
midiVolExp(2.0f), // General MIDI standard
softLockCount(0),
subticks(0),
ticks(0),

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -187,6 +187,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
ds.oldDPCM=true;
ds.delayBehavior=0;
ds.jumpTreatment=2;
ds.oldAlwaysSetVolume=true;
// 1.1 compat flags
if (ds.version>24) {
@ -1876,6 +1877,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
if (ds.version<188) {
ds.ceilVolumeScaling=false;
}
if (ds.version<191) {
ds.oldAlwaysSetVolume=true;
}
ds.isDMF=false;
reader.readS(); // reserved
@ -2424,7 +2428,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
} else {
reader.readC();
}
for (int i=0; i<2; i++) {
if (ds.version>=191) {
ds.oldAlwaysSetVolume=reader.readC();
} else {
reader.readC();
}
for (int i=0; i<1; i++) {
reader.readC();
}
}
@ -5522,7 +5531,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary, bool newPatternFormat) {
w->writeC(song.oldDPCM);
w->writeC(song.resetArpPhaseOnNewNote);
w->writeC(song.ceilVolumeScaling);
for (int i=0; i<2; i++) {
w->writeC(song.oldAlwaysSetVolume);
for (int i=0; i<1; i++) {
w->writeC(0);
}
@ -6445,7 +6455,7 @@ SafeWriter* DivEngine::saveText(bool separatePatterns) {
w->writeText(fmt::sprintf("- type: %d\n",(int)ins->type));
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPZ || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPM) {
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPZ || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPM || ins->type==DIV_INS_ESFM) {
w->writeText("- FM parameters:\n");
w->writeText(fmt::sprintf(" - ALG: %d\n",ins->fm.alg));
w->writeText(fmt::sprintf(" - FB: %d\n",ins->fm.fb));
@ -6489,10 +6499,29 @@ SafeWriter* DivEngine::saveText(bool separatePatterns) {
}
}
if (ins->type==DIV_INS_ESFM) {
w->writeText("- ESFM parameters:\n");
w->writeText(fmt::sprintf(" - noise mode: %d\n",ins->esfm.noise));
for (int j=0; j<ins->fm.ops; j++) {
DivInstrumentESFM::Operator& opE=ins->esfm.op[j];
w->writeText(fmt::sprintf(" - operator %d:\n",j));
w->writeText(fmt::sprintf(" - DL: %d\n",opE.delay));
w->writeText(fmt::sprintf(" - OL: %d\n",opE.outLvl));
w->writeText(fmt::sprintf(" - MI: %d\n",opE.modIn));
w->writeText(fmt::sprintf(" - output left: %s\n",trueFalse[opE.left?1:0]));
w->writeText(fmt::sprintf(" - output right: %s\n",trueFalse[opE.right?1:0]));
w->writeText(fmt::sprintf(" - CT: %d\n",opE.ct));
w->writeText(fmt::sprintf(" - DT: %d\n",opE.dt));
w->writeText(fmt::sprintf(" - fixed frequency: %s\n",trueFalse[opE.fixed?1:0]));
}
}
if (ins->type==DIV_INS_GB) {
w->writeText("- Game Boy parameters:\n");
w->writeText(fmt::sprintf(" - volume: %d\n",ins->gb.envVol));
w->writeText(fmt::sprintf(" - direction: %d\n",gbEnvDir[ins->gb.envDir?1:0]));
w->writeText(fmt::sprintf(" - direction: %s\n",gbEnvDir[ins->gb.envDir?1:0]));
w->writeText(fmt::sprintf(" - length: %d\n",ins->gb.envLen));
w->writeText(fmt::sprintf(" - sound length: %d\n",ins->gb.soundLen));
w->writeText(fmt::sprintf(" - use software envelope: %s\n",trueFalse[ins->gb.softEnv?1:0]));

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -302,7 +302,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
#endif
}
DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles) {
DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles, int rate) {
if (song.sample.size()>=256) {
lastError="too many samples!";
return NULL;
@ -420,8 +420,8 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth,
return NULL;
}
sample->rate=32000;
sample->centerRate=32000;
sample->rate=rate;
sample->centerRate=rate;
sample->depth=depth;
sample->init(samples);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -230,6 +230,29 @@ bool DivInstrumentSNES::operator==(const DivInstrumentSNES& other) {
);
}
bool DivInstrumentESFM::operator==(const DivInstrumentESFM& other) {
return (
_C(noise) &&
_C(op[0]) &&
_C(op[1]) &&
_C(op[2]) &&
_C(op[3])
);
}
bool DivInstrumentESFM::Operator::operator==(const DivInstrumentESFM::Operator& other) {
return (
_C(delay) &&
_C(outLvl) &&
_C(modIn) &&
_C(left) &&
_C(right) &&
_C(fixed) &&
_C(ct) &&
_C(dt)
);
}
#undef _C
#define FEATURE_BEGIN(x) \
@ -743,6 +766,22 @@ void DivInstrument::writeFeatureNE(SafeWriter* w) {
FEATURE_END;
}
void DivInstrument::writeFeatureEF(SafeWriter* w) {
FEATURE_BEGIN("EF");
w->writeC(esfm.noise&3);
for (int i=0; i<4; i++) {
DivInstrumentESFM::Operator& op=esfm.op[i];
w->writeC(((op.delay&7)<<5)|((op.outLvl&7)<<2)|((op.right&1)<<1)|(op.left&1));
w->writeC((op.fixed&1)<<3|(op.modIn&7));
w->writeC(op.ct);
w->writeC(op.dt);
}
FEATURE_END;
}
void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bool insName) {
size_t blockStartSeek=0;
size_t blockEndSeek=0;
@ -786,6 +825,7 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo
bool featureES=false;
bool featureX1=false;
bool featureNE=false;
bool featureEF=false;
bool checkForWL=false;
@ -999,7 +1039,10 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo
featureSM=true;
featureSL=true;
break;
case DIV_INS_ESFM:
featureFM=true;
featureEF=true;
break;
case DIV_INS_MAX:
break;
case DIV_INS_NULL:
@ -1047,6 +1090,9 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo
if (x1_010!=defaultIns.x1_010) {
featureX1=true;
}
if (esfm!=defaultIns.esfm) {
featureEF=true;
}
}
// check ins name
@ -1189,6 +1235,9 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo
if (featureNE) {
writeFeatureNE(w);
}
if (featureEF) {
writeFeatureEF(w);
}
if (fui && (featureSL || featureWL)) {
w->write("EN",2);
@ -2598,6 +2647,32 @@ void DivInstrument::readFeatureNE(SafeReader& reader, short version) {
READ_FEAT_END;
}
void DivInstrument::readFeatureEF(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
unsigned char next=reader.readC();
esfm.noise=next&3;
for (int i=0; i<4; i++) {
DivInstrumentESFM::Operator& op=esfm.op[i];
next=reader.readC();
op.delay=(next>>5)&7;
op.outLvl=(next>>2)&7;
op.right=(next>>1)&1;
op.left=next&1;
next=reader.readC();
op.modIn=next&7;
op.fixed=(next>>3)&1;
op.ct=reader.readC();
op.dt=reader.readC();
}
READ_FEAT_END;
}
DivDataErrors DivInstrument::readInsDataNew(SafeReader& reader, short version, bool fui, DivSong* song) {
unsigned char featCode[2];
bool volIsCutoff=false;
@ -2666,6 +2741,8 @@ DivDataErrors DivInstrument::readInsDataNew(SafeReader& reader, short version, b
readFeatureX1(reader,version);
} else if (memcmp(featCode,"NE",2)==0) { // NES (DPCM)
readFeatureNE(reader,version);
} else if (memcmp(featCode,"EF",2)==0) { // ESFM
readFeatureEF(reader,version);
} else {
if (song==NULL && (memcmp(featCode,"SL",2)==0 || (memcmp(featCode,"WL",2)==0))) {
// nothing

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -85,6 +85,7 @@ enum DivInstrumentType: unsigned short {
DIV_INS_TED=52,
DIV_INS_C140=53,
DIV_INS_C219=54,
DIV_INS_ESFM=55,
DIV_INS_MAX,
DIV_INS_NULL
};
@ -771,6 +772,56 @@ struct DivInstrumentSNES {
d2(0) {}
};
// ESFM operator structure:
// - DELAY, OUT, MOD, L, R, NOISE
// - Virtual: CT, DT, FIXED
// - In FM struct: AM, DAM, AR, DR, MULT, RR, SL, TL
// - In FM struct: KSL, VIB, DVB, WS, SUS, KSR
// - Not in struct: FNUML, FNUMH, BLOCK
struct DivInstrumentESFM {
bool operator==(const DivInstrumentESFM& other);
bool operator!=(const DivInstrumentESFM& other) {
return !(*this==other);
}
// Only works on OP4, so putting it outside the Operator struct instead
unsigned char noise;
struct Operator {
unsigned char delay, outLvl, modIn, left, right, fixed;
signed char ct, dt;
bool operator==(const Operator& other);
bool operator!=(const Operator& other) {
return !(*this==other);
}
Operator():
delay(0),
outLvl(0),
modIn(0),
left(1),
right(1),
fixed(0),
ct(0),
dt(0) {}
} op[4];
DivInstrumentESFM():
noise(0)
{
op[0].modIn=4;
op[0].outLvl=0;
op[1].modIn=7;
op[1].outLvl=0;
op[2].modIn=7;
op[2].outLvl=0;
op[3].modIn=7;
op[3].outLvl=7;
}
};
struct DivInstrument {
String name;
DivInstrumentType type;
@ -787,6 +838,7 @@ struct DivInstrument {
DivInstrumentSoundUnit su;
DivInstrumentES5506 es5506;
DivInstrumentSNES snes;
DivInstrumentESFM esfm;
/**
* these are internal functions.
@ -811,6 +863,7 @@ struct DivInstrument {
void writeFeatureES(SafeWriter* w);
void writeFeatureX1(SafeWriter* w);
void writeFeatureNE(SafeWriter* w);
void writeFeatureEF(SafeWriter* w);
void readFeatureNA(SafeReader& reader, short version);
void readFeatureFM(SafeReader& reader, short version);
@ -831,6 +884,7 @@ struct DivInstrument {
void readFeatureES(SafeReader& reader, short version);
void readFeatureX1(SafeReader& reader, short version);
void readFeatureNE(SafeReader& reader, short version);
void readFeatureEF(SafeReader& reader, short version);
DivDataErrors readInsDataOld(SafeReader& reader, short version);
DivDataErrors readInsDataNew(SafeReader& reader, short version, bool fui, DivSong* song);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -245,6 +245,81 @@ void DivMacroInt::mask(unsigned char id, bool enabled) {
#undef CONSIDER_OP
#undef CONSIDER
#define CONSIDER(x,y,z) \
case z: \
macroState=&x; \
macro=&ins->std.y; \
break;
#define CONSIDER_OP(oi,o) \
CONSIDER(op[oi].am,opMacros[oi].amMacro,0+o) \
CONSIDER(op[oi].ar,opMacros[oi].arMacro,1+o) \
CONSIDER(op[oi].dr,opMacros[oi].drMacro,2+o) \
CONSIDER(op[oi].mult,opMacros[oi].multMacro,3+o) \
CONSIDER(op[oi].rr,opMacros[oi].rrMacro,4+o) \
CONSIDER(op[oi].sl,opMacros[oi].slMacro,5+o) \
CONSIDER(op[oi].tl,opMacros[oi].tlMacro,6+o) \
CONSIDER(op[oi].dt2,opMacros[oi].dt2Macro,7+o) \
CONSIDER(op[oi].rs,opMacros[oi].rsMacro,8+o) \
CONSIDER(op[oi].dt,opMacros[oi].dtMacro,9+o) \
CONSIDER(op[oi].d2r,opMacros[oi].d2rMacro,10+o) \
CONSIDER(op[oi].ssg,opMacros[oi].ssgMacro,11+o) \
CONSIDER(op[oi].dam,opMacros[oi].damMacro,12+o) \
CONSIDER(op[oi].dvb,opMacros[oi].dvbMacro,13+o) \
CONSIDER(op[oi].egt,opMacros[oi].egtMacro,14+o) \
CONSIDER(op[oi].ksl,opMacros[oi].kslMacro,15+o) \
CONSIDER(op[oi].sus,opMacros[oi].susMacro,16+o) \
CONSIDER(op[oi].vib,opMacros[oi].vibMacro,17+o) \
CONSIDER(op[oi].ws,opMacros[oi].wsMacro,18+o) \
CONSIDER(op[oi].ksr,opMacros[oi].ksrMacro,19+o)
void DivMacroInt::restart(unsigned char id) {
DivMacroStruct* macroState=NULL;
DivInstrumentMacro* macro=NULL;
if (e==NULL) return;
if (ins==NULL) return;
switch (id) {
CONSIDER(vol,volMacro,0)
CONSIDER(arp,arpMacro,1)
CONSIDER(duty,dutyMacro,2)
CONSIDER(wave,waveMacro,3)
CONSIDER(pitch,pitchMacro,4)
CONSIDER(ex1,ex1Macro,5)
CONSIDER(ex2,ex2Macro,6)
CONSIDER(ex3,ex3Macro,7)
CONSIDER(alg,algMacro,8)
CONSIDER(fb,fbMacro,9)
CONSIDER(fms,fmsMacro,10)
CONSIDER(ams,amsMacro,11)
CONSIDER(panL,panLMacro,12)
CONSIDER(panR,panRMacro,13)
CONSIDER(phaseReset,phaseResetMacro,14)
CONSIDER(ex4,ex4Macro,15)
CONSIDER(ex5,ex5Macro,16)
CONSIDER(ex6,ex6Macro,17)
CONSIDER(ex7,ex7Macro,18)
CONSIDER(ex8,ex8Macro,19)
CONSIDER_OP(0,0x20)
CONSIDER_OP(2,0x40)
CONSIDER_OP(1,0x60)
CONSIDER_OP(3,0x80)
}
if (macroState==NULL || macro==NULL) return;
if (macro->len<=0) return;
if (macroState->masked) return;
macroState->init();
macroState->prepare(*macro,e);
}
#undef CONSIDER_OP
#undef CONSIDER
void DivMacroInt::release() {
released=true;
}

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -119,6 +119,11 @@ class DivMacroInt {
*/
void release();
/**
* restart macro.
*/
void restart(unsigned char id);
/**
* trigger next macro tick.
*/

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -102,15 +102,19 @@ bool DivDispatch::isVolGlobal() {
return false;
}
int DivDispatch::mapVelocity(int ch, unsigned char vel) {
int DivDispatch::mapVelocity(int ch, float vel) {
const int volMax=MAX(1,dispatch(DivCommand(DIV_CMD_GET_VOLMAX,MAX(ch,0))));
return (vel*volMax)/127;
return round(vel*volMax);
}
int DivDispatch::getPortaFloor(int ch) {
return 0x00;
}
bool DivDispatch::getLegacyAlwaysSetVolume() {
return true;
}
float DivDispatch::getPostAmp() {
return 1.0f;
}

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -721,8 +721,8 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -783,8 +783,8 @@ int DivPlatformArcade::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
case DIV_CMD_GET_VOLMAX:
return 127;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -651,8 +651,8 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
case DIV_CMD_GET_VOLMAX:
return 15;
@ -719,6 +719,10 @@ DivDispatchOscBuffer* DivPlatformAY8910::getOscBuffer(int ch) {
return oscBuf[ch];
}
int DivPlatformAY8910::mapVelocity(int ch, float vel) {
return round(15.0*pow(vel,0.33));
}
unsigned char* DivPlatformAY8910::getRegisterPool() {
return regPool;
}
@ -775,6 +779,10 @@ bool DivPlatformAY8910::keyOffAffectsArp(int ch) {
return true;
}
bool DivPlatformAY8910::getLegacyAlwaysSetVolume() {
return false;
}
void DivPlatformAY8910::notifyInsDeletion(void* ins) {
for (int i=0; i<3; i++) {
chan[i].std.notifyInsDeletion((DivInstrument*)ins);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -131,6 +131,7 @@ class DivPlatformAY8910: public DivDispatch {
int dispatch(DivCommand c);
void* getChanState(int chan);
DivDispatchOscBuffer* getOscBuffer(int chan);
int mapVelocity(int ch, float vel);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void flushWrites();
@ -143,6 +144,7 @@ class DivPlatformAY8910: public DivDispatch {
bool keyOffAffectsArp(int ch);
DivMacroInt* getChanMacroInt(int ch);
DivSamplePos getSamplePos(int ch);
bool getLegacyAlwaysSetVolume();
bool getDCOffRequired();
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -653,8 +653,8 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
case DIV_CMD_GET_VOLMAX:
return 31;
@ -718,6 +718,10 @@ DivDispatchOscBuffer* DivPlatformAY8930::getOscBuffer(int ch) {
return oscBuf[ch];
}
int DivPlatformAY8930::mapVelocity(int ch, float vel) {
return round(31.0*pow(vel,0.22));
}
unsigned char* DivPlatformAY8930::getRegisterPool() {
return regPool;
}
@ -774,6 +778,10 @@ bool DivPlatformAY8930::keyOffAffectsArp(int ch) {
return true;
}
bool DivPlatformAY8930::getLegacyAlwaysSetVolume() {
return false;
}
void DivPlatformAY8930::notifyInsDeletion(void* ins) {
for (int i=0; i<3; i++) {
chan[i].std.notifyInsDeletion((DivInstrument*)ins);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -132,6 +132,7 @@ class DivPlatformAY8930: public DivDispatch {
int dispatch(DivCommand c);
void* getChanState(int chan);
DivDispatchOscBuffer* getOscBuffer(int chan);
int mapVelocity(int ch, float vel);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset();
@ -143,6 +144,7 @@ class DivPlatformAY8930: public DivDispatch {
bool keyOffAffectsArp(int ch);
DivMacroInt* getChanMacroInt(int ch);
DivSamplePos getSamplePos(int ch);
bool getLegacyAlwaysSetVolume();
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -246,8 +246,8 @@ int DivPlatformBubSysWSG::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -441,8 +441,8 @@ int DivPlatformC140::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -536,8 +536,8 @@ int DivPlatformC64::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -1022,8 +1022,8 @@ int DivPlatformES5506::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

1077
src/engine/platform/esfm.cpp Normal file

File diff suppressed because it is too large Load diff

207
src/engine/platform/esfm.h Normal file
View file

@ -0,0 +1,207 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "../dispatch.h"
#include "../../fixedQueue.h"
#include "../../../extern/ESFMu/esfm.h"
// ESFM register address space technically spans 0x800 (2048) bytes,
// but we only need the first 0x254 (596) during normal use.
// Rounding it up to 0x400 bytes, the nearest power of 2.
#define ESFM_REG_POOL_SIZE 0x400
class DivPlatformESFM: public DivDispatch {
struct Channel: public SharedChannel<int> {
struct {
DivInstrumentFM fm;
DivInstrumentESFM esfm;
} state;
unsigned char freqL[4], freqH[4];
bool hardReset;
unsigned char globalPan;
int macroVolMul;
struct {
int baseNoteOverride;
bool fixedArp;
int arpOff;
int pitch2;
bool hasOpArp;
bool hasOpPitch;
} opsState[4];
void handleArpFmOp(int offset=0, int o=0) {
DivMacroInt::IntOp& m=this->std.op[o];
if (m.ssg.had) {
opsState[o].hasOpArp=true;
if (m.ssg.val<0) {
if (!(m.ssg.val&0x40000000)) {
opsState[o].baseNoteOverride=(m.ssg.val|0x40000000)+offset;
opsState[o].fixedArp=true;
} else {
opsState[o].arpOff=m.ssg.val;
opsState[o].fixedArp=false;
}
} else {
if (m.ssg.val&0x40000000) {
opsState[o].baseNoteOverride=(m.ssg.val&(~0x40000000))+offset;
opsState[o].fixedArp=true;
} else {
opsState[o].arpOff=m.ssg.val;
opsState[o].fixedArp=false;
}
}
freqChanged=true;
}
else
{
opsState[o].hasOpArp=false;
}
}
void handlePitchFmOp(int o)
{
DivMacroInt::IntOp& m=this->std.op[o];
if (m.dt.had) {
opsState[o].hasOpPitch=true;
if (m.dt.mode) {
opsState[o].pitch2+=m.dt.val;
CLAMP_VAR(opsState[o].pitch2,-131071,131071);
} else {
opsState[o].pitch2=m.dt.val;
}
this->freqChanged=true;
}
else
{
opsState[o].hasOpPitch=false;
}
}
Channel():
SharedChannel<int>(0),
freqL{0, 0, 0, 0},
freqH{0, 0, 0, 0},
hardReset(false),
globalPan(3),
macroVolMul(64) {
memset(opsState, 0, sizeof(opsState));
}
};
Channel chan[18];
DivDispatchOscBuffer* oscBuf[18];
bool isMuted[18];
struct QueuedWrite {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
FixedQueue<QueuedWrite,2048> writes;
esfm_chip chip;
unsigned char regPool[ESFM_REG_POOL_SIZE];
short oldWrites[ESFM_REG_POOL_SIZE];
short pendingWrites[ESFM_REG_POOL_SIZE];
int octave(int freq);
int toFreq(int freq);
void commitState(int ch, DivInstrument* ins);
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
inline void rWrite(unsigned short a, short v) {
if (!skipRegisterWrites && a<ESFM_REG_POOL_SIZE) {
pendingWrites[a]=v;
}
}
inline void immWrite(unsigned short a, unsigned char v) {
if (!skipRegisterWrites) {
writes.push_back(QueuedWrite(a,v));
if (dumpWrites) {
addWrite(a,v);
}
}
}
/**
* ESFM doesn't have predef algorithms, so a custom KVS heuristic for auto mode is needed.
* This is a bit too complex for a macro.
* The heuristic for auto mode is expressed as:
* true for an operator o
* where op[o].outLvl = 7,
* or op[o].outLvl > 0 and o == 3 (last operator),
* or op[o].outLvl > 0 and (op[o].outLvl - op[o + 1].modIn) >= 2,
* or op[o].outLvl > 0 and op[o + 1].modIn == 0.
*/
inline bool KVS_ES(int c, int o) {
if (c<0 || c>=18 || o<0 || o>=4) return false;
if (chan[c].state.fm.op[o].kvs==1) return true;
if (chan[c].state.fm.op[o].kvs==2) {
if (chan[c].state.esfm.op[o].outLvl==7) return true;
else if (chan[c].state.esfm.op[o].outLvl>0) {
if (o==3) return true;
else if ((chan[c].state.esfm.op[o].outLvl-chan[c].state.esfm.op[o+1].modIn)>=2) {
return true;
}
else if (chan[c].state.esfm.op[o+1].modIn==0) {
return true;
}
}
}
return false;
}
public:
void acquire(short** buf, size_t len);
int dispatch(DivCommand c);
void* getChanState(int chan);
DivMacroInt* getChanMacroInt(int ch);
unsigned short getPan(int ch);
DivDispatchOscBuffer* getOscBuffer(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
int getOutputCount();
void reset();
void forceIns();
void tick(bool sysTick=true);
void muteChannel(int ch, bool mute);
bool keyOffAffectsArp(int ch);
bool keyOffAffectsPorta(int ch);
bool getLegacyAlwaysSetVolume();
void toggleRegisterDump(bool enable);
void notifyInsChange(int ins);
void notifyInsDeletion(void* ins);
int mapVelocity(int ch, float vel);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
void setFlags(const DivConfig& flags);
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
~DivPlatformESFM();
};

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -387,8 +387,8 @@ int DivPlatformFDS::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -186,6 +186,17 @@ class DivPlatformOPN: public DivPlatformFMBase {
void setCombo(bool combo) {
useCombo=combo;
}
virtual int mapVelocity(int ch, float vel) {
if (ch==csmChan) return vel*127.0;
if (ch==adpcmBChanOffs) return vel*255.0;
if (ch>=adpcmAChanOffs) {
if (vel==0) return 0;
if (vel>=1.0) return 31;
return CLAMP(round(32.0-(56.0-log2(vel*127.0)*8.0)),0,31);
}
if (ch>=psgChanOffs) return round(15.0*pow(vel,0.33));
return DivPlatformFMBase::mapVelocity(ch,vel);
}
};
#endif

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -121,6 +121,24 @@ class DivPlatformFMBase: public DivDispatch {
}
}
}
virtual int mapVelocity(int ch, float vel) {
// -0.75dB per step
// -6: 64: 8
// -12: 32: 16
// -18: 16: 24
// -24: 8: 32
// -30: 4: 40
// -36: 2: 48
// -42: 1: 56
if (vel==0) return 0;
if (vel>=1.0) return 127;
return CLAMP(round(128.0-(56.0-log2(vel*127.0)*8.0)),0,127);
}
bool getLegacyAlwaysSetVolume() {
return true;
}
friend void putDispatchChan(void*,int,int);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -311,8 +311,8 @@ int DivPlatformGA20::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -553,8 +553,8 @@ int DivPlatformGB::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -348,7 +348,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
}
}
if (i>=5 && chan[i].furnaceDac) {
if (i>=5 && chan[i].furnaceDac && chan[i].dacMode) {
if (NEW_ARP_STRAT) {
chan[i].handleArp();
} else if (chan[i].std.arp.had) {
@ -1183,8 +1183,8 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
case DIV_CMD_GET_VOLMAX:
return 127;
@ -1300,6 +1300,12 @@ DivDispatchOscBuffer* DivPlatformGenesis::getOscBuffer(int ch) {
return oscBuf[ch];
}
int DivPlatformGenesis::mapVelocity(int ch, float vel) {
if (ch==csmChan) return DivPlatformOPN::mapVelocity(ch,vel);
if (ch>5) return DivPlatformOPN::mapVelocity(5,vel);
return DivPlatformOPN::mapVelocity(ch,vel);
}
unsigned char* DivPlatformGenesis::getRegisterPool() {
return regPool;
}

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -112,6 +112,7 @@ class DivPlatformGenesis: public DivPlatformOPN {
virtual unsigned short getPan(int chan);
DivSamplePos getSamplePos(int ch);
DivDispatchOscBuffer* getOscBuffer(int chan);
virtual int mapVelocity(int ch, float vel);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset();

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -418,9 +418,6 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
opChan[ch].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
break;
case DIV_CMD_PRE_PORTA:
break;
default:
@ -818,6 +815,12 @@ DivDispatchOscBuffer* DivPlatformGenesisExt::getOscBuffer(int ch) {
return NULL;
}
int DivPlatformGenesisExt::mapVelocity(int ch, float vel) {
if (ch>=extChanOffs+4) return DivPlatformGenesis::mapVelocity(ch-3,vel);
if (ch>=extChanOffs) return DivPlatformGenesis::mapVelocity(extChanOffs,vel);
return DivPlatformGenesis::mapVelocity(ch,vel);
}
void DivPlatformGenesisExt::reset() {
DivPlatformGenesis::reset();

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -36,6 +36,7 @@ class DivPlatformGenesisExt: public DivPlatformGenesis {
DivMacroInt* getChanMacroInt(int ch);
unsigned short getPan(int chan);
DivDispatchOscBuffer* getOscBuffer(int chan);
int mapVelocity(int ch, float vel);
void reset();
void forceIns();
void tick(bool sysTick=true);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -395,8 +395,8 @@ int DivPlatformK007232::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -345,8 +345,8 @@ int DivPlatformK053260::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -353,8 +353,8 @@ int DivPlatformLynx::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;
@ -438,6 +438,10 @@ bool DivPlatformLynx::keyOffAffectsPorta(int ch) {
return true;
}
bool DivPlatformLynx::getLegacyAlwaysSetVolume() {
return false;
}
//int DivPlatformLynx::getPortaFloor(int ch) {
// return 12;
//}

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -84,6 +84,7 @@ class DivPlatformLynx: public DivDispatch {
int getOutputCount();
bool keyOffAffectsArp(int ch);
bool keyOffAffectsPorta(int ch);
bool getLegacyAlwaysSetVolume();
//int getPortaFloor(int ch);
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -327,8 +327,8 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -297,8 +297,8 @@ int DivPlatformMSM5232::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -268,8 +268,8 @@ int DivPlatformMSM6258::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
case DIV_CMD_GET_VOLMAX:
return 8;
@ -371,6 +371,10 @@ bool DivPlatformMSM6258::keyOffAffectsArp(int ch) {
return false;
}
bool DivPlatformMSM6258::getLegacyAlwaysSetVolume() {
return false;
}
void DivPlatformMSM6258::notifyInsChange(int ins) {
for (int i=0; i<1; i++) {
if (chan[i].ins==ins) {

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -75,6 +75,7 @@ class DivPlatformMSM6258: public DivDispatch {
void muteChannel(int ch, bool mute);
int getOutputCount();
bool keyOffAffectsArp(int ch);
bool getLegacyAlwaysSetVolume();
void notifyInsChange(int ins);
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -241,8 +241,8 @@ int DivPlatformMSM6295::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
case DIV_CMD_GET_VOLMAX:
return 8;
@ -330,6 +330,10 @@ bool DivPlatformMSM6295::keyOffAffectsArp(int ch) {
return false;
}
bool DivPlatformMSM6295::getLegacyAlwaysSetVolume() {
return false;
}
float DivPlatformMSM6295::getPostAmp() {
return 3.0f;
}

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -87,6 +87,7 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf {
virtual void tick(bool sysTick=true) override;
virtual void muteChannel(int ch, bool mute) override;
virtual bool keyOffAffectsArp(int ch) override;
virtual bool getLegacyAlwaysSetVolume() override;
virtual float getPostAmp() override;
virtual void notifyInsChange(int ins) override;
virtual void notifyInsDeletion(void* ins) override;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -452,8 +452,8 @@ int DivPlatformN163::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -199,7 +199,7 @@ void DivPlatformNamcoWSG::tick(bool sysTick) {
for (int i=0; i<chans; i++) {
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=((chan[i].vol&15)*MIN(15,chan[i].std.vol.val))>>4;
chan[i].outVol=VOL_SCALE_LINEAR(chan[i].vol,chan[i].std.vol.val,15);
}
if (chan[i].std.duty.had) {
chan[i].noise=chan[i].std.duty.val;
@ -445,8 +445,8 @@ int DivPlatformNamcoWSG::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -659,8 +659,8 @@ int DivPlatformNES::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -1343,7 +1343,7 @@ void DivPlatformOPL::commitState(int ch, DivInstrument* ins) {
int DivPlatformOPL::dispatch(DivCommand c) {
if (c.chan>=totalChans && c.chan!=adpcmChan) return 0;
// ineffective in 4-op mode
if (oplType==3 && c.chan!=adpcmChan && c.chan<14 && (c.chan&1) && c.cmd!=DIV_CMD_GET_VOLMAX && c.cmd!=DIV_ALWAYS_SET_VOLUME) {
if (oplType==3 && c.chan!=adpcmChan && c.chan<14 && (c.chan&1) && c.cmd!=DIV_CMD_GET_VOLMAX) {
if (chan[c.chan-1].fourOp) return 0;
}
switch (c.cmd) {
@ -1970,8 +1970,8 @@ int DivPlatformOPL::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
case DIV_CMD_GET_VOLMAX:
if (c.chan==adpcmChan) return 255;
@ -2104,6 +2104,21 @@ DivDispatchOscBuffer* DivPlatformOPL::getOscBuffer(int ch) {
return oscBuf[ch];
}
int DivPlatformOPL::mapVelocity(int ch, float vel) {
if (ch==adpcmChan) return vel*255.0;
// -0.75dB per step
// -6: 64: 8
// -12: 32: 16
// -18: 16: 24
// -24: 8: 32
// -30: 4: 40
// -36: 2: 48
// -42: 1: 56
if (vel==0) return 0;
if (vel>=1.0) return 63;
return CLAMP(round(64.0-(56.0-log2(vel*127.0)*8.0)),0,63);
}
unsigned char* DivPlatformOPL::getRegisterPool() {
return regPool;
}
@ -2264,6 +2279,10 @@ bool DivPlatformOPL::keyOffAffectsPorta(int ch) {
return false;
}
bool DivPlatformOPL::getLegacyAlwaysSetVolume() {
return false;
}
void DivPlatformOPL::notifyInsChange(int ins) {
for (int i=0; i<totalChans; i++) {
if (chan[i].ins==ins) {

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -150,6 +150,7 @@ class DivPlatformOPL: public DivDispatch {
unsigned short getPan(int chan);
DivChannelPair getPaired(int chan);
DivDispatchOscBuffer* getOscBuffer(int chan);
int mapVelocity(int ch, float vel);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset();
@ -161,6 +162,7 @@ class DivPlatformOPL: public DivDispatch {
void setOPLType(int type, bool drums);
bool keyOffAffectsArp(int ch);
bool keyOffAffectsPorta(int ch);
bool getLegacyAlwaysSetVolume();
void toggleRegisterDump(bool enable);
void setFlags(const DivConfig& flags);
void notifyInsChange(int ins);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -853,8 +853,8 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
case DIV_CMD_GET_VOLMAX:
return 15;
@ -962,6 +962,13 @@ DivDispatchOscBuffer* DivPlatformOPLL::getOscBuffer(int ch) {
return oscBuf[ch];
}
int DivPlatformOPLL::mapVelocity(int ch, float vel) {
// -3dB per step
if (vel==0) return 0;
if (vel>=1.0) return 15;
return CLAMP(round(16.0-(14.0-log2(vel*127.0)*2.0)),0,15);
}
unsigned char* DivPlatformOPLL::getRegisterPool() {
return regPool;
}
@ -1036,6 +1043,10 @@ bool DivPlatformOPLL::keyOffAffectsPorta(int ch) {
return false;
}
bool DivPlatformOPLL::getLegacyAlwaysSetVolume() {
return false;
}
void DivPlatformOPLL::notifyInsChange(int ins) {
for (int i=0; i<11; i++) {
if (chan[i].ins==ins) {

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -95,6 +95,7 @@ class DivPlatformOPLL: public DivDispatch {
void* getChanState(int chan);
DivMacroInt* getChanMacroInt(int ch);
DivDispatchOscBuffer* getOscBuffer(int chan);
int mapVelocity(int ch, float vel);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset();
@ -104,6 +105,7 @@ class DivPlatformOPLL: public DivDispatch {
void setYMFM(bool use);
bool keyOffAffectsArp(int ch);
bool keyOffAffectsPorta(int ch);
bool getLegacyAlwaysSetVolume();
float getPostAmp();
void toggleRegisterDump(bool enable);
void setVRC7(bool vrc);

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -474,8 +474,8 @@ int DivPlatformPCE::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;
@ -539,6 +539,10 @@ DivDispatchOscBuffer* DivPlatformPCE::getOscBuffer(int ch) {
return oscBuf[ch];
}
int DivPlatformPCE::mapVelocity(int ch, float vel) {
return round(31.0*pow(vel,0.22));
}
unsigned char* DivPlatformPCE::getRegisterPool() {
return regPool;
}

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -86,6 +86,7 @@ class DivPlatformPCE: public DivDispatch {
DivChannelModeHints getModeHints(int chan);
DivSamplePos getSamplePos(int ch);
DivDispatchOscBuffer* getOscBuffer(int chan);
int mapVelocity(int ch, float vel);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset();

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -452,8 +452,8 @@ int DivPlatformPCMDAC::dispatch(DivCommand c) {
case DIV_CMD_MACRO_ON:
chan[c.chan].std.mask(c.value,false);
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
case DIV_CMD_MACRO_RESTART:
chan[c.chan].std.restart(c.value);
break;
default:
break;

View file

@ -1,6 +1,6 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
* Copyright (C) 2021-2024 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

Some files were not shown because too many files have changed in this diff Show more