mirror of https://github.com/McSinyx/palace
102 lines
3.1 KiB
ReStructuredText
102 lines
3.1 KiB
ReStructuredText
Play an Audio
|
|
=============
|
|
|
|
.. currentmodule:: palace
|
|
|
|
Now that you know how to create a context,
|
|
let's get into the most essential use case: playing audio.
|
|
|
|
Creating a Source
|
|
-----------------
|
|
|
|
To play an audio, you have to create a source. This source
|
|
is an imaginary sound broadcaster, whose positions and properties
|
|
can be changed to create desired effects.
|
|
|
|
.. code-block:: python
|
|
|
|
from palace import Device, Context, Source
|
|
|
|
with Device() as dev, Context(dev) as ctx:
|
|
with Source() as src:
|
|
# to be written
|
|
|
|
Just like for the case of :py:class:`Context`, :py:class:`Source` creation
|
|
requires a context, but here the context is passed implicitly.
|
|
|
|
Decode the Audio File
|
|
---------------------
|
|
|
|
Palace has a module level function :py:func:`decode`, which decodes audio file
|
|
automatically, and this decoded file is a :py:class:`Decoder` object. This object
|
|
can be played by a simple :py:meth:`Decoder.play` method.
|
|
|
|
.. code-block:: python
|
|
|
|
from palace import Device, Context, Source, decode
|
|
|
|
filename = 'some_audio.ogg'
|
|
with Device() as dev, Context(dev) as ctx:
|
|
with Source() as src:
|
|
dec = decode(filename)
|
|
|
|
We are almost there. Now, let's look at the document for :py:meth:`Decoder.play`.
|
|
The method takes 3 parameters: ``chunk_len``, ``queue_size``, and ``source``.
|
|
|
|
The source object is optional, because if you don't have it, a new source
|
|
will be generated by default.
|
|
|
|
The audio is divided into chunks, each of which is of length ``chunk_len``.
|
|
Then ``queue_size`` is the number of these chunks that it will play.
|
|
|
|
.. TODO: I think it's better to include a diagram here. Add later
|
|
|
|
.. code-block:: python
|
|
|
|
from palace import Device, Context, Source, decode
|
|
|
|
filename = 'some_audio.ogg'
|
|
with Device() as dev, Context(dev) as ctx:
|
|
with Source() as src:
|
|
dec = decode(filename)
|
|
dec.play(12000, 4, src)
|
|
|
|
But we don't want it to play only a small part of the audio. We want it to
|
|
play all of it. How do we do that? The answer is a loop.
|
|
|
|
There is a method, :py:meth:`Context.update`, which update the context and the source.
|
|
When the source is updated, it will be filled with new chunks of data from
|
|
the decoder.
|
|
|
|
.. code-block:: python
|
|
|
|
from palace import Device, Context, Source, decode
|
|
|
|
filename = 'some_audio.ogg'
|
|
with Device() as dev, Context(dev) as ctx:
|
|
with Source() as src:
|
|
dec = decode(filename)
|
|
dec.play(12000, 4, src)
|
|
while src.playing:
|
|
ctx.update()
|
|
|
|
If you tried this code for a song, you will find that it's a bit rush.
|
|
That is because the source is renewed too fast. So, a simple solution
|
|
is to ``sleep`` for a while.
|
|
|
|
.. code-block:: python
|
|
|
|
from time import sleep
|
|
from palace import Device, Context, Source, decode
|
|
|
|
filename = 'some_audio.ogg'
|
|
with Device() as dev, Context(dev) as ctx:
|
|
with Source() as src:
|
|
dec = decode(filename)
|
|
dec.play(12000, 4, src)
|
|
while src.playing:
|
|
sleep(0.025)
|
|
ctx.update()
|
|
|
|
Congratulation! Enjoy your music before we get to the next part of this tutorial.
|