 #################################
# The Effects Module
#
# Part of the SharpeSound Editor
# by Paul D. Sharpe
# A 3rd Year Project at the University of Leeds;
# Department of Electronic and Electrical Engineering.
# Date: 27/2/95
#
# Revision:2
# Date: 10/4/95

# Global constants.
set FX(list) [list volume reverse tempo filter vibrato echo]

# Global initialisations.
set FX(VIBDepth) 50
set FX(VIBSpeed) 15
set FX(FLTCentre) 8000
set FX(FLTtype) low
set FX(ECHDelay) 50
set FX(ECHVolume) 50
set FX(volumeVal) 0
set FX(tempoVal) 0

##########################
# EffectBar 
# This procedure generates the effect bar section of Sound Studio.
# There are 3 options.
# 1. init 	: this sets up   but doesn't display them.
# 2. show 	: this packs.
# 3. noshow 	: this unpacks.
proc EffectBar { option } {
   global ConfigSet FX PACK

   # Configuration constants.
   set BordWdth 2
   set ButtWidth 11

   # Initialisation option.
   if {$option == "init" } {

      # Create the widgets if they don't exist.
      if {![winfo exists .effect]} {
	# Create the general frame.
	frame .effect

	# Create the title label.
	label .effect.title
	pack .effect.title -fill x

	# Create the frame to contain the top row of buttons.
	frame .effect.top
	# Create the top row of effect checkbuttons.
	set effects {Filter Reverse Echo Vibrato}
	foreach Effect $effects {
		set effect [string tolower $Effect]
		checkbutton .effect.top.$effect 
		pack .effect.top.$effect -side left \
					-padx 1

		#Bind button 3 to pop up the window to set the settings
		bind .effect.top.$effect <Button-3> "s$Effect"
	}

	# Create the frame to contain the bottom row of buttons.
	frame .effect.bottom

	# Create the bottom row of effect checkbuttons.
	set effects { Tempo Volume }
	foreach Effect $effects {
		set effect [string tolower $Effect]
		checkbutton .effect.bottom.$effect 
		#Bind button 3 to pop up the window to set the settings
		bind .effect.bottom.$effect <Button-3> "sVolTemp $Effect"

		pack 	.effect.bottom.$effect\
			 -side left -padx 1
	}

	# Create the Preview Mode button.
	checkbutton .effect.bottom.preview -variable FX(Preview) -anchor w\
			-relief groove -text "Preview"
	pack .effect.bottom.preview -side left -padx 1
	
	# Create the Apply Now button
	button .effect.bottom.apply -text "Apply Now!" \
				-command "FXApply" -anchor c\
				-relief groove
	pack .effect.bottom.apply -side left -padx 3

	# Pack the top and bottom rows of effects.
	pack .effect.top .effect.bottom -fill x -expand 1
      }
      # Configure the widgets.

      # Configure the frame to contain the PlayPanel
      .effect config 	-background $ConfigSet(cBG1)\
			-borderwidth $ConfigSet(BDW)\
			-relief $ConfigSet(REL)

      # The title label
      .effect.title config\
			-text Effects \
			-background $ConfigSet(cBG1) \
			-foreground $ConfigSet(cFG1) \
			-anchor w\
			-font $ConfigSet(FNT_S)

      # Configure top frame of effect checkbuttons.
      .effect.top config -background $ConfigSet(cBG1) -borderwidth $BordWdth
	
      # Configure the top row of effect checkbuttons.
      set effects {Filter Reverse Echo Vibrato}
      foreach Effect $effects {
		set effect [string tolower $Effect]
		.effect.top.$effect config \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
			-text $Effect\
			-width $ButtWidth \
			-selectcolor $ConfigSet(cAFG)\
			-anchor w\
			-variable FX($effect)\
			-relief groove
      }
      # Configure top frame of effect checkbuttons.
      .effect.bottom config -background $ConfigSet(cBG1) -borderwidth $BordWdth

      # Configure the bottom row of effect checkbuttons.
      set effects { Tempo Volume }
      foreach Effect $effects {
	set effect [string tolower $Effect]
	.effect.bottom.$effect config \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
 			-text $Effect\
			-width $ButtWidth \
			-selectcolor $ConfigSet(cAFG)\
			-anchor w\
			-variable FX($effect)\
			-relief groove
      }
      # Create the Preview Mode button.
      .effect.bottom.preview config \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
			-width $ButtWidth\
			-selectcolor $ConfigSet(cAFG)
      # Create the Apply Now button
      .effect.bottom.apply config \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
			-width [expr $ButtWidth +2]
   }\
   elseif {[winfo exists .effect]} {
	# Show option.
	if {$option == "show"} { 

	  # Pack in packing order (PACK global).
	  if {$PACK(EffectBar) != ""} {
		pack .effect -fill both -expand 1 -after $PACK(EffectBar)
	  } else {
		pack .effect -fill both -expand 1
	  }

	# Noshow option.
	}\
	elseif {$option == "noshow" } { 
		pack forget .effect
	} 
   } else {
	# Debug information
	puts stderr\
	 "Sound Studio : proc EffectBar; illegal option or not initialised"
   }
}


