Merge branch 'master' into preset1
This commit is contained in:
commit
dd93f6d18e
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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.
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
|
@ -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.
|
|
@ -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/")
|
||||
|
||||
|
|
|
@ -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/")
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
setFlags(flags);
|
||||
saaBufLen=65536;
|
||||
for (int i=0; i<2; i++) saaBuf[i]=new short[saaBufLen];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue