Force Touch and Web Audio on the iPhone

3d touch iphone

3D Touch with pressure.js

Since a few weeks I have an iPhone 6S. It has 3D Touch, Apple’s technology to detect pressure on the phone’s screen. It takes some time getting used to. Things unexpectedly happen when you press down on the screen. But it feels naturally very soon. It’s like a third dimension after swiping across the surface of the screen.

The possibilities for audio and music are exciting. Drum rhythms can be tapped in much more expressively. All kinds of sound parameters can be controlled by pressure.

Force Touch in Javascript

The good news is that Force Touch is available in Javascript as an event where ‘force’ is a property of the Touch object.

el.addEventListener('touchforcechange', function(event) {
	console.log(event.changedTouches[0].force);
});

Force is a Number from 0 to 1 with 1 being the maximum pressure.

Pressure.js

Of course not everything is implemented in every browser, or implemented differently. There’s the ‘touchforcechange’ versus the ‘webkitmouseforcechanged’ event, some devices do support the ‘force’ property but not an accompanying ‘change’ event. There’s Force Touch and 3D Touch, which are apparently slightly different.

Luckily Stuart Yamartino‘s Pressure.js library comes to the rescue. It handles both Force Touch and 3D Touch, supports lots of devices, multitouch and has a polyfill for devices without a pressure sensitive interface.

With Pressure.js a listener for pressure changes looks like this:

Pressure.set(el, {
	change: function(force, event) {
		console.log(force);
	}
});

A very simple audio app

Here’s a very basic app to test Force Touch with Web Audio. It shows one big round button. When pressed a sine sound plays with varying pitch. The harder you press the higher the frequency. Try it here:

https://www.hisschemoller.com/projects/pressure/

Or watch this video to see it demonstrated:

To create sound the app uses a Web Audio oscillator node to generate sound and a gain node to start and stop the sound:

aCtx = new AudioContext();

gain = aCtx.createGain();
gain.gain.value = 0;
gain.connect(aCtx.destination);

osc = aCtx.createOscillator();
osc.type = 'sine';
osc.connect(gain);
osc.start();

Three callback functions are passed to the Pressure object to listen to start, end and achange events.

Pressure.set(btnEl, {
	change: onPressureChange,
	start: onPressureStart,
	end: onPressureEnd
});

The onPressureStart and onPressureEnd functions are used to start and stop the sound. The sound isn’t actually stopped. It’s started once and plays continually. To start and stop it, the volume is turned up and down with the Gain node.

PressureChange is the interesting bit. Here the force parameter is converted to a frequency value from 50 to 10,000 Hz. It’s also scaled from linear to logarithmic so that the lower frequencies can be better controlled. The resulting value is used to set the oscillator’s frequency.

onPressureChange = function(force, e) {
	var minFreqLog = Math.log(50),
	    maxFreqLog = Math.log(10000),
	    freq = Math.exp(minFreqLog + ((maxFreqLog - minFreqLog) * force));
	osc.frequency.value = freq;
	freqEl.innerHTML = freq.toFixed(1);
},

onPressureStart = function(e) {
	gain.gain.value = 1;
},

onPressureEnd = function(e) {
	gain.gain.value = 0;
};

Find the complete source files on GitHub.

Conclusion

Using Force Touch in Javascript apps is easy with Pressure.js. I think the technology is very useful for music and audio application. The only thing now is for more devices to support it. Lets hope that iPhone 6S and higher are just the start and that Force Touch will a common feature on touch devices in a few years.

2 Comments

Wouter,

Hi Yaniv, thanks very much for the compliment. A colleague at work told about the Pressure.js library, so I thought it would be fun to try it out combination with the Web Audio API.

Leave a Reply

Your email address will not be published. Required fields are marked *

18 + 15 =