Python: Experimental audio API
Vicki Pfau vi@endrift.com
Sun, 07 Oct 2018 15:21:52 -0700
5 files changed,
77 insertions(+),
1 deletions(-)
M
CHANGES
→
CHANGES
@@ -111,6 +111,7 @@ - Switch: Rotation support
- Qt: State file load/save menu options - Windows installer - Tile viewer now has adjustable width + - Python: Experimental audio API Bugfixes: - PSP2: Fix audio crackling after fast forward - PSP2: Fix audio crackling when buffer is full
M
src/platform/python/_builder.h
→
src/platform/python/_builder.h
@@ -35,6 +35,7 @@ #include <limits.h>
#include "flags.h" +#include <mgba/core/blip_buf.h> #include <mgba/core/cache-set.h> #include <mgba/core/core.h> #include <mgba/core/map-cache.h>
M
src/platform/python/_builder.py
→
src/platform/python/_builder.py
@@ -20,6 +20,7 @@ #define static
#define inline #include "flags.h" #define OPAQUE_THREADING +#include <mgba/core/blip_buf.h> #include <mgba/core/cache-set.h> #include <mgba-util/common.h> #include <mgba/core/core.h>
A
src/platform/python/mgba/audio.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2013-2018 Jeffrey Pfau +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +from ._pylib import ffi, lib # pylint: disable=no-name-in-module + + +class Buffer(object): + def __init__(self, native, internal_rate): + self._native = native + self._internal_rate = internal_rate + + @property + def available(self): + return lib.blip_samples_avail(self._native) + + def set_rate(self, rate): + lib.blip_set_rates(self._native, self._internal_rate, rate) + + def read(self, samples): + buffer = ffi.new("short[%i]" % samples) + count = self.read_into(buffer, samples, 1, 0) + return buffer[:count] + + def read_into(self, buffer, samples, channels=1, interleave=0): + return lib.blip_read_samples(self._native, ffi.addressof(buffer, interleave), samples, channels == 2) + + def clear(self): + lib.blip_clear(self._native) + + +class StereoBuffer(object): + def __init__(self, left, right): + self._left = left + self._right = right + + @property + def available(self): + return min(self._left.available, self._right.available) + + def set_rate(self, rate): + self._left.set_rate(rate) + self._right.set_rate(rate) + + def read(self, samples): + buffer = ffi.new("short[%i]" % (2 * samples)) + count = self.read_into(buffer, samples) + return buffer[0:2 * count] + + def read_into(self, buffer, samples): + samples = self._left.read_into(buffer, samples, 2, 0) + return self._right.read_into(buffer, samples, 2, 1) + + def clear(self): + self._left.clear() + self._right.clear()
M
src/platform/python/mgba/core.py
→
src/platform/python/mgba/core.py
@@ -4,7 +4,7 @@ # This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. from ._pylib import ffi, lib # pylint: disable=no-name-in-module -from . import tile +from . import tile, audio from cached_property import cached_property from functools import wraps@@ -224,6 +224,22 @@
@protected def set_video_buffer(self, image): self._core.setVideoBuffer(self._core, image.buffer, image.stride) + + @protected + def set_audio_buffer_size(self, size) + self._core.setAudioBufferSize(self._core, size) + + @property + def audio_buffer_size(self): + return self._core.getAudioBufferSize(self._core) + + @protected + def get_audio_channels(self): + return audio.StereoBuffer(self.get_audio_channel(0), self.get_audio_channel(1)); + + @protected + def get_audio_channel(self, channel): + return audio.Buffer(self._core.getAudioChannel(self._core, channel), self.frequency) @protected def reset(self):