ref: 824199e016e6ad8747489995fb518d43726ee8d7
parent: 4a95aceff6b745d0dcfc13185c16e682267f7316
author: Olav Sørensen <[email protected]>
date: Fri Mar 24 13:17:45 EDT 2023
Code cleanup + voice volume precision change
--- 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 @@
dAmp *= 32768.0;
dAudioNormalizeMul = dAmp;
- fAudioNormalizeMul = (float)dAmp;
}
void decreaseMasterVol(void)
@@ -206,9 +200,9 @@
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)
@@ -215,8 +209,8 @@
{
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,29 +238,23 @@
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
{
@@ -273,18 +261,12 @@
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 @@
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 @@
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,94 +448,30 @@
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;
+ double dOut;
+ float *fStreamPointer32 = (float *)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
+ // left channel
dOut = (double)audio.fMixBufferL[i] * dAudioNormalizeMul;
- dOut = (dOut + dPrng) - dPrngStateL;
- dPrngStateL = dPrng;
- out32 = (int32_t)dOut;
- CLAMP16(out32);
- *streamPointer16++ = (int16_t)out32;
+ dOut = CLAMP(dOut, -1.0, 1.0);
+ *fStreamPointer32++ = (float)dOut;
- // right channel - 1-bit triangular dithering
- dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5
+ // right channel
dOut = (double)audio.fMixBufferR[i] * dAudioNormalizeMul;
- dOut = (dOut + dPrng) - dPrngStateR;
- dPrngStateR = dPrng;
- out32 = (int32_t)dOut;
- CLAMP16(out32);
- *streamPointer16++ = (int16_t)out32;
+ 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++)
- *streamPointer16++ = 0;
}
}
-static void sendSamples32BitStereo(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;
-
- // 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;
-
- // 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;
-
- // send zeroes to the rest of the channels
- for (uint32_t j = 2; j < numAudioChannels; j++)
- *fStreamPointer32++ = 0.0f;
- }
-}
-
static void doChannelMixing(int32_t bufferPosition, int32_t samplesToMix)
{
voice_t *v = voice; // normal voices
@@ -598,9 +517,9 @@
// 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 @@
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 @@
if (editor.wavIsRendering)
return;
- len /= pmpCountDiv; // bytes -> samples
+ len >>= smpShiftValue; // bytes -> samples
if (len <= 0)
return;
@@ -972,8 +891,10 @@
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 @@
}
}
-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 @@
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 @@
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,19 +1052,11 @@
audio.haveFreq = have.freq;
audio.haveSamples = have.samples;
- audio.haveChannels = have.channels;
+ config.audioFreq = audio.freq = have.freq;
- // set a few variables
-
- config.audioFreq = have.freq;
- audio.freq = have.freq;
- smpBuffSize = have.samples;
-
calcAudioLatencyVars(have.samples, have.freq);
+ smpShiftValue = (newBitDepth == 16) ? 2 : 3;
- pmpChannels = have.channels;
- pmpCountDiv = pmpChannels * ((newBitDepth == 16) ? sizeof (int16_t) : sizeof (float));
-
// make a copy of the new known working audio settings
audio.lastWorkingAudioFreq = config.audioFreq;
@@ -1183,8 +1076,8 @@
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 @@
setMixerBPM(song.BPM); // this is important
- updateSendAudSamplesRoutine(false);
audio.resetSyncTickTimeFlag = true;
-
return true;
}
--- a/src/ft2_audio.h
+++ b/src/ft2_audio.h
@@ -59,7 +59,7 @@
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 @@
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 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);
--- 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...
--- a/src/ft2_inst_ed.c
+++ b/src/ft2_inst_ed.c
@@ -131,9 +131,9 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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];
--- a/src/ft2_module_saver.c
+++ b/src/ft2_module_saver.c
@@ -187,10 +187,10 @@
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 @@
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;
--- a/src/ft2_replayer.c
+++ b/src/ft2_replayer.c
@@ -335,8 +335,6 @@
ch->retrigCnt = 0;
ch->tremorPos = 0;
- ch->envSustainActive = true;
-
instr_t *ins = ch->instrPtr;
assert(ins != NULL);
@@ -352,22 +350,22 @@
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;
}
}
}
@@ -374,7 +372,7 @@
void keyOff(channel_t *ch)
{
- ch->envSustainActive = false;
+ ch->keyOff = true;
instr_t *ins = ch->instrPtr;
assert(ins != NULL);
@@ -571,8 +569,8 @@
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 @@
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,29 +1375,26 @@
{
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;
+ if (ch->fadeoutVol <= 0)
+ {
+ ch->fadeoutVol = 0;
+ ch->fadeoutSpeed = 0;
+ }
}
- else
- {
- ch->fadeoutVol = 0;
- ch->fadeoutSpeed = 0;
- }
}
if (!ch->mute)
@@ -1424,7 +1419,7 @@
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 @@
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,8 +1483,8 @@
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
}
@@ -1496,17 +1491,18 @@
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 @@
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 @@
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 @@
// *** 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 @@
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 @@
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 @@
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 @@
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 @@
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;
--- a/src/ft2_replayer.h
+++ b/src/ft2_replayer.h
@@ -44,7 +44,6 @@
#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 @@
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 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 @@
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;
--- a/src/ft2_sample_saver.c
+++ b/src/ft2_sample_saver.c
@@ -421,10 +421,10 @@
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)
--- a/src/ft2_tables.c
+++ b/src/ft2_tables.c
@@ -41,7 +41,7 @@
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,
--- 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];
--- a/src/ft2_video.c
+++ b/src/ft2_video.c
@@ -121,9 +121,9 @@
"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 @@
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,
--- 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
--- a/src/modloaders/ft2_load_xm.c
+++ b/src/modloaders/ft2_load_xm.c
@@ -251,10 +251,10 @@
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;
--- a/src/scopes/ft2_scopes.c
+++ b/src/scopes/ft2_scopes.c
@@ -78,13 +78,13 @@
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;