###################################################################
# CALLBACK PROCEDURES

###################################################################
# FxApply
# This procedure is the callback to the Effects-Apply Now! menu item
# and the Apply Now! button in the Effects Bar.
# It applies the selected effects to the working file or marked area,
# regardless of the Preview Mode status.
proc FXApply {} {
   global FX

   # Save the current Preview Mode status.
   set temp $FX(Preview)

   # Switch off Preview mode.
   set FX(Preview) 0

   # Apply the effects.
   AddFX

   # Restore the Preview Mode status.
   set FX(Preview) $temp
}


###################################################################
# AddFX
# This procedure modifies the working file or a marked area
# with the selected effects.
# If the preview mode is on the modified file is stored in the 
# temporary file (TMP5) otherwise it overwrites the working file.
# Returns: The name of the output file.
proc AddFX {} {
   global FX LOAD FLAG CARD FILE SAMPLE

   # Proceed only if there is a sample to be modified. 
   if {$FLAG(Loaded)} {

	# Set the name of the file to contain a the source samples.
	set input $FILE(TMP3)

	# Get the samples to be modified.
	if {$FLAG(Marked)} {
		Copy $FILE(TMP5)
	} elseif {$FX(Preview)} { 
		exec cp $FILE(TMP1) $FILE(TMP5)
	}

	# Set the name of the output file.	
	if {$FX(Preview) || $FLAG(Marked)} {
		set output $FILE(TMP5)
	} else {
		set output $FILE(TMP1)	
	}

	# Indicate that there will be a delay.
	WaitPlease

	# Generate the Sox pipe string according to selected effects.
	# Set a flag to check if any effects are selected.
	set effect 0
	set type ".ub"
	# Start the pipe string.
	set pipe "$FILE(Sox)  -t $type $input -t $type - copy"
	# Reverse effect.
	if { $FX(reverse) } { 
	    set pipe "$pipe | $FILE(Sox) -t .ub - -t $type - reverse"
	    set effect 1
	}
	# Echo Effect
	if { $FX(echo) } { 
	    set delay [expr\
		 ($SAMPLE(Size)/$LOAD(rate).0)*$FX(ECHDelay).0/100]
	    set vol [expr 0.5*$FX(ECHVolume).0/100]
	    set pipe "$pipe | $FILE(Sox) -t .ub - -t $type - echo $delay $vol "
	    set effect 1
	}

	# Vibrato effect.
	if { $FX(vibrato) } { 
	    set depth [expr $FX(VIBDepth).0/100]
	    set pipe\
		 "$pipe | $FILE(Sox) -t .ub - -t $type - vibro $FX(VIBSpeed) $depth"
	    set effect 1
	}

	# Filter effect.
	if { $FX(filter) } {
	   switch $FX(FLTtype) {
		low	{
	  	  set pipe "$pipe | $FILE(Sox) -t .ub - \
				-t $type - lowp $FX(FLTCentre)"
			}
		high    {
		  set pipe\
		    "$pipe | $FILE(Sox) -t .ub - \
				-t $type - highp $FX(FLTCentre)"
			}	
		band    {
		  set pipe "$pipe | $FILE(Sox) -t .ub - \
				-t $type - band $FX(FLTCentre) $FX(FLTWidth)"
			}
	   }
	   set effect 1
	}

	# Volume effect.
	if { $FX(volume) } { 
	   if  {$FX(volumeVal)>0} {
		# Increase volume.
		set volume [expr $FX(volumeVal).0/100+1]
	   } else {
		# Decrease volume
		set volume [expr ($FX(volumeVal).0/100)+1]
		# Zero as volume level is not allowed, therefore;
		if {$volume==0} {set volume 0.001}
	   }
	   set pipe "$pipe | $FILE(Sox) -t .ub - -t $type -v $volume - copy"
	   set effect 1
	}
	
	# Tempo Effect.
	if { $FX(tempo) } { 
	   set rate [expr $LOAD(rate)+($LOAD(rate)*$FX(tempoVal).0/-100)]
	   # Ensure that the requested rate is in acceptable range.
	   if {$rate<100} { set rate 100 }
	   if {$rate>50000} { set rate 50000 }
	   set pipe "$pipe | $FILE(Sox) -t .ub - -t $type -r $rate - rate"
	   set effect 1
	}

	# If at least one effect has been selected, perform conversion.
	if {$effect} {
	   # Copy the samples to be modified to the input file.
	   exec mv $output $input

 	   # Complete the pipe string.
	   set pipe "$pipe | $FILE(Sox) -t .ub - -t $type $output"

	   # Convert the samples, by running the pipe
	   eval exec $pipe

	   # Insert the modified marked area.
	   if {!$FX(Preview) && $FLAG(Marked)} {
		exec mv $output $input
		Paste $input
	   }

	   # Update the editing plot.
  	   FillPlot
	}

	# Update status flags.
	set FLAG(Edited) [expr ($FLAG(Edited) || ($effect && !$FX(Preview)))]

	# End delay indication.
	WaitPlease 0

	# Return the name of the output file.
	return $output
   }
   return ""
}


