or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

camera-system.mdcore-graphics.mdgui-framework.mdindex.mdmath-utilities.mdphysics-engines.mdsound-system.mdspecialized-features.mdsprite-system.mdtexture-management.mdwindow-management.md

sound-system.mddocs/

0

# Sound System

1

2

Audio playback capabilities with support for multiple formats, volume control, spatial audio, and sound effect management for creating immersive game experiences with music and sound effects.

3

4

## Capabilities

5

6

### Core Sound Classes

7

8

Base sound classes for loading, playing, and controlling audio in games.

9

10

```python { .api }

11

class Sound:

12

"""

13

Audio sound class for loading and playing sound effects and music.

14

Supports various audio formats including WAV, OGG, and MP3.

15

"""

16

def __init__(self, file_path: str, streaming: bool = False):

17

"""

18

Create a sound object from an audio file.

19

20

Args:

21

file_path: Path to audio file or resource handle (e.g., ":resources:sounds/...")

22

streaming: Whether to stream the audio (for large files like music)

23

"""

24

25

# Properties

26

file_path: str

27

streaming: bool

28

29

def play(self, volume: float = 1.0, pan: float = 0.0, loop: bool = False, speed: float = 1.0) -> object:

30

"""

31

Play the sound with specified parameters.

32

33

Args:

34

volume: Volume level (0.0 = silent, 1.0 = full volume, >1.0 = amplified)

35

pan: Stereo panning (-1.0 = full left, 0.0 = center, 1.0 = full right)

36

loop: Whether to loop the sound continuously

37

speed: Playback speed (1.0 = normal, 2.0 = double speed, 0.5 = half speed)

38

39

Returns:

40

Media player object for controlling playback

41

"""

42

43

def stop(self) -> None:

44

"""Stop all instances of this sound."""

45

46

def get_length(self) -> float:

47

"""

48

Get the duration of the sound in seconds.

49

50

Returns:

51

Duration in seconds

52

"""

53

54

def get_volume(self) -> float:

55

"""

56

Get the current volume level.

57

58

Returns:

59

Volume level (0.0 to 1.0+)

60

"""

61

62

def set_volume(self, volume: float) -> None:

63

"""

64

Set the volume level for new playback instances.

65

66

Args:

67

volume: Volume level (0.0 = silent, 1.0 = full volume)

68

"""

69

```

70

71

### Sound Loading and Management Functions

72

73

Utility functions for loading sounds and managing audio playback.

74

75

```python { .api }

76

def load_sound(file_path: str, streaming: bool = False) -> arcade.Sound:

77

"""

78

Load a sound file and return a Sound object.

79

80

Args:

81

file_path: Path to audio file or resource handle

82

streaming: Whether to stream the audio (recommended for music)

83

84

Returns:

85

Sound object ready for playback

86

"""

87

88

def play_sound(sound: arcade.Sound, volume: float = 1.0, pan: float = 0.0,

89

loop: bool = False, speed: float = 1.0) -> object:

90

"""

91

Play a sound with specified parameters.

92

93

Args:

94

sound: Sound object to play

95

volume: Volume level (0.0 to 1.0+)

96

pan: Stereo panning (-1.0 to 1.0)

97

loop: Whether to loop the sound

98

speed: Playback speed multiplier

99

100

Returns:

101

Media player object for controlling playback

102

"""

103

104

def stop_sound(player: object) -> None:

105

"""

106

Stop a specific sound instance.

107

108

Args:

109

player: Media player object returned from play_sound()

110

"""

111

```

112

113

### Audio Control and Effects

114

115

Advanced audio control functions for managing playback and applying effects.

116

117

