Gamepad Haptics PCM Extension

Editor’s Draft,

More details about this document
This version:
https://w3c.github.io/gamepad-haptics/
Issue Tracking:
GitHub
Editor:
(Meta)
Unstable API

The API represented in this document is under development and may change at any time.


Abstract

This specification extends the Gamepad API’s GamepadHapticActuator interface with the ability to play PCM audio data as haptic feedback.

Status of this document

This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document was published by the Immersive Web Working Group as an Editors' Draft. This document is intended to become a W3C Recommendation. Feedback and comments on this specification are welcome. Please use Github issues. Discussions may also be found in the public-immersive-web-wg@w3.org archives.

Publication as an Editors' Draft does not imply endorsement by W3C and its Members. This is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to cite this document as other than a work in progress.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent that the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 18 August 2025 W3C Process Document.

1. Introduction

Some gamepad devices include haptic actuators capable of rendering audio waveforms directly to the user as haptic feedback. This specification extends the GamepadHapticActuator interface defined in the Gamepad specification with the play() method, which allows authors to play PCM audio data from an AudioBuffer through the gamepad’s haptic actuators.

This enables richer haptic experiences than predefined effects, as developers can design custom waveforms using the Web Audio API and play them through the gamepad’s haptic hardware.

1.1. Terminology

This specification uses the terms GamepadHapticActuator and gamepad task source as defined in the Gamepad specification.

It uses the term AudioBuffer as defined in the Web Audio API specification.

2. GamepadHapticActuator Extension

This specification extends the GamepadHapticActuator interface with a method for playing PCM audio data as haptic feedback.

partial interface GamepadHapticActuator {
  Promise<boolean> play(AudioBuffer sound);
};

2.1. play

The play(sound) method plays PCM audio data from an AudioBuffer through the gamepad’s haptic actuator.

When invoked, the user agent MUST run the following steps:

  1. Let document be the current settings object’s relevant global object’s associated Document.

  2. If document is null or document is not fully active or document’s visibility state is "hidden", return a promise rejected with an "InvalidStateError" DOMException.

  3. If sound’s length is 0, return a promise resolved with true.

  4. If this.[[playingEffectPromise]] is not null:

    1. Let effectPromise be this.[[playingEffectPromise]].

    2. Set this.[[playingEffectPromise]] to null.

    3. Queue a global task on the gamepad task source with the relevant global object of this to resolve effectPromise with "preempted".

  5. Let [[playingEffectPromise]] be a new promise.

  6. Run the following steps in parallel:

    1. Send the PCM data from sound to the haptic actuator for playback. If the actuator does not support PCM playback, queue a global task on the gamepad task source with the relevant global object of this to resolve [[playingEffectPromise]] with false, and abort these steps.

    2. When the playback completes successfully, queue a global task on the gamepad task source with the relevant global object of this to resolve [[playingEffectPromise]] with true.

    3. If an error occurs during playback, queue a global task on the gamepad task source with the relevant global object of this to resolve [[playingEffectPromise]] with false.

  7. Return [[playingEffectPromise]].

NOTE: The sampleRate of the AudioBuffer may not match the native sample rate of the haptic actuator. In this case, the user agent SHOULD resample the audio data to match the actuator’s native sample rate.

Playing a custom haptic waveform from an AudioBuffer:
const audioCtx = new AudioContext();
const sampleRate = audioCtx.sampleRate;
const buffer = audioCtx.createBuffer(1, sampleRate * 0.5, sampleRate);

// Fill with a 150Hz sine wave for 0.5 seconds
const channelData = buffer.getChannelData(0);
for (let i = 0; i < buffer.length; i++) {
  channelData[i] = Math.sin(2 * Math.PI * 150 * i / sampleRate);
}

const gamepad = navigator.getGamepads()[0];
const success = await gamepad.vibrationActuator.play(buffer);
if (success) {
  console.log("Haptic waveform played successfully");
} else {
  console.log("PCM haptic playback failed or is not supported");
}

3. Security and Privacy Considerations

This specification does not introduce any new security or privacy considerations beyond those described in the Gamepad and Web Audio API specifications.

The play() method requires the same user activation and visibility conditions as the existing playEffect() method to prevent abuse of haptic hardware by background pages.

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Conformant Algorithms

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[GAMEPAD]
Steve Agoston; Matthew Reynolds. Gamepad. URL: https://w3c.github.io/gamepad/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBAUDIO-1.0]
Paul Adenot; Hongchan Choi. Web Audio API. URL: https://webaudio.github.io/web-audio-api/
[WEBAUDIO-1.1]
Paul Adenot; Hongchan Choi. Web Audio API 1.1. URL: https://webaudio.github.io/web-audio-api/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

IDL Index

partial interface GamepadHapticActuator {
  Promise<boolean> play(AudioBuffer sound);
};