###################################################################
# sFilter
# This procedure is the callback to the Effects-Filter menu item and 
# a button-3 click on the filter checkbutton in the effect bar. 
# It creates a dialog box to set the parameters for the filter effect.
proc sFilter {} {
   global ConfigSet FX

   #------------------------------
   # LOCAL PROCEDURES START

   # setRanges	
   # Callback to the radio buttons in the dialog box.
   proc setRanges {} {
	global FX LOAD ConfigSet
	
	# Set the path names of the scale widgets.
	set Cpath .filter.main.bottom.centre
	set Wpath .filter.main.bottom.width 

	# Make sure that one button is set initially.
	if {[lsearch [array names FX] FLTtype]==-1 || $FX(FLTtype)=="" } {
		set FX(FLTtype) low
	}
 
	# Set the scale ranges and states according to the type of
	# filter selected.
	switch $FX(FLTtype) {
	  low	{ 
		  $Cpath.scale configure -to [expr $LOAD(rate)/2]
		  $Wpath.scale configure -state disabled
		  $Wpath.label configure -state disabled\
					 -foreground $ConfigSet(cDFG)
		  $Wpath.instr configure -foreground $ConfigSet(cDFG)

		}
	  high	{ 
		  $Cpath.scale configure -to [expr $LOAD(rate)/2]
		  $Wpath.scale configure -state disabled
		  $Wpath.label configure -state disabled\
					 -foreground $ConfigSet(cDFG)
		  $Wpath.instr configure -foreground $ConfigSet(cDFG)
		}
	  band  { 
		  $Cpath.scale configure -to [expr $LOAD(rate)/4]
		  $Wpath.scale configure -state normal\
					 -to [expr $LOAD(rate)]
		  $Wpath.label configure -state normal\
					 -foreground $ConfigSet(cFG1)
		  $Wpath.instr configure -foreground $ConfigSet(cFG1)
		}
	}
   }
   # LOCAL PROCDURES END
   #------------------------------
    
   # Create the dialog box.

   # Create the toplevel window.
   toplevel .filter -bg $ConfigSet(cBG1)
   wm title .filter "Filter Settings"
   # Set window as a pop-up child of the root window.
   wm transient .filter .
   # Stop entry from the main window. (grab).
   catch { grab .filter }

   # Create Widgets
   # Create the General Frame	   
   frame .filter.main	-bg $ConfigSet(cBG1)\
			-bd 2 -relief $ConfigSet(REL)

   # Create the top frame to contain the radio buttons to select filter type.
   frame .filter.main.top -bg $ConfigSet(cBG1)  

   # Create the Radio Buttons.
   set list { "Low Pass" "High Pass" "Band Pass" } 
   set ButtWidth 10
   foreach item $list {
	set path [string tolower [lindex $item 0]]
	radiobutton .filter.main.top.$path \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
 			-text $item\
			-width $ButtWidth \
			-selectcolor $ConfigSet(cAFG)\
			-anchor w\
			-variable FX(FLTtype)\
			-value $path\
			-relief groove\
			-command setRanges
	pack .filter.main.top.$path -side left -padx 3m -pady 3m\
				-fill x -expand 1
   }
   # Create the bottom frame to contain the sliders to adjust frequency range.
   frame .filter.main.bottom -bg $ConfigSet(cBG1)  

   # Create the special slider widget for the centre frequency.  
   frame .filter.main.bottom.centre -bg $ConfigSet(cBG1)
   label .filter.main.bottom.centre.instr \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "Centre Frequency (Hz)"\
			-font $ConfigSet(FNT_S) \
 			-anchor w

   entry .filter.main.bottom.centre.label \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-textvariable "FX(FLTCentre)"\
			-font $ConfigSet(FNT_S) \
			-width 5\
			-insertbackground $ConfigSet(cFG1)\
			-selectforeground $ConfigSet(cAFG)\
			-selectbackground $ConfigSet(cABG)\
			-cursor arrow
   # Bind the entry with special characteristics.
   bindScale .filter.main.bottom.centre .filter.main.done.butt
	 
   scale .filter.main.bottom.centre.scale\
			-showvalue 0\
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-activebackground $ConfigSet(cABG)\
			-from 0 -to 100\
			-width 10 -length 100\
			-orient horizontal\
			-command "set FX(FLTCentre)"

   pack .filter.main.bottom.centre.instr -fill x -expand 1\
					-anchor w
   pack .filter.main.bottom.centre.scale\
	.filter.main.bottom.centre.label \
	  -side left -fill x -expand 1 

   # Create the special slider widget for the bandwidth.
   frame .filter.main.bottom.width -bg $ConfigSet(cBG1)
   label .filter.main.bottom.width.instr \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "Bandwidth (Hz)"\
			-font $ConfigSet(FNT_S) \
 			-anchor w
   entry .filter.main.bottom.width.label \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-textvariable "FX(FLTWidth)"\
			-font $ConfigSet(FNT_S) \
			-width 5\
			-insertbackground $ConfigSet(cFG1)\
			-selectforeground $ConfigSet(cAFG)\
			-selectbackground $ConfigSet(cABG)\
			-cursor arrow
   # Bind the entry with special characteristics.
   bindScale  .filter.main.bottom.width .filter.main.done.butt
	 
   scale .filter.main.bottom.width.scale\
			-showvalue 0\
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-activebackground $ConfigSet(cABG)\
			-from 0 -to 100\
			-width 10 -length 100\
			-orient horizontal\
			-command "set FX(FLTWidth)"

   pack .filter.main.bottom.width.instr -fill x -expand 1\
					-anchor w
   pack .filter.main.bottom.width.scale\
	.filter.main.bottom.width.label \
	  -side left -fill x -expand 1

   pack .filter.main.bottom.centre\
	.filter.main.bottom.width\
	-expand 1 -padx 5m -pady 3m -side left

   # Set the scales to their initial ranges.
   setRanges

   # Make sure that the values is being displayed and the scale sliders
   # are in correct position.
   if {[info exist FX(FLTCentre)]} { 
	if {$FX(FLTCentre)==""} { set FX(FLTCentre) 0 }
	.filter.main.bottom.centre.scale set $FX(FLTCentre)
   } else {
	set FX(FLTCentre) [.filter.main.bottom.centre.scale get]
   }
   if {[info exist FX(FLTWidth)]} {
	if {$FX(FLTWidth)==""} { set FX(FLTWidth) 0 }
	.filter.main.bottom.width.scale set $FX(FLTWidth)
   } else {
	set FX(FLTWidth) [.filter.main.bottom.width.scale get]
   }

  # Create label for the main window.
  label .filter.main.label  \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "Select Type of Filter"\
			-font $ConfigSet(FNT_S) \
 			-anchor w

  # Create the Select checkbutton.
  checkbutton .filter.main.apply \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
			-text "Select the Filter Effect"\
			-selectcolor $ConfigSet(cAFG)\
			-anchor w\
			-variable FX(filter)\
			-relief groove

   # Create the Done button
   frame .filter.main.done -bg $ConfigSet(cBG1)\
			  -relief groove\
			  -bd 2
   button .filter.main.done.butt \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
 			-text Done\
			-command {destroy .filter}
   pack .filter.main.done.butt -expand 1 -ipadx 2m -pady 3m

   # Set the focus on the done button.
   focus .filter.main.done.butt

   # Pack into main.
   pack .filter.main.label \
	.filter.main.top\
	.filter.main.bottom\
	.filter.main.done\
	-fill both -expand 1 -side top
   pack .filter.main.apply -before .filter.main.done -anchor w -fill x\
			  -expand 1 -pady 1m

   # Pack main.
   pack .filter.main -fill both -expand 1
}


