Thesis User Test 2 – Arm Controlled Spatial Panner for Four Speakers

With two vive trackers and four speakers, one or two users can control the placement of audio across an “azimuth.”


here’s some footage of people’s first experience with the system. after experimenting to figure out how it works, people start playing around.


Vive > TouchDesigner Open VR node > TD processing & calibration > OSC to Ableton > 2 Ableton Groups > Envelop.

Music: Do it Anyway – Locked Groove (broken into 4 stems, using NI stems + audacity)


  • It made people aware of their own body and movement, and they liked that.
  • Movement was rewarded with the interaction
  • The interaction was limited, it would be cooler to effect more of the sound
  • Two trackers per person could be the way to go.

Next Steps:

  • hand height controls filter
  • create additional ‘gesture that sends a one shot through a ‘multi delay’
  • keep working on different tracks to find the right music
  • figure out why I can’t get clean ‘elevation’ readings from the tracker
  • move ableton to the same computer

Thesis User Test 1 – Movement Reactive Voices for Two Speakers

For my Thesis, and Sound In Space assignment #2, I am testing how users react when their movements, or how they move with others, impact ‘voices’ in a composition. I’m trying to suss out the proper number of people per voice and the number of voices for my “interactive dance floor.”

Technical setup: Touchdesigner

I created a ‘track control’ component for touchdesigner. The component has a number of options.

  • What is the volume level for ‘off’ and on? This allows users to feel their presence impacting the voice when entering the space.
  • Does it control a ‘rack’ device? This allows it to control parameters on instruments and effects
    • if so, how many parameters (macros) does it control?
  • Does it control clips by switching between them? This allows musical patterns to be changed by the ‘dance amount’
class trackController:
	trackController description:
	controls one voice in ableton

	in[0] - dance amount
	in[1] - isPresent
	def __init__(self, ownerComp):
		# The component to which this extension is attached
		self.ownerComp = ownerComp
		#does this launch clips?
		self.ClipLauncher = False
		#does this control racks?
		self.RackController = False

		#td ableton track object for volume and clips
		self.Track = op('abletonTrack1')
		#clip launcher, initalize it as off
		self.clipControl = op('abletonClipSelector')
		self.clipControl.allowCooking = False

		#rack component for macro control, initalize it as off
		self.rack = op('abletonRack1')
		self.rack.allowCooking = False
		#number of macros
		self.MacroCount = 2
		#store the track id that will be controlled
		self.TrackNumber = 0

		#set the default min/max volumes
		self.minVol = .1
		self.maxVol = .85

		#create a custom menu for controlling this TrackController

	def InitRack(self):
		select the appropriate rack device in ableton
		assumes that its the first device in the chain
		is called every time the TrackID parameter is changed
		self.rack.par.Device = 1
		self.rack.par.Chain1 = 0
	def MakeMenu(self):
		create custom properties on the comp for controlling the track
		o = self.ownerComp
		#reset the custom pars
		#add page for custom parameters
		p = o.appendCustomPage("Track Options")

		#make par for which track to control
		m = p.appendMenu("Track")[0] 
		#set its menu labels to match the ableton track's labels
		m.menuSource = "op('./abletonTrack1').par.Track"

		#add value for number of macros
		c = p.appendInt("Macrocount")[0] #[0] cuz it returns a tuple
		#set the range of the custom par 'macrocount'
		c.normMax = 8
		c.normMin = 0
		#set the default value
		c.normVal = 1
		#c.clampMax = True
		#c.clampMin = True

		#add value for presence volumes
		v = p.appendFloat("Maxvol")[0];
		v.normVal = self.maxVol
		v = p.appendFloat("Minvol")[0];
		v.normVal = self.minVol
		#add toggles to enable/disable clip launcher or rack controller

	def toggleComp(self,comp):
		turns a component on or off
		returns its latest state
		c = not (comp.allowCooking)
		comp.allowCooking = c
		return c

	def ToggleRackControl(self):
		toggles rack component
		self.RackController  = self.toggleComp(self.rack)

	def ToggleClipControl(self):
		toggles clip component
		self.ClipLauncher = self.toggleComp(self.clipControl)

Technical setup: Ableton

In order for a composition in ableton to be controllable. It needs a few things.

  • TDAbleton needs a master component on the master track in ableton
  • Any track that has rack components must have them encapsulated in a TDInstrument component
  • Any clip that is longer than 1/2 a bar and will be switched between needs the ‘Legato’ setting enabled in the clip launching preferences


Still in progress. Need two more voices, plus considering adding in a drum voice when all voices are fully active to give a reward for collectively moving.