RUCKUS-DAC Copyright (C)1993 Cornel Huth Documentation Copyright (C)1993 Cornel Huth All Rights Reserved. Version 1.00. For ordering information, license agreement, and product support information, see Appendix Z. Introduction RUCKUS-DAC is one part of the RUCKUS sound toolkit for DOS programmers. Its forte is its ability to play digital data in three different formats and record in two: VOC, WAVE, and MOD. The other part of the RUCKUS sound toolkit is RUCKUS-MIDI. Its forte is its ability to play standard MIDI data files. See RUCKUS-MIDI for more. RUCKUS-DAC currently supports six sound devices: the PC speaker, a DAC on an LPT port, Disney Sound Source, AdLib MSC, Sound Blaster, and the Sound Blaster Pro (stereo). Since most sound devices emulate one of the above, RUCKUS-DAC should handle most devices likely to be found in a PC. RUCKUS- DAC is implemented to be device-independent. As new sound hardware (with supporting documentation) becomes available to this programmer, it will be added. The code you write to play any of the digital formats using RUCKUS will play on any new device added later without any code changes to your program. You just supply the new device ID (see InitDac for more). The RUCKUS toolkit supports most DOS compilers as is. This documentation describes using RUCKUS with BASIC DOS compilers. Also available is a C- specific version of this documentation. Other implementations should be able to get the necessary details using this documentation. Note that these toolkits will not work with the current or past Turbo Pascal compilers. This is due to Turbo Pascal's proprietary linkage methods. To provide compiler-independence, RUCKUS (and all of my latest toolkits) implements a simple calling scheme: a single far pointer (segmented) is passed to RUCKUS. The data structure that is pointed to varies depending on RUCKUS function. There are 13 structure types ("packs") currently. The first two data members of each pack are identical in all packs. These are Func and Stat. The remaining members, if any, vary depending on requirements. For instance, the LoadDac routine uses, in addition to Func and Stat, six additional members: FilenamePtr, StartPos, LoadSize, XMMflag, XMMhandle and LoadPtr. The steps needed to load a digital (LoadDac is for VOC/WAVE files, LoadMod is for MOD files) data file to memory would be as follows: 1. Allocate pack. Packs are reusable and can be allocated any way you want. Here we make a static allocation for simplicity. DIM LP AS LoadPackTYPE 2. Assign member values: filenameZ$ = file$ + CHR$(0) 'must terminate string with 0 LP.Func = LoadMidi LP.FilenamePtr = SADD(filenameZ$) LP.FilenamePtrSeg = VARSEG(filenameZ$) 'LP.FilenamePtrSeg = SSEG(filenameZ$) 'for BASIC7/VBDOS LP.StartPos = 0& LP.LoadSize = 0& LP.XMMflag = 0 3. Call RUCKUS: stat = RUCKDAC(LP) 4. On return from the call: IF stat = 0 THEN ' LP.LoadPtr -> address of digital data in memory 'or, if XMMflag then LP.XMMhandle = XMS handle of storage After the load you can immediately call the PlayDac routine using the LP.LoadPtr returned from the LoadDac call. You don't need to use the RUCKUS LoadDac routine; you can perform your own digital data file loads to memory (VOC and WAV only, MODs must be loaded by RUCKUS-DAC). However, RUCKUS can load up to 32 separate digital files at one time (and 96 more to XMS) and performs all the necessary memory allocations and deallocations automatically. See LoadDac/LoadMod for more. As you can see, using RUCKUS is easy. If you'd rather use a traditional calling convention, wrap the RUCKUS routines in a BASIC function and call it as you normally would, i.e., stat = LoadDacFile(file$,LP) where LoadDacFile contains the actual code (as shown above). Now that I have your interest, let me tell you why I've provided this toolkit for you. Shareware. That's right. Shareware. What I've done is provide you with a means to evaluate this product completely, with no upfront obligations. If you can't make use of this product, no problem. Think of this as the ultimate return policy. You can actually take the goods home, try it out, break it in. Then, if after a period of no more than 21 days, you feel that this product is well worth the price I'm asking, by all means, you should go ahead and fill out the order form and send it in. If you do not register, then of course, it means the product is not something you can use. If you can't use it, I don't want your money. But if it's something you will use, it's only fair that you register. The PROFESSIONAL registered versions does not have any built-in advertising screens. The PERSONAL DEVELOPER registered version does display a sign-on banner once. See Appendix Z. for ordering options and other related information specific to this product. The documentation that follows describes each of the function routines as to use, pack type used, and sample code in BASIC. Also available is a C version of this toolkit, differing only in example programs and documentation*. For additional source examples see the included X files on disk. *There is a specific object module that must be used with any Borland C compiler, but this LIB will work for other C compilers. RUCKUS-DAC Functions. 0. SysInfoDac ........................................... 5 1. InitDac .............................................. 7 2. ExitDac .............................................. 8 3. AtExitDac ............................................ 9 4. LoadDac .............................................. 10 5. PlayDac .............................................. 12 6. RecordDac ............................................ 13 7. StoreDac ............................................. 15 8. EndDac ............................................... 16 9. PauseDac ............................................. 17 10. DeallocDac ........................................... 18 11 to 19 are not used 20. SetAllDac ............................................ 19 21. SetVolumeDac ......................................... 21 22. SetIntRateDac ........................................ 22 23. SetPriorityDac ....................................... 23 24 to 27 are not used 28. GetBufferDataDac ..................................... 24 29. GetBytePosDac ........................................ 25 30. SetAllSBP ............................................ 26 31. SetVolMainSBP ......................................... 28 32. SetVolVocSBP ......................................... 29 33. SetLevelMicSBP ....................................... 30 34. SetLevelCDSBP ....................................... 31 35. SetLevelLineSBP ...................................... 32 36. SetFilterOutSBP ...................................... 33 37. SetFilterInSBP ....................................... 34 38. SetSourceSBP ......................................... 35 39. SetStereoSBP ......................................... 36 40. SetSpeakerSB ......................................... 37 41 to 47 are not used 48. GetMixerRegSBP ....................................... 38 49. GetDacSB .............................................. 39 50. ExitMod .............................................. 40 51. AtExitMod ............................................ 41 52. LoadMod .............................................. 42 53. PlayMod .............................................. 43 54. EndMod ............................................... 44 55. PauseMod ............................................. 45 56. SetIntRateMod ......................................... 46 57. SetSpeedMod ........................................... 47 58. SetVolumeMod ......................................... 48 59. SetPositionMod ........................................ 49 60. SetStereoMod .......................................... 50 61. SetFastMod ............................................ 51 Appendix A. Tips and Tricks ........................... 52 Appendix B. Pack Structure ............................ 53 Appendix C. Compiler, Linker, QLB, and Call Use ....... 58 Appendix D. RUCKUS-DAC Data Area ...................... 60 Appendix Z. Ordering Information, License Agreement and Product Support........................ 62 SysInfoDac Func: 0 Pack: SysInfoPack Before doing any other RUCKUS function, you should call SysInfoDac to determine what sound devices are available. RUCKUS-DAC currently supports the following devices: 0. PC speaker 1. LPT-DAC device on a printer port, commonly home-built 2. Disney Sound Source, a printer port DAC device 3. AdLib Music Synthesizer Card 4. Sound Blaster (DSP version 1.03 and up) 5. Sound Blaster Pro 6. UltraSound* *The UltraSound (GUS) will be supported in the next release. Since many current sound cards are Sound Blaster compatible, RUCKUS-DAC supports somewhere around 95% of all sound devices in active use on PC- compatible computers. SysInfoDac scans for and detects all devices. In the case of the DAC on the printer port (LPT-DAC), it can only detect if a printer port is available. All other sound cards are detected by their manufacturer's documented methods, and should be 100% reliable. Information returned includes the device's base port address, IRQ line, DMA channel, and capabilities. Since the SB Pro is SB-compatible, and since the SB is AdLib-compatible, these lower devices are also detected in these cards. Sample Use (QuickBASIC 4.5): DIM SIP AS SysInfoPackTYPE SIP.Func = SysInfoDac 'SysInfoDac is a CONST in RUCKDAC.BI stat = RUCKDAC(SIP) 'call to RUCKUS library code IF stat = 0 THEN PRINT "CPU type is "; SIP.CPU PRINT "MHz (approx)"; SIP.MHZ IF SIP.Device5 THEN PRINT "SB PRO at port ";HEX$(SIP.D5port) IF SIP.Device4 THEN PRINT "SB 1.5 at port ";HEX$(SIP.D4port) IF SIP.Device3 THEN PRINT "AdLib at port ";HEX$(SIP.D3port) IF SIP.Device2 THEN PRINT "Disney at port ";HEX$(SIP.D2port) IF SIP.Device1 THEN PRINT "LPT-DAC at port ";HEX$(SIP.D1port) PRINT "PC speaker always available" ENDIF 5 Sample Use (BASIC 7.1/ VBDOS): NOTE: THE ONLY DIFFERENCE IN USING BASIC 7.1 WITH REGARD TO RUCKUS IS THE METHOD OF GETTING A STRING'S ADDRESS. FOR QUICKBASIC, USE VARSEG/SADD. WITH BASIC 7.1 OR VBDOS, USE SSEG/SADD. Since BASIC7 allows arrays in TYPE variables, we use that feature to simplify the variable. You can use the other TYPE variable if you want, but this way seems more versatile to me. To use the SysInfoPackTYPE7 you must uncomment-out the definition in the RUCKDAC.BI file. DIM SIP AS SysInfoPackTYPE7 'NOTE the 7 at the end SIP.Func = SysInfoDac 'SysInfoDac is a CONST in RUCKDAC.BI stat = RUCKDAC(SIP) 'call to RUCKUS library code IF stat = 0 THEN PRINT "CPU type is "; SIP.CPU PRINT "MHz (approx)"; SIP.MHZ FOR i = 5 TO 1 IF SIP.SD(i).device THEN SELECT CASE i CASE 5: PRINT "SB PRO at port ";HEX$(SIP.SD(5).port) CASE 4: PRINT "SB 1.5 at port ";HEX$(SIP.SD(4).port) CASE 3: PRINT "AdLib at port ";HEX$(SIP.SD(3).port) CASE 2: PRINT "Disney at port ";HEX$(SIP.SD(2).port) CASE 1: PRINT "LPT-DAC at port ";HEX$(SIP.SD(1).port) ENDIF NEXT PRINT "PC speaker always available" ENDIF 6 InitDac Func: 1 Pack: InitPack Before you can use a sound device, you must inform RUCKUS about it. The InitDac routine sets up default sets of data that RUCKUS uses, or that you can later change. You cannot operate a device until you have called this routine. You should not InitDac more than one sound device at a time. If you want to use a different device, first ExitDac then InitDac again. The information that InitDac requires is available from the SysInfoDac routine. InitDac returns with information on its data section address and size, and the address of the ExitDac routine (in case AtExitDac doesn't work for your esoteric compiler or run-time library). InitDac is used for both RUCKUS-DAC and the RUCKUS-DAC mod extension code. There is a special feature available for the PC speaker and the AdLib devices: 2x upsampling. To use 2x upsampling, use the I/O port as returned by SysInfoDac for IP.IOport. To use standard (in some cases downsampling) play for the PC speaker and AdLib (recommended for play of samples with rates above 8kHz) use an IP.IOport=0. For an example of 2x upsampling see the MODAC1 documentation. Upsampling is available only for VOC and WAVE playback. Sample Use: DIM IP AS InitPackTYPE 'in RUCKDAC.BI IP.Func = InitDac 'CONST in RUCKDAC.BI IP.DeviceID = device 'see SysInfoDac for device numbers IP.IOport = port 'and other info needed by InitDac IP.IRQline = IRQ IP.DMAch = DMA stat = RUCKDAC(IP) IF stat = 0 THEN 'device initialized okay 'By using the pointer returned by InitDac, we can check on any 'RUCKUS-DAC data value (fully documented in DACDATA.DOC) fast 'DEF & PEEKing are much faster than separate function calls DEF SEG = IP.InfoPtrSeg DacEnd = PEEK(IP.InfoPtrOff + 10) 'since nothing is playing this=1 DEF SEG ENDIF 7 ExitDac Func: 2 Pack: XitPack When using RUCKUS, certain aspects of the computer are controlled by the RUCKUS code. To have RUCKUS return full control back to the computer and operating system, ExitDac must be called. To ensure that this happens, even after an abnormal termination (such as an untrapped divide by zero), RUCKUS provides a routine that ensures that ExitDac is always called before your application ends. See AtExitDac for more. Once a sound device has been initialized with InitDac, you must call ExitDac before you can switch to another device with InitDac. Calling ExitDac releases any memory allocations made while the previous sound device was active (allocations made by LoadDac, LoadMod, or RecordDac). Memory allocations that your program has made on its own are not affected. Tip: If you call InitDac with one device, load a file, then call InitDac again with another device, the memory allocated by the load is not released. This allows you to play data from previous load operation(s) on all the RUCKUS-supported devices. To force the release of a previous memory allocation, see DeallocDac. Sample Use: DIM XP AS ExitPackTYPE XP.Func = ExitDac stat = RUCKDAC(XP) IF stat THEN 'error 8 AtExitDac Func: 3 Pack: XitPack To ensure that all machine control is returned to the operating system and that all RUCKUS-made memory allocations are released before your application program ends, AtExitDac should be used. This routine takes advantage of most compiler's _atexit enregistration routine. This _atexit compiler run-time library routine allows for up to 32 different calls to be made just prior to it (the compiler's run-time code) returning to the operating system (program termination). Most of the time, you can make all the necessary shutdowns that your program requires in your app's code. However, abnormal terminations -- terminations that can cause a bypass of your own shutdown code -- may mean that when the operating systems regains control, certain machine operations are not in a stable state. The AtExitDac routine ensures that ExitDac is called no matter what (in most all cases, except where the program locks up, in which case the session needs to be reset anyway). Note: AtExitDac should be called only once in your program's execution. Graphically, your program executes like this: DOS C>program.exe | Compiler startup code (performs basic setup) | +----->+ | Your program starts, ends +<-----+ | rest of startup code, _atexit registered routines | DOS C>_ Caution: In order for the _atexit registered routines to be called by your compilers run-time, you must not allow you program to exit via non-standard ways. Calling INT21/4C is on example (you should never do this from compiled code, anyway). The startup code is basically a program that sets up your program to run, calls your program, regains control when your program ends, then performs the necessary shutdown actions required, including calling all routines registered with _atexit. Sample Use: DIM XP AS ExitPack XP.Func = AtExitDac stat = RUCKDAC(XP) IF stat THEN PRINT "_atexit is full (more than 32 calls made to _atexit)" 9 LoadDac Func: 4 Pack: LoadPack Though not required, you can have RUCKUS load a digital file into memory for you. It makes the necessary memory allocations and loads the data into conventional or XMS memory. You can load up to 32 separate digital data files to conventional memory at one time, and up to 96 more into XMS. RUCKUS takes care of the memory allocation details. LoadDac can also be instructed to start loading at any particular byte in a file for as many bytes as you specify. This would be useful, for example, if you have a single file made up of several VOC or WAVE files appended to form one large data file. Sample Use: DIM LP AS LoadPackTYPE nix& = SETMEM(700000) mem& = SETMEM(0) IF YouWillBeUsingConventionalMemory THEN nix& = SETMEM(mem& - 2100) 'release all but 2K to the OS 'or as much as needed to store file ELSE nix& = SETMEM(-66000) 'release 64K for temp RUCKUS use 'until after the load into XMS ENDIF LP.Func = LoadDac LP.FilenamePtrOff = SADD(filename$) LP.FilenamePtrSeg = VARSEG(filename$) 'BASIC7 use: 'LP.FilenamePtrOff = SADD(filename$) 'LP.FilenamePtrSeg = SSEG(filename$) LP.StartPos = 0& 'start load at first byte of file LP.LoadSize = 0& 'have RUCKUS load all of it LP.XMMflag = 0 '-1 if loading into XMS stat = RUCKDAC(LP) IF stat = 0 THEN If YouWillBeUsingConventionalMemory THEN ThisDataLoadOff = LP.LoadPtrOff 'needed for later PlayDac ThisDataLoadSeg = LP.LoadPtrSeg nix& = SETMEM(700000) ELSE ThisDataXMShandle = LP.XMMhandle nix& = SETMEM(66000) 'return the 64K to BASIC ENDIF ELSE nix& = SETMEM(700000) '700,000 tells BASIC to reclaim unused memory 'file load error in stat ENDIF 10 'See how much memory was used by this _particular_ load, in K, 'and how much conventional and XMS memory remain DEF SEG = IP.InfoPtrSeg 'IP.InfoPtrSeg returned from InitDac call bp = IP.InfoPtrOff 'assign to make typing shorter Kused = (256 * PEEK(bp + 23)) + PEEK(bp + 22) Kdos = (256 * PEEK(bp + 17)) + PEEK(bp + 16) KXMS = (256 * PEEK(bp + 19)) + PEEK(bp + 18) DEF SEG 'If you dislike DEF SEG=/PEEKs then just wrap up the RUCKUS data gets in 'a separate FUNCTION. See the DATALIST.DOC file for more. The above method, 'however, is as fast as it gets. Note that it may be possible to have more 'than 32767K of XMS (32M) so you may want to define KXMS as LONG and use a '256& in the equation. Note that even though loading into XMS memory, RUCKUS-DAC still needs some conventional memory to use as a buffer. After the load to XMS, the low memory is no longer required. 11 PlayDac Func: 5 Pack: PlaybackPack Once the digital data is in either conventional or XMS memory, you can play it to any of the RUCKUS-supported devices. XMS memory, however, requires DMA playback mode; this mode is supported in the Sound Blasters only. Also, for STEREO playback, DMA mode is required (SB Pro only). In addition to DMA-mode playback, you can instruct RUCKUS to play in the background or foreground. Playing in the background allows your computer program to regain control immediately after play has begun. If you choose foreground play, control does not return to your program until the end of the data has been played, or, until CTRL-ALT is pressed. All RUCKUS-supported devices can be played in the background. Only the Sound Blasters can be played using DMA. DMA playback is similar to background play in that control is returned to your program immediately, but it is also much more efficient since DMA playback uses no CPU time. Background play, on the other hand, can require anywhere from 1 to 100% of available CPU time, depending on what playback rate has been selected (see SetIntRateDac). Since it's possible to load several data files into memory at one time, to play a particular data file requires that you specify its start address or, if loaded to XMS memory, its XMS handle. Given the code sequence example in LoadDac, the following PlayDac code takes up from there: DIM PBP AS PlaybackPackTYPE PBP.Func = PlayDac PBP.Mode = 2 'mode 0=foreground, 1=background, 2=DMA PBP.XMMhandle = 0 '0=conventional memory data follow, 1+=XMS data follows 'If conventional memory used, then the following pointer is the 'segment:offset start address of the VOC/WAVE data to play. ' 'If XMS memory used, the following pointer is the 32-bit offset within the 'XMS handle (PBP.XMMhandle) that the data starts. If you just load one data 'file to one XMM handle, then these will always=0. However, if you're short 'on available XMM handles, you could load several data files into a single, 'huge, XMM allocation. In order to do this, you must do your own data 'loads since LoadDac loads one file per XMM handle. ' PBP.LoadPtrOff = LP.LoadPtrPOff PBP.LoadPtrSeg = LP.LoadPtrSeg 'Note: the PBP.BufferSize is used by PlayMod only. Also, you may want/need 'to perform pre-Play tasks. See SetAllDac/SetAllSBP. stat = RUCKDAC(PBP) IF stat = 0 THEN 'if DMA or background mode then the digital data is playing now, 'but if foreground mode, the play has ended by the time we get here ELSE 'play error 12 RecordDac Func: 6 Pack: RecordPack The Sound Blasters can record as well as play digital data. As with play, you can record directly into conventional or XMS memory. You can let RUCKUS make the memory allocations, or you can allocate your own memory and record into that. With the SB Pro, you can also record in stereo. With the Sound Blaster Pro you can select among three input sources: mic, line, and CD. The earlier Sound Blaster has one input, the mic. A quality microphone can make a big difference. For other-than-mic input on the SB, you can pipe the headphone output of a CD player into the mic input. Your results may vary, but this is better than mic'ing a loudspeaker. For anything other than mic input, the SB Pro is recommended. Its recording quality is very good since it allows sampling rates up to 45.5kHz in mono, and 22.75kHz in stereo. The SB allows recording sampling rates up to 12kHz (rated to 13kHz record and 23kHz playback). The sampling size is 8 bits. NOTE: TO RECORD IN STEREO AT A GIVEN SAMPLE RATE, YOU MUST SPECIFY TWICE THE RATE DESIRED. FOR EXAMPLE, TO RECORD OFF A CD DECK CONNECTED TO THE LINE INPUT OF THE PRO, AT A SAMPLE RATE OF 22.5kHz, YOU MUST SET THE SP.SetIntRate=44100 (BUT SEE THE sr= CALCULATION BELOW). Sample Use: DIM RP AS RecordPackTYPE DIM EP AS ExitPackTYPE 'needed for EndDac call below EP.Func = EndDac 'preload EP.Func here for space reasons nix& = SETMEM(700000) 'we do this to return all previous SETMEMs mem& = SETMEM(0) IF YouWillBeUsingConventionalMemory THEN nix& = SETMEM(mem& - 2100) 'let's see how much memory we have available in which to record DEF SEG = IP.InfoPtrSeg bp = IP.InfoPtrOff Kdos = (256 * PEEK(bp + 17)) + PEEK(bp + 16) KXMS = (256 * PEEK(bp + 19)) + PEEK(bp + 18) DEF SEG 'Since RP.SampleRate is defined as an INTEGER we need to make an 'adjustment to sample rates > 32767. The following shows how to do 'this, given that the variable SampleToRecordAt& is the sample rate: IF SampleToRecordAt& > 32767 THEN sr = SampleToRecordAt& - 65536 ELSE sr = SampleToRecordAt& ENDIF RP.Func = RecordDac RP.SampleRate = sr 13 'To load into XMM and have RUCKUS make the allocation, set RP.XMMhandle 'to -1. If you made your own XMS allocation, set this to your handle. 'To load into conventional memory and have RUCKUS make the allocation, 'set RP.RecordPtrOff/Seg to 0. If you made your own allocation, set this 'to your segment:offset pointer. RP.XMMhandle = 0 'use conventional memory if this is 0 RP.RecordPtrOff = 0 'have RUCKUS make the memory allocation RP.RecordPtrSeg = 0 'if this is 0 (and if RP.XMMhandle=0) 'By using the Kdos or KXMS values above, we can record as many bytes 'as we have available. Below we reserve 5K for miscellaneous use, as 'you should, too. This is the max bytes to record; we can also stop 'at any point before this. RP.RecordBytes = (1024& * (Kdos - 5)) RP.StereoFlag = 0 stat = RUCKDAC(RP) IF stat = 0 THEN 'we are recording right now, using DMA, so, while we could do just 'about anything we wanted, in this example, we just wait until the 'record is over, or until we hit a key DEF SEG = IP.InfoPtrSeg bp = IP.InfoPtrOff + 10 'point to the DacEnd RUCKUS data variable DO akey = LEN(INKEY$) 'if a key pressed this becomes 1 or 2 bdone = PEEK(bp) 'if recording bytes done this becomes 1 LOOP UNTIL akey OR bdone nix = RUCKDAC(EP) 'stop recording (EP defined/assigned above) 'The above loop won't be exited until all the bytes requested have 'been recorded, or a key was pressed. Let's see exactly how many 'bytes were recorded: bp = IP.InfoPtrOff + 36 'still using same DEF SEG = above byte0 = PEEK(bp) 'get 4 bytes of the double-word (LONG) byte1 = PEEK(bp + 1) byte2 = PEEK(bp + 2) 'unless you are recording more than 16MB, 'byte3 = PEEK(bp + 3) 'byte3 will always be 0 RecBytes& = (65536 * byte2) + (256& * byte1) + byte0 DEF SEG ENDIF 'Now you can save the data by using StoreDac, or play it using PlayDac. 'On return from the RECORD, RP.RecordPtrSeg/Off is set to the 'segment:offset of the first byte recorded in conventional memory, or 'if using XMS memory, RP.XMMhandle is set to the XMS handle. Note: This data is preceded by the appropriate Sound Blaster block header(s) but not with a VOC file header. To save the data to either a VOC or WAVE file, use the StoreDac routine. 14 StoreDac Func: 7 Pack: SaveDataPack Once digital data has been loaded or recorded in memory, you can store it do disk in either VOC or WAVE format. If you want, you can load a file in one format and save it in the other with just a few lines of code (shown below). Sample Use: DIM SDP AS SaveDataPackTYPE SDP.Func = StoreDac SDP.FilenamePtrOff = SADD(filename$) SDP.FilenamePtrSeg = VARSEG(filename$) 'BASIC7 use: 'SDP.FilenamePtrOff = SADD(filename$) 'SDP.FilenamePtrSeg = SSEG(filename$) 'the LP pointer below is from (say) a just-loaded VOC file (using 'LoadDac), and we want to convert and store it to WAVE format SDP.DataPtrOff = LP.LoadPtrOff 'segment:offset of conventional memory SDP.DataPtrSeg = LP.LoadPtrSeg 'or 0 if storing from an XMS handle SDP.FileType = 2 '1=VOC, 2=WAVE SDP.XMMhandle = 0 '0 if DOS data, else XMS handle stat = RUCKDAC(SDP) IF stat = 0 THEN 'data stored to filename$ ELSE 'file save error in stat ENDIF Caution: Be sure to account for the expanded memory required once data has been stored to a file. StoreDac builds the appropriate VOC or WAV header and this adds to the total memory required to reload. I suggest that you do not record so much data as to not be able to load it back in once saved to VOC or WAVE format. 15 EndDac Func: 8 Pack: XitPack EndDac is used to end (stop) play or record on command. Once PlayDac has started, it continues to play in the background until either the end of the digital data has been reached, or you call this routine. In the case of a record, play continues until the number of bytes requested has been recorded, or this routine is called. Sample Use: DIM XP AS ExitPackTYPE 'LoadDac and PlayDac, or RecordDac, have already been called 'see those routines for more information XP.Func = EndDac 'if play or record is active this call stat = RUCKDAC(XP) 'ends it 'See RecordDac on getting the number of bytes actually recorded 16 PauseDac Func: 9 Pack: PausePack PauseDac allows you to temporarily pause and then restart a playback. Sample Use: DIM PP AS PausePackTYPE PP.Func = PauseDac PP.Pause = 1 'non-zero pauses, zero restarts stat = RUCKDAC(PP) PRINT "Press a key to continue playback" a$ = INPUT$(1) PP.Pause = 0 stat = RUCKDAC(PP) 'continue playback 17 DeallocDac Func: 10 Pack: DeallocPack If you have RUCKUS load digital data files, which is most likely the case, it makes memory allocations from the operating system memory pool. RUCKUS tracks up to 32 consecutive DOS loads, and up to 96 loads to XMS (provided enough memory and XMS handles). These should be higher than you'll ever likely use at one time. DeallocDac "unloads" files that RUCKUS has loaded, thus releasing the memory that they used. As an example, let's say that you want to start up your program with 5 digital data files in XMS memory. You have 5MB of XMS available. Each data file is 1M in size. To load a new data file after these 5, you will need to unload one of the 5 already loaded. DeallocDac does that for you. The following example loads a single data file to XMS then immediately unloads it. DeallocDac is not used for releasing LoadMod allocations. Sample Use: DIM LP AS LoadPackTYPE DIM DP AS DeallocPackTYPE nix& = SETMEM(700000) nix& = SETMEM(-66000) 'release up to 64K for temp RUCKUS use 'until after the load into XMS LP.Func = LoadDac LP.FilenamePtrOff = SADD(filename$) LP.FilenamePtrSeg = VARSEG(filename$) 'BASIC7 use: 'LP.FilenamePtrOff = SADD(filename$) 'LP.FilenamePtrSeg = SSEG(filename$) LP.StartPos = 0& LP.LoadSize = 0& LP.XMMflag = 1 'non-zero means use XMS for load stat = RUCKDAC(LP) nix& = SETMEM(66000) 'return the 64K to BASIC IF stat = 0 THEN DP.Func = DeallocDac DP.HandSeg = LP.XMMhandle 'XMM handle returned by RUCKDAC(LP) DP.TypeFlag = LP.XMMflag '0=DOS allocation, 1=XMS stat = RUCKDAC(DP) '--if this were a DOS allocation, DP.HandSeg ENDIF '--would be set to LP.LoadPtrSeg only since '--LP.LoadPtrOff=0 as returned by LoadDac IF stat THEN 'file load error or deallocate error in stat ENDIF 18 SetAllDac Func: 20 Pack: SetPack This routine sets the overall playback volume, interrupt rate, and RUCKUS priority in one call. The playback volume affects VOC or WAVE output for non-DMA mode, only. In other words, it's for controlling the volume on the PC speaker, LPT-DAC, Disney Sound Source, and AdLib only. To control the playback volume of the Sound Blaster, you must operate it under non-DMA mode. To control the playback of the Sound Blaster Pro, a separate set of RUCKUS routines are used. See the SetAllSBP routine for more. The default volume is set to 16. Minimum is 0, maximum is 127. For a linear approximation of this volume control, 16 is about half-volume, 8 about 1/4, 64 about 3/4, and 127 full volume. A volume other than 16 may cause a slowdown in performance so 16 should be used as much as possible. Note: SETTING THE VOLUME TO 0 TURNS OFF THE SOUND BLASTER AND PRO'S SPEAKER (REQUIRED BEFORE RECORDING). ANY OTHER SETTING TURNS THE SPEAKER CONNECTION ON. The interrupt rate sets the playback rate of background play for non-DMA mode. For example, let's say you load a file that was recorded with a sample rate of 8000Hz (this information is stored with the VOC or WAVE). That is the value to which you set the interrupt rate. Easy enough. But let's say that it was recorded at 44,100Hz and in stereo. Normally, this data file couldn't be played except with high-end sound cards. What you can do is set the interrupt rate to 8000Hz and have RUCKUS-DAC perform on-the- fly downsampling so that you can play this file on any of the supported devices (in non-DMA mode). In addition to downsampling, RUCKUS-DAC can upsample with the PC Speaker and AdLib cards (the two that need it the most). Let's take that 8000Hz sample rate file again. Upsampling performs on-the-fly adjustments to the data so that it sounds as if the file sample rate were twice the original. This results in a much cleaner sound. There is a drawback: much more CPU time is needed at this high rate, and it should only be used on powerful CPUs. To use the upsampling capabilities of RUCKUS-DAC, set the interrupt rate to the original sample rate. There is also a special method used in the initialization of the device. See InitDac for more. You can experiment with the down- and upsampling of RUCKUS-DAC by using the MODAC.EXE program. When using non-DMA mode, you can select from three priority levels. The default priority=1. This level allows the system to run as normal, even though the computer's ticker has been sped up some thousand times. Priority level 2 hogs all background time for the RUCKUS-DAC playback. The computer's clock is not updated. Priority level 0 gives top priority to other computer events. This level may result in a warbly sound. Priority only affects non-DMA VOC/WAVE output. Use the default level (1). 19 The default interrupt rate is 10989. If you are on a slow machine, this may be too high for non-DMA operations. The following table shows the min, max, and nominal interrupt rate for the supported devices. In all cases, higher rates require more CPU power, except in DMA mode. Nominal values based on a 386/25 CPU. Device MinRate MaxRate Nominal Comments ------ ------- ------- ------- ------------------------------------ PCSKP0 5000 18000 8000 rates < 16000 may be noisy PCSPK1 5000 9000 8000 effective rate=rate*2 LPTDAC 5000 23000 15000 not tested DISNEY 5000 7000 7000 max usable rate is 7000Hz ADLIB0 5000 12000 8000 AdLib very slow as digital device ADLIB1 5000 6000 6500 effective rate=rate*2 SB 5000 23000 15000 DMA mode is 5-23000, record to 12kHz SB PRO 5000 23000 15000 DMA mode is 5-45500 Sample Use: DIM SP AS SetPackTYPE SP.Func = SetAllDac SP.Volume = 16 'any other value slows down performance SP.IntRate = 8000 SP.Priority = 1 stat = RUCKDAC(SP) 20 SetVolumeDac Func: 21 Pack: SetPack SetVolumeDac does two things. First, it controls the non-DMA mode output volume. Second, it turns the SB's speaker on and off; the SB speaker must be off, and remain off, while recording. Under normal use, the SB speaker is turned on and off by RUCKUS automatically. Because of the extra calculations required when the volume is set to anything other than the default (16), it's recommended that the volume be changed only when necessary (especially on slow machines). This routine controls the output volume on all devices in non-DMA mode. In DMA-mode, the SB's volume is not controllable. The SB PRO, however, has a large set of mixer controls that can be controlled via RUCKUS-DAC. See SetAllSBP for more. Sample Use: DIM SP AS SetPackTYPE SP.Func = SetVolumeDac SP.Volume = 127 'set to max volume stat = RUCKDAC(SP) IF stat THEN 'you probably didn't set SP.Func correctly 21 SetIntRateDac Func: 22 Pack: SetPack SetIntRateDac, with respect to the -DAC section of RUCKUS, controls the playback rate of non-DMA output. After loading a file, that file's sample rate is available in the DAC data section. You may choose to have the digital data file played back at that rate, or, you may choose to downsample the original rate. Downsampling is useful since it allows slower computers to play data files originally sampled at rates too high to be played back -- RUCKUS can play a 44.1kHz stereo VOC or WAVE file back through the PC speaker, or any of the other supported devices. Note that the actual downsampled rate is not always exactly what you specify, but a best-fit approximation. As an example, let's suppose you have a VOC file originally sampled at 22050Hz, mono format. While this can easily be played on the SBs using DMA- mode playback, non-DMA mode requires a very powerful CPU to handle that high a rate. After loading using LoadDac, the 22050 sample rate, and its mono format, is determined by reading the DAC data section. To play back this file through PCSPKR0, say, at 11kHz, you'd set SP.IntRate=11025. With the PC speaker and the AdLib, there are two different output modes. The first either plays at the original rate, or is downsampled to a lower rate (as specified by you). The second mode upsamples. By upsampling, RUCKUS can output a much cleaner sound than playing at the original sample rate. However, this is useful only for samples that were originally at a low sample rate. You would not want to upsample a VOC file that was sampled at 22kHz, since that would demand too much CPU power, plus, very little benefit would be achieved. The best use of upsampling is on data that was originally sampled at, say, 8kHz or less. In order to properly upsample, you need to specify a SP.IntRate equal to the original sample rate (this can be found in the DAC data section immediately after a LoadDac). As mentioned, upsample mode is available on the speaker and AdLib devices only. To specify this mode, set the IP.IOport to the physical port when initializing the device (InitDac). In the PC speaker's case, IP.IOport=0x42 (&H42) would activate up-sample mode. Using IP.IOport=0 would have the regular mode used. For the AdLib, specify IP.IOport=0x388 (&H388). As with the PC speaker, setting IP.IOport=0 uses the regular AdLib play mode. Sample Use: DIM SP AS SetPackTYPE SP.Func = SetIntRateDac SP.IntRate = 11025 'for rates > 32767 see RecordDac stat = RUCKDAC(SP) IF stat THEN 'error 22 SetPriorityDac Func: 23 Pack: SetPack When operating in non-DMA mode playback of VOC or WAVE data, RUCKUS reprograms the system timer. Normally, this timer runs at the familiar 18.2 times per second rate. When you play back at, say, a SP.IntRate=10000, this is the new rate that the system timer is set to operate at. So, instead of the timer interrupting the CPU (via IRQ0) 18.2/sec, it interrupts at 10,000/sec. The routine allows you to control the priority given to other events while the timer is operating at this accelerated pace. The default priority is 1. At the priority, the playback code is called at the desired rate, and, given a 10kHz rate, every 550th time the playback code is executed, the original timer-dependant code is executed. This allows the system clock, and any other system in the computer dependant on the clock, to be properly maintained. On each 550th call, RUCKUS first performs all tasks that needs to be done, then it calls the original system code. In most cases, if not all, this priority works best. Priority 0 is exactly like priority 1 except that control is released as soon as the RUCKUS code starts. The permits other tasks to interrupt RUCKUS. This may cause a warbly-type sound, but permits, say, high-speed communications code to operate in the background with missing a beat. Priority 2 causes RUCKUS to use (hog) all background processing time for itself. The system clock is not maintained. Use this priority only if the other two are causing problems (doubtful) or if you want to get the maximum sound performance out of RUCKUS and don't care if the system clock is maintained. Sample Use: DIM SP AS SetPackTYPE SP.Func = SetPriorityDac SP.Priority = 1 '1 is the default so no need to call unless changed stat = RUCKDAC(SP) IF stat THEN 'check SP.Func for proper value 23 GetBufferDataDac Func: 28 Pack: GetDataPack Used to get a specified number of bytes from the current digital data path. This routine is currently under development and should not be used. 24 GetBytePosDac Func: 29 Pack: GetDataPack Used to determine where in the current digital data path processing is occurring. Sample Use: DIM GDP AS GetDataPackTYPE GDP.Func = GetBytePosDac stat = RUCKDAC(GDP) IF stat = 0 THEN PRINT "Curr pos relative start of data is "; HEX$(GDP.BytePos) 25 SetAllSBP Func: 30 Pack: SetProPack This routine allows you to control the mixer facility of the Sound Blaster Pro including main volume, VOC volume, mic level, CD level, line level, output filter, input source selection, record filters, input source, and stereo/mono record mode. During initialization of the Sound Blaster Pro (InitDac), the main and VOC volumes are set to maximum (15) for both left and right channels, the three input levels are set to their minimums (1), all filters are set to off, mode is set to mono record, and input selection is set to mic. NOTE: PLAYBACK OF VOC AND WAVE STEREO DATA FILES IS AUTOMATIC. THE STEREO MODE SETTING IS FOR RECORDING ONLY. TO PLAY STEREO FILES IN MONO ON THE SB PRO, USE THE SOUND BLASTER (DEVICE 4) INSTEAD. The main volume (left and right, as are all mixer controls except mic) adjusts both the digital and synthesizer outputs of the PRO (the synthesizer, or FM section, is not used by RUCKUS-DAC, but is in RUCKUS- MIDI). In normal use the main volume channels would be set to 15, the maximum. The VOC volume adjusts the volume of the digital output channels. Anything played through the SB PRO's digital channels can be adjusted with this. As with the main volume, the VOC volume is normally set to 15, the maximum. The SB PRO provides for three inputs. Mic, CD, and Line. Each of these have separate level adjustments. The mic input level is the odd one out. Unlike the other two, the mic level does not adjust the mic input level, but rather the mic output level. Whenever you record via the mic input line at the back of the card, the input level is controlled by an AGC, automatic gain control. The AGC acts as a real-time level adjuster -- high signal levels (loud sounds) have the AGC automatically decrease the mic input sensitivity -- low signal levels (quiet sounds) have it automatically increase the mic input sensitivity. The actions of an AGC has its drawbacks in reduced dynamic range and perhaps a noticeable "breathing" of the sound on playback. Breathing is where the background noise increases as the level of the sound decreases. However, often the reduced dynamic range makes for a better final results, especially when using a mic/SB combination. The CD input level adjusts the level of the CD-ROM device. No testing has been done with this. It controls the input level from the proprietary CD- ROM drive that CLabs distributes for the SB PRO, or one which is compatible (and is hooked up to the SB PRO's CD connector). Any CD should be able to plug into the CD audio connector of the SB PRO (see the SB PRO docs) and so have its level controllable via RUCKUS-DAC. The Line input level adjusts the input sensitivity. Normally, when recording from this input, the Line level should be set to 15, the maximum. For preamps that have an unusually high line out level, reducing the PRO's line input level may produce a better recording. The output filter can be used to reduce the noise at the mid and high end of the digital data being played. Normally, this filter is not needed. 26 The recording filters are very useful and should be used whenever the recording sample rate is below 18kHz and the source being record has frequencies above 9kHz. There are two filters to choose from: one has a 3.2kHz cutoff, the other 8.8kHz. Whenever you are recording from a source that will include frequencies higher than 3.2kHz, and you have the PRO recording at a sample rate under 6.4kHz, you should select the 3.2kHz filter. This will attenuate frequencies higher than 3.2kHz and should help produce a cleaner recording. Along the same lines, if you are recording frequencies higher than 8.8kHz, and are recording using a sample rate less than 17.6kHz, you should use the 8.8kHz filter. Note that filter use as described above is not a rule, just a guideline. You may find that using no filters is best. With the SB PRO you have 3 input sources to record from: the mic, a CD-ROM drive attached to the SB PRO (requires special cable), or a line-level input. The mic allows mono recording only. The CD-ROM facility controls only a CD-ROM drive hooked up to the SB PRO. The line input can be connected directly to a preamplifier's line out jacks. The SB PRO allows you to record in STEREO from the CD and LINE input sources; mic is always mono. When recording in stereo, the sample rate you record at must be set to twice the desired rate. For example, if you want to record from the LINE input at 22.05kHz, in stereo, set the recording rate to twice 22,050, or 44,100. The SB PRO can sample up to a 45,500Hz rate (which, if a stereo recording, is an effective rate of 22,750Hz). See RecordDac for more. Sample Use: DIM SPP AS SetProPackTYPE 'be careful not to type SBP SPP.Func = SetAllSBP leftCh = 15 : rightCh = 15 'set all output volumes to max SPP.Volume = (256 * leftCh) + rightCh 'could just use = &H0F0F SPP.VolVoc = (256 * leftCh) + rightCh leftCh = 1 : rightCh = 1 'set all input levels to minimum SPP.VolMic = leftCh 'mic is mono, max is 7 SPP.CD = (256 * leftCh) + rightCh SPP.LI = (256 * leftCh) + rightCh SPP.FilterOut = 0 '0=off filter, 1=on (output filter) SPP.FilterIn = 0 '0=off filter, 1=3.2kHz, 2=8.8kHz (record filter) SPP.SourceIn = 0 '0=mic, 1=CD, 2=line SPP.StereoIn = 0 'record mode: 0=mono, 1=stereo stat = RUCKDAC(SPP) IF stat = THEN 'error 27 SetVolMainSBP Func: 31 Pack: SetProPack The main volume (left and right) adjusts both the digital and synthesizer outputs of the PRO; it is the overall volume setting. Each of these outputs also has its own volume control. In normal use, the main volume channels would be set to 15, the maximum. The range of volume is 1 to 15, in steps of 2 (1,3,5,7,9,11,13,15). To set the left channel main volume, multiply the volume desired by 256. To set the right channel, just add its value. For example, to set the main volume to maximum (15, or 0F hex), multiply 15*256 and add 15. In hex, this value is 0F0F (decimal 3855, but decimal is much too awkward). If you know beforehand that you want the main volume at maximum, you can forego the multiplication and simply use 0F0F, as in the example below. NOTE: Since you are the programmer and you have the documentation, do not depend on RUCKUS correcting out-of-value parameters. If you use parameters that are not within specifications, the results are undefined. Sample Use: DIM SPP AS SetProPackTYPE SPP.Func = SetVolMainSBP SPP.Volume = &H0F0F stat = RUCKDAC(SPP) IF stat THEN 'error 28 SetVolVocSBP Func: 32 Pack: SetProPack The VOC volume (left and right) adjusts the digital output volume of the PRO. The range of volume is 1 to 15, in steps of 2 (1,3,5,7,9,11,13,15). To set the left channel VOC volume, multiply the volume desired by 256. To set the right channel, just add its value. For example, to set the VOC volume to maximum (15, or 0F hex), multiply 15*256 and add 15. In hex, this value is 0F0F (decimal 3855, but decimal is much too awkward). If you know beforehand that you want the VOC volume at maximum, you can forego the multiplication and simply use 0F0F, as in the example below. Sample Use: DIM SPP AS SetProPackTYPE SPP.Func = SetVolMainSBP SPP.VolVoc = &H0F0F stat = RUCKDAC(SPP) IF stat THEN 'error 29 SetLevelMicSBP Func: 33 Pack: SetProPack This routine does not actually adjust the mic input level, but rather the mic output level. Whenever you record via the mic input line at the back of the card, the input level is controlled by an AGC, automatic gain control. The AGC acts as a real-time level adjuster -- high signal levels (loud sounds) have the AGC automatically decrease the mic input sensitivity -- low signal levels (quiet sounds) have it automatically increase the mic input sensitivity. The actions of an AGC has its drawbacks in reduced dynamic range and perhaps a noticeable "breathing" of the sound on playback. Breathing is where the background noise increases as the level of the sound decreases. However, often the reduced dynamic range makes for a better final results, especially when using a mic/SB combination. By setting the mic input level, you can use the computer as a public address system. To do this, select mic as the input source, set the mic input level to maximum, and turn on the SB speaker. To avoid feedback, keep the mic away from the loudspeakers. The input level range is 1 to 7, in steps of 2 (1,3,5,7). This setting has no effect on recording level (see above). Sample Use: DIM SPP AS SetProPackTYPE SPP.Func = SetVolMicSBP SPP.VolVoc = &H0007 stat = RUCKDAC(SPP) IF stat THEN 'error 30 SetLevelCDSBP Func: 34 Pack: SetProPack The CD input level (left and right) adjusts the input level of the attached CD-ROM drive. This has not been tested. For its use, see SetLevelLineSBP. 31 SetLevelLineSBP Func: 35 Pack: SetProPack The line level (left and right) adjusts the analog input level of the PRO. The range of volume is 1 to 15, in steps of 2 (1,3,5,7,9,11,13,15). To set the left channel line level, multiply the volume desired by 256. To set the right channel, just add its value. For example, to set the line level to maximum sensitivity (15, or 0F hex), multiply 15*256 and add 15. In hex, this value is 0F0F (decimal 3855, but decimal is much too awkward). If you know beforehand that you want the line level at maximum, you can forego the multiplication and simply use 0F0F, as in the example below. Sample Use: DIM SPP AS SetProPackTYPE SPP.Func = SetVolMainSBP SPP.VolLI = &H0F0F stat = RUCKDAC(SPP) IF stat THEN 'error 32 SetFilterOutSBP Func: 36 Pack: SetProPack The output filter of the PRO can be used to reduce the noise at the mid and high end of the digital data being played. Normally, this filter is not needed. Recordings made at a very low sample rate, say, under 6kHz, may sound better with this output filter on. The digital output filter, and also the analog recording filter, is set off by default. Sample Use: DIM SPP AS SetProPackTYPE SPP.Func = SetFilterOutSBP SPP.FilterOut = 1 'enable output filter stat = RUCKDAC(SPP) 33 SetFilterInSBP Func: 37 Pack: SetProPack The recording filters are very useful and should be used whenever the recording sample rate is below 18kHz and the source being record has frequencies above 9kHz. There are two filters to choose from: one has a 3.2kHz cutoff, the other 8.8kHz. Whenever you are recording from a source that will include frequencies higher than 3.2kHz, and you have the PRO recording at a sample rate under 6.4kHz, you should select the 3.2kHz filter. This will attenuate frequencies higher than 3.2kHz and should help produce a cleaner recording. Along the same lines, if you are recording frequencies higher than 8.8kHz, and are recording using a sample rate less than 17.6kHz, you should use the 8.8kHz filter. Note that filter use as described above is not a rule, just a guideline. You may find that using no filters is best. The input filter is off by default. Sample Use: DIM SPP AS SetProPackTYPE SPP.Func = SetFilterInSBP SPP.FilterIn = 1 '0=no filter, 1=3.2kHz cutoff, 2=8.8kHz cutoff stat = RUCKDAC(SPP) IF stat THEN 'error 34 SetSourceSBP Func: 38 Pack: SetProPack With the SB PRO you have three input sources to record from: the mic, a CD- ROM drive attached to the SB PRO (requires special cable), or a line-level input. The mic allows mono recording only. The CD-ROM facility controls only a CD-ROM drive hooked up to the SB PRO. The line input can be connected directly to a preamplifier's line out jacks. Recording with the mic requires only that it be selected. The mic input level does not control the recording level, but rather the PA output. See SetAllSBP for more. Recording from the connected CD-ROM drive has not been tested. If you can control the CD, you can record from it using RUCKUS. Recording from the line-level input is simple. Just hook your tape-out jacks from your preamplifier to the cable supplied with the SB PRO. This cable, a 1/8-inch mini stereo to 2 RCA phono jacks is the same one that comes with the original Sound Blaster. You'll probably need more cable unless you have your preamp nearby. When recording from either the CD or line, you must set the source's input level. Normally, setting it to maximum (15) is best. If you have particularly high line output levels, you may need to set this lower. As with all mixer settings, settings are 1 to 15 in steps of 2. The mic is 1 to 7, by 2. Sample Use: DIM SPP AS SetProPackTYPE SPP.Func = SetSourceSBP SPP.SourceIn = 2 'set input source to line input stat = RUCKDAC(SPP) IF stat THEN 'error 35 SetStereoSBP Func: 39 Pack: SetProPack The SB PRO allows you to record in STEREO from the CD and LINE input sources; mic is always mono. When recording in stereo, the sample rate you record at must be set to twice the desired rate. For example, if you want to record from the LINE input at 22.05kHz, in stereo, set the recording rate to twice 22,050, or 44,100. The SB PRO can sample up to a 45,500Hz rate (which, if a stereo recording, is an effective rate of 22,750Hz). See RecordDac for more. You must set the mode to stereo or mono before starting the actual record. Sample Use: DIM SPP AS SetProPackTYPE SPP.Func = SetStereoSBP SPP.StereoIn = 1 'set to stereo record stat = RUCKDAC(SPP) IF stat THEN 'error 36 SetSpeakerSB Func: 40 Pack: SetPack The routine activates or deactivates the Sound Blasters' output. When recording it must be off. When playing back, it must be on. When starting a recording, RUCKUS automatically turns the speaker off; when playing back it turns the speaker on. For those occasions when you want to control the speaker connection, use this routine. Note that the generic SetVolumeDac also controls the SB's speaker connection. If the speaker is currently on and you set the volume to 0, the SB speaker is turned off. And, of the speaker is currently off, and you set the volume to a non-zero value, the speaker is turned on. This routine lets you control the connection without changing the generic volume setting. Sample Use: DIM SP AS SetPackTYPE SP.Func = SetSpeakerSB SP.Volume = 0 'use the volume member of SP to control speaker stat = RUCKDAC(SP) 'to turn the speaker on, set SP.Volume = 1 IF stat THEN 'error 'THIS DOES NOT ALTER THE VOLUME 37 GetMixerRegSBP Func: 48 Pack: GetDataPack Get a SB PRO mixer port-value. This routine is under development and should not be used. 38 GetDacSB Func: 49 Pack: GetDataPack This routine gets a byte from the Sound Blasters data channel. This routine should not be called while the Sound Blaster is playing or record. It can be used for level tests. Before using this routine on the PRO, first select the input device (mic, CD, or line) and then perform a 64-byte record from that device. This is because the input device is not selected until you actually record from it. Unlike the other RUCKDAC routines, the return value is not the error code, but rather the data byte itself. To check for an error, use GDP.stat (as you can in all RUCKUS functions). Sample Use: DIM GDP AS GetDataPackTYPE GDP.Func = GetDacSB data = RUCKDAC(GDP) IF GDP.stat THEN 'error 39 ExitMod Func: 50 Pack: XitPack When using RUCKUS, certain aspects of the computer are controlled by the RUCKUS code. To have RUCKUS return full control back to the computer and operating system, ExitMod must be called. To ensure that this happens, even after an abnormal termination (such as an untrapped divide by zero), RUCKUS also provides a routine that ensures that ExitMod is always called before your application ends and returns to the operating system. See AtExitMod for more. Once you have loaded a mod file via LoadMod, or performed any mod function, you must call ExitMod before you end you program and return to DOS. Calling ExitMod releases any memory allocations made, and also performs other system cleanup. Sample Use: DIM XP AS ExitPackTYPE XP.Func = ExitMod stat = RUCKDAC(XP) IF stat THEN 'error 40 AtExitMod Func: 51 Pack: XitPack To ensure that all machine control is returned to the operating system and that all RUCKUS-made memory allocations are released, before your application program ends, AtExitMod should be used (if you have used the mod extensions to RUCKUS-DAC). This routine takes advantage of most compiler's _atexit enregistration routine. This _atexit compiler run-time library routine allows for up to 32 different calls to be made just prior to it (the compiler's run-time code) returning to the operating system (program termination). Most of the time, you can make all the necessary shutdowns that your program requires in your app's code. However, abnormal terminations--terminations that can cause a bypass of your own shutdown code, may mean that when the operating systems regains control, certain machine operations are not in a stable state. The AtExitMod routine ensures that ExitMod is called no matter what (in most all cases, except where the program locks up, in which case the session needs to be reset anyway). Graphically, your program executes like this: DOS C>program.exe | Compiler startup code (performs basic setup) | +----->+ | Your program starts, ends +<-----+ | rest of startup code, _atexit registered routines | DOS C>_ Caution: In order for the _atexit registered routines to be called by your compilers run-time, you must not allow you program to exit via non-standard ways. Calling INT21/4C is on example (you should never do this from compiled code, anyway). The startup code is basically a program that sets up your program to run, calls your program, regains control when your program ends, then performs the necessary shutdown actions required, including calling all routines registered with _atexit. Sample Use: DIM XP AS ExitPack XP.Func = AtExitMod stat = RUCKDAC(XP) IF stat THEN PRINT "_atexit is full (more than 32 calls made to _atexit)" 41 LoadMod Func: 52 Pack: LoadPack It is required that RUCKUS load mod files into memory. RUCKUS makes the necessary memory allocations and loads the data into conventional memory, with UMB blocks used if available and controlled by DOS (via DOS=,UMB in CONFIG.SYS). Only one mod file may be in memory at any one time. To unload the mod file you must execute an ExitMod call. LoadMod can be instructed to start loading at any particular byte in a file. This would be useful, for example, if you have a single file made up of several mod files, appended to form one large data file. Sample Use: DIM LP AS LoadPackTYPE nix& = SETMEM(700000) mem& = SETMEM(0) nix& = SETMEM(mem& - 2100) 'release all but 2K to the OS 'or as much as needed to store file LP.Func = LoadMod LP.FilenamePtrOff = SADD(filename$) LP.FilenamePtrSeg = VARSEG(filename$) 'BASIC7 or VB/DOS use: 'LP.FilenamePtrOff = SADD(filename$) 'LP.FilenamePtrSeg = SSEG(filename$) LP.StartPos = 0& 'start load at first byte of file LP.LoadSize = 0& 'have RUCKUS load all of it LP.XMMflag = 0 'this must be set to zero stat = RUCKDAC(LP) IF stat = 0 THEN 'LP.LoadPtr is not used for Mod loads nix& = SETMEM(700000) ELSE nix& = SETMEM(700000) '700,000 tells BASIC to reclaim unused memory 'file load error in stat ENDIF 42 PlayMod Func: 53 Pack: PlayBackPack Once the mod file has been loaded, you can play it to any of the RUCKUS- supported devices. There are 4 modes that can be used for playback; non-DMA foreground, non-DMA background, DMA foreground, and DMA background. The DMA modes require the Sound Blasters. Also, for STEREO mod playback, DMA mode is required (SB Pro only). Playing in the background allows your computer program to regain control immediately after play has begun. If you choose foreground play, control does not return to your program until the end of the data has been played, or, until CTRL-ALT is pressed. In all cases, mod file playback is best done on a fast computer, though excellent results can be gotten from 286-class machines. For slow machines, DMA foreground allows for best sound, since you can set the mod process rate higher than you can if you choose a background mode. Before play, you should set up other parameters by calling the other Set mod routines (SetIntRateMod, SetStereoMod, and SetFastMod). NOTE: SOME MACHINES ARE NOT ABLE TO HANDLE BACKGROUND DMA MODE AT HIGH RATES, EVEN ON 486-CLASS MACHINES. HOWEVER, BOTH MY 486/33 AND MY 286/16 WORK WELL IN THIS MODE. THE 486/33 CAN PROCESS MOD DATA AT RATES UP TO THE PRO'S MAX, 45,500Hz. THE 286/16 CAN PROCESS UP TO 16kHz IN THIS MODE AND 22kHz IN DMA FOREGROUND. A 286/6 HAS BEEN TESTED TO 8kHz (DMA FOREGROUND) AND PERFORMS WELL. A 12MHz DID 16kHz. ON SLOWER MACHINES, USING A LARGER DMA BUFFER SIZE AND A HIGHER DMAX: VALUE ALLOWS FOR HIGHER RATES TO BE ACHIEVED. IT IS POSSIBLE TO LOCK UP A MACHINE IF TOO HIGH A RATE IS ATTEMPTED. DIM PBP AS PlaybackPackTYPE PBP.Func = PlayMod PBP.Mode = 3 'mode 0=foreground, 1=background, 2=DMA FG, 3=DMA BG PBP.XMMhandle = 0 'this must be set to 0 'PBP.LoadPtr is not used by PlayMod PBP.BufferSize = 4096 'buffer size is bytes per buffer (2 buffers used) 'minimum size is 2048, maximum is 64K-16 'buffers allocated only if DMA play (mode=2 or 3) stat = RUCKDAC(PBP) IF stat = 0 THEN 'if background mode then the mod data is playing now, 'but if foreground mode, the play has ended by the time we get here ELSE 'play error (could be not enough memory for PBP.BufferSize) 43 EndMod Func: 54 Pack: XitPack EndMod is used to end (stop) play on command. Once PlayMod has started, it continues to play in the background until either the end of the mod data has been reached, or you call this routine. Sample Use: DIM XP AS ExitPackTYPE 'LoadMod and PlayMod have already been called 'see those routines for more information XP.Func = EndMod 'if play is active this call stat = RUCKDAC(XP) 'ends it 44 PauseMod Func: 55 Pack: PausePack PauseMod allows you to temporarily pause and then restart a playback. Sample Use: DIM PP AS PausePackTYPE PP.Func = PauseMod PP.Pause = 1 'non-zero pauses, zero restarts stat = RUCKDAC(PP) PRINT "Press a key to continue playback" a$ = INPUT$(1) PP.Pause = 0 stat = RUCKDAC(PP) 'continue playback 45 SetIntRateMod Func: 56 Pack: SetModPack SetIntRateMod, with respect to the mod extensions of RUCKUS, controls the mod data processing rate, which in turn, is the playback rate (the opposite of sample rate). A process rate of 22kHz should be considered a practical maximum. Higher process rates are possible (up to 45.5kHz with the PRO) but the improvement in sound quality over 22kHz is negligible (to me). If the machine is capable, a rate of at least 16kHz should be used. At this rate, sound is reasonably good sounding. Rates below 16kHz will most likely incur a high- pitched whistling noise that can be very annoying. Using the output filter of the SB PRO helps. The whistle is totally absent from the output of the Disney Sound Source (which internally plays at 7kHz regardless of the input stream rate). For PC speaker output, rates above 18kHz are not recommended. Best performance for the PC speaker is at 16kHz. The AdLib, being a very slow device when made to play digital data, has an effective top-end of about 13kHz. When using the SB PRO in stereo mode, the mod process rate must not exceed 45.5kHz/2, or 22.75kHz. This is a limitation of the Sound Blaster. In mono, you can run up to 45.5kHz, if you have the muscle to do so (typically requires a 486, and a DMAX: setting of at least 4). Buffer sizes above 4K matter most on slower machines. Adjusting the mod processing while playing is permitted, though it's recommended to do so only when not. Sample Use: DIM SMP AS SetModPackTYPE SMP.Func = SetIntRateMod SMP.IntRate = 22000 'for rates >32767 see SetRecordDac stat = RUCKDAC(SMP) IF stat THEN 'error 46 SetSpeedMod Func: 57 Pack: SetModPack Temporarily increases or decreases the playback speed of the mod file playing. The basic speed of a mod, with regard to this routine, is 6. However, at any particular point in the mod file this can change. The speed range is 1 to 15, with 1 resulting in fast play, and 15 resulting in a very slow play. Sample Use: DIM SMP AS SetModPackTYPE SMP.Func = SetSpeedMod SMP.Speed = 4 'increase play by 33% over norm stat = RUCKDAC(SMP) IF stat THEN 'error 47 SetVolumeMod Func: 58 Pack: SetModPack SetVolumeMod controls each of the four mod digital output channels. Normally they would all be set to maximum (255). In order to adjust channel volume, FastMod mode must be off. Sample Use: DIM SMP AS SetModPackTYPE SMP.Func = SetVolumeMod SMP.VolCh1 = 255 SMP.VolCh2 = 255 SMP.VolCh3 = 255 SMP.VolCh4 = 255 stat = RUCKDAC(SMP) IF stat THEN 'error 48 SetPositionMod Func: 59 Pack: SetModPack Each mod file is composed of several tracks, known as patterns. Each pattern contains 64*4 notes (64 notes per channel). A mod file can contain up to 63 separate patterns, and can play up to 128 patterns in total (though any pattern can be made to repeat). SetPositionMod lets you move to the start of any pattern to be played (up to the number of patterns to play). The first pattern is pattern number 0. The last possible patter number is 127. Sample Use: DIM SMP AS SetModPackTYPE SMP.Func = SetPositionMod SMP.Position = 0 'restart play from the beginning stat = RUCKDAC(SMP) IF stat THEN 'error 49 SetStereoMod Func: 60 Pack: SetModPack Mod data files contain four channels of information. In mono playback mode, all four of these are combined to form a single digital output stream. In stereo mode (SB PRO only), you can select from three different combine modes. You can increase this to nine stereo combinations by setting the high bit of SMP.Stereo. If set, the left/right channels are reversed. Sample Use: DIM SMP AS SetModPackTYPE SMP.Func = SetPositionMod SMP.Stereo = 1 '0=mono stat = RUCKDAC(SMP) '1=LEFT:ch1+ch3 RIGHT:ch2+ch4 IF stat THEN 'error '2=LEFT:ch1+ch4 RIGHT:ch2+ch3 '3=LEFT:ch1+ch2 RIGHT:ch3+ch4 '&H8000 + mode then LEFT <-> RIGHT, e.g., '&H8001=LEFT:ch2+ch4 RIGHT:ch1+ch3 50 SetFastMod Func: 61 Pack: SetModPack Mod files require lost of CPU power and lots of CPU attention. The most often executed code performs 4 BPTR IMUL instructions every tick of a process clock (10,000 times/sec if that is the process rate selected). Multiply on the 8088 is a very time consuming operation. If an 8088-based computer is to play mod files, these multiplies must be sped up. SetFastMod performs this task by implementing an alternate method. Note that with FastMod mode enable, some mod files may sound odd. The SliceAdj instructs the DMA buffer fill code to perform more than one mix per interrupt. By increasing this number you reduce the interrupt- latency time wasted (since more mod data is processed per interrupt) but you also decrease the amount of time given to other tasks (tasks other than mod playback). Fast CPUs have no problem keeping the DMA buffers full, so even a large SliceAdj will have little of any impact on these machines. However, on slow machines where the DMA buffers are constantly needing to be filled (where neither DMA buffer is ever filled) a SliceAdj above 1 may be desirable. Typically, though, the default of 1 works fine. Sample Use: DIM SMP AS SetModPackTYPE SMP.Func = SetFastMod SMP.FastMode = -1 '0=normal, 1=fast mode enabled, -1 to skip SMP.SliceAdj = 32 'DMA buffer fill count (1-4096, default=1) stat = RUCKDAC(SMP) IF stat THEN 'error 51 Appendix A. Tips and Tricks. See the RUCKUS-MIDI documenation. 52 Appendix B. Pack Structure. DECLARE FUNCTION RUCKDAC% (SEG packinfo AS ANY) CONST SysInfoDac = 0, InitDac = 1, ExitDac = 2, AtExitDac = 3 CONST LoadDac = 4, PlayDac = 5, RecordDac = 6 CONST StoreDac = 7, EndDac = 8, PauseDac = 9 CONST DeallocDac = 10 CONST SetAllDac = 20, SetVolumeDac = 21, SetIntRateDac = 22 CONST SetPriorityDac = 23 CONST GetBufferDataDac = 28, GetBytePosDac = 29 CONST SetAllSBP = 30, SetVolMainSBP = 31, SetVolVocSBP = 32 CONST SetLevelMicSBP = 33, SetLevelCDSBP = 34, SetLevelLineSBP = 35 CONST SetFilterOutSBP = 36, SetFilterInSBP = 37 CONST SetSourceSBP = 38, SetStereoSBP = 39 CONST SetSpeakerSB = 40 CONST GetMixerRegSBP = 48, GetDacSB = 49 CONST ExitMod = 50, AtExitMod = 51 CONST LoadMod = 52, PlayMod = 53 CONST EndMod = 54, PauseMod = 55 CONST SetIntRateMod = 56, SetSpeedMod = 57 CONST SetVolumeMod = 58, SetPositionMod = 59 CONST SetStereoMod = 60, SetFastMod = 61 TYPE DeallocPackTYPE 'DP Func AS INTEGER stat AS INTEGER HandSeg AS INTEGER 'RUCKUS allocates either XMM handle or DOS para TypeFlag AS INTEGER '0=DOS para, 1=XMS handle (not used for Mods) END TYPE '8 TYPE GetDataPackTYPE 'GDP Func AS INTEGER stat AS INTEGER BytePos AS LONG 'ret:current byte relative base ptr (27) BufferPtrOff AS INTEGER 'far pointer to buffer to fill with data,offset BufferPtrSeg AS INTEGER 'segment StartPos AS LONG 'start get at this offset relative BufferPtr BufferCnt AS INTEGER 'bytes to fill (2-65520) MixerReg AS INTEGER 'SBPro mixer register to get END TYPE '20 53 TYPE InitPackTYPE 'IP Func AS INTEGER stat AS INTEGER DeviceID AS INTEGER '0=SPKR,1=LPTDAC,2=DSS,4=SB,5=SBPro IOport AS INTEGER IRQline AS INTEGER DMAch AS INTEGER Flags AS INTEGER '(see Appendix D. RUCKUS-DAC Data Area) InfoPtrOff AS INTEGER 'ret:far ptr to dac info InfoPtrSeg AS INTEGER DacExitPtrOff AS INTEGER 'ret:far ptr to dac's ExitXB routine DacExitPtrSeg AS INTEGER ModExitPtrOff AS INTEGER 'ret:far ptr to mod's ExitXB routine ModExitPtrSeg AS INTEGER END TYPE '24 TYPE LoadPackTYPE 'LP Func AS INTEGER stat AS INTEGER FilenamePtrOff AS INTEGER 'far ptr to filenameZ to load FilenamePtrSeg AS INTEGER StartPos AS LONG 'offset into file to start load at LoadSize AS LONG 'number of bytes to load (or 0 for autosize) XMMflag AS INTEGER 'if <> 0 use XMS for load XMMhandle AS INTEGER 'ret:XMS handle, or LoadPtrOff AS INTEGER 'ret:DOS seg:offset (offset always 0) LoadPtrSeg AS INTEGER 'LoadPtr not used for Mod loads END TYPE '20 TYPE PlaybackPackTYPE 'PBP Func AS INTEGER stat AS INTEGER Mode AS INTEGER '(0=interrupt FG,1=BG,2=DMA,3=DMA+BG for mod) XMMhandle AS INTEGER 'if <> 0 this XMM handle used regardless LoadPtrOff AS INTEGER 'seg:off to start of data to play LoadPtrSeg AS INTEGER BufferSize AS INTEGER 'size of DMA buffer for mod playback END TYPE '14 TYPE PausePackTYPE 'PP Func AS INTEGER stat AS INTEGER Pause AS INTEGER '0=unpause else pause END TYPE '6 54 TYPE RecordPackTYPE 'RP Func AS INTEGER stat AS INTEGER SampleRate AS INTEGER XMMhandle AS INTEGER '-1 auto XMS (ret in dx) else use this handle RecordPtrOff AS INTEGER 'seg:off of buffer to store (0 for auto-store) RecordPtrSeg AS INTEGER 'ret: RecordPtr->buffer used (or in XMMhandle) RecordBytes AS LONG 'bytes to record StereoFlag AS INTEGER 'stereo flag END TYPE '18 TYPE SaveDataPackTYPE 'SDP Func AS INTEGER stat AS INTEGER FilenamePtrOff AS INTEGER 'far ptr to filenameZ to save FilenamePtrSeg AS INTEGER DataPtrOff AS INTEGER 'pointer to start of data to save, offset DataPtrSeg AS INTEGER 'segment (or 0 if XMS) FileType AS INTEGER '1=VOC,2=WAV XMMhandle AS INTEGER 'XMS handle of data to save (0 if DOS data) END TYPE '16 TYPE SetPackTYPE 'SP Func AS INTEGER stat AS INTEGER '(if volume=0 SB speaker off'ed else on'ed) Volume AS INTEGER 'volume (left ch=MSB,right=LSB) (0-127,0-127) IntRate AS INTEGER 'playback interrupt rate (5000-23000) Priority AS INTEGER 'priority level (0-2, default=1) END TYPE '18 TYPE SetModPackTYPE 'SMP 'stereo modes Func AS INTEGER 'A=ch1+ch3 & ch2+ch4 stat AS INTEGER 'B=? VolCh1 AS INTEGER 'channel volume (0-255) 'C=? VolCh2 AS INTEGER 'channel volumes adjustments made only VolCh3 AS INTEGER ' if FastMode=0 VolCh4 AS INTEGER Stereo AS INTEGER 'playback mode (0=mono,stereo 1=A,2=B,3=C) FastMode AS INTEGER 'fast playback (0=normal,1 fast,no ch volumes) IntRate AS INTEGER 'playback interrupt rate (5000-45500) Position AS INTEGER 'pattern list position (0-patterns to play) Speed AS INTEGER 'overall playback speed (1-15,default=6,15=slow) SliceAdj AS INTEGER 'DMA buffer fill count (1-4096, default=1) END TYPE '24 55 TYPE SetProPackTYPE 'SPP Func AS INTEGER stat AS INTEGER Volume AS INTEGER 'volume (low=right;0-15, high byte=left;0-15) VolVoc AS INTEGER ' VolMic AS INTEGER '(mono only, 0-7) input level VolCD AS INTEGER 'input level (0-15,0-15) VolLI AS INTEGER 'input level (0-15,0-15) FilterOut AS INTEGER '0=filter off, 1=filter on FilterIn AS INTEGER '0=filter off, 1=3.2kHz, 2=8.8kHz SourceIn AS INTEGER '0=mic,1=CD,2=line StereoIn AS INTEGER '0=mono,1=stereo record END TYPE '22 TYPE XitPackTYPE 'XP Func AS INTEGER stat AS INTEGER END TYPE '4 56 TYPE SysInfoPackTYPE 'SIP Func AS INTEGER stat AS INTEGER CPU AS INTEGER 'CPU class (88,286,386,486) CPUmode AS INTEGER '0=real mode,1=PM,2=PM w/paging MHz AS INTEGER 'approx speed (5,20,33) Device0 AS INTEGER '=1 speaker available D0port AS INTEGER '42h D0IRQ AS INTEGER 'n/a D0DMA AS INTEGER 'n/a D0flags AS INTEGER 'bit4=MIDI/3=XMS/2=DMA/1=REC/0=PLAY Device1 AS INTEGER '=1 LPT-DAC available on LPT1 D1port AS INTEGER 'port of _first_ LPT found in BIOS data area D1IRQ AS INTEGER 'n/a D1DMA AS INTEGER 'n/a D1flags AS INTEGER 'bit4=MIDI/3=XMS/2=DMA/1=REC/0=PLAY Device2 AS INTEGER '=1 Disney Sound Source available D2port AS INTEGER 'port of DSS D2IRQ AS INTEGER 'n/a D2DMA AS INTEGER 'n/a D2flags AS INTEGER 'bit4=MIDI/3=XMS/2=DMA/1=REC/0=PLAY Device3 AS INTEGER '=1 AdLib available D3port AS INTEGER '388h D3IRQ AS INTEGER 'n/a D3DMA AS INTEGER 'n/a D3flags AS INTEGER 'bit4=MIDI/3=XMS/2=DMA/1=REC/0=PLAY Device4 AS INTEGER '=1 SB available D4port AS INTEGER 'port of SB D4IRQ AS INTEGER 'IRQ D4DMA AS INTEGER 'DMA D4flags AS INTEGER 'bit4=MIDI/3=XMS/2=DMA/1=REC/0=PLAY Device5 AS INTEGER '=1 SBPro available D5port AS INTEGER 'port of SBPro D5IRQ AS INTEGER 'IRQ D5DMA AS INTEGER 'DMA D5flags AS INTEGER 'bit4=MIDI/3=XMS/2=DMA/1=REC/0=PLAY END TYPE '70 TYPE SysDevTYPE 'SD (used by BASIC 7.1 compiler) device AS INTEGER '=1 device available port AS INTEGER IRQ AS INTEGER DMA AS INTEGER Flags AS INTEGER 'bit4=MIDI/3=XMS/2=DMA/1=REC/0=PLAY END TYPE '10 TYPE SysInfoPackTYPE7 'SIP BASIC 7.1: SIP.SD(0).device = ... Func AS INTEGER '******* UNCOMMENT-OUT SD(0 TO 5) BELOW stat AS INTEGER CPU AS INTEGER 'CPU class (88,286,386,486) CPUmode AS INTEGER '0=real mode,1=PM,2=PM w/paging MHz AS INTEGER 'approx speed (5,20,33) ''SD(0 TO 5) AS SysDevTYPE 'QB45 won't accept arrays in TYPEs END TYPE '70 57 Appendix C. Compiler, Linker, QLB, and Call Use. Compile and Link. To create a stand-alone EXE file, compile your BASIC source as required. No special compiler switches are required. When your compiler is finished and has reported no errors during the compile, use the LINK program supplied with your compiler to resolve any external references in your BASIC program code that are dependent on the RUCKUS library code. For example, if you have a single-module BASIC source file called SOUND.BAS, compile it: C>bc SOUND /o; If successful, use the LINK program to build the final EXE: C>link SOUND,SOUND.EXE,nul,RUCKDAC.LIB RUCKMIDI.LIB; If successful, link creates SOUND.EXE ready to be run at the DOS prompt. The BASIC runtime is also supported by RUCKUS. Just compile as you normally would (without the /o, of course). RUCKUS is composed of many separate assembly language modules in two separate LIBs, one for digital data and the other for MIDI data. If you need to use more libraries with your programs, no problem, LINK can handle as many as you have. When LINK prompts you for a library file, just enter RUCKDAC.LIB and RUCKMIDI.LIB followed by any other library you need. For example: C>link Microsoft (R) Segmented Executable Linker Version 5.31.009 Jul 13 1992 Copyright (C) Microsoft Corp 1984-1992. All rights reserved. Object Modules [.OBJ]: SOUND+STUB Run File [.EXE]: SOUND.EXE List File [NUL.MAP]: nul Libraries [.LIB]: RUCKDAC RUCKMIDI MOUSE; Consult your linker programs documentation for more. 58 Creating a QLB. If you use the QuickBASIC environment to program in, you need to build a .QLB so that you can call the RUCKUS routines. While QuickBASIC can load only a single QLB ( C>qb /L quicklib.qlb ), you can combine many LIB and OBJ modules to create the QLB. For example, to make a QLB of the RUCKDAC.LIB, RUCKMIDI.LIB and MOUSE.LIB libraries: C>link /QU RUCKDAC.LIB+RUCKMIDI.LIB+MOUSE.LIB, IDE.QLB, nul, BQLB45.LIB; Note the extension .LIB on the library modules. This is REQUIRED since LINK assumes .OBJ by default. The quick library, BQLB45.LIB, is required for the Libraries: prompt. The exact name depends on the compiler version. Consult your compiler documentation for more. BASIC PDS note: BASIC PDS requires that all BASIC modules included into a QLB be compiled using the /Fs compiler switch. This instructs the compiler to generate code compatible with "far strings". Since RUCKUS is written entirely in assembly language, this is not an issue. However, if you start QBX.EXE with /L and get an INVALID FORMAT error, one of the modules in the .QLB file most likely was a BASIC module that was not compiled with the /Fs switch. Calling RUCKDAC() and RUCKMIDI(). RUCKUS is called through a single entry point. Depending on function (digital or MIDI) you use either RUCKDAC() or RUCKMIDI(). The only argument passed to is a segmented far pointer to the control pack. The first two entries in this pack are the function to be performed and the function return status. RUCKUS is a FUNCTION call returning an INTEGER status value (with a few exceptions, see the documentation). Each function (or routine) uses a prescribed pack format. For example, some routines need only know the function to perform. For example, to end a digital play you could do the following: DIM XP AS XitPackTYPE 'could also DIM SHARED XP.Func = EndDac 'EndDac is defined in RUCKDAC.BI stat = RUCKDAC(XP) 'do the actual call to RUCKUS-DAC 59 Appendix D. RUCKUS-DAC Data Area. The offset value below is relative InfoPtrOff as returned by InitDac. For example, to access dac@end, the following code can be used: DEF SEG = IP.InfoPtrSeg DacIsOver = PEEK(IP.InfoPtrOff + 10) DEF SEG For accessing word (dw) and double-word (dd) values, see Appendix A in the RUCKUS-MIDI document. Most dac@ variables are PUBLIC symbols and may be accessed directly by compilers that allow external references to variables. QuickBASIC does not so the DEF SEG method needs to be used. Where possible, access all dac@ data through a common function so that future changes can be easily made. Name Type Offset Comments ------------------------------ dac@deviceID dw +0 device ID dac@IOport dw 2 port of device dac@IRQ dw 4 IRQ of device dac@DMA dw 6 DMA of device dac@Flags dw 8 bit0=1 use DOS UMB memory bit1-4 reserved bit5=1 force XMS2 to be used bit6=1 force device speaker on until exit bit7=1 force passed parms to be used Following values are ret bits bit8=1 paging mechanism in force, no UMBs bit9-15 reserved dac@end dw 10 =1 end of play dac@pause dw 12 =1 pause play dac@endmod dw 14 =1 end of mod play dac@memDOS dw 16 DOS memory available (in K) dac@memXMM dw 18 XMS memory available (in K) dac@type dw 20 digital type (1=VOC w/header,2=WAV) dac@memUsed dw 22 memory used for last file load (in K) dac@sampleRate dw 24 sample rate currently playing dac@stereo dw 26 stereo dac@vocLen dd 28 length of voc block (only current block) dac@vocPtrPtr dd 32 pointer to pointer->current data dac@recordLen dd 36 length of recorded data 60 dac@sbpMixerPtr dd 40 pointer to SBP mixer data ;-4=farptr to SB data start(sbc@IRQnum) ;+0=volMasterR,+2=L ;+4=volVocR,+6=L ;+8=volMic ;+10=volCDR,+12=CDL ;+14=volLIR,+16=LIL ;+18=filterInOff,+20=filterOutOff ;+22=input source selected ;+24=input cutoff freq selected ;+26=1=stereo data output ;+27=1=high sample rate (>23kHz) ;+28=SB speaker on=1/off=0 ;+30=DSPver (1xx, 2xx, 3xx) ;+32=sbc@DSPtype 1=SB2 or below, 3=SBPro dac@modDataPtr dd 44 pointer to mod data Additional Mod Data Section relative dac@modDataPtr above: Name Type Offset Comments ------------------------------ mod@type dw +0 mod type (15 or 31 samples) mod@samples dw 2 number of instrument samples in mod mod@headerSeg dw 4 header segment (aka sample info) mod@patternSeg dw 6 pats' segment (1 to pats2play 1K patterns) mod@sampleSeg dw31 8 (+62) ;list of sample segments mod@stereo dw 70 =1 then play in stereo (only SBPro) mod@fastMode dw 72 =1 then channel volume adjusts disabled mod@mt_patListPos dw 74 byte pos within mod@patterList (0-127) mod@mt_notePatPos dw 76 note pos within pattern 1K area (0-1008) pattern#=patternList(patListPos) note is at offset (pattern#*1024)+notePatPos -- in segment mod@patternSeg mod@hiPattern dw 78 highest pattern number to play/+1!/ (0-63) mod@pats2play dw 80 pats to play (direct DOS file load here) mod@patternList db128 82 (+128) ;pattern positions (to here) mod@MKoverflow db6 210 (+6) ;overflow for 31-instr patpos read mod@memUsed dw 216 DOS RAM needed by mod file (in para) mod@VS dw 218 times VS handler entered (50Hz rate) 61 Appendix Z. Ordering Information, License Agreement and Product Support. To order you must you the order form included with the distribution files. Its filename is !ORDER.FRM. Orders made without this form may be delayed. There are two RUCKUS packages available. The PERSONAL DEVELOPER version is for the hobby-programmer while the PROFESSIONAL version is for the professional programmer. The PERSONAL DEVELOPER version is for persons that are not creating programs for distribution to others. With the PERSONAL DEVELOPER license you may not distribute any programs you create with RUCKUS. In addition, a sign-on banner is issued once, displaying the RUCKUS copyright and license restriction. The PROFESSIONAL version has no distribution restrictions on end-user programs you create with RUCKUS. The PROFESSIONAL license provides you with the right to create all the end-user programs royalty-free. You also have direct access to the latest version of RUCKUS free-of-charge by way of my support BBS and the RUCKUS Developer's Conference there. No sign-on banner is issued. 62 License Agreement Before using this software you must agree to the following: 1. You are not allowed to operate more than one (1) copy of this software package at one time per license. This means that if you have 10 programmers that COULD possibly use the RUCKUS library at the same time, you must also have ten (10) RUCKUS licenses. 2. You are not allowed to distribute non-executable code containing RUCKUS code. This means that you are not allowed to redistribute RUCKUS code as another .LIB, for example. Also, if RUCKUS code is to be contained in a Dynamic Link Library (DLL) then it must be part of a stand-alone product. This means that you cannot provide a .DLL containing RUCKUS code if that .DLL is to be used as a programming library for other programmers. If you wish to distribute non-executable code containing RUCKUS code you must obtain written permission from the author. 3. This license grants you the right to use the RUCKUS library code on a royalty-free basis, except when the license is the PERSONAL DEVELOPER, in which case you may not distribute any program in which RUCKUS has been used. 4. RUCKUS is owned by the author, Cornel Huth, and is protected by United States copyright laws and international treaty provisions. You are not allowed to make copies of this software except for archival purposes. 5. You may not rent or lease RUCKUS. You may not transfer this license without the written permission of the author. If this software is an update or upgrade, you may not sell or give away previous versions. 6. You may not reverse engineer, decompile, or disassemble this software. 7. There are no expressed or implied warranties with this software. 8. All liabilities in the use of this software rest with the user. 9. U.S. Government Restricted Rights. This software is provided with restricted rights. Use, duplication, or disclosure by the Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Software clause at 52.227-7013. Manufacturer is Cornel Huth/6402 Ingram Rd/San Antonio, TX 78238. This agreement is governed by the laws of the state of Texas. 63 Product Support Support is available 7 days/week from 17:00 to 09:00 Central Time at my BBS, the Fortieth Floor, at 1.210.684.8065. PROFESSIONAL version licensees have free access to all future RUCKUS updates and upgrades via the RUCKUS Developer's Conference on the Fortieth Floor BBS (1.210.684.8065). PERSONAL DEVELOPER licensees have restricted access to in-version maintenance updates at no charge. End of the RUCKUS-DAC DOCUMENT. See also the RUCKUS-MIDI DOCUMENT. 64