Skip to content

Commit ba75623

Browse files
committed
custom mixer/manager support with example
1 parent 199d19b commit ba75623

File tree

4 files changed

+100
-15
lines changed

4 files changed

+100
-15
lines changed

examples/custom_manager.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# -*- coding: utf-8 -*-
2+
from time import sleep
3+
from pyrilla import core
4+
5+
from base import main
6+
7+
8+
def file_handle(filename, ext):
9+
# note: low buffer settings that drop audio quality
10+
# for ilustratory reasons
11+
manager = core.Manager(
12+
thread_policy=core.THREAD_MULTI,
13+
)
14+
mixer = core.Mixer(manager)
15+
16+
sound = core.Sound(filename, ext)
17+
voice = core.Voice(sound, loop=True, mixer=mixer)
18+
19+
voice.play()
20+
21+
try:
22+
while True:
23+
# note: we use multiple thread policy so no need for manual
24+
# update on manager. We can sleep indifinitely
25+
sleep(1.001)
26+
except KeyboardInterrupt:
27+
print("interrupted")
28+
29+
if __name__ == "__main__":
30+
main(file_handle)
31+

examples/paning.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ def file_handle(filename, ext):
3232
core.update()
3333
time.sleep(0.001)
3434

35-
3635
except KeyboardInterrupt:
3736
print("interrupted")
3837

extensions/core.pyx

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
from cython.operator cimport dereference as deref
21
from cpython cimport Py_DECREF, Py_INCREF
32

43
cimport ga
54
cimport gau
65
cimport gc_common
6+
cimport gc_thread
77

88
def initialize():
99
gc_common.initialize(NULL)
@@ -13,11 +13,8 @@ def initialize():
1313
# note: no need to case for shutdown
1414
initialize()
1515

16-
cdef gau.Manager* global_manager = gau.manager_create()
17-
cdef gau.Mixer* global_mixer = gau.manager_mixer(global_manager)
18-
1916
def update():
20-
gau.manager_update(global_manager)
17+
default_manager.update()
2118

2219

2320
cdef on_finish_callback(ga.Handle* in_handle, void* in_context):
@@ -38,18 +35,59 @@ cdef class CallbackContext(object):
3835
self.sound = sound
3936

4037

38+
cdef class Manager(object):
39+
# c types
40+
cdef gau.Manager* p_manager
41+
DEF DEFAULT_BUFFERS_NUMBER = 4
42+
DEF DEFAULT_BUFFER_SAMPLES = 512
43+
44+
def __cinit__(
45+
self,
46+
int device=ga.DEVICE_TYPE_DEFAULT,
47+
int thread_policy=gau.THREAD_POLICY_SINGLE,
48+
int buffers_number=DEFAULT_BUFFERS_NUMBER,
49+
int buffer_samples=DEFAULT_BUFFER_SAMPLES
50+
):
51+
# note: we do not use gau.manager_create()
52+
# instead of that we use the same defaults
53+
self.p_manager = gau.manager_create_custom(
54+
device,
55+
thread_policy,
56+
buffers_number,
57+
buffer_samples,
58+
)
59+
60+
def update(self):
61+
gau.manager_update(self.p_manager)
62+
63+
def __del__(self):
64+
gau.manager_destroy(self.p_manager)
65+
66+
4167
cdef class Mixer(object):
42-
pass
68+
# c types
69+
cdef gau.Mixer* p_mixer
70+
# cython objects
71+
cdef Manager manager
72+
73+
def __cinit__(self, Manager manager):
74+
self.manager = manager
75+
self.p_mixer = gau.manager_mixer(manager.p_manager)
76+
77+
def __del__(self):
78+
ga.mixer_destroy(self.p_mixer)
4379

4480

4581
cdef class Voice(object):
46-
cdef Sound sound
82+
# c types
4783
cdef int loop
48-
cdef Mixer mixer
49-
5084
cdef gau.SampleSourceLoop* loop_src
5185
cdef ga.Handle* handle
5286

87+
# cython types
88+
cdef Sound sound
89+
cdef Mixer mixer
90+
5391
def __cinit__(
5492
self,
5593
Sound sound,
@@ -60,9 +98,10 @@ cdef class Voice(object):
6098
cdef CallbackContext context
6199

62100
self.sound = sound
63-
self.mixer = mixer
64101
self.loop = loop
65102

103+
self.mixer = mixer or default_mixer
104+
66105
if on_finish:
67106
context = CallbackContext(on_finish, self.sound)
68107

@@ -71,7 +110,7 @@ cdef class Voice(object):
71110
Py_INCREF(context)
72111

73112
self.handle = gau.create_handle_sound(
74-
global_mixer,
113+
self.mixer.p_mixer,
75114
self.sound.sound,
76115
<ga.FinishCallback>&on_finish_callback,
77116
<void*>context,
@@ -80,7 +119,7 @@ cdef class Voice(object):
80119

81120
else:
82121
self.handle = gau.create_handle_sound(
83-
global_mixer,
122+
self.mixer.p_mixer,
84123
self.sound.sound,
85124
<ga.FinishCallback>&gau.on_finish_destroy,
86125
NULL,
@@ -152,14 +191,26 @@ cdef class Sound(object):
152191
else:
153192
raise NotImplementedError("streams not implemented yet")
154193

155-
def play(self, on_finish=None):
194+
def play(self, on_finish=None, mixer=None):
156195
cdef Voice voice
157196

158-
voice = Voice(self, on_finish, 0, None)
197+
voice = Voice(self, on_finish, 0, mixer)
159198
voice.play()
160199

161200
return voice
162201

163202
def __del__(self):
164203
"""Release sound (gorilla uses refcounting for that)"""
165204
ga.sound_release(self.sound)
205+
206+
# default manager and mixer
207+
default_manager = Manager()
208+
default_mixer = Mixer(default_manager)
209+
210+
DEVICE_XAUDIO2 = ga.DEVICE_TYPE_XAUDIO2
211+
DEVICE_DIRECTSOUND = ga.DEVICE_TYPE_DIRECTSOUND
212+
DEVICE_OPENAL = ga.DEVICE_TYPE_OPENAL
213+
DEVICE_DEFAULT = ga.DEVICE_TYPE_DEFAULT
214+
215+
THREAD_SINGLE = gau.THREAD_POLICY_SINGLE
216+
THREAD_MULTI = gau.THREAD_POLICY_MULTI

extensions/h_gau_types.pxi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ cdef extern from "gorilla/gau.h":
44

55
ctypedef gau_SampleSourceLoop SampleSourceLoop "gau_SampleSourceLoop" # prefixless
66
ctypedef gau_Manager Manager "gau_Manager" # prefixless
7+
8+
cdef int THREAD_POLICY_UNKNOWN "GAU_THREAD_POLICY_UNKNOWN"
9+
cdef int THREAD_POLICY_SINGLE "GAU_THREAD_POLICY_SINGLE"
10+
cdef int THREAD_POLICY_MULTI "GAU_THREAD_POLICY_MULTI"

0 commit comments

Comments
 (0)