Merge branch 'master' into preset1

This commit is contained in:
cam900 2022-06-07 13:04:17 +09:00
commit dd93f6d18e
25 changed files with 89 additions and 104 deletions

View File

@ -243,7 +243,7 @@ jobs:
cp -v ../LICENSE LICENSE.txt
cp -v ../README.md README.txt
cp -vr ../{papers,demos} ../${binPath}/furnace.exe ./
cp -vr ../{papers,demos,instruments} ../${binPath}/furnace.exe ./
popd

View File

@ -633,6 +633,7 @@ if (NOT ANDROID OR TERMUX)
install(DIRECTORY papers DESTINATION ${CMAKE_INSTALL_DOCDIR})
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/furnace)
install(DIRECTORY demos DESTINATION ${CMAKE_INSTALL_DATADIR}/furnace)
install(DIRECTORY instruments DESTINATION ${CMAKE_INSTALL_DATADIR}/furnace)
foreach(num 16 32 64 128 256 512)
set(res ${num}x${num})
install(FILES res/icon.iconset/icon_${res}.png RENAME furnace.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${res}/apps)

Binary file not shown.

BIN
instruments/FM/default.fui Normal file

Binary file not shown.

BIN
instruments/OPL/key.fui Normal file

Binary file not shown.

Binary file not shown.

18
instruments/README.md Normal file
View File

@ -0,0 +1,18 @@
# instruments
a directory of ready-to-use instruments.
these are organized in the following categories:
- **FM**: FM instruments for OPN/OPM.
- **OPL**: FM instruments for OPL.
- **OPLL**: FM instruments for OPLL.
- **other**: instruments for any other system.
# submit instruments
you may submit your own instruments by creating a pull request or contacting me! the only guidelines are:
- any format Furnace is able to load is accepted.
- I (strongly) prefer original instruments.
thanks for your contribution!

Binary file not shown.

View File

@ -1,9 +1,11 @@
# Commodore 64
a home computer with a synthesizer-grade sound chip of which people took decades to master.
a home computer with a synthesizer-grade sound chip of which people took decades to master. Three oscillators with four selectable waveforms, ring modulation, oscillator sync, multimode filter, ADSR envelope...
very popular in Europe and mostly due to the demoscene, which stretched the machine's limbs to no end.
Two revisions do exist - 6581 (original chip) and 8580 (improved version with working waveform mixing and somewhat more consistent filter curves)
# effects
- `10xx`: change wave. the following values are accepted:

View File

@ -0,0 +1,13 @@
# Namco WSG | Namco C15 | Namco C30
a family of wavetable synth sound chips used by Namco in their arcade machines (Pacman and later). Waveforms are 4-bit, with 32-byte sample length.
Everything starts with Namco WSG, simple 3ch wavetable with no extra frills. C15 is much more advanced sound source with 8 channels. C30 adds stereo output and noise mode.
# effects
-`10xx`: change waveform
-`11xx`: toggle noise mode WARNING: only on C30

View File

@ -0,0 +1,9 @@
# OKI MSM6258 | OKI MSM6295
MSM6258 is a single-channel ADPCM sound source developed by OKI. It allows max sample rate of 15.6 kHz... with no variable pitch. Most prominent use of this chip was Sharp X68000 computer, where it was paired with Yamaha YM2151.
MSM6295 is an upgrade from 6258 - it provides 4 ADPCM channels, at max 32 kHz (still no variable pitch though). Between late 80s and late 90s, it was one of the most common, if not THE most common soundchip used in arcade machines (Capcom, Toaplan, Kaneko, Atari, Tecmo, the list can go on and on...)
# effects
- `20xx`: set chip output rate

View File

@ -0,0 +1,8 @@
# Ricoh RF5C68
YM2612's sidekick - poor man's SPC-700. 8ch PCM sample-based synthesizer used in Sega Mega CD, Fujitsu FM Towns and some of Sega's arcade machines. Supports up to 64 Kbytes of external PCM data.
# effects
none so far.

View File

