diff --git a/doc/2-interface/README.md b/doc/2-interface/README.md index 2ff1ebfc9..6de22e929 100644 --- a/doc/2-interface/README.md +++ b/doc/2-interface/README.md @@ -36,6 +36,7 @@ advanced topics: other topics: +- [settings](../2-interface/settings.md) - [UI components](components.md) - [global keyboard shortcuts](keyboard.md) - [basic mode](basic-mode.md) diff --git a/doc/2-interface/menu-bar.md b/doc/2-interface/menu-bar.md index 8fac9e659..0027d6da7 100644 --- a/doc/2-interface/menu-bar.md +++ b/doc/2-interface/menu-bar.md @@ -183,7 +183,7 @@ it's not really useful, unless you're a developer and want to use a command stre - **basic mode**: toggles [Basic Mode](basic-mode.md). - **visualizer**: toggles pattern view particle effects when the song plays. - **reset layout**: resets the workspace to its defaults. -- **settings...**: opens the Settings window. +- **settings...**: opens the Settings window. these are detailed in [settings.md]. # window diff --git a/doc/2-interface/settings.md b/doc/2-interface/settings.md new file mode 100644 index 000000000..06c21f1c9 --- /dev/null +++ b/doc/2-interface/settings.md @@ -0,0 +1,387 @@ +# settings + +settings are saved when clicking the **OK** button at the bottom of the dialog. + + + +# General + +- **Workspace layout** + - **Import**: reads a .ini layout file. + - **Export**: writes current layout to a .ini file. + - **Reset**: resets layout to default. + +- **Initial system**: the system of chips loaded on starting Furnace. + - **Current system**: sets current chips as default. + - **Randomize**: set default to a random system. + - this will not choose a random system at each start. + - **Reset to defaults**: sets default to "Sega Genesis/Mega Drive". + - **Name**: name for the default system. may be set to any text. + - system configuration: same as in the [chip manager](../8-advanced/chip-manager.md) and [mixer](../8-advanced/mixer.md). + +- **Play intro on start-up:** + - **No**: skips intro entirely. + - **Short**: shows silent title screen briefly. + - **Full (short when loading song)**: shows animated musical intro unless started with a song (command line, double-clicking a .fur file, etc.) + - **Full (always)**: always shows animated musical intro. +- **When creating new song**: + - **Display system preset selector** + - **Start with initial system** + +- **Double-click time (seconds)**: maximum time between mouse clicks to recognize them as a double-click. +- **Toggle channel solo on:** select which interactions with a channel header will toggle solo for that channel. +- **Push value when overwriting instead of clearing it**: in the order list and pattern editors, typing into an already-filled value will shift digits instead of starting fresh. + - if off: moving the cursor onto the value `A5` and typing a "B" results in `0B`. + - if on: with the cursor on the value `A5` and typing a "B" results in `5B`. +- **Move cursor up on backspace-delete** +- **Move cursor by edit step on delete** +- **Change current instrument when changing instrument column (absorb)** +- **Delete effect value when deleting effect** +- **Change order when scrolling outside of pattern bounds**: + - if off, the pattern edit cursor will stay locked within the current order. + - if on, moving the cursor past the edge of the previous or next order will move to that order. +- **Move cursor by edit step on insert (push)** +- **Move cursor to end of clipboard content when pasting** +- **Don't scroll when moving cursor** +- **Double click selects entire column** +- **Allow docking editors** +- **Don't raise pattern editor on click** +- **Focus pattern editor when selecting instrument** +- **Restart song when changing chip properties** +- **Use system file picker**: use native OS file dialog instead of Furnace's. +- **Only allow window movement when clicking on title bar** +- **Enable event delay** + - may cause issues with high-polling-rate mice when previewing notes. +- **Power-saving mode** + - saves power by lowering the frame rate to 2fps when idle. + - may cause issues under Mesa drivers! +- **Disable threaded input (restart after changing!)** + - threaded input processes key presses for note preview on a separate thread (on supported platforms), which reduces latency. + - however, crashes have been reported when threaded input is on. enable this option if that is the case. +- **Remember window position** + - remembers the window's last position on start-up. +- **New instruments are blank** +- **Save unused patterns** +- **Compress when saving** + - use zlib to compress saved songs. +- **Cursor follows current order when moving it** + - applies when playback is stopped. +- **Audio export loop/fade out time:** + - **Set to these values on start-up:** + - **Loops**: number of additional times to play through `0Bxx` song loop. + - **Fade out (seconds)**: length of fade out after final loop. + - **Remember last values** +- **Note preview behavior:** + - **Never** + - **When cursor is in Note column** + - **When cursor is in Note column or not in edit mode** + - **Always** +- **Wrap pattern cursor horizontally:** + - **No** + - **Yes** + - **Yes, and move to next/prev row** +- **Wrap pattern cursor vertically:** + - **No** + - **Yes** + - **Yes, and move to next/prev pattern** +- **Cursor movement keys behavior:** + - **Move by one** + - **Move by Edit Step** +- **Effect input cursor behavior:** + - **Move down** + - **Move to effect value (otherwise move down)** + - **Move to effect value/next effect and wrap around** +- **Allow dragging selection:** + - **No** + - **Yes** + - **Yes (while holding Ctrl only)** + + + +# Audio/MIDI + +- **Backend**: select SDL or JACK for audio output. + - only appears on Linux, or MacOS compiled with JACK support +- **Device**: audio device for playback. +- **Sample rate** +- **Outputs**: select number of audio outputs created, up to 16. + - only appears when Backend is JACK. +- **Channels**: number of output channels to use. +- **Buffer size**: size of buffer in both samples and milliseconds. +- **Quality**: selects quality of resampling. low quality reduces CPU load. +- **Metronome volume** +- **Low-latency mode (experimental!)**: reduces latency by running the engine faster than the tick rate. useful for live playback/jam mode. + - _warning:_ experimental! may produce glitches. only enable if your buffer size is small (10ms or less). +- **Force mono audio** +- **Software clipping**: clips output to nominal range (-1.0 to 1.0) before passing it to the audio device. + - this avoids activating Windows' built-in limiter. +- **want:** displays requested audio configuration. +- **got:** displays actual audio configuration returned by audio backend. + +- **MIDI input** +- **MIDI output** +- **MIDI input settings** + - **Note input** + - **Velocity input** + - **Map MIDI channels to direct channels** + - **Map Yamaha FM voice data to instruments** + - **Program change is instrument selection** + - **Value input style**: + - **Disabled/custom** + - **Two octaves (0 is C-4, F is D#5)** + - **Raw (note number is value)** + - **Two octaves alternate (lower keys are 0-9, upper keys are A-F)** + - **Use dual control change (one for each nibble)** + - **CC of upper nibble** + - **CC of lower nibble** + - **Use 14-bit control change** + - **MSB CC** + - **LSB CC** + - **Use single control change** + - **Control** + - **Per-column control change** + - **Instrument**\ + **Volume**\ + **Effect `x` type**\ + **Effect `x` value** + - **Disabled/custom** + - **Use dual control change (one for each nibble)** + - **CC of upper nibble** + - **CC of lower nibble** + - **Use 14-bit control change** + - **MSB CC** + - **LSB CC** + - **Use single control change (imprecise)** + - **Control** + - **Volume curve** + - **Actions:** + - **`+`** button: adds a new action. + - window-with-arrow button: new action with learning! press a button or move a slider/knob/something on your device. + - each action has the following: + - **Type** + - **Channel** + - **Note/Control** + - **Velocity/Value** + - **Action** + - **Learn** + - **Remove** + +- **MIDI output settings** + - **Output mode:** + - **Off (use for TX81Z)** + - **Melodic** + - **Send Program Change** + - **Send MIDI clock** + - **Send MIDI timecode** + - **Timecode frame rate:** + - **Closest to Tick Rate** + - **Film (24fps)** + - **PAL (25fps)** + - **NTSC drop (29.97fps)** + - **NTSC non-drop (30fps)** + +# Emulation +- **Arcade/YM2151 core** + - **ymfm** + - **Nuked-OPM** +- **Genesis/YM2612 core** + - **Nuked-OPN2** + - **ymfm** +- **SN76489 core** + - **MAME** + - **Nuked-PSG Mod** +- **NES core** + - **puNES** + - **NSFplay** +- **FDS core** + - **puNES** + - **NSFplay** +- **SID core** + - **reSID** + - **reSIDfp** +- **POKEY core** + - **Atari800 (mzpokeysnd)** + - **ASAP (C++ port)** +- **OPN/OPNA/OPNB cores** + - **ymfm only** + - **Nuked-OPN2 (FM) + ymfm (SSG/ADPCM)** + +- **PC Speaker strategy:** + - **evdev SND_TONE** + - **KIOCSOUND on /dev/tty1** + - **/dev/port** + - **KIOCSOUND on standard output** + - **outb()** + +- **Sample ROMs:** + - **OPL4 YRW801 path** + - **MultiPCM TG100 path** + - **MultiPCM MU5 path** + + + +# Appearance + +- **Render driver** +- **Automatic UI scaling factor**: automatically match the OS's UI scaling. +- **UI scaling factor**: only if "Automatic UI scaling factor" is off. +- **Main font**: if "Custom...", a file path selector will appear beneath. +- **Size** +- **Pattern font**: if "Custom...", a file path selector will appear beneath. +- **Size** +- **Icon size** +- **Display Japanese characters**\ + **Display Chinese (Simplified) characters**\ + **Display Chinese (Traditional) characters**\ + **Display Korean characters** + - only toggle these options if you have enough graphics memory. + - these are a temporary solution until dynamic font atlas is implemented in Dear ImGui. + +- **Number of recent files** + +- **Pattern view labels:** +- **Note off (3-char)**: default is `OFF` +- **Note release (3-char)**: default is `===`. +- **Macro release (3-char)**: default is `REL`. +- **Empty field (3-char)**: default is `...`. +- **Empty field (2-char)**: default is `..`. + +- **Orders row number format:** + - **Decimal** + - **Hexadecimal** +- **Pattern row number format:** + - **Decimal** + - **Hexadecimal** +- **FM parameter names:** + - **Friendly** + - **Technical** + - **Technical (alternate)** + +- **Title bar:** + - **Furnace** + - **Song Name - Furnace** + - **file_name.fur - Furnace** + - **/path/to/file.fur - Furnace** +- **Display system name on title bar** +- **Display chip names instead of "multi-system" in title bar** +- **Status bar:** + - **Cursor details** + - **File path** + - **Cursor details or file path** + - **Nothing** +- **Play/edit controls layout:** + - **Classic** + - **Compact** + - **Compact (vertical)** + - **Split** +- **Position of buttons in Orders:** + - **Top** + - **Left** + - **Right** +- **FM parameter editor layout:** + - **Modern** + - **Compact (2x2, classic)** + - **Compact (1x4)** + - **Compact (4x1)** + - **Alternate (2x2)** + - **Alternate (1x4)** + - **Alternate (4x1)** +- **Position of Sustain in FM editor:** + - **Between Decay and Sustain Rate** + - **After Release Rate** +- **Macro editor layout:** + - **Unified** + - **Mobile** + - **Grid** + - **Single (with list)** + - **Single (combo box)** + +- **Namco 163 chip name** + +- **Channel colors:** + - **Single** + - **Channel type** + - **Instrument type** +- **Channel name colors:** + - **Single** + - **Channel type** + - **Instrument type** +- **Channel style:** + - **Classic** + - **Line** + - **Round** + - **Split button** + - **Square border** + - **Round border** +- **Channel volume bar:** + - **None** + - **Simple** + - **Stereo** + - **Real** + - **Real (stereo)** +- **Channel feedback style:** + - **Off** + - **Note** + - **Volume** + - **Active** +- **Channel font:** + - **Regular** + - **Monospace** +- **Center channel name** + +- **Colorize instrument editor using instrument type** +- **Use separate colors for carriers/modulators in FM editor** +- **Unified instrument/wavetable/sample list** +- **Horizontal instrument list** +- **Use standard OPL waveform names** +- **Overflow pattern highlights** +- **Display previous/next pattern** +- **Use German notation**: display `B` notes as `H`, and `A#` notes as `B`. +- **Single-digit effects for 00-0F** +- **Center pattern view**: centers pattern horizontally in view. +- **Unsigned FM detune values** +- **Highlight channel at cursor in Orders** +- **About screen party time** + - _warning:_ may cause epileptic seizures. + +- **Use compact wave editor** +- **Use classic macro editor vertical slider** +- **Rounded window corners** +- **Rounded buttons** +- **Rounded menu corners** +- **Borders around widgets** +- **Disable fade-in during start-up** + +- **Oscilloscope settings:** + - **Rounded corners** + - **Fill entire window** + - **Waveform goes out of bounds** + - **Border** + +- **Pattern view spacing after:** + - **Note** + - **Instrument** + - **Volume** + - **Effect** + - **Effect value** +- **Color scheme** + - **Import** + - **Export** + - **Reset defaults** + - **General** + - **Color scheme type:** + - **Dark** + - **Light** + - **Frame shading** + - several more categories... + + + +# Keyboard + +- **Import** +- **Export** +- **Reset defaults** +- several categories of keybinds... + - click on a keybind then enter a key or key combination to change it + - right-click to clear the keybind diff --git a/src/audio/sdlAudio.cpp b/src/audio/sdlAudio.cpp index 6d0ceff06..5d07921e9 100644 --- a/src/audio/sdlAudio.cpp +++ b/src/audio/sdlAudio.cpp @@ -127,14 +127,20 @@ bool TAAudioSDL::init(TAAudioDesc& request, TAAudioDesc& response) { ac.callback=taSDLProcess; ac.userdata=this; - ai=SDL_OpenAudioDevice(request.deviceName.empty()?NULL:request.deviceName.c_str(),0,&ac,&ar,SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + ai=SDL_OpenAudioDevice(request.deviceName.empty()?NULL:request.deviceName.c_str(),0,&ac,&ar,0); if (ai==0) { logE("could not open audio device: %s",SDL_GetError()); return false; } + const char* backendName=SDL_GetCurrentAudioDriver(); + desc.deviceName=request.deviceName; - desc.name=""; + if (backendName==NULL) { + desc.name=""; + } else { + desc.name=backendName; + } desc.rate=ar.freq; desc.inChans=0; desc.outChans=ar.channels; diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 1aa8188e0..c7b5ac9e0 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -4586,6 +4586,15 @@ bool DivEngine::initAudioBackend() { } } +#ifdef HAVE_SDL2 + if (audioEngine==DIV_AUDIO_SDL) { + String audioDriver=getConfString("sdlAudioDriver",""); + if (!audioDriver.empty()) { + SDL_SetHint("SDL_HINT_AUDIODRIVER",audioDriver.c_str()); + } + } +#endif + lowQuality=getConfInt("audioQuality",0); forceMono=getConfInt("forceMono",0); clampSamples=getConfInt("clampSamples",0); @@ -4594,7 +4603,7 @@ bool DivEngine::initAudioBackend() { midiOutClock=getConfInt("midiOutClock",0); midiOutTime=getConfInt("midiOutTime",0); midiOutTimeRate=getConfInt("midiOutTimeRate",0); - midiOutProgramChange = getConfInt("midiOutProgramChange",0); + midiOutProgramChange=getConfInt("midiOutProgramChange",0); midiOutMode=getConfInt("midiOutMode",DIV_MIDI_MODE_NOTE); if (metroVol<0.0f) metroVol=0.0f; if (metroVol>2.0f) metroVol=2.0f; diff --git a/src/engine/engine.h b/src/engine/engine.h index aceee308b..e4b3e56a3 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -570,6 +570,7 @@ class DivEngine { float oscSize; int oscReadPos, oscWritePos; int tickMult; + int lastNBIns, lastNBOuts, lastNBSize; std::atomic processTime; void runExportThread(); @@ -1252,6 +1253,9 @@ class DivEngine { oscReadPos(0), oscWritePos(0), tickMult(1), + lastNBIns(0), + lastNBOuts(0), + lastNBSize(0), processTime(0), yrw801ROM(NULL), tg100ROM(NULL), diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 683f97211..9b565cdc7 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -322,7 +322,7 @@ void DivPlatformGB::tick(bool sysTick) { rWrite(16+i*5+4,((chan[i].keyOn||chan[i].keyOff)?0x80:0x00)|((chan[i].soundLen<64)<<6)); } else { rWrite(16+i*5+3,(2048-chan[i].freq)&0xff); - rWrite(16+i*5+4,(((2048-chan[i].freq)>>8)&7)|((chan[i].keyOn||chan[i].keyOff)?0x80:0x00)|((chan[i].soundLen<63)<<6)); + rWrite(16+i*5+4,(((2048-chan[i].freq)>>8)&7)|((chan[i].keyOn||(chan[i].keyOff && i!=2))?0x80:0x00)|((chan[i].soundLen<63)<<6)); } if (enoughAlready) { // more compat garbage rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(chan[i].soundLen&63))); @@ -466,7 +466,9 @@ int DivPlatformGB::dispatch(DivCommand c) { if (c.chan!=2) break; chan[c.chan].wave=c.value; ws.changeWave1(chan[c.chan].wave); - chan[c.chan].keyOn=true; + if (chan[c.chan].active) { + chan[c.chan].keyOn=true; + } break; case DIV_CMD_NOTE_PORTA: { int destFreq=NOTE_PERIODIC(c.value2); diff --git a/src/engine/platform/vera.cpp b/src/engine/platform/vera.cpp index fe34b8bc4..5b8c2d9e3 100644 --- a/src/engine/platform/vera.cpp +++ b/src/engine/platform/vera.cpp @@ -19,7 +19,6 @@ #include "vera.h" #include "../engine.h" -#include "../../ta-log.h" #include #include @@ -40,14 +39,15 @@ extern "C" { #define rWriteZSMSync(d) {if (dumpWrites) addWrite(68,(d));} const char* regCheatSheetVERA[]={ - "CHxFreq", "00+x*4", - "CHxVol", "02+x*4", - "CHxWave", "03+x*4", + "CHxFreq", "00+x*4", + "CHxVol", "02+x*4", + "CHxWave", "03+x*4", - "AUDIO_CTRL", "40", - "AUDIO_RATE", "41", - "AUDIO_DATA", "42", - "ZSM_SYNC", "44", + "AUDIO_CTRL", "40", + "AUDIO_RATE", "41", + "AUDIO_DATA", "42", + "ZSM_PCM_LOOP_POINT", "43", + "ZSM_SYNC", "44", NULL }; @@ -230,9 +230,16 @@ void DivPlatformVERA::tick(bool sysTick) { chan[16].freqChanged=false; } + // For export, output the entire sample that starts on this tick if (dumpWrites) { DivSample* s=parent->getSample(chan[16].pcm.sample); if (s->samples>0) { + if (s->isLoopable()) { + // Inform the export process of the loop point for this sample + addWrite(67,s->loopStart&0xff); + addWrite(67,(s->loopStart>>8)&0xff); + addWrite(67,(s->loopStart>>16)&0xff); + } while (true) { short tmp_l=0; short tmp_r=0; @@ -258,8 +265,6 @@ void DivPlatformVERA::tick(bool sysTick) { } chan[16].pcm.pos++; if (s->isLoopable() && chan[16].pcm.pos>=(unsigned int)s->loopEnd) { - //chan[16].pcm.pos=s->loopStart; - logI("VERA PCM export: treating looped sample as non-looped"); chan[16].pcm.sample=-1; break; } diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 798de87b2..9f8a2f10b 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -915,7 +915,7 @@ void DivEngine::processRow(int i, bool afterDelay) { //printf("\x1b[1;36m%d: extern command %d\x1b[m\n",i,effectVal); extValue=effectVal; extValuePresent=true; - dispatchCmd(DivCommand(DIV_CMD_EXTERNAL,effectVal)); + dispatchCmd(DivCommand(DIV_CMD_EXTERNAL,i,effectVal)); break; case 0xef: // global pitch globalPitch+=(signed char)(effectVal-0x80); @@ -1694,6 +1694,10 @@ void DivEngine::runMidiTime(int totalCycles) { } void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) { + lastNBIns=inChans; + lastNBOuts=outChans; + lastNBSize=size; + if (!size) { logW("nextBuf called with size 0!"); return; diff --git a/src/engine/zsm.cpp b/src/engine/zsm.cpp index b0f421114..7cedc6d8e 100644 --- a/src/engine/zsm.cpp +++ b/src/engine/zsm.cpp @@ -61,6 +61,8 @@ void DivZSM::init(unsigned int rate) { pcmRateCache=-1; pcmCtrlRVCache=-1; pcmCtrlDCCache=-1; + pcmIsLooped=false; + pcmLoopPointCache=0; // Channel masks ymMask=0; psgMask=0; @@ -166,6 +168,9 @@ void DivZSM::writePCM(unsigned char a, unsigned char v) { } else if (a==2) { // PCM data pcmCache.push_back(v); numWrites++; + } else if (a==3) { // PCM loop point + pcmLoopPointCache=(pcmLoopPointCache>>8)|(v<<16); + pcmIsLooped=true; } } @@ -213,7 +218,7 @@ SafeWriter* DivZSM::finish() { pcmData.clear(); pcmInsts.clear(); } else if (pcmData.size()) { // if exists, write PCM instruments and blob to the end of file - int pcmOff=w->tell(); + unsigned int pcmOff=w->tell(); w->writeC('P'); w->writeC('C'); w->writeC('M'); @@ -236,10 +241,11 @@ SafeWriter* DivZSM::finish() { w->writeC((unsigned char)(inst.length>>16)&0xff); // Feature mask: Lxxxxxxx // L = Loop enabled - w->writeC(0); - // Loop point (not yet implemented) - w->writeC(0); - w->writeS(0); + w->writeC((unsigned char)inst.isLooped<<7); + // Sample loop point + w->writeC((unsigned char)inst.loopPoint&0xff); + w->writeC((unsigned char)(inst.loopPoint>>8)&0xff); + w->writeC((unsigned char)(inst.loopPoint>>16)&0xff); // Reserved for future use w->writeS(0); w->writeS(0); @@ -289,8 +295,8 @@ void DivZSM::flushWrites() { } ymwrites.clear(); unsigned int pcmInst=0; - int pcmOff=0; - int pcmLen=0; + unsigned int pcmOff=0; + unsigned int pcmLen=0; int extCmd0Len=pcmMeta.size()*2; if (pcmCache.size()) { // collapse stereo data to mono if both channels are fully identical @@ -347,7 +353,7 @@ void DivZSM::flushWrites() { extCmd0Len+=2; // search for a matching PCM instrument definition for (S_pcmInst& inst: pcmInsts) { - if (inst.offset==pcmOff && inst.length==pcmLen && inst.geometry==pcmCtrlDCCache) + if (inst.offset==pcmOff && inst.length==pcmLen && inst.geometry==pcmCtrlDCCache && inst.isLooped==pcmIsLooped && inst.loopPoint==pcmLoopPointCache) break; pcmInst++; } @@ -356,7 +362,11 @@ void DivZSM::flushWrites() { inst.geometry=pcmCtrlDCCache; inst.offset=pcmOff; inst.length=pcmLen; + inst.loopPoint=pcmLoopPointCache; + inst.isLooped=pcmIsLooped; pcmInsts.push_back(inst); + pcmIsLooped=false; + pcmLoopPointCache=0; } } if (extCmd0Len>63) { // this would be bad, but will almost certainly never happen diff --git a/src/engine/zsm.h b/src/engine/zsm.h index 42300cf70..ff497693f 100644 --- a/src/engine/zsm.h +++ b/src/engine/zsm.h @@ -46,7 +46,9 @@ enum PSG_STATE { psg_PREV, psg_NEW, psg_STATES }; class DivZSM { private: struct S_pcmInst { - int geometry, offset, length; + int geometry; + unsigned int offset, length, loopPoint; + bool isLooped; }; SafeWriter* w; int ymState[ym_STATES][256]; @@ -54,6 +56,8 @@ class DivZSM { int pcmRateCache; int pcmCtrlRVCache; int pcmCtrlDCCache; + unsigned int pcmLoopPointCache; + bool pcmIsLooped; std::vector ymwrites; std::vector pcmMeta; std::vector pcmData; diff --git a/src/gui/about.cpp b/src/gui/about.cpp index 2aef20b9e..2652f8731 100644 --- a/src/gui/about.cpp +++ b/src/gui/about.cpp @@ -39,6 +39,7 @@ const char* aboutLine[]={ "cam900", "djtuBIG-MaliceX", "laoo", + "MooingLemur", "OPNA2608", "superctr", "System64", @@ -58,6 +59,8 @@ const char* aboutLine[]={ "cam900", "host12prog", "WindowxDeveloper", + "polluks", + "Electric Keet", "", "-- demo songs --", "0x5066", @@ -134,6 +137,7 @@ const char* aboutLine[]={ "fd", "GENATARi", "host12prog", + "jvsTSX", "Lumigado", "Lunathir", "plane", diff --git a/src/gui/debugWindow.cpp b/src/gui/debugWindow.cpp index b9dc6c423..bfeb9067e 100644 --- a/src/gui/debugWindow.cpp +++ b/src/gui/debugWindow.cpp @@ -388,6 +388,34 @@ void FurnaceGUI::drawDebug() { ImGui::Text("System Managed Scale: %d",sysManagedScale); ImGui::TreePop(); } + if (ImGui::TreeNode("Audio Debug")) { + TAAudioDesc& audioWant=e->getAudioDescWant(); + TAAudioDesc& audioGot=e->getAudioDescGot(); + + ImGui::Text("want:"); + ImGui::Text("- name: %s",audioWant.name.c_str()); + ImGui::Text("- device name: %s",audioWant.deviceName.c_str()); + ImGui::Text("- rate: %f",audioWant.rate); + ImGui::Text("- buffer size: %d",audioWant.bufsize); + ImGui::Text("- fragments: %d",audioWant.fragments); + ImGui::Text("- inputs: %d",audioWant.inChans); + ImGui::Text("- outputs: %d",audioWant.outChans); + ImGui::Text("- format: %d",audioWant.outFormat); + + ImGui::Text("got:"); + ImGui::Text("- name: %s",audioGot.name.c_str()); + ImGui::Text("- device name: %s",audioGot.deviceName.c_str()); + ImGui::Text("- rate: %f",audioGot.rate); + ImGui::Text("- buffer size: %d",audioGot.bufsize); + ImGui::Text("- fragments: %d",audioGot.fragments); + ImGui::Text("- inputs: %d",audioGot.inChans); + ImGui::Text("- outputs: %d",audioGot.outChans); + ImGui::Text("- format: %d",audioGot.outFormat); + + ImGui::Text("last call to nextBuf(): in %d, out %d, size %d",e->lastNBIns,e->lastNBOuts,e->lastNBSize); + + ImGui::TreePop(); + } if (ImGui::TreeNode("Visualizer Debug")) { if (ImGui::BeginTable("visX",3,ImGuiTableFlags_Borders)) { ImGui::TableNextRow(ImGuiTableRowFlags_Headers); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index a1a5cb842..3e7ed0275 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -6329,6 +6329,19 @@ bool FurnaceGUI::init() { } #endif + int numDriversA=SDL_GetNumAudioDrivers(); + if (numDriversA<0) { + logW("could not list audio drivers! %s",SDL_GetError()); + } else { + for (int i=0; i recentFile; std::vector makeInsTypeList; std::vector availRenderDrivers; + std::vector availAudioDrivers; bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting, vgmExportLoop, zsmExportLoop, vgmExportPatternHints; bool vgmExportDirectStream, displayInsTypeList; @@ -1534,6 +1535,7 @@ class FurnaceGUI { String macroRelLabel; String emptyLabel; String emptyLabel2; + String sdlAudioDriver; DivConfig initialSys; Settings(): @@ -1686,7 +1688,8 @@ class FurnaceGUI { noteRelLabel("==="), macroRelLabel("REL"), emptyLabel("..."), - emptyLabel2("..") {} + emptyLabel2(".."), + sdlAudioDriver("") {} } settings; struct Tutorial { diff --git a/src/gui/pattern.cpp b/src/gui/pattern.cpp index a34a856d8..72d953b7a 100644 --- a/src/gui/pattern.cpp +++ b/src/gui/pattern.cpp @@ -133,17 +133,20 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int } ImGui::PopStyleColor(); // for each column + int mustSetXOf=0; for (int j=0; j