GUS Programmer's Digest Sat Jun 12 00:07 Volume 2: Issue 10 Today's Topics: Double buffering algorithm Looping and wave table generation problems Turbo Pascal SDK alpha release. Standard Info: - Meta-info about the GUS can be found at the end of the Digest. - Before you ask a question, please READ THE FAQ. ---------------------------------------------------------------------- Date: Fri, 11 Jun 93 10:13:21 EST From: support@fortech.com (Technical Support) Subject: Double buffering algorithm Message-ID: <9306111013.0.UUL1.3#16204@fortech.com> Hi folks, I've been watching the postings the last few days on how to implement a double buffering scheme of playing digital audio in the GUS. It is actually quite simple, but I guess I didn't explain it very well in the SDK. I'll give a brief description here and I'll try and work up a simple example over the weekend. (no promises, I'm kinda busy ....) I'll use small numbers for illustrative pruposes. Your buffers would normally be much larger. (This example doesn't worry about start up conditions like not enough data to fill buffers, or exactly what happens at the end when you run out of data.) 1) Probe for card 2) Open Card. 3) Allocate a chunk of DRAM. Lets say it ends up at locations 1000 to 2000. 4) Allocate a voice (assume mono. stereo just confuses the issue) 5) Set up a callback for wave table IRQ's 6) Read in 1000 bytes of data and send it to the card. 7) Start up the voice with looping on, uni-directional, irqs enabled with the begin = 1000, start = 1000 and end = 1500. Also turn on the rollover bit on the volume control register for this voice. This setup will start the voice up and will generate an IRQ at location 1500. However, the voice will NOT loop yet. The rollover bit takes precedence. 8) Wait until your foreground code is told it can load a buffer. (See how the callback is defined below. 9) If filling buffer 0, load 500 bytes into 1000-1500. If filling buffer 1, load 500 bytes into 1500-2000. 10) Goto step #8 till data is gone. 11) Stop voice Free memory. Free Voice. Close card. CALLBACK ======== 1) If you just played buffer 0 (1000-1500), turn OFF the rollover bit and set the voice end address to 2000. (This is so when the voice hits 2000, it will loop back to 1000 and generate an IRQ.) Also tell the foreground that the first buffer can now be filled with new data (1000-1500). This might be done by setting a flag that the foreground checks. If you just played buffer 1 (1500-2000), turn ON the rollover bit and set set the voice end address to 1500. (This is so when the voice hits 1500, it will generate and IRQ and continue without looping) Also tell the forground that the second buffer can now be filled with new data (1500-2000). This might be done by setting a flag that the forground checks. =============================================================================== Thats about all there is to it. I've left out some the the implementation details, but thats the basic flow of the logic. The above method is useful if you have some control over how much data you are going to get and when you can get it. If the data is coming to you is random in length and is under some other applications control, some other considerations come into play. I don't have time to give an example of it right now, but it mainly has to do with tacking the data onto the end of data that is playing and moving the end address to the end of the new data. When you hit the end of the allocated DRAM buffer, send as much data as you can to fill the buffer and turn on the loop bit with IRQ. Send the remaining data down to the beginning of the buffer. When the IRQ comes in, turn the looping off and set the new end address to the end of the remaining data that you put at the beginning of the buffer. Sounds complex, but really isn't too bad. Gotta go get some work done. Hope this helps. Like I said, I'll try and work up a simple example, but I can't promise it'll be done over the weekend. Forte Tech. Support. ------------------------------ Date: Fri, 11 Jun 93 12:20:43 EDT From: davidm@opl.com Subject: Looping and wave table generation problems Message-ID: Hi, GUS Programmers, I have writen a simple program that downloads a sine wave with varying amplitude to the GUS' DRAM and then plays it. I have been experimenting with looping and wave table IRQ generation/handling. It's pretty straight forward stuff. The problem I have is that when I enable wave table IRQ's, I get one IRQ, but no looping even though looping is enabled. This is true with either uni-directional or bi-directional looping. Am I doing something wrong (likely) or is this a bug in the SDK (not likely). BTW, I am using the low level SDK version 2.01. Below I have included the relevant parts of my program. If it is compiled with USEIRQS defined, it plays the wave once and stops and one audible bell character is heard. If it is compiled without USEIRQS defined, everything works exactly as expected (i.e. the wave loops until a key is pressed). This is very puzzling to me. If anyone has any thoughts about what is going on here, I would love to hear them. Thanks, Dave David MacMahon Systems Administrator davidm@opl.com --------------------- // VOIce Control Bits (from appendix C of LOWSRC.DOC v2.01) #define VOICB_8BIT 0 #define VOICB_16BIT 4 #define VOICB_NOLOOP 0 #define VOICB_LOOP 8 #define VOICB_UNIDIR 0 #define VOICB_BIDIR 16 #define VOICB_NOWTIRQ 0 #define VOICB_WTIRQ 32 // Global variable int irqcount; void HandleWave( int voice_num) { irqcount++; } void main() { . . [initialization, wave generation and download code deleted] . // Grab the wave handler OldWaveHandler = UltraWaveHandler( HandleWave); #ifdef USEIRQS LoopType = VOICB_LOOP | VOICB_UNIDIR | VOICB_WTIRQ; #else LoopType = VOICB_LOOP | VOICB_UNIDIR | VOICB_NOWTIRQ; #endif // Start voice UltraStartVoice( voice_num, Begin, Start, End, VOICB_8BIT | LoopType); // Wait printf( "Playing... Press any key to quit."); while( !kbhit()) { if( irqcount) { // If there have been wave table IRQ's, // beep PC speaker and reset IRQ counter printf("\a"); irqcount = 0; } } . . [clean-up code deleted] . } ------------------------------ Date: Fri, 11 Jun 93 15:00 EDT From: "Matthew E. Bernold" Subject: Turbo Pascal SDK alpha release. Message-ID: <9306111859.AA13489@orca.es.com> Is anyone out there interested in a Pascal translation of the SDK? I have succeeded in translating about half of the SDK directly from C to Pascal, and am looking for some testers. If you are interested, please E-mail me directly. Once I get all the functions translated, I will release a full beta version on Epas, but for now, I'd like to try a limited distribution. Also, I'm having a few difficulties in some of the translation problems. If anyone out there is fluent in both C and Pascal, and has experience with interrupt handlers and DMA stuff, please drop me a line so I can ask a few questions and get this thing finished. Matthew E. Bernold MEB117@PSUVM.PSU.EDU <> meb@wilbur.cac.psu.edu ------------------------------ End of GUS Programmer's Digest V2 #10 ************************************* To post to tomorrow's digest: To (un)subscribe or get help: To contact a human (last resort): FTP sites: archive.epas.utoronto.ca pub/pc/ultrasound wuarchive.wustl.edu systems/msdos/ultrasound Hints: - Get the FAQ from the FTP sites or the request server. - Mail to for info about other GUS related mailing lists (UNIX, OS/2, GUS-MIDI, etc.)