From: REEKES@applelink.apple.com (Jim Reekes)
Subject: Re: help- sound playing w/ bufferCmd
Date: Wed, 6 Jan 1993 00:36:46 GMT
Distribution: comp
Organization: Apple Computer, Inc.
Followup-To: comp.sys.mac.programmer

In article <TMORROW.93Jan2151912@af4hp.oracle.com>, tmorrow@oracle.com
(Thomas Morrow) wrote:
> 
> 
> I am having trouble using SndDoCommand to play a sampled sound header.
> 
> I do:
> 	SndCommand mySndCmd;
> 	
> 	/* mySndH is a handle to a sound header and data */
> 	/* mySndChan is already properly opened */
> 	mySndCmd.cmd;
> 	mySndCmd.param1 = 0;
> 	mySndCmd.param2 = (long)(*mySndH) & 0xffffff;
> 	SndDoCommand(mySndChan, mySndCmd, false);
> 
> This does not work for some reason; I can't figure out why because if
> I replace the SndDoCommand with a Snd Play, it works:
> 
> 	SndPlay(mySndChan, mySndH, true);
> 	
> So the channel and header must be alright.  I am new to Mac
> programming, and wasn't sure exactly how to set param2 (a long) to the
> header address (Ptr)... The IM IV uses ORD4() to do the type
> conversion, but I am using Think C rather than Lisa Pascal. My way
> seems to work, but what is the elegant way?
> 
> Anyway, I use SndChannelStatus to get the status every event loop
> cycle, and the SCStatus returned is blank (zero) in all except CPUload
> (24),  ChannelAttributes (initMono), and ChannelBusy (true).  How can
> the channel be busy if StartTime == endTime == 0?

You cannot use the 'snd ' resource for the bufferCmd. You must point to the
SoundHeader within the resource.  Also, the code above didn't set the cmd
to bufferCmd. Here's some code anyone can use to find the sound header in a
'snd ' resource. Then change your code above into...

	mySndCmd.cmd = bufferCmd;
	mySndCmd.param1 = 0;
	mySndCmd.param2 = (long) *mySndH + offset;
	err = SndDoCommand(mySndChan, &mySndCmd, true);


// find the sound header inside of the given snd handle

OSErr GetBufferOffset(Handle sndHandle, long *offset)
{
    short       howManyCmds;
    Ptr         cruisePtr;
    OSErr       result;

    if (sndHandle == nil)
        return nilHandleErr;
        
    if (*sndHandle == nil)
        return nilHandleErr;

    result = noErr;
    *offset = 0;

    // set the pointer past the first two words of the snd
    // this is correct for both format 1 and 2 resources
    cruisePtr = *sndHandle + offsetof(SndListResource, modifierPart);

    // if it's a format 1, then point past the modifier parts
    if ( ((SndListPtr)*sndHandle)->format == firstSoundFormat )
        cruisePtr += sizeof(ModRef) *
((SndListPtr)*sndHandle)->numModifiers;

    // now pointing at number of cmds
    howManyCmds = *((short *)cruisePtr);
    cruisePtr += sizeof(howManyCmds);

    // cruisePtr is now at the first sound command
    // cruise all commands and find a soundCmd or bufferCmd
    do {
        switch (((SndCmdPtr)cruisePtr)->cmd) {

            case (soundCmd | dataOffsetFlag):
            case (bufferCmd | dataOffsetFlag):
                *offset = ((SndCmdPtr)cruisePtr)->param2;
                howManyCmds = 0;                // done, get out of loop
                break;

            default:                            // catch any other type of
cmd
                cruisePtr += sizeof(SndCommand);
                howManyCmds -= 1;
                break;
        }
    } while (howManyCmds >= 1);                 // done with all the
commands

    if (*offset == 0)                           // never found sound header
        return badFormat;
        
    return(result);
}



-----------------------------------------------------------------------
Jim Reekes, Polterzeitgeist  |     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."