sample bank import

This commit is contained in:
freq-mod 2024-08-12 15:54:37 +02:00
parent 7591b2ed6a
commit dce4c9a4b2
4 changed files with 155 additions and 24 deletions

View file

@ -681,6 +681,14 @@ src/engine/fileOps/text.cpp
src/engine/fileOps/tfm.cpp src/engine/fileOps/tfm.cpp
src/engine/fileOps/xm.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/blip_buf.c
src/engine/brrUtils.c src/engine/brrUtils.c
src/engine/safeReader.cpp src/engine/safeReader.cpp

View file

@ -617,6 +617,17 @@ class DivEngine {
void loadFF(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath); void loadFF(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
void loadWOPL(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath); void loadWOPL(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
void loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath); void loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
//sample banks
void loadP(SafeReader& reader, std::vector<DivSample*>& ret, String& stripPath);
void loadPPC(SafeReader& reader, std::vector<DivSample*>& ret, String& stripPath);
void loadPPS(SafeReader& reader, std::vector<DivSample*>& ret, String& stripPath);
void loadPVI(SafeReader& reader, std::vector<DivSample*>& ret, String& stripPath);
void loadPDX(SafeReader& reader, std::vector<DivSample*>& ret, String& stripPath);
void loadPZI(SafeReader& reader, std::vector<DivSample*>& ret, String& stripPath);
void loadP86(SafeReader& reader, std::vector<DivSample*>& ret, String& stripPath);
int loadSampleROM(String path, ssize_t expectedSize, unsigned char*& ret); int loadSampleROM(String path, ssize_t expectedSize, unsigned char*& ret);
@ -1027,7 +1038,8 @@ class DivEngine {
int addSamplePtr(DivSample* which); int addSamplePtr(DivSample* which);
// get sample from file // get sample from file
DivSample* sampleFromFile(const char* path); //DivSample* sampleFromFile(const char* path);
std::vector<DivSample*> sampleFromFile(const char* path);
// get raw sample // get raw sample
DivSample* sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles, int rate); DivSample* sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles, int rate);

View file

@ -24,10 +24,12 @@
#include "sfWrapper.h" #include "sfWrapper.h"
#endif #endif
DivSample* DivEngine::sampleFromFile(const char* path) { std::vector<DivSample*> DivEngine::sampleFromFile(const char* path) {
std::vector<DivSample*> ret;
if (song.sample.size()>=256) { if (song.sample.size()>=256) {
lastError="too many samples!"; lastError="too many samples!";
return NULL; return ret;
} }
BUSY_BEGIN; BUSY_BEGIN;
warnings=""; warnings="";
@ -58,6 +60,110 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
} }
extS+=i; 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 if (extS==".dmc" || extS==".brr") { // read as .dmc or .brr
size_t len=0; size_t len=0;
DivSample* sample=new DivSample; DivSample* sample=new DivSample;
@ -68,7 +174,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError=fmt::sprintf("could not open file! (%s)",strerror(errno)); lastError=fmt::sprintf("could not open file! (%s)",strerror(errno));
delete sample; delete sample;
return NULL; return ret;
} }
if (fseek(f,0,SEEK_END)<0) { if (fseek(f,0,SEEK_END)<0) {
@ -76,7 +182,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError=fmt::sprintf("could not get file length! (%s)",strerror(errno)); lastError=fmt::sprintf("could not get file length! (%s)",strerror(errno));
delete sample; delete sample;
return NULL; return ret;
} }
len=ftell(f); len=ftell(f);
@ -86,7 +192,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError="file is empty!"; lastError="file is empty!";
delete sample; delete sample;
return NULL; return ret;
} }
if (len==(SIZE_MAX>>1)) { if (len==(SIZE_MAX>>1)) {
@ -94,7 +200,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError="file is invalid!"; lastError="file is invalid!";
delete sample; delete sample;
return NULL; return ret;
} }
if (fseek(f,0,SEEK_SET)<0) { if (fseek(f,0,SEEK_SET)<0) {
@ -102,7 +208,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError=fmt::sprintf("could not seek to beginning of file! (%s)",strerror(errno)); lastError=fmt::sprintf("could not seek to beginning of file! (%s)",strerror(errno));
delete sample; delete sample;
return NULL; return ret;
} }
if (extS==".dmc") { if (extS==".dmc") {
@ -120,7 +226,7 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError="wait... is that right? no I don't think so..."; lastError="wait... is that right? no I don't think so...";
delete sample; delete sample;
return NULL; return ret;
} }
unsigned char* dataBuf=sample->dataDPCM; unsigned char* dataBuf=sample->dataDPCM;
@ -147,14 +253,14 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError="BRR sample is empty!"; lastError="BRR sample is empty!";
delete sample; delete sample;
return NULL; return ret;
} }
} else if ((len%9)!=0) { } else if ((len%9)!=0) {
fclose(f); fclose(f);
BUSY_END; BUSY_END;
lastError="possibly corrupt BRR sample!"; lastError="possibly corrupt BRR sample!";
delete sample; delete sample;
return NULL; return ret;
} }
} }
@ -163,16 +269,17 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError=fmt::sprintf("could not read file! (%s)",strerror(errno)); lastError=fmt::sprintf("could not read file! (%s)",strerror(errno));
delete sample; delete sample;
return NULL; return ret;
} }
BUSY_END; BUSY_END;
return sample; ret.push_back(sample);
return ret;
} }
} }
#ifndef HAVE_SNDFILE #ifndef HAVE_SNDFILE
lastError="Furnace was not compiled with libsndfile!"; lastError="Furnace was not compiled with libsndfile!";
return NULL; return ret;
#else #else
SF_INFO si; SF_INFO si;
SFWrapper sfWrap; SFWrapper sfWrap;
@ -186,13 +293,13 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
} else { } 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)); 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) { if (si.frames>16777215) {
lastError="this sample is too big! max sample size is 16777215."; lastError="this sample is too big! max sample size is 16777215.";
sfWrap.doClose(); sfWrap.doClose();
BUSY_END; BUSY_END;
return NULL; return ret;
} }
void* buf=NULL; void* buf=NULL;
sf_count_t sampleLen=sizeof(short); sf_count_t sampleLen=sizeof(short);
@ -298,14 +405,15 @@ DivSample* DivEngine::sampleFromFile(const char* path) {
if (sample->centerRate>64000) sample->centerRate=64000; if (sample->centerRate>64000) sample->centerRate=64000;
sfWrap.doClose(); sfWrap.doClose();
BUSY_END; BUSY_END;
return sample; ret.push_back(sample);
return ret;
#endif #endif
} }
DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles, int rate) { DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian, bool unsign, bool swapNibbles, int rate) {
if (song.sample.size()>=256) { if (song.sample.size()>=256) {
lastError="too many samples!"; lastError="too many samples!";
return NULL; return ret;
} }
if (channels<1) { if (channels<1) {
channels=1; channels=1;
@ -362,7 +470,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth,
BUSY_END; BUSY_END;
lastError="file is empty!"; lastError="file is empty!";
delete sample; delete sample;
return NULL; return ret;
} }
if (len==(SIZE_MAX>>1)) { if (len==(SIZE_MAX>>1)) {
@ -370,7 +478,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth,
BUSY_END; BUSY_END;
lastError="file is invalid!"; lastError="file is invalid!";
delete sample; delete sample;
return NULL; return ret;
} }
if (fseek(f,0,SEEK_SET)<0) { if (fseek(f,0,SEEK_SET)<0) {
@ -378,7 +486,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth,
BUSY_END; BUSY_END;
lastError=fmt::sprintf("could not seek to beginning of file! (%s)",strerror(errno)); lastError=fmt::sprintf("could not seek to beginning of file! (%s)",strerror(errno));
delete sample; delete sample;
return NULL; return ret;
} }
lenDivided=len/channels; lenDivided=len/channels;
@ -420,7 +528,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth,
BUSY_END; BUSY_END;
lastError="this sample is too big! max sample size is 16777215."; lastError="this sample is too big! max sample size is 16777215.";
delete sample; delete sample;
return NULL; return ret;
} }
sample->rate=rate; 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)); lastError=fmt::sprintf("could not read file! (%s)",strerror(errno));
delete[] buf; delete[] buf;
delete sample; delete sample;
return NULL; return ret;
} }
fclose(f); fclose(f);

