Made DUMB and modplay volume ramping more sensitive when transititioning to or from zero volume, and implemented Modplug ADPCM sample support into ft2play
parent
4504bf1034
commit
7a0aea53dd
|
@ -3905,6 +3905,13 @@ static void playing_volume_setup(DUMB_IT_SIGRENDERER * sigrenderer, IT_PLAYING *
|
||||||
vol = calculate_volume(sigrenderer, playing, 1.0f);
|
vol = calculate_volume(sigrenderer, playing, 1.0f);
|
||||||
playing->float_volume[0] *= vol;
|
playing->float_volume[0] *= vol;
|
||||||
playing->float_volume[1] *= vol;
|
playing->float_volume[1] *= vol;
|
||||||
|
|
||||||
|
rampScale = 4;
|
||||||
|
|
||||||
|
if (ramp_style > 0 && playing->declick_stage == 2) {
|
||||||
|
if ((playing->ramp_volume[0] == 0 && playing->ramp_volume[1] == 0) || vol == 0)
|
||||||
|
rampScale = 48;
|
||||||
|
}
|
||||||
|
|
||||||
if (ramp_style == 0 || (ramp_style < 2 && playing->declick_stage == 2)) {
|
if (ramp_style == 0 || (ramp_style < 2 && playing->declick_stage == 2)) {
|
||||||
if (playing->declick_stage <= 2) {
|
if (playing->declick_stage <= 2) {
|
||||||
|
@ -3921,7 +3928,6 @@ static void playing_volume_setup(DUMB_IT_SIGRENDERER * sigrenderer, IT_PLAYING *
|
||||||
playing->ramp_delta[0] = 0;
|
playing->ramp_delta[0] = 0;
|
||||||
playing->ramp_delta[1] = 0;
|
playing->ramp_delta[1] = 0;
|
||||||
} else {
|
} else {
|
||||||
rampScale = 4;
|
|
||||||
if (playing->declick_stage == 0) {
|
if (playing->declick_stage == 0) {
|
||||||
playing->ramp_volume[0] = 0;
|
playing->ramp_volume[0] = 0;
|
||||||
playing->ramp_volume[1] = 0;
|
playing->ramp_volume[1] = 0;
|
||||||
|
|
|
@ -81,6 +81,7 @@ typedef struct SampleHeaderTyp_t
|
||||||
uint8_t Typ;
|
uint8_t Typ;
|
||||||
uint8_t Pan;
|
uint8_t Pan;
|
||||||
int8_t RelTon;
|
int8_t RelTon;
|
||||||
|
uint8_t Junk;
|
||||||
}
|
}
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__attribute__ ((packed))
|
__attribute__ ((packed))
|
||||||
|
@ -171,6 +172,7 @@ typedef struct SampleTyp_t
|
||||||
uint8_t Typ;
|
uint8_t Typ;
|
||||||
uint8_t Pan;
|
uint8_t Pan;
|
||||||
int8_t RelTon;
|
int8_t RelTon;
|
||||||
|
uint8_t Junk;
|
||||||
int8_t *Pek;
|
int8_t *Pek;
|
||||||
} SampleTyp;
|
} SampleTyp;
|
||||||
|
|
||||||
|
@ -2251,7 +2253,7 @@ static int8_t LoadInstrHeader(PLAYER *p, MEM *buf, uint16_t i)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ih.SampleSize == 0) || (ih.SampleSize > 40)) ih.SampleSize = 40; // default
|
if ((ih.SampleSize == 0) || (ih.SampleSize > 40)) ih.SampleSize = 40; // default
|
||||||
ih.SampleSize -= (1 + 22); // skip junk + name
|
ih.SampleSize -= (22); // skip name
|
||||||
|
|
||||||
if (ih.AntSamp > 32) return (0);
|
if (ih.AntSamp > 32) return (0);
|
||||||
|
|
||||||
|
@ -2264,9 +2266,9 @@ static int8_t LoadInstrHeader(PLAYER *p, MEM *buf, uint16_t i)
|
||||||
|
|
||||||
for (j = 0; j < ih.AntSamp; ++j)
|
for (j = 0; j < ih.AntSamp; ++j)
|
||||||
{
|
{
|
||||||
mread(&ih.Samp[j], 17, 1, buf);
|
mread(&ih.Samp[j], 18, 1, buf);
|
||||||
mseek(buf, 1 + 22, SEEK_CUR); // skip junk + name
|
mseek(buf, 22, SEEK_CUR); // skip junk + name
|
||||||
memcpy(&p->Instr[i]->Samp[j], &ih.Samp[j], 17);
|
memcpy(&p->Instr[i]->Samp[j], &ih.Samp[j], 18);
|
||||||
|
|
||||||
// non-FT2 fix: Force loop flags off if loop length is 0
|
// non-FT2 fix: Force loop flags off if loop length is 0
|
||||||
if (p->Instr[i]->Samp[j].RepL == 0)
|
if (p->Instr[i]->Samp[j].RepL == 0)
|
||||||
|
@ -2292,6 +2294,40 @@ static void CheckSampleRepeat(PLAYER *p, uint16_t ins, uint8_t smp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int8_t get_adpcm_sample(const int8_t *sampleDictionary, const uint8_t *sampleData, int32_t samplePosition, int8_t *lastDelta)
|
||||||
|
{
|
||||||
|
uint8_t byte = sampleData[samplePosition / 2];
|
||||||
|
byte = (samplePosition & 1) ? byte >> 4 : byte & 15;
|
||||||
|
return *lastDelta += sampleDictionary[byte];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Adpcm2Samp(uint8_t * sample, uint32_t length)
|
||||||
|
{
|
||||||
|
const int8_t *sampleDictionary;
|
||||||
|
const uint8_t *sampleData;
|
||||||
|
|
||||||
|
uint32_t samplePosition;
|
||||||
|
int8_t lastDelta;
|
||||||
|
|
||||||
|
uint8_t * sampleDataOut = (uint8_t *) malloc(length);
|
||||||
|
if (!sampleDataOut)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sampleDictionary = (const int8_t *)sample;
|
||||||
|
sampleData = (uint8_t*)sampleDictionary + 16;
|
||||||
|
|
||||||
|
samplePosition = 0;
|
||||||
|
lastDelta = 0;
|
||||||
|
|
||||||
|
while (samplePosition < length)
|
||||||
|
{
|
||||||
|
sampleDataOut[samplePosition] = get_adpcm_sample(sampleDictionary, sampleData, samplePosition, &lastDelta);
|
||||||
|
samplePosition++;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(sample, sampleDataOut, length);
|
||||||
|
}
|
||||||
|
|
||||||
static int8_t LoadInstrSample(PLAYER *p, MEM *buf, uint16_t i)
|
static int8_t LoadInstrSample(PLAYER *p, MEM *buf, uint16_t i)
|
||||||
{
|
{
|
||||||
uint16_t j;
|
uint16_t j;
|
||||||
|
@ -2301,9 +2337,13 @@ static int8_t LoadInstrSample(PLAYER *p, MEM *buf, uint16_t i)
|
||||||
{
|
{
|
||||||
for (j = 1; j <= p->Instr[i]->AntSamp; ++j)
|
for (j = 1; j <= p->Instr[i]->AntSamp; ++j)
|
||||||
{
|
{
|
||||||
|
int adpcm = 0;
|
||||||
p->Instr[i]->Samp[j - 1].Pek = NULL;
|
p->Instr[i]->Samp[j - 1].Pek = NULL;
|
||||||
|
|
||||||
l = p->Instr[i]->Samp[j - 1].Len;
|
l = p->Instr[i]->Samp[j - 1].Len;
|
||||||
|
if (p->Instr[i]->Samp[j - 1].Junk == 0xAD &&
|
||||||
|
!(p->Instr[i]->Samp[j - 1].Typ & (16|32)))
|
||||||
|
adpcm = (((l + 1) / 2) + 16);
|
||||||
if (l > 0)
|
if (l > 0)
|
||||||
{
|
{
|
||||||
p->Instr[i]->Samp[j - 1].Pek = (int8_t *)(malloc(l));
|
p->Instr[i]->Samp[j - 1].Pek = (int8_t *)(malloc(l));
|
||||||
|
@ -2313,8 +2353,11 @@ static int8_t LoadInstrSample(PLAYER *p, MEM *buf, uint16_t i)
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
mread(p->Instr[i]->Samp[j - 1].Pek, l, 1, buf);
|
mread(p->Instr[i]->Samp[j - 1].Pek, adpcm ? adpcm : l, 1, buf);
|
||||||
Delta2Samp(p->Instr[i]->Samp[j - 1].Pek, l, p->Instr[i]->Samp[j - 1].Typ);
|
if (!adpcm)
|
||||||
|
Delta2Samp(p->Instr[i]->Samp[j - 1].Pek, l, p->Instr[i]->Samp[j - 1].Typ);
|
||||||
|
else
|
||||||
|
Adpcm2Samp(p->Instr[i]->Samp[j - 1].Pek, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckSampleRepeat(p, i, (uint8_t)(j) - 1);
|
CheckSampleRepeat(p, i, (uint8_t)(j) - 1);
|
||||||
|
@ -2721,6 +2764,11 @@ void voiceSetSamplePosition(PLAYER *p, uint8_t i, uint16_t value)
|
||||||
void voiceSetVolume(PLAYER *p, uint8_t i, float vol, uint8_t pan, uint8_t sharp)
|
void voiceSetVolume(PLAYER *p, uint8_t i, float vol, uint8_t pan, uint8_t sharp)
|
||||||
{
|
{
|
||||||
#ifdef USE_VOL_RAMP
|
#ifdef USE_VOL_RAMP
|
||||||
|
if (p->rampStyle > 0 && !sharp)
|
||||||
|
{
|
||||||
|
if ((p->voice[i].volumeL == 0 && p->voice[i].volumeR == 0) || vol == 0)
|
||||||
|
sharp = 3;
|
||||||
|
}
|
||||||
if (p->rampStyle > 1 || (p->rampStyle > 0 && sharp))
|
if (p->rampStyle > 1 || (p->rampStyle > 0 && sharp))
|
||||||
{
|
{
|
||||||
const float rampRate = sharp ? p->f_samplesPerFrameSharp : p->f_samplesPerFrame;
|
const float rampRate = sharp ? p->f_samplesPerFrameSharp : p->f_samplesPerFrame;
|
||||||
|
@ -2731,7 +2779,7 @@ void voiceSetVolume(PLAYER *p, uint8_t i, float vol, uint8_t pan, uint8_t sharp)
|
||||||
p->voice[i].volumeL = 0.0f;
|
p->voice[i].volumeL = 0.0f;
|
||||||
p->voice[i].volumeR = 0.0f;
|
p->voice[i].volumeR = 0.0f;
|
||||||
}
|
}
|
||||||
else
|
else if (sharp != 3)
|
||||||
p->voice[i].rampTerminates = 1;
|
p->voice[i].rampTerminates = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2683,6 +2683,11 @@ void voiceSetSamplePosition(PLAYER *p, uint8_t voiceNumber, uint16_t value)
|
||||||
void voiceSetVolume(PLAYER *p, uint8_t voiceNumber, float volume, uint8_t sharp)
|
void voiceSetVolume(PLAYER *p, uint8_t voiceNumber, float volume, uint8_t sharp)
|
||||||
{
|
{
|
||||||
#ifdef USE_VOL_RAMP
|
#ifdef USE_VOL_RAMP
|
||||||
|
if (p->rampStyle > 0 && !sharp)
|
||||||
|
{
|
||||||
|
if (p->voice[voiceNumber].volume == 0 || volume == 0)
|
||||||
|
sharp = 3;
|
||||||
|
}
|
||||||
if (p->rampStyle > 1 || (p->rampStyle > 0 && sharp != 0))
|
if (p->rampStyle > 1 || (p->rampStyle > 0 && sharp != 0))
|
||||||
{
|
{
|
||||||
const float rampRate = sharp ? p->f_samplesPerFrameSharp : p->f_samplesPerFrame;
|
const float rampRate = sharp ? p->f_samplesPerFrameSharp : p->f_samplesPerFrame;
|
||||||
|
@ -2690,7 +2695,7 @@ void voiceSetVolume(PLAYER *p, uint8_t voiceNumber, float volume, uint8_t sharp)
|
||||||
{
|
{
|
||||||
if (volume)
|
if (volume)
|
||||||
p->voice[voiceNumber].volume = 0.0f;
|
p->voice[voiceNumber].volume = 0.0f;
|
||||||
else
|
else if (sharp != 3)
|
||||||
p->voice[voiceNumber].rampTerminates = 1;
|
p->voice[voiceNumber].rampTerminates = 1;
|
||||||
}
|
}
|
||||||
p->voice[voiceNumber].targetVol = volume;
|
p->voice[voiceNumber].targetVol = volume;
|
||||||
|
|
Loading…
Reference in New Issue