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;
}

 
AAPL
$570.56
Apple Inc.
+13.59
MSFT
$29.11
Microsoft Corpora
-0.65
GOOG
$609.46
Google Inc.
+8.66
MacTech Search:
Community Search:

Fruit Ninja Gets New Update With Powerup...
Fruit Ninja is about to get its biggest update yet to celebrate its second anniversary on Thursday, May 24th. The key new element in the game appears to be that players will now be able to earn an in-game currency, called starfruit, that can be used... | Read more »
Fotor – CameraBag Review
Fotor – CameraBag Review By Jennifer Allen on May 23rd, 2012 Our Rating: :: PLENTIFULiPhone App - Designed for the iPhone, compatible with the iPad A photography app that wants to be able to do everything that could ever be asked... | Read more »
playGO AP1 is the Next Generation of Aud...
With all of Apple’s relatively recent success in the smartphone and tablet market, we can forget sometimes that what kicked off their modern dominance was a device that simply played music. BICOM, Inc. has been recognizing how important music is to... | Read more »
Monkey Pong Review
Monkey Pong Review By Angela LaFollette on May 23rd, 2012 Our Rating: :: BALL BUSTING ACTIONiPhone App - Designed for the iPhone, compatible with the iPad Help the hungry monkey reach all the fruit by bouncing a ball in this family... | Read more »
Heroes & Generals Enters Closed Beta
Creators of Hitman, Roto-Moto, has launched a closed beta of their game, Heroes & Generals. The game is a massively multiplayer first-person shooter involving online fighting between the Axis and Allied forces in Europe. | Read more »
FeedFriendly Review
FeedFriendly Review By Angela LaFollette on May 23rd, 2012 Our Rating: :: EASY TO USEUniversal App - Designed for iPhone and iPad Combine the top three social network newsfeed updates into one location with the help of FeedFriendly... | Read more »
Favorite 4: Euro 2012 Apps
In a matter of weeks, one of the biggest soccer tournaments out there begins: Euro 2012. Qualification is over and 16 European teams are all lined up to prove which one is the best of the bunch. As a Brit, I’m ever hopeful that England will achieve... | Read more »

Price Scanner via MacPrices.net

Are You Sure You Really Want A Retina Display MacB...
Apple didn’t invent the laptop computer, but over the past 21 years they’ve continuously set and reset the bar for laptop innovation and engineering advances, with PC competitors mostly playing catch... Read more
Two PC Pundits Weigh In On PC To Mac Switching (Or...
ZNet’s Stephen Chapman and Forbes’ Brian Caulfield have posted recent blogs on the topic of their personally switching from Windows PCs to Macs. From PC to Mac 10-Months Later ZNet blogger Stephen... Read more
Apple Maintains Top Mobile PC Share in Q112 on Str...
Apple shipped nearly 17.2 million mobile PCs in Q112, accounting for 118% year-over-year shipment growth, according to preliminary results from the latest NPD DisplaySearch Quarterly Mobile PC... Read more
Apple offering refurbished 17″ MacBook Pros for $3...
 The Apple Store has Apple Certified Refurbished 17″ 2.4GHz MacBook Pros available for $2119 including free shipping. That’s $380 off the price of new models. Apple’s one-year warranty is standard. Read more
Week’s Best MacBook Deals
We’ve posted the Week’s Best Deals on MacBook Airs and MacBook Pros for Wednesday, the 23rd of May. Find the lowest price or the best set of bundles from Apple’s Authorized Resellers with these deals... Read more
MacBook Airs on sale for up to $101 off MSRP, free...
 Adorama has MacBook Airs on sale today for up to $101 off MSRP including free shipping. NY and NJ sales tax only. Their prices are among the lowest available for these models from any Apple... Read more
Open-box special: 2.3GHz Mac mini for $493
MacMall has open-box return 2.3GHz Mac minis available for $493 including free shipping. That’s $106 off MSRP. Apple’s one-year warranty and all materials are included. Act now if you’re interested,... Read more
Apple iPhone Charger’s Secrets And Engineering Sup...
Blogger Ken Shirriff’s has posted a thoroughgoing Apple iPhone charger teardown and analysis, the one-line takeaway being: “quality in a tiny expensive package.” Shirriff says that disassembling... Read more

Jobs Board

*Apple* Solutions Consultant-Retail Sal...
Requisition Number 15545402 Job title Apple Solutions Consultant-Retail Sales Location Mobile Country United States City Mobile State Alabama Job type Job description Read more
iPhone Developer at Mastech (Los Angeles...
We are currently seeking an Android/ iPhone Developer for our client in the Insurance domain. We value our professionals, providing comprehensive benefits, exciting challenges, and the opportunity... Read more
24 funny 2d Charaters for iPhone game. a...
We are developing an iPhone game and desire to have 24 characters drawn to our specification. Attached is the detailed spec. Desired Skills: Cartoon, Illustration Read more
*Apple* Solutions Consultant-Retail Sal...
Requisition Number 15545261 Job title Apple Solutions Consultant-Retail Sales Location Spanish Fort Country United States City Spanish Fort State Alabama Job type Job Read more
Android and Iphone Application at Elance...
I need an interval timer application to be created for iphone and android platforms... I am on a tight budget but this ... & IPHONES) not just one so if you can only do one don't waste your time... Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.