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 >
C/C++ Source or Header  |  1989-10-19  |  12KB  |  340 lines

  1. /* Player.c  ----- by Teijo Kinnunen (1989) */
  2. /* This is a code for MED song player. You can freely use it in both
  3.    commercial and non-commercial programs.
  4.    
  5.    Tässä on MED-soittajan lähdekoodi. Sitä saa vapaasti käyttää sekä
  6.    kaupallisissa, että ei-kaupallisissa ohjelmissa.
  7. */
  8. #include <exec/types.h>
  9. #include <exec/io.h>
  10. #include <exec/interrupts.h>
  11. #include <devices/timer.h>
  12. #include <devices/audio.h>
  13. #include <hardware/cia.h>
  14. #include <dos.h>
  15. #include <stdlib.h>
  16. #include "med.h"
  17. #ifdef LATTICE
  18. #include <proto/exec.h>
  19. #endif
  20. extern struct CIA far ciaa; /* Remove 'far' if your compiler doesn't
  21.                   support it. --- Poista 'far' jos kääntäjäsi
  22.                   ei tunne sitä. */
  23. static void SWareIntr();
  24. UWORD soittorivi,soittolohko,soittolohkonnum,soittotila;
  25. struct Task *player;
  26. extern struct CLohko lohko[];
  27. UBYTE playerlopettanut = FALSE;
  28. UBYTE varattava[] = { 0x01,0x02,0x04,0x08 };
  29. UBYTE laiteavattu[] = { FALSE, FALSE, FALSE, FALSE };
  30. extern UBYTE *samples[];
  31. extern struct Kappale song;
  32. extern ULONG soittimenpituus[];
  33. ULONG seurnuotsignmsk,askelm;
  34. UWORD periodit[] = { 856,808,762,720,678,640,604,570,538,508,480,453,
  35.              428,404,381,360,339,320,302,285,269,254,240,226,
  36.              214,202,190,180,170,160,151,143,135,127,120,113,
  37.              107,101,95, 90, 85, 80, 75, 72, 68, 64, 60, 57 };
  38. struct IOAudio *audioioreq[4],audiopervolreq[4],audiostopreq[4],audiorepreq[4];
  39. struct Aloitusviesti aloitusviesti;
  40. struct Soittokasky kasky;
  41. struct MsgPort *audioport[4],*playerport=NULL,*plreply;
  42.  
  43. static void SoitaNuotti(kanava,taajuus,voimakkuus,soitinid)
  44. UBYTE kanava;
  45. UWORD taajuus,voimakkuus,soitinid;
  46. {
  47.   register struct IOAudio *audioreq = audioioreq[kanava];
  48.   register struct IOAudio *repreq = &audiorepreq[kanava];
  49.   BeginIO((struct IORequest *)&audiostopreq[kanava]);
  50.   while(GetMsg(audioport[kanava]));
  51.   audioreq->ioa_Data = samples[soitinid];
  52.   if(song.stoisto[soitinid])
  53.       audioreq->ioa_Length = song.stoisto[soitinid];
  54.   else audioreq->ioa_Length = soittimenpituus[soitinid];
  55.   audioreq->ioa_Request.io_Flags = ADIOF_PERVOL;
  56.   audioreq->ioa_Period = taajuus;
  57.   audioreq->ioa_Volume = voimakkuus;
  58.   BeginIO((struct IORequest *)audioreq);
  59.   if(song.stoisto[soitinid]) { /* toistetaan ikuisesti */
  60.     repreq->ioa_Data = (UBYTE *)(samples[soitinid] +
  61.                 song.stoisto[soitinid]);
  62.     repreq->ioa_Length = song.stoistonpit[soitinid];
  63.     BeginIO((struct IORequest *)repreq);
  64.   }
  65. }
  66.  
  67. void MEDPlayer()
  68. {
  69.   struct Soittokasky *tamakasky;
  70.   ULONG data,signmsk,plrprtmsk,odotusmsk;
  71.   long snsn = AllocSignal(-1); /* seuraavan nuotin signaalin numero */
  72.   register UWORD counter = 0,period,textra;
  73.   register UBYTE raitano;
  74.   UBYTE argumentti[4],efekti[4],kaskynaani;
  75.   UWORD edellinensoitin[4] = { 0,0,0,0 };
  76.   WORD edellinenvoim[4] = { 0,0,0,0 };
  77.   UWORD komento,edarpgpernum,laskuri,kaskynsoitin;
  78.   UWORD edellinenperiod[4] = { 0,0,0,0 };
  79.   BOOL vaihdalohkoa = FALSE,ylsoitin,eikaynnisty = FALSE;
  80.   BYTE ioerror;
  81.   geta4();
  82.   soittotila = ALASOITA;
  83.   aloitusviesti.viesti_msg.mn_ReplyPort = NULL;
  84.   aloitusviesti.viesti_msg.mn_Node.ln_Type = NT_MESSAGE;
  85.   aloitusviesti.viesti_msg.mn_Length = sizeof(struct Aloitusviesti);
  86.   for(laskuri = 0; laskuri < 4; laskuri++) {
  87.     if(!(audioport[laskuri] = CreatePort(0,0))) { eikaynnisty = TRUE; break; }
  88.     if(!(audioioreq[laskuri] = (struct IOAudio *)CreateExtIO(audioport[laskuri],
  89.       sizeof(struct IOAudio)))) { eikaynnisty = TRUE; break; }
  90.     audioioreq[laskuri]->ioa_Request.io_Message.mn_Node.ln_Pri = 50;
  91.     audioioreq[laskuri]->ioa_Data = &varattava[laskuri];
  92.     audioioreq[laskuri]->ioa_Length = 1;
  93.     ioerror = OpenDevice(AUDIONAME,0,(struct IORequest *)audioioreq[laskuri],0);
  94.     if(ioerror) { eikaynnisty = TRUE; break; }
  95.     laiteavattu[laskuri] = TRUE;
  96.     memcpy((char *)&audiopervolreq[laskuri],(char *)audioioreq[laskuri],
  97.     sizeof(struct IOAudio));
  98.     memcpy((char *)&audiostopreq[laskuri],(char *)audioioreq[laskuri],
  99.     sizeof(struct IOAudio));
  100.     memcpy((char *)&audiorepreq[laskuri],(char *)audioioreq[laskuri],
  101.     sizeof(struct IOAudio));
  102.     audiopervolreq[laskuri].ioa_Request.io_Command = ADCMD_PERVOL;
  103.     audiostopreq[laskuri].ioa_Request.io_Command = CMD_FLUSH;
  104.     audioioreq[laskuri]->ioa_Request.io_Command = CMD_WRITE;
  105.     audiorepreq[laskuri].ioa_Request.io_Command = CMD_WRITE;
  106.     audioioreq[laskuri]->ioa_Cycles = 1;
  107.     audiorepreq[laskuri].ioa_Cycles = 0;
  108.     audiostopreq[laskuri].ioa_Request.io_Flags = IOF_QUICK;
  109.     audiopervolreq[laskuri].ioa_Request.io_Flags = IOF_QUICK;
  110.   }
  111.   if(eikaynnisty || snsn == -1 || !(playerport = CreatePort(0,0))) {
  112.     aloitusviesti.viesti_tilanne = PIELEENMENI;
  113.     PutMsg(plreply,(struct Message *)&aloitusviesti);
  114.     goto playerinloppu;
  115.   }
  116.   seurnuotsignmsk = 1 << snsn;
  117.   plrprtmsk = 1 << playerport->mp_SigBit;
  118.   odotusmsk = seurnuotsignmsk | plrprtmsk; /* säästää aikaa laskea se nyt */
  119.   aloitusviesti.viesti_tilanne = KAIKKIHYVIN;
  120.   PutMsg(plreply,(struct Message *)&aloitusviesti);
  121.   for(;;) {
  122.     signmsk = Wait(odotusmsk);
  123.     if(signmsk & plrprtmsk) {
  124.       tamakasky = (struct Soittokasky *)GetMsg(playerport);
  125.       komento = tamakasky->kasky_komento;
  126.       data = tamakasky->kasky_data;
  127.       kaskynaani = tamakasky->kasky_aani;
  128.       kaskynsoitin = tamakasky->kasky_soitin;
  129.       ReplyMsg((struct Message *)tamakasky);
  130.       if(komento == OHJELMANLOPPU) break;
  131.       if(komento == SOITALOHKO) {
  132.     soittotila = SOITALOHKOA;
  133.     soittolohko = data;
  134.       }
  135.       else if(komento == SOITAKAPPALE) {
  136.     soittotila = SOITAKAPPALETTA;
  137.     soittolohkonnum = data;
  138.     soittolohko = song.soittojarjestys[soittolohkonnum];
  139.       }
  140.       else if(komento == SOITANUOTTI)
  141.     SoitaNuotti(kaskynaani,(UWORD)data,
  142.       (UWORD)song.soittimenvoimakkuus[kaskynsoitin],kaskynsoitin);
  143.       else if(komento == SEIS)    soittotila = ALASOITA;
  144.     }
  145.     if(signmsk & seurnuotsignmsk) {
  146.       if(soittotila == ALASOITA) continue;
  147.       if(++counter == 6) {
  148.     counter = 0;
  149.     for(raitano = 0; raitano < 4; raitano++) {
  150.       period=lohko[soittolohko].pala[soittorivi].savel[raitano].savel_period;
  151.       textra=lohko[soittolohko].pala[soittorivi].savel[raitano].savel_extra;
  152.       argumentti[raitano] = (textra & 0x00ff);
  153.       if(period & 0x8000) { /* jos periodin ylin bitti asetettu */
  154.         period &= ~0x8000; /* otetaan se pois */
  155.         ylsoitin = TRUE;
  156.       }
  157.       else ylsoitin = FALSE;
  158.       if(textra & 0xf000 || ylsoitin) {
  159.         edellinensoitin[raitano]=((textra&0xf000)>>12)+(ylsoitin?16:0);
  160.         edellinenvoim[raitano] =
  161.           song.soittimenvoimakkuus[edellinensoitin[raitano]];
  162.       }
  163.       if(efekti[raitano] = ((textra & 0x0f00) >> 8)) {
  164.         if(efekti[raitano] == 0x0f) {
  165.         if(argumentti[raitano]) askelm = 625000 / argumentti[raitano];
  166.         else vaihdalohkoa = TRUE;
  167.         }
  168.         else if(efekti[raitano] == 0x0c)
  169.         edellinenvoim[raitano] = /* vvv-kerrotaan kymmenellä */
  170.             ((argumentti[raitano]>>1)&0xf8)+((argumentti[raitano]>>3)&0xfe)+
  171.             (argumentti[raitano] & 0x0f);
  172.       }
  173.       if(period) {
  174.         edellinenperiod[raitano] = period;
  175.         SoitaNuotti(raitano,period,edellinenvoim[raitano],
  176.         edellinensoitin[raitano]);
  177.       }
  178.     }
  179.     if(++soittorivi > 63 || vaihdalohkoa) {
  180.       if(soittotila == SOITALOHKOA) soittorivi = 0;
  181.       else if(soittotila == SOITAKAPPALETTA) {
  182.         soittorivi = 0;
  183.         if(++soittolohkonnum > song.kappaleen_pituus-1)
  184.             soittolohkonnum = 0;
  185.         if((soittolohko = song.soittojarjestys[soittolohkonnum]) >
  186.         song.lohkoja - 1) soittolohko = song.lohkoja - 1;
  187.       }
  188.       vaihdalohkoa = FALSE;
  189.     }
  190.       }
  191.       for(raitano = 0; raitano < 4; raitano++) {
  192.     period = 0;
  193.     switch(efekti[raitano]) {
  194.       case 0x01: /* liukuu ylös.. */
  195.         if(song.vaihtoja == 5 && !counter) break;
  196.         edellinenperiod[raitano] -= argumentti[raitano];
  197.         if(edellinenperiod[raitano] < 113) edellinenperiod[raitano] = 113;
  198.         break;
  199.       case 0x02: /* sama alas */
  200.         if(song.vaihtoja == 5 && !counter) break;
  201.         edellinenperiod[raitano] += argumentti[raitano];
  202.         if(edellinenperiod[raitano] > 856) edellinenperiod[raitano] = 856;
  203.         break;
  204.       case 0x03: /* vibrato */
  205.         if(counter < 3)
  206.         period = edellinenperiod[raitano] - argumentti[raitano];
  207.         else period = edellinenperiod[raitano];
  208.         break;
  209.       case 0x0d: case 0x0e: /* voimakkuuden muutos */
  210.         if(argumentti[raitano] >> 4 == 0) { /* hiljennä */
  211.         if((edellinenvoim[raitano] -= argumentti[raitano]) < 0)
  212.             edellinenvoim[raitano] = 0;
  213.         } else { /* suurenna */
  214.         if((edellinenvoim[raitano] += (argumentti[raitano] >> 4)) > 64)
  215.             edellinenvoim[raitano] = 64;
  216.         }
  217.         break;
  218.       case 0x00: /* arpeggio */
  219.         if(!argumentti[raitano]) continue;
  220.         switch(counter) {
  221.         case 0:
  222.             for(edarpgpernum = 0; edarpgpernum < 36; edarpgpernum++)
  223.               if(edellinenperiod[raitano] >= periodit[edarpgpernum]) break;
  224.         case 3:
  225.             period = periodit[edarpgpernum + (argumentti[raitano] & 0x0f)];
  226.             break;
  227.         case 1: case 4:
  228.             period = periodit[edarpgpernum + (argumentti[raitano] >> 4)];
  229.             break;
  230.         default: /* 2 ja 5 */
  231.             period = edellinenperiod[raitano];
  232.             break;
  233.         }
  234.         break;
  235.       case 0x0c:
  236.         break;
  237.       default:
  238.         continue;
  239.     }
  240.     if(period) audiopervolreq[raitano].ioa_Period = period;
  241.     else audiopervolreq[raitano].ioa_Period = edellinenperiod[raitano];
  242.     audiopervolreq[raitano].ioa_Volume = edellinenvoim[raitano];
  243.     BeginIO((struct IORequest *)&audiopervolreq[raitano]);
  244.       }
  245.     }
  246.   }
  247. playerinloppu:
  248.   for(laskuri = 0; laskuri < 4; laskuri++) {
  249.     if(laiteavattu[laskuri]) {
  250.       if(!CheckIO((struct IORequest *)audioioreq[laskuri]))
  251.     AbortIO((struct IORequest *)audioioreq[laskuri]);
  252.       audioioreq[laskuri]->ioa_Request.io_Command = CMD_RESET;
  253.       DoIO((struct IORequest *)audioioreq[laskuri]);
  254.       CloseDevice((struct IORequest *)audioioreq[laskuri]);
  255.     }
  256.     if(audioioreq[laskuri])
  257.     DeleteExtIO((struct IORequest *)audioioreq[laskuri]);
  258.     if(audioport[laskuri]) DeletePort(audioport[laskuri]);
  259.   }
  260.   if(playerport) DeletePort(playerport);
  261.   if(snsn != -1) FreeSignal(snsn);
  262.   playerlopettanut = TRUE;
  263. }
  264.  
  265. struct timerequest *timereq;
  266. BOOL timerauki = FALSE;
  267.  
  268. struct Interrupt sware = { { NULL,NULL,0,32,"MEDSWInt" },NULL,SWareIntr };
  269. struct MsgPort timerport = { { NULL,NULL,NT_MSGPORT,0,NULL },PA_SOFTINT,0,
  270.                 (struct Task *)&sware,{ 0 } };
  271.  
  272. void SWareIntr()
  273. {
  274.     geta4();
  275.     Signal(player,seurnuotsignmsk);
  276.     (void)GetMsg(&timerport);
  277.     timereq->tr_time.tv_micro = askelm;
  278.     timereq->tr_time.tv_secs = 0L;
  279.     SendIO((struct IORequest *)timereq);
  280. }
  281.  
  282. LONG PLRInit() /* returns -1 if error, 0 if ok */
  283. {
  284.     struct Aloitusviesti *alkuviesti;
  285.     askelm = 625000 / song.tempo;
  286.     if(!(plreply = CreatePort(0,0))) return(-1);
  287.     kasky.kasky_msg.mn_Node.ln_Type = NT_MESSAGE;
  288.     kasky.kasky_msg.mn_ReplyPort = plreply;
  289.     kasky.kasky_msg.mn_Length = sizeof(struct Soittokasky);
  290.     if(!(player = CreateTask("MEDPlayer.task",21,(APTR)MEDPlayer,5000))) return(-1);
  291.     WaitPort(plreply);
  292.     alkuviesti = (struct Aloitusviesti *)GetMsg(plreply);
  293.     if(alkuviesti->viesti_tilanne == PIELEENMENI) return(-1);
  294.      NewList(&(timerport.mp_MsgList));
  295.     if(!(timereq = (struct timerequest *)CreateExtIO(&timerport,
  296.         sizeof(struct timerequest)))) return(-1);
  297.     if(OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *)timereq,0))
  298.         return(-1);
  299.     timerauki = TRUE;
  300.     timereq->tr_node.io_Command = TR_ADDREQUEST;
  301.     Cause(&sware);
  302.     if(song.liput & LIPPU_SUODATINPAALLA) ciaa.ciapra &= ~CIAF_LED;
  303.     else ciaa.ciapra |= CIAF_LED;
  304.     return(0);
  305. }
  306.  
  307. void PLRPlaySong()
  308. {
  309.     kasky.kasky_komento = SOITAKAPPALE;
  310.     kasky.kasky_data = 0;
  311.     PutMsg(playerport,(struct Message *)&kasky);
  312.     WaitPort(plreply);
  313.     (void)GetMsg(plreply);
  314. }
  315.  
  316. void PLRStop()
  317. {
  318.     kasky.kasky_komento = SEIS;
  319.     PutMsg(playerport,(struct Message *)&kasky);
  320.     WaitPort(plreply);
  321.     (void)GetMsg(plreply);
  322. }
  323.  
  324. void PLRRemove()
  325. {
  326.     timerport.mp_Flags = PA_IGNORE;
  327.     if(!CheckIO((struct IORequest *)timereq))
  328.         AbortIO((struct IORequest *)timereq);
  329.     if(timerauki) CloseDevice((struct IORequest *)timereq);
  330.     if(timereq) DeleteExtIO((struct IORequest *)timereq);
  331.     ciaa.ciapra &= ~CIAF_LED;
  332.     if(playerport) {
  333.         kasky.kasky_komento = OHJELMANLOPPU;
  334.         PutMsg(playerport,(struct Message *)&kasky);
  335.         WaitPort(plreply);
  336.         (void)GetMsg(plreply);
  337.         while(!playerlopettanut);
  338.     }
  339.     if(plreply) DeletePort(plreply);
  340. }