```python { .api }

118

def set_background_music(sound: arcade.Sound, volume: float = 0.5) -> None:

119

"""

120

Set and start playing background music.

121

122

Args:

123

sound: Sound object to use as background music

124

volume: Music volume level

125

"""

126

127

def stop_background_music() -> None:

128

"""Stop the currently playing background music."""

129

130

def pause_background_music() -> None:

131

"""Pause the background music (can be resumed)."""

132

133

def resume_background_music() -> None:

134

"""Resume paused background music."""

135

136

def get_background_music_volume() -> float:

137

"""

138

Get the current background music volume.

139

140

Returns:

141

Volume level (0.0 to 1.0+)

142

"""

143

144

def set_background_music_volume(volume: float) -> None:

145

"""

146

Set the background music volume.

147

148

Args:

149

volume: New volume level (0.0 to 1.0+)

150

"""

151

```

152

153

### Spatial Audio

154

155

Functions for creating positional and directional audio effects.

156

157

```python { .api }

158

def play_sound_3d(sound: arcade.Sound, listener_position: tuple[float, float],

159

sound_position: tuple[float, float], max_distance: float = 1000.0,

160

volume: float = 1.0) -> object:

161

"""

162

Play a sound with 3D spatial positioning.

163

164

Args:

165

sound: Sound object to play

166

listener_position: (x, y) position of the listener

167

sound_position: (x, y) position of the sound source

168

max_distance: Maximum audible distance

169

volume: Base volume level

170

171

Returns:

172

Media player object for controlling playback

173

"""

174

175

def update_sound_3d(player: object, listener_position: tuple[float, float],

176

sound_position: tuple[float, float], max_distance: float = 1000.0) -> None:

177

"""

178

Update the 3D position of a playing sound.

179

180

Args:

181

player: Media player object from play_sound_3d()

182

listener_position: New listener position

183

sound_position: New sound source position

184

max_distance: Maximum audible distance

185

"""

186

```

187

188

### Audio Streaming

189

190

Classes and functions for handling streaming audio, particularly useful for music and large audio files.

191

192

```python { .api }

193

class StreamingSound(arcade.Sound):

194

"""

195

Specialized sound class for streaming large audio files from disk.

196

More memory efficient for long audio tracks like background music.

197

"""

198

def __init__(self, file_path: str, buffer_size: int = 65536):

199

"""

200

Create a streaming sound.

201

202

Args:

203

file_path: Path to audio file

204

buffer_size: Size of streaming buffer in bytes

205

"""

206

207

buffer_size: int

208

209

def preload_streaming(self, seconds: float = 2.0) -> None:

210

"""

211

Preload a portion of the streaming audio to reduce latency.

212

213

Args:

214

seconds: Amount of audio to preload in seconds

215

"""

216

217

def create_sound_stream(file_path: str, buffer_size: int = 65536) -> arcade.StreamingSound:

218

"""

219

Create a streaming sound object for large audio files.

220

221

Args:

222

file_path: Path to audio file

223

buffer_size: Streaming buffer size

224

225

Returns:

226

StreamingSound object

227

"""

228

```

229

230

### Audio Format Support

231

232

Information about supported audio formats and codec capabilities.

233

234

```python { .api }

235

# Supported audio formats

236

SUPPORTED_FORMATS: list[str] = [

237

".wav", # Waveform Audio File Format (uncompressed)

238

".ogg", # Ogg Vorbis (compressed, open source)

239

".mp3", # MPEG Audio Layer 3 (compressed)

240

".flac", # Free Lossless Audio Codec

241

".aiff", # Audio Interchange File Format

242

".au", # Sun/Unix audio format

243

]

244

245

def is_audio_format_supported(file_path: str) -> bool:

246

"""

247

Check if an audio file format is supported.

248

249

Args:

250

file_path: Path to audio file

251

252

Returns:

253

True if format is supported, False otherwise

254

"""

255

256

def get_audio_info(file_path: str) -> dict:

257

"""

258

Get information about an audio file.

259

260

Args:

261

file_path: Path to audio file

262

263

Returns:

264

Dictionary with audio properties (duration, sample_rate, channels, etc.)

265

"""

266

```

267

268

## Usage Examples

269

270

### Basic Sound Effects

271

272

