ref: c1ad6de18c3cda9591fd4f881575d6088a0d9057
dir: /src/ft2_replayer.h/
#pragma once #include <stdint.h> #include <stdbool.h> #include "ft2_unicode.h" #include "mixer/ft2_windowed_sinc.h" #include "ft2_cpu.h" enum { // voice flags IS_Vol = 1, // set volume IS_Period = 2, // set resampling rate IS_Trigger = 4, // trigger sample IS_Pan = 8, // set panning IS_QuickVol = 16, // 5ms volramp instead of tick ms LOOP_DISABLED = 0, LOOP_FORWARD = 1, LOOP_PINGPONG = 2, // tracker playback modes PLAYMODE_IDLE = 0, PLAYMODE_EDIT = 1, PLAYMODE_SONG = 2, PLAYMODE_PATT = 3, PLAYMODE_RECSONG = 4, PLAYMODE_RECPATT = 5, // note cursor positions CURSOR_NOTE = 0, CURSOR_INST1 = 1, CURSOR_INST2 = 2, CURSOR_VOL1 = 3, CURSOR_VOL2 = 4, CURSOR_EFX0 = 5, CURSOR_EFX1 = 6, CURSOR_EFX2 = 7 }; // do not touch these! #define MIN_BPM 32 #define MAX_BPM 255 #define MAX_SPEED 31 #define MAX_CHANNELS 32 #define TRACK_WIDTH (5 * MAX_CHANNELS) #define C4_FREQ 8363 #define NOTE_C4 (4*12) #define NOTE_OFF 97 #define MAX_NOTES (10*12*16+16) #define MAX_PATTERNS 256 #define MAX_PATT_LEN 256 #define MAX_INST 128 #define MAX_SMP_PER_INST 16 #define MAX_ORDERS 256 #define STD_ENV_SIZE ((6*2*12*2*2) + (6*8*2) + (6*5*2) + (6*2*2)) #define INSTR_HEADER_SIZE 263 #define INSTR_XI_HEADER_SIZE 298 #define MAX_SAMPLE_LEN 0x3FFFFFFF #define FT2_QUICKRAMP_SAMPLES 200 #define PROG_NAME_STR "Fasttracker II clone" enum // sample flags { LOOP_OFF = 0, LOOP_FWD = 1, LOOP_BIDI = 2, SAMPLE_16BIT = 16, SAMPLE_STEREO = 32, SAMPLE_ADPCM = 64, // not an existing flag, but used by loader }; enum // envelope flags { ENV_ENABLED = 1, ENV_SUSTAIN = 2, ENV_LOOP = 4 }; #define GET_LOOPTYPE(smpFlags) ((smpFlags) & (LOOP_FWD | LOOP_BIDI)) #define DISABLE_LOOP(smpFlags) ((smpFlags) &= ~(LOOP_FWD | LOOP_BIDI)) #define SAMPLE_LENGTH_BYTES(smp) (smp->length << !!(smp->flags & SAMPLE_16BIT)) #define FINETUNE_MOD2XM(f) (((uint8_t)(f) & 0x0F) << 4) #define FINETUNE_XM2MOD(f) ((uint8_t)(f) >> 4) /* Some of the following structs MUST be packed! ** Please do NOT edit these structs unless you ** absolutely know what you are doing! */ #ifdef _MSC_VER #pragma pack(push) #pragma pack(1) #endif typedef struct xmHdr_t { char ID[17], name[20], x1A, progName[20]; uint16_t version; int32_t headerSize; uint16_t numOrders, songLoopStart, numChannels, numPatterns; uint16_t numInstr, flags, speed, BPM; uint8_t orders[256]; } #ifdef __GNUC__ __attribute__ ((packed)) #endif xmHdr_t; typedef struct xmPatHdr_t { int32_t headerSize; uint8_t type; int16_t numRows; uint16_t dataSize; } #ifdef __GNUC__ __attribute__ ((packed)) #endif xmPatHdr_t; typedef struct modSmpHdr_t { char name[22]; uint16_t length; uint8_t finetune, volume; uint16_t loopStart, loopLength; } #ifdef __GNUC__ __attribute__ ((packed)) #endif modSmpHdr_t; typedef struct modHdr_t { char name[20]; modSmpHdr_t smp[31]; uint8_t numOrders, songLoopStart, orders[128]; char ID[4]; } #ifdef __GNUC__ __attribute__ ((packed)) #endif modHdr_t; typedef struct xmSmpHdr_t { uint32_t length, loopStart, loopLength; uint8_t volume; int8_t finetune; uint8_t flags, panning; int8_t relativeNote; uint8_t nameLength; // only handled before saving (ignored under load) char name[22]; } #ifdef __GNUC__ __attribute__ ((packed)) #endif xmSmpHdr_t; typedef struct xmInsHdr_t { uint32_t instrSize; char name[22]; uint8_t type; int16_t numSamples; int32_t sampleSize; uint8_t note2SampleLUT[96]; int16_t volEnvPoints[12][2], panEnvPoints[12][2]; uint8_t volEnvLength, panEnvLength; uint8_t volEnvSustain, volEnvLoopStart, volEnvLoopEnd; uint8_t panEnvSustain, panEnvLoopStart, panEnvLoopEnd; uint8_t volEnvFlags, panEnvFlags; uint8_t vibType, vibSweep, vibDepth, vibRate; uint16_t fadeout; uint8_t midiOn, midiChannel; int16_t midiProgram, midiBend; int8_t mute; uint8_t junk[15]; xmSmpHdr_t smp[16]; } #ifdef __GNUC__ __attribute__ ((packed)) #endif xmInsHdr_t; typedef struct pattNote_t // must be packed! { uint8_t note, instr, vol, efx, efxData; } #ifdef __GNUC__ __attribute__ ((packed)) #endif note_t; typedef struct syncedChannel_t // used for audio/video sync queue (pack to save RAM) { uint8_t status, pianoNoteNum, smpNum, instrNum; int32_t smpStartPos; uint8_t scopeVolume; uintCPUWord_t scopeDelta; } #ifdef __GNUC__ __attribute__ ((packed)) #endif syncedChannel_t; #ifdef _MSC_VER #pragma pack(pop) #endif typedef struct sample_t { char name[22+1]; bool isFixed; int8_t finetune, relativeNote, *dataPtr, *origDataPtr; uint8_t volume, flags, panning; int32_t length, loopStart, loopLength; // fix for resampling interpolation taps int8_t leftEdgeTapSamples8[SINC_TAPS+SINC_LEFT_TAPS]; int16_t leftEdgeTapSamples16[SINC_TAPS+SINC_LEFT_TAPS]; int16_t fixedSmp[SINC_RIGHT_TAPS]; int32_t fixedPos; } sample_t; typedef struct instr_t { bool midiOn, mute; uint8_t midiChannel, note2SampleLUT[96]; uint8_t volEnvLength, panEnvLength; uint8_t volEnvSustain, volEnvLoopStart, volEnvLoopEnd; uint8_t panEnvSustain, panEnvLoopStart, panEnvLoopEnd; uint8_t volEnvFlags, panEnvFlags; 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 sample_t smp[16]; } instr_t; typedef struct channel_t { bool keyOff, channelOff, mute; volatile uint8_t status, tmpStatus; int8_t relativeNote, finetune; uint8_t smpNum, instrNum, efxData, efx, smpOffset, tremorSave, tremorPos; uint8_t globVolSlideSpeed, panningSlideSpeed, waveCtrl, portaDirection; uint8_t glissFunk, vibPos, tremPos, vibSpeed, vibDepth, tremSpeed, tremDepth; 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, 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, autoVibAmp, autoVibSweep; uint16_t midiVibDepth; int32_t fadeoutVol, fadeoutSpeed; int32_t volEnvDelta, panEnvDelta, volEnvValue, panEnvValue; int32_t oldFinalPeriod, smpStartPos; double dFinalVol; // 0.0 .. 1.0 sample_t *smpPtr; instr_t *instrPtr; } channel_t; typedef struct song_t { bool pBreakFlag, posJumpFlag, isModified; char name[20+1], instrName[1+MAX_INST][22+1]; uint8_t curReplayerTick, curReplayerRow, curReplayerSongPos, curReplayerPattNum; // used for audio/video sync queue uint8_t pattDelTime, pattDelTime2, pBreakPos, orders[MAX_ORDERS]; int16_t songPos, pattNum, row, currNumRows; uint16_t songLength, songLoopStart, BPM, speed, initialSpeed, globalVolume, tick; int32_t numChannels; uint32_t playbackSeconds; uint64_t playbackSecondsFrac; } song_t; double getSampleC4Rate(sample_t *s); void setNewSongPos(int32_t pos); void resetReplayerState(void); void fixString(char *str, int32_t lastChrPos); // removes leading spaces and 0x1A chars void fixSongName(void); void fixInstrAndSampleNames(int16_t insNum); void calcReplayerVars(int32_t rate); // used on external sample load and during sample loading in some module formats void tuneSample(sample_t *s, const int32_t midCFreq, bool linearPeriodsFlag); void calcReplayerLogTab(void); // for linear period -> hz calculation double dLinearPeriod2Hz(int32_t period); double dAmigaPeriod2Hz(int32_t period); double dPeriod2Hz(int32_t period); int32_t getPianoKey(uint16_t period, int8_t finetune, int8_t relativeNote); // for piano in Instr. Ed. bool allocateInstr(int16_t insNum); void freeInstr(int32_t insNum); void freeAllInstr(void); void freeSample(int16_t insNum, int16_t smpNum); void freeAllPatterns(void); void updateChanNums(void); bool setupReplayer(void); void closeReplayer(void); void resetMusic(void); void startPlaying(int8_t mode, int16_t row); void stopPlaying(void); void stopVoices(void); void setPos(int16_t songPos, int16_t row, bool resetTimer); void pauseMusic(void); // stops reading pattern data void resumeMusic(void); // starts reading pattern data void setSongModifiedFlag(void); void removeSongModifiedFlag(void); void playTone(uint8_t chNum, uint8_t insNum, uint8_t note, int8_t vol, uint16_t midiVibDepth, uint16_t midiPitch); void playSample(uint8_t chNum, uint8_t insNum, uint8_t smpNum, uint8_t note, uint16_t midiVibDepth, uint16_t midiPitch); void playRange(uint8_t chNum, uint8_t insNum, uint8_t smpNum, uint8_t note, uint16_t midiVibDepth, uint16_t midiPitch, int32_t smpOffset, int32_t length); void keyOff(channel_t *ch); void conv8BitSample(int8_t *p, int32_t length, bool stereo); // changes sample sign void conv16BitSample(int8_t *p, int32_t length, bool stereo); // changes sample sign void delta2Samp(int8_t *p, int32_t length, uint8_t smpFlags); void samp2Delta(int8_t *p, int32_t length, uint8_t smpFlags); void setPatternLen(uint16_t pattNum, int16_t numRows); void setFrequencyTable(bool linearPeriodsFlag); void tickReplayer(void); // periodically called from audio callback void resetChannels(void); bool patternEmpty(uint16_t pattNum); int16_t getUsedSamples(int16_t smpNum); int16_t getRealUsedSamples(int16_t smpNum); void setStdEnvelope(instr_t *ins, int16_t i, uint8_t type); void setNoEnvelope(instr_t *ins); void setSyncedReplayerVars(void); void decSongPos(void); void incSongPos(void); void decCurIns(void); void incCurIns(void); void decCurSmp(void); void incCurSmp(void); void pbPlaySong(void); void pbPlayPtn(void); void pbRecSng(void); void pbRecPtn(void); // ft2_replayer.c extern int8_t playMode; extern bool songPlaying, audioPaused, musicPaused; extern volatile bool replayerBusy; extern const uint16_t *note2Period; extern int16_t patternNumRows[MAX_PATTERNS]; extern channel_t channel[MAX_CHANNELS]; extern song_t song; extern instr_t *instr[128+4]; extern note_t *pattern[MAX_PATTERNS];