View file

@ -1593,7 +1593,7 @@ class FurnaceGUI {
int sampleTexW, sampleTexH; int sampleTexW, sampleTexH;
bool updateSampleTex; 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 workingDirSong, workingDirIns, workingDirWave, workingDirSample, workingDirAudioExport;
String workingDirVGMExport, workingDirZSMExport, workingDirROMExport; String workingDirVGMExport, workingDirZSMExport, workingDirROMExport;
String workingDirFont, workingDirColors, workingDirKeybinds; String workingDirFont, workingDirColors, workingDirKeybinds;
@ -1605,6 +1605,7 @@ class FurnaceGUI {
String folderString; String folderString;
std::vector<DivSystem> sysSearchResults; std::vector<DivSystem> sysSearchResults;
std::vector<std::pair><DivSample*,bool>> sampleBankSearchResults;
std::vector<FurnaceGUISysDef> newSongSearchResults; std::vector<FurnaceGUISysDef> newSongSearchResults;
std::vector<int> paletteSearchResults; std::vector<int> paletteSearchResults;
FixedQueue<String,32> recentFile; FixedQueue<String,32> recentFile;
@ -1620,6 +1621,7 @@ class FurnaceGUI {
bool displayNew, displayExport, displayPalette, fullScreen, preserveChanPos, sysDupCloneChannels, sysDupEnd, noteInputPoly, notifyWaveChange; bool displayNew, displayExport, displayPalette, fullScreen, preserveChanPos, sysDupCloneChannels, sysDupEnd, noteInputPoly, notifyWaveChange;
bool wantScrollListIns, wantScrollListWave, wantScrollListSample; bool wantScrollListIns, wantScrollListWave, wantScrollListSample;
bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString; bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString;
bool displayPendingSamples, replacePendingSample;
bool changeCoarse; bool changeCoarse;
bool mobileEdit; bool mobileEdit;
bool killGraphics; bool killGraphics;
@ -2373,6 +2375,7 @@ class FurnaceGUI {
std::vector<DivCommand> cmdStream; std::vector<DivCommand> cmdStream;
std::vector<Particle> particles; std::vector<Particle> particles;
std::vector<std::pair<DivInstrument*,bool>> pendingIns; std::vector<std::pair<DivInstrument*,bool>> pendingIns;
std::vector <std::pair<DivSample*,bool>> pendingSamples;
std::vector<FurnaceGUISysCategory> sysCategories; std::vector<FurnaceGUISysCategory> sysCategories;