Thread View: comp.sources.mac
1 messages
1 total messages
Started by Dwight Hare
Thu, 31 Mar 1988 04:53
Example use of Mac II sound chip
Author: Dwight Hare
Date: Thu, 31 Mar 1988 04:53
Date: Thu, 31 Mar 1988 04:53
185 lines
6367 bytes
6367 bytes
[Example use of Mac II sound chip]
I found programming the Mac II sound chip using the new interface
described in IM Vol. V hard to figure out, so I thought others might
be interested in what appears to be a successful program to play
buffers of sampled sound. If all of this is obvious to anyone, I'd
like to hear from you!
Dwight
dhare@sun.com
---
/*
* play.c - use the mac II sound chip to play a sampled sound in chunks.
* The eventual purpose is to do some animation in synch with the music.
* Written in MPW C by Dwight Hare, March, 1988.
*/
/* The following defines and data structures are used from sound.h:
*
* #define callBackCmd 13
* #define bufferCmd 81
* #define initMono 0x80
*
* typedef struct SndCommand {
* unsigned short cmd;
* short param1;
* long param2;
* } SndCommand;
*
* typedef struct SndChannel {
* struct SndChannel *nextChan;
* ModifierStubPtr firstMod;
* ProcPtr callBack;
* long userInfo;
* Time wait;
* SndCommand cmdInProgress;
* short flags;
* short qLength;
* short qHead;
* short qTail;
* SndCommand queue[stdQLength];
* } SndChannel, *SndChannelPtr;
*
* typedef struct SoundHeader {
* char * samplePtr;
* unsigned long length;
* Fixed sampleRate;
* unsigned long loopStart;
* unsigned long loopEnd;
* short baseNote;
* char sampleArea[0];
* } SoundHeader, *SoundHeaderPtr;
*/
#define __ALLNU__ /* needed to get new sound stuff in Sound.h */
#include <memory.h>
#include <sound.h>
#include <toolutils.h>
#define NIL (Ptr)0
/*
* This callback routine is used to indicate when a sound has finished
* (I haven't found any other way to do it).
*/
pascal void
snd_done(chan, cmd)
SndChannelPtr chan;
SndCommand *cmd;
{
chan->userInfo = 1;
}
/*
* play plays the given sound in "sample" of length "len" at the sampled
* rate "rate" (typically 22255 for a Soundwave sample at the highest
* rate) and plays the sound in "incr" chunks (22255 would play in
* one second chunks at the rate of 22255).
*/
OSErr
play(sample, len, rate, incr)
unsigned char *sample;
long len, rate, incr;
{
unsigned char *Sp;
SndChannelPtr sndp = NIL;
SndCommand playcmd, callcmd;
SoundHeaderPtr playbuf, playbuf1, playbuf2;
long i;
OSErr err;
/*
* We need two buffers for the bufferCmd since the first one
* isn't quite finished when we set up the second one.
*/
playbuf1 = (SoundHeaderPtr)NewPtr(sizeof(SoundHeader));
playbuf2 = (SoundHeaderPtr)NewPtr(sizeof(SoundHeader));
if (playbuf1 == NIL || playbuf2 == NIL) {
return(-1);
}
/*
* The loopStart, loopEnd, and baseNote are for playing the
* sampled sounds as notes, we are not using that feature.
*/
playbuf1->sampleRate = FixRatio(rate, 1);
playbuf2->sampleRate = FixRatio(rate, 1);
playbuf1->loopStart = 0;
playbuf2->loopStart = 0;
playbuf1->loopEnd = 0;
playbuf2->loopEnd = 0;
playbuf1->baseNote = 60;
playbuf2->baseNote = 60;
/*
* Create a new sound channel using the sampled synthesizer played
* in mono. The callback routine will be used below to determine
* the end of the sound.
*/
if ((err = SndNewChannel(&sndp, sampledSynth, initMono, snd_done))
!= noErr) {
return(err);
}
/*
* The playcmd is used in a SndDoCommand. The bufferCmd plays the
* buffer pointed to by param2 (set below).
*/
playcmd.cmd = bufferCmd;
playcmd.param1 = 0;
/*
* The callcmd is used in a SndDoCommand. The callBackCmd calls
* the callback routine (snd_done) specified in the SndNewChannel
* call. This callback will be put after each play cmd to indicate
* when a sound has (almost) finished.
*/
callcmd.cmd = callBackCmd;
callcmd.param1 = 0;
callcmd.param2 = 0;
/* We start with the first playbuf */
playbuf = playbuf1;
for (i = len, Sp = sample; i > 0; i -= incr, Sp += incr) {
/* change buffers */
if (playbuf == playbuf1)
playbuf = playbuf2;
else playbuf = playbuf1;
/* set the buffer length to either the increment or
the rest of the sample */
playbuf->length = i < incr? i : incr;
/* Set the pointer to the sound to be played */
playbuf->samplePtr = Sp;
/*
* Set the bufferCmd pointer to this buffer. This command
* buffer is copied by the SndDoCommand so we don't need
* two of them
*/
playcmd.param2 = (long)playbuf;
/* set the flag we use in snd_done to indicate the finish */
sndp->userInfo = 0;
/* Play the buffer */
if ((err = SndDoCommand(sndp, &playcmd, true)) != noErr) {
return(err);
}
/* Put the callback in the queue after the sound */
if ((err = SndDoCommand(sndp, &callcmd, true)) != noErr) {
return(err);
}
/* Now wait for the sound to finish (later we'll do some
animation) */
while(sndp->userInfo != 1);
}
/*
* Cleanup
*/
if ((err = SndDisposeChannel(sndp, false)) != noErr) {
return(err);
}
DisposPtr(playbuf1); DisposPtr(playbuf2);
return(noErr);
}
---
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads