home *** CD-ROM | disk | FTP | other *** search
- /*
- DEMO2.C, Low level demonstration program.
-
- Copyright Ad Lib Inc, 1988.
-
- 17-Oct-88, Dale Glowinski, Marc Savary, Ad Lib Inc.
-
- This is a demonstration program which shows an alternate method for
- generating sound. Its general strategy is to start a sound, and then
- adjust it for volume or frequency at regular intervals. This eliminates
- the need to use a music (.ROL) file which would be played as a piece
- of music. (However, before coding a sound effect, it is a good idea
- to develop an approximation of the desired sound using the
- Visual Composer.) This method is only useful for sounds which are
- repetitive or continuous.
-
- The program uses several routines in ADLIB.C, which is slightly
- different from the original version, but only in that several "static"
- statements have been removed to make several lower level routines
- available to this module.
-
- Compiled with Microsoft C, V5.0, as follows:
- cl -AS -Zi -Ox -Gs demo2.c adlib.obj
-
- Some of the programming was done in a rather arbitrary fashion in order
- to save time and to keep the code as simple as possible:
- - Volumes are set to a value which was based on whatever sounded best.
- Depending on what you wish to do, variables and passing values might
- be in order. Ditto for pitches.
- - A simple counter was used to create the timing, so that the speed
- of the sounds produced by the executable file will vary with the
- speed of the processor. Certainly, one would have to use the real
- timer in a real application. (The timing counter can be changed by
- using the "/t" execution option.)
-
- */
-
-
- #include <stdlib.h>
- #include <fcntl.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #include <io.h>
- #include <string.h>
-
- #include "adlib.h"
-
- /* synthesizer modes */
- #define MELODIC 0
- #define PERCUSSIVE 1
- #define MODE MELODIC
-
- /* computer keyboard scan codes */
- #define LEFT 75
- #define RIGHT 77
- #define UP 72
- #define DOWN 80
- #define PAGEUP 73
- #define PAGEDOWN 81
-
- /* flags used for Set_Instrument() */
- #define RELEASE 1
- #define NO_RELEASE 0
-
- #if (MODE == PERCUSSIVE)
- #define NR_VOICES 11
- #else
- #define NR_VOICES 9
- #endif
-
- #define SIREN 0
- #define COPTER 1
- #define PLANEa 2
- #define PLANEb 3
- #define BOMBa 4
- #define BOMBb 5
- #define BOMBc 6
- #define BOMBd 7
- #define JETa 8
- #define JETb 9
- #define JETc 10
- #define JETd 11
- #define JETe 12
- #define FAKE_ID 13
- #define NR_SOUNDS 14
-
- /* These are declared in ADLIB.C */
- extern char slotVoice [][2];
- extern char slotPerc [][2];
- extern NoteOff (int);
- extern NoteOn (int);
-
- /* Timbre information for each sound */
- unsigned char op [NR_SOUNDS][2][30];
-
- /* These arrays contain information for each sound */
- unsigned int fnum [NR_SOUNDS];
- int octave [NR_SOUNDS];
- int volume [NR_SOUNDS];
- int myVoice [NR_SOUNDS]; /* voice number being used */
-
- int voices [NR_VOICES]; /* used to allocate voices */
-
- int mode; /* card mode */
- int start_time = 100;
- int timing = 100;
-
- /* These routines are redefined to clarify their appearance in the code. */
- #define SetVoiceVolume(x,y) SetVoiceVolume(myVoice[x],y)
- #define NoteOn(x) NoteOn(myVoice[x]);
- #define NoteOff(x) NoteOff(myVoice[x]);
-
-
- main( argc, argv)
- int argc;
- char *argv[];
- {
- int i;
- extern SoundColdInit();
-
- for ( i = 1, argv++; i < argc; i++, argv++)
- {
- strupr ( *argv);
- if ( ! strncmp( "/T", *argv, 2)) start_time = atoi (*argv + 2);
- }
-
- Instrument_Init ();
- Demo_Init ();
-
- Choose_Sound (); /* user interface routine */
-
- Stifle ();
- SoundColdInit (0x388);
- }
-
-
- /*-----------------------------------------------------------------------*/
- float frq_low [12] = {16.352, 17.324, 18.354, 19.445, 20.601, 21.826,
- 23.124, 24.499, 25.956, 27.500, 29.135, 30.867};
-
- unsigned int freq_nums [12];
-
- /*
- frq_low is a table of frequencies for the first 12 pitches. If Note_A is
- one octave higher than Note_B, then the frequency of Note_B is twice that
- of Note_A. We can then use this relationship to find the frequency for any
- note by multiplying the value in frq_low (pitch % 12) by a power of 2, where
- the power of two is the octave (b = pitch / 12 - 1). This can be expressed
- as follows:
- frequency = frq_low [pitch % 12] * (2 ** b)
-
- freq_nums is a table of f-numbers given a pitch (modulo 12). The card uses
- the f-number and the octave bits to determine the pitch it will output.
- Note that the f-numbers preserve the same power of 2 relationship between
- octaves as for frequency.
-
- The f-numbers can be calculated using a transformed version of the formula
- on page 47 of the programmer's manual:
- 1. fnum = freq * (2 ** 20-b) / 50 kHz
- 2. fnum = freq * (2 ** 20) * (2 ** -b) / 50000 (from 1)
- 3. fnum = freq * 20.971 * (2 ** -b) (from 2)
- 4. freq = frq_low [pitch % 12] * (2 ** b)
- 5. fnum = frq_low [pitch % 12] * 20.971 (from 3 & 4)
- (b is the octave less 1 so that 0 <= b <= 7.)
- Thus, the f-numbers are the integer results of multiplying the values in
- frq_low by 20.971.
-
- This gives a range of 343 to 685 for the f-numbers. However, the f-number
- register is 9 bits and can hold an unsigned value of 0 to 1023. The range
- outside of 343-685 can be used, but it should be noted that in the lower
- ranges, a small change in f-number will yield a larger change in output
- frequency. By always using the range 343-685, one will have the same
- incremental degree of control between pitches regardless of the octave.
- */
-
-
- /*-----------------------------------------------------------------------
- This sets up the table of f-numbers for a given pitch. This actually could
- be calculated beforehand and the array initialized to the calculated values,
- but it is done here for illustrative purposes. */
-
- SetUp_FNums ()
- {
- int n;
- float f;
- for (n=0; n < 12; n++) {
- f = frq_low [n] * 20.971;
- freq_nums [n] = (unsigned int) f;
-
- /* Round number up if necessary */
- f -= (float) freq_nums [n];
- if (f > 0.5) freq_nums [n]++;
- }
- }
-
-
- /*-----------------------------------------------------------------------
- This does a note-on for the passed f-num. If the note is already on,
- only the frequency of the note will change. */
-
- Out_Freq (sound_ID, fNbr, octave)
- unsigned int sound_ID;
- unsigned int fNbr; /* f-number for card */
- unsigned int octave;
- {
- unsigned int t1;
-
- octave -= 1;
- while (fNbr > 1023) {
- fNbr >>= 1;
- octave++;
- }
- while (fNbr < freq_nums [0]) {
- fNbr <<= 1;
- octave--;
- }
-
- SndOutput (0xA0 + myVoice [sound_ID], fNbr);
-
- t1 = 0x20 | (octave << 2) | (0x3 & (fNbr >> 8));
- SndOutput (0xB0 + myVoice [sound_ID], t1);
- return (octave);
- }
-
-
- /*-----------------------------------------------------------------------
- Initialize the card and set up several variables. */
-
- Demo_Init ()
- {
- extern SoundColdInit();
- int n;
- timing = start_time;
-
- n = SoundColdInit (0x388);
- if (!n) {
- printf ("\nSound card not found.\n");
- exit (0);
- }
- mode = MODE;
- SetMode (mode);
-
- SetUp_FNums ();
- for (n=0; n < NR_VOICES; n++) voices [n] = -1;
- for (n=0; n < NR_SOUNDS; n++) {
- myVoice [n] = -1;
- volume [n] = 0x50;
- fnum [n] = 0;
- }
- }
-
-
- /*-----------------------------------------------------------------------
- Given a pitch, return its f-number. */
-
- #define Pitch_to_Fnum(x) (freq_nums [x % 12])
-
- /*
- unsigned int Pitch_to_Fnum (pitch)
- int pitch;
- {
- return (freq_nums [pitch % 12]);
- }
- */
-
-
- /*-----------------------------------------------------------------------
- If the release values have been set to zero, a sound will continue to be
- heard even if a note-off is done. This routine resets the release values
- for every voice to an arbitrary value in order to shut them off. */
-
- Stifle_Voice (sound_ID)
- int sound_ID;
- {
- int voice;
- voice = myVoice [sound_ID];
- if (voice == -1) return;
-
- SetASlotParam (slotVoice [voice][0], prmRelease, 10);
- SetASlotParam (slotVoice [voice][1], prmRelease, 10);
- NoteOff (sound_ID);
- Free_Voice (sound_ID);
- }
-
- /* Silence all voices. */
- Stifle ()
- {
- int n;
- for (n=0; n < NR_SOUNDS; n++) Stifle_Voice (n);
- }
-
-
- /*-----------------------------------------------------------------------
- Finds an available voice and sets the approriate entry in the myVoice table.
- Returns 0 if no more voices available else returns 1.*/
-
- Alloc_Voice (sound_ID)
- int sound_ID;
- {
- register int n;
- for (n=0; n < NR_VOICES && voices [n] != -1; n++);
- if (n >= NR_VOICES) return (0);
- voices [n] = sound_ID;
- myVoice [sound_ID] = n;
- return (1);
- }
-
- /* De-allocate the voice which was allocated in the above routine. */
- Free_Voice (sound_ID)
- int sound_ID;
- {
- register int n;
- n = myVoice [sound_ID];
- if (n == -1) return;
- voices [n] = -1;
- myVoice [sound_ID] = -1;
- }
-
-
- /*-----------------------------------------------------------------------
- Read the .INS file into the appropriate operator buffers. */
-
- Read_Ins_File (name, sound_ID)
- char *name;
- int sound_ID;
- {
- unsigned char *op0, *op1;
- int file, n, ok;
- unsigned char temp [20];
-
- op0 = op [sound_ID][0];
- op1 = op [sound_ID][1];
-
- file = open (name, O_RDONLY & O_RAW);
- if (file < 0) {
- printf ("Can't open %s\n", name);
- return (0);
- }
- read (file, temp, 2);
- for (n=0; n < 13; n++) read (file, &op0 [n], 2);
- for (n=0; n < 13; n++) read (file, &op1 [n], 2);
- ok = read (file, temp, 20);
- if (ok) {
- read (file, &op0 [prmWaveSel], 2);
- read (file, &op1 [prmWaveSel], 2);
- }
- close (file);
- return (1);
- }
-
-
- /*-----------------------------------------------------------------------
- Given the timbre parameters, initialize a voice. NOTE: The real voice
- number is passed here, not the sound's ID code. */
-
- SetUp_Timbre (voice, op0, op1)
- int voice;
- unsigned char *op0, *op1;
- {
- SetCharSlotParam (slotVoice [voice][0], op0, op0 [prmWaveSel]);
- if (mode == MELODIC || voice <= BD)
- SetCharSlotParam (slotVoice [voice][1], op1, op1 [prmWaveSel]);
- }
-
-
- /*-----------------------------------------------------------------------
- Set up an instrument for the passed voice. Resets the release values
- according to the passed flag. This routine is similar to SetVoiceTimbre()
- in ADLIB.C. */
-
- Set_Instrument (sound_ID, rel_flag)
- int sound_ID, rel_flag;
- {
- int ok, voice, rel_value;
- unsigned char *op0, *op1;
-
- ok = Alloc_Voice (sound_ID);
- if (!ok) {
- printf ("No more voices available\n");
- return (0);
- }
- voice = myVoice [sound_ID];
-
- op0 = op [sound_ID][0];
- op1 = op [sound_ID][1];
-
- /* Setting the release values to zero has the effect of making the note
- play forever. */
- if (rel_flag) rel_value = 1;
- else rel_value = 0;
- op0 [prmRelease] = rel_value;
- op1 [prmRelease] = rel_value;
-
- SetUp_Timbre (voice, op0, op1);
-
- SetVoiceVolume (sound_ID, 0x60);
- return (1);
- }
-
-
- /*-----------------------------------------------------------------------
- Read in all of the required .INS files. */
-
- Instrument_Init ()
- {
- Read_Ins_File ("instr\\jet11a.ins", JETa);
- Read_Ins_File ("instr\\jet11b.ins", JETb);
- Read_Ins_File ("instr\\oboe1.ins", JETc);
- Read_Ins_File ("instr\\siren2a.ins", JETd);
- Read_Ins_File ("instr\\siren2a.ins", JETe);
-
- Read_Ins_File ("instr\\flute.ins", BOMBa);
- Read_Ins_File ("instr\\plane1.ins", BOMBb);
- Read_Ins_File ("instr\\plane1.ins", BOMBc);
- Read_Ins_File ("instr\\plane1.ins", BOMBd);
-
- Read_Ins_File ("instr\\plane3.ins", PLANEa);
- Read_Ins_File ("instr\\plane3.ins", PLANEb);
-
- Read_Ins_File ("instr\\siren1.ins", SIREN);
- Read_Ins_File ("instr\\helico3.ins", COPTER);
- }
-
-
- /*------------------------------------------------------------------------
- This creates a delay in a rather simple manner in order to create a fake
- timer. In a real application, a scheduling or a timer routine would have
- call the Internal_Driver() routine at the appropriate moment. */
-
- delay (n)
- int n;
- {
- int i, j = 5;
- for (i=0; i < (n * 100); i++) j %= 23;
- }
-
-
- /*********************************** Jet *********************************/
-
- Drive_Jet ()
- {
- static int flag = 1;
- static int n = -0x40;
- if (!fnum [JETa]) return;
-
- if (flag) {
- /* raise the volume and pitch */
- SetVoiceVolume (JETa, 0x50+n);
- SetVoiceVolume (JETb, 0x60+n);
- SetVoiceVolume (JETc, 0x30+(n/2));
- SetVoiceVolume (JETd, 0x60+n);
- SetVoiceVolume (JETe, 0x45+n);
- Out_Freq (JETa, fnum [JETa]+n, octave [JETa]);
- Out_Freq (JETb, fnum [JETb]+n, octave [JETb]);
- Out_Freq (JETd, fnum [JETd]+n, octave [JETd]);
- Out_Freq (JETe, fnum [JETe]+n, octave [JETe]);
- n++;
- if (n >= 0x1f) flag = 0;
- }
- else /* flag is 0 */ {
- /* lower the volume and pitch */
- SetVoiceVolume (JETa, 0x50+n);
- SetVoiceVolume (JETb, 0x60+n);
- SetVoiceVolume (JETc, 0x30+(n/2));
- SetVoiceVolume (JETd, 0x60+n);
- SetVoiceVolume (JETe, 0x45+n);
- Out_Freq (JETa, fnum [JETa]+n, octave [JETa]);
- Out_Freq (JETb, fnum [JETb]+n, octave [JETb]);
- Out_Freq (JETd, fnum [JETd]+n, octave [JETd]);
- Out_Freq (JETe, fnum [JETe]+n, octave [JETe]);
- n--;
- if (n <= -0x40) {
- /* "shut off" the jet: set variables to zero */
- flag = 1;
- fnum [JETa] = 0;
- fnum [JETb] = 0;
- fnum [JETc] = 0;
- fnum [JETd] = 0;
- fnum [JETe] = 0;
- Stifle_Voice (JETa);
- Stifle_Voice (JETb);
- Stifle_Voice (JETc);
- Stifle_Voice (JETd);
- Stifle_Voice (JETe);
- }
- }
- }
-
-
- /*-----------------------------------------------------------------------
- This needs five voices to get a good effect. JET11A.INS and JET11B.INS
- alone have been described as being like a vacuum cleaner. But if ever
- you need a vacuum cleaner sound... */
-
- Jet ()
- {
- int n, ok;
- if (fnum [JETa]) return;
-
- Set_Instrument (JETa, NO_RELEASE);
- Set_Instrument (JETb, NO_RELEASE);
- Set_Instrument (JETc, NO_RELEASE);
- Set_Instrument (JETd, NO_RELEASE);
- ok = Set_Instrument (JETe, NO_RELEASE);
-
- if (!ok) {
- for (n=JETa; n < JETe; n++) Free_Voice (n);
- return;
- }
-
- fnum [JETa] = Pitch_to_Fnum (52);
- fnum [JETb] = Pitch_to_Fnum (88);
- fnum [JETc] = Pitch_to_Fnum (16);
- fnum [JETd] = Pitch_to_Fnum (100);
- fnum [JETe] = Pitch_to_Fnum (101);
- octave [JETa] = 52 / 12;
- octave [JETb] = 88 / 12;
- octave [JETc] = 1;
- octave [JETd] = 100 / 12;
- octave [JETe] = 101 / 12;
-
- /* The pitch of JETc does not vary, so it turned on on here. The other
- voices are output in Drive_Jet(). */
- SetVoiceVolume (JETc, 0);
- Out_Freq (JETc, fnum [JETc], octave [JETc]);
- Drive_Jet ();
-
- printf ("Jet started\n");
- }
-
-
- /*********************************** Bomb ********************************/
-
- unsigned bomb_low;
- int wait_time;
-
- Drive_Bomb ()
- {
- if (!fnum [BOMBa]) return;
-
- if (fnum [BOMBa] > bomb_low) {
- /* Decrease pitch of bomb falling sound */
- fnum [BOMBa] -= 4;
- Out_Freq (BOMBa, fnum [BOMBa], octave [BOMBa]);
- }
- else {
- if (!wait_time) {
- /* Shut off the flute (bomb falling sound) */
- Stifle_Voice (BOMBa);
-
- /* Turn on the exploding sound. The more voices which can be used
- here, the better the effect, although the minimum is two voices.
- For each voice added, set the pitch a half-tone above the
- previous voice. */
- Out_Freq (BOMBb, fnum [BOMBb], octave [BOMBb]);
- Out_Freq (BOMBc, fnum [BOMBc], octave [BOMBc]);
- Out_Freq (BOMBd, fnum [BOMBd], octave [BOMBd]);
- wait_time = 160;
- }
- else { /* wait to let sound fade, otherwise it may get cut off */
- wait_time--;
- if (!wait_time) { /* wait has expired, free voices */
- timing += 5;
- fnum [BOMBa] = 0;
- Stifle_Voice (BOMBb);
- Stifle_Voice (BOMBc);
- Stifle_Voice (BOMBd);
- }
- }
- }
- }
-
- /*-----------------------------------------------------------------------*/
-
- Bomb ()
- {
- int new_oct, ok;
- unsigned char c;
-
- if (!fnum [BOMBa]) {
- Set_Instrument (BOMBb, RELEASE);
- Set_Instrument (BOMBc, RELEASE);
- Set_Instrument (BOMBd, RELEASE);
- ok = Set_Instrument (BOMBa, NO_RELEASE);
- if (!ok) {
- Free_Voice (BOMBb);
- Free_Voice (BOMBc);
- Free_Voice (BOMBd);
- return;
- }
-
- timing -= 5;
- fnum [BOMBb] = Pitch_to_Fnum (12);
- fnum [BOMBc] = Pitch_to_Fnum (13);
- fnum [BOMBd] = Pitch_to_Fnum (14);
- octave [BOMBb] = 1;
- octave [BOMBc] = 1;
- octave [BOMBd] = 1;
- SetVoiceVolume (BOMBb, 0x7f);
- SetVoiceVolume (BOMBc, 0x7f);
- SetVoiceVolume (BOMBd, 0x7f);
- SetVoiceVolume (BOMBa, volume [BOMBa]);
- }
-
- octave [BOMBa] = 95 / 12;
- fnum [BOMBa] = Pitch_to_Fnum (95);
- bomb_low = fnum [BOMBa] >> 2;
- wait_time = 0;
-
- Out_Freq (BOMBa, fnum [BOMBa], octave [BOMBa]);
-
- /* Read input from keyboard */
- printf ("\n Bomb: press spacebar to exit, 'S' to silence ");
- do {
- while (! kbhit ())
- Internal_Driver ();
- c = getch ();
- if (c) {
- c = toupper (c);
- if (c == 'S') {
- timing += 5;
- Stifle_Voice (BOMBa);
- Stifle_Voice (BOMBb);
- Stifle_Voice (BOMBc);
- Stifle_Voice (BOMBd);
- fnum [BOMBa] = 0;
- c = ' ';
- }
- }
- else {
- c = getch ();
- }
- }
- while (c != ' ');
- }
-
-
- /********************************* Airplane ******************************/
-
- Drive_Airplane ()
- {
- /* Here, one could adjust the pitch up and down slightly in order to
- give the sound a more pronounced whine. */
- }
-
-
- /*-----------------------------------------------------------------------*/
-
- Airplane ()
- {
- static int inc = 6;
- static pitch = 30;
- int n, new_oct, ok;
- unsigned char c;
-
- if (!fnum [PLANEb]) {
- ok = Set_Instrument (PLANEa, NO_RELEASE);
- if (!ok) return;
- ok = Set_Instrument (PLANEb, NO_RELEASE);
- if (!ok) {
- Free_Voice (PLANEa);
- return;
- }
-
- timing -= 5;
- volume [PLANEb] = volume [PLANEa] * 3 / 4;
- octave [PLANEa] = octave [PLANEb] = pitch / 12;
- fnum [PLANEa] = Pitch_to_Fnum (pitch);
- fnum [PLANEb] = fnum [PLANEa] + 2;
-
- SetVoiceVolume (PLANEa, volume [PLANEa]);
- SetVoiceVolume (PLANEb, volume [PLANEb]);
- Out_Freq (PLANEa, fnum [PLANEa], octave [PLANEa]);
- }
-
- /* Read keyboard input */
- printf ("\nAirplane: press spacebar to exit, 'S' to silence ");
- do {
- while (! kbhit ())
- Internal_Driver ();
- c = getch ();
- if (c) {
- c = toupper (c);
- if (c == 'S') {
- timing += 5;
- Stifle_Voice (PLANEa);
- Stifle_Voice (PLANEb);
- fnum [PLANEa] = 0;
- fnum [PLANEb] = 0;
- c = ' ';
- }
- }
- else {
- c = getch ();
- switch (c) {
- case LEFT:
- /* Decrease volume */
- if (volume [PLANEa] == 0) break;
- volume [PLANEa] -= 2;
- volume [PLANEb] = volume [PLANEa] * 3 / 4;
- SetVoiceVolume (PLANEa, volume [PLANEa]);
- SetVoiceVolume (PLANEb, volume [PLANEb]);
- break;
- case RIGHT:
- /* Increase volume */
- if (volume [PLANEa] >= 0x7e) break;
- volume [PLANEa] += 2;
- volume [PLANEb] = volume [PLANEa] * 3 / 4;
- SetVoiceVolume (PLANEa, volume [PLANEa]);
- SetVoiceVolume (PLANEb, volume [PLANEb]);
- break;
- case UP:
- /* Increase pitch */
- fnum [PLANEa] += 2;
- Out_Freq (PLANEa, fnum [PLANEa], octave [PLANEa]);
- fnum [PLANEb] = fnum [PLANEa] + 1;
- break;
- case DOWN:
- /* Decrease pitch */
- if (fnum [PLANEa] <= 18) break;
- fnum [PLANEa] -= 2;
- Out_Freq (PLANEa, fnum [PLANEa], octave [PLANEa]);
- fnum [PLANEb] = fnum [PLANEa] + 1;
- break;
- }
- }
- }
- while (c != ' ');
- }
-
-
- /*********************************** Siren *******************************/
-
- unsigned siren_high;
- unsigned siren_low;
-
- Drive_Siren () {
- static flag = 1;
- if (!fnum [SIREN]) return;
-
- if (flag) {
- /* increase pitch */
- fnum [SIREN] += 4;
- Out_Freq (SIREN, fnum [SIREN], octave [SIREN]);
- if (fnum [SIREN] >= siren_high) flag = 0;
- }
- else {
- /* decrease pitch */
- fnum [SIREN] -= 4;
- Out_Freq (SIREN, fnum [SIREN], octave [SIREN]);
- if (fnum [SIREN] <= siren_low) flag = 1;
- }
- }
-
-
- /*-----------------------------------------------------------------------*/
-
- Siren ()
- {
- int ok;
- unsigned char c;
-
- if (!fnum [SIREN]) {
- ok = Set_Instrument (SIREN, NO_RELEASE);
- if (!ok) return;
- timing -= 5;
- volume [SIREN] = 0x60;
- octave [SIREN] = 67 / 12;
- fnum [SIREN] = Pitch_to_Fnum (67) >> 1;
- siren_low = Pitch_to_Fnum (66);
- siren_high = Pitch_to_Fnum (71);
-
- SetVoiceVolume (SIREN, volume [SIREN]);
- Out_Freq (SIREN, fnum [SIREN], octave [SIREN]);
- }
-
- /* Read keyboard input */
- printf ("\nSiren: press spacebar to exit, 'S' to silence ");
- do {
- while (! kbhit ())
- Internal_Driver ();
- c = getch ();
- if (c) {
- c = toupper (c);
- if (c == 'S') {
- timing += 5;
- Stifle_Voice (SIREN);
- fnum [SIREN] = 0;
- c = ' ';
- }
- }
- else {
- c = getch ();
- switch (c) {
- case LEFT:
- /* decrease volume */
- if (volume [SIREN] == 0) break;
- volume [SIREN] -= 2;
- SetVoiceVolume (SIREN, volume [SIREN]);
- break;
- case RIGHT:
- /* increase volume */
- if (volume [SIREN] == 0x7f) break;
- volume [SIREN] += 2;
- SetVoiceVolume (SIREN, volume [SIREN]);
- break;
- case UP:
- /* increase pitch */
- fnum [SIREN] += 8;
- Out_Freq (SIREN, fnum [SIREN], octave [SIREN]);
- break;
- case DOWN:
- /* decrease pitch */
- fnum [SIREN] -= 8;
- Out_Freq (SIREN, fnum [SIREN], octave [SIREN]);
- break;
- }
- }
- }
- while (c != ' ');
- }
-
-
- /******************************** Helicopter *****************************/
-
- int heli_wait;
-
- Drive_Helicopter ()
- {
- static int cntr = 0;
- if (!fnum [COPTER]) return;
-
- cntr++;
- if (cntr >= heli_wait) {
- NoteOff (COPTER);
- Out_Freq (COPTER, fnum [COPTER], octave [COPTER]);
- cntr = 0;
- }
- }
-
-
- /*-----------------------------------------------------------------------*/
-
- Helicopter ()
- {
- int pitch, ok;
- unsigned char c;
-
- if (!fnum [COPTER]) {
- ok = Set_Instrument (COPTER, RELEASE);
- if (!ok) return;
- timing -= 5;
- heli_wait = 5;
- pitch = 39;
- volume [COPTER] = 0x70;
- octave [COPTER] = pitch / 12;
- fnum [COPTER] = Pitch_to_Fnum (pitch);
-
- SetVoiceVolume (COPTER, volume [COPTER]);
- Out_Freq (COPTER, fnum [COPTER], octave [COPTER]);
- }
-
- /* Read keyboard input */
- printf ("\nHelicopter: Pg Up - faster, Pg Dn - slower, spacebar to exit ");
- do {
- while (! kbhit ()) Internal_Driver ();
- c = getch ();
- if (c) {
- c = toupper (c);
- if (c == 'S') {
- timing += 5;
- Stifle_Voice (COPTER);
- fnum [COPTER] = 0;
- c = ' ';
- }
- }
- else {
- c = getch ();
- switch (c) {
- case LEFT:
- /* decrease volume */
- if (volume [COPTER] == 0) break;
- volume [COPTER] -= 2;
- SetVoiceVolume (COPTER, volume [COPTER]);
- break;
- case RIGHT:
- /* increase volume */
- if (volume [COPTER] == 0x7f) break;
- volume [COPTER] += 2;
- SetVoiceVolume (COPTER, volume [COPTER]);
- break;
- case UP:
- /* increase pitch */
- fnum [COPTER] += 2;
- break;
- case DOWN:
- /* decrease pitch */
- if (fnum [COPTER] > 0) fnum [COPTER] -= 2;
- break;
- case PAGEUP:
- /* increase frequency of note off/on */
- if (heli_wait > 0) heli_wait--;
- break;
- case PAGEDOWN:
- /* decrease frequency of note off/on */
- if (heli_wait < 0x7fff) heli_wait++;
- break;
- }
- }
- }
- while (c != ' ');
- }
-
-
- /************************************************************************
- Routine which allows one to read in an instrument file and play with
- the pitch and volume. */
-
- Test ()
- {
- #ifdef TEST
- char fname [40];
- int pitch, octave, volume;
- unsigned int fnum1;
- unsigned char c;
-
- printf ("\nFile name: ");
- scanf ("%s", fname);
- Read_Ins_File (fname, FAKE_ID);
- if (!Set_Instrument (FAKE_ID, NO_RELEASE)) return;
- printf ("Start pitch: ");
- scanf ("%d", &pitch);
-
- volume = 0x60;
- octave = pitch / 12;
- fnum1 = Pitch_to_Fnum (pitch);
- SetVoiceVolume (FAKE_ID, volume);
- Out_Freq (FAKE_ID, fnum1, octave);
-
- printf ("\nTest: press spacebar to stop ");
- do {
- while (! kbhit ());
- c = getch ();
- if (!c) {
- c = getch ();
- switch (c) {
- case LEFT:
- /* decrease volume */
- if (volume == 0) break;
- volume -= 2;
- SetVoiceVolume (FAKE_ID, volume);
- break;
- case RIGHT:
- /* increase volume */
- if (volume == 0x7f) break;
- volume += 2;
- SetVoiceVolume (FAKE_ID, volume);
- break;
- case UP:
- /* increase pitch */
- fnum1 += 5;
- Out_Freq (FAKE_ID, fnum1, octave);
- break;
- case DOWN:
- /* decrease pitch */
- fnum1 -= 4;
- Out_Freq (FAKE_ID, fnum1, octave);
- break;
- }
- }
- }
- while (c != ' ');
- printf (" fnum=%d, octave=%d, vol=%d ", fnum1, octave, volume);
- Stifle ();
- #endif
- }
-
-
- /************************************************************************
- This routine must be called constantly (or at a constant interval) in order
- to keep producing the sound effects. In a real application, this routine or
- a variation of it would be hooked up to the timer interrupt directly or via
- another routine. */
-
- Internal_Driver ()
- {
- Drive_Siren ();
- Drive_Airplane ();
- Drive_Bomb ();
- Drive_Helicopter ();
- Drive_Jet ();
- delay (timing);
- }
-
-
- /*-----------------------------------------------------------------------
- Main loop. Displays menu and reads user's selection. */
-
- Choose_Sound ()
- {
- unsigned char c;
- printf (
- "\nTo speed up or slow down, re-execute using /Txxx, where xxx is a"
- "\nnumber. xxx is currently %d.", timing);
- printf ("\n\nUse up and down arrows to change pitch. Use left and\n"
- "right arrows to change volume.");
- do {
- printf ("\nChoose one:\n A)irplane\n B)omb\n "
- "H)elicopter\n J)et\n S)iren\n R)eset all\n Q)uit\n");
- while (! kbhit ()) Internal_Driver ();
- c = getch ();
- if (!c) getch ();
- else {
- c = toupper (c);
- switch (c) {
- case 'A': Airplane ();
- break;
- case 'B': Bomb ();
- break;
- case 'H': Helicopter ();
- break;
- case 'J': Jet ();
- break;
- case 'R': Stifle ();
- Demo_Init ();
- break;
- case 'S': Siren ();
- break;
- case 'T': Test ();
- break;
- }
- }
- }
- while (c != 'Q');
- }
-
-
-