From: REEKES@applelink.apple.com (Jim Reekes)
Newsgroups: comp.sys.mac.programmer
Subject: Re: Playing non-MIDI frequencies (SOURCE)
Date: 9 Apr 92 20:10:43 GMT
Organization: Apple Computer, Inc.

In article <6293@lib.tmc.edu>, cshotton@oac.hsc.uth.tmc.edu (Chuck Shotton) writes:
> 
> In article <1992Mar27.135258.11955@terminator.cc.umich.edu>, potts@itl.itd.umich.edu (Paul Potts) writes:
> > 
> > In article <1992Mar4.160559.24912@walter.bellcore.com> bobh@twinkie.bellcore.com () writes:
> > >Help, I feel betrayed.  I want to play some pure sine-waves of frequencies
> > >which are not "standard" MIDI frequencies (I'm trying to simulate a telephone
> > >touch-tone keypad) and I'm having some problems.
> > 
> 
> This is a Pascal unit I wrote a LONG time ago to play touch tones out the Mac's
> speaker. I make no claims about its correctness, and it definitely uses the
> OLD Sound Manager. (This unit is part of a XCMD...)
> 
> Chuck
>
> lots 'o code followed...


There's an easier method.  Get the 'snd ' resources out of HyperCard 2.0 or
later.  It contains samples of the actual telephone frequencies.  You knew
that HyperCard supported the "DIAL" command didn't you?  Well it does,
and it does it using a simple method.

So, ya wanna do dial tones just like HyperCard? Well, that's not so hard (as
long as you are patient enough to read through all the Sound Manager documents
and beat your head against the wall for half an hour, like I did). The
technique is simple: lift the 'snd ' resources from HyperCard and use them to
generate dial tones! (Yes, that's OK, dtmf tones are generic sounds; just
don't lift any of the other sounds!)
 
Start by using ResEdit to copy 'snd ' resources #130-145 from the HyperCard
program file (I got them out of 2.0). Next use the Sound Manager to play them
and to use them as an instrument definition for the samplesynth. Since this
can be tricky, and since you may or may not want dive deep into the Sound
Manager, I am including a generic subroutine that I wrote that will "dial" for
you. All I ask is that if you use it "as is" in your application, please
remember me in your prayers.
 
How to use the dial procedure:
 
To call the dial procedure simply pass it a string and it will do the rest.
All digits A thru D, # and * play the proper tone for the touch tone key; any
other characters generate a 1/2 second delay. Each tone is sounded for about
1/4 second. The interface to it is simply: Procedure Dial(theNum:Str255).
Please note that in order to keep this short, very little error checking has
been added, please add any/all that you need.
 
And now for the fabulous source code:
 
PROCEDURE Dial(theNum: Str255);

VAR
    i                  : Integer;
    theSound           : Handle;
    theResNum          : Integer;
    dummy              : LongInt;
    err                : OSErr;
    chan               : SndChannelPtr;
    cmd                : SndCommand;

BEGIN
    IF Length(theNum) = 0 THEN
        Exit(Dial);

    chan := NIL;        {allocate a channel}
    err := SndNewChannel(chan, sampledSynth, 0, NIL);
    IF err <> noErr
        Exit(Dial);

    FOR i := 1 TO Length(theNum) DO BEGIN

        CASE theNum[i] OF
            '0'..'9': theResNum := ord(theNum[i]) - ord('0') + 130;
            'A'..'D': theResNum := ord(theNum[i]) - ord('A') + 140;
            '*': theResNum := 144;
            '#': theResNum := 145;
            OTHERWISE theResNum := 0;
        END;

        IF theResNum <> 0 THEN BEGIN
            {Load the proper sound resource}
            theSound := GetResource('snd ', theResNum);
            HLock(theSound);

            {See sound manager docs for resource format of}
            {type 2 sounds for more info}
            cmd.cmd := soundCmd;
            cmd.param1 := 0;
            
            {This next line ASSUMES it was a format 2 'snd ' resource}
            {This will not work for other 'snd ' resources}
            cmd.param2 := ORD4(theSound^) + 14;
            err := SndDoImmediate(chan, cmd);

            {Now send the freqDurationCmd to play a middle C}
            {that's how the instrument was defined in HyperCard}
            cmd.cmd := freqDurationCmd;                     
            cmd.Param1 := 4000;                 {2 seconds in duration}
            cmd.Param2 := $FF000000 + 60;       {Loud + Middle c}
            err := SndDoImmediate(chan, cmd);

        END ELSE
            Delay(30, dummy);   {all nonDTMF characters produce a delay...}
    END;
    err := SndDisposeChannel(chan, false);
    HUnlock(theSound);
END;


-----------------------------------------------------------------------
Jim Reekes, E.O.             |     Macintosh Toolbox Engineering
                             |          Sound Manager Expert
Apple Computer, Inc.         | "All opinions expressed are mine, and do
20525 Mariani Ave. MS: 81-KS |   not necessarily represent those of my
Cupertino, CA 95014          |       employer, Apple Computer Inc."