farren@well.UUCP (Mike Farren) (06/21/89)
Well, having just fought my way through a three-week battle with the audio.device, I thought I'd put a few notes out, for all of you folks who might want to do real nice sounds, and lots of 'em... I have just completed the conversion of the Macintosh game "Crystal Quest" to the Amy. CQ is noted for its interesting sampled sounds on the Mac, and one of the primary goals of the conversion was to replicate those sounds. "No problem," I think, "I'll just whip up a quick audio IO routine." So, I did something that looks like this: Init - allocate four channels, three ioa's per channel for bookkeeping convenience. Play - check channel with CMD_READ. If busy, issue CMD_RESET (or, at one point, CMD_FLUSH), Wait() for return. Then, issue CMD_WRITE to produce sound. repeat as necessary (sometimes, many times per second as events occur). The result: occasional crashes which had as their main symptom a total lock of the machine, accompanied by either endlessly repeating CQ sounds, or something which _sounded_ like the audio channel was "playing" some system memory or other - you could hear the keyboard, mouse, and disk accesses over the audio channels! O.K., says I - this means that I can't use the audio.device routines. I'll have to roll my own. No problem - just stuff stuff into the registers directly, and provide a new interrupt routine to service the audio interrupt. Well, there's a problem here, too - the documentation for the audio hardware is sadly deficient. They tell you that the hardware issues an interrupt at the end of the audio block, which is great - that allows you to shut the damn thing off to prevent infinite repeats. What they only mention in two spots in the Hardware manual, and in fine print at that, is that that is not the only time the hardware issues an audio interrupt. It also issues the interrupt when the registers you've stuffed data into are copied into the actual working registers in the hardware, i.e., when you initially turn on audio DMA. What's more, there is no way that I could see to determine unequivocally WHICH of the two circumstances caused the interrupt, from the point of view of the interrupt routine. No flags, no nothing. Here's what I ended up with: Play sound: turn off audio DMA. Wait enough time to be SURE that the channel is reset (I used MOVE #100,D0 - DBF d0,<here> - probably overkill). Stuff values into registers, set a flag to 1, turn on DMA. Audio Interrupt: check flag. If 1, set the flag to 2, return. If 2, turn off audio DMA, wait enough time (again) to be sure channel is reset, set flag to 0, return. It would have been a lot handier if C/A had provided two things: first, a flag to indicate which of the two states had caused the interrupt. Second, a "hard reset" capability for the channel which would not require waiting "approximately two sampling periods" to ensure the actual resetting of the channel. While it seems to work o.k., I hate the idea of delay loops in an interrupt routine - it's not very polite, you know? -- Mike Farren uucp: well!farren
cmcmanis%pepper@Sun.COM (Chuck McManis) (06/22/89)
In article <12293@well.UUCP> farren@well.UUCP (Mike Farren) writes:
->Here's what I ended up with:
->
->Play sound: turn off audio DMA. Wait enough time to be SURE that the
->channel is reset (I used MOVE #100,D0 - DBF d0,<here> - probably overkill).
-->Stuff values into registers, set a flag to 1, turn on DMA. ...
-> ... While it seems to work o.k., I hate
->the idea of delay loops in an interrupt routine - it's not very polite,
->you know?
Ever tried it on a 68020 or 030? Bet it isn't "overkill" any more.
I think there must be a better answer and one that will work on all
processors as well. Have you seen Bryce's article "How to waste time" ?
--Chuck McManis
uucp: {anywhere}!sun!cmcmanis BIX: cmcmanis ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.
"A most excellent barbarian ... Genghis Kahn!"
kent@swrinde.nde.swri.edu (Kent D. Polk) (06/23/89)
In article <12293@well.UUCP> farren@well.UUCP (Mike Farren) writes: >Well, having just fought my way through a three-week battle with the >audio.device, I thought I'd put a few notes out, for all of you folks >who might want to do real nice sounds, and lots of 'em... Check out Rob Peck's Audiotools (almost) library. The functions may be fast enough for your application. At least it's a good tutorial. Saved me an uncountable number of hours. Now, I just need to figure out how to modulate one channel from another using my own samples (looooong ones) :^) >Init - allocate four channels, three ioa's per channel for bookkeeping >convenience. myport = InitAudio() channel = GetChannel(x) >Play - check channel with CMD_READ. If busy, issue CMD_RESET (or, at PlayFreq(channel, freq, wf, vol, duration, priority, messageport, id) PlayNote(channel, note, wf, vol, duration, priority, messageport, id) MayGetNote(port, flag) /* if flag is nonzero, wait for message from the next * Play*() which was instructed to send a message * when it started playing. */ >Second, a "hard reset" capability for the channel which would not >require waiting "approximately two sampling periods" to ensure the >actual resetting of the channel.[...] FlushChannel(channel) /* Immediately stop playing this channel */ Lots more neat stuff. Also, version 3 (1.3?) supports playing samples (supposedly). I haven't received the new version yet. ======================================================= Kent Polk - Southwest Research Institute {cs.utexas.edu, gatech!petro sun!texsun}!swrinde!kent kent@swrinde.nde.swri.edu ------------------------------------------------------- "Anything worth doing is worth overdoing" =======================================================
rap@ez.ardent.com (Rob Peck) (06/23/89)
In article <17648@swrinde.nde.swri.edu> kent@swrinde.UUCP (Kent D. Polk) writes: >In article <12293@well.UUCP> farren@well.UUCP (Mike Farren) writes: >>Well, having just fought my way through a three-week battle with the >>audio.device, I thought I'd put a few notes out, for all of you folks >>who might want to do real nice sounds, and lots of 'em... > >Check out Rob Peck's Audiotools (almost) library. The functions may be >fast enough for your application. At least it's a good tutorial. Saved >me an uncountable number of hours. Just for those who need the info... Audiotools release 3 was placed on the Washington DC Devcon disks and included in the conference notes. I hope to have a release 4 available in another 3-4 months, depending on other things gettin in the way so to speak. Particularly to include one channel modulating another as Kent wants to do (if he figures it out, I wanna see it). And yes, release 3 has PlaySamp(...) for sampled sounds. An alert of things-to-come is that the NEXT issue of Compute's Amiga Resource (Summer '89???) in my column I answer the question "How Can I Play A Sampled Sound?". A short program reads and parses an 8SVX IFF sampled sound ("hello" or "hello, world") and sets up the audio device to play it back exactly as recorded. The trick was to set the appropriate parameters based on what is read from the 8SVX file which was 8343 samples per second. The other trick was to calculate the proper sampling rate even though using exclusively integer arithmetic in 32-bits max width. I think I even got it right (whew). Anyway, the compiled version (lattice 5.02, with no option flags set) is about 8600 bytes, and the PD program that does the same thing on the Audiomaster II disk (maybe it does more, but who knows) is slightly over 18k. Oh yes, theirs runs from Workbench, to keep code size down, mine is CLI only, but can be run from ICONX to get wbench support, so to speak. Now that I know how to calculate from sample rates, this'll be in the next audiotools. Nother thing that will definitely go in is converting it fully to a shared library, and probably AREXX support so that directly under AREXX, the equivalent of PlayNote/PlayFreq/PlaySamp could be called. ============= For any who already HAVE the audiotools... note that I'll likely remove support for permanently allocated i/o control blocks, assigning only dynamic ones. As seen in the source code, they are handled a little differently and someone once ran into a bug for which no static i/o blocks were playing on any channel and yet something in the system thought that at least one was not yet "back" from doing its job. Nobody else ever reported a similar bug, but I may not want to take a chance. Handle everything the same, and shrink code size as well. Rob Peck DATAPATH, POBox 1828, Los Gatos, CA 95031