# Audio

You can play musics and sound effects through `sol.audio`.

## Audio contexts

Sounds and musics are played into an *audio context*: either the global context of [`sol.main`](../general-features.md#solmainadd_audio_effecteffect), a [game](../game.md#gameadd_audio_effecteffect)'s own context or a [map](../map.md#mapadd_audio_effecteffect)'s own context. Audio contexts are notably used to apply [audio effects](../general-features.md#solmainadd_audio_effecteffect) (reverb, chorus, echo, flanger, low-pass and high-pass filters) to the sounds and musics that play into them.

Most functions of `sol.audio` accept an optional `context` parameter as their first argument, to target a specific audio context instead of the default, global one. When this parameter is omitted, the global context of `sol.main` is used.

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The audio context to use.

    Available in quest format 2.1 and later. With an earlier quest format, these functions always operate on the global context of `sol.main` and do not accept this extra parameter.

    If this parameter is set to a value that is not `sol.main`, a game or a map, Solarus shows a warning in the console and falls back to the global context of `sol.main`.

## Functions of `sol.audio`

### `sol.audio.play_sound([context,] sound_id)`

Plays a sound effect. Generates a Lua error if the sound does not exist.

Multiple sounds can be played in parallel. But to get more control of your sound effect being played, especially if you want to pause or stop it, you can use the more powerful [sol.sound module](./sound.md) instead of this function.

Unlike music files, sound files are entirely read before being played.

This is equivalent to [`sol.sound.create(sound_id):play()`](./sound.md#solsoundcreatesound_id).

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The [audio context](#audio-contexts) in which to play the sound.

`sound_id` (string)
: Name of the sound file to play, relative to the `sounds` directory and without extension. Currently, only OGG Vorbis (`.ogg`) sound files are supported.

### `sol.audio.preload_sounds()`

Loads all sounds effects into memory for faster future access.

!!! warning "Deprecated"

    This method is deprecated since Solarus 2.0. Sound effects are always automatically preloaded now.

### `sol.audio.play_music([context,] music_id, [action])`

Plays a music. If the music does not exist, a Lua error is generated.

Only one music can be played at a time per audio context. If the same music was already playing in this context, it continues normally and does not
restart. If a different music was already playing in this context, it is stopped and replaced by the new one.

When the music reaches the end, the `action` parameter indicates what to do next. The default behavior is to loop from the beginning.

However, some music files already have their own loop internal loop information. Such musics are able to loop to a specific point rather than
to the beginning. Since they already loop forever internally, they don't have an end and the `action` parameter has no effect on them.

See [Music Loop Settings](../../files-specs/audio/musics.md#loop-settings) to know how Solarus supports internal loop information for each format.

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The [audio context](#audio-contexts) in which to play the music.

`music_id` (string or `nil`)
: Name of the music file to play, relative to the `musics` directory and without extension. The following extensions will be tried in this order: `.ogg`, `.it` and `.spc`. Passing `nil` stops playing any music (the third parameter has no effect in this case).

    If you set the music name to the same music that is already playing in this context, or to the special value `"same"`, then this function does nothing: the music keeps playing (it does not restart) and the third parameter is ignored.

`action` (function or boolean, optional, default: `true`)
: What to do when the music finishes (reaches its end).

    - A **boolean** value indicates whether or not the music should loop.
    - A **function** value indicates a custom action (and implies no loop). It will be called when the music finishes. This allows you to perform an action of your choice, like playing another music.

        Note however that there might be some small delay between the exact end of the music and the time when your function is called, because the music can end between simulation frames but your function will be called the frame after that.

### `sol.audio.get_music([context])`

Returns the name of the music currently playing.

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The [audio context](#audio-contexts) to query.

Return value (string or `nil`)
: Name of the music file currently playing in this context, relative to the `musics` directory and without extension. Returns `nil` if no music is playing in this context.

### `sol.audio.stop_music([context])`

Stops playing music. This function has no effect if no music was playing in this context.

This is equivalent to `sol.audio.play_music("none")` (or `sol.audio.play_music(context, "none")` when targeting a specific context).

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The [audio context](#audio-contexts) in which to stop the music.

### `sol.audio.get_sound_volume()`

Returns the global volume of sound effects.

Return value (number)
: The global volume of sound effects, as an integer between `0` (mute) and `100` (full volume).

### `sol.audio.set_sound_volume(volume)`

Sets the default volume of sound effects. Note that individual sound effects have their own volume relative to this global sound volume.

`volume` (number)
: The new default volume of sound effects, as an integer between `0` (mute) and `100` (full volume).

### `sol.audio.get_music_volume()`

Returns the current volume of musics. This volume applies to all musics played by [`sol.audio.play_music()`](#solaudioplay_musiccontext-music_id-action).

Return value (number)
: The current volume of musics, as an integer between `0` (no sound effects) and `100` (full volume).

### `sol.audio.set_music_volume(volume)`

Sets the volume of musics. This volume applies to all musics played by [`sol.audio.play_music()`](#solaudioplay_musiccontext-music_id-action).

`volume` (number)
: The new volume of musics, as an integer between `0` (no music) and `100` (full volume).

### `sol.audio.get_music_format([context])`

Returns the format of the music currently playing.

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The [audio context](#audio-contexts) to query.

Return value (string or `nil`)
: Returns `nil` if no music is playing in this context. Format of the music:

    - `"ogg"`
    - `"it"`
    - `"spc"`

### `sol.audio.get_music_num_channels([context])`

Returns the number of channels of the current `.it` music. This function is only supported for `.it` musics.

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The [audio context](#audio-contexts) to query.

Return value (number or `nil`)
: Number of channels of the music. Returns `nil` if the current music format in this context is not `.it`.

### `sol.audio.get_music_channel_volume([context,] channel)`

Returns the volume of notes of a channel for the current `.it` music. This function is only supported for `.it` musics.

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The [audio context](#audio-contexts) to query.

`channel` (number)
: Index of a channel (the first one is zero).

Return value (number or `nil`)
: Volume of the channel. Returns `nil` if the current music format in this context is not `.it`.

!!! note "Note"

    The channel should have the same volume for all its notes. Otherwise, calling this function does not make much sense.

### `sol.audio.set_music_channel_volume([context,] channel, volume)`

Sets the volume of all notes of a channel for the current `.it` music. This function has no effect for musics other than `.it`.

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The [audio context](#audio-contexts) in which to set the volume.

`channel` (number)
: Index of a channel (the first one is zero).

`volume` (number)
: The volume to set.

### `sol.audio.get_music_tempo([context])`

Returns the tempo of the current `.it` music. This function is only supported for `.it` musics.

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The [audio context](#audio-contexts) to query.

Return value (number or `nil`)
: Tempo of the music. Returns `nil` if the current music format in this context is not `.it`.

### `sol.audio.set_music_tempo([context,] tempo)`

Sets the tempo of the current `.it` music. This function is only supported for `.it` musics.

`context` (`sol.main`, [game](../game.md) or [map](../map.md), optional, default: `sol.main`)
: The [audio context](#audio-contexts) in which to set the tempo.

`tempo` (number)
: Tempo to set.