```python

273

import arcade

274

275

class SoundEffectsGame(arcade.Window):

276

def __init__(self):

277

super().__init__(800, 600, "Sound Effects Example")

278

279

self.sound_list = {}

280

self.background_music = None

281

282

def setup(self):

283

# Load sound effects

284

self.sound_list["jump"] = arcade.load_sound(":resources:sounds/jump1.wav")

285

self.sound_list["coin"] = arcade.load_sound(":resources:sounds/coin1.wav")

286

self.sound_list["hit"] = arcade.load_sound(":resources:sounds/hit1.wav")

287

self.sound_list["explosion"] = arcade.load_sound(":resources:sounds/explosion1.wav")

288

289

# Load and start background music

290

self.background_music = arcade.load_sound(":resources:music/1918.mp3", streaming=True)

291

arcade.play_sound(self.background_music, volume=0.3, loop=True)

292

293

# Create some sprites for interaction

294

self.player_list = arcade.SpriteList()

295

self.coin_list = arcade.SpriteList()

296

297

# Player sprite

298

self.player = arcade.Sprite(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png", 0.5)

299

self.player.center_x = 400

300

self.player.center_y = 300

301

self.player_list.append(self.player)

302

303

# Create coins

304

for i in range(5):

305

coin = arcade.Sprite(":resources:images/items/coinGold.png", 0.3)

306

coin.center_x = 150 + i * 100

307

coin.center_y = 200

308

self.coin_list.append(coin)

309

310

def on_draw(self):

311

self.clear()

312

self.player_list.draw()

313

self.coin_list.draw()

314

315

# Draw instructions

316

arcade.draw_text("SPACE = Jump sound", 10, 550, arcade.color.WHITE, 16)

317

arcade.draw_text("Move player to collect coins", 10, 525, arcade.color.WHITE, 16)

318

arcade.draw_text("X = Explosion sound", 10, 500, arcade.color.WHITE, 16)

319

arcade.draw_text("M = Toggle music", 10, 475, arcade.color.WHITE, 16)

320

321

def on_update(self, delta_time):

322

self.player_list.update()

323

324

# Check for coin collisions

325

coins_hit = arcade.check_for_collision_with_list(self.player, self.coin_list)

326

for coin in coins_hit:

327

# Play coin sound with slight volume variation

328

arcade.play_sound(self.sound_list["coin"], volume=0.8 + (0.4 * random.random()))

329

coin.remove_from_sprite_lists()

330

331

def on_key_press(self, key, modifiers):

332

if key == arcade.key.SPACE:

333

# Play jump sound

334

arcade.play_sound(self.sound_list["jump"], volume=0.5)

335

336

elif key == arcade.key.X:

337

# Play explosion with random pan

338

pan = (random.random() - 0.5) * 2 # Random pan from -1.0 to 1.0

339

arcade.play_sound(self.sound_list["explosion"], volume=0.7, pan=pan)

340

341

elif key == arcade.key.M:

342

# Toggle background music

343

if self.background_music_playing:

344

arcade.stop_sound(self.background_music)

345

self.background_music_playing = False

346

else:

347

arcade.play_sound(self.background_music, volume=0.3, loop=True)

348

self.background_music_playing = True

349

350

# Movement controls

351

elif key == arcade.key.LEFT:

352

self.player.change_x = -5

353

elif key == arcade.key.RIGHT:

354

self.player.change_x = 5

355

elif key == arcade.key.UP:

356

self.player.change_y = 5

357

elif key == arcade.key.DOWN:

358

self.player.change_y = -5

359

360

def on_key_release(self, key, modifiers):

361

if key in (arcade.key.LEFT, arcade.key.RIGHT):

362

self.player.change_x = 0

363

elif key in (arcade.key.UP, arcade.key.DOWN):

364

self.player.change_y = 0

365

366

def main():

367

game = SoundEffectsGame()

368

game.setup()

369

arcade.run()

370

371

if __name__ == "__main__":

372

main()

373

```

