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/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

View file

@ -618,6 +618,17 @@ class DivEngine {
void loadWOPL(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);
bool initAudioBackend();
@ -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<DivSample*> sampleFromFile(const char* path);
// get raw sample
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"
#endif
DivSample* DivEngine::sampleFromFile(const char* path) {
std::vector<DivSample*> DivEngine::sampleFromFile(const char* path) {
std::vector<DivSample*> 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);

View file

@ -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<DivSystem> sysSearchResults;
std::vector<std::pair><DivSample*,bool>> sampleBankSearchResults;
std::vector<FurnaceGUISysDef> newSongSearchResults;
std::vector<int> paletteSearchResults;
FixedQueue<String,32> 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<DivCommand> cmdStream;
std::vector<Particle> particles;
std::vector<std::pair<DivInstrument*,bool>> pendingIns;
std::vector <std::pair<DivSample*,bool>> pendingSamples;
std::vector<FurnaceGUISysCategory> sysCategories;