[Back to FAQ SWAG index] [Back to Main SWAG index] [Original]
{
Two ways to create dial tones: digital sample for each tone, or generate tone
with a digital to analog convertor. The MCI mmSystem uses MS Windows 3.1 high
resolution timer. The following demonstrate other ways to generate tones: }
program PlayTone;
{ Author: John Howard }
uses WinProcs;
(* Comments from Don Phillip Gibson, CompuServe [75725,1752] are enclosed in
star brackets *)
const Magic : integer=376;
Tempo : integer = 120;
NoteType : integer = 4;
(*
Magic is used as a multiplier to determine the duration of a
note. The Windows API documentation for setVoiceSound
indicates that duration should be a straight forward
calculation of yea-so-many clock ticks. It just isn't so.
Brute force experimentation found 376. It seems to work fine
regardless of processor speed or whatever. I've tested on
386/33, 386/16, and 8088/4.7 machines -- they all work. Let
me tell you, it was sure fun setting up and running Windows on
that 8088/4.7 CGA equipment.
The actual tone production routines follow. If you've explored
the API music functions at all, you may wonder why I'm using
setVoiceSound instead of setVoiceNote. setVoiceNote seems, on the
surface, to be the automatic way to write these sorts of things,
but it just doesn't work very well. Whole notes and half notes
are incorrectly produced, dots are impossible, and the nicety of
having legato is gone. setVoiceSound works much better, though it
does require that you calculate a duration rather than just
specifying tempo and length.
Windows wants the fractional and integer portions of the frequency
stuffed respectively into the low and high words of a long integer.
setVoiceSound doesn't provide for a rest. Instead, I've plugged an
impossibly high pitch into the [0] slot of that array. It's
presumably playing, but you shouldn't hear it.
*)
var Pitch : array[0..84] of LongInt;
Herz : array[0..11] of Real;
Tone : integer; { index }
function Duration(Tempo, NoteType : integer) : integer;
var Temp : real;
begin
Temp := 60 / Tempo * Magic * 4 / NoteType;
Duration := trunc(Temp);
end;
BEGIN {main}
Pitch[0] := MakeLong(0,20000);
Tone := 0; { example tone index }
Herz[Tone] := 523.25; { note 'C' white frequency }
Pitch[Tone+1] := MakeLong(trunc(frac(Herz[Tone])),trunc(int(Herz[Tone])));
setVoiceSound(1,Pitch[Tone+1],Duration(Tempo,NoteType) * 7 div 8 );
{1. Accept note number}
setVoiceSound(1,Pitch[0],Duration(Tempo,NoteType) * 1 div 8 );
{2. Sound off, zero means silence}
{3. Translate note into 'frequency'}
{4. Setup timer chip}
{5. Setup frequency}
{6. Sound on}
{7. Setup note length delays}
(*
I don't know why I've got to send one last 'empty' note to the
voice queue, but without it, the last real note doesn't get played.
That's the purpose of the next statement.
*)
setVoiceSound(1,0,1);
setVoiceThreshold(1,0);
StartSound;
repeat until GetThresholdStatus = 1;
CloseSound;
END. {main}
1-800-451-6644 Philips/Signetics BBS Filename: DTMF.ZIP
{ snippet follows }
; The following code uses both timers in an 80c31 to generate
; DTMF tones, and signalling tones such as BUSY, RING-BACK, etc.
; This file also contains the connections for a very crude 2 bit
; per tone A\D converter wich uses 4 bits of P1 and a low pass filter.
; Compensation for twist isn't included but could be handled by
; playing with the hi and low tone dac values and the summing amp
; input resistors.
;
; If this code is used in any application I only request that
; credit be given to me:
; Bert Rinne
; Advanced Logic Systems Inc.
; 13 Twin Meadows Dr.
; Hudson N.H. 03051
; (C) 1993
; *** Another method of tone generation is documented in the
; 'YUCK' Zilog Z8 microcontrollers book circa 1991 using the
; Super8. It is a waveform synthesis model using a 8Khz sampled
; data system with 1 timer and an 8 bit dac. If anyone should
; adapt the technique to the '51/'31 family please post the
; code on this BBS in return for the info.
;
; Bert Rinne 12/93
SIGNAL_LOW equ 021h ;2 bytes for signal fLOW timer
SIGNAL_HIGH equ 023h ;2 bytes for signal fHIGH timer
fHIGH equ 025h ; frequency high
fLOW equ 026h ; frequency low
CNT_10mS equ 027h ; decrement 10 millisecond used as a timer
; HARDWARE CONFIGURATION ____/\/\/\___
;--------, | |
; 8031 | 47k +-----][----|
; P1.0 |-----/\/\/\------, | |
; | 12k +--/\/\/\--, | \ |
; P1.1 |-----/\/\/\------' | | | \ |
; | +---][---+---|- \_|____||___
; | 47k | | / ||
; P1.2 |-----/\/\/\------, | ,--|+ /
; | 12k |--/\/\/\--' | |/
; P1.3 |-----/\/\/\------' |
;--------' +2.5V
;
; the dac uses 3 bits per channel internal to the mpu and
; counts as follows 000 001 010 011 100 101 110 111
; using bit 2 as the sign and complementing bits 0 & 1 we
; get 000 001 010 011 111 110 101 100 and
; output 00 01 10 11 11 10 01 00
; The above was coupled to a 100mw amp and used to dial the phone
; via acoustical coupling (held phone near speaker) with no errors.
;
; Funky DAC courtesy of Don Lancaster's wonderful book -
; The CMOS Cookbook, Howard Sams Inc.
;
; DIALING TONES (dtmf)
;
; 1209 1336 1477 1633
;
; 697 1 2 3 A
;
; 770 4 5 6 B
;
; 852 7 8 9 C
;
; 941 * 0 # D
;
; Using the formula f = -(((osc/12)/bits-per-cycle)/desired-freq.)
;
; thus at 11.059 MHz clock and 8 bits per cycle:
;
; desired timer value actual freq
; 697 = -165 698.2
; 770 = -150 768
; 852 = -135 853.3
; 941 = -122 944
;
; 1209 = -95 1212.6
; 1336 = -86 1339.5
; 1477 = -78 1476.9
; 1633 = -71 1622.5
; Low frequency low byte
F697 equ LOW(-165)
F770 equ LOW(-150)
F852 equ LOW(-135)
F941 equ LOW(-122)
; High frequency low byte
F1209 equ LOW(-95)
F1336 equ LOW(-86)
F1477 equ LOW(-78)
F1633 equ LOW(-71)
; Tone time on >40 mS Bell spec minimum so we
; Tone time off >40 mS will use 100mS on/70 mS off
;
; SIGNAL TONES
; NOTE *** the signal tone values are adjusted by LOAD_DTMF:
; to compensate for latency time while re-loading the timers.
; The latency time is 2 us. and is critical for
; valid signal tone frequencies.
;
; Low High (Hz)
; Dial tone 350 440 steady tone -13dBm
; ring-back 440 480 2 sec on/ 4 sec off -19dBm
; busy 480 620 .5 sec on/.5 sec off -24dBm
; NOTE: *******
; Although the following are not implemented, they are valid
; signal tones:
;
; Reorder: 480 620 .25 sec on/.25 sec off -24dBm
;
; Partial dial tone
; 480 steady tone -17dBm
;
; Auto credit call prompting:
; 941 1477 940 mSEC -10dBm/freq.
; followed by 440 350 exponentially decaying from -10dBm
; @ a time constant of 200mSec.
;
; Reference: Mitel Semiconductor Data book circa '86-'87.
; "Credit must be given where due."
;
; Pulse dialing can be accomplished very easily using the timers
; and if you're reading this you can figure it out.
;
; desired timer value actual freq
; 350 -329 350
; 440 -262 439.7
; 480 -240 480
; 620 -186 619
F350 equ -329
F440 equ -262
F480 equ -240
F620 equ -186
TONE_TBL:
; 0
db F941 ;fLOW = 941
db F1336 ;fHIGH = 1336
db 76 ;76 * fLOW intrs = 10mS
db 0
; 1
db F697 ;fLOW = 697
db F1209 ;fHIGH = 1209
db 56 ;56 * fLOW intrs = 10 mS
db 0
; 2
db F697 ;fLOW = 697
db F1336 ;fHIGH = 1336
db 56
db 0
; 3
db F697 ;fLOW = 697
db F1477 ;fHIGH = 1477
db 56
db 0
; 4
db F770 ;fLOW = 770
db F1209 ;fHIGH = 1209
db 62
db 0
; 5
db F770 ;fLOW = 770
db F1336 ;fHIGH = 1336
db 62
db 0
; 6
db F770 ;fLOW = 770
db F1477 ;fHIGH = 1477
db 62
db 0
; 7
db F852 ;fLOW = 852
db F1209 ;fHIGH = 1209
db 68
db 0
; 8
db F852 ;fLOW = 852 (853)
db F1336 ;fHIGH = 1336 (1340)
db 68
db 0
; 9
db F852 ;fLOW = 852 (853)
db F1477 ;fHIGH = 1477 (1477)
db 68
db 0
; A
db F697 ;fLOW = 697 (698)
db F1633 ;fHIGH = 1633 (1622)
db 56
db 0
; B
db F770 ;fLOW = 770 (768)
db F1633 ;fHIGH = 1633 (1622)
db 62
db 0
; C
db F852 ;fLOW = 852 (853)
db F1633 ;fHIGH = 1633 (1622)
db 68
db 0
; D
db F941 ;fLOW = 941 (944)
db F1633 ;fHIGH = 1633 (1622)
db 76
db 0
; *
db F941 ;fLOW = 941 (944)
db F1209 ;fHIGH = 1209 (1213)
db 76
db 0
; #
db F941 ;fLOW = 941 (944)
db F1477 ;fHIGH = 1477 (1477)
db 76
db 0
[Back to FAQ SWAG index] [Back to Main SWAG index] [Original]