{--Title: MVFUNCT.PAS Author: Patrick O'Malley AKA Silicom Slim Constact: e-mail: d005530c@dcfreenet.seflin.lib.fl.us Language: Turbo Pascal v6.0 Description: Functions and procedures to interface with the ProAudio Spectrum's mixer and volume controls. Status: Public Domain This unit is a primer for programming the ProAudio Spectum basic or 16, it doesn't seem to matter. IMPORTANT TECH NOTE: All settings are in percent! Just a decimal from 0 to 100. Very odd. And sometimes when you set a volume too low, it will just go to 0. Basically what you enter will result in a volume +-2 percentage points off what you entered. Doesn't make much difference. I have no idea what CrossChannels are. Or the FMSplitChips thing. They don't seem too interesting anyhow. For the unknowing, mixers and volumes are basically the same thing. Setting the output of a mixer changes it's volume if you play something that uses that mixer. For example, a cd-rom drive is attached to the internal mixer input. The volume functions aren't really just for volumes anyhow. They control the treble, bass, loudness & enhanced switches too. Most of the procedures and functions are simple to understand. The GetFunctionTable procedure is used internally by the unit. I'd like to request code re:SoundBlaster mixer/vol stuff. --} Unit MVFunct; interface CONST {--volume channel select constants--} {--These constants are used _only_ with the functions/procedures that use a call to functiontable.mvset(or get)volumefunction. VolMute is strange. It appears in the COMMON.INC file of the PAS-SDK but is never explained and doesn't seem to have an effect. VolLoudEnh is also odd. It is supposed to be used to set the Loudness and Enhanced switches (and it does). The only problem is that using a value of 100% turns _both_ on. Doing a 0% turns off only enhanced then. Maybe there is some trick I haven't discovered. VolBass & VolTreble set the Bass and Treble. VolLeft and VolRight are the master volume settings. VolMode is some sort of modal setting. No documentation in the PAS-SDK.--} VolMute = $40; VolLoudEnh = $41; VolBass = $42; VolTreble = $43; VolLeft = $44; VolRight = $45; VolMode = $46; {--mixer selection constants--} {--These constants are used when a mixer can either be an input of output mixer. For example, the internal connector (hooked to the cd-rom drive) can either output sound or input it. So you can select the levels at which it does these. For outputting sound levels use pmOUTPUTMIXER. --} pmOUTPUTMIXER = $00; pmINPUTMIXER = $20; {--left channel selection values--} {--these constants are used to select which mixer (they are: internal which is usually the CD-ROM, external which _can_ be attached to external music equiptment, microphone, PCM or digital sound, the internal speaker which is re-routed by the pro-audio out it's speakers and the sound-blaster emulation mixer. I have no idea what R_ or L_IMIXER is.--} L_FM = $01; L_IMIXER = $02; L_EXT = $03; L_INT = $04; L_MIC = $05; L_PCM = $06; L_SPEAKER = $07; L_FREE = $00; L_SBDAC = $00; {--right channel selection values--} {--these constants can be used in places that ask for the channel to, for example, change the setting of. they are for the right channel only. --} R_FM = $08; R_IMIXER = $09; R_EXT = $0A; R_INT = $0B; R_MIC = $0C; R_PCM = $0D; R_SPEAKER = $0E; R_FREE = $0F; R_SBDAC = $0F; {--The following is used for the get/set, on/off procedures--} Get = True; Set_ = False; On = true; Off = false; Type tFunctionTable = record MVSetMixerFunction, MVSetVolumeFunction, MVSetFilterFunction, MVSetCrossChannel, MVGetMixerFunction, MVGetVolumeFunction, MVGetFilterFunction, MVGetCrossChannel, MVRealSoundSwitch, MVFMSplitSwitch : Pointer; end; Var FunctionTable : tFunctionTable; Function IsMVSOUNDInstalled : Boolean; Procedure GetFunctionTable; {internal, used by MVFUNCT.TPU} Procedure SetMasterVolume(R,L : Boolean;R_Setting,L_Setting : Word); Procedure SetMixer(In_Out, Channel_Select : Byte; Mixer_Setting : Word); Procedure GetMasterVolume(R,L : Boolean; Var R_Setting, L_Setting : Word); Function GetMixer(In_Out, Channel_Select : Word) : Byte; Procedure SetFilter(Filter_Setting : Byte); Function GetFilter : Byte; Procedure Get_Set_RealSound(Get_Set : Boolean;Var On_Off : boolean); Procedure SetVolume(Channel,Setting : Word); Function GetVolume(Channel : Word) : Byte; Function GetIRQ : Byte; Function GetDMA : Byte; implementation Function IsMVSOUNDInstalled : Boolean; {Basically this function checks for MVSOUND.SYS, the device driver that is required to do the mixer functions that follow. Simple. } Var edx : Word; Begin IsMVSOUNDInstalled := FALSE; asm mov ax, 0bc00h mov bx, 03f3fh xor cx, cx xor dx, dx int 2fh xor cx, bx xor dx, cx mov [edx], dx end; if edx = $4d56 then IsMVSOUNDInstalled := True else IsMVSOUNDInstalled := False; End; {IsMVSOUNDInstalled func} Procedure GetFunctionTable; {used by the unit} Var FTableSeg, FTableOfs : Word; Begin Asm mov ax, 0bc03h int 2fh mov [ftableofs], bx {function table offset} mov [ftableseg], dx {function table segment} end; {--Move the table into the function table of pointers for pascal--} Move(Mem[ftableseg:ftableofs],Mem[seg(functiontable):ofs(functiontable)],40); End; {GetFunctionTable proc} Procedure SetMasterVolume(R,L : Boolean;R_Setting,L_Setting : Word); {This procedure is actually the SetVolume procedure but is master volume channel specific. Vars R&L : Boolean tell it which channel (right or left) to change. R_&L_Setting are the % (0-100) to set the channel to. } Begin If R then begin asm mov bx, R_Setting mov cx, VolRight {$F+} call functiontable.mvsetvolumefunction {$F-} end; end; if L then begin asm mov bx, L_Setting mov cx, VolLeft {$F+} call functiontable.mvsetvolumefunction {$F-} end; end; End; {setmastervolume func} Procedure SetMixer(In_Out, Channel_Select : Byte; Mixer_Setting : Word); { This procedure is used to set the I/O volume of one of the mixers. In_Out is a constant listed above under mixer selection constants. Channel_Select is either the right or left constant from the list above under channel selection values. Mixer_Setting is the % (0-100) to set the volume to. } Begin Asm mov bx, Mixer_Setting xor cx, cx xor dx, dx mov cl, In_Out mov dl, Channel_Select {$F+} call functiontable.MVSetMixerFunction {$F-} End; End; {setmixer proc} Procedure GetMasterVolume(R,L : Boolean; Var R_Setting, L_Setting : Word); { See SetMaster volume for the variable descriptions. Basically returns the current master volume. } Var Temp : Word; Begin If R then Begin Asm mov cx, VolRight {$F+} call functiontable.mvgetvolumefunction {$F-} mov [Temp], bx end; R_Setting := Temp; end; If L then Begin asm mov cx, VolLeft {$F+} call functiontable.mvgetvolumefunction {$F-} mov [Temp], bx end; L_Setting := Temp; end; End; {getmastervolume proc} Function GetMixer(In_Out, Channel_Select : Word) : Byte; { See SetMixer for variable descriptions. Basically just returns the volume of the selected mixer. } Var Temp : Byte; Begin asm mov cx, In_Out mov dx, Channel_Select {$F+} call functiontable.mvgetmixerfunction {$F-} mov [temp], bl end; GetMixer := Temp; end; {getmixersetting proc} Procedure SetFilter(Filter_Setting : Byte); { I'm a little unsure about this function call. Here is what the SDK says: 0% filters out amything higher than 0khz (mute) 100% filters out anything lower than 20khz It does mute it, but I can't attach a spectrum analyzer to the speaker to test the frequency. Filter_Setting is the % to filter? } Begin Asm xor bx, bx mov bl, Filter_Setting {$F+} call functiontable.mvsetfilterfunction {$F-} end; End; {setfilter proc} Function GetFilter : Byte; { See SetFilter } Var Temp : Byte; Begin asm {$F+} call functiontable.mvgetfilterfunction {$F-} mov [Temp], bl end; GetFilter := Temp; End; {getfilter proc} Procedure Get_Set_RealSound(Get_Set : Boolean;Var On_Off : boolean); { If Get_Set is true then it is gotten, otherwise it is set. If On_Off is true then it is turned on, otherwise turned off. I added some constants: Get, Set_, On, Off for this procedure. If someone wants to make this procedure better, you have my blessing. Yuk. } Var ebx, ecx, return : word; Begin if Get_Set then ecx := 0 else ecx := 1; if on_off then ebx := 100 else ebx := 0; asm mov bx, ebx mov cx, ecx {$F+} call functiontable.mvrealsoundswitch {$F-} mov [return], bx end; If Get_Set then If return = 100 then On_Off := True else On_Off := False; end; {get_set_realsound} Function GetIRQ : Byte; { Returns the IRQ of the PAS } Var Res : Byte; Begin asm mov ax, 0bc04h int 2fh mov [res], cl end; GETIRQ := res; end; {getirq proc} Function GetDMA : byte; { Returns the DMA of the PAS } Var res: byte; Begin asm mov ax, 0bc04h int 2fh mov [res], bl end; GetDMA := Res; End; {getdma proc} Procedure SetVolume(Channel,Setting : Word); { This procedure will change the setting of a specific channel specified by the constants listed under volume channel selection constants. Channel is the constant specifying the channel to change Setting is the % volume (0-100) } Begin asm mov bx, Setting mov cx, Channel {$F+} call functiontable.mvsetvolumefunction {$F-} end; End; {setvolume proc} Function GetVolume(Channel : Word) : Byte; { See setvolume } Var Res:Byte; Begin asm mov cx, channel {$F+} call functiontable.mvgetvolumefunction {$F-} mov [res], bl end; GetVolume := Res; End; {getvolume func} begin if isMVSOUNDInstalled then getfunctiontable else begin Writeln('MVSOUND.SYS is not installed.'); Halt(1); End; end.