home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Large Pack of OldSkool DOS MOD Trackers
/
far100.zip
/
TRAK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-06
|
17KB
|
577 lines
/* Farandole Composer v1.00 (c)'94 by Daniel Potter */
/* This is the module used for playing/tracking songs. May you blow your nose
many times over it. This module has been changed slightly since release
but the changes are only cosmetic so don't worry about it. */
#define _PORT_DEFS
#include "defaults.h"
#include "dos.h"
#include "far.h"
#include "math.h"
#include "kb.h"
#include "gus.h"
volatile word OverFlow=0,OCount=0,PlayOrder=0;
int mTempo[16];
volatile long PitchWheel[16]={0},DestPitch[16]={0},Increment[16]={0},PresPitch[16]={0};
volatile int VolWheel[16]={0},DestVol[16]={0},VIncrement[16]={0},PresVol[16]={0};
volatile long RetLeft[16]={0},RetSpc[16]={0},CurSpc[16]={0},RetSmp[16]={0},RetVol[16]={0xF};
volatile int OfftCnt[16]={0},RetCnt[16]={0};
volatile int VibOn[16]={0};
volatile int VibPtr[16]={0},VibInc[16]={0};
volatile int CurVols[16]={15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15};
int SinTable[16][128]={0};
volatile int CurFreqs[16]={0};
volatile int VibAmp=4;
volatile Flag near TempoType=1;
volatile int PlayTempo=4,TempoBend=0;
volatile int CurChSmp[16]={0};
volatile int Bars[16]={0};
volatile byte GrabBuf[64]={0};
extern Flag BarsOff;
word fs;
extern word Freqs[];
extern int fsize;
// This used to be a routine to do real volume bars. it was too slow.. have
// at it.
void GetBarData(int ch) {
int q,s;
long ChPos;
int div;
/* ChPos=VoicePos(ch)-4;
U_DumpDRAMToMemory(GrabBuf,ChPos>>16,ChPos&0xFFFF,8);
for (q=0,div=0;q<8;q++) div+=GrabBuf[q];
Bars[ch]=(long)abs(div)*32/((long)128*8);
// Bars[ch]=(long)Bars[ch]*0xEFFF/VolTab[(CurVols[ch]*4)+VolWheel[ch]];
if (Bars[ch]<0) Bars[ch]=0;
if (Bars[ch]>31) Bars[ch]=31; */
Bars[ch]=0;
}
void ChSpeed(dword divisor) {
byte om;
om=inportb(0x21);
disable();
outp(0x43,0x34);
outp(0x40,divisor&0xFF);
outp(0x40,divisor>>8);
outp(0x43,0x90);
outp(0x61,inportb(0x61)|3);
outp(0x21,om);
enable();
}
void UpdateTempo(int tps) {
dword eax,di,cx;
switch(TempoType) {
case 0:
eax=(dword)((long)tps*32)>>2;
if (!eax) return;
eax=1197255/eax;
OCount=32; OverFlow=32;
break;
case 1:
if (!tps) return;
eax=1197255/tps;
cx=0; di=0;
while (eax>0xFFFF) {
eax>>=1;
di++; cx++;
}
if (cx>=2) di++;
di+=3;
OverFlow=di; OCount=di;
break;
}
ChSpeed(eax);
}
void UdTempo() {
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
return;
}
void CalcTempo() {
word q;
double t,f=1,y,amp;
mTempo[0]=256;
for (q=1;q<16;q++) mTempo[q]=128/q;
for (amp=0;amp<16;amp++)
for (t=0;t<1;t+=(1.0/128)) {
y=sin(2*3.1415*f*t)*amp;
SinTable[amp][t*128]=y;
}
}
#pragma option -r-
void UpdateTops();
void interrupt (*OldInt8)();
void interrupt Int8() {
word c,ov,m,q;
long fp,sp,t,ch;
byte fekt;
// outportb(0x20,0x20);
if (!TempoType) {
if ((OCount%8)) goto oo;
}
for (ch=0;ch<16;ch++) {
if (!(OCount%8)) {
/* if (Bars[ch]<(PlayTempo)) Bars[ch]=0;
if (Bars[ch]) Bars[ch]-=PlayTempo; */
GetBarData(ch);
UpdateBars();
}
if (VibOn[ch]) {
VibPtr[ch]+=VibInc[ch]; // Update vibrato table cntr
if (VibPtr[ch]>=128) // Reset counter
VibPtr[ch]=0;
if (!Increment[ch]) // Note port doing it for us?
SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
}
if (Increment[ch]) { // Deal with note port
t=(CurFreqs[ch]+PitchWheel[ch]);
if (Increment[ch]<0) {
if (t<=DestPitch[ch]) {
Increment[ch]=0;
PresPitch[ch]=0;
CurFreqs[ch]=DestPitch[ch];
DestPitch[ch]=0;
}
else
PresPitch[ch]+=Increment[ch];
}
else {
if (t>=DestPitch[ch]) {
Increment[ch]=0;
PresPitch[ch]=0;
CurFreqs[ch]=DestPitch[ch];
DestPitch[ch]=0;
}
else
PresPitch[ch]+=Increment[ch];
}
}
PitchWheel[ch]=PresPitch[ch]/256;
SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
if (VIncrement[ch]) { // Deal with vol port
t=(CurVols[ch]*4)+VolWheel[ch];
if (VIncrement[ch]<0) {
if (t<=DestVol[ch]) {
VIncrement[ch]=0;
PresVol[ch]=0;
CurVols[ch]=DestVol[ch]/4;
DestVol[ch]=0;
}
else
PresVol[ch]+=VIncrement[ch];
}
else {
if (t>=DestVol[ch]) {
VIncrement[ch]=0;
PresVol[ch]=0;
CurVols[ch]=DestVol[ch]/4;
DestPitch[ch]=0;
}
else
PresVol[ch]+=VIncrement[ch];
}
VolWheel[ch]=PresVol[ch];
if ( ((CurVols[ch]*4)+VolWheel[ch])< 0) {
VIncrement[ch]=0;
PresVol[ch]=0;
CurVols[ch]=DestVol[ch]/4;
DestVol[ch]=0;
SetVol(ch,VolTab[0]);
}
else
SetVol(ch,VolTab[(CurVols[ch]*4)+VolWheel[ch]]);
}
if (RetLeft[ch] && ChanOn[ch]) { // Deal with retrigger
CurSpc[ch]+=2;
if (CurSpc[ch]>=RetSpc[ch]) {
if (!OfftCnt[ch]) goto DoNote1; // No note offset (retrig)
if (OfftCnt[ch]==RetCnt[ch]) goto DoNote1; // Time for output of note
goto NoNote1;
DoNote1:
q=RetSmp[ch];
m=Sample[q].LoopMode;
CurVols[ch]=RetVol[ch]-1;
CurChSmp[ch]=q;
if (m&(1<<2))
PlaySample(Sample[q].Seg/2,
Sample[q].Off/2,
Sample[q].Rep/2,
Sample[q].RepEnd/2,
ch,m);
else
PlaySample(Sample[q].Seg,
Sample[q].Off,
Sample[q].Rep,
Sample[q].RepEnd,
ch,m);
SetVol(ch,VolTab[(CurVols[ch]*4)+VolWheel[ch]]);
RetLeft[ch]--;
CurSpc[ch]=0;
NoNote1:
RetCnt[ch]++;
}
}
}
oo:
if (OCount--) {
outportb(0x20,0x20);
return;
}
OCount=OverFlow;
ov=CurVoice;
for (c=0;c<16;c++) {
CurVoice=c;
OfftCnt[CurVoice]=0; RetCnt[CurVoice]=0; RetLeft[CurVoice]=0;
// if (Bars[CurVoice]<(PlayTempo*2)) Bars[CurVoice]=0;
// if (Bars[CurVoice]) Bars[CurVoice]-=PlayTempo*2;
fekt=Pattern[CurSpot+3]&0xF0;
if (Pattern[CurSpot] && ChanOn[CurVoice] && fekt!=0x30) {
q=Pattern[CurSpot+1];
m=Sample[q].LoopMode;
if (Sample[Pattern[CurSpot+1]].SType&1) m|=(1<<2);
CurFreqs[CurVoice]=Freqs[Pattern[CurSpot]-1];
SetFreq(CurVoice,CurFreqs[CurVoice]);
CurChSmp[CurVoice]=q;
if (m&(1<<2))
PlaySample(Sample[q].Seg/2,
Sample[q].Off/2,
Sample[q].Rep/2,
Sample[q].RepEnd/2,
CurVoice,m);
else
PlaySample(Sample[q].Seg,
Sample[q].Off,
Sample[q].Rep,
Sample[q].RepEnd,
CurVoice,m);
PresPitch[CurVoice]=0;
DestPitch[CurVoice]=0; Increment[CurVoice]=0;
// Bars[CurVoice]=(Pattern[CurSpot+2]*fs)/16;
}
SetBalance(CurVoice,CurBalance[CurVoice]);
if (Pattern[CurSpot+2] && ChanOn[CurVoice] && fekt!=0xa0) {
PresVol[CurVoice]=0; VolWheel[CurVoice]=0;
DestVol[CurVoice]=0; VIncrement[CurVoice]=0;
CurVols[CurVoice]=(Pattern[CurSpot+2]-1);
SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)]);
// Bars[CurVoice]=(Pattern[CurSpot+2]*fs)/16;
}
if (Pattern[CurSpot+3]) {
switch(Pattern[CurSpot+3]&0xF0) {
case 0xf0: // Modify tempo
CurTempo=Pattern[CurSpot+3]&0xF;
PlayTempo=CurTempo;
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
break;
case 0xe0: // Fine tempo up/cancel
if (Pattern[CurSpot+3]&0xF) {
TempoBend+=Pattern[CurSpot+3]&0xF;
if ((TempoBend+mTempo[PlayTempo])>=100)
TempoBend=100;
}
else
TempoBend=0;
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
break;
case 0xd0: // Fine tempo down/cancel
if (Pattern[CurSpot+3]&0xF) {
TempoBend-=Pattern[CurSpot+3]&0xF;
if ((TempoBend+mTempo[PlayTempo])<=0)
TempoBend=0;
}
else
TempoBend=0;
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
break;
case 0xb0: // Set Balance
CurBalance[CurVoice]=Pattern[CurSpot+3]&0xF;
SetBalance(CurVoice,CurBalance[CurVoice]);
if (Tracking)
UpdatePanning();
break;
case 0x10: // raise pitch
PresPitch[CurVoice]+=((Pattern[CurSpot+3]&0xF)*4)*256;
PitchWheel[CurVoice]=PresPitch[CurVoice]/256;
DestPitch[CurVoice]=0; Increment[CurVoice]=0;
SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
break;
case 0x20: // lower pitch
PresPitch[CurVoice]-=((Pattern[CurSpot+3]&0xF)*4)*256;
PitchWheel[CurVoice]=PresPitch[CurVoice]/256;
DestPitch[CurVoice]=0; Increment[CurVoice]=0;
SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
break;
case 0x30: // Port to note
if (Pattern[CurSpot]) {
t=0;
fp=CurFreqs[CurVoice]+PitchWheel[CurVoice];
sp=Freqs[Pattern[CurSpot]-1];
DestPitch[CurVoice]=sp;
if (fp>sp) {t=sp;sp=fp;fp=t;}
if (Pattern[CurSpot+3]&0xF)
Increment[CurVoice]=((sp-fp)*256)/((Pattern[CurSpot+3]&0xF)*
(mTempo[PlayTempo]+TempoBend));
else
Increment[CurVoice]=((sp-fp)*256)/(1*
(mTempo[PlayTempo]+TempoBend));
Increment[CurVoice]*=8;
if (t) Increment[CurVoice]=-Increment[CurVoice];
}
break;
case 0xC0: // Note Offset
OfftCnt[CurVoice]=Pattern[CurSpot+3]&0xF;
if (Pattern[CurSpot]) {
RetLeft[CurVoice]=0xE;
if (TempoType)
RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/4;
else
RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/2;
RetSmp[CurVoice]=Pattern[CurSpot+1];
RetVol[CurVoice]=Pattern[CurSpot+2];
CurSpc[CurVoice]=0;
}
break;
case 0x40: // Retrigger
if (Pattern[CurSpot]) {
RetLeft[CurVoice]=(Pattern[CurSpot+3]&0xF)-1;
if (TempoType)
RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/4;
else
RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/2;
RetSmp[CurVoice]=Pattern[CurSpot+1];
RetVol[CurVoice]=Pattern[CurSpot+2];
CurSpc[CurVoice]=0;
}
break;
case 0x50: // Set vibrato amplitude
VibAmp=Pattern[CurSpot+3]&0xF;
break;
case 0x60: // Vibrato Control
if (!VibOn[CurVoice]) {
VibOn[CurVoice]=1;
VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
VibPtr[CurVoice]=0;
}
else
VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
break;
case 0x90: // Sustained vibrato control
if (Pattern[CurSpot+3]&0xF) { // On
if (!VibOn[CurVoice]) {
VibOn[CurVoice]=2;
VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
VibPtr[CurVoice]=0;
}
else
VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
}
else { // Off
VibPtr[CurVoice]=0;
VibInc[CurVoice]=0;
VibOn[CurVoice]=FALSE;
}
break;
case 0x70: // VolSldUp
q=Pattern[CurSpot+3]&0xF;
CurVols[CurVoice]+=q;
if (CurVols[CurVoice]>0xF) CurVols[CurVoice]=0xF;
SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)+VolWheel[CurVoice]]);
// Bars[CurVoice]=((CurVols[CurVoice]+1)*fs)/16;
break;
case 0x80: // VolSldDn
q=Pattern[CurSpot+3]&0xF;
CurVols[CurVoice]-=q;
if (CurVols[CurVoice]<0) CurVols[CurVoice]=0;
SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)+VolWheel[CurVoice]]);
// Bars[CurVoice]=((CurVols[CurVoice]+1)*fs)/16;
break;
case 0xA0: // Port to Vol
if (Pattern[CurSpot+2]) {
t=0;
fp=(CurVols[CurVoice]*4)+VolWheel[CurVoice];
sp=(Pattern[CurSpot+2]*4)-1;
DestVol[CurVoice]=sp;
if (fp>sp) {t=sp;sp=fp;fp=t;}
if (Pattern[CurSpot+3]&0xF)
VIncrement[CurVoice]=((sp-fp)*16)/((Pattern[CurSpot+3]&0xF)*
(mTempo[PlayTempo]+TempoBend));
else
VIncrement[CurVoice]=((sp-fp)*16)/(1*
(mTempo[PlayTempo]+TempoBend));
if (t) VIncrement[CurVoice]=-VIncrement[CurVoice];
}
break;
case 0x00: // Global funct
switch(Pattern[CurSpot+3]&0xF) {
case 1: // Ramp off
case 2: // Ramp on
VolRamps=(Pattern[CurSpot+3]&0xF)-1;
break;
case 3:
q=CurChSmp[CurVoice];
SetLoops(Sample[q].Seg,Sample[q].Off,Sample[q].Len,
Sample[q].LoopMode&0xf7,CurVoice);
break;
case 4: // 669 tempos
case 5: // far tempos
TempoType=(Pattern[CurSpot+3]&0xF)-4;
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
break;
}
break;
}
}
if (VibOn[CurVoice]==1 && (Pattern[CurSpot+3]&0xF0)!=0x60) {
VibPtr[CurVoice]=0;
VibInc[CurVoice]=0;
VibOn[CurVoice]=FALSE;
}
/* if (Bars[CurVoice]>=fs) Bars[CurVoice]=fs-1;
if (Bars[CurVoice]<1) Bars[CurVoice]=1; */
}
CurVoice=ov;
if (CurRow<=BreakLoc) {
if (CurRow-CurTop==31) {
if (Tracking) {
CurRow++;
CurTop=CurRow;
TrakUpdate=TRUE;
}
else
CurRow++;
}
else
if (Tracking) {
MoveCurs(CurVoice,CurRow+1);
UDBars=TRUE;;
}
else
CurRow++;
}
else {
if (PatLock) {
if (Tracking) {
TrakUpdate=TRUE;
CurRow=0; CurTop=0;
}
else
CurRow=0;
}
else {
PutAwayPat(CurPattern);
if (Order[CurOrder+1]==0xFF)
CurOrder=LoopTo;
else
CurOrder++;
CurPattern=Order[CurOrder];
GetPat(CurPattern);
if (Tracking) {
CurTop=0;
CurRow=0;
TrakUpdate=TRUE;
}
else
CurRow=0;
}
}
outportb(0x20,0x20);
}
#pragma option -r
void StopMusic() {
word q;
if (Playing) {
ChSpeed(0);
setvect(8,OldInt8);
if (Tracking) UpdateChans();
KillBars();
}
for (q=0;q<16;q++) StopSample(q);
Playing=NO;
}
void ResetChannel(int ch) {
PlaySample(0,32,0,0,ch,0);
}
void StartMusic() {
word q;
fs=fsize*4;
StopMusic();
KillBars();
memset(GrabBuf,0,64);
U_DumpSampleToDRAM(GrabBuf,0,0,64);
for (q=0;q<16;q++) SetBalance(q,CurBalance[q]);
for (q=0;q<16;q++) ResetChannel(q);
memset(PitchWheel,0,sizeof(PitchWheel));
memset(VibOn,0,sizeof(VibOn));
memset(VibPtr,0,sizeof(VibPtr));
memset(VibInc,0,sizeof(VibInc));
memset(RetLeft,0,sizeof(RetLeft));
PlayTempo=CurTempo;
UpdateChans();
UpdateOrder();
OldInt8=getvect(8);
setvect(8,Int8);
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
OCount=OverFlow;
Playing=YES;
if (!Tracking) {
DrawF(0,42,11,9," Playing song.. Press any key except D to stop playback - Press D to shell to DOS ");
do {
GetCh();
if (LKHit=='D') {
DosShell();
LKHit='D';
}
} while (LKHit=='D');
StopMusic();
UpdateStat();
UpdateChans();
}
}