!WIDTH 78 ;------------------------------------------ !TOPIC 2 Contents !INDEX 1 ;------------------------------------------ Units in help file MAKEHELP.TXT:  3UltraDrv ;------------------------------------------ !TOPIC 3 UltraDrv ;------------------------------------------ Unit UltraDrv (in 2MAKEHELP.TXT help file)  Gravis Ultrasound driver unit. This unit provides functions and procedures for programming the Gravis UltraSound 16-bit 44Khz stereo sound card. Simply include this unit in your USES clause. Constants: 11Khz_11 12Khz_22 13Khz_44 15Loop_Volume 16Bi_Directional_Volume 17Enable_Volume_Handler 19Voice_Data_16Bit 20Loop_Voice 21Bi_Directional_Voice 22Enable_VoiceEnd_Handler 24DMA_Data_16Bit 25Convert_Data 26Ultra_Installed Types: 4PFV 5INT_PROC 6WORD_PROC 7TWOWORD_PROC 8Ultra_CFG 9VOICE_DATA_3D 10SOUND_3D Variables: 27Ultra_Config 28UltraOk 29UltraError 30UltraErrorStr Functions and Procedures: 31UltraCalcRate 32UltraClose 33UltraDownLoad 34UltraDRAMDMABusy 35UltraGoRecord 36UltraGoVoice 37UltraDisableLineIn 38UltraDisableMicIn 39UltraDisableOutput 40UltraEnableLineIn 41UltraEnableMicIn 42UltraEnableOutput 43UltraGetLineIn 44UltraGetMicIn 45UltraGetOutput 46UltraDRAMTcHandler 47UltraMIDIXMitHandler 48UltraMIDIRecvHandler 49UltraTimer1Handler 50UltraTimer2Handler 51UltraWaveHandler 52UltraVolumeHandler 53UltraRecordHandler 54UltraAuxHandler 55UltraMaxAvail 56UltraMaxAlloc 57UltraMemAvail 58UltraMemAlloc 59UltraMemFree 60UltraMIDIDisableRecv 61UltraMIDIDisableXmit 62UltraMIDIEnableRecv 63UltraMIDIEnableXmit 64UltraMIDIRecv 65UltraMIDIReset 66UltraMIDIStatus 67UltraMIDIXmit 68UltraOpen 69UltraPeekData 70UltraPing 71UltraPokeData 72UltraPrimeRecord 73UltraPrimeVoice 74UltraProbe 75UltraRampVolume 76UltraReadRecordPosition 77UltraReadVoice 78UltraReadVolume 79UltraRecordData 80UltraRecordDMABusy 81UltraReset 82UltraSetBalance 83UltraSetFrequency 84UltraSetLoopMode 85UltraSetRecordFrequency 86UltraSetVoice 87UltraSetVoiceEnd 88UltraSetVolume 89UltraSizeDRAM 90UltraStartTimer 91UltraStartVoice 92UltraStopTimer 93UltraStopVoice 94UltraStopVolume 95UltraTimerStopped 96UltraTrimJoystick 97UltraUpLoad 98UltraVectorVolume 99UltraVersion 100UltraVersionStr 101UltraVoiceStopped 102UltraVolumeStopped 103UltraWaitDRAMDMA 104UltraWaitRecordDMA 105UltraVoiceOff 106UltraVoiceOn 107UltraSetLinearVolume 108UltraReadLinearVolume 109UltraRampLinearVolume 110UltraVectorLinearVolume 111UltraClearVoices 112UltraAllocVoice 113UltraFreeVoice 116UltraAbsPosition3D 117UltraAngPosition3D 118UltraAngFltPosition3D 119UltraCloseDup3D 120UltraDup3D 121UltraLoad3DEffect 122UltraSetFreq3D 123UltraRelease3DInterleave 124UltraSetup3DInterleave 125UltraStart3D 126UltraStop3D 127UltraUnLoad3DEffect Other: 14Volume_Control_Bits 18Voice_Control_Bits 23DMA_Control_Bits 114Focal_Point_3d 115ThreeD_data_format ;------------------------------------------ !TOPIC 4 PFV ;------------------------------------------ 3UltraDrv.PFV = PROCEDURE  This type is used to designate procedures which can be called by the interrupt service routine. When the ISR finds that a specific condition has occurred, it will call a processing procedure that you specify. If you do not specify a processing procedure, a default routine is supplied which does nothing. Since PASCAL cannot return function or procedure type values from functions, the equivalent routine was made into a procedure which took a single VAR parameter. Thus, when you are going to change the address of a callback routine, you put the new address into a variable, run it through the procedure, and what will then be in the variable is the address of the old handler: !LINE !NOWRAP VAR OldProc : PFV; Procedure MyNewProc; (* The new handler *) { begin ... end; ...somewhere else... Set OldProc to address of new handler OldProc := MyNewProc; Now set the new handler and return the old one UltraDRAMTcHandler(OldProc); ... !LINE !WRAP At this point, OldProc holds the address of the old routine. Therefore, to chain to the old routine, you would simply have to call OldProc from your handler.  See also: 54UltraAuxHandler 46UltraDRAMTcHandler 53UltraRecordHandler 49UltraTimer1Handler 50UltraTimer2Handler ;------------------------------------------ !TOPIC 5 INT_PROC ;------------------------------------------ 3UltraDrv.INT_PROC = PROCEDURE (Voice: INTEGER) This type is used to designate procedures which can be called by the interrupt service routine. When the ISR finds that a specific condition has occurred, it will call a processing procedure that you specify. If you do not specify a processing procedure, a default routine is supplied which does nothing. Since PASCAL cannot return function or procedure type values from functions, the equivalent routine was made into a procedure which took a single VAR parameter. Thus, when you are going to change the address of a callback routine, you put the new address into a variable, run it through the procedure, and what will then be in the variable is the address of the old handler: !LINE !NOWRAP VAR OldProc : INT_PROC; Procedure MyNewProc(I : INTEGER); (* The new handler *) { begin ... end; ...somewhere else... Set OldProc to address of new handler OldProc := MyNewProc; Now set the new handler and return the old one UltraWaveHandler(OldProc); ... !LINE !WRAP At this point, OldProc holds the address of the old routine. Therefore, to chain to the old routine, you would simply have to call OldProc from your handler.  See also: 52UltraVolumeHandler 51UltraWaveHandler ;------------------------------------------ !TOPIC 6 WORD_PROC ;------------------------------------------ 3UltraDrv.WORD_PROC = PROCEDURE (MIDI_Send: WORD) This type is used to designate procedures which can be called by the interrupt service routine. When the ISR finds that a specific condition has occurred, it will call a processing procedure that you specify. If you do not specify a processing procedure, a default routine is supplied which does nothing. Since PASCAL cannot return function or procedure type values from functions, the equivalent routine was made into a procedure which took a single VAR parameter. Thus, when you are going to change the address of a callback routine, you put the new address into a variable, run it through the procedure, and what will then be in the variable is the address of the old handler: !LINE !NOWRAP VAR OldProc : WORD_PROC; Procedure MyNewProc(W : WORD); (* The new handler *) { begin ... end; ...somewhere else... Set OldProc to address of new handler OldProc := MyNewProc; Now set the new handler and return the old one UltraMIDIXMitHandler(OldProc); ... !LINE !WRAP At this point, OldProc holds the address of the old routine. Therefore, to chain to the old routine, you would simply have to call OldProc from your handler.  See also: 47UltraMIDIXMitHandler ;------------------------------------------ !TOPIC 7 TWOWORD_PROC ;------------------------------------------ 3UltraDrv.TWOWORD_PROC = PROCEDURE (MIDI_Status: WORD; MIDI_Data: WORD) This type is used to designate procedures which can be called by the interrupt service routine. When the ISR finds that a specific condition has occurred, it will call a processing procedure that you specify. If you do not specify a processing procedure, a default routine is supplied which does nothing. Since PASCAL cannot return function or procedure type values from functions, the equivalent routine was made into a procedure which took a single VAR parameter. Thus, when you are going to change the address of a callback routine, you put the new address into a variable, run it through the procedure, and what will then be in the variable is the address of the old handler: !LINE !NOWRAP VAR OldProc : TWOWORD_PROC; Procedure MyNewProc(W1 : WORD; W2 : WORD); (* The new handler *) { begin ... end; ...somewhere else... Set OldProc to address of new handler OldProc := MyNewProc; Now set the new handler and return the old one UltraWaveHandler(OldProc); ... !LINE !WRAP At this point, OldProc holds the address of the old routine. Therefore, to chain to the old routine, you would simply have to call OldProc from your handler.  See also: 48UltraMIDIRecvHandler ;------------------------------------------ !TOPIC 8 Ultra_CFG ;------------------------------------------ 3UltraDrv.Ultra_CFG = RECORD This record holds the configuration found in the DOS Environment string ULTRASND, if it can be read. If the string cannot be read, the fields will contain default values. !LINE !NOWRAP  Base_Port : WORD; default $220 Dram_DMA_Chan : WORD; default 1 ADC_DMA_Chan : WORD; default 1 GF1_IRQ_Num : WORD; default 11 MIDI_IRQ_Num : WORD; default 5 !LINE !WRAP  ;------------------------------------------ !TOPIC 9 VOICE_DATA_3D ;------------------------------------------ 3UltraDrv.VOICE_DATA_3D = RECORD This record holds the data for one of the six voices used to produce a 3-D sound. The fields are typical values needed to play a voice. !LINE !NOWRAP  VoiceNum : INTEGER; CurVol : INTEGER; VBegin : LONGINT; VStart : LONGINT; VEnd : LONGINT; !LINE !WRAP  See also: 0SOUND-3D ;------------------------------------------ !TOPIC 10 SOUND_3D ;------------------------------------------ 3UltraDrv.SOUND_3D = RECORD This record holds the data for a 3-D sound, including the sound type (interleaved or blocked), the hemisphere flags, the ramping speed, the 0-0-0 (maximum) volume, the number of independent tracks for the sound, as well as voice and DMA mode bytes. Specific data for each voice is held in an array at the bottom of the record. !LINE !NOWRAP  SType : BYTE; Flags : INTEGER; Rate : BYTE; MaxVol : INTEGER; Num_Tracks : INTEGER; Freq : LONGINT; VMode : BYTE; DMode : BYTE; VData : ARRAY[0..5] OF VOICE_DATA_3D; !LINE !WRAP  See also: 9VOICE_DATA_3D ;------------------------------------------ !TOPIC 11 Khz_11 ;------------------------------------------ Const 3UltraDrv.Khz_11 = 11025;  Common recording and playback frequency for sound and voice. See also: 83UltraSetFrequency ;------------------------------------------ !TOPIC 12 Khz_22 ;------------------------------------------ Const 3UltraDrv.Khz_22 = 22050;  Common recording and playback frequency for misc sounds. See also: 83UltraSetFrequency ;------------------------------------------ !TOPIC 13 Khz_44 ;------------------------------------------ Const 3UltraDrv.Khz_44 = 44100;  Common frequency for CD quality recording and playback. See also: 83UltraSetFrequency ;------------------------------------------ !TOPIC 14 Volume_Control_Bits ;------------------------------------------  Volume Control Bits: You can OR together the following constants to produce a volume ramp mode byte: !LINE !NOWRAP  Loop_Volume = 08; Bi_Directional_Volume = 16; Enable_Volume_Handler = 32; !LINE !WRAP  ;------------------------------------------ !TOPIC 15 Loop_Volume ;------------------------------------------ Const 3UltraDrv.Loop_Volume = 08;  See also: 14Volume_Control_Bits ;------------------------------------------ !TOPIC 16 Bi_Directional_Volume ;------------------------------------------ Const 3UltraDrv.Bi_Directional_Volume = 16;  See also: 14Volume_Control_Bits ;------------------------------------------ !TOPIC 17 Enable_Volume_Handler ;------------------------------------------ Const 3UltraDrv.Enable_Volume_Handler = 32;  See also: 14Volume_Control_Bits ;------------------------------------------ !TOPIC 18 Voice_Control_Bits ;------------------------------------------  Voice Control Bits: You can OR together the following constants to produce a voice control byte: !LINE !NOWRAP  Voice_Data_16Bit = 04; Loop_Voice = 08; Bi_Directional_Voice = 16; Enable_VoiceEnd_Handler = 32; !LINE !WRAP  ;------------------------------------------ !TOPIC 19 Voice_Data_16Bit ;------------------------------------------ Const 3UltraDrv.Voice_Data_16Bit = 04;  See also: 18Voice_Control_Bits ;------------------------------------------ !TOPIC 20 Loop_Voice ;------------------------------------------ Const 3UltraDrv.Loop_Voice = 08;  See also: 18Voice_Control_Bits ;------------------------------------------ !TOPIC 21 Bi_Directional_Voice ;------------------------------------------ Const 3UltraDrv.Bi_Directional_Voice = 16;  See also: 18Voice_Control_Bits ;------------------------------------------ !TOPIC 22 Enable_VoiceEnd_Handler ;------------------------------------------ Const 3UltraDrv.Enable_VoiceEnd_Handler = 32;  See also: 18Voice_Control_Bits ;------------------------------------------ !TOPIC 23 DMA_Control_Bits ;------------------------------------------  DMA Control Bits: You can OR together the following constants to produce a DMA control byte: !LINE !NOWRAP  DMA_Data_16Bit = 64; Convert_Data = 128; !LINE !WRAP  ;------------------------------------------ !TOPIC 24 DMA_Data_16Bit ;------------------------------------------ Const 3UltraDrv.DMA_Data_16Bit = 64;  See also: 23DMA_Control_Bits ;------------------------------------------ !TOPIC 25 Convert_Data ;------------------------------------------ Const 3UltraDrv.Convert_Data = 128;  See also: 23DMA_Control_Bits ;------------------------------------------ !TOPIC 26 Ultra_Installed ;------------------------------------------ Const 3UltraDrv.Ultra_Installed: BOOLEAN = FALSE;  This constant is initially set to FALSE to signify that the card has not yet been found. In the initialization section of the unit, which is executed BEFORE your application, this constant is changed to TRUE if the 'ULTRASND' environment variable can successfully be read from the DOS environment. See also: 8Ultra_CFG ;------------------------------------------ !TOPIC 27 Ultra_Config ;------------------------------------------ 3UltraDrv.Ultra_Config: 8Ultra_CFG; This variable holds the current configuration. If the configuration can successfully be read at program start-up, this variable will hold the values found in the environment string. If the environment variable cannot be found, you may wish to specify values other than the defaults prior to opening the card with 68UltraOpen. See also: 8Ultra_CFG ;------------------------------------------ !TOPIC 28 UltraOk ;------------------------------------------ 3UltraDrv.UltraOk: BOOLEAN; If there is an error while executing any of the procedures or functions in this driver unit, this BOOLEAN will be set to FALSE. Otherwise, it will remain TRUE. See also: 29UltraError 30UltraErrorStr ;------------------------------------------ !TOPIC 29 UltraError ;------------------------------------------ 3UltraDrv.UltraError: INTEGER; This reports the error number if an error occurs in any procedure or function in the driver unit. Check 30UltraErrorStr for a string description of the error. See also: 30UltraErrorStr 28UltraOk ;------------------------------------------ !TOPIC 30 UltraErrorStr ;------------------------------------------ 3UltraDrv.UltraErrorStr: STRING; This string reports a description of the error if an error occurs in any procedure or function in the driver unit. Check 29UltraError for the error's number. See also: 29UltraError 28UltraOk ;------------------------------------------ !TOPIC 31 UltraCalcRate ;------------------------------------------ FUNCTION 3UltraDrv.UltraCalcRate(StartV: WORD; EndV: WORD; Mil_Secs: LONGINT): BYTE;  This routine calculates the rate necessary to ramp the volume from StartV volume (logarithmic) to EndV volume (logarithmic) in a desired number of milliseconds. This value should be passed to 75UltraRampVolume. This is only an approximation. The longer the time span, the less precise the result is likely to be. The function returns a value which can be passed to 75UltraRampVolume or 109UltraRampLinearVolume. See also: 109UltraRampLinearVolume 75UltraRampVolume ;------------------------------------------ !TOPIC 32 UltraClose ;------------------------------------------ FUNCTION 3UltraDrv.UltraClose: BOOLEAN;  This routine should be called before your application exits. It shuts down all audio and puts the card in a stable state. It also puts the PC back to the state prior to running your application (resets interrupt vectors etc). The function returns TRUE if Close was successful, FALSE otherwise.  See also: 68UltraOpen 81UltraReset ;------------------------------------------ !TOPIC 33 UltraDownLoad ;------------------------------------------ FUNCTION 3UltraDrv.UltraDownLoad(DataPtr: POINTER; Control: BYTE; DRAM_Loc: LONGINT; Len: WORD; Wait: BOOLEAN): BOOLEAN;  This routine will transfer a chunk of data from the PC's RAM to the UltraSound's DRAM. It will transfer 'Len' number of bytes from DataPtr (in PC) to DRAM_Loc (in UltraSound). If 'Wait' is TRUE, then it will wait until the transfer is complete. If 'Wait' is FALSE, it will return as soon as transfer is started. In some cases where you need to get output quickly, you can start the download and then immediately start a voice playing the data. The DMA transfer is MUCH faster than the voice playback, so it will be able to download data ahead of the playback. For obvious reasons, this will not work if you want to play the data backwards. The function returns TRUE if transfer was successful, FALSE otherwise. If unsuccessful, check 30UltraErrorStr for the reason. #M See also: 23DMA_Control_Bits 34UltraDRAMDMABusy 97UltraUpload  ;------------------------------------------ !TOPIC 34 UltraDRAMDMABusy ;------------------------------------------ FUNCTION 3UltraDrv.UltraDRAMDMABusy: BOOLEAN;  This routine will check to see if the to/from DRAM DMA channel is busy. It might be useful so your application doesn't hang around while waiting for a DMA transfer to complete. The function returns TRUE if the channel is still busy, FALSE if it's free.  See also: 0 0 33UltraDownload 97UltraUpload 103UltraWaitDRAMDMA ;------------------------------------------ !TOPIC 35 UltraGoRecord ;------------------------------------------ FUNCTION 3UltraDrv.UltraGoRecord(Control: BYTE): BOOLEAN;  This routine will start up a pre-primed record (done with 72UltraPrimeRecord). It can also be used to restart a indefinite recording process from the recording handler callback. The function returns TRUE if Record started ok. FALSE otherwise. If FALSE check the 30UltraErrorStr for the reason.  See also: 0 0 72UltraPrimeRecord 79UltraRecordData 53UltraRecordHandler ;------------------------------------------ !TOPIC 36 UltraGoVoice ;------------------------------------------ PROCEDURE 3UltraDrv.UltraGoVoice(Voice: INTEGER; VMode: BYTE);  This routine will start up a voice that has already been primed with set-up values by 73UltraPrimeVoice. This can be useful if you need to start multiple voices as close together as possible. See also: 0 73UltraPrimeVoice 91UltraStartVoice ;------------------------------------------ !TOPIC 37 UltraDisableLineIn ;------------------------------------------ PROCEDURE 3UltraDrv.UltraDisableLineIn;  If line level input is enabled and output is enabled, the input is routed directly to the output and audio will be heard. If this is not desired, use this to disable line in. See also: 0 40UltraEnableLineIn 43UltraGetLineIn ;------------------------------------------ !TOPIC 38 UltraDisableMicIn ;------------------------------------------ PROCEDURE 3UltraDrv.UltraDisableMicIn;  If microphone input is enabled and output is enabled, the input is routed directly to the output and audio will be heard. If this is not desired, use this to disable microphone in. See also: 0 41UltraEnableMicIn 44UltraGetMicIn ;------------------------------------------ !TOPIC 39 UltraDisableOutput ;------------------------------------------ PROCEDURE 3UltraDrv.UltraDisableOutput;  This routine will disable all output from the UltraSound. This can be used during recording so that the input will not be looped back to the output. It is also useful to disable output during resets since that will help eliminate 'pops' during initialization. See also: 0 42UltraEnableOutput 45UltraGetOutput ;------------------------------------------ !TOPIC 40 UltraEnableLineIn ;------------------------------------------ PROCEDURE 3UltraDrv.UltraEnableLineIn;  Turns on the line level input. If you are not recording from the line input, it is probably not desirable to have this enabled since it will be looped back to the output (if output is enabled). See also: 0 37UltraDisableLineIn 43UltraGetLineIn ;------------------------------------------ !TOPIC 41 UltraEnableMicIn ;------------------------------------------ PROCEDURE 3UltraDrv.UltraEnableMicIn;  This routine should be called when you want to record from the microphone. It is possible to have both the microphone input enabled and line level input enabled. If you are not recording from the microphone, it is recommended that it be disabled, since it will reduce noise on the output. See also: 0 38UltraDisableMicIn 44UltraGetMicIn ;------------------------------------------ !TOPIC 42 UltraEnableOutput ;------------------------------------------ PROCEDURE 3UltraDrv.UltraEnableOutput;  This routine must be called to enable any output from the UltraSound. This can be used to turn on output after muting it with 39UltraDisableOutput. See also: 0 39UltraDisableOutput 45UltraGetOutput ;------------------------------------------ !TOPIC 43 UltraGetLineIn ;------------------------------------------ FUNCTION 3UltraDrv.UltraGetLineIn: BOOLEAN;  This can be useful if you want to change the state of the line level input and then restore it back to the original state. The function returns TRUE if LineIn is Enabled, FALSE otherwise.  See also: 0 37UltraDisableLineIn 40UltraEnableLineIn ;------------------------------------------ !TOPIC 44 UltraGetMicIn ;------------------------------------------ FUNCTION 3UltraDrv.UltraGetMicIn: BOOLEAN;  This can be useful if you want to change the state of the microphone input and then restore it back to the original state. The function returns TRUE if Output is Enabled, FALSE otherwise.  See also: 0 38UltraDisableMicIn 41UltraEnableMicIn ;------------------------------------------ !TOPIC 45 UltraGetOutput ;------------------------------------------ FUNCTION 3UltraDrv.UltraGetOutput: BOOLEAN;  This can be useful if you want to change the state of the output and then restore it back to the original state. The function returns TRUE if Output is Enabled, FALSE otherwise.  See also: 0 39UltraDisableOutput 42UltraEnableOutput ;------------------------------------------ !TOPIC 46 UltraDRAMTcHandler ;------------------------------------------ PROCEDURE 3UltraDrv.UltraDRAMTcHandler(VAR Handler: 4PFV);  This procedure defines a callback for a DMA transfer to the UltraSound has been completed. The routine address passed as a parameter is set as the new handler. No parameters are passed to your new handler. See also: 4PFV ;------------------------------------------ !TOPIC 47 UltraMIDIXMitHandler ;------------------------------------------ PROCEDURE 3UltraDrv.UltraMIDIXMitHandler(VAR Handler: 6WORD_PROC);  This procedure defines a callback for a MIDI transmit empty interrupt occurs. This can be used to send out MIDI data under interrupt control. The routine address passed as a parameter is set as the new handler. The MIDI Status Byte is passed to the new handler defined. See also: 0 48UltraMIDIRecvHandler 6WORD_PROC ;------------------------------------------ !TOPIC 48 UltraMIDIRecvHandler ;------------------------------------------ PROCEDURE 3UltraDrv.UltraMIDIRecvHandler(VAR Handler: 7TWOWORD_PROC);  This procedure defines a callback for a byte is received in the MIDI input port. This can be used to get data from the MIDI port under interrupt contol. The routine address passed as a parameter is set as the new handler. The MIDI port status and MIDI data are passed to your handler. See also: 0 7TWOWORD_PROC 47UltraMIDIXmitHandler ;------------------------------------------ !TOPIC 49 UltraTimer1Handler ;------------------------------------------ PROCEDURE 3UltraDrv.UltraTimer1Handler(VAR Handler: 4PFV);  This procedure defines a callback for the UltraSound's Timer 1 'Ticks'. The routine address passed as a parameter is set as the new handler. No parameters are passed to this handler. See also: 0 0 4PFV 90UltraStartTimer 50UltraTimer2Handler ;------------------------------------------ !TOPIC 50 UltraTimer2Handler ;------------------------------------------ PROCEDURE 3UltraDrv.UltraTimer2Handler(VAR Handler: 4PFV);  This procedure defines a callback for the UltraSound's Timer 2 'Ticks'. The routine address passed as a parameter is set as the new handler. No parameters are passed to this handler. See also: 0 0 4PFV 90UltraStartTimer 49UltraTimer1Handler ;------------------------------------------ !TOPIC 51 UltraWaveHandler ;------------------------------------------ PROCEDURE 3UltraDrv.UltraWaveHandler(VAR Handler: 5INT_PROC);  This procedure defines a callback for a voice generates a wavetable interrupt. This happens when a voice hits it's end and interrupts are enabled. It will happen even if looping is on (i.e. the voice keeps playing). The routine address passed as a parameter is set as the new handler. Normally, This procedure is used to signify that a voice is done playing. This handler can be useful for starting another voice or counting the number of times that a voice goes through a loop. The voice number that generated the interrupt is passed back to your handler. See also: 0 5INT_PROC ;------------------------------------------ !TOPIC 52 UltraVolumeHandler ;------------------------------------------ PROCEDURE 3UltraDrv.UltraVolumeHandler(VAR Handler: 5INT_PROC);  This procedure defines a callback for a volume ramp ends. The routine address passed as a parameter is set as the new handler. This routine can be used to generate a volume envelope (attack, decay, sustain, release). This is done by changing to the appropriate volume ramps in the handler to handle the next part of the envelope. The voice number causing the interrupt will be passed back to your handler. See also: 4PFV ;------------------------------------------ !TOPIC 53 UltraRecordHandler ;------------------------------------------ PROCEDURE 3UltraDrv.UltraRecordHandler(VAR Handler: 4PFV);  This routine is called when a buffer that was being recorded into is full. The routine address passed as a parameter is set as the new handler. Normally, this procedure would be used to let the application start up another record. A double buffering scheme could be used to record data continuously. No parameters are passed to this handler. As long as the DMA channels for recording and playback are different, the UltraSound is capable of simultaneously recording and playback. At high data rates your application may have a problem with throughput. See also: 4PFV ;------------------------------------------ !TOPIC 54 UltraAuxHandler ;------------------------------------------ PROCEDURE 3UltraDrv.UltraAuxHandler(VAR Handler: 4PFV);  This handler will be called at the end of ALL interrupts that happen on the UltraSound. Its primary purpose is for use with the new UltraMax card since its shares its IRQ with the GF1. See also: 0 4PFV ;------------------------------------------ !TOPIC 55 UltraMaxAvail ;------------------------------------------ FUNCTION 3UltraDrv.UltraMaxAvail: LONGINT;  This routine will return the largest block of DRAM (in bytes) that can still be allocated. This can be useful for determining whether or not a patch or sample can be loaded. The maximum size of a block is 256K. This routine is included to provide consistency of naming for PASCAL Programmers. The function returns number of bytes in largest available block.  See also: 0 58UltraMemAlloc 57UltraMemAvail 59UltraMemFree ;------------------------------------------ !TOPIC 56 UltraMaxAlloc ;------------------------------------------ FUNCTION 3UltraDrv.UltraMaxAlloc: LONGINT;  This routine will return the largest block of DRAM (in bytes) that can still be allocated. This can be useful for determining whether or not a patch or sample can be loaded. The maximum size of a block is 256K. The function returns number of bytes in largest available block.  See also: 0 55UltraMaxAvail 58UltraMemAlloc 57UltraMemAvail 59UltraMemFree ;------------------------------------------ !TOPIC 57 UltraMemAvail ;------------------------------------------ FUNCTION 3UltraDrv.UltraMemAvail: LONGINT;  This will return the total amount of DRAM still available for use on the UltraSound. See also: 0 56UltraMaxAlloc 55UltraMaxAvail 58UltraMemAlloc 59UltraMemFree ;------------------------------------------ !TOPIC 58 UltraMemAlloc ;------------------------------------------ FUNCTION 3UltraDrv.UltraMemAlloc(Size: LONGINT; VAR Location: LONGINT): BOOLEAN;  This routine allocates a chunk of DRAM of 'Size' bytes from the UltraSound's DRAM. The memory allocation structures are set up by 68UltraOpen. 'Location' is filled in with the DRAM location of the start of the chunk of memory. The memory address returned will ALWAYS be aligned on a 32 byte boundary so that the DRAM can be DMA'ed into without error. Also, the size will be rounded UP to the next 32 byte boundary. PASCAL users can reference section 1.8.3 for a detailed look at how the memory is managed. The function returns TRUE if the allocation was successful. If FALSE, check 30UltraErrorStr for the reason.  See also: 0 56UltraMaxAlloc 55UltraMaxAvail 57UltraMemAvail 59UltraMemFree ;------------------------------------------ !TOPIC 59 UltraMemFree ;------------------------------------------ FUNCTION 3UltraDrv.UltraMemFree(Size: LONGINT; Location: LONGINT): BOOLEAN;  Frees a previously allocated chunk of UltraSound memory. The size will automatically be rounded UP to the next 32 byte boundary. The function returns TRUE if deallocation was successful. If FALSE, check 30UltraErrorStr for the reason.  See also: 0 55UltraMaxAvail 58UltraMemAlloc 57UltraMemAvail 0UltraMemInit ;------------------------------------------ !TOPIC 60 UltraMIDIDisableRecv ;------------------------------------------ PROCEDURE 3UltraDrv.UltraMIDIDisableRecv;  This routine will disable the receive data interrupts from the MIDI. If the interrupt is enabled, it should be disabled before leaving your application. See also: 0 62UltraMIDIEnableRecv 48UltraMIDIRecvHandler ;------------------------------------------ !TOPIC 61 UltraMIDIDisableXmit ;------------------------------------------ PROCEDURE 3UltraDrv.UltraMIDIDisableXmit;  This routine will turn off MIDI transmit interrupts. It MUST be called when you are through sending data. See also: 0 63UltraMIDIEnableXmit 47UltraMIDIXmitHandler ;------------------------------------------ !TOPIC 62 UltraMIDIEnableRecv ;------------------------------------------ PROCEDURE 3UltraDrv.UltraMIDIEnableRecv;  This routine will enable receive data interrupts from the MIDI port. It is necessary to set up a callback routine for your application to process the data. See also: 0 60UltraMIDIDisableRecv 48UltraMIDIRecvhandler ;------------------------------------------ !TOPIC 63 UltraMIDIEnableXmit ;------------------------------------------ PROCEDURE 3UltraDrv.UltraMIDIEnableXmit;  This routine will enable transmit data interrupts to be generated as each byte is transmitted out the MIDI port. Note that a transmit interrupt will be generated as soon as the IRQ is enabled unless a byte is sent out immediately prior to enabling it. This is because the xmit buffer is initially empty (unless primed) so it will pop an interrupt. Also note that you MUST disable this interrupt when you are not sending any more data or else you will be hung up getting transmit ready interrupts. See also: 0 61UltraMIDIDisableXmit 47UltraMIDIXmitHandler ;------------------------------------------ !TOPIC 64 UltraMIDIRecv ;------------------------------------------ FUNCTION 3UltraDrv.UltraMIDIRecv: BYTE;  This routine is used to read a byte from the MIDI port. It assumes that the byte is waiting. The Byte is there if it got to the MIDI receive interrupt callback routine or if you have polled the status and determined the receive buffer is full. The function returns MIDI data byte.  See also: 0 48UltraMIDIRecvHandler 66UltraMIDIStatus ;------------------------------------------ !TOPIC 65 UltraMIDIReset ;------------------------------------------ PROCEDURE 3UltraDrv.UltraMIDIReset;  This routine should be used to ensure that the MIDI port is ready to use. All MIDI interrupts will be disabled by this call. See also: 0 0UltraEnableMIDIRecv 0UltraEnableMIDIXmit ;------------------------------------------ !TOPIC 66 UltraMIDIStatus ;------------------------------------------ FUNCTION 3UltraDrv.UltraMIDIStatus: BYTE;  This routine returns the current MIDI port status bits. This can be used to determine if an error has occurred or if the port is ready to be read or written. The function returns The MIDI status byte.  See also: 0 64UltraMIDIRecv 67UltraMIDIXmit ;------------------------------------------ !TOPIC 67 UltraMIDIXmit ;------------------------------------------ PROCEDURE 3UltraDrv.UltraMIDIXmit(Data: BYTE);  This routine will send the 'Data' byte out the MIDI data port. If interrupts are enabled, an interrupt will be generated when the Byte has been transmitted. See also: 47UltraMIDIXmitHandler ;------------------------------------------ !TOPIC 68 UltraOpen ;------------------------------------------ FUNCTION 3UltraDrv.UltraOpen(VAR Config: 8Ultra_CFG; Voices: INTEGER): BOOLEAN;  This routine should ALWAYS be called to initialize the UltraSound. It will probe for the card and program the IRQ and DMA latches. It will then disable line and microphone input and enable output. It also initializes the memory structures. The number of active voices is an important parameter to the UltraSound: the fewer the number of voices, the more oversampling that occurs on playback. This will make the sound much 'cleaner'. If you specify a number of voices less than 14, the card will still be initialized to use 14 voices. Likewise, if you select larger than 32 voices, you will still only have 32. The function returns TRUE if the card was successfully opened. If FALSE, check 30UltraErrorStr for the reason.  See also: 0 32UltraClose 74UltraProbe ;------------------------------------------ !TOPIC 69 UltraPeekData ;------------------------------------------ FUNCTION 3UltraDrv.UltraPeekData(PPort: INTEGER; Address: LONGINT): BYTE;  This routine is used to allow an application to look at any location in UltraSound's DRAM. This can be handy for obtaining VU information or any other time it is nice to know what is in DRAM. Be aware that if the data is playable it will be in twos compliment form. If the data that you want is 16 bit data, you will need to peek both locations and do any appropriate conversions. The data will be in low/high format. That means that the low byte of the data will be in the even byte and the high byte will be in the odd byte. The function returns Data byte at location specified.  See also: 0 71UltraPokeData 97UltraUpload ;------------------------------------------ !TOPIC 70 UltraPing ;------------------------------------------ FUNCTION 3UltraDrv.UltraPing(PPort: WORD): BOOLEAN;  This routine will determine if an UltraSound is present by attempting to read and write to its DRAM. This routine assumes that at least a simple reset has been done since power-up so that the board is no longer in a reset state. If it is on a reset state, this routine will ALWAYS fail. 74UltraProbe pulls a quick reset and then calls 70UltraPing. The function returns TRUE if the card was found. If FALSE, check 30UltraErrorStr for the reason.  See also: 74UltraProbe ;------------------------------------------ !TOPIC 71 UltraPokeData ;------------------------------------------ PROCEDURE 3UltraDrv.UltraPokeData(PPort: INTEGER; Address: LONGINT; Data: BYTE);  Poke an 8 bit value directly into UltraSound DRAM. This can be useful to set the value of the location that a voice is pointing to. It is often desirable to point a voice to a known value since its output is ALWAYS summed in to the output even if the voice is not running. Be aware that there is no automatic conversion of data poked into DRAM. Since the UltraSound can only play twos compliment data, make sure that the data you are poking is in that format. Also be careful with 16 bit data. See also: 0 33UltraDownload 69UltraPeekData ;------------------------------------------ !TOPIC 72 UltraPrimeRecord ;------------------------------------------ FUNCTION 3UltraDrv.UltraPrimeRecord(PC_Ptr: POINTER; Size: WORD; RRepeat: BOOLEAN): BOOLEAN;  This routine will setup the DMA channel to do a record, but does not start it. This can be used to help synchronize events. Programming the DMA channel can take enough time so that a few samples may be lost. (Depending on sample rate). This routine will help alleviate this problem by doing the programming ahead of time. The function returns TRUE if setup was successful. If FALSE, check 30UltraErrorStr for the reason.  See also: 35UltraGoRecord ;------------------------------------------ !TOPIC 73 UltraPrimeVoice ;------------------------------------------ FUNCTION 3UltraDrv.UltraPrimeVoice(Voice: INTEGER; VBegin: LONGINT; VStart: LONGINT; VEnd: LONGINT; VMode: BYTE): BYTE;  This routine is used to do all the setup necessary to start a voice but does NOT start it up. This can be useful if you want to start more than 1 voice at the same time. Use 73UltraPrimeVoice to do all the necessary setup and then use 36UltraGoVoice to start the voices. 91UltraStartVoice calls 73UltraPrimeVoice and then immediately 36UltraGoVoice. The function returns An updated mode value. The mode may be modified on the basis of the location parameters. This altered value should be the one passed to 36UltraGoVoice.  See also: 0 36UltraGoVoice 91UltraStartVoice ;------------------------------------------ !TOPIC 74 UltraProbe ;------------------------------------------ FUNCTION 3UltraDrv.UltraProbe(PPort: WORD): BOOLEAN;  This routine probes for the existence of an UltraSound card at the specified base port. An application could call this before calling 68UltraOpen to see if a card is present. 68UltraOpen calls this routine also. The difference between 74UltraProbe and 70UltraPing is that 74UltraProbe will pull a reset to make sure the board is running. 70UltraPing assumes this has already been done. The function returns TRUE if the card is found. If FALSE, check 30UltraErrorStr for the reason.  See also: 0 68UltraOpen 70UltraPing ;------------------------------------------ !TOPIC 75 UltraRampVolume ;------------------------------------------ PROCEDURE 3UltraDrv.UltraRampVolume(Voice: INTEGER; StartV: WORD; EndV: WORD; VRate: BYTE; VMode: BYTE);  Start a volume ramp from a starting volume to the ending volume. The rate at which the ramp occurs can be calculated using 31UltraCalcRate. The mode determines the looping and interrupting characteristics of the ramp. If you choose to have it interrupt at the end of the ramp, you should set up an routine to call for a volume interrupt. This is done with the routine 52UltraVolumeHandler. See also: 0 31UltraCalcRate 52UltraVolumeHandler 14Volume_Control_Bits ;------------------------------------------ !TOPIC 76 UltraReadRecordPosition ;------------------------------------------ FUNCTION 3UltraDrv.UltraReadRecordPosition: WORD;  This routine can be used to monitor the amount data recorded. The function returns Number of BYTES recorded so far.  See also: 79UltraRecordData ;------------------------------------------ !TOPIC 77 UltraReadVoice ;------------------------------------------ FUNCTION 3UltraDrv.UltraReadVoice(Voice: INTEGER): LONGINT;  This routine can be used to monitor a voice's progress. The function returns The voice's current position in DRAM.  See also: 86UltraSetVoice ;------------------------------------------ !TOPIC 78 UltraReadVolume ;------------------------------------------ FUNCTION 3UltraDrv.UltraReadVolume(Voice: INTEGER): WORD;  This routine returns the current volume of a voice. This can be useful when used in conjunction with volume ramps. The value returned is logarithmic, not linear. PASCAL users can use 108UltraReadLinearVolume. The function returns 0-4095 value, the current logarithmic volume.  See also: 0 75UltraRampVolume 88UltraSetVolume ;------------------------------------------ !TOPIC 79 UltraRecordData ;------------------------------------------ FUNCTION 3UltraDrv.UltraRecordData(PC_Ptr: POINTER; Control: BYTE; Size: WORD; Wait: BOOLEAN; RRepeat: BOOLEAN): BOOLEAN;  This routine will record a buffer of data from UltraSound. It can be in either 8-bit mono or stereo. In stereo, there are two bytes and the left byte is first. If mono is being used, the left channel is the one that is sampled. If 'wait' is set to a non-zero value, then this routine will not return until the buffer has been filled. If 'repeat' is TRUE, then the DMA channel will be set up in auto-init mode so that the recording is done indefinitely. If this is done, then the buffer MUST reside completely in 1 64K page of PC RAM. Also, it is probably necessary that your application hooks to the record handler so that the control register on the UltraSound can be hit to restart the recording process (35UltraGoRecord). This will be very quick since the PC DMA controller will not be re- programmed. The function returns TRUE if successful. If FALSE, check 30UltraErrorStr for the reason.  See also: 0 35UltraGoRecord 85UltraSetRecordFrequency 104UltraWaitRecordDMA ;------------------------------------------ !TOPIC 80 UltraRecordDMABusy ;------------------------------------------ FUNCTION 3UltraDrv.UltraRecordDMABusy: BOOLEAN;  This routine checks to see if the record DMA channel is busy. It might be busy doing a record (or playback if the record & playback channels are the same). The function returns TRUE if the channel is busy, FALSE otherwise.  See also: 79UltraRecordData ;------------------------------------------ !TOPIC 81 UltraReset ;------------------------------------------ FUNCTION 3UltraDrv.UltraReset(Voices: INTEGER): BOOLEAN;  This routine is called by 68UltraOpen to make sure the card is in a known state. 32UltraClose also calls this routine. The function returns TRUE if card is successfully reset. If FALSE, check 30UltraErrorStr for the reason.  See also: 0 32UltraClose 68UltraOpen ;------------------------------------------ !TOPIC 82 UltraSetBalance ;------------------------------------------ PROCEDURE 3UltraDrv.UltraSetBalance(Voice: INTEGER; Data: BYTE);  This routine sets the voice's position between right and left speakers. A 0 will place the audio all the way to the left whereas a 15 will put the sound all the way to the right. Values that are out of range will move the balance to the nearest extreme. ;------------------------------------------ !TOPIC 83 UltraSetFrequency ;------------------------------------------ PROCEDURE 3UltraDrv.UltraSetFrequency(Voice: INTEGER; Speed_Khz: LONGINT);  This routine sets the voice's playback rate to the specified absolute frequency. The number of active voices is taken into account when making the appropriate calculations. ;------------------------------------------ !TOPIC 84 UltraSetLoopMode ;------------------------------------------ PROCEDURE 3UltraDrv.UltraSetLoopMode(Voice: INTEGER; VMode: BYTE);  This routine will set this voice's looping mode to the specified mode. See also: 18Voice_Control_Bits ;------------------------------------------ !TOPIC 85 UltraSetRecordFrequency ;------------------------------------------ PROCEDURE 3UltraDrv.UltraSetRecordFrequency(Rate: LONGINT);  This routine sets the record rate to the specified frequency. Since the UltraSound uses the PC DMA channel to do the sampling directly into PC RAM, no voice specification is necessary. ;------------------------------------------ !TOPIC 86 UltraSetVoice ;------------------------------------------ PROCEDURE 3UltraDrv.UltraSetVoice(Voice: INTEGER; Location: LONGINT);  This routine sets a voice's current position to an absolute location. This can be useful to set a voice to a location with a known value since all voices' current locations are summed in to the output even if the voice is not running. 'Pops' in the audio may result if a voice is set to a location that contains a significant value. ;------------------------------------------ !TOPIC 87 UltraSetVoiceEnd ;------------------------------------------ PROCEDURE 3UltraDrv.UltraSetVoiceEnd(Voice: INTEGER; VEnd: LONGINT);  This routine sets a new endpoint for the specified voice. Used in conjunction with 84UltraSetLoopMode to turn looping off, a sampled decay can be implemented. See also: 84UltraSetLoopMode ;------------------------------------------ !TOPIC 88 UltraSetVolume ;------------------------------------------ PROCEDURE 3UltraDrv.UltraSetVolume(Voice: INTEGER; Volume: WORD);  This routine sets the volume of the voice to a specific logarithmic value. The range is from 0 to 4095. Use 107UltraSetLinearVolume to do linear volumes. See also: 107UltraSetLinearVolume ;------------------------------------------ !TOPIC 89 UltraSizeDRAM ;------------------------------------------ FUNCTION 3UltraDrv.UltraSizeDRAM: INTEGER;  This routine will always return the same value, which is the amount of DRAM that has been installed on the card. Use 57UltraMemAvail to see how much DRAM is still free. The function returns number of kilobytes found on the UltraSound.  See also: 0UltraMemInit ;------------------------------------------ !TOPIC 90 UltraStartTimer ;------------------------------------------ PROCEDURE 3UltraDrv.UltraStartTimer(Timer: INTEGER; Time: BYTE);  This routine can be used to start up one of two available hardware timers. Timer #1 is an 80 microsecond (.00008s) timer. Timer #2 is a 320 microsecond (.00032s) timer. When starting either timer, you supply the number of counts before the timer 'ticks'. When the timer 'ticks', it ALWAYS calls the callback routine defined for it. If you don't supply one, a default is used. These timers can be used to trigger various real time events. They are used extensively in music compostition programs. Please remember that the callback routine is called directly from the interrupt handler, so you must be careful what you do in the callback routine. Note that the specified timer is automatically restarted after it ticks. Your application must explicitly call 92UltraStopTimer to shut it off. Example: Giving Timer 1 a duration of 10 counts would make the timer tick every 800 microseconds (.0008s). This would mean your callback routine is called 1250 times a second.  See also: 0 0 0 92UltraStopTimer 49UltraTimer1Handler 50UltraTimer2Handler 95UltraTimerStopped ;------------------------------------------ !TOPIC 91 UltraStartVoice ;------------------------------------------ PROCEDURE 3UltraDrv.UltraStartVoice(Voice: INTEGER; VBegin: LONGINT; VStart: LONGINT; VEnd: LONGINT; VMode: BYTE);  This routine will set up and start up a voice. The voice will begin playback at the 'begin' and continue to 'end'. If looping is enabled for this voice, then it will then jump to 'start' and then continue to 'end'. The method of looping is determined by 'mode'. See also: 0 0UltraLoopMode 0UltraSetEnd 18Voice_Control_Bits ;------------------------------------------ !TOPIC 92 UltraStopTimer ;------------------------------------------ PROCEDURE 3UltraDrv.UltraStopTimer(Timer: INTEGER);  If you have started a timer with 90UltraStartTimer, you will probably want to shut it off before shutting down your application. If you forget, 32UltraClose automatically shuts it down. See also: 90UltraStartTimer ;------------------------------------------ !TOPIC 93 UltraStopVoice ;------------------------------------------ PROCEDURE 3UltraDrv.UltraStopVoice(Voice: INTEGER);  This routine will stop a voice which is playing at it's current position. Don't forget that if a voice is left at an unknown position, the data that is at that position will still be summed into the final output. See also: 0 87UltraSetVoiceEnd 91UltraStartVoice ;------------------------------------------ !TOPIC 94 UltraStopVolume ;------------------------------------------ PROCEDURE 3UltraDrv.UltraStopVolume(Voice: INTEGER);  You can use this routine if you wish to stop an volume ramp after a specified period of time, or you wish to make sure that a volume ramp has stopped. See also: 0 109UltraRampLinearVolume 75UltraRampVolume ;------------------------------------------ !TOPIC 95 UltraTimerStopped ;------------------------------------------ FUNCTION 3UltraDrv.UltraTimerStopped(Timer: INTEGER): BOOLEAN;  This routine can be used to see if a timer is currently being used. The function returns FALSE if still running, TRUE if stopped.  See also: 0 90UltraStartTimer 92UltraStopTimer ;------------------------------------------ !TOPIC 96 UltraTrimJoystick ;------------------------------------------ PROCEDURE 3UltraDrv.UltraTrimJoystick(JoyVal: BYTE);  This routine is used to set the speed compensation value on the joystick port on the UltraSound. The faster the computer, the smaller this value should be. This allows all software that reads the joystick to return consistent joystick positions regardless of the speed of the machine. This is normally not needed and probably should never be used in your application. The utility ULTRAJOY.EXE which is included with all UltraSound stock software is used to set this value up in your AUTOEXEX.BAT file. ;------------------------------------------ !TOPIC 97 UltraUpLoad ;------------------------------------------ FUNCTION 3UltraDrv.UltraUpLoad(DataPtr: POINTER; Control: BYTE; DRAM_Loc: LONGINT; Len: WORD; Wait: BOOLEAN): BOOLEAN;  This routine will retrieve a chunk of data from the UltraSound's DRAM. It will transfer 'len' number of bytes to DataPtr (in PC) from DRAM_loc (in UltraSound). If 'Wait' is TRUE, then it will wait until the transfer is complete. If 'Wait' is FALSE, it will return as soon as transfer is started. The function returns TRUE if transfer was successful. If FALSE, check 30UltraErrorStr for the reason.  See also: 0 23DMA_Control_Bits 33UltraDownload 0UltraDRAMDMAWait ;------------------------------------------ !TOPIC 98 UltraVectorVolume ;------------------------------------------ PROCEDURE 3UltraDrv.UltraVectorVolume(Voice: INTEGER; VEnd: WORD; VRate: BYTE; VMode: BYTE);  This routine can be used to ramp from an unknown volume value to a new value. It is useful if you are doing volume envelopes and need to restart the attack/decay sequence at any time. See also: 0 75UltraRampVolume 94UltraStopVolume ;------------------------------------------ !TOPIC 99 UltraVersion ;------------------------------------------ PROCEDURE 3UltraDrv.UltraVersion(VAR Major: BYTE; VAR Minor: BYTE);  This routine can be useful to track the version of the SDK that was used in compiling your source code. The function returns Major (1 digit) and minor (2 digits) version of the unit.  See also: 100UltraVersionStr ;------------------------------------------ !TOPIC 100 UltraVersionStr ;------------------------------------------ FUNCTION 3UltraDrv.UltraVersionStr: STRING;  This routine can be useful to track the version of the SDK that was used in compiling your source code. The function returns Major and minor version of the unit, in string format.  See also: 99UltraVersion ;------------------------------------------ !TOPIC 101 UltraVoiceStopped ;------------------------------------------ FUNCTION 3UltraDrv.UltraVoiceStopped(Voice: INTEGER): BOOLEAN;  This routine can be used to see if a sample has finished playing . The function returns TRUE if the voice is stopped, FALSE otherwise.  ;------------------------------------------ !TOPIC 102 UltraVolumeStopped ;------------------------------------------ FUNCTION 3UltraDrv.UltraVolumeStopped(Voice: INTEGER): BOOLEAN;  This routine is used to determine the current state of the volume of the voice. It can be used to see if a volume ramp is still running. The function returns TRUE if no volume ramp is running, FALSE otherwise.  See also: 0 109UltraRampLinearVolume 75UltraRampVolume ;------------------------------------------ !TOPIC 103 UltraWaitDRAMDMA ;------------------------------------------ PROCEDURE 3UltraDrv.UltraWaitDRAMDMA;  If a DMA transfer to/from DRAM is started but told not to wait for it to complete, this routine can be used to wait until it has completed. See also: 0 33UltraDownload 97UltraUpload ;------------------------------------------ !TOPIC 104 UltraWaitRecordDMA ;------------------------------------------ PROCEDURE 3UltraDrv.UltraWaitRecordDMA;  This can be used to let an application wait until a complete sample is finished being acquired. See also: 79UltraRecordData ;------------------------------------------ !TOPIC 105 UltraVoiceOff ;------------------------------------------ PROCEDURE 3UltraDrv.UltraVoiceOff(Voice: INTEGER; VEnd: BOOLEAN);  This routine will either stop a voice immediately or let it finish its current loop. If 'VEnd' is FALSE then it will stop abruptly, otherwise it will finish the current loop. 77UltraReadVoice could be called afterwards if you need to know where the loop finished. If used with 87UltraSetVoiceEnd, you could implement a sampled decay on the end of your sample. This would occur if your loop point was not at the end of your data, and you changed the end point to the real end point of your data and then called this routine with VEnd set to TRUE. See also: 0 77UltraReadVoice 87UltraSetVoiceEnd ;------------------------------------------ !TOPIC 106 UltraVoiceOn ;------------------------------------------ PROCEDURE 3UltraDrv.UltraVoiceOn(Voice: INTEGER; VBegin: LONGINT; Start_Loop: LONGINT; End_Loop: LONGINT; Control: BYTE; Freq: LONGINT);  This routine just sets the frequency with 83UltraSetFrequency and then calls 91UltraStartVoice. See also: 0 83UltraSetFrequency 91UltraStartVoice ;------------------------------------------ !TOPIC 107 UltraSetLinearVolume ;------------------------------------------ PROCEDURE 3UltraDrv.UltraSetLinearVolume(Voice: INTEGER; Index: INTEGER);  This routine indexes into a table to translate a linear volume (0-511) to a logarithmic one (0-4095), and then calls 88UltraSetVolume. See also: 88UltraSetVolume ;------------------------------------------ !TOPIC 108 UltraReadLinearVolume ;------------------------------------------ FUNCTION 3UltraDrv.UltraReadLinearVolume(Voice: INTEGER): INTEGER;  This routine indexes into a table to translate a 0-4095 logarithmic volume to a 0-511 linear volume. The function returns Linear Volume Value (0-511).  See also: 0 107UltraSetLinearVolume 88UltraSetVolume ;------------------------------------------ !TOPIC 109 UltraRampLinearVolume ;------------------------------------------ PROCEDURE 3UltraDrv.UltraRampLinearVolume(Voice: INTEGER; Start_Idx: WORD; End_Idx: WORD; Msecs: LONGINT; VMode: BYTE);  This routine is used to ramp between linear volume settings. It uses the same method as 107UltraSetLinearVolume to determine the actual volume settings to use, and then calls 75UltraRampVolume. See also: 0 75UltraRampVolume 107UltraSetLinearVolume ;------------------------------------------ !TOPIC 110 UltraVectorLinearVolume ;------------------------------------------ PROCEDURE 3UltraDrv.UltraVectorLinearVolume(Voice: INTEGER; End_Idx: WORD; VRate: BYTE; VMode: BYTE);  This routine can be used to ramp from an unknown volume to a new linear volume. It is useful if you are doing volume envelopes and need to restart the attack/decay sequence at any time. It can also produce a smoother ramp from one volume to another, since arbitrarily setting a volume that is far away from the current volume can cause 'pops'. See also: 0 108UltraReadLinearVolume 107UltraSetLinearVolume ;------------------------------------------ !TOPIC 111 UltraClearVoices ;------------------------------------------ PROCEDURE 3UltraDrv.UltraClearVoices;  This routine will deallocate all previously allocated voices. It would be advisable to call this before using either 112UltraAllocVoice or 113UltraFreeVoice. See also: 0 112UltraAllocVoice 113UltraFreeVoice ;------------------------------------------ !TOPIC 112 UltraAllocVoice ;------------------------------------------ FUNCTION 3UltraDrv.UltraAllocVoice(VAR Voice_Num: INTEGER): BOOLEAN;  This routine will return a voice for your application to use. If you supply a voice number, it will attempt to allocate that particular voice. If you pass a -1 for the voice number, it will return the next free voice. This routine will only allocate voices up to the number of active voices specified in the 68UltraOpen function. The function returns TRUE if there was no problem allocating the voice. If FALSE, check 30UltraErrorStr for the reason.  See also: 0 111UltraClearVoices 0UltraFreeVoices ;------------------------------------------ !TOPIC 113 UltraFreeVoice ;------------------------------------------ PROCEDURE 3UltraDrv.UltraFreeVoice(Voice_Num: INTEGER);  This routine will free up a previously allocated voice. This should be used when your application no longer needs the voice so it can be re-allocated at another time. See also: 0 112UltraAllocVoice 111UltraClearVoices ;------------------------------------------ !TOPIC 114 Focal_Point_3d ;------------------------------------------  Focal point 3-d sound Three dimensional audio on the UltraSound is achieved by a technique called binaural representation. Basically, this means that a mono sound is 'shaped' in such a way that when it is presented to the right and left ears properly, the sound seems to come from the proper place in space. This technique is also called convolution. This is done thru algorithms developed by Focal Point(tm) 3D Audio. Focal Point has provided a utility (called FP3D.EXE) to convert a mono sound file to a 3D file capable of being played on an UltraSound. The basic concept is that the mono sound is processed in such a way that the file that is output contains up to 6 tracks of sound. When the sound is played back, the volumes and balances are adjusted to make the sound appear to originate from anywhere in the 3D space. It is possible to create files that only have 4 tracks and can therefore only be positioned in 2 dimensions. This may be adequate for many applications and it will make the resultant file smaller. There are 2 types of 3D sound that an application might want to use. The first is a sound effect. This is a sound that can be completely loaded into DRAM and played and positioned at any time. It is used for things like gunshots, cars etc. These can be looped or non-looped. The other type of sound is a sound track. This is for a very long sound that cannot be loaded in DRAM all at once. The implementation of each of these methods is very different. A sound effect is implemented using a blocked data format. This means that each track's data is in a block of its own. A sound track uses interleaved data. This means that all the track's data is interleaved together. See also: 115ThreeD_data_format ;------------------------------------------ !TOPIC 115 ThreeD_data_format ;------------------------------------------  3-D file data formats: A blocked file would look like this: HEADER FFFFFRRRRRBBBBBLLLLLUUUUUDDDDD.... whereas an interleaved file would look like this: HEADER FRBLUDFRBLUDFRBLUDFRBLUDFRBLUD... where F = Front Track R = Right Track B = Behind Track L = Left Track U = Up Track D = Down Track Both of these methods have their individual advantages and disadvantages. First, the interleaved method makes it very easy to read in the data in a continuous stream since it will look the same all the way through the file. It is also faster to read 60K of data once rather than 6 10K reads. This makes it very useful for a sound track. However, one drawback is that it has a very limited number of frequencies that it will run at. The reason for this is rather difficult to explain, but it pertains to getting the UltraSound's voices to play every 4th (or 5th, etc) sample. The UltraSound normally would interpolate between data points but it can't do that here because the adjacent data points are not in the same track. If you want to run at 22050 Hz, then you need to have only 28 active voices to accomplish this. If you want to play a track at 44100 Hz, you must have only 14 active voices. Blocked data doesn't have this problem. Since the data is NOT interleaved, but in a block of contiguous DRAM, its frequency can be adjusted to any value. This is usually very useful for sound effects (rev'ing engines etc). Also, since the data is blocked, each track's data can be allocated separately and can therefore be up to 256K. An interleaved file must fit into 1 256K bank since we cannot play 16bit data across a 256K bank. See the two example 3D programs provided (PLAY3D and PLAY3DI) for ideas on how to implement 3D sound into you applications. ;------------------------------------------ !TOPIC 116 UltraAbsPosition3D ;------------------------------------------ PROCEDURE 3UltraDrv.UltraAbsPosition3D(VAR Sound: 10SOUND_3D; XPos: INTEGER; YPos: INTEGER; ZPos: INTEGER);  This routine will position a sound using standard cartesian coordinates. The X position range is from -511 (left) to +511 (right). The Y position is from -511 (below) to +511 (above). The Z position is from -511 (behind) to +511 (ahead). The X and Z positions determine the azimuth position and Y determines the elevation. The distance away from the listener is determined using trigonometry. Once these are determined, 117UltraAngPosition3d is called. If the distance is calculated to be greater than 511, it is clipped to 511. Also, if the distance is calculated to be 0, no positioning is done since the origin is undefined. (i.e. A sound cannot be generated INSIDE your head (origin)). See also: 114Focal_Point_3d 117UltraAngPosition3d ;------------------------------------------ !TOPIC 117 UltraAngPosition3D ;------------------------------------------ PROCEDURE 3UltraDrv.UltraAngPosition3D(VAR Sound: 10SOUND_3D; AZIMuth: INTEGER; Elevation: INTEGER; Vol_Dist: INTEGER);  This routine will position a 3D sound using polar coordinates. The azimuth and elevation are specified in degrees. Azimuth is the angle in the horizontal plane. Straight ahead is 0 degrees, 90 degrees is to the right, -90 degrees is to the left and 180 (or -180) is directly behind you. If an angle larger than 180 or smaller that - 180 is specified, it is converted to its -180 to 180 equivalent. For example, 270 degrees is equivalent to -90 degrees. Elevation is the angle of elevation above or below the horizontal plane. 0 degrees is no elevation, 90 degrees is straight up, and -90 is straight down. Any angle larger than 90 or smaller that -90 is ignored. If more precision is needed, use 118UltraAngFltPosition3D so that floating point arithmetic is used. Since that routine uses floating point functions (slow), your application may not want to use it. See also: 114Focal_Point_3d 116UltraAbsPosition3d ;------------------------------------------ !TOPIC 118 UltraAngFltPosition3D ;------------------------------------------ PROCEDURE 3UltraDrv.UltraAngFltPosition3D(VAR Sound: 10SOUND_3D; AZIMuth: DOUBLE; Elevation: DOUBLE; Vol_Dist: INTEGER);  This routine will position a 3D sound using polar coordinates. The azimuth and elevation are specified as floating point numbers in degrees. For example, 45 and one half degrees would be specified as 45.5. Azimuth is the angle in the horizontal plane. Straight ahead is 0 degrees, 90 degrees is to the right, -90 degrees is to the left and 180 (or -180) is directly behind you. If an angle larger than 180 or smaller that -180 is specified, it is converted to its -180 to 180 equivalent. For example, 270 degrees is equivalent to -90 degrees. Elevation is the angle above or below the horizontal plane. 0 degrees is no elevation, 90 degrees is straight up, and -90 is straight down. Any angle larger than 90 or smaller that -90 is ignored. If your application does not need to use the floating point routine, it is advisable to use UltraAngPosition because it avoids using some floating-point functions (which are slow). See also: 114Focal_Point_3d ;------------------------------------------ !TOPIC 119 UltraCloseDup3D ;------------------------------------------ PROCEDURE 3UltraDrv.UltraCloseDup3D(VAR Sound: 10SOUND_3D);  This routine must be used to free up the resources associated with a duplicated 3d effect. This routine will only release the voices used by the duplicated effect, not the DRAM allocated by the original effect. The original effect should be closed with 127UltraUnLoad3dEffect. See also: 0 114Focal_Point_3d 120UltraDup3d 127UltraUnLoad3DEffect ;------------------------------------------ !TOPIC 120 UltraDup3D ;------------------------------------------ FUNCTION 3UltraDrv.UltraDup3D(VAR Current: 10SOUND_3D; VAR Sound: 10SOUND_3D): BOOLEAN;  This routine is very useful if you want to use the same sound effect in multiple places at once. This allows you to use the same DRAM data and just allocate some more voices to move the sound. This helps to save DRAM space. Make sure that you use 119UltraCloseDup3d to free the voices, NOT 127UltraUnLoad3dEffect - that will release all the DRAM for the sound. This new effect can be passed to any other routines the same way the original effect is. The function returns TRUE if duplication successful. If FALSE, check 30UltraErrorStr for the reason.  See also: 114Focal_Point_3d 119UltraCloseDup3d ;------------------------------------------ !TOPIC 121 UltraLoad3DEffect ;------------------------------------------ FUNCTION 3UltraDrv.UltraLoad3DEffect(VAR Sound: 10SOUND_3D; VAR FileName: STRING; PC_Buffer: POINTER; Size: WORD): BOOLEAN;  This routine is used to load a 3D sound into the DRAM on the UltraSound. It will allocate all necessary resources so that 125UltraStart3D can be called later. As many buffers of DRAM as needed will be allocated along with the proper number of voices. These resources will be freed up when you call 127UltraUnLoad3dEffect. The file specified MUST be a properly formatted or the routine will fail. This means that it must have the proper header and 3D data in it. The 'pc_buffer' is a buffer supplied by your application for this routine's use to download data into the UltraSound. The 'size' parameter is the size of the 'pc_buffer'. The larger this buffer is, the faster it will download. The function returns TRUE if the file could be loaded. If FALSE check 30UltraErrorStr for the reason.  See also: 0 0 114Focal_Point_3d 33UltraDownload 58UltraMemAlloc 0UltraVoiceAlloc ;------------------------------------------ !TOPIC 122 UltraSetFreq3D ;------------------------------------------ FUNCTION 3UltraDrv.UltraSetFreq3D(VAR Sound: 10SOUND_3D; Frequency: LONGINT): BOOLEAN;  This routine will allow you to alter the frequency that the 3D sound is using. This allows you to do pitch shifting to get a doppler shift type effect. This routine can only be done on blocked data. The function returns TRUE if the frequency was changed ok. If FALSE, check 30UltraErrorStr for the reason.  See also: 114Focal_Point_3d ;------------------------------------------ !TOPIC 123 UltraRelease3DInterleave ;------------------------------------------ PROCEDURE 3UltraDrv.UltraRelease3DInterleave(VAR Sound: 10SOUND_3D);  This routines will release the DRAM and voices allocated for an interleaved sound track. See also: 114Focal_Point_3d 124UltraSetup3dInterleave ;------------------------------------------ !TOPIC 124 UltraSetup3DInterleave ;------------------------------------------ FUNCTION 3UltraDrv.UltraSetup3DInterleave(VAR Sound: 10SOUND_3D; VAR FileName: STRING; Size: LONGINT): BOOLEAN;  This routine will allocate the voices and memory necessary to play back an interleaved 3D sound. It will NOT load any of the file data into DRAM. Your application is responsible for that. It will open the file, read the header, allocate the appropriate resources, and set up the begin, start and end loop points for each voice. Since the sound is interleaved, the loop points are staggared appropriately. The function returns TRUE if the file could be read successfully. If FALSE, check 30UltraErrorStr for the reason.  See also: 114Focal_Point_3d 121UltraLoad3dEffect ;------------------------------------------ !TOPIC 125 UltraStart3D ;------------------------------------------ PROCEDURE 3UltraDrv.UltraStart3D(VAR Sound: 10SOUND_3D);  This routine will start a 3D sound. If you want it to begin at a specific point in space, be sure that you position it first. It is not necessary to stop the sound before starting it again. See also: 114Focal_Point_3d 125UltraStart3d ;------------------------------------------ !TOPIC 126 UltraStop3D ;------------------------------------------ PROCEDURE 3UltraDrv.UltraStop3D(VAR Sound: 10SOUND_3D; Abruptly: BOOLEAN);  This routine will stop a 3D sound. There are two ways to stop a sound: if the 'abruptly' flag is TRUE, then the sound will shut off immediately; if it is FALSE, then the sound will be ramped down very quickly. The second method will give a smoother transition. See also: 114Focal_Point_3d ;------------------------------------------ !TOPIC 127 UltraUnLoad3DEffect ;------------------------------------------ PROCEDURE 3UltraDrv.UltraUnLoad3DEffect(VAR Sound: 10SOUND_3D);  This routine is used to free up all the resources (voices & DRAM) that a 3D sound uses. Since a 3D sound can use a lot of the voices & DRAM, you should free up the resources you can. See also: 114Focal_Point_3d 121UltraLoad3dEffect