From dce4c9a4b2483ce32ea5fabc0ab8e6b5fba338a7 Mon Sep 17 00:00:00 2001 From: freq-mod Date: Mon, 12 Aug 2024 15:54:37 +0200 Subject: [PATCH 01/11] sample bank import --- CMakeLists.txt | 8 ++ src/engine/engine.h | 14 +++- src/engine/fileOpsSample.cpp | 152 ++++++++++++++++++++++++++++++----- src/gui/gui.h | 5 +- 4 files changed, 155 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7bc35433..a4b2a922c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -681,6 +681,14 @@ src/engine/fileOps/text.cpp src/engine/fileOps/tfm.cpp src/engine/fileOps/xm.cpp +src/engine/fileOps/p.cpp +src/engine/fileOps/p86.cpp +src/engine/fileOps/pdx.cpp +src/engine/fileOps/ppc.cpp +src/engine/fileOps/pps.cpp +src/engine/fileOps/pvi.cpp +src/engine/fileOps/pzi.cpp + src/engine/blip_buf.c src/engine/brrUtils.c src/engine/safeReader.cpp diff --git a/src/engine/engine.h b/src/engine/engine.h index a2e900c81..6979f2c26 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -617,6 +617,17 @@ class DivEngine { void loadFF(SafeReader& reader, std::vector& ret, String& stripPath); void loadWOPL(SafeReader& reader, std::vector& ret, String& stripPath); void loadWOPN(SafeReader& reader, std::vector& ret, String& stripPath); + + //sample banks + void loadP(SafeReader& reader, std::vector& ret, String& stripPath); + void loadPPC(SafeReader& reader, std::vector& ret, String& stripPath); + void loadPPS(SafeReader& reader, std::vector& ret, String& stripPath); + void loadPVI(SafeReader& reader, std::vector& ret, String& stripPath); + void loadPDX(SafeReader& reader, std::vector& ret, String& stripPath); + void loadPZI(SafeReader& reader, std::vector& ret, String& stripPath); + void loadP86(SafeReader& reader, std::vector& ret, String& stripPath); + + int loadSampleROM(String path, ssize_t expectedSize, unsigned char*& ret); @@ -1027,7 +1038,8 @@ class DivEngine { int addSamplePtr(DivSample* which); // get sample from file - DivSample* sampleFromFile(const char* path); + //DivSample* sampleFromFile(const char* path); + std::vector sampleFromFile(const char* path); // get raw sample DivSample* sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles, int rate); diff --git a/src/engine/fileOpsSample.cpp b/src/engine/fileOpsSample.cpp index 26d921ac8..711ea74b3 100644 --- a/src/engine/fileOpsSample.cpp +++ b/src/engine/fileOpsSample.cpp @@ -24,10 +24,12 @@ #include "sfWrapper.h" #endif -DivSample* DivEngine::sampleFromFile(const char* path) { +std::vector DivEngine::sampleFromFile(const char* path) { + std::vector ret; + if (song.sample.size()>=256) { lastError="too many samples!"; - return NULL; + return ret; } BUSY_BEGIN; warnings=""; @@ -58,6 +60,110 @@ DivSample* DivEngine::sampleFromFile(const char* path) { } extS+=i; } + + if(extS == ".pps" || extS == ".ppc" || extS == ".pvi" || + extS == ".pdx" || extS == ".pzi" || extS == ".p86" || + extS == ".p") //sample banks! + { + String stripPath; + const char* pathReduxEnd=strrchr(pathRedux,'.'); + if (pathReduxEnd==NULL) { + stripPath=pathRedux; + } else { + for (const char* i=pathRedux; i!=pathReduxEnd && (*i); i++) { + stripPath+=*i; + } + } + + FILE* f=ps_fopen(path,"rb"); + if (f==NULL) { + lastError=strerror(errno); + return ret; + } + unsigned char* buf; + ssize_t len; + if (fseek(f,0,SEEK_END)!=0) { + lastError=strerror(errno); + fclose(f); + return ret; + } + len=ftell(f); + if (len<0) { + lastError=strerror(errno); + fclose(f); + return ret; + } + if (len==(SIZE_MAX>>1)) { + lastError=strerror(errno); + fclose(f); + return ret; + } + if (len==0) { + lastError=strerror(errno); + fclose(f); + return ret; + } + if (fseek(f,0,SEEK_SET)!=0) { + lastError=strerror(errno); + fclose(f); + return ret; + } + buf=new unsigned char[len]; + if (fread(buf,1,len,f)!=(size_t)len) { + logW("did not read entire sample bank file buffer!"); + lastError=_LE("did not read entire sample bank file!"); + delete[] buf; + return ret; + } + fclose(f); + + SafeReader reader = SafeReader(buf,len); + + if(extS == ".pps") + { + loadPPS(reader,ret,stripPath); + } + if(extS == ".ppc") + { + loadPPC(reader,ret,stripPath); + } + if(extS == ".pvi") + { + loadPVI(reader,ret,stripPath); + } + if(extS == ".pdx") + { + loadPDX(reader,ret,stripPath); + } + if(extS == ".pzi") + { + loadPZI(reader,ret,stripPath); + } + if(extS == ".p86") + { + loadP86(reader,ret,stripPath); + } + if(extS == ".p") + { + loadP(reader,ret,stripPath); + } + + if((int)ret.size() > 0) + { + int counter = 0; + + for(DivSample* s: ret) + { + s->name = fmt::sprintf("%s sample %d", stripPath, counter); + counter++; + } + } + + delete[] buf; //done with buffer + BUSY_END; + return ret; + } + if (extS==".dmc" || extS==".brr") { // read as .dmc or .brr size_t len=0; DivSample* sample=new DivSample; @@ -68,7 +174,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) { BUSY_END; lastError=fmt::sprintf("could not open file! (%s)",strerror(errno)); delete sample; - return NULL; + return ret; } if (fseek(f,0,SEEK_END)<0) { @@ -76,7 +182,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) { BUSY_END; lastError=fmt::sprintf("could not get file length! (%s)",strerror(errno)); delete sample; - return NULL; + return ret; } len=ftell(f); @@ -86,7 +192,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) { BUSY_END; lastError="file is empty!"; delete sample; - return NULL; + return ret; } if (len==(SIZE_MAX>>1)) { @@ -94,7 +200,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) { BUSY_END; lastError="file is invalid!"; delete sample; - return NULL; + return ret; } if (fseek(f,0,SEEK_SET)<0) { @@ -102,7 +208,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) { BUSY_END; lastError=fmt::sprintf("could not seek to beginning of file! (%s)",strerror(errno)); delete sample; - return NULL; + return ret; } if (extS==".dmc") { @@ -120,7 +226,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) { BUSY_END; lastError="wait... is that right? no I don't think so..."; delete sample; - return NULL; + return ret; } unsigned char* dataBuf=sample->dataDPCM; @@ -147,14 +253,14 @@ DivSample* DivEngine::sampleFromFile(const char* path) { BUSY_END; lastError="BRR sample is empty!"; delete sample; - return NULL; + return ret; } } else if ((len%9)!=0) { fclose(f); BUSY_END; lastError="possibly corrupt BRR sample!"; delete sample; - return NULL; + return ret; } } @@ -163,16 +269,17 @@ DivSample* DivEngine::sampleFromFile(const char* path) { BUSY_END; lastError=fmt::sprintf("could not read file! (%s)",strerror(errno)); delete sample; - return NULL; + return ret; } BUSY_END; - return sample; + ret.push_back(sample); + return ret; } } #ifndef HAVE_SNDFILE lastError="Furnace was not compiled with libsndfile!"; - return NULL; + return ret; #else SF_INFO si; SFWrapper sfWrap; @@ -186,13 +293,13 @@ DivSample* DivEngine::sampleFromFile(const char* path) { } else { lastError=fmt::sprintf("could not open file! (%s)\nif this is raw sample data, you may import it by right-clicking the Load Sample icon and selecting \"import raw\".",sf_error_number(err)); } - return NULL; + return ret; } if (si.frames>16777215) { lastError="this sample is too big! max sample size is 16777215."; sfWrap.doClose(); BUSY_END; - return NULL; + return ret; } void* buf=NULL; sf_count_t sampleLen=sizeof(short); @@ -298,14 +405,15 @@ DivSample* DivEngine::sampleFromFile(const char* path) { if (sample->centerRate>64000) sample->centerRate=64000; sfWrap.doClose(); BUSY_END; - return sample; + ret.push_back(sample); + return ret; #endif } DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles, int rate) { if (song.sample.size()>=256) { lastError="too many samples!"; - return NULL; + return ret; } if (channels<1) { channels=1; @@ -362,7 +470,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, BUSY_END; lastError="file is empty!"; delete sample; - return NULL; + return ret; } if (len==(SIZE_MAX>>1)) { @@ -370,7 +478,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, BUSY_END; lastError="file is invalid!"; delete sample; - return NULL; + return ret; } if (fseek(f,0,SEEK_SET)<0) { @@ -378,7 +486,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, BUSY_END; lastError=fmt::sprintf("could not seek to beginning of file! (%s)",strerror(errno)); delete sample; - return NULL; + return ret; } lenDivided=len/channels; @@ -420,7 +528,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, BUSY_END; lastError="this sample is too big! max sample size is 16777215."; delete sample; - return NULL; + return ret; } sample->rate=rate; @@ -435,7 +543,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, lastError=fmt::sprintf("could not read file! (%s)",strerror(errno)); delete[] buf; delete sample; - return NULL; + return ret; } fclose(f); diff --git a/src/gui/gui.h b/src/gui/gui.h index 515d77fc8..8eeb5b113 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1593,7 +1593,7 @@ class FurnaceGUI { int sampleTexW, sampleTexH; bool updateSampleTex; - String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName, nextFile, sysSearchQuery, newSongQuery, paletteQuery; + String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName, nextFile, sysSearchQuery, newSongQuery, paletteQuery, sampleBankSearchQuery; String workingDirSong, workingDirIns, workingDirWave, workingDirSample, workingDirAudioExport; String workingDirVGMExport, workingDirZSMExport, workingDirROMExport; String workingDirFont, workingDirColors, workingDirKeybinds; @@ -1605,6 +1605,7 @@ class FurnaceGUI { String folderString; std::vector sysSearchResults; + std::vector> sampleBankSearchResults; std::vector newSongSearchResults; std::vector paletteSearchResults; FixedQueue recentFile; @@ -1620,6 +1621,7 @@ class FurnaceGUI { bool displayNew, displayExport, displayPalette, fullScreen, preserveChanPos, sysDupCloneChannels, sysDupEnd, noteInputPoly, notifyWaveChange; bool wantScrollListIns, wantScrollListWave, wantScrollListSample; bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString; + bool displayPendingSamples, replacePendingSample; bool changeCoarse; bool mobileEdit; bool killGraphics; @@ -2373,6 +2375,7 @@ class FurnaceGUI { std::vector cmdStream; std::vector particles; std::vector> pendingIns; + std::vector > pendingSamples; std::vector sysCategories; From 235a2544582a4d7de1787e8d08675d52a952b048 Mon Sep 17 00:00:00 2001 From: freq-mod Date: Mon, 12 Aug 2024 18:22:52 +0200 Subject: [PATCH 02/11] sample banks part 2 --- src/gui/gui.cpp | 340 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 308 insertions(+), 32 deletions(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 3ba5e2705..8b2ce9ef0 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3739,8 +3739,9 @@ bool FurnaceGUI::loop() { } int sampleCountBefore=e->song.sampleLen; std::vector instruments=e->instrumentFromFile(ev.drop.file,true,settings.readInsNames); + std::vector samples = e->sampleFromFile(ev.drop.file); DivWavetable* droppedWave=NULL; - DivSample* droppedSample=NULL; + //DivSample* droppedSample=NULL; if (!instruments.empty()) { if (e->song.sampleLen!=sampleCountBefore) { e->renderSamplesP(); @@ -3765,10 +3766,24 @@ bool FurnaceGUI::loop() { } nextWindow=GUI_WINDOW_WAVE_LIST; MARK_MODIFIED; - } else if ((droppedSample=e->sampleFromFile(ev.drop.file))!=NULL) { + } + else if (!samples.empty()) + { + if (e->song.sampleLen!=sampleCountBefore) { + //e->renderSamplesP(); + } + if (!e->getWarnings().empty()) + { + showWarning(e->getWarnings(),GUI_WARN_GENERIC); + } int sampleCount=-1; - sampleCount=e->addSamplePtr(droppedSample); - if (sampleCount>=0 && settings.selectAssetOnLoad) { + for (DivSample* s: samples) + { + sampleCount=e->addSamplePtr(s); + } + //sampleCount=e->addSamplePtr(droppedSample); + if (sampleCount>=0 && settings.selectAssetOnLoad) + { curSample=sampleCount; updateSampleTex=true; } @@ -5259,24 +5274,45 @@ bool FurnaceGUI::loop() { String errs=_("there were some errors while loading samples:\n"); bool warn=false; for (String i: fileDialog->getFileName()) { - DivSample* s=e->sampleFromFile(i.c_str()); - if (s==NULL) { + DivSample*=e->sampleFromFile(i.c_str()); + if () { + std::vector samples=e->sampleFromFile(i.c_str()); + if (samples.empty()) { if (fileDialog->getFileName().size()>1) { warn=true; errs+=fmt::sprintf("- %s: %s\n",i,e->getLastError()); } else {; showError(e->getLastError()); } - } else { - if (e->addSamplePtr(s)==-1) { - if (fileDialog->getFileName().size()>1) { - warn=true; - errs+=fmt::sprintf("- %s: %s\n",i,e->getLastError()); - } else { - showError(e->getLastError()); + } + else + { + if((int)samples.size() == 1) + { + if (e->addSamplePtr(samples[0]) == -1) + { + if (fileDialog->getFileName().size()>1) + { + warn=true; + errs+=fmt::sprintf("- %s: %s\n",i,e->getLastError()); + } + else + { + showError(e->getLastError()); + } + } + else + { + MARK_MODIFIED; } - } else { - MARK_MODIFIED; + } + else + { + for (DivSample* s: samples) { //ask which samples to load! + pendingSamples.push_back(std::make_pair(s,false)); + } + displayPendingSamples=true; + replacePendingSample = false; } } } @@ -5285,24 +5321,44 @@ bool FurnaceGUI::loop() { } break; } - case GUI_FILE_SAMPLE_OPEN_REPLACE: { - DivSample* s=e->sampleFromFile(copyOfName.c_str()); - if (s==NULL) { + case GUI_FILE_SAMPLE_OPEN_REPLACE: + { + std::vector samples=e->sampleFromFile(copyOfName.c_str()); + if (samples.empty()) + { showError(e->getLastError()); - } else { - if (curSample>=0 && curSample<(int)e->song.sample.size()) { - e->lockEngine([this,s]() { - // if it crashes here please tell me... - DivSample* oldSample=e->song.sample[curSample]; - e->song.sample[curSample]=s; - delete oldSample; - e->renderSamples(); - MARK_MODIFIED; - }); - updateSampleTex=true; - } else { - showError(_("...but you haven't selected a sample!")); - delete s; + } + else + { + if((int)samples.size() == 1) + { + if (curSample>=0 && curSample<(int)e->song.sample.size()) + { + DivSample* s = samples[0]; + e->lockEngine([this, s]() + { + // if it crashes here please tell me... + DivSample* oldSample=e->song.sample[curSample]; + e->song.sample[curSample]= s; + delete oldSample; + e->renderSamples(); + MARK_MODIFIED; + }); + updateSampleTex=true; + } + else + { + showError(_("...but you haven't selected a sample!")); + delete samples[0]; + } + } + else + { + for (DivSample* s: samples) { //ask which samples to load! + pendingSamples.push_back(std::make_pair(s,false)); + } + displayPendingSamples=true; + replacePendingSample = true; } } break; @@ -5690,6 +5746,11 @@ bool FurnaceGUI::loop() { ImGui::OpenPopup(_("Select Instrument")); } + if (displayPendingSamples) { + displayPendingSamples=false; + ImGui::OpenPopup(_("Select Sample")); + } + if (displayPendingRawSample) { displayPendingRawSample=false; ImGui::OpenPopup(_("Import Raw Sample")); @@ -6422,6 +6483,190 @@ bool FurnaceGUI::loop() { } ImGui::EndPopup(); } +centerNextWindow(_("Select Sample"),canvasW,canvasH); + if (ImGui::BeginPopupModal(_("Select Sample"),NULL,ImGuiWindowFlags_AlwaysAutoResize)) { + bool quitPlease=false; + + ImGui::AlignTextToFramePadding(); + ImGui::Text(_("this is a sample bank! select which ones to load:")); + ImGui::SameLine(); + if (ImGui::Button(_("All"))) { + for (std::pair& i: pendingSamples) { + i.second=true; + } + } + ImGui::SameLine(); + if (ImGui::Button(_("None"))) { + for (std::pair& i: pendingSamples) { + i.second=false; + } + } + bool reissueSearch=false; + + if (ImGui::InputTextWithHint("##SysSearch",settings.language == 0 ? "Search..." : _("Search..."),&sampleBankSearchQuery)) reissueSearch=true; + + bool anySelected=false; + float sizeY=ImGui::GetFrameHeightWithSpacing()*pendingSamples.size(); + if (sizeY>(canvasH-180.0*dpiScale)) + { + sizeY=canvasH-180.0*dpiScale; + if (sizeY<60.0*dpiScale) sizeY=60.0*dpiScale; + } + if (ImGui::BeginTable("PendingSamplesList",1,ImGuiTableFlags_ScrollY,ImVec2(0.0f,sizeY))) + { + if (sampleBankSearchQuery.empty()) + { + for (size_t i=0; iname); + if (pendingInsSingle) + { + if (ImGui::Selectable(id.c_str())) + { + pendingSamples[i].second=true; + quitPlease=true; + } + } + else + { + ImGuiIO& io = ImGui::GetIO(); + if(ImGui::Checkbox(id.c_str(),&pendingSamples[i].second) && io.KeyShift) + { + for(int jj = (int)i - 1; jj >= 0; jj--) + { + if(pendingSamples[jj].second) //pressed shift and there's selected item above + { + for(int k = jj; k < (int)i; k++) + { + pendingSamples[k].second = true; + } + + break; + } + } + } + } + if (pendingSamples[i].second) anySelected=true; + } + } + else //display search results + { + if(reissueSearch) + { + String lowerCase=sampleBankSearchQuery; + + for (char& ii: lowerCase) + { + if (ii>='A' && ii<='Z') ii+='a'-'A'; + } + + sampleBankSearchResults.clear(); + for (int j=0; j < (int)pendingSamples.size(); j++) + { + String lowerCase1 = pendingSamples[j].first->name; + + for (char& ii: lowerCase1) + { + if (ii>='A' && ii<='Z') ii+='a'-'A'; + } + + if (lowerCase1.find(lowerCase)!=String::npos) + { + sampleBankSearchResults.push_back(std::make_pair(pendingSamples[j].first, pendingSamples[j].second)); + } + } + } + + for (size_t i=0; iname); + + ImGuiIO& io = ImGui::GetIO(); + if(ImGui::Checkbox(id.c_str(),&sampleBankSearchResults[i].second) && io.KeyShift) + { + for(int jj = (int)i - 1; jj >= 0; jj--) + { + if(sampleBankSearchResults[jj].second) //pressed shift and there's selected item above + { + for(int k = jj; k < (int)i; k++) + { + sampleBankSearchResults[k].second = true; + } + + break; + } + } + } + if (sampleBankSearchResults[i].second) anySelected=true; + } + + for (size_t i=0; i 0) + { + for (size_t j=0; j& i: pendingSamples) { + i.second=false; + } + quitPlease=true; + } + if (quitPlease) + { + ImGui::CloseCurrentPopup(); + int counter = 0; + for (std::pair& i: pendingSamples) + { + if (!i.second) + { + delete i.first; + } + else + { + if(counter == 0 && replacePendingSample) + { + *e->song.sample[curSample]=*i.first; + replacePendingSample = false; + } + else + { + e->addSamplePtr(i.first); + } + } + counter++; + } + + curSample = (int)e->song.sample.size() - 1; + pendingSamples.clear(); + } + + ImGui::EndPopup(); + } centerNextWindow(_("Import Raw Sample"),canvasW,canvasH); if (ImGui::BeginPopupModal(_("Import Raw Sample"),NULL,ImGuiWindowFlags_AlwaysAutoResize)) { @@ -7435,6 +7680,14 @@ bool FurnaceGUI::init() { compatFormats+="*.dmc "; compatFormats+="*.brr"; + + compatFormats+="*.ppc "; + compatFormats+="*.pps "; + compatFormats+="*.pvi "; + compatFormats+="*.pdx "; + compatFormats+="*.pzi "; + compatFormats+="*.p86 "; + compatFormats+="*.p"; audioLoadFormats[1]=compatFormats; audioLoadFormats.push_back(_("NES DPCM data")); @@ -7443,6 +7696,27 @@ bool FurnaceGUI::init() { audioLoadFormats.push_back(_("SNES Bit Rate Reduction")); audioLoadFormats.push_back("*.brr"); + audioLoadFormats.push_back(_("PMD YM2608 ADPCM-B sample bank")); + audioLoadFormats.push_back("*.ppc"); + + audioLoadFormats.push_back(_("PDR 4-bit AY-3-8910 sample bank")); + audioLoadFormats.push_back("*.pps"); + + audioLoadFormats.push_back(_("FMP YM2608 ADPCM-B sample bank")); + audioLoadFormats.push_back("*.pvi"); + + audioLoadFormats.push_back(_("MDX OKI ADPCM sample bank")); + audioLoadFormats.push_back("*.pdx"); + + audioLoadFormats.push_back(_("FMP 8-bit PCM sample bank")); + audioLoadFormats.push_back("*.pzi"); + + audioLoadFormats.push_back(_("PMD 8-bit PCM sample bank")); + audioLoadFormats.push_back("*.p86"); + + audioLoadFormats.push_back(_("PMD OKI ADPCM sample bank")); + audioLoadFormats.push_back("*.p"); + audioLoadFormats.push_back(_("all files")); audioLoadFormats.push_back("*"); @@ -7865,6 +8139,8 @@ FurnaceGUI::FurnaceGUI(): snesFilterHex(false), modTableHex(false), displayEditString(false), + displayPendingSamples(false), + replacePendingSample(false), changeCoarse(false), mobileEdit(false), killGraphics(false), From aa225175a877c90f9bd9e4ecc6b2b3be30e97dcd Mon Sep 17 00:00:00 2001 From: freq-mod Date: Mon, 12 Aug 2024 19:23:52 +0200 Subject: [PATCH 03/11] sample banks part 3 --- src/engine/fileOpsSample.cpp | 14 ++++++++------ src/gui/gui.cpp | 4 ---- src/gui/gui.h | 4 ++-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/engine/fileOpsSample.cpp b/src/engine/fileOpsSample.cpp index 711ea74b3..560eb7870 100644 --- a/src/engine/fileOpsSample.cpp +++ b/src/engine/fileOpsSample.cpp @@ -24,6 +24,8 @@ #include "sfWrapper.h" #endif +#define _LE(string) (string) + std::vector DivEngine::sampleFromFile(const char* path) { std::vector ret; @@ -413,7 +415,7 @@ std::vector DivEngine::sampleFromFile(const char* path) { DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles, int rate) { if (song.sample.size()>=256) { lastError="too many samples!"; - return ret; + return NULL; } if (channels<1) { channels=1; @@ -470,7 +472,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, BUSY_END; lastError="file is empty!"; delete sample; - return ret; + return NULL; } if (len==(SIZE_MAX>>1)) { @@ -478,7 +480,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, BUSY_END; lastError="file is invalid!"; delete sample; - return ret; + return NULL; } if (fseek(f,0,SEEK_SET)<0) { @@ -486,7 +488,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, BUSY_END; lastError=fmt::sprintf("could not seek to beginning of file! (%s)",strerror(errno)); delete sample; - return ret; + return NULL; } lenDivided=len/channels; @@ -528,7 +530,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, BUSY_END; lastError="this sample is too big! max sample size is 16777215."; delete sample; - return ret; + return NULL; } sample->rate=rate; @@ -543,7 +545,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, lastError=fmt::sprintf("could not read file! (%s)",strerror(errno)); delete[] buf; delete sample; - return ret; + return NULL; } fclose(f); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 8b2ce9ef0..efe8c8883 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -5274,8 +5274,6 @@ bool FurnaceGUI::loop() { String errs=_("there were some errors while loading samples:\n"); bool warn=false; for (String i: fileDialog->getFileName()) { - DivSample*=e->sampleFromFile(i.c_str()); - if () { std::vector samples=e->sampleFromFile(i.c_str()); if (samples.empty()) { if (fileDialog->getFileName().size()>1) { @@ -6503,8 +6501,6 @@ centerNextWindow(_("Select Sample"),canvasW,canvasH); } bool reissueSearch=false; - if (ImGui::InputTextWithHint("##SysSearch",settings.language == 0 ? "Search..." : _("Search..."),&sampleBankSearchQuery)) reissueSearch=true; - bool anySelected=false; float sizeY=ImGui::GetFrameHeightWithSpacing()*pendingSamples.size(); if (sizeY>(canvasH-180.0*dpiScale)) diff --git a/src/gui/gui.h b/src/gui/gui.h index 8eeb5b113..233b7bd85 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1605,7 +1605,7 @@ class FurnaceGUI { String folderString; std::vector sysSearchResults; - std::vector> sampleBankSearchResults; + std::vector> sampleBankSearchResults; std::vector newSongSearchResults; std::vector paletteSearchResults; FixedQueue recentFile; @@ -2375,7 +2375,7 @@ class FurnaceGUI { std::vector cmdStream; std::vector particles; std::vector> pendingIns; - std::vector > pendingSamples; + std::vector> pendingSamples; std::vector sysCategories; From d1e198ddffb1088aac1889b1ee89c01b8357de14 Mon Sep 17 00:00:00 2001 From: freq-mod Date: Mon, 12 Aug 2024 19:25:53 +0200 Subject: [PATCH 04/11] part 4 --- src/engine/fileOps/p.cpp | 131 +++++++++++++++++++++++++++++ src/engine/fileOps/p86.cpp | 149 +++++++++++++++++++++++++++++++++ src/engine/fileOps/pdx.cpp | 108 ++++++++++++++++++++++++ src/engine/fileOps/ppc.cpp | 149 +++++++++++++++++++++++++++++++++ src/engine/fileOps/pps.cpp | 132 +++++++++++++++++++++++++++++ src/engine/fileOps/pvi.cpp | 165 +++++++++++++++++++++++++++++++++++++ src/engine/fileOps/pzi.cpp | 162 ++++++++++++++++++++++++++++++++++++ 7 files changed, 996 insertions(+) create mode 100644 src/engine/fileOps/p.cpp create mode 100644 src/engine/fileOps/p86.cpp create mode 100644 src/engine/fileOps/pdx.cpp create mode 100644 src/engine/fileOps/ppc.cpp create mode 100644 src/engine/fileOps/pps.cpp create mode 100644 src/engine/fileOps/pvi.cpp create mode 100644 src/engine/fileOps/pzi.cpp diff --git a/src/engine/fileOps/p.cpp b/src/engine/fileOps/p.cpp new file mode 100644 index 000000000..fd309dc85 --- /dev/null +++ b/src/engine/fileOps/p.cpp @@ -0,0 +1,131 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "shared.h" + +#ifdef HAVE_GUI +#include "../gui/gui.h" +extern FurnaceGUI g; +#endif + +#define _LE(string) (string) + +class DivEngine; + +//P VOX ADPCM sample bank + +/* ======================================= + Header +======================================= + +0x0000 - 0x03FF 256 * { + Sample start (uint32_t) + - 0x00000000 = unused +} + + +======================================= + Body +======================================= + +Stream of Sample Data { + + MSM6258 ADPCM encoding + nibble-swapped VOX / Dialogic ADPCM + Mono + Sample rate? + 16000Hz seems fine + +} */ + +#define P_BANK_SIZE 256 +#define P_SAMPLE_RATE 16000 + +typedef struct +{ + uint32_t start_pointer; +} P_HEADER; + + +void DivEngine::loadP(SafeReader& reader, std::vector& ret, String& stripPath) +{ + try + { + reader.seek(0, SEEK_SET); + + P_HEADER headers[P_BANK_SIZE]; + + for(int i = 0; i < P_BANK_SIZE; i++) + { + headers[i].start_pointer = (unsigned int)reader.readI_BE(); + } + + for(int i = 0; i < P_BANK_SIZE; i++) + { + if(headers[i].start_pointer != 0) + { + DivSample* s = new DivSample; + + s->rate = P_SAMPLE_RATE; + s->centerRate = P_SAMPLE_RATE; + s->depth = DIV_SAMPLE_DEPTH_VOX; + + reader.seek((int)headers[i].start_pointer, SEEK_SET); + + int sample_pos = 0; + int sample_len = 0; + + if(i < P_BANK_SIZE - 1) + { + sample_len = headers[i + 1].start_pointer - headers[i].start_pointer; + } + else + { + sample_len = (int)reader.size() - headers[i].start_pointer; + } + + if(sample_len > 0) + { + s->init(sample_len * 2); + + for(int j = 0; j < sample_len; j++) + { + unsigned char curr_byte = (unsigned char)reader.readC(); + curr_byte = (curr_byte << 4) | (curr_byte >> 4); + + s->dataVOX[sample_pos] = curr_byte; + sample_pos++; + } + + ret.push_back(s); + logI("p: start %d len %d", headers[i].start_pointer, sample_len); + } + else + { + delete s; + } + } + } + } + catch (EndOfFileException& e) + { + lastError=_LE("premature end of file"); + logE("premature end of file"); + } +} \ No newline at end of file diff --git a/src/engine/fileOps/p86.cpp b/src/engine/fileOps/p86.cpp new file mode 100644 index 000000000..367541600 --- /dev/null +++ b/src/engine/fileOps/p86.cpp @@ -0,0 +1,149 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "shared.h" + +#ifdef HAVE_GUI +#include "../gui/gui.h" +extern FurnaceGUI g; +#endif + +#define _LE(string) (string) + +class DivEngine; + +//P86 8-bit PCM sample bank + +/* ======================================= + Header +======================================= + +0x0000 Identifier (12b) + "PCM86 DATA(\n)(\0)" +0x000C Targeted P86DRV version (1b) + version . +0x000D File Length (3b) +0x0010 - 0x060F 256 * { + + Pointer to Sample Data Start (3b) + Length of Sample Data (3b) + + (0x000000 0x000000 -> no sample for this instrument ID) + +} + + +======================================= + Body +======================================= + +Stream of Sample Data { + + 8-Bit Signed + Mono + 16540Hz + (above sample rate according to KAJA's documentation + any sample rate possible, for different base note & octave) + +} */ + +#define P86_BANK_SIZE 256 +#define P86_SAMPLE_RATE 16540 + +#define P86_FILE_SIG "PCM86 DATA\n\0" + +typedef struct +{ + uint32_t start_pointer; + uint32_t sample_length; +} P86_HEADER; + +#define UNUSED(x) (void)(x) + +uint32_t read_3bytes(SafeReader& reader) +{ + unsigned char arr[3]; + + for (int i = 0; i < 3; i++) + { + arr[i] = (unsigned char)reader.readC(); + } + + return (arr[0] | (arr[1] << 8) | (arr[2] << 16)); +} + +void DivEngine::loadP86(SafeReader& reader, std::vector& ret, String& stripPath) +{ + try + { + reader.seek(0, SEEK_SET); + + P86_HEADER headers[P86_BANK_SIZE]; + + String file_sig = reader.readString(12); + if(file_sig != P86_FILE_SIG) return; + + uint8_t version = reader.readC(); + UNUSED(version); + + uint32_t file_size = read_3bytes(reader); + UNUSED(file_size); + + for(int i = 0; i < P86_BANK_SIZE; i++) + { + headers[i].start_pointer = read_3bytes(reader); + headers[i].sample_length = read_3bytes(reader); + } + + for(int i = 0; i < P86_BANK_SIZE; i++) + { + if(headers[i].start_pointer != 0 && headers[i].sample_length != 0) + { + DivSample* s = new DivSample; + + s->rate = P86_SAMPLE_RATE; + s->centerRate = P86_SAMPLE_RATE; + s->depth = DIV_SAMPLE_DEPTH_8BIT; + s->init(headers[i].sample_length); //byte per sample + + reader.seek((int)headers[i].start_pointer, SEEK_SET); + + int sample_pos = 0; + + for(uint32_t j = 0; j < headers[i].sample_length; j++) + { + unsigned char curr_byte = (unsigned char)reader.readC(); + //curr_byte += 0x80; + + s->data8[sample_pos] = curr_byte; + sample_pos++; + } + + ret.push_back(s); + + logI("p86: start %06X len %06X", headers[i].start_pointer, headers[i].sample_length); + } + } + } + catch (EndOfFileException& e) + { + lastError=_LE("premature end of file"); + logE("premature end of file"); + } +} \ No newline at end of file diff --git a/src/engine/fileOps/pdx.cpp b/src/engine/fileOps/pdx.cpp new file mode 100644 index 000000000..9da099a04 --- /dev/null +++ b/src/engine/fileOps/pdx.cpp @@ -0,0 +1,108 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "shared.h" + +#ifdef HAVE_GUI +#include "../gui/gui.h" +extern FurnaceGUI g; +#endif + +#define _LE(string) (string) + +class DivEngine; + +//PDX 8-bit OKI ADPCM sample bank + +/* File format +The file starts with a header with 96 8-byte pairs, with each pair containing offset and length of ADPCM data chunks for each note value, like so: + +[[byte pointer to sample in file -- 32-bit unsigned integer (4 bytes)] [empty: $0000 -- 16-bit integer] [length of sample, amount in bytes -- 16-bit unsigned integer] ×96] [ADPCM data] EOF + +The first sample (1) is mapped to 0x80 (= the lowest note within MXDRV) and the last sample (96) is mapped to 0xDF (= the highest note within MXDRV). + + +Samples are encoded in 4-bit OKI ADPCM encoded nibbles, where each byte contains 2 nibbles: [nibble 2 << 4 || nibble 1] + + +Unfortunately, sample rates for each samples are not defined within the .PDX file and have to be set manually with the appropriate command for that at play-time */ + +#define PDX_BANK_SIZE 96 +#define PDX_SAMPLE_RATE 16000 + +typedef struct +{ + unsigned int start_pointer; + unsigned short sample_length; +} PDX_HEADER; + +#define UNUSED(x) (void)(x) + +void DivEngine::loadPDX(SafeReader& reader, std::vector& ret, String& stripPath) +{ + try + { + reader.seek(0, SEEK_SET); + + PDX_HEADER headers[PDX_BANK_SIZE]; + + for(int i = 0; i < PDX_BANK_SIZE; i++) + { + headers[i].start_pointer = (unsigned int)reader.readI_BE(); + unsigned short empty = (unsigned short)reader.readS_BE(); //skip 1st 2 bytes + UNUSED(empty); + headers[i].sample_length = (unsigned short)reader.readS_BE(); + } + + for(int i = 0; i < PDX_BANK_SIZE; i++) + { + if(headers[i].start_pointer != 0 && headers[i].sample_length != 0) + { + DivSample* s = new DivSample; + + s->rate = PDX_SAMPLE_RATE; + s->centerRate = PDX_SAMPLE_RATE; + s->depth = DIV_SAMPLE_DEPTH_VOX; + s->init(headers[i].sample_length * 2); + + reader.seek((int)headers[i].start_pointer, SEEK_SET); + + int sample_pos = 0; + + for(unsigned short j = 0; j < headers[i].sample_length; j++) + { + unsigned char curr_byte = (unsigned char)reader.readC(); + curr_byte = (curr_byte << 4) | (curr_byte >> 4); + + s->dataVOX[sample_pos] = curr_byte; + sample_pos++; + } + + ret.push_back(s); + + logI("pdx: start %d len %d", headers[i].start_pointer, headers[i].sample_length); + } + } + } + catch (EndOfFileException& e) + { + lastError=_LE("premature end of file"); + logE("premature end of file"); + } +} \ No newline at end of file diff --git a/src/engine/fileOps/ppc.cpp b/src/engine/fileOps/ppc.cpp new file mode 100644 index 000000000..f5180a590 --- /dev/null +++ b/src/engine/fileOps/ppc.cpp @@ -0,0 +1,149 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "shared.h" + +#ifdef HAVE_GUI +#include "../gui/gui.h" +extern FurnaceGUI g; +#endif + +#define _LE(string) (string) + +class DivEngine; + +//PPC PMD's YM2608 ADPCM-B sample bank + +/* ======================================== + General +======================================== + +ADPCM RAM addresses: see docs/common.txt { + + address_start = 0x0026 + file_header_size = 0x0420 + +} + + +======================================== + Header +======================================== + +0x0000 Identifier (30b) + "ADPCM DATA for PMD ver.4.4- " +0x001E Address of End of Data (32B blocks) in ADPCM RAM (1h) + File Size == address -> file offset + +0x0020 - 0x041F 256 * { + + Start of Sample (32b blocks) in ADPCM RAM (1h) + End of Sample (32b blocks) in ADPCM RAM (1h) + + (0x0000 0x0000 -> no sample for this instrument ID) + +} + + +======================================== + Body +======================================== + +Stream of Sample Data { + + Yamaha ADPCM-B encoding (4-Bit Signed ADPCM) + Mono + 16kHz + (above sample rate according to KAJA's documentation + any sample rate possible, for different base note & octave) + +} */ + +#define PPC_FILE_SIG "ADPCM DATA for PMD ver.4.4- " + +#define PPC_BANK_SIZE 256 +#define PPC_SAMPLE_RATE 16000 + +typedef struct +{ + uint16_t start_pointer; + uint16_t end_pointer; +} PPC_HEADER; + +#define UNUSED(x) (void)(x) + +#define ADPCM_DATA_START 0x0420 + +void DivEngine::loadPPC(SafeReader& reader, std::vector& ret, String& stripPath) +{ + try + { + reader.seek(0, SEEK_SET); + + String file_sig = reader.readString(30); + unsigned short end_of_data = (unsigned short)reader.readS(); + UNUSED(end_of_data); + + if(file_sig != PPC_FILE_SIG) return; + + PPC_HEADER headers[PPC_BANK_SIZE]; + + for(int i = 0; i < PPC_BANK_SIZE; i++) + { + headers[i].start_pointer = (unsigned short)reader.readS(); + headers[i].end_pointer = (unsigned short)reader.readS(); + } + + for(int i = 0; i < PPC_BANK_SIZE; i++) + { + if((headers[i].start_pointer != 0 || headers[i].end_pointer != 0) && headers[i].start_pointer < headers[i].end_pointer) + { + DivSample* s = new DivSample; + + s->rate = PPC_SAMPLE_RATE; + s->centerRate = PPC_SAMPLE_RATE; + s->depth = DIV_SAMPLE_DEPTH_ADPCM_B; + s->init((headers[i].end_pointer - headers[i].start_pointer) * 32 * 2); + + int sample_pos = 0; + int sample_length = (headers[i].end_pointer - headers[i].start_pointer) * 32; + + //reader.seek(ADPCM_DATA_START + headers[i].start_pointer * 32, SEEK_SET); + + for(int j = 0; j < sample_length; j++) + { + unsigned char curr_byte = (unsigned char)reader.readC(); + //curr_byte=(curr_byte<<4)|(curr_byte>>4); + + s->dataB[sample_pos] = curr_byte; + sample_pos++; + } + + logI("ppc: start %d end %d len in bytes %d", headers[i].start_pointer, headers[i].end_pointer, (headers[i].end_pointer - headers[i].start_pointer) * 32); + + ret.push_back(s); + } + } + } + catch (EndOfFileException& e) + { + lastError=_LE("premature end of file"); + logE("premature end of file"); + } +} \ No newline at end of file diff --git a/src/engine/fileOps/pps.cpp b/src/engine/fileOps/pps.cpp new file mode 100644 index 000000000..c4156a10d --- /dev/null +++ b/src/engine/fileOps/pps.cpp @@ -0,0 +1,132 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "shared.h" + +#ifdef HAVE_GUI +#include "../gui/gui.h" +extern FurnaceGUI g; +#endif + +#define _LE(string) (string) + +class DivEngine; + +//PPS AY-3-8910 sample bank + +/* ======================================= + Header +======================================= + +0x0000 - 0x0053 14 * { + + Pointer to Sample Data Start (1h) + Length of Sample Data (1h) + "Pitch"(?) (1b) + Volume Reduction (1b) + +} + + (0x0000 0x0000 [0x00 0x00] -> no sample for this instrument ID) + +} + + +======================================= + Body +======================================= + +Stream of Sample Data { + + 4-Bit Unsigned + (afaict) + Mono + 16Hz + (based on tests, maybe alternatively 8kHz) + +} */ + +#define PPS_BANK_SIZE 14 +#define PPS_SAMPLE_RATE 16000 + +typedef struct +{ + uint16_t start_pointer; + uint16_t sample_length; + uint8_t _pitch; + uint8_t _vol; +} PPS_HEADER; + + +void DivEngine::loadPPS(SafeReader& reader, std::vector& ret, String& stripPath) +{ + try + { + reader.seek(0, SEEK_SET); + + PPS_HEADER headers[PPS_BANK_SIZE]; + + for(int i = 0; i < PPS_BANK_SIZE; i++) + { + headers[i].start_pointer = (unsigned short)reader.readS(); + headers[i].sample_length = (unsigned short)reader.readS(); + headers[i]._pitch = (unsigned char)reader.readC(); + headers[i]._vol = (unsigned char)reader.readC(); + } + + for(int i = 0; i < PPS_BANK_SIZE; i++) + { + if(headers[i].start_pointer != 0 || headers[i].sample_length != 0 + || headers[i]._pitch != 0 || headers[i]._vol != 0) + { + DivSample* s = new DivSample; + + s->rate = PPS_SAMPLE_RATE; + s->centerRate = PPS_SAMPLE_RATE; + s->depth = DIV_SAMPLE_DEPTH_8BIT; + s->init(headers[i].sample_length * 2); //byte per sample + + reader.seek((int)headers[i].start_pointer, SEEK_SET); + + int sample_pos = 0; + + for(int j = 0; j < headers[i].sample_length; j++) + { + unsigned char curr_byte = (unsigned char)reader.readC(); + + s->data8[sample_pos] = (curr_byte >> 4) | (curr_byte & 0xf0); + s->data8[sample_pos] += 0x80; + sample_pos++; + s->data8[sample_pos] = (curr_byte << 4) | (curr_byte & 0xf); + s->data8[sample_pos] += 0x80; + sample_pos++; + } + + ret.push_back(s); + + logI("pps: start %d len %d", headers[i].start_pointer, headers[i].sample_length); + } + } + } + catch (EndOfFileException& e) + { + lastError=_LE("premature end of file"); + logE("premature end of file"); + } +} diff --git a/src/engine/fileOps/pvi.cpp b/src/engine/fileOps/pvi.cpp new file mode 100644 index 000000000..c6e7956b4 --- /dev/null +++ b/src/engine/fileOps/pvi.cpp @@ -0,0 +1,165 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "shared.h" + +#ifdef HAVE_GUI +#include "../gui/gui.h" +extern FurnaceGUI g; +#endif + +#define _LE(string) (string) + +class DivEngine; + +//PVI YM2608 ADPCM-B sample bank + +/* ======================================= + General +======================================= + +ADPCM RAM addresses: see docs/common.txt { + + address_start = 0x0000 + file_header_size = 0x0210 + +} + +======================================= + Header +======================================= + +0x0000 Identifier (4b) + "PVI2" +0x0004 - 0x0007 Unknown Settings (4b) + Unknown mappings PCME switches <-> Values + "0x10 0x00 0x10 0x02" in all example files + First 1h may be Start Address in ADPCM RAM? +0x0008 - 0x0009 "Delta-N" playback frequency (1h) + Default 0x49BA "== 16kHz"?? +0x000A Unknown (1b) + RAM type? (Docs indicate values 0 or 8, all example files have value 0x02?) +0x000B Amount of defined Samples (1b) +0x000C - 0x000F Unknown (4b) + Padding? + "0x00 0x00 0x00 0x00" in all example files +0x0010 - 0x020F 128 * { + + Start of Sample (32b blocks) in ADPCM RAM (1h) + End of Sample (32b blocks) in ADPCM RAM (1h) + + (0x0000 0x0000 -> no sample for this instrument ID) + +} + + +======================================= + Body +======================================= + +Stream of Sample Data { + + Yamaha ADPCM-B encoding (4-Bit Signed ADPCM) + Mono + Sample rate as specified earlier + (examples i have seems Stereo or 32kHz despite "16kHz" playback frequency setting?) + +} */ + +#define PVIV2_FILE_SIG "PVI2" +#define PVIV1_FILE_SIG "PVI1" + +#define PVI_BANK_SIZE 128 +#define PVI_SAMPLE_RATE 16000 + +typedef struct +{ + uint16_t start_pointer; + uint16_t end_pointer; +} PVI_HEADER; + +#define UNUSED(x) (void)(x) + +#define ADPCM_DATA_START 0x0210 + +void DivEngine::loadPVI(SafeReader& reader, std::vector& ret, String& stripPath) +{ + try + { + reader.seek(0, SEEK_SET); + + String file_sig = reader.readString(4); + if(file_sig != PVIV1_FILE_SIG && file_sig != PVIV2_FILE_SIG) return; + + unsigned int unknown_settings = (unsigned int)reader.readI(); + UNUSED(unknown_settings); + unsigned short delta_n = (unsigned short)reader.readS(); + UNUSED(delta_n); + unsigned char one_byte = (unsigned char)reader.readC(); + UNUSED(one_byte); + unsigned char amount_of_samples = (unsigned char)reader.readC(); + UNUSED(amount_of_samples); + unsigned int padding = (unsigned int)reader.readI(); + UNUSED(padding); + + PVI_HEADER headers[PVI_BANK_SIZE]; + + for(int i = 0; i < PVI_BANK_SIZE; i++) + { + headers[i].start_pointer = (unsigned short)reader.readS(); + headers[i].end_pointer = (unsigned short)reader.readS(); + } + + for(int i = 0; i < PVI_BANK_SIZE; i++) + { + if((headers[i].start_pointer != 0 || headers[i].end_pointer != 0) && headers[i].start_pointer < headers[i].end_pointer) + { + DivSample* s = new DivSample; + + s->rate = PVI_SAMPLE_RATE; + s->centerRate = PVI_SAMPLE_RATE; + s->depth = DIV_SAMPLE_DEPTH_ADPCM_B; + s->init((headers[i].end_pointer - headers[i].start_pointer) * 32 * 2); + + int sample_pos = 0; + int sample_length = (headers[i].end_pointer - headers[i].start_pointer) * 32; + + reader.seek(ADPCM_DATA_START + headers[i].start_pointer * 32, SEEK_SET); + + for(int j = 0; j < sample_length; j++) + { + unsigned char curr_byte = (unsigned char)reader.readC(); + //curr_byte=(curr_byte<<4)|(curr_byte>>4); + + s->dataB[sample_pos] = curr_byte; + sample_pos++; + } + + logI("pvi: start %d end %d len in bytes %d", headers[i].start_pointer, headers[i].end_pointer, (headers[i].end_pointer - headers[i].start_pointer) * 32); + + ret.push_back(s); + } + } + } + catch (EndOfFileException& e) + { + lastError=_LE("premature end of file"); + logE("premature end of file"); + } +} \ No newline at end of file diff --git a/src/engine/fileOps/pzi.cpp b/src/engine/fileOps/pzi.cpp new file mode 100644 index 000000000..33161401d --- /dev/null +++ b/src/engine/fileOps/pzi.cpp @@ -0,0 +1,162 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "shared.h" + +#ifdef HAVE_GUI +#include "../gui/gui.h" +extern FurnaceGUI g; +#endif + +#define _LE(string) (string) + +class DivEngine; + +//PZI 8-bit PCM sample bank + +/* ======================================= + Header +======================================= + +0x0000 Identifier (4b) + "PZI1" +0x0004 - 0x001F Unknown (28b) + Part of identifier? Settings? + All (\0)s in all example files +0x0020 - 0x091F 128 * { + + Start of Sample after header (2h) + Length of Sample (2h) + Offset of loop start from sample start (2h) + Offset of loop end from sample start (2h) + Sample rate (1h) + + (0xFFFFFFFF 0xFFFFFFFF loop offsets -> no loop information) + +} + + +======================================= + Body +======================================= + +Stream of Sample Data { + + Unsigned 8-Bit + Mono + Sample rate as specified in header + +} */ + +#define PZI_BANK_SIZE 128 + +#define PZI_FILE_SIG "PZI1" + +#define NO_LOOP (0xFFFFFFFFU) + +#define SAMPLE_DATA_OFFSET 0x0920 + +#define MAX_SANITY_CAP 9999999 + +#define HEADER_JUNK_SIZE 28 + +typedef struct +{ + uint32_t start_pointer; + uint32_t sample_length; + uint32_t loop_start; + uint32_t loop_end; + uint16_t sample_rate; +} PZI_HEADER; + +#define UNUSED(x) (void)(x) + +void DivEngine::loadPZI(SafeReader& reader, std::vector& ret, String& stripPath) +{ + try + { + reader.seek(0, SEEK_SET); + + PZI_HEADER headers[PZI_BANK_SIZE]; + + String file_sig = reader.readString(4); + if(file_sig != PZI_FILE_SIG) return; + + for (int i = 0; i < HEADER_JUNK_SIZE; i++) + { + unsigned char curr_byte = (unsigned char)reader.readC(); + UNUSED(curr_byte); + } + + for(int i = 0; i < PZI_BANK_SIZE; i++) + { + headers[i].start_pointer = (unsigned int)reader.readI(); + headers[i].sample_length = (unsigned int)reader.readI(); + headers[i].loop_start = (unsigned int)reader.readI(); + headers[i].loop_end = (unsigned int)reader.readI(); + headers[i].sample_rate = (unsigned short)reader.readS(); + } + + for(int i = 0; i < PZI_BANK_SIZE; i++) + { + if (headers[i].start_pointer < MAX_SANITY_CAP && headers[i].sample_length < MAX_SANITY_CAP && + headers[i].loop_start < MAX_SANITY_CAP && headers[i].loop_end < MAX_SANITY_CAP && + headers[i].start_pointer > 0 && headers[i].sample_length > 0) + { + DivSample* s = new DivSample; + + s->rate = headers[i].sample_rate; + s->centerRate = headers[i].sample_rate; + s->depth = DIV_SAMPLE_DEPTH_8BIT; + s->init(headers[i].sample_length); //byte per sample + + reader.seek((int)headers[i].start_pointer + SAMPLE_DATA_OFFSET, SEEK_SET); + + int sample_pos = 0; + + for (uint32_t j = 0; j < headers[i].sample_length; j++) + { + unsigned char curr_byte = (unsigned char)reader.readC(); + curr_byte += 0x80; + + s->data8[sample_pos] = curr_byte; + sample_pos++; + } + + if (headers[i].loop_start != NO_LOOP && headers[i].loop_end != NO_LOOP) + { + s->loop = true; + s->loopMode = DIV_SAMPLE_LOOP_FORWARD; + s->loopStart = headers[i].loop_start; + s->loopEnd = headers[i].loop_end; + } + + ret.push_back(s); + + logI("pzi: start %d len %d sample rate %d loop start %d loop end %d", headers[i].start_pointer, headers[i].sample_length, + headers[i].sample_rate, headers[i].loop_start, headers[i].loop_end); + } + } + } + catch (EndOfFileException& e) + { + lastError=_LE("premature end of file"); + logE("premature end of file"); + } +} \ No newline at end of file From 8e39d5ff8ffb36cabbbb3fd87d6a7778ffd4ec02 Mon Sep 17 00:00:00 2001 From: freq-mod Date: Mon, 12 Aug 2024 19:26:20 +0200 Subject: [PATCH 05/11] part final please god --- src/engine/fileOps/importExport.h | 45 ++++++++++++++++++++++++++ src/engine/fileOps/shared.h | 53 +++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/engine/fileOps/importExport.h create mode 100644 src/engine/fileOps/shared.h diff --git a/src/engine/fileOps/importExport.h b/src/engine/fileOps/importExport.h new file mode 100644 index 000000000..5433c7445 --- /dev/null +++ b/src/engine/fileOps/importExport.h @@ -0,0 +1,45 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "../dataErrors.h" +#include "../engine.h" +#include "../../ta-log.h" +#include "../instrument.h" +#include "../song.h" +#include +#include + +#define DIV_READ_SIZE 131072 +#define DIV_DMF_MAGIC ".DelekDefleMask." +#define DIV_FUR_MAGIC "-Furnace module-" +#define DIV_FTM_MAGIC "FamiTracker Module" +#define DIV_DN_FTM_MAGIC "Dn-FamiTracker Module" +#define DIV_FC13_MAGIC "SMOD" +#define DIV_FC14_MAGIC "FC14" +#define DIV_S3M_MAGIC "SCRM" +#define DIV_XM_MAGIC "Extended Module: " +#define DIV_IT_MAGIC "IMPM" +#define DIV_TFM_MAGIC "TFMfmtV2" + +enum DivFurVariants: int { + DIV_FUR_VARIANT_VANILLA=0, + DIV_FUR_VARIANT_B=1, +}; diff --git a/src/engine/fileOps/shared.h b/src/engine/fileOps/shared.h new file mode 100644 index 000000000..6abb5ed85 --- /dev/null +++ b/src/engine/fileOps/shared.h @@ -0,0 +1,53 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "importExport.h" + +// MIDI-related +struct midibank_t { + String name; + uint8_t bankMsb, + bankLsb; +}; + +// Reused patch data structures + +// SBI and some other OPL containers + +struct sbi_t { + uint8_t Mcharacteristics, + Ccharacteristics, + Mscaling_output, + Cscaling_output, + Meg_AD, + Ceg_AD, + Meg_SR, + Ceg_SR, + Mwave, + Cwave, + FeedConnect; +}; + +bool stringNotBlank(String& str); +// detune needs extra translation from register to furnace format +uint8_t fmDtRegisterToFurnace(uint8_t&& dtNative); + +void readSbiOpData(sbi_t& sbi, SafeReader& reader); \ No newline at end of file From 03bc023644b888f8a5e89f88b957593a8ad193e9 Mon Sep 17 00:00:00 2001 From: freq-mod Date: Tue, 13 Aug 2024 13:55:20 +0200 Subject: [PATCH 06/11] spacing --- src/gui/gui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index efe8c8883..4803db5e5 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -7675,7 +7675,7 @@ bool FurnaceGUI::init() { #endif compatFormats+="*.dmc "; - compatFormats+="*.brr"; + compatFormats+="*.brr "; compatFormats+="*.ppc "; compatFormats+="*.pps "; @@ -7683,7 +7683,7 @@ bool FurnaceGUI::init() { compatFormats+="*.pdx "; compatFormats+="*.pzi "; compatFormats+="*.p86 "; - compatFormats+="*.p"; + compatFormats+="*.p "; audioLoadFormats[1]=compatFormats; audioLoadFormats.push_back(_("NES DPCM data")); From 33f56ba5315f8ed8fc78d202ae21306f5cf71b10 Mon Sep 17 00:00:00 2001 From: freq-mod Date: Wed, 14 Aug 2024 20:27:58 +0200 Subject: [PATCH 07/11] remove leftovers --- src/engine/fileOps/p.cpp | 4 +--- src/engine/fileOps/p86.cpp | 4 +--- src/engine/fileOps/pdx.cpp | 4 +--- src/engine/fileOps/ppc.cpp | 4 +--- src/engine/fileOps/pps.cpp | 4 +--- src/engine/fileOps/pvi.cpp | 4 +--- src/engine/fileOps/pzi.cpp | 4 +--- 7 files changed, 7 insertions(+), 21 deletions(-) diff --git a/src/engine/fileOps/p.cpp b/src/engine/fileOps/p.cpp index fd309dc85..09d8adad2 100644 --- a/src/engine/fileOps/p.cpp +++ b/src/engine/fileOps/p.cpp @@ -24,8 +24,6 @@ extern FurnaceGUI g; #endif -#define _LE(string) (string) - class DivEngine; //P VOX ADPCM sample bank @@ -125,7 +123,7 @@ void DivEngine::loadP(SafeReader& reader, std::vector& ret, String& } catch (EndOfFileException& e) { - lastError=_LE("premature end of file"); + lastError=_("premature end of file"); logE("premature end of file"); } } \ No newline at end of file diff --git a/src/engine/fileOps/p86.cpp b/src/engine/fileOps/p86.cpp index 367541600..840d65d28 100644 --- a/src/engine/fileOps/p86.cpp +++ b/src/engine/fileOps/p86.cpp @@ -24,8 +24,6 @@ extern FurnaceGUI g; #endif -#define _LE(string) (string) - class DivEngine; //P86 8-bit PCM sample bank @@ -143,7 +141,7 @@ void DivEngine::loadP86(SafeReader& reader, std::vector& ret, String } catch (EndOfFileException& e) { - lastError=_LE("premature end of file"); + lastError=_("premature end of file"); logE("premature end of file"); } } \ No newline at end of file diff --git a/src/engine/fileOps/pdx.cpp b/src/engine/fileOps/pdx.cpp index 9da099a04..fa57b2006 100644 --- a/src/engine/fileOps/pdx.cpp +++ b/src/engine/fileOps/pdx.cpp @@ -24,8 +24,6 @@ extern FurnaceGUI g; #endif -#define _LE(string) (string) - class DivEngine; //PDX 8-bit OKI ADPCM sample bank @@ -102,7 +100,7 @@ void DivEngine::loadPDX(SafeReader& reader, std::vector& ret, String } catch (EndOfFileException& e) { - lastError=_LE("premature end of file"); + lastError=_("premature end of file"); logE("premature end of file"); } } \ No newline at end of file diff --git a/src/engine/fileOps/ppc.cpp b/src/engine/fileOps/ppc.cpp index f5180a590..a5555abca 100644 --- a/src/engine/fileOps/ppc.cpp +++ b/src/engine/fileOps/ppc.cpp @@ -24,8 +24,6 @@ extern FurnaceGUI g; #endif -#define _LE(string) (string) - class DivEngine; //PPC PMD's YM2608 ADPCM-B sample bank @@ -143,7 +141,7 @@ void DivEngine::loadPPC(SafeReader& reader, std::vector& ret, String } catch (EndOfFileException& e) { - lastError=_LE("premature end of file"); + lastError=_("premature end of file"); logE("premature end of file"); } } \ No newline at end of file diff --git a/src/engine/fileOps/pps.cpp b/src/engine/fileOps/pps.cpp index c4156a10d..e491302b6 100644 --- a/src/engine/fileOps/pps.cpp +++ b/src/engine/fileOps/pps.cpp @@ -24,8 +24,6 @@ extern FurnaceGUI g; #endif -#define _LE(string) (string) - class DivEngine; //PPS AY-3-8910 sample bank @@ -126,7 +124,7 @@ void DivEngine::loadPPS(SafeReader& reader, std::vector& ret, String } catch (EndOfFileException& e) { - lastError=_LE("premature end of file"); + lastError=_("premature end of file"); logE("premature end of file"); } } diff --git a/src/engine/fileOps/pvi.cpp b/src/engine/fileOps/pvi.cpp index c6e7956b4..8352ebf9e 100644 --- a/src/engine/fileOps/pvi.cpp +++ b/src/engine/fileOps/pvi.cpp @@ -24,8 +24,6 @@ extern FurnaceGUI g; #endif -#define _LE(string) (string) - class DivEngine; //PVI YM2608 ADPCM-B sample bank @@ -159,7 +157,7 @@ void DivEngine::loadPVI(SafeReader& reader, std::vector& ret, String } catch (EndOfFileException& e) { - lastError=_LE("premature end of file"); + lastError=_("premature end of file"); logE("premature end of file"); } } \ No newline at end of file diff --git a/src/engine/fileOps/pzi.cpp b/src/engine/fileOps/pzi.cpp index 33161401d..69bf15d87 100644 --- a/src/engine/fileOps/pzi.cpp +++ b/src/engine/fileOps/pzi.cpp @@ -24,8 +24,6 @@ extern FurnaceGUI g; #endif -#define _LE(string) (string) - class DivEngine; //PZI 8-bit PCM sample bank @@ -156,7 +154,7 @@ void DivEngine::loadPZI(SafeReader& reader, std::vector& ret, String } catch (EndOfFileException& e) { - lastError=_LE("premature end of file"); + lastError=_("premature end of file"); logE("premature end of file"); } } \ No newline at end of file From 5bfd389ae64806304b4f3f730c8a72171819acd5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 17 Aug 2024 18:24:04 -0500 Subject: [PATCH 08/11] GUI: new default value for S3M OPL3 --- src/gui/gui.h | 2 +- src/gui/settings.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/gui.h b/src/gui/gui.h index 0a3b9b013..59413e3e1 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -2217,7 +2217,7 @@ class FurnaceGUI { maxUndoSteps(100), vibrationStrength(0.5f), vibrationLength(20), - s3mOPL3(0), + s3mOPL3(1), mainFontPath(""), headFontPath(""), patFontPath(""), diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index ae085f072..16414eab0 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -4754,7 +4754,7 @@ 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.s3mOPL3=conf.getInt("s3mOPL3",1); settings.backupEnable=conf.getInt("backupEnable",1); settings.backupInterval=conf.getInt("backupInterval",30); From aa4ccc3c3fa1be95ed7288244cc03323281925b3 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 17 Aug 2024 18:51:05 -0500 Subject: [PATCH 09/11] importExport/shared -> fileOpsCommon --- src/engine/fileOps/fileOpsCommon.h | 31 +++++++++++++++++ src/engine/fileOps/importExport.h | 45 ------------------------- src/engine/fileOps/p.cpp | 2 +- src/engine/fileOps/p86.cpp | 2 +- src/engine/fileOps/pdx.cpp | 2 +- src/engine/fileOps/ppc.cpp | 2 +- src/engine/fileOps/pps.cpp | 2 +- src/engine/fileOps/pvi.cpp | 2 +- src/engine/fileOps/pzi.cpp | 2 +- src/engine/fileOps/s3m.cpp | 15 --------- src/engine/fileOps/shared.h | 53 ------------------------------ 11 files changed, 38 insertions(+), 120 deletions(-) delete mode 100644 src/engine/fileOps/importExport.h delete mode 100644 src/engine/fileOps/shared.h diff --git a/src/engine/fileOps/fileOpsCommon.h b/src/engine/fileOps/fileOpsCommon.h index 306166c55..d3821bf3b 100644 --- a/src/engine/fileOps/fileOpsCommon.h +++ b/src/engine/fileOps/fileOpsCommon.h @@ -63,3 +63,34 @@ enum DivFurVariants: int { DIV_FUR_VARIANT_VANILLA=0, DIV_FUR_VARIANT_B=1, }; + +// MIDI-related +struct midibank_t { + String name; + uint8_t bankMsb, + bankLsb; +}; + +// Reused patch data structures + +// SBI and some other OPL containers + +struct sbi_t { + uint8_t Mcharacteristics, + Ccharacteristics, + Mscaling_output, + Cscaling_output, + Meg_AD, + Ceg_AD, + Meg_SR, + Ceg_SR, + Mwave, + Cwave, + FeedConnect; +}; + +//bool stringNotBlank(String& str); +// detune needs extra translation from register to furnace format +//uint8_t fmDtRegisterToFurnace(uint8_t&& dtNative); + +//void readSbiOpData(sbi_t& sbi, SafeReader& reader); diff --git a/src/engine/fileOps/importExport.h b/src/engine/fileOps/importExport.h deleted file mode 100644 index 5433c7445..000000000 --- a/src/engine/fileOps/importExport.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Furnace Tracker - multi-system chiptune tracker - * Copyright (C) 2021-2024 tildearrow and contributors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#pragma once - -#include "../dataErrors.h" -#include "../engine.h" -#include "../../ta-log.h" -#include "../instrument.h" -#include "../song.h" -#include -#include - -#define DIV_READ_SIZE 131072 -#define DIV_DMF_MAGIC ".DelekDefleMask." -#define DIV_FUR_MAGIC "-Furnace module-" -#define DIV_FTM_MAGIC "FamiTracker Module" -#define DIV_DN_FTM_MAGIC "Dn-FamiTracker Module" -#define DIV_FC13_MAGIC "SMOD" -#define DIV_FC14_MAGIC "FC14" -#define DIV_S3M_MAGIC "SCRM" -#define DIV_XM_MAGIC "Extended Module: " -#define DIV_IT_MAGIC "IMPM" -#define DIV_TFM_MAGIC "TFMfmtV2" - -enum DivFurVariants: int { - DIV_FUR_VARIANT_VANILLA=0, - DIV_FUR_VARIANT_B=1, -}; diff --git a/src/engine/fileOps/p.cpp b/src/engine/fileOps/p.cpp index 09d8adad2..205f79462 100644 --- a/src/engine/fileOps/p.cpp +++ b/src/engine/fileOps/p.cpp @@ -17,7 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "shared.h" +#include "fileOpsCommon.h" #ifdef HAVE_GUI #include "../gui/gui.h" diff --git a/src/engine/fileOps/p86.cpp b/src/engine/fileOps/p86.cpp index 840d65d28..8a26a0ea2 100644 --- a/src/engine/fileOps/p86.cpp +++ b/src/engine/fileOps/p86.cpp @@ -17,7 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "shared.h" +#include "fileOpsCommon.h" #ifdef HAVE_GUI #include "../gui/gui.h" diff --git a/src/engine/fileOps/pdx.cpp b/src/engine/fileOps/pdx.cpp index fa57b2006..de34a49c5 100644 --- a/src/engine/fileOps/pdx.cpp +++ b/src/engine/fileOps/pdx.cpp @@ -17,7 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "shared.h" +#include "fileOpsCommon.h" #ifdef HAVE_GUI #include "../gui/gui.h" diff --git a/src/engine/fileOps/ppc.cpp b/src/engine/fileOps/ppc.cpp index a5555abca..35dd18467 100644 --- a/src/engine/fileOps/ppc.cpp +++ b/src/engine/fileOps/ppc.cpp @@ -17,7 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "shared.h" +#include "fileOpsCommon.h" #ifdef HAVE_GUI #include "../gui/gui.h" diff --git a/src/engine/fileOps/pps.cpp b/src/engine/fileOps/pps.cpp index e491302b6..f9592e07b 100644 --- a/src/engine/fileOps/pps.cpp +++ b/src/engine/fileOps/pps.cpp @@ -17,7 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "shared.h" +#include "fileOpsCommon.h" #ifdef HAVE_GUI #include "../gui/gui.h" diff --git a/src/engine/fileOps/pvi.cpp b/src/engine/fileOps/pvi.cpp index 8352ebf9e..d03d61c21 100644 --- a/src/engine/fileOps/pvi.cpp +++ b/src/engine/fileOps/pvi.cpp @@ -17,7 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "shared.h" +#include "fileOpsCommon.h" #ifdef HAVE_GUI #include "../gui/gui.h" diff --git a/src/engine/fileOps/pzi.cpp b/src/engine/fileOps/pzi.cpp index 69bf15d87..7463cd23a 100644 --- a/src/engine/fileOps/pzi.cpp +++ b/src/engine/fileOps/pzi.cpp @@ -17,7 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "shared.h" +#include "fileOpsCommon.h" #ifdef HAVE_GUI #include "../gui/gui.h" diff --git a/src/engine/fileOps/s3m.cpp b/src/engine/fileOps/s3m.cpp index 9e212d8d3..11d0f4fb4 100644 --- a/src/engine/fileOps/s3m.cpp +++ b/src/engine/fileOps/s3m.cpp @@ -19,21 +19,6 @@ #include "fileOpsCommon.h" -// SBI and some other OPL containers -struct sbi_t { - uint8_t Mcharacteristics, - Ccharacteristics, - Mscaling_output, - Cscaling_output, - Meg_AD, - Ceg_AD, - Meg_SR, - Ceg_SR, - Mwave, - Cwave, - FeedConnect; -}; - static void readSbiOpData(sbi_t& sbi, SafeReader& reader) { sbi.Mcharacteristics = reader.readC(); sbi.Ccharacteristics = reader.readC(); diff --git a/src/engine/fileOps/shared.h b/src/engine/fileOps/shared.h deleted file mode 100644 index 6abb5ed85..000000000 --- a/src/engine/fileOps/shared.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Furnace Tracker - multi-system chiptune tracker - * Copyright (C) 2021-2024 tildearrow and contributors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#pragma once - -#include "importExport.h" - -// MIDI-related -struct midibank_t { - String name; - uint8_t bankMsb, - bankLsb; -}; - -// Reused patch data structures - -// SBI and some other OPL containers - -struct sbi_t { - uint8_t Mcharacteristics, - Ccharacteristics, - Mscaling_output, - Cscaling_output, - Meg_AD, - Ceg_AD, - Meg_SR, - Ceg_SR, - Mwave, - Cwave, - FeedConnect; -}; - -bool stringNotBlank(String& str); -// detune needs extra translation from register to furnace format -uint8_t fmDtRegisterToFurnace(uint8_t&& dtNative); - -void readSbiOpData(sbi_t& sbi, SafeReader& reader); \ No newline at end of file From 7974b9627514f048ebd6c25cfb8d0f796a7122a5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 18 Aug 2024 02:30:30 -0500 Subject: [PATCH 10/11] fixes --- src/engine/fileOps/p.cpp | 5 ----- src/engine/fileOps/p86.cpp | 5 ----- src/engine/fileOps/pdx.cpp | 5 ----- src/engine/fileOps/ppc.cpp | 5 ----- src/engine/fileOps/pps.cpp | 5 ----- src/engine/fileOps/pvi.cpp | 5 ----- src/engine/fileOps/pzi.cpp | 5 ----- src/engine/fileOpsSample.cpp | 4 +--- 8 files changed, 1 insertion(+), 38 deletions(-) diff --git a/src/engine/fileOps/p.cpp b/src/engine/fileOps/p.cpp index 205f79462..9ba650c0e 100644 --- a/src/engine/fileOps/p.cpp +++ b/src/engine/fileOps/p.cpp @@ -19,11 +19,6 @@ #include "fileOpsCommon.h" -#ifdef HAVE_GUI -#include "../gui/gui.h" -extern FurnaceGUI g; -#endif - class DivEngine; //P VOX ADPCM sample bank diff --git a/src/engine/fileOps/p86.cpp b/src/engine/fileOps/p86.cpp index 8a26a0ea2..560867007 100644 --- a/src/engine/fileOps/p86.cpp +++ b/src/engine/fileOps/p86.cpp @@ -19,11 +19,6 @@ #include "fileOpsCommon.h" -#ifdef HAVE_GUI -#include "../gui/gui.h" -extern FurnaceGUI g; -#endif - class DivEngine; //P86 8-bit PCM sample bank diff --git a/src/engine/fileOps/pdx.cpp b/src/engine/fileOps/pdx.cpp index de34a49c5..cd03369a7 100644 --- a/src/engine/fileOps/pdx.cpp +++ b/src/engine/fileOps/pdx.cpp @@ -19,11 +19,6 @@ #include "fileOpsCommon.h" -#ifdef HAVE_GUI -#include "../gui/gui.h" -extern FurnaceGUI g; -#endif - class DivEngine; //PDX 8-bit OKI ADPCM sample bank diff --git a/src/engine/fileOps/ppc.cpp b/src/engine/fileOps/ppc.cpp index 35dd18467..3c5144dbd 100644 --- a/src/engine/fileOps/ppc.cpp +++ b/src/engine/fileOps/ppc.cpp @@ -19,11 +19,6 @@ #include "fileOpsCommon.h" -#ifdef HAVE_GUI -#include "../gui/gui.h" -extern FurnaceGUI g; -#endif - class DivEngine; //PPC PMD's YM2608 ADPCM-B sample bank diff --git a/src/engine/fileOps/pps.cpp b/src/engine/fileOps/pps.cpp index f9592e07b..39c573342 100644 --- a/src/engine/fileOps/pps.cpp +++ b/src/engine/fileOps/pps.cpp @@ -19,11 +19,6 @@ #include "fileOpsCommon.h" -#ifdef HAVE_GUI -#include "../gui/gui.h" -extern FurnaceGUI g; -#endif - class DivEngine; //PPS AY-3-8910 sample bank diff --git a/src/engine/fileOps/pvi.cpp b/src/engine/fileOps/pvi.cpp index d03d61c21..4181ea60d 100644 --- a/src/engine/fileOps/pvi.cpp +++ b/src/engine/fileOps/pvi.cpp @@ -19,11 +19,6 @@ #include "fileOpsCommon.h" -#ifdef HAVE_GUI -#include "../gui/gui.h" -extern FurnaceGUI g; -#endif - class DivEngine; //PVI YM2608 ADPCM-B sample bank diff --git a/src/engine/fileOps/pzi.cpp b/src/engine/fileOps/pzi.cpp index 7463cd23a..906e1f43b 100644 --- a/src/engine/fileOps/pzi.cpp +++ b/src/engine/fileOps/pzi.cpp @@ -19,11 +19,6 @@ #include "fileOpsCommon.h" -#ifdef HAVE_GUI -#include "../gui/gui.h" -extern FurnaceGUI g; -#endif - class DivEngine; //PZI 8-bit PCM sample bank diff --git a/src/engine/fileOpsSample.cpp b/src/engine/fileOpsSample.cpp index 560eb7870..5008392f8 100644 --- a/src/engine/fileOpsSample.cpp +++ b/src/engine/fileOpsSample.cpp @@ -24,8 +24,6 @@ #include "sfWrapper.h" #endif -#define _LE(string) (string) - std::vector DivEngine::sampleFromFile(const char* path) { std::vector ret; @@ -113,7 +111,7 @@ std::vector DivEngine::sampleFromFile(const char* path) { buf=new unsigned char[len]; if (fread(buf,1,len,f)!=(size_t)len) { logW("did not read entire sample bank file buffer!"); - lastError=_LE("did not read entire sample bank file!"); + lastError=_("did not read entire sample bank file!"); delete[] buf; return ret; } From e7c39a0d6fb8513992028d9d98a70bab5bb0d904 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 18 Aug 2024 05:52:50 -0500 Subject: [PATCH 11/11] fix --- src/gui/gui.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index a70c4e008..95e8ffd36 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -6627,7 +6627,9 @@ bool FurnaceGUI::loop() { } ImGui::EndPopup(); } -centerNextWindow(_("Select Sample"),canvasW,canvasH); + + // TODO: fix style + centerNextWindow(_("Select Sample"),canvasW,canvasH); if (ImGui::BeginPopupModal(_("Select Sample"),NULL,ImGuiWindowFlags_AlwaysAutoResize)) { bool quitPlease=false; @@ -6673,6 +6675,7 @@ centerNextWindow(_("Select Sample"),canvasW,canvasH); } else { + // TODO:fixstyle from hereonwards ImGuiIO& io = ImGui::GetIO(); if(ImGui::Checkbox(id.c_str(),&pendingSamples[i].second) && io.KeyShift) { @@ -7830,7 +7833,7 @@ bool FurnaceGUI::init() { compatFormats+="*.pdx "; compatFormats+="*.pzi "; compatFormats+="*.p86 "; - compatFormats+="*.p "; + compatFormats+="*.p"; audioLoadFormats[1]=compatFormats; audioLoadFormats.push_back(_("NES DPCM data"));