Sound Demo

sound_demo.py
1"""
2Sound Panning Demo
3
4If Python and Arcade are installed, this example can be run from the
5command line with:
6python -m arcade.examples.sound_demo
7
8Each button plays a sound when clicked.
9
10The top left button plays a streaming music track when pressed. If you
11click it while it's already playing, it will intentionally crash the
12demo to demonstrate how you shouldn't try to play a streaming sound
13that's already playing.
14
15The lower 3 rows of buttons play a non-streaming (static) sound with
16different panning and volume. Going from left to right changes the
17panning, which is how much the sound plays in the left speaker vs the
18right speaker. Lower rows play the sound louder than the higher ones.
19"""
20
21import typing
22
23import arcade
24
25WINDOW_WIDTH = 1280
26WINDOW_HEIGHT = 720
27WINDOW_TITLE = "Sound Panning Demo"
28BUTTON_SIZE = 30
29
30
31SOUND_PANNING = [-1.0, -0.5, 0.0, 0.5, 1.0]
32MARGIN = WINDOW_WIDTH / 4
33BUTTON_X_POSITIONS = [
34 MARGIN,
35 MARGIN + (WINDOW_WIDTH - MARGIN * 2) / 3 * 1,
36 MARGIN + (WINDOW_WIDTH - MARGIN * 2) / 3 * 2,
37 MARGIN + (WINDOW_WIDTH - MARGIN * 2) / 3 * 3,
38 WINDOW_WIDTH - MARGIN,
39]
40
41
42VOLUME_VARIATION = [0.1, 0.5, 1]
43Y_OFFSETS = [50, 0, -50]
44
45
46class SoundButton(arcade.SpriteSolidColor):
47 """
48 A sprite that stores settings about how to play a sound.
49
50 This class can load a sound as either a static sound or a streaming
51 sound. Streaming should be used for long files that will only have
52 one instance playing, such as music or ambiance tracks.
53
54 If you try to play a sound created with streaming=True while it is
55 already playing, it will raise an exception! Non-streaming (static)
56 sounds are fine with it, and can have play() called on them as many
57 times as you want.
58 """
59
60 def __init__(
61 self,
62 sound_file,
63 pan=0.5,
64 volume=0.5,
65 center_x=0,
66 center_y=0,
67 streaming=False
68 ):
69 super().__init__(BUTTON_SIZE, BUTTON_SIZE, color=arcade.color.WHITE)
70 self.sound = arcade.Sound(sound_file, streaming=streaming)
71 self.pan = pan
72 self.volume = volume
73 self.center_x = center_x
74 self.center_y = center_y
75
76 def play(self):
77 self.sound.play(pan=self.pan, volume=self.volume)
78
79
80class GameView(arcade.View):
81 def __init__(self):
82 super().__init__()
83 self.background_color = arcade.color.AMAZON
84 self.button_sprites = None
85
86 def setup(self):
87 self.button_sprites = arcade.SpriteList()
88
89 # create the streaming button at the top left
90 self.button_sprites.append(
91 SoundButton(
92 ":resources:music/funkyrobot.mp3",
93 pan=-1.0,
94 volume=0.1,
95 center_x=BUTTON_X_POSITIONS[0],
96 center_y=WINDOW_HEIGHT / 2 + 150,
97 streaming=True
98 )
99 )
100
101 # Position the grid of buttons
102 # The zip function takes pieces from iterables and returns them
103 # as tuples. For more information, see the python doc:
104 # https://docs.python.org/3/library/functions.html#zip
105 for vol, y_offset in zip(VOLUME_VARIATION, Y_OFFSETS):
106 for pan_setting, x_pos in zip(SOUND_PANNING, BUTTON_X_POSITIONS):
107 self.button_sprites.append(
108 SoundButton(
109 ":resources:sounds/upgrade4.wav",
110 pan_setting,
111 vol,
112 x_pos,
113 WINDOW_HEIGHT / 2 + y_offset,
114 )
115 )
116
117 def on_draw(self):
118 self.clear()
119 self.button_sprites.draw()
120
121 def on_update(self, delta_time):
122 self.button_sprites.update()
123
124 def on_mouse_press(self, x, y, button, key_modifiers):
125 hit_sprites = arcade.get_sprites_at_point((x, y), self.button_sprites)
126 for sprite in hit_sprites:
127 button_sprite = typing.cast(SoundButton, sprite)
128 if button == arcade.MOUSE_BUTTON_LEFT:
129 button_sprite.play()
130
131
132def main():
133 """ Main function """
134 # Create a window class. This is what actually shows up on screen
135 window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
136
137 # Create and setup the GameView
138 game = GameView()
139 game.setup()
140
141 # Show GameView on screen
142 window.show_view(game)
143
144 # Start the arcade game loop
145 arcade.run()
146
147
148if __name__ == "__main__":
149 main()