###################################################################
# sReverse
# This is the callback to the Effect-Reverse menu-item.
# It doesn't do any thing, it is a by-product of condensed coding.
proc sReverse {} {
	# Do nothing.
}


###################################################################
# sEcho
# This procedure is the callback to the Effect-Echo and 
# a button-3 click on the Echo checkbutton in the effect bar.
# It creates a dialog box to set the parameters for the Echo effect.
# BUGS: It doesn't take full advantage of the effect possibilities
# in Sox, but it creates echos that are of a acceptable duration.
proc sEcho {} {
   global ConfigSet FX

   # Create the dialog box.

   # Create toplevel window.
   toplevel .echo -bg $ConfigSet(cBG1)
   wm title .echo "Echo Settings"
   # Set window as a pop-up child of the root window.
   wm transient .echo .
   # Stop entry from the main window. (grab).
   catch { grab .echo }

   # Create Widgets.
   # Create the general frame.	   
   frame .echo.main 	-bg $ConfigSet(cBG1)\
			-bd 2 -relief $ConfigSet(REL)

   # Create the set frame to contain the scale widgets for setting
   # the delay and volume parameters
   frame .echo.main.set -bg $ConfigSet(cBG1)  

   # Create the delay scale widget.
   frame .echo.main.set.delay -bg $ConfigSet(cBG1)
   label .echo.main.set.delay.instr \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "Delay relative to Sample (%)"\
			-font $ConfigSet(FNT_S) \
 			-anchor w
   entry .echo.main.set.delay.label \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-textvariable "FX(ECHDelay)"\
			-font $ConfigSet(FNT_S) \
			-width 5\
			-insertbackground $ConfigSet(cFG1)\
			-selectforeground $ConfigSet(cAFG)\
			-selectbackground $ConfigSet(cABG)\
			-cursor arrow
   # Bind the entry with special characteristics.
   bindScale .echo.main.set.delay .echo.main.done.butt
		 
   scale .echo.main.set.delay.scale\
			-showvalue 0\
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-activebackground $ConfigSet(cABG)\
			-from 0 -to 100\
			-width 10 -length 100\
			-orient horizontal\
			-command "set FX(ECHDelay)"

   # Make sure that the value is being displayed and the scale slider
   # is in the correct position.
   if {[info exist FX(ECHDelay)]} {  
		if {$FX(ECHDelay)==""} { set FX(ECHDelay) 0 }
		.echo.main.set.delay.scale set $FX(ECHDelay)
   } else {
	set FX(ECHDelay) [.echo.main.set.delay.scale get]
   }

   pack .echo.main.set.delay.instr 	-fill x -expand 1\
					-anchor w
   pack .echo.main.set.delay.scale\
	.echo.main.set.delay.label \
	  	-side left -fill x -expand 1 

   # Create the volume scale widget.
   frame .echo.main.set.volume -bg $ConfigSet(cBG1)
   label .echo.main.set.volume.instr \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "Volume of Echo"\
			-font $ConfigSet(FNT_S) \
 			-anchor w
   entry .echo.main.set.volume.label \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-textvariable "FX(ECHVolume)"\
			-font $ConfigSet(FNT_S) \
			-width 5\
			-insertbackground $ConfigSet(cFG1)\
			-selectforeground $ConfigSet(cAFG)\
			-selectbackground $ConfigSet(cABG)\
			-cursor arrow
   # Bind the entry with special characteristics.
   bindScale .echo.main.set.volume .echo.main.done.butt
		 
   scale .echo.main.set.volume.scale\
			-showvalue 0\
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-activebackground $ConfigSet(cABG)\
			-from 0 -to 100\
			-width 10 -length 100\
			-orient horizontal\
			-command "set FX(ECHVolume)"
   # Make sure that the value is being displayed and the scale slider
   # is in the correct position.
   if {[info exist FX(ECHVolume)]} { 
	if {$FX(ECHVolume)==""} { set FX(ECHVolume) 0 }
	.echo.main.set.volume.scale set $FX(ECHVolume)
   } else {
	set FX(ECHVolume) [.echo.main.set.volume.scale get]
   }

   pack .echo.main.set.volume.instr 	-fill x -expand 1\
					-anchor w
   pack .echo.main.set.volume.scale\
	.echo.main.set.volume.label \
	  	-side left -fill x -expand 1

   # Pack the delay and volume scale widgets.
   pack .echo.main.set.delay\
	.echo.main.set.volume\
		-expand 1 -padx 5m -pady 3m -side left

   # Create the label for the main window.
   label .echo.main.label  \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "Set the Echo Dimentions"\
			-font $ConfigSet(FNT_S) \
 			-anchor w
   # Create the Select checkbutton.
   checkbutton .echo.main.apply \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
			-text "Select the Echo Effect"\
			-selectcolor $ConfigSet(cAFG)\
			-anchor w\
			-variable FX(echo)\
			-relief groove

   # Create the Done button
   frame .echo.main.done -bg $ConfigSet(cBG1)\
			  -relief groove\
			  -bd 2
   button .echo.main.done.butt \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
 			-text Done\
			-command {destroy .echo}
   pack .echo.main.done.butt -expand 1 -ipadx 2m -pady 3m

   # Set the focus on the done button.
   focus .echo.main.done.butt

   # Pack into main.
   pack .echo.main.label \
	.echo.main.set\
	.echo.main.done\
	-fill both -expand 1 -side top
   pack .echo.main.apply -before .echo.main.done -anchor w -expand 1 -fill x\
			-pady 1m

   # Pack main.
   pack .echo.main -fill both -expand 1
}



