TweetFollow Us on Twitter

Playing sound
Volume Number:7
Issue Number:1
Column Tag:XCMD Corner

Playing With Sound

By Donald Koscheka, Contributing Editor

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

The Importance of XCMDs

One of the questions that is raised by Hypercard 2.0’s new XCMD interface is, “How important are XCMDs to the vitality of the Macintosh?”. One cannot imagine that XCMDs would be very important at all so it would be useful to the xcmd programmer to ponder the future of xcmds in the Macintosh programming world.

After studying Hypercard 2.0 in great detail, I’ve concluded that XCMDs are very important to the success of this product and that Apple Computer, Inc. is acknowledging this by providing more services to the XCMD programmer such as windoids and script manipulation capability. But another event in the small computer world lends even more credence to XCMD as programming art. That event is quietly taking over the MS-DOS world as Microsoft successfully evangelizes the concept of Dynamic Link Libraries, or DLLs.

If you’re not a PC programmer (and who can afford not to be), then you may not know that DLLs are code modules that are written in such a way as to be loadable and thus callable at any time. DLLs are code segments that have a standard programming interface associated with them. In effect, DLLs allow you to build re-usable code modules that in theory can be used in any application. Well, if every application had such an interface on the Mac, let’s call it XCmdPtr, then xcmds would serve the same purpose -- the ability to call xcmds from any program that runs on the mac. Without a lot of induction, one can come to the conclusion that if xcmds can give you this type of capability on the Mac, then they are indeed important, at least at the conceptual level.

If xcmds become callable from any application then they become an integral part of the future of the Macintosh. It is not unimaginable to believe that someday you will flesh-out your application with some sort of screen generator and then build a set of xcmds to implement the application-specific code. I find it impossible to believe that this effective approach to programming won’t become the norm for all programmers in the future. In fact, Michael Swain suggests exactly this approach for PC programmers using ToolBook ( “Dr. Dobbs Journal”, November, 1990). When I read this column, my eyes popped out of my head. Mr. Swain’s concept of marrying rapid prototyping with rapid code development via DLL’s is exactly what we’ve been doing with Hypercard for the last three years. Any Windows developer that takes his advice will wonder what all the fuss was about; Windows will appear to be an easy and natural development environment.

So now I can rest easy. I am convinced that the XCMD approach to programming will prevail over time. It’s working for me. By forcing me to avoid globals and to think modularly, XCMDs have allowed me to write code that is re-usable in a wide-variety of applications. Each time I write an XCMD, I create a piece of code that I not only know I will use again but that I can comfortably extract from Hypercard without worrying about breaking it. That is the programmer’s holy grail and that is why XCMDs not only have a future, they are the future.

Playsound

Several months ago, I got a call from Bill Leitman, a fellow Mac developer in the New York area. He was working with a small film company in Brooklyn that needed an xcmd that played a portion of a sound resource. Bill’s approach was quite reasonable, he took a piece of code that he knew to be working from another application and dropped it into an xcmd. Lo and behold, it didn’t work. He called me in desperation to see if there was anything that I knew about xcmds that was causing his problem. To no avail, I also tried to get the sound manager to work from within an xcmd but after hours of head scratching and staring at TMON windows, I came to the conclusion that Hypercard just wasn’t going to let me use the sound manager.

This was unfortunate and unbelievable, but I’ve never been able to find a way to get the sampled synth playing in an xcmd. Imagine my surprise when I first encountered the following callbacks in Hypercard 2.0: BEGINXSOUND and ENDXSOUND. Is it possible that it wasn’t me? Did Hypercard actually work the way I thought it did by taking over the sound driver and not making it available to anyone else. I don’t know the answer to this question, ‘tho I’d like to so please write if you have some input. I do know that this must have been a problem since Apple went to the motions of adding these callbacks, which work quite perfectly for me.

This month’s playsound xcmd (listing 1) was inspired by Mr. Leitman and I am grateful to him that he gave me an excuse to explore the sound manager. It’s more daunting than the Sunday Times crossword puzzle and just as much fun!

Playsound takes up to four parameters: the first is the name of the file to retrieve the sound resource from. The second parameter is the name of the sound resource to retrieve. The third parameter is the index to the sample to start playing from (0 means play from the beginning of the sound). The fourth parameter is the last sample to play to. These last two parameters are optional, if they are left out, the entire sound resource will be played.

For simplicity, this code makes two assumptions that you can modify to meet your own needs: (1) you want to play the sound using the sampled synthesizer and (2) the sound is a format 2 ‘snd ‘ resource. I chose not to support format 1 ‘snd ‘ resources because Inside Macintosh indicates that format 2 snd resources should be adopted by developers as a standard. Should you decide that you want to support format 1 resources, refer to page 491 of Inside Macintosh Volume V for details on that format.

