home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
QBAS
/
RUKQ10.ZIP
/
RUCKDAC.DOC
< prev
next >
Wrap
Text File
|
1993-02-15
|
108KB
|
4,225 lines
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