ft2-clone

Fasttracker 2 clone
Log | Files | Refs | README | LICENSE

commit 824199e016e6ad8747489995fb518d43726ee8d7
parent 4a95aceff6b745d0dcfc13185c16e682267f7316
Author: Olav Sørensen <olav.sorensen@live.no>
Date:   Fri, 24 Mar 2023 17:17:18 +0100

Code cleanup + voice volume precision change

Diffstat:
Msrc/ft2_audio.c | 223++++++++++++++++++++-----------------------------------------------------------
Msrc/ft2_audio.h | 6+++---
Msrc/ft2_header.h | 2+-
Msrc/ft2_inst_ed.c | 88++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/ft2_module_saver.c | 10+++++-----
Msrc/ft2_replayer.c | 140+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/ft2_replayer.h | 14+++++++-------
Msrc/ft2_sample_saver.c | 8++++----
Msrc/ft2_tables.c | 2+-
Msrc/ft2_tables.h | 2+-
Msrc/ft2_video.c | 6+++---
Msrc/mixer/ft2_mix.h | 1+
Msrc/modloaders/ft2_load_xm.c | 8++++----
Msrc/scopes/ft2_scopes.c | 4++--
14 files changed, 202 insertions(+), 312 deletions(-)

diff --git a/src/ft2_audio.c b/src/ft2_audio.c @@ -14,11 +14,9 @@ #include "ft2_wav_renderer.h" #include "ft2_tables.h" #include "ft2_structs.h" -// -------------------------------- #include "mixer/ft2_mix.h" #include "mixer/ft2_center_mix.h" #include "mixer/ft2_silence_mix.h" -// -------------------------------- // hide POSIX warnings #ifdef _MSC_VER @@ -27,14 +25,11 @@ #define INITIAL_DITHER_SEED 0x12345000 -static int8_t pmpCountDiv, pmpChannels = 2; -static uint16_t smpBuffSize; +static int32_t smpShiftValue; static uint32_t oldAudioFreq, tickTimeLenInt, randSeed = INITIAL_DITHER_SEED; static uint64_t tickTimeLenFrac; -static float fAudioNormalizeMul, fPanningTab[256+1]; -static double dAudioNormalizeMul, dPrngStateL, dPrngStateR; +static double dAudioNormalizeMul, dPanningTab[256+1], dPrngStateL, dPrngStateR; static voice_t voice[MAX_CHANNELS * 2]; -static void (*sendAudSamplesFunc)(uint8_t *, uint32_t, uint8_t); // "send mixed samples" routines // globalized audio_t audio; @@ -121,7 +116,6 @@ void setAudioAmp(int16_t amp, int16_t masterVol, bool bitDepth32Flag) dAmp *= 32768.0; dAudioNormalizeMul = dAmp; - fAudioNormalizeMul = (float)dAmp; } void decreaseMasterVol(void) @@ -206,17 +200,17 @@ void audioSetInterpolationType(uint8_t interpolationType) void calcPanningTable(void) { - // same formula as FT2's panning table (with 0.0f..1.0f range) + // same formula as FT2's panning table (with 0.0..1.0 range) for (int32_t i = 0; i <= 256; i++) - fPanningTab[i] = sqrtf(i / 256.0f); + dPanningTab[i] = sqrt(i / 256.0); } static void voiceUpdateVolumes(int32_t i, uint8_t status) { voice_t *v = &voice[i]; - const float fVolumeL = v->fVolume * fPanningTab[256-v->panning]; - const float fVolumeR = v->fVolume * fPanningTab[ v->panning]; + const float fVolumeL = (float)(v->dVolume * dPanningTab[256-v->panning]); + const float fVolumeR = (float)(v->dVolume * dPanningTab[ v->panning]); if (!audio.volumeRampingFlag) { @@ -244,47 +238,35 @@ static void voiceUpdateVolumes(int32_t i, uint8_t status) const float fVolumeLTarget = -f->fVolumeL; const float fVolumeRTarget = -f->fVolumeR; - f->volumeRampLength = audio.quickVolRampSamples; - f->fVolumeLDelta = fVolumeLTarget / (int32_t)f->volumeRampLength; - f->fVolumeRDelta = fVolumeRTarget / (int32_t)f->volumeRampLength; + f->volumeRampLength = audio.quickVolRampSamples; // 5ms + const float fVolumeRampLength = (float)(int32_t)f->volumeRampLength; + + f->fVolumeLDelta = fVolumeLTarget / fVolumeRampLength; + f->fVolumeRDelta = fVolumeRTarget / fVolumeRampLength; f->isFadeOutVoice = true; } // make current voice fade in from zero when it starts - v->fVolumeL = 0.0f; - v->fVolumeR = 0.0f; + v->fVolumeL = v->fVolumeR = 0.0f; } - // ramp volume changes - - /* FT2 has two internal volume ramping lengths: - ** IS_QuickVol: 5ms - ** Normal: The duration of a tick (samplesPerTick) - */ - // if destination volume and current volume is the same (and we have no sample trigger), don't do ramp if (fVolumeL == v->fVolumeL && fVolumeR == v->fVolumeR && !(status & IS_Trigger)) { - v->volumeRampLength = 0; // there is no volume change + v->volumeRampLength = 0; } else { const float fVolumeLTarget = fVolumeL - v->fVolumeL; const float fVolumeRTarget = fVolumeR - v->fVolumeR; - if (status & IS_QuickVol) - { - v->volumeRampLength = audio.quickVolRampSamples; - v->fVolumeLDelta = fVolumeLTarget / (int32_t)v->volumeRampLength; - v->fVolumeRDelta = fVolumeRTarget / (int32_t)v->volumeRampLength; - } - else - { - v->volumeRampLength = audio.samplesPerTickInt; - v->fVolumeLDelta = fVolumeLTarget / (int32_t)v->volumeRampLength; - v->fVolumeRDelta = fVolumeRTarget / (int32_t)v->volumeRampLength; - } + // IS_QuickVol = 5ms, otherwise the duration of a tick + v->volumeRampLength = (status & IS_QuickVol) ? audio.quickVolRampSamples : audio.samplesPerTickInt; + const float fVolumeRampLength = (float)(int32_t)v->volumeRampLength; + + v->fVolumeLDelta = fVolumeLTarget / fVolumeRampLength; + v->fVolumeRDelta = fVolumeRTarget / fVolumeRampLength; } } @@ -367,9 +349,10 @@ void updateVoices(void) if (status & IS_Vol) { - v->fVolume = ch->fFinalVol; + v->dVolume = ch->dFinalVol; - const int32_t scopeVolume = (int32_t)((SCOPE_HEIGHT * ch->fFinalVol) + 0.5f); // rounded + // set scope volume + const int32_t scopeVolume = (int32_t)((SCOPE_HEIGHT * ch->dFinalVol) + 0.5); // rounded v->scopeVolume = (uint8_t)scopeVolume; } @@ -435,7 +418,7 @@ static inline int32_t random32(void) return (int32_t)randSeed; } -static void sendSamples16BitDitherStereo(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels) +static void sendSamples16BitDitherStereo(uint8_t *stream, uint32_t sampleBlockLength) { int32_t out32; double dOut, dPrng; @@ -465,91 +448,27 @@ static void sendSamples16BitDitherStereo(uint8_t *stream, uint32_t sampleBlockLe audio.fMixBufferL[i] = 0.0f; audio.fMixBufferR[i] = 0.0f; } - - (void)numAudioChannels; } -static void sendSamples16BitDitherMultiChan(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels) +static void sendSamples32BitStereo(uint8_t *stream, uint32_t sampleBlockLength) { - int32_t out32; - double dOut, dPrng; - - int16_t *streamPointer16 = (int16_t *)stream; - for (uint32_t i = 0; i < sampleBlockLength; i++) - { - // left channel - 1-bit triangular dithering - dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5 - dOut = (double)audio.fMixBufferL[i] * dAudioNormalizeMul; - dOut = (dOut + dPrng) - dPrngStateL; - dPrngStateL = dPrng; - out32 = (int32_t)dOut; - CLAMP16(out32); - *streamPointer16++ = (int16_t)out32; - - // right channel - 1-bit triangular dithering - dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5 - dOut = (double)audio.fMixBufferR[i] * dAudioNormalizeMul; - dOut = (dOut + dPrng) - dPrngStateR; - dPrngStateR = dPrng; - out32 = (int32_t)dOut; - CLAMP16(out32); - *streamPointer16++ = (int16_t)out32; - - // clear what we read from the mixing buffer - audio.fMixBufferL[i] = 0.0f; - audio.fMixBufferR[i] = 0.0f; - - // send zeroes to the rest of the channels - for (uint32_t j = 2; j < numAudioChannels; j++) - *streamPointer16++ = 0; - } -} - -static void sendSamples32BitStereo(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels) -{ - float fOut, *fStreamPointer32 = (float *)stream; + double dOut; + float *fStreamPointer32 = (float *)stream; for (uint32_t i = 0; i < sampleBlockLength; i++) { // left channel - fOut = audio.fMixBufferL[i] * fAudioNormalizeMul; - fOut = CLAMP(fOut, -1.0f, 1.0f); - *fStreamPointer32++ = fOut; - - // right channel - fOut = audio.fMixBufferR[i] * fAudioNormalizeMul; - fOut = CLAMP(fOut, -1.0f, 1.0f); - *fStreamPointer32++ = fOut; - - // clear what we read from the mixing buffer - audio.fMixBufferL[i] = 0.0f; - audio.fMixBufferR[i] = 0.0f; - } - - (void)numAudioChannels; -} - -static void sendSamples32BitMultiChan(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels) -{ - float fOut, *fStreamPointer32 = (float *)stream; - for (uint32_t i = 0; i < sampleBlockLength; i++) - { - // left channel - fOut = audio.fMixBufferL[i] * fAudioNormalizeMul; - fOut = CLAMP(fOut, -1.0f, 1.0f); - *fStreamPointer32++ = fOut; + dOut = (double)audio.fMixBufferL[i] * dAudioNormalizeMul; + dOut = CLAMP(dOut, -1.0, 1.0); + *fStreamPointer32++ = (float)dOut; // right channel - fOut = audio.fMixBufferR[i] * fAudioNormalizeMul; - fOut = CLAMP(fOut, -1.0f, 1.0f); - *fStreamPointer32++ = fOut; + dOut = (double)audio.fMixBufferR[i] * dAudioNormalizeMul; + dOut = CLAMP(dOut, -1.0, 1.0); + *fStreamPointer32++ = (float)dOut; // clear what we read from the mixing buffer audio.fMixBufferL[i] = 0.0f; audio.fMixBufferR[i] = 0.0f; - - // send zeroes to the rest of the channels - for (uint32_t j = 2; j < numAudioChannels; j++) - *fStreamPointer32++ = 0.0f; } } @@ -598,9 +517,9 @@ void mixReplayerTickToBuffer(uint32_t samplesToMix, uint8_t *stream, uint8_t bit // normalize mix buffer and send to audio stream if (bitDepth == 16) - sendSamples16BitDitherStereo(stream, samplesToMix, 2); + sendSamples16BitDitherStereo(stream, samplesToMix); else - sendSamples32BitStereo(stream, samplesToMix, 2); + sendSamples32BitStereo(stream, samplesToMix); } int32_t pattQueueReadSize(void) @@ -903,7 +822,7 @@ static void fillVisualsSyncBuffer(void) c->smpStartPos = s->smpStartPos; c->pianoNoteNum = 255; // no piano key - if (songPlaying && (c->status & IS_Period) && s->envSustainActive) + if (songPlaying && (c->status & IS_Period) && !s->keyOff) { const int32_t note = getPianoKey(s->finalPeriod, s->finetune, s->relativeNote); if (note >= 0 && note <= 95) @@ -929,7 +848,7 @@ static void SDLCALL audioCallback(void *userdata, Uint8 *stream, int len) if (editor.wavIsRendering) return; - len /= pmpCountDiv; // bytes -> samples + len >>= smpShiftValue; // bytes -> samples if (len <= 0) return; @@ -972,8 +891,10 @@ static void SDLCALL audioCallback(void *userdata, Uint8 *stream, int len) samplesLeft -= samplesToMix; } - // normalize mix buffer and send to audio stream - sendAudSamplesFunc(stream, len, pmpChannels); + if (config.specialFlags & BITDEPTH_16) + sendSamples16BitDitherStereo(stream, len); + else + sendSamples32BitStereo(stream, len); (void)userdata; } @@ -1007,30 +928,6 @@ static void freeAudioBuffers(void) } } -void updateSendAudSamplesRoutine(bool lockMixer) -{ - if (lockMixer) - lockMixerCallback(); - - if (config.specialFlags & BITDEPTH_16) - { - if (pmpChannels > 2) - sendAudSamplesFunc = sendSamples16BitDitherMultiChan; - else - sendAudSamplesFunc = sendSamples16BitDitherStereo; - } - else - { - if (pmpChannels > 2) - sendAudSamplesFunc = sendSamples32BitMultiChan; - else - sendAudSamplesFunc = sendSamples32BitStereo; - } - - if (lockMixer) - unlockMixerCallback(); -} - static void calcAudioLatencyVars(int32_t audioBufferSize, int32_t audioFreq) { double dInt; @@ -1079,20 +976,16 @@ bool setupAudio(bool showErrorMsg) audio.wantFreq = config.audioFreq; audio.wantSamples = configAudioBufSize; - audio.wantChannels = 2; // set up audio device memset(&want, 0, sizeof (want)); - - // these three may change after opening a device, but our mixer is dealing with it want.freq = config.audioFreq; want.format = (config.specialFlags & BITDEPTH_32) ? AUDIO_F32 : AUDIO_S16; want.channels = 2; - // ------------------------------------------------------------------------------- want.callback = audioCallback; want.samples = configAudioBufSize; - audio.dev = SDL_OpenAudioDevice(audio.currOutputDevice, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); // prevent SDL2 from resampling + audio.dev = SDL_OpenAudioDevice(audio.currOutputDevice, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); if (audio.dev == 0) { if (showErrorMsg) @@ -1105,18 +998,26 @@ bool setupAudio(bool showErrorMsg) if (have.format != AUDIO_S16 && have.format != AUDIO_F32) { if (showErrorMsg) - showErrorMsgBox("Couldn't open audio device:\nThe program doesn't support an SDL_AudioFormat of '%d' (not 16-bit or 32-bit float).", - (uint32_t)have.format); + showErrorMsgBox("Couldn't open audio device:\nThis program only supports 16-bit or 32-bit float audio streams. Sorry!"); closeAudio(); return false; } - // test if the received audio rate is compatible + // test if the received audio stream is compatible + + if (have.channels != 2) + { + if (showErrorMsg) + showErrorMsgBox("Couldn't open audio device:\nThis program only supports stereo audio streams. Sorry!"); + + closeAudio(); + return false; + } #if CPU_64BIT if (have.freq != 44100 && have.freq != 48000 && have.freq != 96000 && have.freq != 192000) -#else +#else // 32-bit CPUs only support .16fp resampling precision. Not sensible with high rates. if (have.freq != 44100 && have.freq != 48000) #endif { @@ -1151,18 +1052,10 @@ bool setupAudio(bool showErrorMsg) audio.haveFreq = have.freq; audio.haveSamples = have.samples; - audio.haveChannels = have.channels; - - // set a few variables - - config.audioFreq = have.freq; - audio.freq = have.freq; - smpBuffSize = have.samples; + config.audioFreq = audio.freq = have.freq; calcAudioLatencyVars(have.samples, have.freq); - - pmpChannels = have.channels; - pmpCountDiv = pmpChannels * ((newBitDepth == 16) ? sizeof (int16_t) : sizeof (float)); + smpShiftValue = (newBitDepth == 16) ? 2 : 3; // make a copy of the new known working audio settings @@ -1183,8 +1076,8 @@ bool setupAudio(bool showErrorMsg) stopAllScopes(); - audio.tickSampleCounter = 0; // zero tick sample counter so that it will instantly initiate a tick - audio.tickSampleCounterFrac = 0; + // zero tick sample counter so that it will instantly initiate a tick + audio.tickSampleCounterFrac = audio.tickSampleCounter = 0; calcReplayerVars(audio.freq); @@ -1193,9 +1086,7 @@ bool setupAudio(bool showErrorMsg) setMixerBPM(song.BPM); // this is important - updateSendAudSamplesRoutine(false); audio.resetSyncTickTimeFlag = true; - return true; } diff --git a/src/ft2_audio.h b/src/ft2_audio.h @@ -59,7 +59,7 @@ typedef struct audio_t double dHz2MixDeltaMul, dAudioLatencyMs; SDL_AudioDeviceID dev; - uint32_t wantFreq, haveFreq, wantSamples, haveSamples, wantChannels, haveChannels; + uint32_t wantFreq, haveFreq, wantSamples, haveSamples; } audio_t; typedef struct @@ -78,7 +78,8 @@ typedef struct const int16_t *leftEdgeTaps16; const float *fSincLUT; - float fVolume, fVolumeL, fVolumeR, fVolumeLDelta, fVolumeRDelta, fVolumeLTarget, fVolumeRTarget; + double dVolume; + float fVolumeL, fVolumeR, fVolumeLDelta, fVolumeRDelta, fVolumeLTarget, fVolumeRTarget; } voice_t; #ifdef _MSC_VER @@ -153,7 +154,6 @@ void lockAudio(void); void unlockAudio(void); void lockMixerCallback(void); void unlockMixerCallback(void); -void updateSendAudSamplesRoutine(bool lockMixer); void resetRampVolumes(void); void updateVoices(void); void mixReplayerTickToBuffer(uint32_t samplesToMix, uint8_t *stream, uint8_t bitDepth); diff --git a/src/ft2_header.h b/src/ft2_header.h @@ -12,7 +12,7 @@ #endif #include "ft2_replayer.h" -#define PROG_VER_STR "1.65" +#define PROG_VER_STR "1.66" // do NOT change these! It will only mess things up... diff --git a/src/ft2_inst_ed.c b/src/ft2_inst_ed.c @@ -131,9 +131,9 @@ void sanitizeInstrument(instr_t *ins) ins->midiBend = CLAMP(ins->midiBend, 0, 36); if (ins->midiChannel > 15) ins->midiChannel = 15; - if (ins->vibDepth > 0x0F) ins->vibDepth = 0x0F; - if (ins->vibRate > 0x3F) ins->vibRate = 0x3F; - if (ins->vibType > 3) ins->vibType = 0; + if (ins->autoVibDepth > 0x0F) ins->autoVibDepth = 0x0F; + if (ins->autoVibRate > 0x3F) ins->autoVibRate = 0x3F; + if (ins->autoVibType > 3) ins->autoVibType = 0; for (int32_t i = 0; i < 96; i++) { @@ -537,17 +537,17 @@ static void drawFadeout(void) static void drawVibSpeed(void) { - hexOutBg(505, 236, PAL_FORGRND, PAL_DESKTOP, getCurDispInstr()->vibRate, 2); + hexOutBg(505, 236, PAL_FORGRND, PAL_DESKTOP, getCurDispInstr()->autoVibRate, 2); } static void drawVibDepth(void) { - hexOutBg(512, 250, PAL_FORGRND, PAL_DESKTOP, getCurDispInstr()->vibDepth, 1); + hexOutBg(512, 250, PAL_FORGRND, PAL_DESKTOP, getCurDispInstr()->autoVibDepth, 1); } static void drawVibSweep(void) { - hexOutBg(505, 264, PAL_FORGRND, PAL_DESKTOP, getCurDispInstr()->vibSweep, 2); + hexOutBg(505, 264, PAL_FORGRND, PAL_DESKTOP, getCurDispInstr()->autoVibSweep, 2); } static void drawRelativeNote(void) @@ -598,10 +598,10 @@ static void setStdVolEnvelope(instr_t *ins, uint8_t num) ins->volEnvLoopEnd = (uint8_t)config.stdVolEnvLoopEnd[num]; ins->volEnvLength = (uint8_t)config.stdVolEnvLength[num]; ins->volEnvFlags = (uint8_t)config.stdVolEnvFlags[num]; - ins->vibRate = (uint8_t)config.stdVibRate[num]; - ins->vibDepth = (uint8_t)config.stdVibDepth[num]; - ins->vibSweep = (uint8_t)config.stdVibSweep[num]; - ins->vibType = (uint8_t)config.stdVibType[num]; + ins->autoVibRate = (uint8_t)config.stdVibRate[num]; + ins->autoVibDepth = (uint8_t)config.stdVibDepth[num]; + ins->autoVibSweep = (uint8_t)config.stdVibSweep[num]; + ins->autoVibType = (uint8_t)config.stdVibType[num]; memcpy(ins->volEnvPoints, config.stdEnvPoints[num][0], sizeof (int16_t) * 12 * 2); @@ -641,10 +641,10 @@ static void setOrStoreVolEnvPreset(uint8_t num) config.stdVolEnvLoopEnd[num] = ins->volEnvLoopEnd; config.stdVolEnvLength[num] = ins->volEnvLength; config.stdVolEnvFlags[num] = ins->volEnvFlags; - config.stdVibRate[num] = ins->vibRate; - config.stdVibDepth[num] = ins->vibDepth; - config.stdVibSweep[num] = ins->vibSweep; - config.stdVibType[num] = ins->vibType; + config.stdVibRate[num] = ins->autoVibRate; + config.stdVibDepth[num] = ins->autoVibDepth; + config.stdVibSweep[num] = ins->autoVibSweep; + config.stdVibType[num] = ins->autoVibType; memcpy(config.stdEnvPoints[num][0], ins->volEnvPoints, sizeof (int16_t) * 12 * 2); } @@ -673,10 +673,10 @@ static void setOrStorePanEnvPreset(uint8_t num) config.stdPanEnvLoopEnd[num] = ins->panEnvLoopEnd; config.stdPanEnvLength[num] = ins->panEnvLength; config.stdPanEnvFlags[num] = ins->panEnvFlags; - config.stdVibRate[num] = ins->vibRate; - config.stdVibDepth[num] = ins->vibDepth; - config.stdVibSweep[num] = ins->vibSweep; - config.stdVibType[num] = ins->vibType; + config.stdVibRate[num] = ins->autoVibRate; + config.stdVibDepth[num] = ins->autoVibDepth; + config.stdVibSweep[num] = ins->autoVibSweep; + config.stdVibType[num] = ins->autoVibType; memcpy(config.stdEnvPoints[num][1], ins->panEnvPoints, sizeof (int16_t) * 12 * 2); } @@ -1376,9 +1376,9 @@ void setVibSpeedScroll(uint32_t pos) return; } - if (ins->vibRate != (uint8_t)pos) + if (ins->autoVibRate != (uint8_t)pos) { - ins->vibRate = (uint8_t)pos; + ins->autoVibRate = (uint8_t)pos; drawVibSpeed(); setSongModifiedFlag(); } @@ -1393,9 +1393,9 @@ void setVibDepthScroll(uint32_t pos) return; } - if (ins->vibDepth != (uint8_t)pos) + if (ins->autoVibDepth != (uint8_t)pos) { - ins->vibDepth = (uint8_t)pos; + ins->autoVibDepth = (uint8_t)pos; drawVibDepth(); setSongModifiedFlag(); } @@ -1410,9 +1410,9 @@ void setVibSweepScroll(uint32_t pos) return; } - if (ins->vibSweep != (uint8_t)pos) + if (ins->autoVibSweep != (uint8_t)pos) { - ins->vibSweep = (uint8_t)pos; + ins->autoVibSweep = (uint8_t)pos; drawVibSweep(); setSongModifiedFlag(); } @@ -1423,7 +1423,7 @@ void rbVibWaveSine(void) if (instr[editor.curInstr] == NULL || editor.curInstr == 0) return; - instr[editor.curInstr]->vibType = 0; + instr[editor.curInstr]->autoVibType = 0; uncheckRadioButtonGroup(RB_GROUP_INST_WAVEFORM); radioButtons[RB_INST_WAVE_SINE].state = RADIOBUTTON_CHECKED; @@ -1436,7 +1436,7 @@ void rbVibWaveSquare(void) if (instr[editor.curInstr] == NULL || editor.curInstr == 0) return; - instr[editor.curInstr]->vibType = 1; + instr[editor.curInstr]->autoVibType = 1; uncheckRadioButtonGroup(RB_GROUP_INST_WAVEFORM); radioButtons[RB_INST_WAVE_SQUARE].state = RADIOBUTTON_CHECKED; @@ -1449,7 +1449,7 @@ void rbVibWaveRampDown(void) if (instr[editor.curInstr] == NULL || editor.curInstr == 0) return; - instr[editor.curInstr]->vibType = 2; + instr[editor.curInstr]->autoVibType = 2; uncheckRadioButtonGroup(RB_GROUP_INST_WAVEFORM); radioButtons[RB_INST_WAVE_RAMP_DOWN].state = RADIOBUTTON_CHECKED; @@ -1462,7 +1462,7 @@ void rbVibWaveRampUp(void) if (instr[editor.curInstr] == NULL || editor.curInstr == 0) return; - instr[editor.curInstr]->vibType = 3; + instr[editor.curInstr]->autoVibType = 3; uncheckRadioButtonGroup(RB_GROUP_INST_WAVEFORM); radioButtons[RB_INST_WAVE_RAMP_UP].state = RADIOBUTTON_CHECKED; @@ -1702,7 +1702,7 @@ void drawPiano(chSyncData_t *chSyncData) channel_t *c = channel; for (int32_t i = 0; i < song.numChannels; i++, c++) { - if (c->instrNum == editor.curInstr && c->envSustainActive) + if (c->instrNum == editor.curInstr && !c->keyOff) { const int32_t note = getPianoKey(c->finalPeriod, c->finetune, c->relativeNote); if (note >= 0 && note <= 95) @@ -2214,14 +2214,14 @@ void updateInstEditor(void) setScrollBarPos(SB_INST_PAN, s->panning, false); setScrollBarPos(SB_INST_FTUNE, 128 + s->finetune, false); setScrollBarPos(SB_INST_FADEOUT, ins->fadeout, false); - setScrollBarPos(SB_INST_VIBSPEED, ins->vibRate, false); - setScrollBarPos(SB_INST_VIBDEPTH, ins->vibDepth, false); - setScrollBarPos(SB_INST_VIBSWEEP, ins->vibSweep, false); + setScrollBarPos(SB_INST_VIBSPEED, ins->autoVibRate, false); + setScrollBarPos(SB_INST_VIBDEPTH, ins->autoVibDepth, false); + setScrollBarPos(SB_INST_VIBSWEEP, ins->autoVibSweep, false); // set radio buttons uncheckRadioButtonGroup(RB_GROUP_INST_WAVEFORM); - switch (ins->vibType) + switch (ins->autoVibType) { default: case 0: tmpID = RB_INST_WAVE_SINE; break; @@ -2972,10 +2972,10 @@ static int32_t SDLCALL saveInstrThread(void *ptr) ih.panEnvLoopEnd = ins->panEnvLoopEnd; ih.volEnvFlags = ins->volEnvFlags; ih.panEnvFlags = ins->panEnvFlags; - ih.vibType = ins->vibType; - ih.vibSweep = ins->vibSweep; - ih.vibDepth = ins->vibDepth; - ih.vibRate = ins->vibRate; + ih.vibType = ins->autoVibType; + ih.vibSweep = ins->autoVibSweep; + ih.vibDepth = ins->autoVibDepth; + ih.vibRate = ins->autoVibRate; ih.fadeout = ins->fadeout; ih.midiOn = ins->midiOn ? 1 : 0; ih.midiChannel = ins->midiChannel; @@ -3177,10 +3177,10 @@ static int32_t SDLCALL loadInstrThread(void *ptr) ins->panEnvLoopEnd = xi_h.panEnvLoopEnd; ins->volEnvFlags = xi_h.volEnvFlags; ins->panEnvFlags = xi_h.panEnvFlags; - ins->vibType = xi_h.vibType; - ins->vibSweep = xi_h.vibSweep; - ins->vibDepth = xi_h.vibDepth; - ins->vibRate = xi_h.vibRate; + ins->autoVibType = xi_h.vibType; + ins->autoVibSweep = xi_h.vibSweep; + ins->autoVibDepth = xi_h.vibDepth; + ins->autoVibRate = xi_h.vibRate; ins->fadeout = xi_h.fadeout; ins->midiOn = (xi_h.midiOn == 1) ? true : false; ins->midiChannel = xi_h.midiChannel; @@ -3364,9 +3364,9 @@ static int32_t SDLCALL loadInstrThread(void *ptr) if (i == 0) { - ins->vibSweep = patWave_h.vibSweep; - ins->vibRate = (patWave_h.vibRate + 2) >> 2; // rounded - ins->vibDepth = (patWave_h.vibDepth + 1) >> 1; // rounded + ins->autoVibSweep = patWave_h.vibSweep; + ins->autoVibRate = (patWave_h.vibRate + 2) >> 2; // rounded + ins->autoVibDepth = (patWave_h.vibDepth + 1) >> 1; // rounded } s = &instr[editor.curInstr]->smp[i]; diff --git a/src/ft2_module_saver.c b/src/ft2_module_saver.c @@ -187,10 +187,10 @@ bool saveXM(UNICHAR *filenameU) ih.panEnvLoopEnd = ins->panEnvLoopEnd; ih.volEnvFlags = ins->volEnvFlags; ih.panEnvFlags = ins->panEnvFlags; - ih.vibType = ins->vibType; - ih.vibSweep = ins->vibSweep; - ih.vibDepth = ins->vibDepth; - ih.vibRate = ins->vibRate; + ih.vibType = ins->autoVibType; + ih.vibSweep = ins->autoVibSweep; + ih.vibDepth = ins->autoVibDepth; + ih.vibRate = ins->autoVibRate; ih.fadeout = ins->fadeout; ih.midiOn = ins->midiOn ? 1 : 0; ih.midiChannel = ins->midiChannel; @@ -363,7 +363,7 @@ static bool saveMOD(UNICHAR *filenameU) if (j == 1) { - if (ins->fadeout != 0 || ins->volEnvFlags != 0 || ins->panEnvFlags != 0 || ins->vibRate > 0 || + if (ins->fadeout != 0 || ins->volEnvFlags != 0 || ins->panEnvFlags != 0 || ins->autoVibRate > 0 || GET_LOOPTYPE(smp->flags) == LOOP_BIDI || smp->relativeNote != 0 || ins->midiOn) { test = true; diff --git a/src/ft2_replayer.c b/src/ft2_replayer.c @@ -335,8 +335,6 @@ static void retrigEnvelopeVibrato(channel_t *ch) ch->retrigCnt = 0; ch->tremorPos = 0; - ch->envSustainActive = true; - instr_t *ins = ch->instrPtr; assert(ins != NULL); @@ -352,29 +350,29 @@ static void retrigEnvelopeVibrato(channel_t *ch) ch->panEnvPos = 0; } + ch->keyOff = false; ch->fadeoutSpeed = ins->fadeout; // FT2 doesn't check if fadeout is more than 4095! ch->fadeoutVol = 32768; - if (ins->vibDepth > 0) + if (ins->autoVibDepth > 0) { - ch->eVibPos = 0; - - if (ins->vibSweep > 0) + ch->autoVibPos = 0; + if (ins->autoVibSweep > 0) { - ch->eVibAmp = 0; - ch->eVibSweep = (ins->vibDepth << 8) / ins->vibSweep; + ch->autoVibAmp = 0; + ch->autoVibSweep = (ins->autoVibDepth << 8) / ins->autoVibSweep; } else { - ch->eVibAmp = ins->vibDepth << 8; - ch->eVibSweep = 0; + ch->autoVibAmp = ins->autoVibDepth << 8; + ch->autoVibSweep = 0; } } } void keyOff(channel_t *ch) { - ch->envSustainActive = false; + ch->keyOff = true; instr_t *ins = ch->instrPtr; assert(ins != NULL); @@ -571,8 +569,8 @@ static void finePortaDown(channel_t *ch, uint8_t param) ch->fPortaDownSpeed = param; ch->realPeriod += param << 2; - if ((int16_t)ch->realPeriod > MAX_FRQ-1) // FT2 bug, should've been unsigned comparison - ch->realPeriod = MAX_FRQ-1; + if ((int16_t)ch->realPeriod >= 32000) // FT2 bug, should've been unsigned comparison + ch->realPeriod = 32000-1; ch->outPeriod = ch->realPeriod; ch->status |= IS_Period; @@ -1128,8 +1126,8 @@ static void xFinePorta(channel_t *ch, uint8_t param) uint16_t newPeriod = ch->realPeriod; newPeriod += param; - if ((int16_t)newPeriod > MAX_FRQ-1) // FT2 bug, should've been unsigned comparison - newPeriod = MAX_FRQ-1; + if ((int16_t)newPeriod >= 32000) // FT2 bug, should've been unsigned comparison + newPeriod = 32000-1; ch->outPeriod = ch->realPeriod = newPeriod; ch->status |= IS_Period; @@ -1377,28 +1375,25 @@ static void updateChannel(channel_t *ch) { bool envInterpolateFlag, envDidInterpolate; uint8_t envPos; - int16_t autoVibVal; - uint16_t autoVibAmp; int32_t envVal; - float fVol; + double dVol; instr_t *ins = ch->instrPtr; assert(ins != NULL); // *** FADEOUT *** - if (!ch->envSustainActive) + if (ch->keyOff) { - ch->status |= IS_Vol; + ch->status |= IS_Vol; // always update volume, even if fadeout has reached 0 - // unsigned clamp + reset - if (ch->fadeoutVol >= ch->fadeoutSpeed) + if (ch->fadeoutSpeed > 0) // 0..4095 { ch->fadeoutVol -= ch->fadeoutSpeed; - } - else - { - ch->fadeoutVol = 0; - ch->fadeoutSpeed = 0; + if (ch->fadeoutVol <= 0) + { + ch->fadeoutVol = 0; + ch->fadeoutSpeed = 0; + } } } @@ -1424,7 +1419,7 @@ static void updateChannel(channel_t *ch) if (envPos == ins->volEnvLoopEnd) { - if (!(ins->volEnvFlags & ENV_SUSTAIN) || envPos != ins->volEnvSustain || ch->envSustainActive) + if (!(ins->volEnvFlags & ENV_SUSTAIN) || envPos != ins->volEnvSustain || !ch->keyOff) { envPos = ins->volEnvLoopStart; ch->volEnvTick = ins->volEnvPoints[envPos][0]; @@ -1438,7 +1433,7 @@ static void updateChannel(channel_t *ch) if (envPos < ins->volEnvLength) { envInterpolateFlag = true; - if ((ins->volEnvFlags & ENV_SUSTAIN) && ch->envSustainActive) + if ((ins->volEnvFlags & ENV_SUSTAIN) && !ch->keyOff) { if (envPos-1 == ins->volEnvSustain) { @@ -1488,25 +1483,26 @@ static void updateChannel(channel_t *ch) const int32_t vol = song.globalVolume * ch->outVol * ch->fadeoutVol; - fVol = vol * (1.0f / (64.0f * 64.0f * 32768.0f)); - fVol *= (int32_t)envVal * (1.0f / (64.0f * (1 << 16))); // volume envelope value + dVol = vol * (1.0 / (64.0 * 64.0 * 32768.0)); + dVol *= envVal * (1.0 / (64.0 * (1 << 16))); // volume envelope value ch->status |= IS_Vol; // update mixer vol every tick when vol envelope is enabled } else { const int32_t vol = song.globalVolume * ch->outVol * ch->fadeoutVol; - fVol = vol * (1.0f / (64.0f * 64.0f * 32768.0f)); + + dVol = vol * (1.0 / (64.0 * 64.0 * 32768.0)); } /* FT2 doesn't clamp here, but it's actually important if you ** move envelope points with the mouse while playing the instrument. */ - ch->fFinalVol = CLAMP(fVol, 0.0f, 1.0f); + ch->dFinalVol = CLAMP(dVol, 0.0, 1.0); } else { - ch->fFinalVol = 0.0f; + ch->dFinalVol = 0.0; } // *** PANNING ENVELOPE *** @@ -1528,7 +1524,7 @@ static void updateChannel(channel_t *ch) if (envPos == ins->panEnvLoopEnd) { - if (!(ins->panEnvFlags & ENV_SUSTAIN) || envPos != ins->panEnvSustain || ch->envSustainActive) + if (!(ins->panEnvFlags & ENV_SUSTAIN) || envPos != ins->panEnvSustain || !ch->keyOff) { envPos = ins->panEnvLoopStart; @@ -1543,7 +1539,7 @@ static void updateChannel(channel_t *ch) if (envPos < ins->panEnvLength) { envInterpolateFlag = true; - if ((ins->panEnvFlags & ENV_SUSTAIN) && ch->envSustainActive) + if ((ins->panEnvFlags & ENV_SUSTAIN) && !ch->keyOff) { if (envPos-1 == ins->panEnvSustain) { @@ -1606,51 +1602,53 @@ static void updateChannel(channel_t *ch) // *** AUTO VIBRATO *** #ifdef HAS_MIDI - if (ch->midiVibDepth > 0 || ins->vibDepth > 0) + if (ch->midiVibDepth > 0 || ins->autoVibDepth > 0) #else if (ins->vibDepth > 0) #endif { - if (ch->eVibSweep > 0) + uint16_t autoVibAmp; + + if (ch->autoVibSweep > 0) { - autoVibAmp = ch->eVibSweep; - if (ch->envSustainActive) + autoVibAmp = ch->autoVibSweep; + if (!ch->keyOff) { - autoVibAmp += ch->eVibAmp; - if ((autoVibAmp >> 8) > ins->vibDepth) + autoVibAmp += ch->autoVibAmp; + if ((autoVibAmp >> 8) > ins->autoVibDepth) { - autoVibAmp = ins->vibDepth << 8; - ch->eVibSweep = 0; + autoVibAmp = ins->autoVibDepth << 8; + ch->autoVibSweep = 0; } - ch->eVibAmp = autoVibAmp; + ch->autoVibAmp = autoVibAmp; } } else { - autoVibAmp = ch->eVibAmp; + autoVibAmp = ch->autoVibAmp; } #ifdef HAS_MIDI // non-FT2 hack to make modulation wheel work when auto vibrato rate is zero - if (ch->midiVibDepth > 0 && ins->vibRate == 0) - ins->vibRate = 0x20; + if (ch->midiVibDepth > 0 && ins->autoVibRate == 0) + ins->autoVibRate = 0x20; autoVibAmp += ch->midiVibDepth; #endif - ch->eVibPos += ins->vibRate; + ch->autoVibPos += ins->autoVibRate; - if (ins->vibType == 1) autoVibVal = (ch->eVibPos > 127) ? 64 : -64; // square - else if (ins->vibType == 2) autoVibVal = (((ch->eVibPos >> 1) + 64) & 127) - 64; // ramp up - else if (ins->vibType == 3) autoVibVal = ((-(ch->eVibPos >> 1) + 64) & 127) - 64; // ramp down - else autoVibVal = vibSineTab[ch->eVibPos]; // sine + int16_t autoVibVal; + if (ins->autoVibType == 1) autoVibVal = (ch->autoVibPos > 127) ? 64 : -64; // square + else if (ins->autoVibType == 2) autoVibVal = (((ch->autoVibPos >> 1) + 64) & 127) - 64; // ramp up + else if (ins->autoVibType == 3) autoVibVal = ((-(ch->autoVibPos >> 1) + 64) & 127) - 64; // ramp down + else autoVibVal = autoVibSineTab[ch->autoVibPos]; // sine - autoVibVal <<= 2; - uint16_t tmpPeriod = (autoVibVal * (int16_t)autoVibAmp) >> 16; + autoVibVal = (autoVibVal * (int16_t)autoVibAmp) >> (6+8); - tmpPeriod += ch->outPeriod; - if (tmpPeriod > MAX_FRQ-1) - tmpPeriod = 0; // yes, FT2 does this (!) + uint16_t tmpPeriod = ch->outPeriod + autoVibVal; + if (tmpPeriod >= 32000) // unsigned comparison + tmpPeriod = 0; #ifdef HAS_MIDI if (midi.enable) @@ -1787,8 +1785,8 @@ static void portaDown(channel_t *ch, uint8_t param) ch->portaDownSpeed = param; ch->realPeriod += param << 2; - if ((int16_t)ch->realPeriod > MAX_FRQ-1) // FT2 bug, should've been unsigned comparison - ch->realPeriod = MAX_FRQ-1; + if ((int16_t)ch->realPeriod >= 32000) // FT2 bug, should've been unsigned comparison + ch->realPeriod = 32000-1; ch->outPeriod = ch->realPeriod; ch->status |= IS_Period; @@ -2590,10 +2588,10 @@ void setStdEnvelope(instr_t *ins, int16_t i, uint8_t type) ins->volEnvLoopStart = (uint8_t)config.stdVolEnvLoopStart[i]; ins->volEnvLoopEnd = (uint8_t)config.stdVolEnvLoopEnd[i]; ins->fadeout = config.stdFadeout[i]; - ins->vibRate = (uint8_t)config.stdVibRate[i]; - ins->vibDepth = (uint8_t)config.stdVibDepth[i]; - ins->vibSweep = (uint8_t)config.stdVibSweep[i]; - ins->vibType = (uint8_t)config.stdVibType[i]; + ins->autoVibRate = (uint8_t)config.stdVibRate[i]; + ins->autoVibDepth = (uint8_t)config.stdVibDepth[i]; + ins->autoVibSweep = (uint8_t)config.stdVibSweep[i]; + ins->autoVibType = (uint8_t)config.stdVibType[i]; ins->volEnvFlags = (uint8_t)config.stdVolEnvFlags[i]; } @@ -2632,10 +2630,10 @@ void setNoEnvelope(instr_t *ins) ins->panEnvFlags = 0; ins->fadeout = 0; - ins->vibRate = 0; - ins->vibDepth = 0; - ins->vibSweep = 0; - ins->vibType = 0; + ins->autoVibRate = 0; + ins->autoVibDepth = 0; + ins->autoVibSweep = 0; + ins->autoVibType = 0; resumeMusic(); } @@ -2857,8 +2855,8 @@ void startPlaying(int8_t mode, int16_t row) if (song.speed == 0) song.speed = song.initialSpeed; - audio.tickSampleCounter = 0; // zero tick sample counter so that it will instantly initiate a tick - audio.tickSampleCounterFrac = 0; + // zero tick sample counter so that it will instantly initiate a tick + audio.tickSampleCounterFrac = audio.tickSampleCounter = 0; unlockMixerCallback(); @@ -3104,7 +3102,7 @@ void stopVoices(void) ch->realVol = 0; ch->outVol = 0; ch->oldVol = 0; - ch->fFinalVol = 0.0f; + ch->dFinalVol = 0.0; ch->oldPan = 128; ch->outPan = 128; ch->finalPan = 128; diff --git a/src/ft2_replayer.h b/src/ft2_replayer.h @@ -44,7 +44,6 @@ enum #define MAX_SPEED 31 #define MAX_CHANNELS 32 #define TRACK_WIDTH (5 * MAX_CHANNELS) -#define MAX_FRQ 32000 #define C4_FREQ 8363 #define NOTE_C4 (4*12) #define NOTE_OFF 97 @@ -232,7 +231,7 @@ typedef struct instr_t uint8_t volEnvSustain, volEnvLoopStart, volEnvLoopEnd; uint8_t panEnvSustain, panEnvLoopStart, panEnvLoopEnd; uint8_t volEnvFlags, panEnvFlags; - uint8_t vibType, vibSweep, vibDepth, vibRate; + uint8_t autoVibType, autoVibSweep, autoVibDepth, autoVibRate; uint16_t fadeout; int16_t volEnvPoints[12][2], panEnvPoints[12][2], midiProgram, midiBend; int16_t numSamples; // used by loader only @@ -241,7 +240,7 @@ typedef struct instr_t typedef struct channel_t { - bool envSustainActive, channelOff, mute; + bool keyOff, channelOff, mute; volatile uint8_t status, tmpStatus; int8_t relativeNote, finetune; uint8_t smpNum, instrNum, efxData, efx, smpOffset, tremorSave, tremorPos; @@ -250,16 +249,17 @@ typedef struct channel_t uint8_t jumpToRow, patLoopCounter, volSlideSpeed, fVolSlideUpSpeed, fVolSlideDownSpeed; uint8_t fPortaUpSpeed, fPortaDownSpeed, ePortaUpSpeed, ePortaDownSpeed; uint8_t portaUpSpeed, portaDownSpeed, retrigSpeed, retrigCnt, retrigVol; - uint8_t volColumnVol, noteNum, panEnvPos, eVibPos, volEnvPos, realVol, oldVol, outVol; + uint8_t volColumnVol, noteNum, panEnvPos, autoVibPos, volEnvPos, realVol, oldVol, outVol; uint8_t oldPan, outPan, finalPan; int16_t midiPitch; uint16_t outPeriod, realPeriod, finalPeriod, noteData, wantPeriod, portaSpeed; - uint16_t volEnvTick, panEnvTick, eVibAmp, eVibSweep; - uint16_t fadeoutVol, fadeoutSpeed, midiVibDepth; + uint16_t volEnvTick, panEnvTick, autoVibAmp, autoVibSweep; + uint16_t midiVibDepth; + int32_t fadeoutVol, fadeoutSpeed; int32_t volEnvDelta, panEnvDelta, volEnvValue, panEnvValue; int32_t oldFinalPeriod, smpStartPos; - float fFinalVol; // 0.0f .. 1.0f + double dFinalVol; // 0.0 .. 1.0 sample_t *smpPtr; instr_t *instrPtr; diff --git a/src/ft2_sample_saver.c b/src/ft2_sample_saver.c @@ -421,10 +421,10 @@ static bool saveWAVSample(UNICHAR *filenameU, bool saveRangedData) mptExtraChunk.defaultPan = smp->panning; // 0..255 mptExtraChunk.defaultVolume = smp->volume * 4; // 0..256 mptExtraChunk.globalVolume = 64; // 0..64 - mptExtraChunk.vibratoType = ins->vibType; // 0..3 0 = sine, 1 = square, 2 = ramp up, 3 = ramp down - mptExtraChunk.vibratoSweep = ins->vibSweep; // 0..255 - mptExtraChunk.vibratoDepth = ins->vibDepth; // 0..15 - mptExtraChunk.vibratoRate= ins->vibRate; // 0..63 + mptExtraChunk.vibratoType = ins->autoVibType; // 0..3 0 = sine, 1 = square, 2 = ramp up, 3 = ramp down + mptExtraChunk.vibratoSweep = ins->autoVibSweep; // 0..255 + mptExtraChunk.vibratoDepth = ins->autoVibDepth; // 0..15 + mptExtraChunk.vibratoRate = ins->autoVibRate; // 0..63 fwrite(&mptExtraChunk, sizeof (mptExtraChunk), 1, f); if (mptExtraChunk.chunkSize & 1) diff --git a/src/ft2_tables.c b/src/ft2_tables.c @@ -41,7 +41,7 @@ const uint8_t arpTab[256] = 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x4F,0x52,0x4D,0x49,0x4C,0x42,0x4D,0x42,0x4D }; -const int8_t vibSineTab[256] = // for auto-vibrato +const int8_t autoVibSineTab[256] = { 0, -2, -3, -5, -6, -8, -9, -11, -12, -14, -16, -17, -19, -20, -22, -23, -24, -26, -27, -29, -30, -32, -33, -34, -36, -37, -38, -39, -41, -42, -43, -44, diff --git a/src/ft2_tables.h b/src/ft2_tables.h @@ -13,7 +13,7 @@ extern const uint16_t ptPeriods[3 * 12]; extern const uint8_t arpTab[256]; -extern const int8_t vibSineTab[256]; // for auto-vibrato +extern const int8_t autoVibSineTab[256]; extern const uint8_t vibTab[32]; extern const uint16_t amigaPeriod[8 * 12]; extern const uint16_t linearPeriods[1936]; diff --git a/src/ft2_video.c b/src/ft2_video.c @@ -121,9 +121,9 @@ static void drawFPSCounter(void) "Frames per second: %.3f\n" \ "Monitor refresh rate: %.1fHz (+/-)\n" \ "59..61Hz GPU VSync used: %s\n" \ + "HPC frequency (timer): %.4fMHz\n" \ "Audio frequency: %.1fkHz (expected %.1fkHz)\n" \ "Audio buffer samples: %d (expected %d)\n" \ - "Audio channels: %d (expected %d)\n" \ "Audio latency: %.1fms (expected %.1fms)\n" \ "Render size: %dx%d (offset %d,%d)\n" \ "Disp. size: %dx%d (window: %dx%d)\n" \ @@ -136,9 +136,9 @@ static void drawFPSCounter(void) dAvgFPS, dRefreshRate, video.vsync60HzPresent ? "yes" : "no", - audio.haveFreq * (1.0 / 1000.0), audio.wantFreq * (1.0 / 1000.0), + hpcFreq.freq64 / (1000.0 * 1000.0), + audio.haveFreq / 1000.0, audio.wantFreq / 1000.0, audio.haveSamples, audio.wantSamples, - audio.haveChannels, audio.wantChannels, dAudLatency, ((audio.wantSamples * 1000.0) / audio.wantFreq), video.renderW, video.renderH, video.renderX, video.renderY, video.displayW, video.displayH, video.windowW, video.windowH, diff --git a/src/mixer/ft2_mix.h b/src/mixer/ft2_mix.h @@ -3,6 +3,7 @@ #include <stdint.h> #include "../ft2_cpu.h" +// the fractional bits are hardcoded, changing these will break things! #if CPU_64BIT #define MIXER_FRAC_BITS 32 #else diff --git a/src/modloaders/ft2_load_xm.c b/src/modloaders/ft2_load_xm.c @@ -251,10 +251,10 @@ static bool loadInstrHeader(FILE *f, uint16_t i) ins->panEnvLoopEnd = ih.panEnvLoopEnd; ins->volEnvFlags = ih.volEnvFlags; ins->panEnvFlags = ih.panEnvFlags; - ins->vibType = ih.vibType; - ins->vibSweep = ih.vibSweep; - ins->vibDepth = ih.vibDepth; - ins->vibRate = ih.vibRate; + ins->autoVibType = ih.vibType; + ins->autoVibSweep = ih.vibSweep; + ins->autoVibDepth = ih.vibDepth; + ins->autoVibRate = ih.vibRate; ins->fadeout = ih.fadeout; ins->midiOn = (ih.midiOn == 1) ? true : false; ins->midiChannel = ih.midiChannel; diff --git a/src/scopes/ft2_scopes.c b/src/scopes/ft2_scopes.c @@ -78,13 +78,13 @@ static void setChannel(int32_t chNr, bool on) ch->realVol = 0; ch->outVol = 0; ch->oldVol = 0; - ch->fFinalVol = 0.0f; + ch->dFinalVol = 0.0; ch->outPan = 128; ch->oldPan = 128; ch->finalPan = 128; ch->status = IS_Vol; - ch->envSustainActive = false; // non-FT2 bug fix for stuck piano keys + ch->keyOff = true; // non-FT2 bug fix for stuck piano keys } scope[chNr].wasCleared = false;