The xcmd parses out the parameters, opens the appropriate resource file and loads the ‘snd ‘ resource which it then detaches from the resource map. This is important because we are going to modify the resource and we don’t want the changes to be written back out by mistake. We call BEGINXSOUND to advise hypercard that we want to take over the sound drive for a while. Next we call PlayRunSound to play the sound, or sound fragment, and then we call ENDXSOUND to give the sound driver back to Hypercard.

PlayRunSound() is the heart and soul of this xcmd. The first thing that it does is check to see if the appropriate synthesizer is available. If so, it then allocates a new channel via the SndNewChannel call. This call returns a pointer to our new channel, initialized for the sampled synthesizer in theChan. We will pass this pointer to SndDoCommand to play this sound on that channel.

Once the channel is initialized and we know that we can use it, we set the start and stop time of the sound and play it. The first thing we need to do is check to see if we have the correct resource format which we do by testing to make sure that the first word in the resource (sndHdl) is set to 2. If it is, then we can access the fields in the snd resource by referring to the documentation on page 494 of IM vol V.

Figure 1. A typical format 2 ‘snd ‘ resource.

Here is how the sound fragment scheme works: The snd resource contains some header information (6 bytes) followed by a number of 8 byte sound commands (the sample sound resource in figure 1 contains only one sound command). The sound data immediately follows the sound commands. If there is only one sound command, then the sampled data table will begin at offset 14 (0x0E) in the record.

The first two long words in the sound data table tell us where the samples start and how many of them there are. The where is usually set to 0 and the how much is usually set to the number of samples to play back. We can modify these fields to change the starting point and the number of samples to play. Or, we can set just the new starting point and play back to the end of the sound. Playsound doesn’t use the sound command (in this case, ‘soundCmd’) but rather uses the ‘bufferCmd’ instead.

So, we modify the sound table by stuffing new values for the pointer and length and then call the sound manager via the bufferCmd. Once the sound is done playing, we call SndDisposeChannel to remove our allocated channel, in effect freeing up the sampled synthesizer in preparing to give it back to Hypercard. That’s all there is to it. You might want to use this xcmd to continue to explore the sound manager. It appears to have rich and intriguing repertoire. In fact, I hope to present more on the sound manager in the future. In the meantime, I will continue to illuminate Hypercard 2.0. Happy Hacking.

Listing 1:  PlaySndFrag.c
/********************************/
/* File: PlaySndFrag.c    */
/********************************/
#define UsingHypercard

#include  <SoundMgr.h>
#include<SetupA4.h>
#include  <HyperXCmd.h>
/* usage: playSndFrag fileName, soundName, start ,stop
 project requires the following files or libraries:
 ANSI-A4-- the A4 based standard “C” libraries
 HyperXLib-- the xcmd callback glue
 MacTraps -- what it is
 PlaySnd.c-- this file */
 
void    putResult( XCmdPtr pp, char *msg);
void  PlayRunSound( Handle sndHdl, long start, long stop );
long  paramtoNum( XCmdPtr pp, short i );
void  paramtoPString( XCmdPtr pp, short i, char *str );
Handle  strToParam( char  *str );

#ifndef NIL
 #defineNIL (void *)0L
#endif

pascal void main( XCmdPtr pp )
/******************************************
* The main entry point 
******************************************/
{
 short resFile;  /*** resource file holding ‘snd ‘ ***/
 short saveResFile; /*** previous resource file id ***/
 Handle sndHdl; /*** handle to the sound resource ***/
 long start; /*** start sample in sound ***/
 long stop; /*** end sample in sound ***/
 char  *temp[256]; 
 /*** for converting to pascal strings ***/
   
 pp->returnValue = NIL;  /* empty return means OK */
 if (pp->paramCount == 1){
 if ( **(pp->params[0]) == ‘!’ ){
 pp->returnValue = strToParam(“Play Sound XCMD, version 1.0, ©Donald 
Koscheka, 1990”);
 return;
 }
 
 if ( **(pp->params[0]) == ‘?’ ){
 pp->returnValue = strToParam(“PlaySound FILE, ‘snd ‘ rsrc id [,start][,stop]”);
 return;
 }
 }

 paramtoPString( pp, 0, (char *)&temp );           
 start  = paramtoNum( pp, 2 );
 stop   = paramtoNum( pp, 3 );
  
 saveResFile = CurResFile(); /* save current res file id */
 resFile = OpenResFile( temp );
  
 if (resFile == -1) {
 putResult( pp, “can’t open resource file” );
 return;
 }
 
 UseResFile( resFile );  /* in case it was already open */
 paramtoPString( pp, 1, (char *)&temp );
 sndHdl = Get1NamedResource( ‘snd ‘, &temp );
 /* getting the resource ok */
 
 if(!sndHdl){
   putResult( pp, “no such snd” );
 UseResFile( saveResFile ); 
   return;
 }
 
   BEGINXSOUND( pp, NIL );
 DetachResource( sndHdl );
    PlayRunSound( sndHdl, start, stop );
 DisposHandle( sndHdl );
    ENDXSOUND( pp );
    
 UseResFile( saveResFile ); 
}
 
