Looping a sound

From Valve Developer Community
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
English (en)Русский (ru)Translate (Translate)

A looped sound will repeat endlessly without any gap between its end and start. It is up to the sound artist to ensure that the end and start of the file match up however, otherwise there will be a "pop" as the waveform jumps from one shape to another.

GoldSrc GoldSrc and Source Source detect looped sounds ONLY through cue points embedded in the file. This is a WAV-only feature, so MP3s cannot be looped. Microsoft ADPCM compressed WAVs can be looped, but due to the way they are encoded, there may a pop when the sound restarts if the sound is shorter than a few seconds.

Note.pngNote:Source 2 Source 2 supports looping both WAV and MP3, but only S&box S&box's tools can set the looping flag in a VSND for MP3 files; first-party Valve tools still rely upon WAV cues points to determine when a VSND should loop.
Note.pngFix:With custom audio backends, it is theoretically possible to loop filetypes other than WAV. Compressed audio formats usually have a small decoding delay upon restarting a track, which can appear as a small pop or stutter, with MP3 being worse due to its fixed frame size and Ogg Vorbis being the cleanest. This can theoretically be avoided for any compressed format, including MP3.
Note.pngNote:There is no need to mark a sound as looping when playing it, but if using ambient_generic you will find that the "Is NOT Looped" flag must be set correctly if you want to stop the sound after it starts!
Warning.pngWarning:Left 4 Dead 2 During development: editing the contents of an existing sound file stored in your campaign's sound.cache will not show any change until the sound cache is rebuilt! See Creating a sound.cache file or L4D2 Custom Sound and Music Tutorial for further instructions.
Todo: Remove stuff regarding end loop points; they don't work in any engine, and can prevent the sound from looping in GoldSrc GoldSrc.

Looping a WAV

These free programs can add cue points to a WAV:

GoldWave

Open Goldwave and open the sound you want to loop. Click the cues icon. (Cues button.jpg) Then in the new window click on the New button and add a cue point At Start. Then click New for another cue point and add a point At End. So it looks similar to this:

Cue dialog.jpg

Wavosaur

Warning.pngWarning:
  • GoldSrc GoldSrc doesn't use Wavosaur's loop points. Instead, the start cue is actually the first marker (M0).
  • Source Source supports both Wavosaur's loop points and markers for looping a sound but will prioritize markers over loop points if both are present. Because of this, and because end points are unused, markers may be preferred for compatibility.
  • End cue points are unused. You should trim the file instead.
  • Wavosaur does not support ADPCM-compressed WAV files; attempting to open one will result in the application crashing!
Todo: Do loop points work in Portal 2 Portal 2? The marker route was initially added to the page due to the loop points being reported as non-functional in that game.

Looping from beginning to end

  • Open Wavosaur.
  • Open the sound you want to loop.
  • Go to Tools > Markers > Create marker, or press M. This will add a new M0 marker at the beginning.
    • If the marker is not at the beginning, move it there by dragging it with the mouse.

After that, click "Save" or "Save As".

Looping from anywhere in the file

  1. Open Wavosaur.
  2. Open the sound you want to loop.
  3. Go to Tools > Loop > Create loop points. It should create loop points.
    1. You can change their positions by dragging them.
    2. If you're looping a sound for Source, the end point should be moved at the end of the track, as end cues are not functional (see the Discussion page). You should trim the end instead.
    3. Double-clicking between the loop points will select the whole region between them and allow you to play it on loop.

Once you have found a satisfying position for the starting point:

  1. Click outside of the selection to clear it.
  2. Double-click the area between the loop points to select it.
    1. Do NOT play it now! Wavosaur uses the "playing position" to create markers.
  3. Go to Tools > Markers > Create marker, or press M. This will add a new M0 marker at the exact position of the loop's starting point.
  4. Go to Tools > Loop > Delete loop points to clean up the unnecessary data. Failure to do so is inconsequential in Source, but will result in the track not looping in GoldSrc.

After that, click "Save" or "Save As".

With a hex editor or script

Bytes of a Cue Chunk of a WAV file
Bytes (hex) as ASCII as Little
Endian

Integer
Description
63 75 65 20 "cue " begins a new cue chunk
1C 00 00 00 28 size of this cue chunk in bytes
(= the number of bytes that follow)
01 00 00 00 1 number of cue points that follow now
01 00 00 00 1 ID of first (and only) cue point
00 00 00 00 0 position
(Wavosaur uses this as the cue point position)
64 61 74 61 "data" what kind of chunk this first cue point lies in
00 00 00 00 0 chunk start
00 00 00 00 0 block start
00 00 00 00 0 sample position that Source uses to loop

Each WAV file consists of chunks where each chunk starts with an ID in ASCII, its size and more chunk-specific bytes. PCM waves typically consist of an format chunk, which describes how the audio samples are represented in bytes, and a data chunk, containing those bytes.

Loop points are defined in a separate cue chunk. The order of chunks in a file does not matter. That's why it is possible to simply append some bytes to the end of a non-looping WAV file to add a loop point. The following bytes represent a cue chunk that defines one cue point at the very first sample which makes Source loop it in its entirety:

