From ad4572be43f1cd5a35a19198b006a6c1b45a08b8 Mon Sep 17 00:00:00 2001 From: Eknous-P Date: Fri, 24 Oct 2025 11:19:38 +0400 Subject: [PATCH] formats combo, more format for wav export --- src/engine/engine.h | 17 ++++++++--- src/engine/wavOps.cpp | 53 +++++++++++++++++++++++++++------- src/gui/exportOptions.cpp | 61 ++++++++++++++++++++++----------------- 3 files changed, 89 insertions(+), 42 deletions(-) diff --git a/src/engine/engine.h b/src/engine/engine.h index 18fdcf1f8..254a8ad02 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -102,8 +102,7 @@ enum DivMIDIModes { }; enum DivAudioExportFormats { - DIV_EXPORT_FORMAT_S16=0, - DIV_EXPORT_FORMAT_F32, + DIV_EXPORT_FORMAT_WAV=0, DIV_EXPORT_FORMAT_OPUS, DIV_EXPORT_FORMAT_FLAC, DIV_EXPORT_FORMAT_VORBIS, @@ -116,10 +115,18 @@ enum DivAudioExportBitrateModes { DIV_EXPORT_BITRATE_AVERAGE, }; +enum DivAudioExportWavFormats { + DIV_EXPORT_WAV_U8=0, + DIV_EXPORT_WAV_S16, + DIV_EXPORT_WAV_S32, + DIV_EXPORT_WAV_F32 +}; + struct DivAudioExportOptions { DivAudioExportModes mode; DivAudioExportFormats format; DivAudioExportBitrateModes bitRateMode; + DivAudioExportWavFormats wavFormat; int sampleRate; int chans; int loops; @@ -130,7 +137,7 @@ struct DivAudioExportOptions { float vbrQuality; DivAudioExportOptions(): mode(DIV_EXPORT_MODE_ONE), - format(DIV_EXPORT_FORMAT_S16), + format(DIV_EXPORT_FORMAT_WAV), bitRateMode(DIV_EXPORT_BITRATE_CONSTANT), sampleRate(44100), chans(2), @@ -514,6 +521,7 @@ class DivEngine { DivAudioEngines audioEngine; DivAudioExportModes exportMode; DivAudioExportFormats exportFormat; + DivAudioExportWavFormats wavFormat; DivAudioExportBitrateModes exportBitRateMode; double exportFadeOut; bool isFadingOut; @@ -1506,7 +1514,8 @@ class DivEngine { haltOn(DIV_HALT_NONE), audioEngine(DIV_AUDIO_NULL), exportMode(DIV_EXPORT_MODE_ONE), - exportFormat(DIV_EXPORT_FORMAT_S16), + exportFormat(DIV_EXPORT_FORMAT_WAV), + wavFormat(DIV_EXPORT_WAV_S16), exportBitRateMode(DIV_EXPORT_BITRATE_CONSTANT), exportFadeOut(0.0), isFadingOut(false), diff --git a/src/engine/wavOps.cpp b/src/engine/wavOps.cpp index 805fc2733..5c2a4f894 100644 --- a/src/engine/wavOps.cpp +++ b/src/engine/wavOps.cpp @@ -113,7 +113,7 @@ bool DivEngine::getIsFadingOut() { #ifdef HAVE_SNDFILE #define MAP_BITRATE \ - if (exportFormat!=DIV_EXPORT_FORMAT_S16 && exportFormat!=DIV_EXPORT_FORMAT_F32) { \ + if (exportFormat!=DIV_EXPORT_FORMAT_WAV) { \ double mappedLevel=0.0; \ \ switch (exportFormat) { \ @@ -179,11 +179,26 @@ void DivEngine::runExportThread() { si.samplerate=got.rate; si.channels=exportOutputs; switch (exportFormat) { - case DIV_EXPORT_FORMAT_S16: - si.format=SF_FORMAT_WAV|SF_FORMAT_PCM_16; - break; - case DIV_EXPORT_FORMAT_F32: - si.format=SF_FORMAT_WAV|SF_FORMAT_FLOAT; + case DIV_EXPORT_FORMAT_WAV: + si.format=SF_FORMAT_WAV; + switch (wavFormat) { + case DIV_EXPORT_WAV_U8: + si.format|=SF_FORMAT_PCM_U8; + break; + case DIV_EXPORT_WAV_S16: + si.format|=SF_FORMAT_PCM_16; + break; + case DIV_EXPORT_WAV_S32: + si.format|=SF_FORMAT_PCM_32; + break; + case DIV_EXPORT_WAV_F32: + si.format|=SF_FORMAT_FLOAT; + break; + default: + si.format|=SF_FORMAT_PCM_U8; + logW("wtf"); + break; + } break; case DIV_EXPORT_FORMAT_OPUS: si.format=SF_FORMAT_OGG|SF_FORMAT_OPUS; @@ -426,11 +441,26 @@ void DivEngine::runExportThread() { si.samplerate=got.rate; si.channels=exportOutputs; switch (exportFormat) { - case DIV_EXPORT_FORMAT_S16: - si.format=SF_FORMAT_WAV|SF_FORMAT_PCM_16; - break; - case DIV_EXPORT_FORMAT_F32: - si.format=SF_FORMAT_WAV|SF_FORMAT_FLOAT; + case DIV_EXPORT_FORMAT_WAV: + si.format=SF_FORMAT_WAV; + switch (wavFormat) { + case DIV_EXPORT_WAV_U8: + si.format|=SF_FORMAT_PCM_U8; + break; + case DIV_EXPORT_WAV_S16: + si.format|=SF_FORMAT_PCM_16; + break; + case DIV_EXPORT_WAV_S32: + si.format|=SF_FORMAT_PCM_32; + break; + case DIV_EXPORT_WAV_F32: + si.format|=SF_FORMAT_FLOAT; + break; + default: + si.format|=SF_FORMAT_PCM_U8; + logW("wtf"); + break; + } break; case DIV_EXPORT_FORMAT_OPUS: si.format=SF_FORMAT_OGG|SF_FORMAT_OPUS; @@ -584,6 +614,7 @@ bool DivEngine::saveAudio(const char* path, DivAudioExportOptions options) { exportPath=path; exportMode=options.mode; exportFormat=options.format; + wavFormat=options.wavFormat; exportBitRate=options.bitRate; exportBitRateMode=options.bitRateMode; exportVBRQuality=options.vbrQuality; diff --git a/src/gui/exportOptions.cpp b/src/gui/exportOptions.cpp index 759111d9c..e3a708cbd 100644 --- a/src/gui/exportOptions.cpp +++ b/src/gui/exportOptions.cpp @@ -23,6 +23,21 @@ #include "misc/cpp/imgui_stdlib.h" #include +const char* audioExportFormats[]={ + _("Wave"), + _("Opus"), + _("FLAC (Free Lossless Audio Codec)"), + _("Vorbis"), + _("MP3") +}; + +const char* audioExportWavFormats[]={ + _("Unsigned 8-bit"), + _("Signed 16-bit"), + _("Signed 32-bit"), + _("FLoat 32-bit"), +}; + void FurnaceGUI::drawExportAudio(bool onWindow) { exitDisabledTimer=1; @@ -34,7 +49,8 @@ void FurnaceGUI::drawExportAudio(bool onWindow) { } if (ImGui::RadioButton(_("multiple files (one per chip)"),audioExportOptions.mode==DIV_EXPORT_MODE_MANY_SYS)) { audioExportOptions.mode=DIV_EXPORT_MODE_MANY_SYS; - audioExportOptions.format=DIV_EXPORT_FORMAT_S16; + audioExportOptions.format=DIV_EXPORT_FORMAT_WAV; + audioExportOptions.wavFormat=DIV_EXPORT_WAV_S16; } if (ImGui::RadioButton(_("multiple files (one per channel)"),audioExportOptions.mode==DIV_EXPORT_MODE_MANY_CHAN)) { audioExportOptions.mode=DIV_EXPORT_MODE_MANY_CHAN; @@ -42,31 +58,14 @@ void FurnaceGUI::drawExportAudio(bool onWindow) { ImGui::Unindent(); if (audioExportOptions.mode!=DIV_EXPORT_MODE_MANY_SYS) { - ImGui::Text(_("File format:")); - ImGui::Indent(); - if (ImGui::RadioButton(_("Wave (16-bit integer)"),audioExportOptions.format==DIV_EXPORT_FORMAT_S16)) { - audioExportOptions.format=DIV_EXPORT_FORMAT_S16; - } - if (ImGui::RadioButton(_("Wave (32-bit float)"),audioExportOptions.format==DIV_EXPORT_FORMAT_F32)) { - audioExportOptions.format=DIV_EXPORT_FORMAT_F32; - } - if (supportsOgg) { - if (ImGui::RadioButton(_("Opus"),audioExportOptions.format==DIV_EXPORT_FORMAT_OPUS)) { - audioExportOptions.format=DIV_EXPORT_FORMAT_OPUS; - } - if (ImGui::RadioButton(_("FLAC (Free Lossless Audio Codec)"),audioExportOptions.format==DIV_EXPORT_FORMAT_FLAC)) { - audioExportOptions.format=DIV_EXPORT_FORMAT_FLAC; - } - if (ImGui::RadioButton(_("Vorbis"),audioExportOptions.format==DIV_EXPORT_FORMAT_VORBIS)) { - audioExportOptions.format=DIV_EXPORT_FORMAT_VORBIS; + if (ImGui::BeginCombo(_("File Format"), audioExportFormats[audioExportOptions.format])) { + for (size_t i=0; i<(supportsMP3?5:4); i++) { + if (ImGui::Selectable(audioExportFormats[i],audioExportOptions.format==i)) { + audioExportOptions.format=(DivAudioExportFormats)i; } } - if (supportsMP3) { - if (ImGui::RadioButton(_("MP3"),audioExportOptions.format==DIV_EXPORT_FORMAT_MPEG_L3)) { - audioExportOptions.format=DIV_EXPORT_FORMAT_MPEG_L3; - } - } - ImGui::Unindent(); + ImGui::EndCombo(); + } } bool rateCheck=( @@ -126,7 +125,7 @@ void FurnaceGUI::drawExportAudio(bool onWindow) { } } - if (audioExportOptions.format!=DIV_EXPORT_FORMAT_S16 && audioExportOptions.format!=DIV_EXPORT_FORMAT_F32) { + if (audioExportOptions.format!=DIV_EXPORT_FORMAT_WAV) { if (audioExportOptions.format==DIV_EXPORT_FORMAT_FLAC) { if (ImGui::SliderFloat(_("Compression level"),&audioExportOptions.vbrQuality,0,8)) { if (audioExportOptions.vbrQuality<0) audioExportOptions.vbrQuality=0; @@ -143,6 +142,15 @@ void FurnaceGUI::drawExportAudio(bool onWindow) { if (audioExportOptions.bitRatemaxBitRate) audioExportOptions.bitRate=maxBitRate; } + } else { + if (ImGui::BeginCombo(_("Format"), audioExportWavFormats[audioExportOptions.wavFormat])) { + for (size_t i=0; i<4; i++) { + if (ImGui::Selectable(audioExportWavFormats[i], audioExportOptions.wavFormat==i)) { + audioExportOptions.wavFormat=(DivAudioExportWavFormats)i; + } + } + ImGui::EndCombo(); + } } if (ImGui::InputInt(_("Loops"),&audioExportOptions.loops,1,2)) { @@ -207,8 +215,7 @@ void FurnaceGUI::drawExportAudio(bool onWindow) { if (isOneOn && !rateCheck) { if (ImGui::Button(_("Export"),ImVec2(200.0f*dpiScale,0))) { switch (audioExportOptions.format) { - case DIV_EXPORT_FORMAT_S16: - case DIV_EXPORT_FORMAT_F32: + case DIV_EXPORT_FORMAT_WAV: audioExportFilterName=_("Wave file"); audioExportFilterExt=".wav"; break;