374

375

### 3D Spatial Audio Example

376

377

```python

378

import arcade

379

import math

380

381

class SpatialAudioGame(arcade.Window):

382

def __init__(self):

383

super().__init__(800, 600, "3D Spatial Audio")

384

385

self.player_list = arcade.SpriteList()

386

self.sound_source_list = arcade.SpriteList()

387

self.ambient_sound = None

388

self.sound_players = []

389

390

def setup(self):

391

# Create player (listener)

392

self.player = arcade.Sprite(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png", 0.4)

393

self.player.center_x = 400

394

self.player.center_y = 300

395

self.player_list.append(self.player)

396

397

# Create sound sources around the map

398

self.sound_sources = []

399

400

# Campfire sound source

401

campfire = arcade.Sprite(":resources:images/tiles/torch1.png", 0.5)

402

campfire.center_x = 200

403

campfire.center_y = 200

404

campfire.sound = arcade.load_sound(":resources:sounds/fire.wav")

405

self.sound_source_list.append(campfire)

406

self.sound_sources.append(campfire)

407

408

# Water sound source

409

water = arcade.Sprite(":resources:images/tiles/water.png", 0.5)

410

water.center_x = 600

411

water.center_y = 400

412

water.sound = arcade.load_sound(":resources:sounds/water.wav")

413

self.sound_source_list.append(water)

414

self.sound_sources.append(water)

415

416

# Start playing spatial sounds

417

self.start_spatial_sounds()

418

419

def start_spatial_sounds(self):

420

"""Start playing all spatial sound sources."""

421

for source in self.sound_sources:

422

player = arcade.play_sound_3d(

423

source.sound,

424

listener_position=(self.player.center_x, self.player.center_y),

425

sound_position=(source.center_x, source.center_y),

426

max_distance=300.0,

427

volume=0.5

428

)

429

source.player = player

430

self.sound_players.append(player)

431

432

def update_spatial_audio(self):

433

"""Update 3D audio based on player position."""

434

listener_pos = (self.player.center_x, self.player.center_y)

435

436

for source in self.sound_sources:

437

source_pos = (source.center_x, source.center_y)

438

439

# Update 3D position

440

arcade.update_sound_3d(

441

source.player,

442

listener_position=listener_pos,

443

sound_position=source_pos,

444

max_distance=300.0

445

)

446

447

def on_draw(self):

448

self.clear()

449

450

# Draw sound source ranges

451

for source in self.sound_sources:

452

# Draw audible range circle

453

arcade.draw_circle_outline(source.center_x, source.center_y, 300, arcade.color.YELLOW, 2)

454

455

self.sound_source_list.draw()

456

self.player_list.draw()

457

458

# Draw instructions and info

459

arcade.draw_text("Move with arrow keys", 10, 570, arcade.color.WHITE, 16)

460

arcade.draw_text("Listen to spatial audio effects", 10, 545, arcade.color.WHITE, 16)

461

462

# Draw distance to nearest sound source

463

if self.sound_sources:

464

nearest = min(self.sound_sources,

465

key=lambda s: arcade.get_distance_between_sprites(self.player, s))

466

distance = arcade.get_distance_between_sprites(self.player, nearest)

467

arcade.draw_text(f"Distance to nearest source: {distance:.1f}", 10, 520, arcade.color.WHITE, 16)

468

469

def on_update(self, delta_time):

470

self.player_list.update()

471

self.update_spatial_audio()

472

473

def on_key_press(self, key, modifiers):

474

if key == arcade.key.LEFT:

475

self.player.change_x = -5

476

elif key == arcade.key.RIGHT:

477

self.player.change_x = 5

478

elif key == arcade.key.UP:

479

self.player.change_y = 5

480

elif key == arcade.key.DOWN:

481

self.player.change_y = -5

482

483

def on_key_release(self, key, modifiers):

484

if key in (arcade.key.LEFT, arcade.key.RIGHT):

485

self.player.change_x = 0

486

elif key in (arcade.key.UP, arcade.key.DOWN):

487

self.player.change_y = 0

488

489

def main():

490

game = SpatialAudioGame()

491

game.setup()

492

arcade.run()

493

494

if __name__ == "__main__":

495

main()

496

```

