diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 8b4883e9..276dba6a 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1890,7 +1890,6 @@ bool DivEngine::addSampleFromFile(const char* path) { if (sf_readf_short(f,buf,si.frames)!=si.frames) { logW("sample read size mismatch!\n"); } - sf_close(f); DivSample* sample=new DivSample; int sampleCount=(int)song.sample.size(); const char* sName=strrchr(path,DIR_SEPARATOR); @@ -1923,7 +1922,28 @@ bool DivEngine::addSampleFromFile(const char* path) { sample->rate=si.samplerate; if (sample->rate<4000) sample->rate=4000; if (sample->rate>96000) sample->rate=96000; + sample->centerRate=si.samplerate; + SF_INSTRUMENT inst; + if (sf_command(f, SFC_GET_INSTRUMENT, &inst, sizeof(inst)) == SF_TRUE) + { + // There's no documentation on libsndfile detune range, but the code + // implies -50..50. Yet when loading a file you can get a >50 value. + if(inst.detune > 50) + inst.detune = inst.detune - 100; + short pitch = ((0x3c-inst.basenote)*100) + inst.detune; + sample->centerRate=si.samplerate*pow(2.0,pitch/(12.0 * 100.0)); + if(inst.loop_count && inst.loops[0].mode == SF_LOOP_FORWARD) + { + sample->loopStart=inst.loops[0].start; + if(inst.loops[0].end < (unsigned int)sampleCount) + sampleCount=inst.loops[0].end; + } + } + + if (sample->centerRate<4000) sample->centerRate=4000; + if (sample->centerRate>64000) sample->centerRate=64000; + sf_close(f); song.sample.push_back(sample); song.sampleLen=sampleCount+1; renderSamples(); diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 8cb758a7..b44f5ba0 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -21,6 +21,7 @@ #include "../ta-log.h" #include #include +#include bool DivSample::save(const char* path) { SNDFILE* f; @@ -44,6 +45,23 @@ bool DivSample::save(const char* path) { return false; } + SF_INSTRUMENT inst; + memset(&inst, 0, sizeof(inst)); + inst.gain = 1; + short pitch = (0x3c * 100) + 50 - (log2((double)centerRate/rate) * 12.0 * 100.0); + inst.basenote = pitch / 100; + inst.detune = 50 - (pitch % 100); + inst.velocity_hi = 0x7f; + inst.key_hi = 0x7f; + if(loopStart != -1) + { + inst.loop_count = 1; + inst.loops[0].mode = SF_LOOP_FORWARD; + inst.loops[0].start = loopStart; + inst.loops[0].end = length; + } + sf_command(f, SFC_SET_INSTRUMENT, &inst, sizeof(inst)); + if (depth==16) { sf_writef_short(f,data,length); } else { @@ -54,6 +72,7 @@ bool DivSample::save(const char* path) { sf_writef_short(f,cbuf,length); delete[] cbuf; } + sf_close(f); return true;