###################################################################
# sVibrato
# This procedure is the callback to the Effects-Vibrato menu item and 
# a button-3 click on the Vibrato checkbutton in the effect bar.
# It creates a dialog box to set the parameters for the vibrato effect.
proc sVibrato {} {
   global ConfigSet FX

   # Create the dialog box.
	
   # Create toplevel window.
   toplevel .vibro -bg $ConfigSet(cBG1)
   wm title .vibro "Vibrato Settings"
   # Set window as a pop-up child of the root window.
   wm transient .vibro .
   # Stop entry from the main window. (grab).
   catch { grab .vibro }

   # Create Widgets
   # Create the general frame.	   
   frame .vibro.main -bg $ConfigSet(cBG1)\
			-bd 2 -relief $ConfigSet(REL)

   # Create the set frame to contain the scale widgets.
   frame .vibro.main.set -bg $ConfigSet(cBG1)  

   # Create the speed scale widget. 
   frame .vibro.main.set.speed -bg $ConfigSet(cBG1)
   label .vibro.main.set.speed.instr \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "Speed of Vibrato (Hz)"\
			-font $ConfigSet(FNT_S) \
 			-anchor w
   entry .vibro.main.set.speed.label \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-textvariable "FX(VIBSpeed)"\
			-font $ConfigSet(FNT_S) \
			-width 5\
			-insertbackground $ConfigSet(cFG1)\
			-selectforeground $ConfigSet(cAFG)\
			-selectbackground $ConfigSet(cABG)\
			-cursor arrow
   # Bind the entry with special characteristics.
   bindScale .vibro.main.set.speed .vibro.main.done.butt
		 
   scale .vibro.main.set.speed.scale\
			-showvalue 0\
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-activebackground $ConfigSet(cABG)\
			-from 1 -to 30\
			-width 10 -length 100\
			-orient horizontal\
			-command "set FX(VIBSpeed)"

   # Make sure that the value is being displayed and the scale slider
   # is in the correct position.
   if {[info exist FX(VIBSpeed)]} {
		if {$FX(VIBSpeed)==""} { set FX(VIBSpeed) 0 }
		.vibro.main.set.speed.scale set $FX(VIBSpeed)
   } else {
	set FX(VIBSpeed) [.vibro.main.set.speed.scale get]
   }
   pack .vibro.main.set.speed.instr -fill x -expand 1\
					-anchor w
   pack .vibro.main.set.speed.scale\
	.vibro.main.set.speed.label \
	  -side left -fill x -expand 1 

   # Create the depth scale widget.
   frame .vibro.main.set.depth -bg $ConfigSet(cBG1)
   label .vibro.main.set.depth.instr \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "Depth of Vibrato"\
			-font $ConfigSet(FNT_S) \
 			-anchor w
    entry .vibro.main.set.depth.label \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-textvariable "FX(VIBDepth)"\
			-font $ConfigSet(FNT_S) \
			-width 5\
			-insertbackground $ConfigSet(cFG1)\
			-selectforeground $ConfigSet(cAFG)\
			-selectbackground $ConfigSet(cABG)\
			-cursor arrow
   # Bind the entry with special characteristics.
   bindScale .vibro.main.set.depth .vibro.main.done.butt
		 
   scale .vibro.main.set.depth.scale\
			-showvalue 0\
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-activebackground $ConfigSet(cABG)\
			-from 0 -to 100\
			-width 10 -length 100\
			-orient horizontal\
			-command "set FX(VIBDepth)"

   # Make sure that the value is being displayed and the scale slider
   # is in the correct position.
   if {[info exist FX(VIBDepth)]} { 
		if {$FX(VIBDepth)==""} { set FX(VIBDepth) 0 }
		.vibro.main.set.depth.scale set $FX(VIBDepth)
   } else {
	set FX(VIBDepth) [.vibro.main.set.depth.scale get]
   }

   pack .vibro.main.set.depth.instr -fill x -expand 1\
					-anchor w
   pack .vibro.main.set.depth.scale\
	.vibro.main.set.depth.label \
	  -side left -fill x -expand 1

   # Pack the scale widgets.
   pack .vibro.main.set.speed\
	.vibro.main.set.depth\
	-expand 1 -padx 5m -pady 3m -side left

   # Create the label for the main window.
   label .vibro.main.label  \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "Set the Vibrato Parameters"\
			-font $ConfigSet(FNT_S) \
 			-anchor w

   # Create the Select checkbutton.
   checkbutton .vibro.main.apply \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
			-text "Select the Vibrato effect."\
			-selectcolor $ConfigSet(cAFG)\
			-anchor w\
			-variable FX(vibrato)\
			-relief groove

   # Create the Done Button
   frame .vibro.main.done -bg $ConfigSet(cBG1)\
			  -relief groove\
			  -bd 2
   button .vibro.main.done.butt \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
 			-text Done\
			-command {destroy .vibro}
   pack .vibro.main.done.butt -expand 1 -ipadx 2m -pady 3m

   # Set the focus on the done button.
   focus .vibro.main.done.butt

   # Pack into main.
   pack .vibro.main.label \
	.vibro.main.set\
	.vibro.main.done\
		-fill both -expand 1 -side top
   pack .vibro.main.apply -before .vibro.main.done -anchor w -fill x -expand 1\
			  -pady 1m 

   # Pack main.
   pack .vibro.main -fill both -expand 1
}

