[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Musical Playback In Aztec C



Musical Playback functions for Aztec C that runs on the apple ][

The ProDOS 8 version will also run nicely on a GS. Code for a ProDOS
demo is
also below as is a SND file converter that runs in MS-DOS.

On the apple, it's all based on clicking the speaker at varying
intervals.
That's why the SID chip on the C64 was so cool!


x--- snip ---x

/*

/* create a proper musical scale for the apple */
/* this is the algorithm that will be used     */
/* june 1991 */
/* tired of flat notes... select a piano scale */

/* Apple Pitch Values  */

int __pitch[5][12]={

/* C    C#    D    D#     E     F    F#     G    G#   A   A#   B */
/* 0    1     2    3      4     5    6      7    8    9   10  11 */

285, 270, 257, 243, 229, 215, 200, 188, 179, 171, 167, 160,
150, 142, 132, 126, 117, 111, 106,  99,  93,  88,  83,  79,
74,  70,  65,  61,  58,  55,  51,   48,  45,  43,  40,  38,
36,  34,  32,  30,  28,  26,  24,   23,  21,  20,  19,  18,
17,  34,  32,  30,  28,  26,  24,   23,  21,  20,  19,  18};

sound(octave,note,duration)
char octave,note,duration;
{
    int j,pit,temp;

    switch(octave)
    {
      case 0:
      case 1: pit= __pitch[0][note];break;

      case 2: pit= __pitch[1][note];break;
      case 3: pit= __pitch[2][note];break;

      case 4: pit= __pitch[3][note];break;
      case 5:
      case 6: pit= __pitch[4][note];break;

      /* silence... try to match the sound loop */
      case 7: pit= 128;
              temp=(1024*duration)/pit;
              NOPER:;  /* loop the required note length */
                     j=pit;
              COUNTING:;
                     if(j--)goto COUNTING;
                     if(temp--)goto NOPER;
              return 0;
            }
temp=(1024*duration)/pit;

TOPPER:;  /* loop the required note length */
#asm
        BIT $C030
#endasm
        j=pit;
COUNTER:;
        if(j--)goto COUNTER;
        if(temp--)goto TOPPER;

        /* wait for the duration specified by pitch */
        /* then click it again                      */

}

x--- snip ---x

play(song)
char *song;
{
    char octave, note, duration;
    int ctr=0;

    while( (octave=song[ctr++])!=255)
    {

      note=song[ctr++];
      duration=song[ctr++];
      sound(octave,note,duration);
    }

}

x--- snip ---x

#include <stdio.h>

int getch();


/* musical array created from file WEASEL.SND */
/* array structure is octave, note, duration */
char WEASEL[]={
 2,  7,  2, 7,  0,  2, 2,  7,  2, 2,  9,  2, 7,  0,  2, 2,  9,  2,
 2, 11,  2, 3,  2,  2, 2, 11,  2, 2,  7,  2, 7,  0,  2, 2,  2,  2,
 2,  7,  2, 7,  0,  2, 2,  7,  2, 2,  9,  2, 7,  0,  2, 2,  9,  2,
 2, 11,  6, 2,  7,  2, 7,  0,  2, 2,  2,  2, 2,  7,  2, 7,  0,  2,
 2,  7,  2, 2,  9,  2, 7,  0,  2, 2,  9,  2, 2, 11,  2, 3,  2,  2,
 2, 11,  2, 2,  7,  2, 7,  0,  4, 3,  4,  2, 7,  0,  4, 2,  9,  2,
 7,  0,  2, 3,  0,  2, 2, 11,  6, 2,  7,  2, 7,  0,  4, 3,  7,  2,
 7,  0,  2, 3,  7,  2, 3,  4,  2, 7,  0,  2, 3,  7,  2, 3,  6,  2,
 3,  9,  2, 3,  6,  2, 3,  2,  2, 7,  0,  4, 3,  7,  2, 7,  0,  2,
 3,  7,  2, 3,  4,  2, 7,  0,  2, 3,  7,  2, 3,  6,  6, 3,  2,  2,
 7,  0,  2, 2, 11,  2, 3,  0,  2, 7,  0,  2, 2, 11,  2, 3,  0,  2,
 7,  0,  2, 3,  2,  2, 3,  4,  2, 7,  0,  2, 3,  6,  2, 3,  7,  2,
 7,  0,  4, 3,  4,  2, 7,  0,  4, 2,  9,  2, 7,  0,  2, 3,  0,  2,
 2, 11,  6, 2,  7,  2,
'\xff','\xff','\xff'};


/* musical array created from file FROG.SND */
/* array structure is octave, note, duration */
char FROG[]={
 3,  0,  6, 3,  5,  3, 3,  5,  3, 3,  5,  3, 3,  5,  3, 3,  5,  3,
 3,  5,  3, 3,  9,  6, 3,  7,  6, 3,  2,  6, 3,  0,  6, 3,  5, 12,
 7,  0,  6, 3,  0,  6, 3,  5, 12, 7,  0, 12, 3,  9,  3, 4,  0,  3,
 4,  0,  3, 4,  0,  3, 4,  0,  3, 4,  0,  3, 4,  2,  6, 4,  0,  6,
 3,  9,  6, 3,  5,  6, 3,  7,  6, 3,  5,  6, 3,  5,  6, 3,  5,  3,
 3,  7,  3, 3,  9,  6, 3,  5,  6, 3,  2,  6, 3,  0,  6, 3,  5, 12,
 7,  0,  6, 3,  0,  6, 3,  5, 12,
'\xff','\xff','\xff'};

/* musical array created from file bug.snd */
/* array structure is octave, note, duration */
char bug[]={
 2,  2,  1, 7,  0,  1, 2,  2,  1, 7,  0,  1, 2,  2,  1, 7,  0,  1,
 2,  7,  1, 7,  0,  5, 2, 11,  1, 7,  0,  3, 2,  2,  1, 7,  0,  1,
 2,  2,  1, 7,  0,  1, 2,  2,  1, 7,  0,  1, 2,  7,  1, 7,  0,  5,
 2, 11,  1, 7,  0,  5, 1,  2,  1, 7,  0,  1, 1,  2,  1, 7,  0,  1,
 1,  7,  1, 7,  0,  3, 2,  7,  1, 7,  0,  1, 2,  7,  1, 7,  0,  1,
 2,  6,  1, 7,  0,  1, 2,  6,  1, 7,  0,  1, 2,  4,  1, 7,  0,  1,
 2,  4,  1, 7,  0,  1, 2,  2,  8, 7,  0,  2, 2,  2,  1, 7,  0,  1,
 2,  2,  1, 7,  0,  1, 2,  2,  1, 7,  0,  1, 2,  6,  1, 7,  0,  5,
 2,  9,  1, 7,  0,  3, 2,  2,  1, 7,  0,  1, 2,  2,  1, 7,  0,  1,
 2,  2,  1, 7,  0,  1, 2,  6,  1, 7,  0,  5, 2,  9,  1, 7,  0,  5,
 1,  9,  1, 7,  0,  1, 1,  9,  1, 7,  0,  1, 1,  2,  1, 7,  0,  3,
 3,  2,  2, 3,  4,  2, 3,  2,  2, 3,  0,  2, 2, 11,  2, 2,  9,  2,
 2,  7,  8,
'\xff','\xff','\xff'};

main()
{
   int c=0;

   scr_clear();
   scr_curs(1,0);
   printf("SONGSTER by Bill Buckels 2007\n");
   printf("1 - Pop Goes The Weasel\n");
   printf("2 - Froggy Went a Courting\n");
   printf("3 - La Cucaracha\n");
   printf("ESC Exit to PRODOS\n");

   for(;;) {

      c = getch();
      if (c == 27)break;

      switch(c)
      {
    case 49: play(WEASEL); break;
    case 50: play(FROG); break;
    case 51: play(bug); break;
    default: sound(0,0,3);

   }


   }
   scr_clear();
   _exit();
}

x--- snip ---x

And here's how I made those... this is in 16 bit IBM C

/* converts binary musical files of type .SND   */
/* to character arrays for embedding in C code  */
/* a binary file of the array is also created.  */
/* the output files are music macros for the apple II */


#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>

char far *soundbuffer;

#define S_IWRITE    0000200     /* write permission, owner   */

int makefile(char *filename,int length)
{
int fh;

if((fh = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IWRITE)) ==
-1)
        return 0;
    write(fh,(char *)&soundbuffer[0],length);
    if(close(fh) == -1)
    return 0;
}