63 75 65 20 1C 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 64 61 74 61 00 00 00 00 00 00 00 00 00 00 00 00

The last four bytes (the rightmost 00 00 00 00 in this case) represent a little endian integer which Source uses as the sample index at which the file should be looped. (Tested in: Portal 2Counter-Strike: Global Offensive) To set the loop point to the audio position at x seconds of a 44100 Hz mono or stereo file, represent x * 44100 in hexadecimal, reverse the byte order and use that instead of the above last four bytes. Example: To set the loop point at 2.6 seconds from the beginning, replace the last four bytes of the above with 2.6 * 44,100 = 114,660 = [1BFE4]_hex = [E4 BF 01 00]_le.

Tip.pngTip:The Windows Calculator can represent numbers in both decimal and hexadecimal in programmer mode (scientific mode before Win7).

Now, to append some bytes to an existing WAV file, you can do the following.

Linux/MacOS LinuxmacOS

Create a file from the above bytes named cue.bin using the script below, then run cat my_nonlooping_sound.wav cue.bin > my_looping_sound.wav. The following is a bash shell script used to generate cue.bin.

cue.sh
#!/bin/bash

# Wave file cue chunk according to https://www.recordingblogs.com/wiki/cue-chunk-of-a-wave-file
# Original script by SavageX; permission is granted to modify as needed.

ECHO="echo -en"
OUT="cue.bin"

function append_bytes() {
    $ECHO $1 >> $OUT
}

function append_cue() {
    OUT=$1

    # chunk ID, "cue "
    append_bytes "cue\x20"

    # size of the chunk: (12 + 24) - 8 = 28
    # Why -8? ID and size don't count.
    append_bytes "\x1C\x00\x00\x00"

    # number of data points: 1
    append_bytes "\x01\x00\x00\x00"

    # ID of data point: 1
    append_bytes "\x01\x00\x00\x00"

    # position: If there is no playlist chunk, this is zero
    append_bytes "\x00\x00\x00\x00"

    # data chunk ID
    append_bytes "data"

    # chunk start: 0
    append_bytes "\x00\x00\x00\x00"

    # block start: 0
    append_bytes "\x00\x00\x00\x00"

    # sample start: 0
    append_bytes "\x00\x00\x00\x00"
}

rm -f cue.bin
append_cue cue.bin

Windows Windows

The following is a batch script file that appends the above bytes to the input files. Create a text file, paste the text in and save the file with the .bat extension. Drag-dropping non-looping WAV files on it (i. e. running the script with %1, %2, ... being the input files) will create looping copys ending with _loop.wav.

loop_wav.bat
@echo off
setlocal

rem Message for empty input
if "%~1"=="" (
    echo Please drag and drop one or multiple non-looping WAV files onto this script.
    echo For each file it will create a new copy ending with "_loop.wav" which will loop in Source, GoldSrc, and IdTech 2 games.
    pause
    exit /b
)

rem Define the names of helper files that we will need
set "chunkTxt=temp_cue_chunk.txt"
set "chunkBin=temp_cue_chunk.bin"
rem Create a temporary text file containing the cue chunk as hex values
>"%chunkTxt%" ( echo:63 75 65 20 1C 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 64 61 74 61 00 00 00 00 00 00 00 00 00 00 00 00 )
rem Convert the hex values to a binary file - that's what we will append to the WAV files
rem The certutil.exe lives in Windows/System32/ and should exist since XP
certutil -f -decodehex "%chunkTxt%" "%chunkBin%" >nul

rem Append the cue chunk to the WAV file
for %%F in (%*) do (
    copy /b "%%~F"+"%chunkBin%" "%%~dpnF_loop.wav" >nul
    echo Created looped WAV file "%%~nF_loop.wav".
)

rem Delete helper files
del "%chunkTxt%"
del "%chunkBin%"

pause

Cue location

Your cues do not have to be at the start and end of the file. If you place them in the middle Source will start playing the sound normally, then when it reaches the end cue will loop back to the start cue. From then on only what's between the cues will play.

Warning.pngWarning:It seems that the end cue maybe doesn't have any effect at all. See the Discussion page for more details.
Icon-Bug.pngBug:In Source Source games, in order to correctly loop an ADPCM-compressed WAV file from any location other than the beginning, the start cue's location (in samples) must be divided by 2. For instance, if your start cue is positioned at the sample 398060 for a sound in PCM format, it must be changed to 199030 for the same sound in ADPCM format.
This bug doesn't impact loops that start at the beginning, as 0 divided by 2 is still 0.  (tested in: Team Fortress 2)

This can be used to give a sound a "winding up" effect that only plays once (e.g. a motor starting).

Looping an MP3

The name of the ambient_generic is "MP3".

In Source Source, MP3 files can't be looped with start/end queues like a WAV. A logic_timer can be a good workaround; have it start playing the sound again after it has fully played (or has played to the point desired).

This could also be done using User I/O from the ambient_generic to itself, and an input delay (another entity will still need to be used to trigger the initial input).

Icon-Important.pngImportant:In singleplayer games prior to Portal 2 Portal 2, pausing the game pauses entity I/O but not music, causing the timer to go out of sync and leave a gap at the end of the song before looping.

See also

External links