home *** CD-ROM | disk | FTP | other *** search
- /* 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);
- }