SOUND.DOC -- Description of the Sound Generation Routines in SOUND.ASM ====================================================================== From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT' by Christopher L. Morgan Copyright (C) 1984 by The Waite Group, Inc. Purpose: -------- The routines in SOUND.ASM are useful for producing sound on the PC via the speaker and associated timer chip. The routines named TONExxxx are primitives that directly access the speaker and timer. All other routines call these routines to produce any sound. Contents: --------- DELAY -- Delay for a specified time interval FREQ -- Convert from frequency to period GLISSNDO -- Make a glissando (sliding tone) LINSCALE -- Provide linear scaling PITCH -- Convert from pitch number PLAY -- Play music from a table TONE -- Make a tone TONE_INIT -- Initialize speaker timer TONE_OFF -- Turn off tone TONE_ON -- Turn on tone TONE_SET -- Set the tone on the speaker Overview: --------- The speaker is connected to the output of timer 2, which produces a square wave whose frequency can be set using the TONE_SET routine. TONE_SET assumes the timer has been properly initialized, as is done during normal boot-up. TONE_INIT can also be used to initialize the timer. The frequency of the square wave from the timer is determined by the formula, f=F/n, where f is the frequency of the square wave, F is 1,193,182 and n is a 16-bit integer that is input to the routine. The constant, F, is exactly 1/3 the frequency of the NTSC subcarrier used for color encoding by the Color/Graphics Adapter. F is derived by hardware from a main clock signal that runs at 14,317,800 Hertz and supplies the timing for most of the computer. TONE_ON and TONE_OFF provide control over whether the square wave reaches the speaker, thus turning the sound on or off. There are actually two bits involved, one to control the connection between the clock signal and the timer, and one to control the connection between the timer and the speaker. Both routines switch both connections simultaneously. There is no provision to control the bits independently. The routine, DELAY, provides timing for the duration of musical notes in milliseconds. The routine, FREQ, uses the formula, n=F/f, to compute the input parameter for TONE_SET from a given frequency. Using this just before TONE_SET permits working directly with frequencies rather than clock cycles of the 1,193,182 Hertz clock. The routine, TONE, uses the other routines to produce tones of a given frequency and duration. The frequency is input as a 16-bit integer and the duration is in milliseconds using the DELAY routine. The rest of the routines provide special sound effects. SCALE converts numbers between 0 and 1 into numbers within the range of X1 and X2, which are any specified 16-bit integers. This is used with RANDOM to produce pseudo-random numbers between 0 and 1. The routine, WHITE, uses these pseudo-random numbers along with SCALE to generate white noise. The routine, GUN shows how to shape white noise into a machine gun sound. The routine, GLISSANDO, makes a tone that slides smoothly from one frequency, X1, to another, X2. RED shows how to shape glissandos into red alert sirens. PITCH and PLAY are music routines. PITCH converts the pitch number to a value useable by TONE_SET to set the frequency. PLAY plays music from a "playlist" of notes. __________________________ Descriptions of Routines __________________________ DELAY -- Delay for a specified number of milliseconds ----------------------------------------------------- Function: This routine provides a time delay for specifying the duration of a sound, a wait, etc. Input: Upon input, CX contains the no. of milliseconds to delay. Output: None Register used: CX is first saved and then restored. _______________________________________________________________________________ FREQ -- Convert from Frequency to Period ---------------------------------------- Function: This routine converts from frequency to the number required by TONE_SET to set the frequency. The routine evaluates the formula, N = F/f, where f is the frequency input to this routine, n is the number output by this routine, and F is 1,193,182. In other words, this routine divides the specified frequency, f, into the 1,193,182 hertz clock frequency that drives the timer. Use this routine just before TONE_SET. Input: Upon entry, the frequency is in CX. Output: Upon exit, F/f is in CX. Registers used: CX is modified, AX & DX are first saved and then restored. _______________________________________________________________________________ GLISSNDO -- Make a Glissando ---------------------------- Function: This routine makes a glissando; i.e., a sound that slides from one frequency to another. The rate of change can be controlled. Input: Upon entry, the starting frequency is in BX, the ending frequency is in CX, and the control parameter for the rate increase is in DX. Increasing the value in DX slows down the rate of change. Output: To the speaker and timer only. Registers used: All registers are saved and then restored. Segments referenced: The data segment must contain the variables, F_START & F_END. Routines called: TONE_SET, TONE_ON, TONE_OFF, DELAY Special note: The speaker timer must already have been initialized. If necessary, use TONE_INIT to initialize before calling this routine. _______________________________________________________________________________ PITCH -- Convert from Pitch Number ---------------------------------- Function: This routine converts from pitch number to the value required by TONE_SET to set the frequency. The pitch numbers refer to an extended chromatic scale. The notes of this scale are numbered from 0 to 95 with 12 notes/octave. 0 corresponds to a C at 16.35 hertz. Input: Upon entry the pitch number of the note is in AL. Output: Upon exit, the DX register has the proper value for TONE_SET. Registers used: DX has value; AX, BX, & CX are saved and then restored. Segments Referenced: The data segment must contain the following pitch table: NOTES DW 4186 ;C DW 4435 ;C#/D- DW 4699 ;D DW 4978 ;D#/E- DW 5274 ;E DW 5588 ;F DW 5920 ;F#/G- DW 6272 ;G DW 6645 ;G#/A- DW 7040 ;A DW 7459 ;A#/B- DW 7902 ;B Routines called: FREQ _______________________________________________________________________________ LINSCALE -- Do Linear Scaling ----------------------------- Function: This routine performs a linear scaling, converting a fixed point number between 0 and 1 into an integer between X1 and X2, where X1 and X2 are 16-bit integers. Input: Upon entry, CX has a binary fixed point number between 0 and 1. The binary point is to the left of the leftmost bit. X1 and X2 are variables stored in memory. Output: Upon exit, CX contains the 16-bit integer result. Registers used: CX is modified, AX & DX are first saved and then restored. Segments referenced: The data segment must contain the variables, X1 & X2. _______________________________________________________________________________ PLAY -- Play Music ------------------ Function: This program plays music. It reads a binary "play" list that contains instructions to make the tune. This list consists of a series of music instructions: Tempo, Note, Rest, and End. The syntax for the instructions are: Tempo Command first byte = ASCII "T" second byte = tempo in whole notes/minute Note Command first byte = ASCII "N" second byte = pitch number (integer 0-95) third byte = length (8-bit binary fixed point - scale 1) fourth byte = style (8-bit binary fixed point - scale 0) Rest Command first byte = ASCII "R" second byte = length (8-bit binary fixed point - scale 1) End Command first byte = ASCII "X" The scaling is: scale 0 has the binary point to the left of the leftmost digit scale 1 has the binary point to the right of the leftmost bit Input: Upon entry, the address of the "play" list is in DS:SI Output: To the speaker and timer only Registers Used: Entry registers are saved and restored Segments Referenced: The data segment contains the "play" list and the variables WHOLE, ACCOUNT, and RCOUNT Routines Called: PITCH, TONE_OFF, DELAY _______________________________________________________________________________ TONE -- Make a Tone ------------------- Function: This routine makes a tone of a given frequency and given length. Input: Upon entry, the frequency is in CX and the length in no. of milliseconds is in DX. Output: To the speaker and timer only. Registers used: AX, CX, & DX are first saved and then restored. Segments referenced: The data segment must contain the variable, COUNT. Routines called: TONE_SET, TONE_ON, TONE_OFF, DELAY Special note: The speaker timer must already have been properly initialized. This should normally occur during boot-up. _______________________________________________________________________________ TONE_INIT -- Initialize Speaker Timer ------------------------------------- Function: This routine initializes the part of the 8253 timer chip used by the speaker system. Particularly, it sets up channel 2 of this timer as a square wave generator. This routine does not select the frequency, nor does it turn on the tone. Use TONE_SET to select the frequency, TONE_ON to turn the tone on, and TONE_OFF to turn it off. Input: None Output: Only to the timer 2 of the speaker circuit. Registers used: AX is first saved and then restored. _______________________________________________________________________________ TONE_OFF -- Turn off Tone ------------------------- Function: This routine turns of the timer and speaker. Input: None Output: To the timer and speaker only. Registers Used: AX register is first saved and then restored. _______________________________________________________________________________ TONE_ON -- Turn on Tone ----------------------- Function: This routine turns on the timer and speaker to produce a tone. The frequency of the tone must have already been selected on the timer. you can use TONE_SET to set the frequency of the tone. Input: None Output: To the timer and speaker only. Register used: AX is first saved and then restored. _______________________________________________________________________________ TONE_SET -- Set the Tone on the Speaker --------------------------------------- Function: This routine selects the frequency of the square wave tone to the speaker. The input to this routine is a 16-bit integer n which determines the frequency, f, according to the following formula: f = F/n where F is 1,193,182, the frequency of a clock signal which feeds the timer. The value, n, is the number of cycles of the clock signal per cycle of the resulting square wave. This routine does not actually turn on the tone. Use TONE_ON to turn on the tone, and TONE_OFF to turn it off. This routine assumes the speaker timer has already been properly initialized. This happens during normal boot-up, or you can use TONE_INIT to initialize the timer. Input: Upon entry, the 16-bit integer, n, is in the CX register. Output: Only to the timer 2. Register used: AX is first saved and then restored. _______________________________________________________________________________ >>>Physical EOF SOUND.DOC<<<