# SoundPlayer

The Sound System allows for the creation, manipulation, and synchronization of 2D and 3D audio within the game world. It supports NUI-based audio playback, spatialization, occlusion, looping, and global networking.

### 🎵 Accessing the API

You can access the sound system from any other resource using the export:

```lua
local SoundSystem = exports['ak47_lib']:CreateSound(data)
-- or 
local SoundSystem = Lib47.CreateSound(data)
```

***

### 🛠 Constructor

#### `CreateSound(data)`

Creates a new sound instance. This is the main entry point for the API.

**Parameters (`data` table)**

| **Property**     | **Type** | **Default**              | **Description**                                                                                                        |
| ---------------- | -------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| `url`            | String   | Required                 | The direct URL or file path to the audio file (mp3, ogg, wav).                                                         |
| `coords`         | vector3  | `nil`                    | The coordinates for 3D audio. If omitted, the sound defaults to 2D (global UI sound).                                  |
| `soundId`        | String   | Generated                | A unique identifier. Provide one if you need to reference it strictly.                                                 |
| `is3d`           | Boolean  | `true` (if coords exist) | Forces the sound to be 3D or 2D.                                                                                       |
| `volume`         | Number   | `0.5`                    | The initial volume of the sound (0.0 to 1.0).                                                                          |
| `maxDistance`    | Number   | `20.0`                   | The distance at which the sound ceases to be heard (for 3D sounds).                                                    |
| `rate`           | Number   | `1.0`                    | The playback speed. `1.0` is normal, `0.5` is half speed, `2.0` is double speed.                                       |
| `loop`           | Boolean  | `false`                  | New: If `true`, the audio will restart automatically when it finishes.                                                 |
| `interiorEffect` | Boolean  | `false`                  | If `true`, the sound will be occluded (muffled/silent) if the player is in a different interior than the sound source. |
| `global`         | Boolean  | `false`                  | If `true`, the sound creation and state will be synchronized to all clients via the server.                            |

**Returns**

Returns a Sound Object (Wrapper) containing methods to control the audio.

***

### 🧬 Sound Object Methods

Once you have created a sound object, you can use the following methods to control it.

#### `:play()`

Starts or resumes the audio playback.

* Returns: `Sound Object`

#### `:pause()`

Pauses the audio playback.

* Returns: `Sound Object`

#### `:destroy()`

Stops the sound, removes it from the internal tracker, and cleans up NUI resources.

* Returns: `nil`
* Note: It is recommended to assign your variable to the result of this function to clear your local variable (e.g., `mySound = mySound:destroy()`).

#### `:setVolume(volume)`

Updates the volume dynamically.

* volume (Number): 0.0 to 1.0.
* Returns: `Sound Object`

#### `:setRate(rate)`

Updates the playback speed dynamically.

* rate (Number): Playback rate (e.g., 0.5, 1.0, 1.5).
* Returns: `Sound Object`

#### `:setMaxDistance(distance)`

Updates the max hearing distance for 3D sounds.

* distance (Number): The new radius.
* Returns: `Sound Object`

#### `:updateCoords(coords)`

Updates the location of the sound source. Useful for attaching sounds to moving entities.

* coords (vector3): The new coordinates.
* Returns: `Sound Object`

#### `:getInfo()`

Asynchronously retrieves the current state of the audio from the NUI.

* Returns: Table `{ duration: number, currentTime: number }`
* Note: This uses `Citizen.Await`. It is non-blocking to the game thread but will yield the coroutine until data is received.

***

### 📚 Examples

#### Example 1: Looping Background Ambience

This plays a 2D sound that repeats forever. Perfect for weather effects or background music.

```lua
local rain = exports['ak47_lib']:CreateSound({
    url = "sounds/rain_loop.ogg",
    volume = 0.2,
    is3d = false,
    loop = true -- Audio will restart immediately upon ending
})

rain:play()
```

#### Example 2: Looping 3D Machine Sound

A generator placed on the ground that hums continuously.

```lua
local generator = exports['ak47_lib']:CreateSound({
    soundId = "gen_01",
    url = "sounds/generator_hum.mp3",
    coords = vector3(250.0, -50.0, 30.0),
    maxDistance = 15.0,
    volume = 0.6,
    loop = true, -- Repeats forever
    interiorEffect = true -- Muffles if you enter a nearby building
})

generator:play()
```

#### Example 3: Global Siren (Syncs to all players)

A loud alarm that loops and is heard by everyone on the server.

```lua
local alarm = exports['ak47_lib']:CreateSound({
    soundId = "prison_alarm",
    url = "https://mysounds.com/alarm.mp3",
    coords = vector3(1800.0, 2600.0, 45.0),
    maxDistance = 300.0,
    volume = 1.0,
    global = true, -- Synced to all players
    loop = true    -- Loops for all players
})

alarm:play()

-- Stop it after 30 seconds
SetTimeout(30000, function()
    if alarm then alarm:destroy() end
end)
```

#### Example 4: The "All Variables" Configuration

An example utilizing every possible configuration option available in the API.

```lua
local complexSound = exports['ak47_lib']:CreateSound({
    soundId = "custom_event_01",       -- Custom ID
    url = "sounds/weird_effect.ogg",   -- File path
    coords = vector3(100.5, 200.5, 30.0), -- 3D Location
    is3d = true,                       -- Enforce 3D
    volume = 0.8,                      -- 80% Volume
    maxDistance = 50.0,                -- Heard up to 50m
    rate = 0.5,                        -- Slow motion (half speed)
    loop = true,                       -- Keep playing
    interiorEffect = true,             -- Occlude walls/interiors
    global = true                      -- Sync to network
})

complexSound:play()
```

#### Example 5: Moving Entity Sound

Attaching a looping engine sound to a vehicle or player.

```lua
local ped = PlayerPedId()
local engine = exports['ak47_lib']:CreateSound({
    url = "sounds/engine_idle.wav",
    coords = GetEntityCoords(ped),
    maxDistance = 40.0,
    loop = true
})

engine:play()

Citizen.CreateThread(function()
    while engine do
        local coords = GetEntityCoords(ped)
        engine:updateCoords(coords)
        Wait(100)
    end
end)
```