497

498

### Music Player with Controls

499

500

```python

501

import arcade

502

503

class MusicPlayerExample(arcade.Window):

504

def __init__(self):

505

super().__init__(800, 600, "Music Player")

506

507

self.music_list = []

508

self.current_track = 0

509

self.current_player = None

510

self.is_playing = False

511

self.volume = 0.7

512

513

def setup(self):

514

# Load music tracks

515

self.music_list = [

516

arcade.load_sound(":resources:music/1918.mp3", streaming=True),

517

arcade.load_sound(":resources:music/funkyrobot.mp3", streaming=True),

518

]

519

520

# Start with first track

521

self.play_current_track()

522

523

def play_current_track(self):

524

"""Start playing the current track."""

525

if self.current_player:

526

arcade.stop_sound(self.current_player)

527

528

if self.music_list:

529

music = self.music_list[self.current_track]

530

self.current_player = arcade.play_sound(music, volume=self.volume, loop=True)

531

self.is_playing = True

532

533

def next_track(self):

534

"""Switch to the next track."""

535

if self.music_list:

536

self.current_track = (self.current_track + 1) % len(self.music_list)

537

self.play_current_track()

538

539

def previous_track(self):

540

"""Switch to the previous track."""

541

if self.music_list:

542

self.current_track = (self.current_track - 1) % len(self.music_list)

543

self.play_current_track()

544

545

def toggle_playback(self):

546

"""Toggle play/pause."""

547

if self.is_playing:

548

arcade.pause_background_music()

549

self.is_playing = False

550

else:

551

arcade.resume_background_music()

552

self.is_playing = True

553

554

def adjust_volume(self, change: float):

555

"""Adjust the volume up or down."""

556

self.volume = max(0.0, min(1.0, self.volume + change))

557

if self.current_player:

558

arcade.set_background_music_volume(self.volume)

559

560

def on_draw(self):

561

self.clear()

562

563

# Draw music player interface

564

arcade.draw_text("Music Player", 400, 500, arcade.color.WHITE, 36, anchor_x="center")

565

566

if self.music_list:

567

track_name = f"Track {self.current_track + 1}/{len(self.music_list)}"

568

arcade.draw_text(track_name, 400, 450, arcade.color.WHITE, 24, anchor_x="center")

569

570

status = "Playing" if self.is_playing else "Paused"

571

arcade.draw_text(f"Status: {status}", 400, 400, arcade.color.WHITE, 20, anchor_x="center")

572

573

arcade.draw_text(f"Volume: {self.volume:.1f}", 400, 350, arcade.color.WHITE, 20, anchor_x="center")

574

575

# Draw controls

576

controls = [

577

"SPACE = Play/Pause",

578

"N = Next Track",

579

"P = Previous Track",

580

"+ = Volume Up",

581

"- = Volume Down"

582

]

583

584

for i, control in enumerate(controls):

585

arcade.draw_text(control, 400, 280 - i * 30, arcade.color.LIGHT_GRAY, 16, anchor_x="center")

586

587

def on_key_press(self, key, modifiers):

588

if key == arcade.key.SPACE:

589

self.toggle_playback()

590

elif key == arcade.key.N:

591

self.next_track()

592

elif key == arcade.key.P:

593

self.previous_track()

594

elif key == arcade.key.PLUS or key == arcade.key.EQUAL:

595

self.adjust_volume(0.1)

596

elif key == arcade.key.MINUS:

597

self.adjust_volume(-0.1)

598

599

def main():

600

game = MusicPlayerExample()

601

game.setup()

602

arcade.run()

603

604

if __name__ == "__main__":

605

main()

606

```