diff --git a/doc/2-interface/README.md b/doc/2-interface/README.md index aa16af8d4..7d4300adf 100644 --- a/doc/2-interface/README.md +++ b/doc/2-interface/README.md @@ -18,30 +18,31 @@ the default layout of Furnace is depicted below. - [play/edit controls](play-edit-controls.md) - [instrument/wavetable/sample list](asset-list.md) - [song information](song-info.md) -- [effect list window](effect-list-window.md) - [pattern view](../3-pattern/README.md) +- [effect list window](effect-list-window.md) - [instrument editor](../4-instrument/README.md) - [wavetable editor](../5-wave/README.md) - [sample editor](../6-sample/README.md) ## advanced topics -- [mixer](../8-advanced/mixer.md) -- [grooves](../8-advanced/grooves.md) -- [channels](../8-advanced/channels.md) -- [pattern manager](../8-advanced/pat-manager.md) -- [chip manager](../8-advanced/chip-manager.md) -- [compatibility flags](../8-advanced/compat-flags.md) - [song comments](../8-advanced/comments.md) -- [piano/input pad](../8-advanced/piano.md) +- [channels](../8-advanced/channels.md) +- [chip manager](../8-advanced/chip-manager.md) +- [pattern manager](../8-advanced/pat-manager.md) +- [mixer](../8-advanced/mixer.md) +- [compatibility flags](../8-advanced/compat-flags.md) - [oscilloscope](../8-advanced/osc.md) - [oscilloscope (per channel)](../8-advanced/chanosc.md) +- [oscilloscope (X-Y)](../8-advanced/xyosc.md) - [clock](../8-advanced/clock.md) -- [register view](../8-advanced/regview.md) +- [grooves](../8-advanced/grooves.md) - [log viewer](../8-advanced/log-viewer.md) +- [register view](../8-advanced/regview.md) - [statistics](../8-advanced/stats.md) +- [memory composition](../8-advanced/memory-composition.md) ## other topics -- [basic mode](basic-mode.md) +- [piano/input pad](../8-advanced/piano.md) - [settings](settings.md) diff --git a/doc/2-interface/export.md b/doc/2-interface/export.md index 8d6f32074..2b68a0a9a 100644 --- a/doc/2-interface/export.md +++ b/doc/2-interface/export.md @@ -2,25 +2,27 @@ Furnace allows you to export your song in several formats. this section deals with describing the available export options. -## export audio +## audio this option allows you to export your song in .wav format. I know I know, no .mp3 or .ogg export yet, but you can use a converter. -there are two parameters: - +- **Export type**: + - **one file**: exports your song to one .wav file. + - **multiple files (one per chip)**: exports the output of each chip to .wav files. + - **multiple files (one per channel)**: exports the output of each channel to .wav files. + - useful for usage with a channel visualizer such as corrscope. +- **Bit depth**: default is 16-bit integer. +- **Sample rate**: affects the quality of the output file. + - default is 44100, "CD quality". + - lower sample rates lose fidelity as upper frequencies disappear. + - higher sample rates gain frequencies that can't be heard at the cost of file size and rendering time. +- **Channels in file**: default is 2 (stereo). Set to 1 for mono. - **Loops**: sets the number of times the song will loop. - does not have effect if the song ends with `FFxx` effect. - **Fade out (seconds)**: sets the fade out time when the song is over. - does not have effect if the song ends with `FFxx` effect. -and three export choices: - -- **one file**: exports your song to one .wav file. -- **multiple files (one per chip)**: exports the output of each chip to .wav files. -- **multiple files (one per channel)**: exports the output of each channel to .wav files. - - useful for usage with a channel visualizer such as corrscope. - -## export VGM +## VGM this option allows exporting to a VGM (Video Game Music) file. these can be played back with VGMPlay (for example). @@ -40,9 +42,6 @@ the following settings exist: - **custom**: allows you to specify how many ticks to add. - `0` is effectively none, disabling loop trail completely. - this option will not appear if the loop modality isn't set to None as there wouldn't be a need to. -- **chips to export**: select which chips are going to be exported. - - due to VGM format limitations, you can only select up to two of each chip type. - - some chips will not be available, either because VGM doesn't support these yet, or because you selected an old format version. - **add pattern change hints**: this option adds a "hint" when a pattern change occurs. only useful if you're a developer. - the format of the "hint" data block that gets written is: `67 66 FE ll ll ll ll 01 oo rr pp pp pp ...` - `ll`: length, a 32-bit little-endian number @@ -51,14 +50,11 @@ the following settings exist: - `pp`: pattern index (one per channel) - **direct stream mode**: this option allows DualPCM to work. don't use this for other chips. - may or may not play well with hardware VGM players. +- **chips to export**: select which chips are going to be exported. + - due to VGM format limitations, you can only select up to two of each chip type. + - some chips will not be available, either because VGM doesn't support these yet, or because you selected an old format version. -click on **click to export** to begin exporting. - -## export text - -this option allows you to export your song as a text file. - -## export ZSM +## ZSM ZSM (ZSound Music) is a format designed for the Commander X16 to allow hardware playback. it may contain data for either YM2151 or VERA chips. @@ -72,21 +68,21 @@ the following settings are available: - **loop**: enables loop. if disabled, the song won't loop. - **optimize size**: removes unnecessary commands to reduce size. -click on **Begin Export** to... you know. +## text -## export command stream +this option allows you to export your song as a text file. -this option exports a binary file which contains a dump of the internal command stream produced when playing the song. +## command stream -it's not really useful, unless you're a developer and want to use a command stream dump for some reason (e.g. writing a hardware sound driver). +this option exports a binary file in Furnace's own command stream format (FCS) which contains a dump of the internal command stream produced when playing the song. -- **export**: exports in Furnace's own command stream format (FCS). see `export-tech.md` in `papers/` for details. +it's not really useful, unless you're a developer and want to use a command stream dump for some reason (e.g. writing a hardware sound driver). see `export-tech.md` in `papers/` for details. -## export DMF +## DMF this option allows you to save your song as a .dmf which can be opened in DefleMask. -the following systems are supported when saving as 1.0/legacy: +the following systems are supported when saving as 1.0/legacy (0.12): - Sega Genesis/Mega Drive (YM2612 + SN76489) - Sega Genesis/Mega Drive (YM2612 + SN76489, extended channel 3) - Sega Master System @@ -97,7 +93,7 @@ the following systems are supported when saving as 1.0/legacy: - Arcade (YM2151 + SegaPCM 5-channel compatibility) - Neo Geo CD (DefleMask 1.0+) -the following systems are supported when saving as 1.1.3+: +the following systems are also supported when saving as 1.1.3+: - Sega Master System (with FM expansion) - NES + Konami VRC7 - Famicom Disk System diff --git a/doc/2-interface/keyboard.md b/doc/2-interface/keyboard.md index 317538567..675ba0b55 100644 --- a/doc/2-interface/keyboard.md +++ b/doc/2-interface/keyboard.md @@ -39,7 +39,7 @@ the keys in the "Global hotkeys" section can be used in any window, although not | Panic | `F12` | | | | | **Window activation** | | -| Find/Replace | Ctrl-F | +| Find/Replace | `Ctrl-F` | | Settings | — | | Song Information | — | | Subsongs | — | @@ -63,16 +63,23 @@ the keys in the "Global hotkeys" section can be used in any window, although not | Piano | — | | Oscilloscope (master) | — | | Oscilloscope (per-channel) | — | +| Oscilloscope (X-Y) | — | | Volume Meter | — | | Clock | — | | Register View | — | | Log Viewer | — | | Statistics | — | +| Memory Composition | — | | Effect List | — | | Debug Menu | `Ctrl-Shift-D` | +| Command Stream Player | — | | About | — | | Collapse/expand current window | — | | Close current window | `Shift-Escape` | +| Command Palette | `Ctrl-P` | +| Recent files (Palette) | — | +| Insstruments (Palette) | — | +| Samples (Palette) | — | | | | | **Note input** | | | _see "note input" section after table_ | | @@ -102,8 +109,8 @@ the keys in the "Global hotkeys" section can be used in any window, although not | Move cursor down by one (override Edit Step) | `Shift-End` | | Move cursor to previous channel | — | | Move cursor to next channel | — | -| Move cursor to next channel (overflow) | — | | Move cursor to previous channel (overflow) | — | +| Move cursor to next channel (overflow) | — | | Move cursor to beginning of pattern | `Home` | | Move cursor to end of pattern | `End` | | Move cursor up (coarse) | `PageUp` | @@ -118,6 +125,10 @@ the keys in the "Global hotkeys" section can be used in any window, although not | Expand selection to end of pattern | — | | Expand selection upwards (coarse) | `Shift-PageUp` | | Expand selection downwards (coarse) | `Shift-PageDown` | +| Move selection up by one | `Alt-Up` | +| Move selection down by one | `Alt-Down` | +| Move selection to previous channel | `Alt-Left` | +| Move selection to next channel | `Alt-Right` | | Delete | `Delete` | | Pull delete | `Backspace` | | Insert | `Insert` | @@ -143,102 +154,103 @@ the keys in the "Global hotkeys" section can be used in any window, although not | Clear note input latch | — | | | | | **Instrument list** | | -| Add | `Insert` | -| Duplicate | `Ctrl-D` | -| Open | — | -| Open (replace current) | — | -| Save | — | -| Save (.dmp) | — | -| Move up | `Shift-Up` | -| Move down | `Shift-Down` | -| Delete | — | -| Edit | `Shift-Return` | -| Cursor up | `Up` | -| Cursor down | `Down` | -| Toggle folders/standard view | `Ctrl-V` | +| Add instrument | `Insert` | +| Duplicate instrument | `Ctrl-D` | +| Open instrument | — | +| Open instrument (replace current) | — | +| Save instrument | — | +| Save instrument (.dmp) | — | +| Move instrument up in list | `Shift-Up` | +| Move instrument down in list | `Shift-Down` | +| Delete instrument | — | +| Edit instrument | `Shift-Return` | +| Instrument cursor up | `Up` | +| Instrument cursor down | `Down` | +| Instruments: toggle folders/standard view | `Ctrl-V` | | | | | **Wavetable list** | | -| Add | `Insert` | -| Duplicate | `Ctrl-D` | -| Open | — | -| Open (replace current) | — | -| Save | — | -| Save (.dmw) | — | -| Save (raw) | — | -| Move up | `Shift-Up` | -| Move down | `Shift-Down` | -| Delete | — | -| Edit | `Shift-Return` | -| Cursor up | `Up` | -| Cursor down | `Down` | -| Toggle folders/standard view | `Ctrl-V` | +| Add wavetable | `Insert` | +| Duplicate wavetable | `Ctrl-D` | +| Open wavetable | — | +| Open wavetable (replace current) | — | +| Save wavetable | — | +| Save wavetable (.dmw) | — | +| Save wavetable (raw) | — | +| Move wavetable up in list | `Shift-Up` | +| Move wavetable down in list | `Shift-Down` | +| Delete wavetable | — | +| Edit wavetable | `Shift-Return` | +| Wavetable cursor up | `Up` | +| Wavetable cursor down | `Down` | +| Wavetables: toggle folders/standard view | `Ctrl-V` | | | | | **Sample list** | | -| Add | `Insert` | -| Duplicate | `Ctrl-D` | -| Create wavetable from selection | `Ctrl-W` | -| Open | — | -| Open (replace current) | — | -| Import raw data | — | -| Import raw data (replace current) | — | -| Save | — | -| Save (raw) | — | -| Move up | `Shift-Up` | -| Move down | `Shift-Down` | -| Delete | — | -| Edit | `Shift-Return` | -| Cursor up | `Up` | -| Cursor down | `Down` | -| Preview | — | -| Stop preview | — | -| Toggle folders/standard view | `Ctrl-V` | +| Add sample | `Insert` | +| Duplicate sample | `Ctrl-D` | +| Sample Editor: Create wavetable from selection | `Ctrl-W` | +| Open sample | — | +| Open sample (replace current) | — | +| Import raw sample data | — | +| Import raw sample data (replace current) | — | +| Save sample | — | +| Save sample (raw) | — | +| Move sample up in list | `Shift-Up` | +| Move sample down in list | `Shift-Down` | +| Delete sample | — | +| Edit sample | `Shift-Return` | +| Sample cursor up | `Up` | +| Sample cursor down | `Down` | +| Sample Preview | — | +| Stop sample preview | — | +| Samples: Toggle folders/standard view | `Ctrl-V` | +| Samples: Make me a drum kit | — | | | | | **Orders** | | | Previous order | `Up` | | Next order | `Down` | -| Cursor left | `Left` | -| Cursor right | `Right` | -| Increase value | — | -| Decrease value | — | -| Switch edit mode | — | -| Toggle alter entire row | `Ctrl-L` | -| Add | `Insert` | -| Duplicate | `Ctrl-D` | -| Deep clone | `Ctrl-Shift-D` | -| Duplicate to end of song | `Ctrl-E` | -| Deep clone to end of song | `Ctrl-Shift-E` | -| Remove | `Delete` | -| Move up | `Shift-Up` | -| Move down | `Shift-Down` | -| Replay | — | +| Order cursor left | `Left` | +| Order cursor right | `Right` | +| Increase order value | — | +| Decrease order value | — | +| Switch order edit mode | — | +| Order: Toggle alter entire row | `Ctrl-L` | +| Add order | `Insert` | +| Duplicate order | `Ctrl-D` | +| Deep clone order | `Ctrl-Shift-D` | +| Copy current order to end of song | `Ctrl-E` | +| Deep clone current order to end of song | `Ctrl-Shift-E` | +| Remove order | `Delete` | +| Move order up | `Shift-Up` | +| Move order down | `Shift-Down` | +| Replay order | — | | | | | **Sample editor** | | -| Edit mode: Select | `Shift-I` | -| Edit mode: Draw | `Shift-D` | -| Cut | `Ctrl-X` | -| Copy | `Ctrl-C` | -| Paste | `Ctrl-V` | -| Paste replace | `Ctrl-Shift-V` | -| Paste mix | `Ctrl-Alt-V` | -| Select all | `Ctrl-A` | -| Resize | `Ctrl-R` | -| Resample | `Ctrl-E` | -| Amplify | `Ctrl-B` | -| Normalize | `Ctrl-N` | -| Fade in | `Ctrl-I` | -| Fade out | `Ctrl-O` | -| Insert silence | `Insert` | -| Apply silence | `Shift-Delete` | -| Delete | `Delete` | -| Trim | `Ctrl-Delete` | -| Reverse | `Ctrl-T` | -| Invert | `Ctrl-Shift-T` | -| Signed/unsigned exchange | `Ctrl-U` | -| Apply filter | `Ctrl-F` | -| Preview sample | — | -| Stop sample preview | — | -| Zoom in | `Ctrl-=` | -| Zoom out | `Ctrl--` | -| Toggle auto-zoom | `Ctrl-0` | -| Create instrument from sample | — | -| Set loop to selection | `Ctrl-L` | +| Sample editor mode: Select | `Shift-I` | +| Sample editor mode: Draw | `Shift-D` | +| Sample editor: Cut | `Ctrl-X` | +| Sample editor: Copy | `Ctrl-C` | +| Sample editor: Paste | `Ctrl-V` | +| Sample editor: Paste replace | `Ctrl-Shift-V` | +| Sample editor: Paste mix | `Ctrl-Alt-V` | +| Sample editor: Select all | `Ctrl-A` | +| Sample editor: Resize | `Ctrl-R` | +| Sample editor: Resample | `Ctrl-E` | +| Sample editor: Amplify | `Ctrl-B` | +| Sample editor: Normalize | `Ctrl-N` | +| Sample editor: Fade in | `Ctrl-I` | +| Sample editor: Fade out | `Ctrl-O` | +| Sample editor: Insert silence | `Insert` | +| Sample editor: Apply silence | `Shift-Delete` | +| Sample editor: Delete | `Delete` | +| Sample editor: Trim | `Ctrl-Delete` | +| Sample editor: Reverse | `Ctrl-T` | +| Sample editor: Invert | `Ctrl-Shift-T` | +| Sample editor: Signed/unsigned exchange | `Ctrl-U` | +| Sample editor: Apply filter | `Ctrl-F` | +| Sample editor: Preview sample | — | +| Sample editor: Stop sample preview | — | +| Sample editor: Zoom in | `Ctrl-=` | +| Sample editor: Zoom out | `Ctrl--` | +| Sample editor: Toggle auto-zoom | `Ctrl-0` | +| Sample editor: Create instrument from sample | — | +| Sample editor: Set loop to selection | `Ctrl-L` | diff --git a/doc/2-interface/menu-bar.md b/doc/2-interface/menu-bar.md index ec3c6b1bf..fff10825b 100644 --- a/doc/2-interface/menu-bar.md +++ b/doc/2-interface/menu-bar.md @@ -2,24 +2,20 @@ the menu bar allows you to select from five menus: file, edit, settings, window and help. -items in _italic_ don't appear in basic mode and are only available in advanced mode. - ## file -- **new...**: creates a new song. +- **new...**: opens the new song dialog to choose a system. + - click a system name to create a new song with it. + - some systems have several variants, which are inside a group. - **open...**: opens the file picker, allowing you to select a song to open. - see [file formats](formats.md) for a list of formats Furnace is able to open. - **open recent**: contains a list of the songs you've opened before. - **clear history**: erases the file history. - - **save**: saves the current song. - opens the file picker if this is a new song, or a backup. - **save as...**: opens the file picker, allowing you to save the song under a different name. - -- **export**: allows you to export your song into other formats, such as audio files, VGM and more. see the [export](export.md) page for more information. - +- **export...**: allows you to export your song into other formats, such as audio files, VGM and more. see the [export](export.md) page for more information. - **manage chips**: opens the [Chip Manager](../8-advanced/chip-manager.md) dialog. - - **restore backup**: restores a previously saved backup. - Furnace keeps up to 5 backups of a song. - the backup directory is located in: @@ -28,21 +24,18 @@ items in _italic_ don't appear in basic mode and are only available in advanced - Linux/other: `~/.config/furnace/backups` - this directory grows in size as you use Furnace. remember to delete old backups periodically to save space. - **do NOT rely on the backup system as auto-save!** you should save a restored backup because Furnace will not save backups of backups. - - **exit**: closes Furnace. ## edit - **...**: does nothing except prevent accidental clicks on later menu items if the menu is too tall to fit on the program window. - - **undo**: reverts the last action. - **redo**: repeats what you undid previously. - - **cut**: moves the current selection in the pattern view to clipboard. - **copy**: copies the current selection in the pattern view to clipboard. - **paste**: inserts the clipboard's contents in the cursor position. - you may be able to paste from OpenMPT as well. -- _**paste special...**:_ variants of the paste feature. +- **paste special...**: variants of the paste feature. - **paste mix**: inserts the clipboard's contents in the cursor position, but does not erase the occupied region. - **paste mix (background)**: does the same thing as paste mix, but doesn't alter content which is already there. - **paste with ins (foreground)**: same thing as paste mix, but changes the instrument. @@ -55,81 +48,84 @@ items in _italic_ don't appear in basic mode and are only available in advanced - if the selection is tall, it will select the entire column. - if a column is already selected, it will select the entire channel. - if a channel is already selected, it will select the entire pattern. - -- _**operation mask**:_ toggles which columns will be affected by the listed operations. [more information here.](../8-advanced/opmask.md) -- _**input latch**:_ determines which data are placed along with a note. [more information here.](../8-advanced/inputlatch.md) - +- **operation mask**: toggles which columns will be affected by the listed operations. [more information here.](../8-advanced/opmask.md) +- **input latch**: determines which data are placed along with a note. [more information here.](../8-advanced/inputlatch.md) - **note/octave up/down**: transposes notes in the current selection. - - **values up/down**: changes values in the current selection by ±1 or ±16. - - **transpose**: transpose notes or change values by a specific amount. - - **interpolate**: fills in gaps in the selection by interpolation between values. -- **change instrument**: changes the instrument number in a selection. -- **gradient/fade**: replace the selection with a "gradient" that goes from the beginning of the selection to the end. +- **change instrument...**: changes the instrument number in a selection. +- **gradient/fade...**: replace the selection with a "gradient" that goes from the beginning of the selection to the end. - does not affect the note column. - **Nibble mode**: when enabled, the fade will be per-nibble (0 to F) rather than per-value (00 to FF). - use for effects like `04xy` (vibrato). -- **scale**: scales values in the selection by a specific amount. +- **scale...**: scales values in the selection by a specific amount. - use to change volume in a selection for example. - **randomize**: replaces the selection with random values. - does not affect the note column. + - **Nibble mode**: when enabled, the randomization will be per-nibble (0 to F) rather than per-value (00 to FF). - **invert values**: `00` becomes `FF`, `01` becomes `FE`, `02` becomes `FD` and so on. - - **flip selection**: flips the selection so it is backwards. - **collapse/expand amount**: allows you to specify how much to collapse/expand in the next two menu items. - **collapse**: shrinks the selected contents. - **expand**: expands the selected contents. - - **collapse pattern**: same as collapse, but affects the entire pattern. - **expand pattern**: same as expand, but affects the entire pattern. - - **collapse song**: same as collapse, but affects the entire song. - it also changes speeds and pattern length to compensate. - **expand song**: same as expand, but affects the entire song. - it also changes speeds and pattern length to compensate. - -- _**find/replace**:_ shows [the Find/Replace window](../8-advanced/find-replace.md). - -- **clear**: opens a window that allows you to mass-delete things like songs, unused instruments, and the like. +- **find/replace**: shows [the Find/Replace window](../8-advanced/find-replace.md). +- **clear...**: opens a window that allows you to mass-delete things like songs, unused instruments, and the like. ## settings - **full screen**: expands the Furnace window so it covers your screen. - **lock layout**: prevents you from dragging/resizing docked windows, or docking more. -- **basic mode**: toggles [Basic Mode](basic-mode.md). -- **visualizer**: toggles pattern view particle effects when the song plays. +- **pattern visualizer**: toggles pattern view particle effects when the song plays. - **reset layout**: resets the workspace to its defaults. -- **settings...**: shows the Settings window. these are detailed in [settings.md]. +- **user systems...**: shows the User Systems window. this is detailed in [the User Systems documentation](../8-advanced/user-systems.md). +- **settings...**: shows the Settings window. these are detailed in [the Settings documentation](settings.md). ## window all these menu items show or hide their associated windows. -- [song information](song-info.md) -- [subsongs](song-info.md) -- [speed](song-info.md) -- [instruments](../4-instrument/README.md) -- [wavetables](../5-wave/README.md) -- [samples](../6-sample/README.md) -- [orders](order-list.md) -- [pattern](../3-pattern/README.md) -- _[mixer](../8-advanced/mixer.md)_ -- _[grooves](../8-advanced/grooves.md)_ -- _[channels](../8-advanced/channels.md)_ -- _[pattern manager](../8-advanced/pat-manager.md)_ -- _[chip manager](../8-advanced/chip-manager.md)_ -- _[compatibility flags](../8-advanced/compat-flags.md)_ -- [song comments](../8-advanced/comments.md) - -- [piano](../8-advanced/piano.md) -- [oscilloscope](../8-advanced/osc.md) -- [oscilloscopes (per-channel)](../8-advanced/chanosc.md) -- [clock](../8-advanced/clock.md) -- [register view](../8-advanced/regview.md) -- [log viewer](../8-advanced/log-viewer.md) -- [stats](../8-advanced/stats.md) +- song + - **[song comments](../8-advanced/comments.md)** + - **[song information](song-info.md)** + - **[subsongs](song-info.md)** + - **[channels](../8-advanced/channels.md)** + - **[chip manager](../8-advanced/chip-manager.md)** + - **[orders](order-list.md)** + - **[pattern](../3-pattern/README.md)** + - **[pattern manager](../8-advanced/pat-manager.md)** + - **[mixer](../8-advanced/mixer.md)** + - **[compatibility flags](../8-advanced/compat-flags.md)** +- assets + - **[instruments](../4-instrument/README.md)** + - **[samples](../6-sample/README.md)** + - **[wavetables](../5-wave/README.md)** + - **[instrument editor](../4-instrument/README.md)** + - **[sample editor](../6-sample/README.md)** + - **[wavetable editor](../5-wave/README.md)** +- visualizers + - **[oscilloscope](../8-advanced/osc.md)** + - **[oscilloscope (per-channel)](../8-advanced/chanosc.md)** + - **[oscilloscope (X-Y)](../8-advanced/xyosc.md)** + - volume meter +- tempo + - **[clock](../8-advanced/clock.md)** + - **[grooves](../8-advanced/grooves.md)** + - **[speed](song-info.md)** +- debug + - **[log viewer](../8-advanced/log-viewer.md)** + - **[register view](../8-advanced/regview.md)** + - **[statistics](../8-advanced/stats.md)** + - **[memory composition](../8-advanced/memory-composition.md)** +- **[effect list](../3-pattern/effects.md)** +- **[play/edit controls](play-edit-controls.md)** +- **[piano/input pad](../8-advanced/piano.md)** ## help diff --git a/doc/2-interface/play-edit-controls.md b/doc/2-interface/play-edit-controls.md index d7814ac25..47e4f103b 100644 --- a/doc/2-interface/play-edit-controls.md +++ b/doc/2-interface/play-edit-controls.md @@ -13,6 +13,7 @@ the "Play/Edit Controls" are used to control playback and change parameters of t - **Poly**: turns on polyphony for previewing notes. toggles to **Mono** for monophony (one note at a time only). - **Octave**: sets current input octave. - **Step**: sets edit step. if this is 1, entering a note or effect will move to the next row. if this is a larger number, rows will be skipped. if this is 0, the cursor will stay in place. + - if clicked, Step becomes **Coarse**, which sets the number of rows moved with `PgUp`, `PgDn`, and related movement shortcuts. clicking again will revert it to Step. - **Follow orders**: if on, the selected order in the orders window will follow the song during playback. - **Follow pattern**: if on, the cursor will follow playback and the song will scroll by as it plays. diff --git a/doc/2-interface/settings.md b/doc/2-interface/settings.md index ec61e9371..cfe12c949 100644 --- a/doc/2-interface/settings.md +++ b/doc/2-interface/settings.md @@ -1,25 +1,31 @@ # settings -the Settings window allows you to change Furnace setting. +the Settings window allows you to change Furnace settings. + +settings are saved when clicking the **OK** or **Apply** buttons at the bottom of the window, and when closing the program. several backups are kept in the Furnace settings directory. -settings are saved when clicking the **OK** or **Apply** buttons at the bottom of the window. ## General ### Program +- **Language**: select the language used for the interface. some languages are incomplete, and are listed with their approximate completion percentage. - **Render backend**: changing this may help with performace or compatibility issues. the available render backends are: + - SDL Renderer: this was the only available render backend prior to the addition of dedicated OpenGL/DirectX backends in 0.6. default on macOS. + - it is slower than the other backends. + - DirectX 11: works with the majority of graphics chips/cards and is optimized specifically for Windows. + - DirectX 9: use if your hardware is incompatible with DirectX 11. - OpenGL 3.0: works with the majority of graphics chips/cards (from 2010 onwards). default on Linux. - OpenGL 2.0: use if you have a card without OpenGL 3.0 support. - OpenGL 1.1: use if your card doesn't even support OpenGL 2.0. - - DirectX 11: works with the majority of graphics chips/cards and is optimized specifically for Windows. - - SDL Renderer: this was the only available render backend prior to the addition of dedicated OpenGL/DirectX backends in 0.6. default on macOS. - - it is slower than the other backends. - Software: this is a last resort backend which renders the interface in software. very slow! -- **Render driver**: this setting appears when using the SDL Renderer backend. it allows you to select an SDL render driver. +- **Advanced render backend settings**: only applicable with some render backends. + - **Render driver**: this setting only appears when using the SDL Renderer backend. it allows you to select an SDL render driver. + - OpenGL settings: these only appear when using an OpenGL backend, and should only be adjusted if the display is incorrect. - **VSync**: synchronizes rendering to VBlank and eliminates tearing. - **Frame rate limit**: allows you to set a frame rate limit (in frames per second). - only has effect when VSync is off or not available (e.g. software rendering or force-disabled on driver settings). +- **Display render time**: displays frame rate and frame render time at the right side of the menu bar. - **Late render clear**: this option is only useful when using old versions of Mesa drivers. it force-waits for VBlank by clearing after present, reducing latency. - **Power-saving mode**: saves power by lowering the frame rate to 2fps when idle. - may cause issues under Mesa drivers! @@ -49,6 +55,9 @@ settings are saved when clicking the **OK** or **Apply** buttons at the bottom o - **Remember last values** - **Store instrument name in .fui**: when enabled, saving an instrument will store its name. this may increase file size. - **Load instrument name from .fui**: when enabled, loading an instrument will use the stored name (if present). otherwise, it will use the file name. +- **Auto-fill file name when saving**: pre-fill the file name field when saving or exporting. + - when saving a module, the existing file name will be auto-filled. + - when saving an instrument or sample, its name will be auto-filled. ### New Song @@ -79,6 +88,11 @@ settings are saved when clicking the **OK** or **Apply** buttons at the bottom o - **New instruments are blank**: when enabled, adding FM instruments will make them blank (rather than loading the default one). +### Configuration +- **Import**: select an exported `.ini` config file to overwrite current settings. +- **Export**: select an `.ini` file to save current settings. +- **Factory Reset**: resets all settings to default and purges settings backups. + ## Audio ### Output @@ -100,9 +114,7 @@ settings are saved when clicking the **OK** or **Apply** buttons at the bottom o - **Sample rate**: audio output rate. - a lower rate decreases quality and isn't really beneficial. - if using PortAudio backend, be careful about this value. -- **Outputs**: number of audio outputs created, up to 16. - - only appears when Backend is JACK. -- **Channels**: mono, stereo or something. +- **Outputs**: number of audio outputs created, up to 16. default is 2 (stereo). - **Buffer size**: size of buffer in both samples and milliseconds. - setting this to a low value may cause stuttering/glitches in playback (known as "underruns" or "xruns"). - setting this to a high value increases latency. @@ -135,6 +147,7 @@ settings are saved when clicking the **OK** or **Apply** buttons at the bottom o ### MIDI input - **MIDI input**: input device. + - **Rescan MIDI devices**: repopulates list with all currently connected MIDI devices. useful if a device is connected while Furnace is running. - **Note input**: enables note input. disable if you intend to use this device only for binding actions. - **Velocity input**: enables velocity input when entering notes in the pattern. - **Map MIDI channels to direct channels**: when enabled, notes from MIDI channels will be mapped to channels rather than the cursor position. @@ -291,6 +304,7 @@ below all the binds, select a key from the dropdown list to add it. it will appe - **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. for example: - if off: moving the cursor onto the value `A5` and typing a "B" results in `0B`. - if on: moving the cursor onto the value `A5` and typing a "B" results in `5B`. +- **Keyboard note/value input repeat (hold key to input continuously)** - **Effect input behavior:** - **Move down**: after entering an effect (or effect value), the cursor moves down. - **Move to effect value (otherwise move down)**: after entering an effect, the cursor moves to its value. if entering a value, the cursor moves down. @@ -359,11 +373,7 @@ below all the binds, select a key from the dropdown list to add it. it will appe - **Pattern font** font for the pattern view, the order list, and related. - if "Custom...", a file path selector will appear. - **Size**: font size. -- **Display Japanese characters**, **Display Chinese (Simplified) characters**, **Display Chinese (Traditional) characters** and **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. - #### FreeType-specific settings - - **Anti-aliased fonts**: when enabled, fonts will be rendered smooth. - **Support bitmap fonts**: this option allows you to enable the loading of bitmap fonts. - be noted that this may force non-bitmap fonts to undesired sizes! @@ -376,6 +386,13 @@ below all the binds, select a key from the dropdown list to add it. it will appe - **Disable**: only rely upon font hinting data. - **Enable**: prefer font hinting data if present. - **Force**: ignore font hinting data. +#### non-specific settings +- **Oversample**: renders the font internally at higher resolution for visual quality. + - higher settings use more video memory. + - for pixel or bitmap fonts, set this to **1x**. +- **Load fallback font**: load an extra font that contains nearly all characters that can be used, in case the selected fonts lack them. uses much video memory +- **Display Japanese characters**, **Display Chinese (Simplified) characters**, **Display Chinese (Traditional) characters** and **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. ### Program @@ -386,15 +403,16 @@ below all the binds, select a key from the dropdown list to add it. it will appe - **/path/to/file.fur - Furnace** - **Display system name on title bar** - **Display chip names instead of "multi-system" in title bar** -- **Export options layout:** - - **Sub-menus in File menu**: export options appear in the File menu as sub-menus. - - **Modal window with tabs**: a single "export..." option that opens a dialog with export options. this is the default. - - **Modal windows with options in File menu**: like Sub-menus in File menu, but instead of being sub-menus, selecting one opens a dialog with export settings. - **Status bar:** - **Cursor details** - **File path** - **Cursor details or file path** - **Nothing** +- **Display playback status when playing**: display playback time and current location in the menu bar. +- **Export options layout:** + - **Sub-menus in File menu**: export options appear in the File menu as sub-menus. + - **Modal window with tabs**: a single "export..." option that opens a dialog with export options. this is the default. + - **Modal windows with options in File menu**: like Sub-menus in File menu, but instead of being sub-menus, selecting one opens a dialog with export settings. - **Capitalize menu bar** - **Display add/configure/change/remove chip menus in File menu**: if enabled, the "manage chips" item in the file menu is split into the four listed items for quick access. @@ -532,10 +550,10 @@ below all the binds, select a key from the dropdown list to add it. it will appe - **Rounded window corners** - **Rounded buttons** - **Rounded menu corners** +- **Rounded tabs** +- **Rounded scrollbars** - **Borders around widgets**: draws borders on buttons, checkboxes, text widgets, and the like. - - ## Color ### Color scheme @@ -544,9 +562,28 @@ below all the binds, select a key from the dropdown list to add it. it will appe - **Export** - **Reset defaults** - **Guru mode**: exposes all color options (instead of accent colors). -- **General** +- **Interface** + - **Frame shading**: applies a gradient effect to buttons and input boxes. - **Color scheme type:** - **Dark** - **Light** - - **Frame shading**: applies a gradient effect to buttons and input boxes. + - **Accent colors**: select main interface colors. + - **Primary** + - **Secondary** - several more categories... + +## Backup + +### Configuration + +- **Enable backup system**: turn on automatic backups of the current open file. +- **Interval (in seconds)**: time between automatic backups. +- **Backups per file**: maximum number of backups to store for each file. oldest backups are deleted first. + +### Backup Management + +- **Purge before**: + - **Go**: purge all backups from before the selected date. +- total space used by all backups: + - **Refresh**: recalculate space. + - **Delete All**: purge all backups. diff --git a/doc/2-interface/song-info.md b/doc/2-interface/song-info.md index 24a42f95e..f9773807c 100644 --- a/doc/2-interface/song-info.md +++ b/doc/2-interface/song-info.md @@ -3,11 +3,11 @@ - **Name**: the track's title. - **Author**: the author(s) of this track. - **Album**: the associated album name (or the name of the game the song is from). -- **System**: the game console or computer the track is designed for. this is automatically set when creating a new tune, but in advanced mode, it can be changed to anything one wants. the **Auto** button will provide a guess based on the chips in use. +- **System**: the name of the game console or computer the track is designed for. this is automatically set when creating a new tune, but can be changed to anything. the **Auto** button will provide a guess based on the chips in use. all of this metadata will be included in a VGM export. this isn't the case for an audio export, however. -- _**Tuning (A-4)**_: set tuning based on the note A-4, which should be 440 in most cases. opening an Amiga MOD will set it to 436 for hardware compatibility. available only in advanced mode. +- **Tuning (A-4)**: set tuning based on the note A-4, which should be 440 in most cases. opening an Amiga MOD will set it to 436 for hardware compatibility. ## subsongs @@ -23,16 +23,17 @@ this window allows one to create **subsongs** - multiple individual songs within there are multiple ways to set the tempo of a song. -items in _italic_ don't appear in basic mode and are only available in advanced mode. +**Base Tempo**: tempo in beats per minute (BPM). this is affected by the Highlight settings below. +- clicking the Base Tempo button switches to the more technical Tick Rate. **Tick Rate**: the frequency of ticks per second, thus the rate at which notes and effects are processed. - all values are allowed for all chips, though most chips have hardware limitations that mean they should stay at either 60 (approximately NTSC) or 50 (exactly PAL). -- clicking the Tick Rate button switches to a more traditional **Base Tempo** BPM setting. +- clicking the Tick Rate button switches to the more traditional Base Tempo BPM setting. **Speed**: the number of ticks per row. - clicking the "Speed" button changes to more complex modes covered in the [grooves](../8-advanced/grooves.md) page. -_**Virtual Tempo**:_ Simulates any arbitrary tempo without altering the tick rate. it does this by adding or skipping ticks to approximate the tempo. the two numbers represent a ratio applied to the actual tick rate. example: +**Virtual Tempo**: simulates any arbitrary tempo without altering the tick rate. it does this by adding or skipping ticks to approximate the tempo. the two numbers represent a ratio applied to the actual tick rate. example: - set tick rate to 150 BPM (60 Hz) and speed to 6. - set the first virtual tempo number (numerator) to 200. - set the second virtual tempo number (denominator) to 150. @@ -40,7 +41,8 @@ _**Virtual Tempo**:_ Simulates any arbitrary tempo without altering the tick rat - the ratio doesn't have to match BPM numbers. set the numerator to 4 and the denominator to 5, and the virtual BPM becomes 150 × 4/5 = 120. - another way to accomplish this with more control over the results is to use grooves. see the page on [grooves](../8-advanced/grooves.md) for details. -_**Divider**:_ Changes the effective tick rate. a tick rate of 60Hz and a divisor of 6 will result in ticks lasting a tenth of a second each! +**Divider**: changes the effective tick rate. a tick rate of 60Hz and a divisor of 6 will result in ticks lasting a tenth of a second each! +- to the right, the effective BPM is listed, taking all settings into account. **Highlight**: sets the pattern row highlights: - the first value represents the number of rows per beat. @@ -50,4 +52,4 @@ _**Divider**:_ Changes the effective tick rate. a tick rate of 60Hz and a diviso **Pattern Length**: the length of each pattern in rows. this affects all patterns in the song, and every pattern must be the same length. (Individual patterns can be cut short by `0Bxx`, `0Dxx`, and `FFxx` commands.) -_**Song Length**:_ how many orders are in the order list. decreasing it will hide the orders at the bottom. increasing it will restore those orders; increasing it further will add new orders of all `00` patterns. +**Song Length**: how many orders are in the order list. decreasing it will hide the orders at the bottom. increasing it will restore those orders; increasing it further will add new orders of all `00` patterns. diff --git a/doc/3-pattern/README.md b/doc/3-pattern/README.md index 31713ea64..77060b5f2 100644 --- a/doc/3-pattern/README.md +++ b/doc/3-pattern/README.md @@ -119,6 +119,10 @@ Shift-Up | expand selection upwards Shift-Down | expand selection downwards Shift-Left | expand selection to the left Shift-Right | expand selection to the right +Alt-Up | move selection up by one +Alt-Down | move selection down by one +Alt-Left | move selection to previous channel +Alt-Right | move selection to next channel Backspace | delete note at cursor and/or pull pattern upwards (configurable) Delete | delete selection Insert | create blank row at cursor position and push pattern diff --git a/doc/6-sample/README.md b/doc/6-sample/README.md index 2e870c95d..5ebe571c1 100644 --- a/doc/6-sample/README.md +++ b/doc/6-sample/README.md @@ -89,6 +89,7 @@ in there, you can modify certain data pertaining to your sample, such as the: - **Open**: replaces current sample. - right-clicking brings up a menu: - **import raw...**: brings up a file selector, then presents a dialog to choose the format of the selected file. + - **import raw (replace)...**: same as above, but instead of adding it to the sample list, it replaces the currently selected sample. - **Save**: saves current sample to disk. - right-clicking brings up a menu: - **save raw...**: brings up a file selector, then saves the sample as raw data. diff --git a/doc/7-systems/gba.md b/doc/7-systems/gba.md index 692d8db0d..a0653a5fe 100644 --- a/doc/7-systems/gba.md +++ b/doc/7-systems/gba.md @@ -15,11 +15,11 @@ it features echo and up to 16 voices. - `10xx`: **change wave.** - `11xy`: **configure echo.** - - this effect is kinda odd. this is how it works: - -> How do you echo on GBA -> -> Create an empty instrment and put a very high note of it in channel 1 then do 110x in effect column and set volume column to set feedback and do nothing else on it + - this effect is kinda odd. here's how to use it: + - create an empty instrument and put a very high note of it in channel 1. + - put `110x` in the effect column. + - set volume column to set feedback. + - don't use the channel for anything else. - `12xy`: **toggle invert.** - `x` left channel. diff --git a/doc/7-systems/snes.md b/doc/7-systems/snes.md index 7b39ed87f..978af2106 100644 --- a/doc/7-systems/snes.md +++ b/doc/7-systems/snes.md @@ -59,7 +59,7 @@ Furnace also allows the SNES to use wavetables (and the wavetable synthesizer) i - `00` to `7F` for 0 to 127. - `80` to `FF` for -128 to -1. - note: be sure the sum of all coefficients is between -128 and 127. sums outside that may result in overflow and therefore clicking. - - see [SnesLab](https://sneslab.net/wiki/FIR_Filter) for a full explanation and examples. + - see SnesLab for [echo filter explanations and examples](https://sneslab.net/wiki/FIR_Filter#Uses). ## info @@ -67,6 +67,8 @@ this chip uses the [SNES](../4-instrument/snes.md) instrument editor. when two channels are joined for pitch modulation, the channel bar will show `mod` on a bracket tying them together. +when using sample offset commands, be sure to open each involved sample in the sample editor, look to the "Info" section at the top-left, and check the "no BRR filters" box. this prevents sound glitches, at the cost of lowering the sample quality to 4-bit. + ## channel status the following icons are displayed when channel status is enabled in the pattern view: @@ -93,6 +95,8 @@ the following options are available in the Chip Manager window: - **Feedback**: sets how much of the echo output will be fed back into the buffer. - **Echo volume**: sets echo volume. - **Echo filter**: adjusts echo filter. +- **Dec/Hex**: toggles decimal or hexadecimal mode for the filter settings text entry box to the right. + - SnesLab provides [echo filter explanations and examples](https://sneslab.net/wiki/FIR_Filter#Uses). their example filter strings can be pasted directly into the filter settings text entry box if set to Hex mode. ## ADSR diff --git a/doc/8-advanced/README.md b/doc/8-advanced/README.md index 4a9512823..759737e0e 100644 --- a/doc/8-advanced/README.md +++ b/doc/8-advanced/README.md @@ -8,22 +8,27 @@ as listed in the "Edit" menu: as listed in the "Window" menu: -- [mixer](mixer.md) -- [grooves](grooves.md) -- [channel manager](channels.md) -- [pattern manager](pat-manager.md) -- [chip manager](chip-manager.md) -- [compatibility flags](compat-flags.md) -- [song comments](comments.md) - -- [piano](piano.md) -- [oscilloscope](osc.md) -- [oscilloscope (X-Y)](xyosc.md) -- [oscilloscopes (per-channel)](chanosc.md) -- [clock](clock.md) -- [register view](regview.md) -- [log viewer](log-viewer.md) -- [stats](stats.md) +- song + - [song comments](../8-advanced/comments.md) + - [channels](../8-advanced/channels.md) + - [chip manager](../8-advanced/chip-manager.md) + - [pattern manager](../8-advanced/pat-manager.md) + - [mixer](../8-advanced/mixer.md) + - [compatibility flags](../8-advanced/compat-flags.md) +- visualizers + - [oscilloscope](../8-advanced/osc.md) + - [oscilloscope (per-channel)](../8-advanced/chanosc.md) + - [oscilloscope (X-Y)](../8-advanced/xyosc.md) + - volume meter +- tempo + - [clock](../8-advanced/clock.md) + - [grooves](../8-advanced/grooves.md) +- debug + - [log viewer](../8-advanced/log-viewer.md) + - [register view](../8-advanced/regview.md) + - [statistics](../8-advanced/stats.md) + - [memory composition](../8-advanced/memory-composition.md) +- [piano/input pad](../8-advanced/piano.md) other: diff --git a/doc/8-advanced/channels.md b/doc/8-advanced/channels.md index 5b70f00dd..53bc00065 100644 --- a/doc/8-advanced/channels.md +++ b/doc/8-advanced/channels.md @@ -5,8 +5,9 @@ the "Channels" dialog allows manipulation of the song's channels. ![channels dialog](channels.png) each channel has the following options: -- **Visible**: uncheck the box to hide the channel from the pattern view. pattern data will be kept. -- crossed-arrows button: click and drag to rearrange pattern data throughout the song. +- **Pat**: uncheck the box to hide the channel from the pattern view. pattern data will be kept. +- **Osc**: uncheck the box to hide the channel from the per-channel oscilloscope view. +- **Swap**: click and drag to rearrange pattern data throughout the song. - note: this does **not** move channels around! it only moves the channel's pattern data. - **Name**: the name displayed at the top of each channel in the pattern view. - the next setting is "short name", which is displayed in the orders view and/or when a channel is collapsed. diff --git a/doc/8-advanced/chanosc.md b/doc/8-advanced/chanosc.md index 6a2cd27ed..54163dfb3 100644 --- a/doc/8-advanced/chanosc.md +++ b/doc/8-advanced/chanosc.md @@ -14,6 +14,7 @@ right-clicking the view will display the configuration view shown above: - **Mode 2**: bias slightly toward more columns. - **Mode 3**: always more columns than rows. - **Amplitude**: scales amplitude for all oscilloscope views. +- **Line size**: controls line thickness. - **Gradient**: this allows you to use a gradient for determining the waveforms' colors instead of a single color. see the gradient section for more information. - if this option is off, a color selector will be displayed. right-click on it for some options: - select between the square selector and the color wheel selector. diff --git a/doc/8-advanced/chip-manager.md b/doc/8-advanced/chip-manager.md index 41a187fd9..09388e802 100644 --- a/doc/8-advanced/chip-manager.md +++ b/doc/8-advanced/chip-manager.md @@ -8,6 +8,8 @@ the **chip manager** window allows you to manage chips, including adding, changi **Clone channel data**: when cloning chips, also copy patterns, pattern names, channel names and other parameters to the clone. +**Clone at end**: instead of inserting the clone directly after the cloned chip, add it to the end. + to move a chip around, click and drag the ![crossed-arrows](chip-manager-move.png) button to the left. to duplicate a chip, click the **Clone** button. diff --git a/doc/8-advanced/user-systems.md b/doc/8-advanced/user-systems.md new file mode 100644 index 000000000..d60772654 --- /dev/null +++ b/doc/8-advanced/user-systems.md @@ -0,0 +1,22 @@ +# user systems + +combinations of chips and chip configurations can be stored as **user systems** – presets that are easily accessed when starting a new song. + +![user systems window](user-systems.png) + +the `+` button at the top of the **Systems** list will add a new system. + +next to the **Name** field, the **Remove** button removes the current system from the list. + +chip configuration is exactly as in the [chip manager](chip-manager.md) window. + +the **Advanced** field stores additional settings that are set when a new song is started. these are listed in "option=value" format, one per line. +- `tickRate`: sets tick rate. + +**Save and Close**: as it says. + +**Import**: opens a dialog to select a `.cfgu` file, then adds its systems to the list. + +**Import (replace)**: opens a similar dialog, then clears the existing systems list and replaces it with the imported one. + +**Export**: stores the current list of systems in a selected `.cfgu` file. \ No newline at end of file diff --git a/doc/8-advanced/user-systems.png b/doc/8-advanced/user-systems.png new file mode 100644 index 000000000..c300530a3 Binary files /dev/null and b/doc/8-advanced/user-systems.png differ diff --git a/src/engine/fileOps/it.cpp b/src/engine/fileOps/it.cpp index a3ed09c49..a729706d7 100644 --- a/src/engine/fileOps/it.cpp +++ b/src/engine/fileOps/it.cpp @@ -639,6 +639,8 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { logD("seek not needed..."); } + logV("reading sample data (%d)",s->samples); + if (flags&8) { // compressed sample unsigned int ret=0; logV("decompression begin... (%d)",s->samples); @@ -672,62 +674,66 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { } logV("got: %d",ret); } else { - if (s->depth==DIV_SAMPLE_DEPTH_16BIT) { - if (flags&4) { // downmix stereo - for (unsigned int i=0; isamples; i++) { - short l; - if (convert&2) { - l=reader.readS_BE(); - } else { - l=reader.readS(); + try { + if (s->depth==DIV_SAMPLE_DEPTH_16BIT) { + if (flags&4) { // downmix stereo + for (unsigned int i=0; isamples; i++) { + short l; + if (convert&2) { + l=reader.readS_BE(); + } else { + l=reader.readS(); + } + if (!(convert&1)) { + l^=0x8000; + } + s->data16[i]=l; } - if (!(convert&1)) { - l^=0x8000; + for (unsigned int i=0; isamples; i++) { + short r; + if (convert&2) { + r=reader.readS_BE(); + } else { + r=reader.readS(); + } + if (!(convert&1)) { + r^=0x8000; + } + s->data16[i]=(s->data16[i]+r)>>1; } - s->data16[i]=l; - } - for (unsigned int i=0; isamples; i++) { - short r; - if (convert&2) { - r=reader.readS_BE(); - } else { - r=reader.readS(); + } else { + for (unsigned int i=0; isamples; i++) { + if (convert&2) { + s->data16[i]=reader.readS_BE()^((convert&1)?0:0x8000); + } else { + s->data16[i]=reader.readS()^((convert&1)?0:0x8000); + } } - if (!(convert&1)) { - r^=0x8000; - } - s->data16[i]=(s->data16[i]+r)>>1; } } else { - for (unsigned int i=0; isamples; i++) { - if (convert&2) { - s->data16[i]=reader.readS_BE()^((convert&1)?0:0x8000); - } else { - s->data16[i]=reader.readS()^((convert&1)?0:0x8000); + if (flags&4) { // downmix stereo + for (unsigned int i=0; isamples; i++) { + signed char l=reader.readC(); + if (!(convert&1)) { + l^=0x80; + } + s->data8[i]=l; + } + for (unsigned int i=0; isamples; i++) { + signed char r=reader.readC(); + if (!(convert&1)) { + r^=0x80; + } + s->data8[i]=(s->data8[i]+r)>>1; + } + } else { + for (unsigned int i=0; isamples; i++) { + s->data8[i]=reader.readC()^((convert&1)?0:0x80); } } } - } else { - if (flags&4) { // downmix stereo - for (unsigned int i=0; isamples; i++) { - signed char l=reader.readC(); - if (!(convert&1)) { - l^=0x80; - } - s->data8[i]=l; - } - for (unsigned int i=0; isamples; i++) { - signed char r=reader.readC(); - if (!(convert&1)) { - r^=0x80; - } - s->data8[i]=(s->data8[i]+r)>>1; - } - } else { - for (unsigned int i=0; isamples; i++) { - s->data8[i]=reader.readC()^((convert&1)?0:0x80); - } - } + } catch (EndOfFileException& e) { + logW("premature end of file..."); } } diff --git a/src/engine/fileOps/s3m.cpp b/src/engine/fileOps/s3m.cpp index d13c1c7c2..9e212d8d3 100644 --- a/src/engine/fileOps/s3m.cpp +++ b/src/engine/fileOps/s3m.cpp @@ -51,6 +51,7 @@ static void readSbiOpData(sbi_t& sbi, SafeReader& reader) { bool DivEngine::loadS3M(unsigned char* file, size_t len) { struct InvalidHeaderException {}; bool success=false; + bool opl2=!getConfInt("s3mOPL3",0); char magic[4]={0,0,0,0}; SafeReader reader=SafeReader(file,len); warnings=""; @@ -273,11 +274,16 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { bool hasPCM=false; bool hasFM=false; int numChans=0; + int realNumChans=0; - for (int i=0; i<32; i++) { - if (chanSettings[i]==255) continue; - if ((chanSettings[i]&127)>=32) continue; - if ((chanSettings[i]&127)>=16) { + for (int ch=0; ch<32; ch++) { + if (chanSettings[ch]!=255) realNumChans++; + } + + for (int ch=0; ch<32; ch++) { + if (chanSettings[ch]==255) continue; + if ((chanSettings[ch]&127)>=32) continue; + if ((chanSettings[ch]&127)>=16) { hasFM=true; } else { hasPCM=true; @@ -287,34 +293,69 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { if (hasFM && hasPCM) break; } - int pcmChan=hasFM?9:0; + int pcmChan=hasFM?(opl2 ? 9 : 18):0; int fmChan=hasPCM?32:0; int invalidChan=40; - for (int i=0; i<32; i++) { - if (chanSettings[i]==255) { - chanMap[i]=invalidChan++; + for (int ch=0; ch<32; ch++) { + if (chanSettings[ch]==255) { + chanMap[ch]=invalidChan++; continue; } - if ((chanSettings[i]&127)>=32) { - chanMap[i]=invalidChan++; + if ((chanSettings[ch]&127)>=32) { + chanMap[ch]=invalidChan++; continue; } - if ((chanSettings[i]&127)>=16) { - chanMap[i]=fmChan++; + if ((chanSettings[ch]&127)>=16) { + chanMap[ch]=fmChan++; } else { - chanMap[i]=pcmChan++; + chanMap[ch]=pcmChan++; } } + char buffer[40]; + int chanIndex = 1; + if (hasPCM) { - for (int i=pcmChan; i<32; i++) { - ds.subsong[0]->chanShow[i]=false; - ds.subsong[0]->chanShowChanOsc[i]=false; + for(int ch = 0; ch < pcmChan - (realNumChans - (hasFM ? 9 : 0)); ch++) + { + ds.subsong[0]->chanShow[ch]=false; + ds.subsong[0]->chanShowChanOsc[ch]=false; + } + + for (int ch=pcmChan; ch<32; ch++) { + ds.subsong[0]->chanShow[ch]=false; + ds.subsong[0]->chanShowChanOsc[ch]=false; + } + + for(int ch = 0; ch < 32; ch++) + { + if(ds.subsong[0]->chanShow[ch]) + { + snprintf(buffer, 40, _("Channel %d"), chanIndex); + ds.subsong[0]->chanName[ch] = buffer; + chanIndex++; + } + } + } + + if (hasFM && !opl2) { + for (int ch=(hasPCM?32:0) + 9; ch<(hasPCM?32:0) + 18; ch++) { + ds.subsong[0]->chanShow[ch]=false; + ds.subsong[0]->chanShowChanOsc[ch]=false; + } + + chanIndex = 1; + + for (int ch=(hasPCM?32:0); ch<(hasPCM?32:0) + 9; ch++) { + snprintf(buffer, 40, _("FM %d"), chanIndex); + ds.subsong[0]->chanName[ch] = buffer; + chanIndex++; } } logV("numChans: %d",numChans); + logV("realNumChans: %d",realNumChans); ds.systemName="PC"; if (hasPCM) { @@ -327,7 +368,7 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { ds.systemLen++; } if (hasFM) { - ds.system[ds.systemLen]=DIV_SYSTEM_OPL2; + ds.system[ds.systemLen]=opl2 ? DIV_SYSTEM_OPL2 : DIV_SYSTEM_OPL3; ds.systemVol[ds.systemLen]=1.0f; ds.systemPan[ds.systemLen]=0; ds.systemLen++; diff --git a/src/gui/debugWindow.cpp b/src/gui/debugWindow.cpp index 594554c57..b08c60532 100644 --- a/src/gui/debugWindow.cpp +++ b/src/gui/debugWindow.cpp @@ -36,6 +36,8 @@ static float oscDebugMax=1.0; static float oscDebugPower=1.0; static int oscDebugRepeat=1; static int numApples=1; +static int getGainChan=0; +static int getGainVol=0; static void _drawOsc(const ImDrawList* drawList, const ImDrawCmd* cmd) { if (cmd!=NULL) { @@ -721,6 +723,13 @@ void FurnaceGUI::drawDebug() { ImGui::TreePop(); } #endif + if (ImGui::TreeNode("Get Gain Test")) { + float realVol=e->getGain(getGainChan,getGainVol); + ImGui::InputInt("Chan",&getGainChan); + ImGui::InputInt("Vol",&getGainVol); + ImGui::Text("result: %.0f%%",realVol*100.0f); + ImGui::TreePop(); + } if (ImGui::TreeNode("User Interface")) { if (ImGui::Button("Inspect")) { inspectorOpen=!inspectorOpen; diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index fff5a85d9..bf5b89519 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -676,6 +676,17 @@ void FurnaceGUI::doAction(int what) { latchTarget=0; latchNibble=false; break; + case GUI_ACTION_PAT_ABSORB_INSTRUMENT: { + DivPattern* pat=e->curPat[cursor.xCoarse].getPattern(e->curOrders->ord[cursor.xCoarse][curOrder],false); + if (!pat) break; + for (int i=cursor.y; i>=0; i--) { + if (pat->data[i][2] >= 0) { + curIns=pat->data[i][2]; + break; + } + } + break; + } case GUI_ACTION_INS_LIST_ADD: if (settings.insTypeMenu) { diff --git a/src/gui/gui.h b/src/gui/gui.h index 5af5ca026..86a68a8f5 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -817,6 +817,7 @@ enum FurnaceGUIActions { GUI_ACTION_PAT_LATCH, GUI_ACTION_PAT_SCROLL_MODE, GUI_ACTION_PAT_CLEAR_LATCH, + GUI_ACTION_PAT_ABSORB_INSTRUMENT, GUI_ACTION_PAT_MAX, GUI_ACTION_INS_LIST_MIN, @@ -1958,6 +1959,7 @@ class FurnaceGUI { unsigned int maxUndoSteps; float vibrationStrength; int vibrationLength; + int s3mOPL3; String mainFontPath; String headFontPath; String patFontPath; @@ -2214,6 +2216,7 @@ class FurnaceGUI { maxUndoSteps(100), vibrationStrength(0.5f), vibrationLength(20), + s3mOPL3(0), mainFontPath(""), headFontPath(""), patFontPath(""), diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index a23ac03d7..dc634b969 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -688,6 +688,7 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={ D("PAT_LATCH", _N("Set note input latch"), 0), D("PAT_SCROLL_MODE", _N("Change mobile scroll mode"), 0), D("PAT_CLEAR_LATCH", _N("Clear note input latch"), 0), + D("PAT_ABSORB_INSTRUMENT", _N("Set current instrument to channel's current instrument column"), 0), D("PAT_MAX", "", NOT_AN_ACTION), D("INS_LIST_MIN", _N("---Instrument list"), NOT_AN_ACTION), diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index a84cff3e7..9f002816c 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -1254,6 +1254,14 @@ void FurnaceGUI::drawSettings() { } popDestColor(); + // SUBSECTION IMPORT + CONFIG_SUBSECTION(_("Import")); + bool s3mOPL3B=settings.s3mOPL3; + if (ImGui::Checkbox(_("Use OPL3 instead of OPL2 for S3M import"),&s3mOPL3B)) { + settings.s3mOPL3=s3mOPL3B; + settingsChanged=true; + } + END_SECTION; } CONFIG_SECTION(_("Audio")) { @@ -2415,6 +2423,7 @@ void FurnaceGUI::drawSettings() { UI_KEYBIND_CONFIG(GUI_ACTION_PAT_EXPAND_SONG); UI_KEYBIND_CONFIG(GUI_ACTION_PAT_LATCH); UI_KEYBIND_CONFIG(GUI_ACTION_PAT_CLEAR_LATCH); + UI_KEYBIND_CONFIG(GUI_ACTION_PAT_ABSORB_INSTRUMENT); KEYBIND_CONFIG_END; ImGui::TreePop(); @@ -4746,6 +4755,8 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { settings.vibrationStrength=conf.getFloat("vibrationStrength",0.5f); settings.vibrationLength=conf.getInt("vibrationLength",20); + settings.s3mOPL3=conf.getInt("s3mOPL3",0); + settings.backupEnable=conf.getInt("backupEnable",1); settings.backupInterval=conf.getInt("backupInterval",30); settings.backupMaxCopies=conf.getInt("backupMaxCopies",5); @@ -5258,6 +5269,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { clampSetting(settings.backupMaxCopies,1,100); clampSetting(settings.autoFillSave,0,1); clampSetting(settings.autoMacroStepSize,0,1); + clampSetting(settings.s3mOPL3,0,1); if (settings.exportLoops<0.0) settings.exportLoops=0.0; if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0; @@ -5331,6 +5343,8 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("vibrationStrength",settings.vibrationStrength); conf.set("vibrationLength",settings.vibrationLength); + conf.set("s3mOPL3",settings.s3mOPL3); + conf.set("backupEnable",settings.backupEnable); conf.set("backupInterval",settings.backupInterval); conf.set("backupMaxCopies",settings.backupMaxCopies);