Skip to content

Commit 13796b2

Browse files
committed
- added openal.loaders module for sound loading functions
- minor documentation improvements
1 parent 26ef138 commit 13796b2

File tree

17 files changed

+316
-117
lines changed

17 files changed

+316
-117
lines changed

Makefile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ docs:
5656

5757
release: dist
5858
runtest:
59-
@PYTHONPATH=$(PYTHONPATH) $(PYTHON) -B -m test.util.runtests
59+
@PYTHONPATH=$(PYTHONPATH) $(PYTHON) -B -m openal.test.util.runtests
6060

6161
# Do not run these in production environments! They are for testing
6262
# purposes only!
@@ -75,10 +75,10 @@ installall:
7575
@pypy2.0 setup.py install
7676

7777
testall:
78-
@-PYTHONPATH=$(PYTHONPATH) python2.7 -B -m test.util.runtests
79-
@-PYTHONPATH=$(PYTHONPATH) python3.2 -B -m test.util.runtests
80-
@-PYTHONPATH=$(PYTHONPATH) python3.3 -B -m test.util.runtests
81-
@-PYTHONPATH=$(PYTHONPATH) pypy2.0 -B -m test.util.runtests
78+
@-PYTHONPATH=$(PYTHONPATH) python2.7 -B -m openal.test.util.runtests
79+
@-PYTHONPATH=$(PYTHONPATH) python3.2 -B -m openal.test.util.runtests
80+
@-PYTHONPATH=$(PYTHONPATH) python3.3 -B -m openal.test.util.runtests
81+
@-PYTHONPATH=$(PYTHONPATH) pypy2.0 -B -m openal.test.util.runtests
8282

8383
purge_installs:
8484
rm -rf /usr/local/lib/python2.7/site-packages/openal*

doc/openalaudio.rst renamed to doc/audio.rst

Lines changed: 149 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
.. module:: openal.audio
22
:synopsis: Advanced OpenAL audio module
33

4-
Using openalaudio
5-
=================
4+
openal.audio - advanced sound support
5+
======================================
66
:mod:`openal.audio` is a set of advanced, pythonic classes for 3D positional
77
audio support via the OpenAL standard. It utilises :mod:`openal`, but hides all
88
the :mod:`ctypes` related, sequential programming workflow from you. It is
@@ -47,7 +47,6 @@ while each of them uses its own execution context.
4747

4848
Placing the listener
4949
--------------------
50-
5150
The OpenAL standard supports 3D positional audio, so that a source of sound can
5251
be placed anywhere relative to the listener (the user of the application or
5352
some in-application avatar).
@@ -121,7 +120,6 @@ ears of you receive the noise in nearly the same way).
121120

122121
Creating sound sources
123122
----------------------
124-
125123
A :class:`SoundSource` represents an object that can emit sounds. It can be any
126124
kind of object and allows you to play any sound, you put into it. In an
127125
application you can enable objects to emit sounds, by binding a
@@ -135,7 +133,6 @@ application you can enable objects to emit sounds, by binding a
135133

136134
Creating and playing sounds
137135
---------------------------
138-
139136
To create and play sounds you use :class:`SoundData` objects, which contain the
140137
raw PCM data to be played. To play the sound, the :class:`SoundData` needs to
141138
be queued on a :class:`SoundSource`, which provides all the necessary
@@ -148,20 +145,160 @@ There are some helper functions, which create :class:`SoundData` objects from
148145
audio files. If you have a raw PCM data buffer, you can create a
149146
:class:`SoundData` from it directly. ::
150147

151-
>>> rawsound = SoundData(pcmformat, pcmbuf, size_of_buf, frequency_in_hz)
148+
>>> rawsound = SoundData(pcmbuf, size_of_buf, channels, bitrate, frequency_in_hz)
152149

153-
Queueing the loaded sound is done via the :meth:`SoundSource.queue()` or
154-
:meth:`SoundSource.play()` method, which appends the sound to the source for
155-
processing and playback. ::
150+
Queueing the loaded sound is done via the :meth:`SoundSource.queue()` method,
151+
which appends the sound to the source for processing and playback. ::
156152