int xplay(int xfrequency)
{
  if(xfrequency < 64 || xfrequency > 4096 )
  {
    /* if we are out of range don't play anything */
    return -1;
  }

  /* octave 0 */
  if(xfrequency<127)
  {
  if(xfrequency<67 ) return  0 ;
  if(xfrequency<71 ) return  1 ;
  if(xfrequency<76 ) return  2 ;
  if(xfrequency<80 ) return  3 ;
  if(xfrequency<85 ) return  4 ;
  if(xfrequency<90 ) return  5 ;
  if(xfrequency<96 ) return  6 ;
  if(xfrequency<101) return  7 ;
  if(xfrequency<107) return  8 ;
  if(xfrequency<114) return  9 ;
  if(xfrequency<120) return  10;
                     return  11;
  }

  /* first octave */
  if(xfrequency<255)
  {
  if(xfrequency<136) return  12;
  if(xfrequency<143) return  13;
  if(xfrequency<152) return  14;
  if(xfrequency<160) return  15;
  if(xfrequency<170) return  16;
  if(xfrequency<180) return  17;
  if(xfrequency<190) return  18;
  if(xfrequency<202) return  19;
  if(xfrequency<215) return  20;
  if(xfrequency<227) return  21;
  if(xfrequency<240) return  22;
                     return  23;
  }

  /* second octave */
  if(xfrequency<512)
  {
   if(xfrequency<270)return 24;
   if(xfrequency<286)return 25;
   if(xfrequency<304)return 26;
   if(xfrequency<322)return 27;
   if(xfrequency<340)return 28;
   if(xfrequency<360)return 29;
   if(xfrequency<382)return 30;
   if(xfrequency<406)return 31;
   if(xfrequency<428)return 32;
   if(xfrequency<454)return 33;
   if(xfrequency<480)return 34;
                     return 35;
   }

   /* third octave */

  if(xfrequency<1024)
  {
  if(xfrequency<540)return 36 ;
  if(xfrequency<572)return 37 ;
  if(xfrequency<605)return 38 ;
  if(xfrequency<643)return 39 ;
  if(xfrequency<680)return 40 ;
  if(xfrequency<720)return 41 ;
  if(xfrequency<765)return 42 ;
  if(xfrequency<810)return 43 ;
  if(xfrequency<855)return 44 ;
  if(xfrequency<910)return 45 ;
  if(xfrequency<965)return 46 ;
                    return 47 ;
  }

  /* fourth octave */

  if(xfrequency<2048)
  {
  if(xfrequency<1080) return  48;
  if(xfrequency<1144) return  49;
  if(xfrequency<1210) return  50;
  if(xfrequency<1286) return  51;
  if(xfrequency<1340) return  52;
  if(xfrequency<1440) return  53;
  if(xfrequency<1530) return  54;
  if(xfrequency<1620) return  55;
  if(xfrequency<1710) return  56;
  if(xfrequency<1820) return  57;
  if(xfrequency<1930) return  58;
                      return  59;
  }

  /* fifth octave */
  /* sixth octave ignored */
   if(xfrequency<2160)return 60;
   if(xfrequency<2288)return 61;
   if(xfrequency<2420)return 62;
   if(xfrequency<2572)return 63;
   if(xfrequency<2680)return 64;
   if(xfrequency<2880)return 65;
   if(xfrequency<3060)return 66;
   if(xfrequency<3240)return 67;
   if(xfrequency<3420)return 68;
   if(xfrequency<3640)return 69;
   if(xfrequency<3860)return 70;
                      return 71;

}