void  PlayRunSound( sndHdl, start, stop )
 Handle sndHdl;
 long   start;
 long stop;
/**********************************
* st[0] determines whether we have a
* format 2 or a format 1 ‘snd ‘ resource.    
* currently use the 44K sampler. Refer to Inside Macintosh Vol V p.494 
for the format of a format 2 ‘snd ‘ resource
**********************************/
{
    short *st;
    long  *lt;
    SndCommand   sndCmd;
   long idx;
 SndChannelPtr theChan  = NIL;
 OSErr    err;
   
 sndCmd.cmd = availableCmd;
 
 if( err = SndControl( sampledSynth, &sndCmd ) ) return;
 if( err = SndNewChannel( &theChan, sampledSynth, initSRate44k, NIL ) 
) return; 
  
 HLock( sndHdl );
   st = (short *)*sndHdl;
 sndCmd.cmd = bufferCmd;
   sndCmd.param1 = 0L;
 if( *st == 2){
 idx  = 6L + ((long)st[2] << 3);
 /* offset to start of commands    */
 lt     = *sndHdl + idx;
   sndCmd.param2 = (long)lt;
   
   if( start )
   lt[0]= (long)*sndHdl + idx + start; 
   
   if( stop )
        lt[1]  = stop  - start;  
        
 err = SndDoCommand( theChan, &sndCmd, FALSE );
   err = SndDisposeChannel( theChan, FALSE );
 }
 HUnlock( sndHdl );
}
 
void putResult( XCmdPtr pp , char *msg )
{
   if (pp->returnValue)   
 DisposHandle(pp->returnValue);  
 
   pp->returnValue = (Handle)NewHandle(1 + strlen(msg) );
   strcpy( *(pp->returnValue), msg);
}
 
Handle  strToParam( char  *str )
/***************************
* Given a pointer to a string, copy that string into a handle
* and return the handle.
* The input and output strings are both null-terminated
***************************/
{
 Handle outH = NIL;
 long len = 0;
 
 len = strlen( str );
 if( len )
 if( outH = NewHandle( len ) )
 BlockMove( str, *outH, len + 1 );
 return( outH );
}

void  paramtoPString( XCmdPtr pp, short i, char *str )
/************************
* Given an index into the parameter list, convert the data
* in the Block into a pstring
*
* This sequence is so common in XCMDs that it makes sense to make it 
a subr. This is a generic routine that you can use in any xcmd.
************************/
{
 if( pp->params[i] ){
 HLock( pp->params[i] );
 ZEROTOPAS( pp, (Ptr)*(pp->params[i]), (StringPtr)str );
 HUnlock( pp->params[i] );
 }
 else
 *str = ‘\0’;
}

