diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index d46ced4f..822109be 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -19,6 +19,7 @@ #include "sample.h" #include "../ta-log.h" +#include "../fileutils.h" #include #include #ifdef HAVE_SNDFILE @@ -444,6 +445,28 @@ bool DivSample::save(const char* path) { #endif } +bool DivSample::saveRaw(const char* path) { + if (samples<1) { + logE("sample is empty though!"); + return false; + } + + FILE* f=ps_fopen(path,"wb"); + if (f==NULL) { + logE("could not save sample: %s!",strerror(errno)); + return false; + } + if (depth==DIV_SAMPLE_DEPTH_BRR && getLoopStartPosition(DIV_SAMPLE_DEPTH_BRR)) {\ + // TODO: BRR loop pos? + } + + if (fwrite(getCurBuf(),1,getCurBufLen(),f)!=getCurBufLen()) { + logW("did not write entire instrument!"); + } + fclose(f); + return true; +} + // 16-bit memory is padded to 512, to make things easier for ADPCM-A/B. bool DivSample::initInternal(DivSampleDepth d, int count) { switch (d) { diff --git a/src/engine/sample.h b/src/engine/sample.h index 76eaee9a..8006ab0b 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -201,6 +201,13 @@ struct DivSample { */ bool save(const char* path); + /** + * save this sample to a file (raw). + * @param path a path. + * @return whether saving succeeded or not. + */ + bool saveRaw(const char* path); + /** * @warning DO NOT USE - internal function * initialize sample data. diff --git a/src/gui/dataList.cpp b/src/gui/dataList.cpp index 2a37c7e8..cce7f09c 100644 --- a/src/gui/dataList.cpp +++ b/src/gui/dataList.cpp @@ -700,6 +700,11 @@ void FurnaceGUI::drawSampleList(bool asChild) { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Save"); } + if (ImGui::BeginPopupContextItem("SampleSaveOpt")) { + if (ImGui::MenuItem("save raw...")) { + doAction(GUI_ACTION_SAMPLE_LIST_SAVE_RAW); + } + } ImGui::SameLine(); if (ImGui::ArrowButton("SampleUp",ImGuiDir_Up)) { doAction(GUI_ACTION_SAMPLE_LIST_MOVE_UP); diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index 16884d70..357361e1 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -815,6 +815,9 @@ void FurnaceGUI::doAction(int what) { case GUI_ACTION_SAMPLE_LIST_SAVE: if (curSample>=0 && curSample<(int)e->song.sample.size()) openFileDialog(GUI_FILE_SAMPLE_SAVE); break; + case GUI_ACTION_SAMPLE_LIST_SAVE_RAW: + if (curSample>=0 && curSample<(int)e->song.sample.size()) openFileDialog(GUI_FILE_SAMPLE_SAVE_RAW); + break; case GUI_ACTION_SAMPLE_LIST_MOVE_UP: if (e->moveSampleUp(curSample)) { curSample--; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 6d51bac1..64be68eb 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1726,6 +1726,16 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { dpiScale ); break; + case GUI_FILE_SAMPLE_SAVE_RAW: + if (!dirExists(workingDirSample)) workingDirSample=getHomeDir(); + hasOpened=fileDialog->openSave( + "Load Raw Sample", + {"all files", "*"}, + ".*", + workingDirSample, + dpiScale + ); + break; case GUI_FILE_EXPORT_AUDIO_ONE: if (!dirExists(workingDirAudioExport)) workingDirAudioExport=getHomeDir(); hasOpened=fileDialog->openSave( @@ -4447,6 +4457,7 @@ bool FurnaceGUI::loop() { case GUI_FILE_SAMPLE_OPEN_REPLACE: case GUI_FILE_SAMPLE_OPEN_REPLACE_RAW: case GUI_FILE_SAMPLE_SAVE: + case GUI_FILE_SAMPLE_SAVE_RAW: workingDirSample=fileDialog->getPath()+DIR_SEPARATOR_STR; break; case GUI_FILE_EXPORT_AUDIO_ONE: @@ -4714,7 +4725,16 @@ bool FurnaceGUI::loop() { break; case GUI_FILE_SAMPLE_SAVE: if (curSample>=0 && curSample<(int)e->song.sample.size()) { - e->song.sample[curSample]->save(copyOfName.c_str()); + if (!e->song.sample[curSample]->save(copyOfName.c_str())) { + showError("could not save sample! open Log Viewer for more information."); + } + } + break; + case GUI_FILE_SAMPLE_SAVE_RAW: + if (curSample>=0 && curSample<(int)e->song.sample.size()) { + if (!e->song.sample[curSample]->saveRaw(copyOfName.c_str())) { + showError("could not save sample! open Log Viewer for more information."); + } } break; case GUI_FILE_EXPORT_AUDIO_ONE: diff --git a/src/gui/gui.h b/src/gui/gui.h index 365e21ef..833a8c1c 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -365,6 +365,7 @@ enum FurnaceGUIFileDialogs { GUI_FILE_SAMPLE_OPEN_REPLACE, GUI_FILE_SAMPLE_OPEN_REPLACE_RAW, GUI_FILE_SAMPLE_SAVE, + GUI_FILE_SAMPLE_SAVE_RAW, GUI_FILE_EXPORT_AUDIO_ONE, GUI_FILE_EXPORT_AUDIO_PER_SYS, GUI_FILE_EXPORT_AUDIO_PER_CHANNEL, @@ -591,6 +592,7 @@ enum FurnaceGUIActions { GUI_ACTION_SAMPLE_LIST_OPEN_RAW, GUI_ACTION_SAMPLE_LIST_OPEN_REPLACE_RAW, GUI_ACTION_SAMPLE_LIST_SAVE, + GUI_ACTION_SAMPLE_LIST_SAVE_RAW, GUI_ACTION_SAMPLE_LIST_MOVE_UP, GUI_ACTION_SAMPLE_LIST_MOVE_DOWN, GUI_ACTION_SAMPLE_LIST_DELETE, diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index f747dbbe..985382b8 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -636,6 +636,7 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={ D("SAMPLE_LIST_OPEN_RAW", "Import raw data", 0), D("SAMPLE_LIST_OPEN_REPLACE_RAW", "Import raw data (replace current)", 0), D("SAMPLE_LIST_SAVE", "Save", 0), + D("SAMPLE_LIST_SAVE_RAW", "Save (raw)", 0), D("SAMPLE_LIST_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP), D("SAMPLE_LIST_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN), D("SAMPLE_LIST_DELETE", "Delete", 0), diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index f5216db0..02d03db0 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -133,6 +133,12 @@ void FurnaceGUI::drawSampleEdit() { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Open"); } + if (ImGui::BeginPopupContextItem("SampleEOpenOpt")) { + if (ImGui::MenuItem("import raw...")) { + doAction((curSample>=0 && curSample<(int)e->song.sample.size())?GUI_ACTION_SAMPLE_LIST_OPEN_REPLACE_RAW:GUI_ACTION_SAMPLE_LIST_OPEN_RAW); + } + ImGui::EndPopup(); + } ImGui::SameLine(); if (ImGui::Button(ICON_FA_FLOPPY_O "##SESave")) { doAction(GUI_ACTION_SAMPLE_LIST_SAVE); @@ -140,6 +146,11 @@ void FurnaceGUI::drawSampleEdit() { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Save"); } + if (ImGui::BeginPopupContextItem("SampleESaveOpt")) { + if (ImGui::MenuItem("save raw...")) { + doAction(GUI_ACTION_SAMPLE_LIST_SAVE_RAW); + } + } ImGui::SameLine();