main(int argc, char *argv[])
{
   FILE *fp,*fp2;
   char *wordptr;
   char *ptr;
   long target;
   int bincounter=0;
   int *intptr;

   int octave, note;
   int frequency,duration,counter=0;
   char scratchbuffer[128],writebuffer[128],binbuffer[128];

   if(argc!=2)
   {
    printf("SND filename required...");
    exit(0);
    }

   if((fp=fopen(argv[1],"rb"))==NULL)
   {
    perror(argv[1]);
    exit(0);
    }



   strcpy(scratchbuffer,argv[1]);
   wordptr=strtok(scratchbuffer,".");
   sprintf(writebuffer,"%s.TXT",scratchbuffer);
   sprintf(binbuffer,"%s.BIN",scratchbuffer);

   fp2=fopen(writebuffer,"w");


        target=filelength(fileno(fp))+8;
        soundbuffer = _fmalloc(target);
        memset(soundbuffer,0,target);
        ptr= (char *)&soundbuffer[2];

   fprintf(fp2,
   "/* musical array created from file %s */\n",argv[1]);
   fprintf(fp2,
   "/* array structure is octave, note, duration */\n");
   fprintf(fp2,
   "char %s[]={\n",scratchbuffer);

    while((frequency=getw(fp))!=-1){
         duration=fgetc(fp);

         if((frequency=xplay(frequency))<0)
         {
            octave=7;
            note  =0;
         }
         else
         {
            octave = frequency/12;
            note   = frequency%12;
        }
         fprintf(fp2,"%2d, %2d, %2d,",octave,note,duration);

         *ptr++=(char)octave;
         *ptr++=(char)note;
         *ptr++=(char)duration;
         bincounter+=3;

         counter++;
         if(counter==6){
            fprintf(fp2,"\n");
            counter=0;
         }
         }


   /* use 255 as the terminator... */
   fprintf(fp2,"\n\'\\xff\',\'\\xff\',\'\\xff\'};\n",scratchbuffer);

         *ptr++='\xff';
         *ptr++='\xff';
         *ptr++='\xff';
         bincounter+=3;

   fclose(fp);
   fclose(fp2);
   intptr=(int *)&soundbuffer[0];
   *intptr=bincounter;
   makefile(binbuffer,bincounter+2);
   _ffree(soundbuffer);
   exit(0);

}