157153
>>> wavsound = load_wav_file("vroom.wav")
158-
>>> source.play(wavsound)
154+
>>> source.queue(wavsound)
159155

160156
You just need to inform the :class:`SoundSink` about the :class:`SoundSource`
161157
afterwards, so that it knows that a new sound emitter is available. ::
162158

163159
>>> soundsink.play(source)
164160
165161
When you add other sounds to play to the source, they will be picked up
166-
automatically for playback, as long as the :class:`SoundSource` is not paused,
167-
stopped or ran out of something to play.
162+
automatically for playback, as long as the :class:`SoundSource` is not paused
163+
or ran out of something to play.
164+
165+
API
166+
^^^
167+
168+
.. class:: OpenALError([msg=None[, alcdevice=None]])
169+
170+
An OpenAL specific exception class. If a new :class:`OpenALError` is created
171+
and no *msg* is provided, the message will be set a mapped value of
172+
:meth:`openal.al.alGetError()`. If an :class:`openal.alc.ALCdevice` is
173+
provided as *alcdevice*, :meth:`openal.alc.alcGetError()` will be used
174+
instead of :meth:`openal.al.alGetError()`.
175+
176+
.. class:: SoundData(data=None, channels=None, bitrate=None, size=None, \
177+
frequency=None, dformat=None)
178+
179+
The :class:`SoundData` consists of a PCM audio data buffer, the audio
180+
frequency and additional format information to allow easy buffering through
181+
OpenAL.
182+
183+
.. attribute:: channels
184+
185+
The channel count for the sound data.
186+
187+
.. attribute:: bitrate
188+
189+
The bitrate of the sound data.
190+
191+
.. attribute:: size
192+
193+
The buffer size in bytes.
194+
195+
.. attribute:: frequency
196+
197+
The sound frequency in Hz.
198+
199+
.. attribute:: data
200+
201+
The buffered audio data.
202+
203+
.. class:: SoundListener(position=[0, 0, 0], velocity=[0, 0, 0], \
204+
orientation=[0, 0, -1, 0, 1, 0])
205+
206+
A listener object within the 3D audio space.
207+
208+
.. attribute:: orientation
209+
210+
The listening orientation as 6-value list.
211+
212+
.. attribute:: position
213+
214+
The listener position as 3-value list.
215+
216+
.. attribute:: velocity
217+
218+
The movement velocity as 3-value list.
219+
220+
.. attribute:: gain
221+
222+
The relative sound volume (perceiptive for the listener).
223+
224+
.. attribute:: changed
225+
226+
Indicates, if an attribute has been changed.
227+
228+
.. class:: SoundSource(gain=1.0, pitch=1.0, position=[0, 0, 0], \
229+
velocity=[0, 0, 0])
230+
231+
An object within the application world, which can emit sounds.
232+
233+
.. attribute:: gain
234+
235+
The volume gain of the source.
236+
237+
.. attribute:: pitch
238+
239+
The pitch of the source.
240+
241+
.. attribute:: position
242+
243+
The (initial) position of the source as 3-value tuple in a x-y-z
244+
coordinate system.
245+
246+
.. attribute:: velocity
247+
248+
The velocity of the source as 3-value tuple in a x-y-z coordinate system.
249+
250+
.. method:: queue(sounddata : SoundData) -> None
251+
252+
Adds a :class:`SoundData` audio buffer to the source's processing and
253+
playback queue.
254+
255+
.. class:: SoundSink(device=None)
256+
257+
Audio playback system.
258+
259+
The SoundSink handles audio output for sound sources. It connects to an
260+
audio output device and manages the source settings, their buffer queues
261+
and the playback of them.
262+
263+
.. attribute:: device
264+
265+
The used OpenAL :class:`openal.alc.ALCdevice`.
266+
267+
.. attribute:: context
268+
269+
The used :class:`openal.alc.ALCcontext`.
270+
271+
.. method:: activate() -> None
272+
273+
Activates the :class:`SoundSink`, marking its :attr:`context` as the
274+
currently active one.
275+
276+
Subsequent OpenAL operations are done in the context of the
277+
SoundSink's bindings.
278+
279+
.. method:: set_listener(listener : SoundListener) -> None
280+
281+
Sets the listener position for the :class:`SoundSink`.
282+
283+
.. note::
284+
285+
This implicitly activates the :class:`SoundSink`.
286+
287+
.. method:: process_source(source : SoundSource) -> None
288+
289+
Processes a single :class:`SoundSource`.
290+
291+
.. note::
292+
293+
This does *not* activate the :class:`SoundSink`. If another
294+
:class:`SoundSink` is active, chances are good that the
295+
source is processed in that :class:`SoundSink`.
296+
297+
.. method:: process(world, components) -> None
298+
299+
Processes :class:`SoundSource` components, according to their
300+
:attr:`SoundSource.request`
301+
302+
.. note::
303+
304+
This implicitly activates the :class:`SoundSink`.

