?? modeng.c
字號:
/* * $Id: modeng.c 1.11 1996/09/13 15:10:01 chasan released $ * * Extended module player engine. * * Copyright (C) 1995-1999 Carlos Hasan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */#ifdef __GNUC__#include <memory.h>#endif#include <string.h>#include <malloc.h>#include "audio.h"#include "tables.h"/* * Module player state control bit fields */#define AUDIO_PLAYER_JUMP 0x01#define AUDIO_PLAYER_BREAK 0x02#define AUDIO_PLAYER_DELAY 0x04#define AUDIO_PLAYER_BPM 0x08#define AUDIO_PLAYER_VOLUME 0x10#define AUDIO_PLAYER_PAUSE 0x20#define AUDIO_PLAYER_ACTIVE 0x80/* * Tracks control bit fields */#define AUDIO_CTRL_PITCH 0x01#define AUDIO_CTRL_VOLUME 0x02#define AUDIO_CTRL_PANNING 0x04#define AUDIO_CTRL_KEYON 0x08#define AUDIO_CTRL_KEYOFF 0x10#define AUDIO_CTRL_TOUCH 0x20/* * Some useful macro defines */#define LOPARAM(x) ((BYTE)(x)&0x0F)#define HIPARAM(x) ((BYTE)(x)>>4)#define CLIP(x,a,b) ((x)<(a)?(a):((x)>(b)?(b):(x)))#define ABS(x) ((x)>0?(x):-(x))/* * Module player track structure */typedef struct { BYTE nNote; /* note index (1-96) */ BYTE nPatch; /* patch number (1-128) */ BYTE nVolume; /* volume command */ BYTE nCommand; /* effect */ BYTE bParams; /* parameters */} NOTE, *LPNOTE;typedef struct { BYTE fKeyOn; /* key on flag */ BYTE bControl; /* control bits */ BYTE nVolumeCmd; /* volume command */ BYTE nCommand; /* command */ BYTE bParams; /* parameters */ BYTE nPatch; /* patch number */ BYTE nSample; /* sample number */ BYTE nNote; /* current note */ int nFinetune; /* current finetune */ int nRelativeNote; /* relative note */ int nVolume; /* current volume */ int nOutVolume; /* output volume */ int nFinalVolume; /* final volume */ int nPanning; /* current panning */ int nFinalPanning; /* final panning */ int nPeriod; /* current period */ int nOutPeriod; /* output period */ int nFinalPeriod; /* final period */ LONG dwFrequency; /* frequency */ LPAUDIOPATCH lpPatch; /* current patch */ LPAUDIOSAMPLE lpSample; /* current sample */ /* waves & gliss control */ BYTE bWaveCtrl; /* vibrato & tremolo control bits */ BYTE bGlissCtrl; /* glissando control bits */ /* vibrato & tremolo waves */ int nVibratoFrame; /* vibrato frame */ int nVibratoDepth; /* vibrato depth */ int nVibratoRate; /* vibrato rate */ int nTremoloFrame; /* tremolo frame */ int nTremoloDepth; /* tremolo depth */ int nTremoloRate; /* tremolo rate */ /* command parameters */ int nPortaUp; /* portamento up rate */ int nPortaDown; /* portamento down rate */ int nTonePorta; /* tone portamento rate */ int nWantedPeriod; /* tone portamento target */ BYTE bVolumeSlide; /* volume slide rate */ BYTE bPanningSlide; /* panning slide rate */ BYTE nFinePortaUp; /* fine portamento up rate */ BYTE nFinePortaDown; /* fine portamento down rate */ BYTE nExtraPortaUp; /* extra fine porta up rate */ BYTE nExtraPortaDown; /* extra fine porta down rate */ BYTE nRetrigType; /* multi retrig type */ BYTE nRetrigInterval; /* multi retrig interval */ BYTE nRetrigFrame; /* multi retrig frame */ BYTE bTremorParms; /* tremor parameters */ BYTE bTremorOnOff; /* tremor on/off state */ BYTE nTremorFrame; /* tremor frame */ LONG dwSampleOffset; /* last sample offset */ /* volume fadeout */ int nVolumeFade; /* volume fadeout level */ int nVolumeFadeout; /* volume fadeout rate */ /* volume envelope */ int nVolumeFrame; /* volume envelope frame */ int nVolumeValue; /* volume envelope value */ int nVolumePoint; /* volume envelope point index */ int nVolumeSlope; /* volume envelope slope */ /* panning envelope */ int nPanningFrame; /* panning envelope frame */ int nPanningValue; /* panning envelope value */ int nPanningPoint; /* panning envelope point index */ int nPanningSlope; /* panning envelope slope */ /* automatic vibrato */ int nAutoVibratoFrame; /* auto vibrato frame */ int nAutoVibratoValue; /* auto vibrato envelope */ int nAutoVibratoSlope; /* auto vibrato slope */ /* pattern loop variables */ int nPatternRow; /* pattern loop row */ int nPatternLoop; /* pattern loop counter */} TRACK, *LPTRACK;/* * Module player run-time state structure */static struct { LPAUDIOMODULE lpModule; /* current module */ LPBYTE lpData; /* pattern data pointer */ TRACK aTracks[32]; /* array of tracks */ HAC aVoices[32]; /* array of voices */ WORD wControl; /* player control bits */ WORD wFlags; /* module control bits */ int nTracks; /* number of channels */ int nFrame; /* current frame */ int nRow; /* pattern row */ int nRows; /* number of rows */ int nPattern; /* pattern number */ int nOrder; /* order number */ int nTempo; /* current tempo */ int nBPM; /* current BPM */ int nVolume; /* global volume */ int nVolumeRate; /* global volume slide */ int nJumpOrder; /* position jump */ int nJumpRow; /* break pattern */ int nPatternDelay; /* pattern delay counter */ LPFNAUDIOCALLBACK lpfnCallback; /* sync callback routine */} Player;static VOID PlayNote(LPTRACK lpTrack);static VOID StopNote(LPTRACK lpTrack);static VOID RetrigNote(LPTRACK lpTrack);/* * Low-level extended module player routines */static LONG GetFrequencyValue(int nPeriod){ UINT nNote, nOctave; if (nPeriod > 0) { if (Player.wFlags & AUDIO_MODULE_LINEAR) { nOctave = nPeriod / (12 * 16 * 4); nNote = nPeriod % (12 * 16 * 4); return aFrequencyTable[nNote] >> nOctave; } else { return (4L * 8363L * 428L) / nPeriod; } } return 0L;}static int GetPeriodValue(int nNote, int nRelativeNote, int nFinetune){ int nOctave; nNote = ((nNote + nRelativeNote - 1) << 6) + (nFinetune >> 1); if (nNote >= 0 && nNote < 10 * 12 * 16 * 4) { if (Player.wFlags & AUDIO_MODULE_LINEAR) { return (10 * 12 * 16 * 4 - nNote); } else { nOctave = nNote / (12 * 16 * 4); nNote = nNote % (12 * 16 * 4); return aPeriodTable[nNote >> 2] >> nOctave; } } return 0;}static VOID OnArpeggio(LPTRACK lpTrack){ int nNote; if (lpTrack->bParams) { nNote = lpTrack->nNote; switch (Player.nFrame % 3) { case 1: nNote += HIPARAM(lpTrack->bParams); break; case 2: nNote += LOPARAM(lpTrack->bParams); break; } lpTrack->nOutPeriod = GetPeriodValue(nNote, lpTrack->nRelativeNote, lpTrack->nFinetune); lpTrack->bControl |= AUDIO_CTRL_PITCH; }}static VOID OnPortaUp(LPTRACK lpTrack){ if (!Player.nFrame) { if (lpTrack->bParams != 0x00) { lpTrack->nPortaUp = (int) lpTrack->bParams << 2; } } else { lpTrack->nPeriod -= lpTrack->nPortaUp; if (lpTrack->nPeriod < AUDIO_MIN_PERIOD) lpTrack->nPeriod = AUDIO_MIN_PERIOD; lpTrack->nOutPeriod = lpTrack->nPeriod; lpTrack->bControl |= AUDIO_CTRL_PITCH; }}static VOID OnPortaDown(LPTRACK lpTrack){ if (!Player.nFrame) { if (lpTrack->bParams != 0x00) { lpTrack->nPortaDown = (int) lpTrack->bParams << 2; } } else { lpTrack->nPeriod += lpTrack->nPortaDown; if (lpTrack->nPeriod > AUDIO_MAX_PERIOD) lpTrack->nPeriod = AUDIO_MAX_PERIOD; lpTrack->nOutPeriod = lpTrack->nPeriod; lpTrack->bControl |= AUDIO_CTRL_PITCH; }}static VOID OnTonePorta(LPTRACK lpTrack){ if (!Player.nFrame) { if (lpTrack->bParams != 0x00) { lpTrack->nTonePorta = (int) lpTrack->bParams << 2; } lpTrack->nWantedPeriod = GetPeriodValue(lpTrack->nNote, lpTrack->nRelativeNote, lpTrack->nFinetune); lpTrack->bControl &= ~(AUDIO_CTRL_PITCH | AUDIO_CTRL_KEYON); } else { if (lpTrack->nPeriod < lpTrack->nWantedPeriod) { lpTrack->nPeriod += lpTrack->nTonePorta; if (lpTrack->nPeriod > lpTrack->nWantedPeriod) { lpTrack->nPeriod = lpTrack->nWantedPeriod; } } else if (lpTrack->nPeriod > lpTrack->nWantedPeriod) { lpTrack->nPeriod -= lpTrack->nTonePorta; if (lpTrack->nPeriod < lpTrack->nWantedPeriod) { lpTrack->nPeriod = lpTrack->nWantedPeriod; } } /* TODO: glissando not implemented */ lpTrack->nOutPeriod = lpTrack->nPeriod; lpTrack->bControl |= AUDIO_CTRL_PITCH; }}static VOID OnVibrato(LPTRACK lpTrack){ int nDelta, nFrame; if (!Player.nFrame) { if (LOPARAM(lpTrack->bParams)) { lpTrack->nVibratoDepth = LOPARAM(lpTrack->bParams); } if (HIPARAM(lpTrack->bParams)) { lpTrack->nVibratoRate = HIPARAM(lpTrack->bParams) << 2; } } else { nFrame = (lpTrack->nVibratoFrame >> 2) & 0x1F; switch (lpTrack->bWaveCtrl & 0x03) { case 0x00: nDelta = aSineTable[nFrame]; break; case 0x01: nDelta = nFrame << 3; if (lpTrack->nVibratoFrame & 0x80) nDelta ^= 0xFF; break; case 0x02: nDelta = 0xFF; break; default: /* TODO: random waveform not implemented */ nDelta = 0x00; break; } nDelta = ((nDelta * lpTrack->nVibratoDepth) >> 5); lpTrack->nOutPeriod = lpTrack->nPeriod; if (lpTrack->nVibratoFrame & 0x80) { lpTrack->nOutPeriod -= nDelta; if (lpTrack->nOutPeriod < AUDIO_MIN_PERIOD) lpTrack->nOutPeriod = AUDIO_MIN_PERIOD; } else { lpTrack->nOutPeriod += nDelta; if (lpTrack->nOutPeriod > AUDIO_MAX_PERIOD) lpTrack->nOutPeriod = AUDIO_MAX_PERIOD; } lpTrack->bControl |= AUDIO_CTRL_PITCH; lpTrack->nVibratoFrame += lpTrack->nVibratoRate; }}static VOID OnFineVibrato(LPTRACK lpTrack){ int nDelta, nFrame; if (!Player.nFrame) { if (LOPARAM(lpTrack->bParams)) { lpTrack->nVibratoDepth = LOPARAM(lpTrack->bParams); } if (HIPARAM(lpTrack->bParams)) { lpTrack->nVibratoRate = HIPARAM(lpTrack->bParams) << 2; } } else { nFrame = (lpTrack->nVibratoFrame >> 2) & 0x1F; switch (lpTrack->bWaveCtrl & 0x03) { case 0x00: nDelta = aSineTable[nFrame]; break; case 0x01: nDelta = nFrame << 3; if (lpTrack->nVibratoFrame & 0x80) nDelta ^= 0xFF; break; case 0x02: nDelta = 0xFF; break; default: /* TODO: random waveform not implemented */ nDelta = 0x00; break; } nDelta = ((nDelta * lpTrack->nVibratoDepth) >> 7); lpTrack->nOutPeriod = lpTrack->nPeriod; if (lpTrack->nVibratoFrame & 0x80) { lpTrack->nOutPeriod -= nDelta; if (lpTrack->nOutPeriod < AUDIO_MIN_PERIOD) lpTrack->nOutPeriod = AUDIO_MIN_PERIOD; } else { lpTrack->nOutPeriod += nDelta; if (lpTrack->nOutPeriod > AUDIO_MAX_PERIOD) lpTrack->nOutPeriod = AUDIO_MAX_PERIOD; } lpTrack->bControl |= AUDIO_CTRL_PITCH; lpTrack->nVibratoFrame += lpTrack->nVibratoRate; }}static VOID OnVolumeSlide(LPTRACK lpTrack){ if (!Player.nFrame) { if (lpTrack->bParams != 0x00) { lpTrack->bVolumeSlide = lpTrack->bParams; } } else { if (HIPARAM(lpTrack->bVolumeSlide)) { lpTrack->nVolume += HIPARAM(lpTrack->bVolumeSlide); if (lpTrack->nVolume > AUDIO_MAX_VOLUME) lpTrack->nVolume = AUDIO_MAX_VOLUME; } else { lpTrack->nVolume -= LOPARAM(lpTrack->bVolumeSlide); if (lpTrack->nVolume < AUDIO_MIN_VOLUME) lpTrack->nVolume = AUDIO_MIN_VOLUME; } lpTrack->nOutVolume = lpTrack->nVolume; lpTrack->bControl |= AUDIO_CTRL_VOLUME; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -