Trim a WAV file without re-encoding it
Cuts one time range from a PCM or IEEE-float WAV and writes it as a new WAV without decoding, resampling or re-encoding the audio. Every retained sample byte stays unchanged, and the file never leaves this browser tab.
PCM or IEEE-float WAV, including RF64 and WAVE_FORMAT_EXTENSIBLE. The file stays in this tab.
How it works
What this works out
A WAV does not store a list of seconds that can simply be deleted. It stores a sequence of sample frames: at each tick of the sample rate, one sample for every channel. A stereo 24-bit file therefore has six bytes in each frame — three for the left sample and three for the right — and a safe cut has to begin and end between whole six-byte groups.
This tool turns the two times into those frame boundaries, copies the selected groups unchanged, and writes the sizes a new WAV header needs. That is the important distinction between a cut and an audio conversion: no sample is ever interpreted as sound, so there is nothing to quantise, resample or compress.
The method
The first twelve bytes establish the container. RIFF means ordinary
little-endian WAV; RF64 means the same chunk structure with 64-bit lengths in
a ds64 chunk; both must be followed by WAVE. RIFX reverses every
multi-byte value and is intentionally refused. Writing its sample bytes into a
new little-endian file without converting them would turn valid audio into
noise.
After that comes a flat list of chunks. Each has a four-character name, a 32-bit payload length, the payload, and one alignment byte when that length is odd. Two chunks supply everything needed here:
fmtsays how wide a frame is and how many frames play each second.datais the frame sequence itself.
For plain PCM or IEEE float, the frame width is fixed:
bytes per sample = bits per sample / 8
bytes per frame = channels × bytes per sample
total frames = data bytes / bytes per frame
start frame = round(start seconds × sample rate)
end frame = min(total frames, round(end seconds × sample rate))
kept frames = end frame − start frame
kept bytes = kept frames × bytes per frame
The header’s blockAlign field is checked against that frame width before any
copy happens. If they disagree, choosing either figure would be a guess about
where one frame ends and the next begins, so the file is refused with the two
conflicting figures named. The same rule rejects a data chunk ending in half a
frame.
The output is then assembled from a twelve-byte RIFF header, the original
fmt payload, a four-byte fact frame count for float audio, and a new
data chunk. The selected data range is copied in 4 MB pieces so a large file
can report real progress and respond to Cancel between pieces. The copied
range is never decoded; a test compares it directly with the same byte range
in the source.
Metadata is not carried across. That is not just a privacy default. A cue at
frame 96,000 belongs two seconds into a 48 kHz source, but after removing the
first second it belongs at frame 48,000. Copying the old cue chunk would
produce a valid-looking marker in the wrong place. Loop points, regions and
broadcast timestamps have the same problem, so a clean container is the only
answer that does not silently lie.
Before you read on
A 48 kHz stereo, 24-bit WAV is cut from 1.000 s to 1.001 s. How many audio bytes are retained?
The range holds 48 sample frames. Each frame has a three-byte left sample and a three-byte right sample, so its width is six bytes and the retained audio is 48 × 6 = 288 bytes. That frame width, not the apparent number of milliseconds, is what makes a byte boundary safe. The header is additional; 288 is only the unchanged audio payload.
A worked example
The unit test uses a deliberately tiny mono 8-bit PCM WAV so every byte can be
accounted for. Its sample rate is 8 Hz and its data chunk contains 16 one-byte
frames, so the original is exactly two seconds long. The requested range is
0.25 seconds to 1.25 seconds.
| Figure | Working | Result |
|---|---|---|
| First frame | round(0.25 × 8) | 2 |
| End frame | round(1.25 × 8) | 10 |
| Frames kept | 10 − 2 | 8 |
| Trimmed length | 8 ÷ 8 Hz | 1 second |
| Audio bytes kept | 8 frames × 1 byte | 8 bytes |
| Output file | 44-byte PCM header + 8 audio bytes | 52 bytes |
The test fills the source audio with known byte values and asserts that output audio is exactly source bytes 2 through 9 — frame 2 inclusive to frame 10 exclusive. It also asserts the frame numbers, both durations, the 52-byte file size, the WAV MIME type and the download name. If the implementation and this example stop describing the same operation, the test fails.
What it does not do
This is a frame cutter, not an editor. It does not fade the edges, find silence, normalise loudness, mix channels, change sample rate, convert bit depth or preview the recording. Each of those requires reading sample values and making a separate quality decision; none belongs inside a tool whose promise is that the retained values stay untouched.
It also does not attempt to repair a damaged WAV. A recorder that stopped mid-frame or wrote a chunk length past the physical end may contain recoverable sound, but choosing what to discard is recovery work, not trimming. Inspect the header first to see which claim is inconsistent; then repair the recording in an audio editor before cutting it.
And because metadata is deliberately removed, this is not the right operation for a Broadcast Wave hand-off that must preserve timecode, iXML production notes or cue regions. It is the right one when the wanted artifact is the selected audio itself in a compact, private, ordinary WAV.
If an SRT or WebVTT sidecar was aligned before the cut, shift subtitle timing by the amount removed from the beginning. That changes the external cue clock; it does not touch the copied audio samples or put subtitle metadata in the WAV.
How it is done
- Check that the first twelve bytes identify a little-endian RIFF or RF64 WAVE file. A big-endian RIFX file is refused because copying its samples into a little-endian container would change their meaning.
- Walk the RIFF chunk list, respecting the pad byte after an odd-length payload, until the fmt and data chunks have both been found. For RF64, read the 64-bit audio length from its ds64 chunk.
- Read the channel count, sample rate, block alignment and bit depth from fmt. If the format is WAVE_FORMAT_EXTENSIBLE, unwrap its sub-format GUID to distinguish PCM from IEEE float.
- Verify that the format is fixed-width PCM or IEEE float and that the declared block alignment equals channels multiplied by bytes per sample. A compressed or internally inconsistent file is refused rather than cut at a guessed boundary.
- Divide the data length by the block alignment to get the exact number of complete sample frames and, from that, the recording length.
- Multiply each requested time by the sample rate and round to the nearest whole frame. Clamp an end beyond the recording to its final frame; refuse a start at or beyond the end.
- Copy the selected frame range in 4 MB pieces into a fresh WAV. The format block is preserved, a new fact count is written for float audio, and the RIFF and data sizes are recalculated.
- Leave metadata chunks out of the result because their cue positions, loop points and time references would describe the untrimmed recording. Offer the new metadata-free WAV as a download.
What it assumes
- PCM and IEEE-float WAV files are supported, including WAVE_FORMAT_EXTENSIBLE and RF64. Compressed WAV encodings and big-endian RIFX are not, because cutting either safely requires decoding or byte-order conversion.
- A requested time can fall between sample frames. It is rounded to the nearest complete frame, so the largest timing adjustment is half a frame — about 0.011 milliseconds at 44.1 kHz.
- An end time beyond the file is clamped to the last complete frame. A start at or beyond that frame leaves no playable audio and is refused rather than producing an empty file.
- The sample rate, channel count, bit depth, format block and retained sample bytes are copied. There is no gain change, fade, resampling, dither or codec pass.
- Metadata is deliberately not copied. Broadcast time references, cue points, regions, loops, labels, artwork and comments would otherwise point into the old timeline or disclose details the visitor did not intend to keep.
- A data chunk must contain a whole number of sample frames and fit inside the file. A partial last frame or a chunk length past the end is treated as truncation rather than silently repaired.
- The whole input and the trimmed output exist in memory at once. Input is therefore capped at 256 MB, and a bounded RF64 result is written as an ordinary RIFF WAV.
Common questions
Does trimming a WAV reduce its audio quality?
No, not for the supported PCM and IEEE-float files. Complete sample frames are copied byte for byte, so there is no codec generation, resampling, gain change or dither. The complete file has different bytes because its container sizes are new and its metadata is omitted, but the retained audio payload is unchanged.
Why is the cut a fraction of a millisecond from the time I entered?
Digital audio can start only on a sample frame, not between two of them. Each time is rounded to the nearest frame, which limits the difference to half a frame: about 0.011 milliseconds at 44.1 kHz or 0.010 milliseconds at 48 kHz.
Which kinds of WAV file can this trim?
Little-endian RIFF and RF64 files containing integer PCM or 32-bit or 64-bit IEEE-float audio are supported, including the extensible format used for high bit depths and multichannel recordings. Compressed WAV and big-endian RIFX need a decoder or byte-order conversion and are refused.
Why are my WAV markers and comments missing afterward?
They were left out deliberately. A cue point, loop boundary or broadcast time reference is measured against the original recording; copying it unchanged would put it at the wrong point in the trimmed file. The output contains only the audio format, a frame count when needed, and the audio.
Does the WAV leave my browser while it is trimmed?
No. A worker in this tab reads the header and copies the selected bytes, then the browser offers those bytes as a local download. The page's automated browser test loads a real WAV and fails if any request leaves the site while the file is present.
Why will it not trim my MP3 even when I renamed it to .wav?
A filename does not change an audio format. MP3 stores compressed frames with boundaries and timing rules that are not WAV sample frames, so the first bytes are checked rather than trusting the extension. Converting or cutting MP3 requires a codec and is a different operation.