[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]