###################################################################
#
# This procedure is the callback to the Effect-Volume, Effect-Tempo
# menu items and a button-3 click on the Volume and Tempo checkbuttons
# in the effect bar.
# It creates a dialog box to set the parameters for the Volume and
# Tempo effects (a single slider).
# The parameters are
# Name	: Either "Volume" or "Tempo". The default is Volume.
# min	: The minimum value of the scale. The default is -100.
# max 	: The maximum value of the scale. The default is +100.
proc sVolTemp { {Name Volume} {min -100} {max 100}} {
   global ConfigSet FX

   # Get a lower case version of Name for widget manipulation.
   set name [string tolower $Name]

   # Create the dialog box.

   # Create toplevel window .
   toplevel .volt -bg $ConfigSet(cBG1)
   wm title .volt "$Name"
   # Set window as a pop-up child of the root window.
   wm transient .volt .
   # Stop entry from the main window. (grab).
   catch { grab .volt }

   # Create Widgets
   # Create the general frame.	   
   frame .volt.main -bg $ConfigSet(cBG1)\
			-bd 2 -relief $ConfigSet(REL)

   # Create the scale widget.
   frame .volt.main.set -bg $ConfigSet(cBG1)
   label .volt.main.set.instr \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "$Name"\
			-font $ConfigSet(FNT_S) \
 			-anchor w
   entry .volt.main.set.label \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-textvariable "FX($name\Val)"\
			-font $ConfigSet(FNT_S) \
			-width 5\
			-insertbackground $ConfigSet(cFG1)\
			-selectforeground $ConfigSet(cAFG)\
			-selectbackground $ConfigSet(cABG)\
			-cursor arrow
   # Bind the entry with special characteristics.
   bindScale .volt.main.set .volt.main.done.butt

   scale .volt.main.set.scale\
			-showvalue 0\
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-activebackground $ConfigSet(cABG)\
			-from $min -to $max\
			-width 10 -length 200\
			-orient horizontal\
			-command "set FX($name\Val)"

   # Make sure that the value is being displayed and the scale slider
   # is in the correct position.
   if {$FX($name\Val)!=""} {
		.volt.main.set.scale set $FX($name\Val)
   } else {
	set FX($name\Val) [.volt.main.set.scale get]
   }
   pack .volt.main.set.instr -fill x -expand 1\
					-anchor w
   pack .volt.main.set.scale\
	.volt.main.set.label \
	  -side left -fill x -expand 1


   # Create the label for the main window.
   label .volt.main.label  \
			-bg $ConfigSet(cBG1)\
			-fg $ConfigSet(cFG1)\
			-text "Set $Name Effect"\
			-font $ConfigSet(FNT_S) \
 			-anchor w

   # Create the Select checkbutton
   checkbutton .volt.main.apply \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
			-text "Select the $Name Effect"\
			-selectcolor $ConfigSet(cAFG)\
			-anchor w\
			-variable FX($name)\
			-relief groove

   # Create the Done button
   frame .volt.main.done  -bg $ConfigSet(cBG1)\
			  -relief groove\
			  -bd 2
   button .volt.main.done.butt \
			-foreground $ConfigSet(cFG2) \
			-background $ConfigSet(cBG2) \
			-activebackground $ConfigSet(cABG) \
			-activeforeground $ConfigSet(cAFG) \
			-disabledforeground $ConfigSet(cDFG) \
 			-text Done\
			-command \
			   "destroy .volt
			   # Set the scale in the effectBar 
			   # if it is present.
   			   # ( I am using the binding on the entry 
			   #   which shows the value,
   			   # since it does the same job really)
   			   if {\[winfo exists .effect.bottom.$name.label\]} {
   			     eval \[bind .effect.bottom.$name.label <Return>\]
   			   }"
   pack .volt.main.done.butt -expand 1 -ipadx 2m -pady 3m
  
   # Set the focus on the done button.
   focus .volt.main.done.butt


   # Pack into main.
   pack .volt.main.label \
	.volt.main.set\
	.volt.main.done\
	-fill both -expand 1 -side top
   pack .volt.main.apply -before .volt.main.done -anchor w -fill x\
			  -expand 1 -pady 1m

   # Pack main.
   pack .volt.main -fill both -expand 1
}