@ -2,6 +2,8 @@
one of two chips that powered the Sega Genesis. It is a six-channel, four-operator FM synthesizer. Channel #6 can be turned into 8-bit PCM player.
For 0.6pre1, Furnace can now support advanced YM2612 features that [Fractal](https://gitlab.com/Natsumi/Fractal-Sound) sound driver adds: two software-mixed PCM channels (variable pitch, sample offsets, max 13.7 khz rate) and CSM - ch3 special mode feature that can be abused to produce rudimentary speech synthesis.
# effects
- `10xy`: set LFO parameters.
@ -64,4 +66,4 @@ one of two chips that powered the Sega Genesis. It is a six-channel, four-operat
- `5Cxx`: set D2R/SR of operator 1.
- `5Dxx`: set D2R/SR of operator 2.
- `5Exx`: set D2R/SR of operator 3.
- `5Fxx`: set D2R/SR of operator 4.
- `5Fxx`: set D2R/SR of operator 4.

View File

@ -0,0 +1,7 @@
# Yamaha YMZ280B (PCMD8)
8ch PCM/ADPCM sample-based synthesizer designed for use with arcade machines. Lived throughout mid to late 90s. It has 16-level stereo panning, up to 16-bit PCM and up to 16Mbytes of external PCM data.
# effects
none so far.

View File

@ -0,0 +1,10 @@
# ZX Spectrum Speaker
Rather than having a dedicated sound synthesizer, early ZX Spectrum models had one piezo beeper, controlled by Z80 CPU and ULA chip. It's capabilities should be on par with an IBM PC speaker... right?
Not really - very soon talented programmers found out ways to output much more than one square wave channel. A lot of ZX beeper routines do exist, as of 0.6pre1 Furnace supports only one - Follin-like engine with 6 channels of narrow pulse wave and click drums.
# effects
- `12xx`: set pulse width
- `17xx`: trigger overlay drums.

View File

@ -29,8 +29,9 @@ cp ../../win32build/furnace.exe . || exit 1
cp ../../README.md README.txt || exit 1
cp -r ../../papers papers || exit 1
cp -r ../../demos demos || exit 1
cp -r ../../instruments instruments || exit 1
zip -r furnace.zip LICENSE.txt furnace.exe README.txt papers demos
zip -r furnace.zip LICENSE.txt furnace.exe README.txt papers demos instruments
furName=$(git describe --tags | sed "s/v0/0/")

View File

@ -29,8 +29,9 @@ cp ../../winbuild/furnace.exe . || exit 1
cp ../../README.md README.txt || exit 1
cp -r ../../papers papers || exit 1
cp -r ../../demos demos || exit 1
cp -r ../../instruments instruments || exit 1
zip -r furnace.zip LICENSE.txt furnace.exe README.txt papers demos
zip -r furnace.zip LICENSE.txt furnace.exe README.txt papers demos instruments
furName=$(git describe --tags | sed "s/v0/0/")

View File

@ -312,10 +312,7 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
dispatch=new DivPlatformTX81Z;
break;
case DIV_SYSTEM_SAA1099: {
int saaCore=eng->getConfInt("saaCore",1);
if (saaCore<0 || saaCore>2) saaCore=0;
dispatch=new DivPlatformSAA1099;
((DivPlatformSAA1099*)dispatch)->setCore((DivSAACores)saaCore);
break;
}
case DIV_SYSTEM_PCSPKR:

View File

@ -71,28 +71,6 @@ const char* DivPlatformSAA1099::getEffectName(unsigned char effect) {
return NULL;
}
void DivPlatformSAA1099::acquire_mame(short* bufL, short* bufR, size_t start, size_t len) {
if (saaBufLen<len) {
saaBufLen=len;
for (int i=0; i<2; i++) {
delete[] saaBuf[i];
saaBuf[i]=new short[saaBufLen];
}
}
while (!writes.empty()) {
QueuedWrite w=writes.front();
saa.control_w(w.addr);
saa.data_w(w.val);
regPool[w.addr&0x1f]=w.val;
writes.pop();
}
saa.sound_stream_update(saaBuf,len,oscBuf);
for (size_t i=0; i<len; i++) {
bufL[i+start]=saaBuf[0][i];
bufR[i+start]=saaBuf[1][i];
}
}
void DivPlatformSAA1099::acquire_saaSound(short* bufL, short* bufR, size_t start, size_t len) {
if (saaBufLen<len*2) {
saaBufLen=len*2;
@ -115,17 +93,7 @@ void DivPlatformSAA1099::acquire_saaSound(short* bufL, short* bufR, size_t start
}
void DivPlatformSAA1099::acquire(short* bufL, short* bufR, size_t start, size_t len) {
switch (core) {
case DIV_SAA_CORE_MAME:
acquire_mame(bufL,bufR,start,len);
break;
case DIV_SAA_CORE_SAASOUND:
acquire_saaSound(bufL,bufR,start,len);
break;
case DIV_SAA_CORE_E:
//acquire_e(bufL,bufR,start,len);
break;
}
acquire_saaSound(bufL,bufR,start,len);
}
inline unsigned char applyPan(unsigned char vol, unsigned char pan) {
@ -420,16 +388,7 @@ int DivPlatformSAA1099::getRegisterPoolSize() {
void DivPlatformSAA1099::reset() {
while (!writes.empty()) writes.pop();
memset(regPool,0,32);
switch (core) {
case DIV_SAA_CORE_MAME:
saa=saa1099_device();
break;
case DIV_SAA_CORE_SAASOUND:
saa_saaSound->Clear();
break;
case DIV_SAA_CORE_E:
break;
}
saa_saaSound->Clear();
for (int i=0; i<6; i++) {
chan[i]=DivPlatformSAA1099::Channel();
chan[i].std.setEngine(parent);
@ -500,16 +459,8 @@ void DivPlatformSAA1099::setFlags(unsigned int flags) {
oscBuf[i]->rate=rate;
}
switch (core) {
case DIV_SAA_CORE_MAME:
break;
case DIV_SAA_CORE_SAASOUND:
saa_saaSound->SetClockRate(chipClock);
saa_saaSound->SetSampleRate(rate);
break;
case DIV_SAA_CORE_E:
break;
}
saa_saaSound->SetClockRate(chipClock);
saa_saaSound->SetSampleRate(rate);
}
void DivPlatformSAA1099::poke(unsigned int addr, unsigned short val) {
@ -520,10 +471,6 @@ void DivPlatformSAA1099::poke(std::vector<DivRegWrite>& wlist) {
for (DivRegWrite& i: wlist) rWrite(i.addr,i.val);
}
void DivPlatformSAA1099::setCore(DivSAACores c) {
core=c;
}
int DivPlatformSAA1099::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
parent=p;
dumpWrites=false;
@ -533,11 +480,9 @@ int DivPlatformSAA1099::init(DivEngine* p, int channels, int sugRate, unsigned i
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
}
if (core==DIV_SAA_CORE_SAASOUND) {
saa_saaSound=CreateCSAASound();
saa_saaSound->SetOversample(1);
saa_saaSound->SetSoundParameters(SAAP_NOFILTER|SAAP_16BIT|SAAP_STEREO);
}
saa_saaSound=CreateCSAASound();
saa_saaSound->SetOversample(1);
saa_saaSound->SetSoundParameters(SAAP_NOFILTER|SAAP_16BIT|SAAP_STEREO);
setFlags(flags);
saaBufLen=65536;
for (int i=0; i<2; i++) saaBuf[i]=new short[saaBufLen];

View File

@ -22,15 +22,8 @@
#include "../dispatch.h"
#include "../macroInt.h"
#include <queue>
#include "sound/saa1099.h"
#include "../../../extern/SAASound/src/SAASound.h"
enum DivSAACores {
DIV_SAA_CORE_MAME=0,
DIV_SAA_CORE_SAASOUND,
DIV_SAA_CORE_E
};
class DivPlatformSAA1099: public DivDispatch {
protected:
struct Channel {
@ -58,8 +51,6 @@ class DivPlatformSAA1099: public DivDispatch {
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
DivSAACores core;
saa1099_device saa;
CSAASound* saa_saaSound;
unsigned char regPool[32];
unsigned char lastBusy;
@ -83,9 +74,7 @@ class DivPlatformSAA1099: public DivDispatch {
unsigned char saaNoise[2];
friend void putDispatchChan(void*,int,int);
void acquire_e(short* bufL, short* bufR, size_t start, size_t len);
void acquire_saaSound(short* bufL, short* bufR, size_t start, size_t len);
void acquire_mame(short* bufL, short* bufR, size_t start, size_t len);
public:
void acquire(short* bufL, short* bufR, size_t start, size_t len);
@ -99,7 +88,6 @@ class DivPlatformSAA1099: public DivDispatch {
void forceIns();
void tick(bool sysTick=true);
void muteChannel(int ch, bool mute);
void setCore(DivSAACores core);
void setFlags(unsigned int flags);
bool isStereo();
int getPortaFloor(int ch);

View File

@ -190,8 +190,8 @@ void FurnaceGUI::drawChanOsc() {
needlePos-=alignment;
*/
String cPhase=fmt::sprintf("%d cphase: %f",point,phase);
dl->AddText(inRect.Min,0xffffffff,cPhase.c_str());
//String cPhase=fmt::sprintf("%d cphase: %f",point,phase);
//dl->AddText(inRect.Min,0xffffffff,cPhase.c_str());
needlePos-=displaySize;
for (unsigned short i=0; i<512; i++) {

View File

@ -12,7 +12,7 @@ void FurnaceGUI::drawFindReplace() {
if (!findOpen) return;
ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
if (ImGui::Begin("Find/Replace",&findOpen,globalWinFlags)) {
ImGui::Text("What am I gonna do with you?");
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_FIND;
ImGui::End();

View File

@ -1900,11 +1900,6 @@ void FurnaceGUI::editOptions(bool topMenu) {
char id[4096];
editOptsVisible=true;
if (topMenu) {
ImGui::Text("...");
ImGui::Separator();
}
if (ImGui::MenuItem("cut",BIND_FOR(GUI_ACTION_PAT_CUT))) doCopy(true);
if (ImGui::MenuItem("copy",BIND_FOR(GUI_ACTION_PAT_COPY))) doCopy(false);
if (ImGui::MenuItem("paste",BIND_FOR(GUI_ACTION_PAT_PASTE))) doPaste();
@ -2946,6 +2941,8 @@ bool FurnaceGUI::loop() {
ImGui::EndMenu();
}
if (ImGui::BeginMenu("edit")) {
ImGui::Text("...");
ImGui::Separator();
if (ImGui::MenuItem("undo",BIND_FOR(GUI_ACTION_UNDO))) doUndo();
if (ImGui::MenuItem("redo",BIND_FOR(GUI_ACTION_REDO))) doRedo();
ImGui::Separator();

View File

@ -873,7 +873,6 @@ class FurnaceGUI {
int arcadeCore;
int ym2612Core;
int snCore;
int saaCore;
int nesCore;
int fdsCore;
int pcSpeakerOutMethod;
@ -974,7 +973,6 @@ class FurnaceGUI {
arcadeCore(0),
ym2612Core(0),
snCore(0),
saaCore(1),
nesCore(0),
fdsCore(0),
pcSpeakerOutMethod(0),

View File

@ -84,11 +84,6 @@ const char* snCores[]={
"Nuked-PSG Mod"
};
const char* saaCores[]={
"MAME",
"SAASound"
};
const char* nesCores[]={
"puNES",
"NSFplay"
@ -899,10 +894,6 @@ void FurnaceGUI::drawSettings() {
ImGui::SameLine();
ImGui::Combo("##SNCore",&settings.snCore,snCores,2);
ImGui::Text("SAA1099 core");
ImGui::SameLine();
ImGui::Combo("##SAACore",&settings.saaCore,saaCores,2);
ImGui::Text("NES core");
ImGui::SameLine();
ImGui::Combo("##NESCore",&settings.nesCore,nesCores,2);
@ -1954,7 +1945,6 @@ void FurnaceGUI::syncSettings() {
settings.arcadeCore=e->getConfInt("arcadeCore",0);
settings.ym2612Core=e->getConfInt("ym2612Core",0);
settings.snCore=e->getConfInt("snCore",0);
settings.saaCore=e->getConfInt("saaCore",1);
settings.nesCore=e->getConfInt("nesCore",0);
settings.fdsCore=e->getConfInt("fdsCore",0);
settings.pcSpeakerOutMethod=e->getConfInt("pcSpeakerOutMethod",0);
@ -2048,7 +2038,6 @@ void FurnaceGUI::syncSettings() {
clampSetting(settings.arcadeCore,0,1);
clampSetting(settings.ym2612Core,0,1);
clampSetting(settings.snCore,0,1);
clampSetting(settings.saaCore,0,1);
clampSetting(settings.nesCore,0,1);
clampSetting(settings.fdsCore,0,1);
clampSetting(settings.pcSpeakerOutMethod,0,4);
@ -2171,7 +2160,6 @@ void FurnaceGUI::commitSettings() {
e->setConf("arcadeCore",settings.arcadeCore);
e->setConf("ym2612Core",settings.ym2612Core);
e->setConf("snCore",settings.snCore);
e->setConf("saaCore",settings.saaCore);
e->setConf("nesCore",settings.nesCore);
e->setConf("fdsCore",settings.fdsCore);
e->setConf("pcSpeakerOutMethod",settings.pcSpeakerOutMethod);