Update center rate and loop information when loading and saving samples

This commit is contained in:
Ian Karlsson 2022-02-23 14:32:35 +01:00
parent 29cae1a3f8
commit 6472795b01
2 changed files with 40 additions and 1 deletions

View file

@ -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();

View file

@ -21,6 +21,7 @@
#include "../ta-log.h"
#include <string.h>
#include <sndfile.h>
#include <math.h>
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;