long  paramtoNum( XCmdPtr pp, short i )
/************************
* Given a Block to an input argument in the paramBlk
* return an integer representation of the data.
************************/
{
 char   theStr[32];
 
 theStr[0] = ‘\0’;
 if( pp->params[i] ){
 HLock( pp->params[ i ] );
 ZEROTOPAS( pp, (char *)*(pp->params[ i ]), theStr );
 HUnlock( pp->params[ i ] );
 return STRTOLONG( pp, theStr );
 }
 return 0L;
}

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Can PokeMatch help you find love with Po...
The unofficial Pokemon GO companion app space has exploded almost as fast as the game itself over the last few weeks. Aspiring app developers, many of them working solo, have given us apps that locate Pokemon, keep track of the server status, and... | Read more »
How to get started with Prisma
If there's one thing people like to do more than taking pictures with their smartphones, it's tinkering with those photos in some way. Numerous apps have sprung up over the last several years that allow you to use filters and special effects to... | Read more »
6 Pokemon GO updates you can expect, acc...
Pokemon GO had a scheduled appearance at this year's San Diego Comic-Con for a while, but it was only relatively close to the show that it was upgraded to a spot in Hall H. That's the biggest venue at SDCC, one usually reserved for the largest... | Read more »
How to evolve Eevee in Pokemon GO
By now, almost everyone should be hip to how to evolve Pokemon in Pokemon GO (and if not, there's a guide for that). Just gather enough candy of the appropriate type, feed them all to the Pokemon, and evolution happens. It's a miracle that would... | Read more »
CSR Racing 2: Guide to all game modes
It might not seem like there are all that many ways to go fast in a straight line, but CSR Racing 2 begs to differ. [Read more] | Read more »
Bulb Boy (Games)
Bulb Boy 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Multi-award winning 2D point & click horror adventure about a boy with a glowing head. | Read more »
5 top free emoji keyboard apps
If we're not at peak emoji yet as a society, it feels like we definitely should be. The emoji concept has gone far beyond what anyone in Japan could have envisioned when the people there unleashed it on an unsuspecting world, but the West has... | Read more »
How to unlock more characters in Disney...
One of the big charms of Disney Emoji Blitz is seeing a wide variety of beloved Disney and Pixar characters transformed into smiling emojis. Even someone like the sneaky Randall from Monsters Inc., who probably never cracked a smile on film, is... | Read more »
Cubway (Games)
Cubway 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Cubway is a journey with an abstract story of lifecycle of rebirth, called Samsara. Guide the cube through the long way full of dangers... | Read more »
Colorcube (Games)
Colorcube 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Turn pieces and blend colours in this minimal yet visually stunning puzzler.Over 200 handcrafted and challenging levels. Features... | Read more »

Price Scanner via MacPrices.net

GSK Rheumatoid Arthritis Study Leverages iPho...
Global healthcare products company GlaxoSmithKline (GSK) says that since 2014 they have begun transforming the way they conduct research, by leveraging state-of-the-art digital technologies — a... Read more
Clearance 12-inch Retina MacBooks, Apple refu...
Apple has Certified Refurbished 2015 12″ Retina MacBooks available starting at $929. Apple will include a standard one-year warranty with each MacBook, and shipping is free. The following... Read more
13-inch Retina MacBook Pros on sale for up to...
B&H Photo has 13″ Retina MacBook Pros on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY tax only: - 13″ 2.7GHz/128GB Retina MacBook Pro: $1199 $100 off MSRP - 13″ 2.7GHz/... Read more
13-inch 1.6GHz/128GB MacBook Air on sale for...
Amazon has the 13″ 1.6GHz/128GB MacBook Air on sale for $200 off MSRP for a limited time. Shipping is free: - 13″ 1.6GHz/128GB MacBook Air (sku MMGF2LL/A): $799.99 $200 off MSRP Their price is the... Read more
13-inch 1.6GHz/256GB MacBook Air on sale for...
Amazon has the 13″ 1.6GHz/256GB MacBook Air on sale for $200 off MSRP for a limited time. Shipping is free: - 13″ 1.6GHz/256GB MacBook Air (sku MMGG2LL/A): $999.99 $200 off MSRP Their price is the... Read more
Free iOS Business App notably* Helps Service...
PayStudio Inc. has introduced their new business app notably* 1.0, developed for iPhone and iPod touch. notably* was specifically developed to help service and trade professionals go digital and... Read more
27-inch iMacs on sale for $200 off MSRP
Amazon has 27″ iMacs on sale for $200 off MSRP including free shipping: - 27″ 3.3GHz iMac 5K: $2099 $200 off MSRP - 27″ 3.2GHz/1TB Fusion iMac 5K: $1799.99 $200 off MSRP - 27″ 3.2GHz/1TB HD iMac 5K... Read more
Mac Pros on sale for $200 off MSRP
B&H Photo has Mac Pros on sale for $200 off MSRP. Shipping is free, and B&H charges sales tax in NY only: - 3.7GHz 4-core Mac Pro: $2799, $200 off MSRP - 3.5GHz 6-core Mac Pro: $3799, $200... Read more
Save up to $600 with Apple refurbished Mac Pr...
Apple has Certified Refurbished Mac Pros available for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The following... Read more
Apple price trackers, updated continuously
Scan our Apple Price Trackers for the latest information on sales, bundles, and availability on systems from Apple’s authorized internet/catalog resellers. We update the trackers continuously: - 15″... Read more

Jobs Board

*Apple* Retail - Multiple Positions, Willow...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Evangelist - JAMF Software (United S...
The Apple Evangelist is responsible for building and cultivating strategic relationships with Apple 's small and mid-market business development field teams. This Read more
*Apple* Solutions Consultant - APPLE (United...
Job Summary As an Apple Solutions Consultant, you'll be the link between our future customers and our products. You'll showcase your entrepreneurial spirit as you Read more
*Apple* Professional Learning Specialist - A...
Job Summary The Apple Professional Learning Specialist is a full-time position for one year with Apple in the Phoenix, AZ area. This position requires a high Read more
*Apple* Picker - Apple Hill Orchard (United...
Apple Hill Orchard, Co. Rte. 21,Whitehall, NY 9/7/16-10/228/16. Pick fresh market or processing apples Productivity of 60 boxes and 80 boxes processing fruit per Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.