home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff255.lzh
/
MED
/
Player_Source
/
Player.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-10-19
|
12KB
|
340 lines
/* Player.c ----- by Teijo Kinnunen (1989) */
/* This is a code for MED song player. You can freely use it in both
commercial and non-commercial programs.
Tässä on MED-soittajan lähdekoodi. Sitä saa vapaasti käyttää sekä
kaupallisissa, että ei-kaupallisissa ohjelmissa.
*/
#include <exec/types.h>
#include <exec/io.h>
#include <exec/interrupts.h>
#include <devices/timer.h>
#include <devices/audio.h>
#include <hardware/cia.h>
#include <dos.h>
#include <stdlib.h>
#include "med.h"
#ifdef LATTICE
#include <proto/exec.h>
#endif
extern struct CIA far ciaa; /* Remove 'far' if your compiler doesn't
support it. --- Poista 'far' jos kääntäjäsi
ei tunne sitä. */
static void SWareIntr();
UWORD soittorivi,soittolohko,soittolohkonnum,soittotila;
struct Task *player;
extern struct CLohko lohko[];
UBYTE playerlopettanut = FALSE;
UBYTE varattava[] = { 0x01,0x02,0x04,0x08 };
UBYTE laiteavattu[] = { FALSE, FALSE, FALSE, FALSE };
extern UBYTE *samples[];
extern struct Kappale song;
extern ULONG soittimenpituus[];
ULONG seurnuotsignmsk,askelm;
UWORD periodit[] = { 856,808,762,720,678,640,604,570,538,508,480,453,
428,404,381,360,339,320,302,285,269,254,240,226,
214,202,190,180,170,160,151,143,135,127,120,113,
107,101,95, 90, 85, 80, 75, 72, 68, 64, 60, 57 };
struct IOAudio *audioioreq[4],audiopervolreq[4],audiostopreq[4],audiorepreq[4];
struct Aloitusviesti aloitusviesti;
struct Soittokasky kasky;
struct MsgPort *audioport[4],*playerport=NULL,*plreply;
static void SoitaNuotti(kanava,taajuus,voimakkuus,soitinid)
UBYTE kanava;
UWORD taajuus,voimakkuus,soitinid;
{
register struct IOAudio *audioreq = audioioreq[kanava];
register struct IOAudio *repreq = &audiorepreq[kanava];
BeginIO((struct IORequest *)&audiostopreq[kanava]);
while(GetMsg(audioport[kanava]));
audioreq->ioa_Data = samples[soitinid];
if(song.stoisto[soitinid])
audioreq->ioa_Length = song.stoisto[soitinid];
else audioreq->ioa_Length = soittimenpituus[soitinid];
audioreq->ioa_Request.io_Flags = ADIOF_PERVOL;
audioreq->ioa_Period = taajuus;
audioreq->ioa_Volume = voimakkuus;
BeginIO((struct IORequest *)audioreq);
if(song.stoisto[soitinid]) { /* toistetaan ikuisesti */
repreq->ioa_Data = (UBYTE *)(samples[soitinid] +
song.stoisto[soitinid]);
repreq->ioa_Length = song.stoistonpit[soitinid];
BeginIO((struct IORequest *)repreq);
}
}
void MEDPlayer()
{
struct Soittokasky *tamakasky;
ULONG data,signmsk,plrprtmsk,odotusmsk;
long snsn = AllocSignal(-1); /* seuraavan nuotin signaalin numero */
register UWORD counter = 0,period,textra;
register UBYTE raitano;
UBYTE argumentti[4],efekti[4],kaskynaani;
UWORD edellinensoitin[4] = { 0,0,0,0 };
WORD edellinenvoim[4] = { 0,0,0,0 };
UWORD komento,edarpgpernum,laskuri,kaskynsoitin;
UWORD edellinenperiod[4] = { 0,0,0,0 };
BOOL vaihdalohkoa = FALSE,ylsoitin,eikaynnisty = FALSE;
BYTE ioerror;
geta4();
soittotila = ALASOITA;
aloitusviesti.viesti_msg.mn_ReplyPort = NULL;
aloitusviesti.viesti_msg.mn_Node.ln_Type = NT_MESSAGE;
aloitusviesti.viesti_msg.mn_Length = sizeof(struct Aloitusviesti);
for(laskuri = 0; laskuri < 4; laskuri++) {
if(!(audioport[laskuri] = CreatePort(0,0))) { eikaynnisty = TRUE; break; }
if(!(audioioreq[laskuri] = (struct IOAudio *)CreateExtIO(audioport[laskuri],
sizeof(struct IOAudio)))) { eikaynnisty = TRUE; break; }
audioioreq[laskuri]->ioa_Request.io_Message.mn_Node.ln_Pri = 50;
audioioreq[laskuri]->ioa_Data = &varattava[laskuri];
audioioreq[laskuri]->ioa_Length = 1;
ioerror = OpenDevice(AUDIONAME,0,(struct IORequest *)audioioreq[laskuri],0);
if(ioerror) { eikaynnisty = TRUE; break; }
laiteavattu[laskuri] = TRUE;
memcpy((char *)&audiopervolreq[laskuri],(char *)audioioreq[laskuri],
sizeof(struct IOAudio));
memcpy((char *)&audiostopreq[laskuri],(char *)audioioreq[laskuri],
sizeof(struct IOAudio));
memcpy((char *)&audiorepreq[laskuri],(char *)audioioreq[laskuri],
sizeof(struct IOAudio));
audiopervolreq[laskuri].ioa_Request.io_Command = ADCMD_PERVOL;
audiostopreq[laskuri].ioa_Request.io_Command = CMD_FLUSH;
audioioreq[laskuri]->ioa_Request.io_Command = CMD_WRITE;
audiorepreq[laskuri].ioa_Request.io_Command = CMD_WRITE;
audioioreq[laskuri]->ioa_Cycles = 1;
audiorepreq[laskuri].ioa_Cycles = 0;
audiostopreq[laskuri].ioa_Request.io_Flags = IOF_QUICK;
audiopervolreq[laskuri].ioa_Request.io_Flags = IOF_QUICK;
}
if(eikaynnisty || snsn == -1 || !(playerport = CreatePort(0,0))) {
aloitusviesti.viesti_tilanne = PIELEENMENI;
PutMsg(plreply,(struct Message *)&aloitusviesti);
goto playerinloppu;
}
seurnuotsignmsk = 1 << snsn;
plrprtmsk = 1 << playerport->mp_SigBit;
odotusmsk = seurnuotsignmsk | plrprtmsk; /* säästää aikaa laskea se nyt */
aloitusviesti.viesti_tilanne = KAIKKIHYVIN;
PutMsg(plreply,(struct Message *)&aloitusviesti);
for(;;) {
signmsk = Wait(odotusmsk);
if(signmsk & plrprtmsk) {
tamakasky = (struct Soittokasky *)GetMsg(playerport);
komento = tamakasky->kasky_komento;
data = tamakasky->kasky_data;
kaskynaani = tamakasky->kasky_aani;
kaskynsoitin = tamakasky->kasky_soitin;
ReplyMsg((struct Message *)tamakasky);
if(komento == OHJELMANLOPPU) break;
if(komento == SOITALOHKO) {
soittotila = SOITALOHKOA;
soittolohko = data;
}
else if(komento == SOITAKAPPALE) {
soittotila = SOITAKAPPALETTA;
soittolohkonnum = data;
soittolohko = song.soittojarjestys[soittolohkonnum];
}
else if(komento == SOITANUOTTI)
SoitaNuotti(kaskynaani,(UWORD)data,
(UWORD)song.soittimenvoimakkuus[kaskynsoitin],kaskynsoitin);
else if(komento == SEIS) soittotila = ALASOITA;
}
if(signmsk & seurnuotsignmsk) {
if(soittotila == ALASOITA) continue;
if(++counter == 6) {
counter = 0;
for(raitano = 0; raitano < 4; raitano++) {
period=lohko[soittolohko].pala[soittorivi].savel[raitano].savel_period;
textra=lohko[soittolohko].pala[soittorivi].savel[raitano].savel_extra;
argumentti[raitano] = (textra & 0x00ff);
if(period & 0x8000) { /* jos periodin ylin bitti asetettu */
period &= ~0x8000; /* otetaan se pois */
ylsoitin = TRUE;
}
else ylsoitin = FALSE;
if(textra & 0xf000 || ylsoitin) {
edellinensoitin[raitano]=((textra&0xf000)>>12)+(ylsoitin?16:0);
edellinenvoim[raitano] =
song.soittimenvoimakkuus[edellinensoitin[raitano]];
}
if(efekti[raitano] = ((textra & 0x0f00) >> 8)) {
if(efekti[raitano] == 0x0f) {
if(argumentti[raitano]) askelm = 625000 / argumentti[raitano];
else vaihdalohkoa = TRUE;
}
else if(efekti[raitano] == 0x0c)
edellinenvoim[raitano] = /* vvv-kerrotaan kymmenellä */
((argumentti[raitano]>>1)&0xf8)+((argumentti[raitano]>>3)&0xfe)+
(argumentti[raitano] & 0x0f);
}
if(period) {
edellinenperiod[raitano] = period;
SoitaNuotti(raitano,period,edellinenvoim[raitano],
edellinensoitin[raitano]);
}
}
if(++soittorivi > 63 || vaihdalohkoa) {
if(soittotila == SOITALOHKOA) soittorivi = 0;
else if(soittotila == SOITAKAPPALETTA) {
soittorivi = 0;
if(++soittolohkonnum > song.kappaleen_pituus-1)
soittolohkonnum = 0;
if((soittolohko = song.soittojarjestys[soittolohkonnum]) >
song.lohkoja - 1) soittolohko = song.lohkoja - 1;
}
vaihdalohkoa = FALSE;
}
}
for(raitano = 0; raitano < 4; raitano++) {
period = 0;
switch(efekti[raitano]) {
case 0x01: /* liukuu ylös.. */
if(song.vaihtoja == 5 && !counter) break;
edellinenperiod[raitano] -= argumentti[raitano];
if(edellinenperiod[raitano] < 113) edellinenperiod[raitano] = 113;
break;
case 0x02: /* sama alas */
if(song.vaihtoja == 5 && !counter) break;
edellinenperiod[raitano] += argumentti[raitano];
if(edellinenperiod[raitano] > 856) edellinenperiod[raitano] = 856;
break;
case 0x03: /* vibrato */
if(counter < 3)
period = edellinenperiod[raitano] - argumentti[raitano];
else period = edellinenperiod[raitano];
break;
case 0x0d: case 0x0e: /* voimakkuuden muutos */
if(argumentti[raitano] >> 4 == 0) { /* hiljennä */
if((edellinenvoim[raitano] -= argumentti[raitano]) < 0)
edellinenvoim[raitano] = 0;
} else { /* suurenna */
if((edellinenvoim[raitano] += (argumentti[raitano] >> 4)) > 64)
edellinenvoim[raitano] = 64;
}
break;
case 0x00: /* arpeggio */
if(!argumentti[raitano]) continue;
switch(counter) {
case 0:
for(edarpgpernum = 0; edarpgpernum < 36; edarpgpernum++)
if(edellinenperiod[raitano] >= periodit[edarpgpernum]) break;
case 3:
period = periodit[edarpgpernum + (argumentti[raitano] & 0x0f)];
break;
case 1: case 4:
period = periodit[edarpgpernum + (argumentti[raitano] >> 4)];
break;
default: /* 2 ja 5 */
period = edellinenperiod[raitano];
break;
}
break;
case 0x0c:
break;
default:
continue;
}
if(period) audiopervolreq[raitano].ioa_Period = period;
else audiopervolreq[raitano].ioa_Period = edellinenperiod[raitano];
audiopervolreq[raitano].ioa_Volume = edellinenvoim[raitano];
BeginIO((struct IORequest *)&audiopervolreq[raitano]);
}
}
}
playerinloppu:
for(laskuri = 0; laskuri < 4; laskuri++) {
if(laiteavattu[laskuri]) {
if(!CheckIO((struct IORequest *)audioioreq[laskuri]))
AbortIO((struct IORequest *)audioioreq[laskuri]);
audioioreq[laskuri]->ioa_Request.io_Command = CMD_RESET;
DoIO((struct IORequest *)audioioreq[laskuri]);
CloseDevice((struct IORequest *)audioioreq[laskuri]);
}
if(audioioreq[laskuri])
DeleteExtIO((struct IORequest *)audioioreq[laskuri]);
if(audioport[laskuri]) DeletePort(audioport[laskuri]);
}
if(playerport) DeletePort(playerport);
if(snsn != -1) FreeSignal(snsn);
playerlopettanut = TRUE;
}
struct timerequest *timereq;
BOOL timerauki = FALSE;
struct Interrupt sware = { { NULL,NULL,0,32,"MEDSWInt" },NULL,SWareIntr };
struct MsgPort timerport = { { NULL,NULL,NT_MSGPORT,0,NULL },PA_SOFTINT,0,
(struct Task *)&sware,{ 0 } };
void SWareIntr()
{
geta4();
Signal(player,seurnuotsignmsk);
(void)GetMsg(&timerport);
timereq->tr_time.tv_micro = askelm;
timereq->tr_time.tv_secs = 0L;
SendIO((struct IORequest *)timereq);
}
LONG PLRInit() /* returns -1 if error, 0 if ok */
{
struct Aloitusviesti *alkuviesti;
askelm = 625000 / song.tempo;
if(!(plreply = CreatePort(0,0))) return(-1);
kasky.kasky_msg.mn_Node.ln_Type = NT_MESSAGE;
kasky.kasky_msg.mn_ReplyPort = plreply;
kasky.kasky_msg.mn_Length = sizeof(struct Soittokasky);
if(!(player = CreateTask("MEDPlayer.task",21,(APTR)MEDPlayer,5000))) return(-1);
WaitPort(plreply);
alkuviesti = (struct Aloitusviesti *)GetMsg(plreply);
if(alkuviesti->viesti_tilanne == PIELEENMENI) return(-1);
NewList(&(timerport.mp_MsgList));
if(!(timereq = (struct timerequest *)CreateExtIO(&timerport,
sizeof(struct timerequest)))) return(-1);
if(OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *)timereq,0))
return(-1);
timerauki = TRUE;
timereq->tr_node.io_Command = TR_ADDREQUEST;
Cause(&sware);
if(song.liput & LIPPU_SUODATINPAALLA) ciaa.ciapra &= ~CIAF_LED;
else ciaa.ciapra |= CIAF_LED;
return(0);
}
void PLRPlaySong()
{
kasky.kasky_komento = SOITAKAPPALE;
kasky.kasky_data = 0;
PutMsg(playerport,(struct Message *)&kasky);
WaitPort(plreply);
(void)GetMsg(plreply);
}
void PLRStop()
{
kasky.kasky_komento = SEIS;
PutMsg(playerport,(struct Message *)&kasky);
WaitPort(plreply);
(void)GetMsg(plreply);
}
void PLRRemove()
{
timerport.mp_Flags = PA_IGNORE;
if(!CheckIO((struct IORequest *)timereq))
AbortIO((struct IORequest *)timereq);
if(timerauki) CloseDevice((struct IORequest *)timereq);
if(timereq) DeleteExtIO((struct IORequest *)timereq);
ciaa.ciapra &= ~CIAF_LED;
if(playerport) {
kasky.kasky_komento = OHJELMANLOPPU;
PutMsg(playerport,(struct Message *)&kasky);
WaitPort(plreply);
(void)GetMsg(plreply);
while(!playerlopettanut);
}
if(plreply) DeletePort(plreply);
}