doc/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
# General information about the project.
5050
project = u'PyAL'
51-
copyright = u'2012, Marcus von Appen'
51+
copyright = u'2012-2013, Marcus von Appen'
5252

5353
# The version info for the project you're documenting, acts as replacement for
5454
# |version| and |release|, also used in various other places throughout the
@@ -235,7 +235,7 @@
235235
# dir menu entry, description, category)
236236
texinfo_documents = [
237237
('index', 'PyAL', u'PyAL Documentation',
238-
u'Marcus von Appen', 'PyAL', 'One line description of project.',
238+
u'Marcus von Appen', 'PyAL', 'ctypes wrapper for OpenAL',
239239
'Miscellaneous'),
240240
]
241241

doc/index.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ Contents
88
========
99

1010
.. toctree::
11-
:maxdepth: 2
11+
:maxdepth: 1
1212

1313
install.rst
1414
integration.rst
1515
openal.rst
16-
openalaudio.rst
16+
audio.rst
17+
loaders.rst
1718
news.rst
1819

1920
Further readings:

doc/loaders.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.. module:: openal.loaders
2+
:synopsis: Easy sound loading supports
3+
4+
openal.loaders - loading sounds
5+
===============================
6+
7+
.. todo::
8+
9+
Outline
10+
11+
API
12+
^^^
13+
14+
.. function:: load_file(fname : string) -> SoundData
15+
16+
Loads an audio file into a :class:`SoundData` object.
17+
18+
.. function:: load_stream(source : object) -> SoundData
19+
20+
Not implemented yet.
21+
22+
.. function:: load_wav_file(fname : string) -> SoundData
23+
24+
Loads a WAV audio file into a :class:`SoundData` object.

doc/news.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ Release News
22
============
33
This describes the latest changes between the PyAL releases.
44

5-
1.0.0
5+
0.1.0
66
-----
7-
Released on 2013-XX-XX.
7+
Released on 2013-04-21.
88

99
* Initial Release

doc/todos.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
TODOs
2-
=====
1+
Todo list for PyAL
2+
==================
33

4-
General
5-
-------
64
* proper unit tests
5+
* more examples

examples/audioplayer.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import os
33
import sys
44
import time
5-
import wave
6-
from openal.audio import SoundSink, SoundData, SoundSource
5+
from openal.audio import SoundSink, SoundSource
6+
from openal.loaders import load_wav_file
77

88
def run():
99
if len (sys.argv) < 2:
@@ -14,19 +14,14 @@ def run():
1414
else:
1515
fname = sys.argv[1]
1616

17-
wavefp = wave.open(fname)
18-
channels = wavefp.getnchannels()
19-
bitrate = wavefp.getsampwidth() * 8
20-
samplerate = wavefp.getframerate()
21-
wavbuf = wavefp.readframes(wavefp.getnframes())
2217

2318
sink = SoundSink()
2419
sink.activate()
2520

2621
source = SoundSource(position=[10, 0, 0])
2722
source.looping = True
2823

29-
data = SoundData(wavbuf, channels, bitrate, len(wavbuf), samplerate)
24+
data = load_wav_file(fname)
3025
source.queue(data)
3126

3227
sink.play(source)

0 commit comments

Comments
 (0)