home *** CD-ROM | disk | FTP | other *** search
- /*
- * MUSIC.C
- * Usage: RUN386 -CALLBUFS 1 MUSIC
- * Purpose: demonstrates interfacing between assembly
- * language and NDP C programs. The NDP code calls
- * protected mode assembly language routines. These
- * in turn communicate with a real mode assembly
- * language routine. These assembly routines are used
- * to control the underlying PC hardware. They do so
- * by reading from and writing to ports and by
- * taking over the timer tick interrupt.
- * Copyright (C) MicroWay, Inc., 1989
- *
- */
-
- #include <stdio.h>
-
- #define WHOLE 64
- #define WHOLEDOT WHOLE+WHOLE/2
- #define HALF WHOLE/2
- #define HALFDOT WHOLE/2+WHOLE/4
- #define QUARTER WHOLE/4
- #define QUARTERDOT WHOLE/4+WHOLE/8
- #define EIGHTH WHOLE/8
- #define EIGHTHDOT WHOLE/8+WHOLE/16
- #define SIXTEENTH WHOLE/16
- #define SIXTEENTHDOT WHOLE/16+WHOLE/32
- #define THIRTYSECOND WHOLE/32
- #define THIRTYSECONDDOT WHOLE/32+WHOLE/64
- #define SIXTYFOURTH WHOLE/64
- #define NONE 0
-
- #define ERROR_VAL -1
-
- /* This example plays musical tunes. The tune is
- * represented by an array of structures. Each
- * structure represents a note: the first field
- * gives the note's duration and the second field
- * denotes its name. Each name represents a note
- * in the tempered chromatic scale. The names take
- * one of three forms:
- * 'A-G' ['#'|'b'] '0-8'
- * or 'A-G' '0-8'
- * or 'R'
- * The first letter of every note must be in upper
- * case - lower case 'b' is reserved to indicate the
- * tone is a flat. If the note is a sharp or a flat,
- * the second character is a '#' or a 'b' and the
- * third character is a digit indicating the octave.
- * If the note is not a sharp or a flat, then the
- * second character is a digit indicating the octave.
- * The only other character allowed is an upper case
- * 'R', to denote rest or pause. Every name occupies
- * 4 bytes and has 1, 2 or 3 printable characters, the
- * rest being null bytes(s) (value 0, not character '0').
- * Since this is a tempered scale, the frequency of
- * adjacent sharps and flats is the same, e.g., G#0 and
- * Ab0 have the same pitch.
- *
- */
-
- typedef struct {
- int duration; /* time to sound the NOTE */
- char name[4]; /* name of the NOTE */
- } NOTE;
-
-
- /* The following data structure holds information about
- * a tone in the tempered chromatic scale. There is an
- * array of such structures defined in the assembly
- * language module PLAY.S. Each structure holds
- * information about a tone in the tempered chromatic
- * scale and the entire array spans eight octaves.
- * The first field of these is the name of the tone
- * and takes essentially the same form as the name
- * field in the NOTE structure. The tones range from
- * C0 to C8, middle C being C4. The second field is
- * the frequency of the tone, e.g., A4 is 440 Hertz.
- * The third field is the count between pulses to the
- * speaker and is inversely proportional to the
- * frequency. Notes C0 to E0 will not play, because
- * their frequency is too low (i.e., their count is
- * too high and occupies more than 16 bits) - using
- * them will generate an error. For details on these
- * structures, see PLAY.S.
- *
- */
- typedef struct {
- char name[4]; /* name of the tone */
- float freq; /* frequency of the tone */
- int count; /* Timer freq div by tone freq */
- } TONE;
-
- /* Next, the tune to be played */
- NOTE tune [] = {
- WHOLE, "C5",
- HALF, "E5",
- WHOLE, "G5",
- HALF, "E5",
- QUARTER, "R",
- WHOLE, "F4",
- QUARTER, "D5",
- HALF, "B4"
- WHOLE, "C5",
- NONE, ""
- };
-
- extern TONE tcs []; /* Octaves in the Tempered Chromatic Scale */
- extern void init_tcs();
- extern int init_timer_isr();
- extern int play();
- extern int restore_timer_isr();
-
- void main ()
-
- {
- int i;
-
- init_tcs(); /* initialize tempered chromatic scales */
-
- /* display initialized tempered chromatic scales */
- i = 0;
- while (*tcs[i].name) {
- printf ("%s\t%4.2f\t%d\n",tcs[i].name,
- tcs[i].freq,tcs[i].count);
- i++;
- }
-
- /* set up new timer interrupt service routine */
- i = init_timer_isr();
- if (i == ERROR_VAL) {
- printf ("Problem in initializing new timer ISR\n");
- printf ("Be sure to invoke RUN386.EXE with ");
- printf ("-CALLBUFS equal to at least 1\n");
- exit(1);
- }
-
- /* play a little tune */
- i = play(tune);
- if (i == ERROR_VAL) {
- printf ("Problem in play function\n");
- exit(1);
- }
-
- /* restore old timer interrupt service routine */
- i = restore_timer_isr();
- if (i == ERROR_VAL) {
- printf ("Problem in restoring old timer ISR\n");
- exit(1);
- }
-
- exit(0);
- }
-
-