Skip to content

WebAudio Pitch Shifting - #69

Closed
iambalaam wants to merge 8 commits into
mainfrom
web-audio
Closed

WebAudio Pitch Shifting#69
iambalaam wants to merge 8 commits into
mainfrom
web-audio

Conversation

@iambalaam

@iambalaam iambalaam commented Jul 14, 2026

Copy link
Copy Markdown
Contributor
  • Improves cypress test harness
    • Tests now use the WebAudio AnalyserNode to inspect the actual audio coming from the browser.
    • We can test output volume and frequency (using our constant volume 440Hz sinwave)
  • Adds a custom PhaseVocoderProcessor WebAudio AudioWorklet to manually handle pitch correction.
    • We disable preservesPitch on HTMLMediaElements
    • We handle blocks of 128 audio frames (~3ms) each invocation and use FFT.js
  • Uses WebAudio for all audio control of HTMLMediaElements
    • We create an AudioContext for each audioOutput (connecting an element to an audioContext is irreversible)
    • Graph: Media Element -> Source Node -> PhaseVocoderProcessor -> GainNode -> output *
  • Adds a build step for the audio worklet
    • Without this step, the worklet would need to be hosted as another file
    • This makes the bundle size a bit bigger, but it's nicer to be dependency-less

* I opted for a GainNode here for a couple reasons:

  • Provides better accuracy when performing transforms with lower volume
  • Provides a handy 'final node' to connect to when testing (that can be connected to an AnalyserNode)

@iambalaam
iambalaam requested review from chetbox and tomdixon July 14, 2026 14:59
@iambalaam iambalaam changed the title Web audio WebAudio Pitch Shifting Jul 14, 2026
@iambalaam
iambalaam force-pushed the web-audio branch 2 times, most recently from 2d0e765 to ec17251 Compare July 14, 2026 15:07
if (mediaElement.volume !== 1) {
mediaElement.volume = 1;
}
gainNode.gain.value = clipVolume;

@tomdixon tomdixon Jul 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you checked that the gain node volume scales in the same way as the mediaElement? e.g. that 50% sounds equivalent on both.


const PLAYBACK_ADJUSTMENT_SMOOTHING = 0.3;
const MAX_PLAYBACK_RATE_ADJUSTMENT = 0.1;
const PITCH_CORRECTION_1_BIN_UP = 1.026;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get an explainer comment on the magic numbers?

@iambalaam iambalaam mentioned this pull request Jul 28, 2026
@iambalaam iambalaam closed this Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants