palace
Advanced tools
| #!/usr/bin/env python3 | ||
| # Sample for tone generator | ||
| # Copyright (C) 2020 Ngô Ngọc Đức Huy | ||
| # | ||
| # This file is part of palace. | ||
| # | ||
| # palace is free software: you can redistribute it and/or modify it | ||
| # under the terms of the GNU Lesser General Public License as published | ||
| # by the Free Software Foundation, either version 3 of the License, | ||
| # or (at your option) any later version. | ||
| # | ||
| # palace is distributed in the hope that it will be useful, | ||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| # GNU Lesser General Public License for more details. | ||
| # | ||
| # You should have received a copy of the GNU Lesser General Public License | ||
| # along with palace. If not, see <https://www.gnu.org/licenses/>. | ||
| from argparse import Action, ArgumentParser | ||
| from functools import partial | ||
| from math import pi | ||
| from random import random | ||
| from time import sleep | ||
| from typing import Callable, Dict, Tuple | ||
| from palace import Buffer, Context, BaseDecoder, Device | ||
| from numpy import arange, float32, ndarray, sin, vectorize | ||
| from scipy.signal import sawtooth, square, unit_impulse | ||
| WAVEFORMS: Dict[str, Callable[[ndarray], ndarray]] = { | ||
| 'sine': sin, | ||
| 'square': square, | ||
| 'sawtooth': sawtooth, | ||
| 'triangle': partial(sawtooth, 0.5), | ||
| 'impulse': lambda frames: unit_impulse(len(frames)), | ||
| 'white-noise': vectorize(lambda time: random())} | ||
| class ToneGenerator(BaseDecoder): | ||
| def __init__(self, waveform: str, duration: float, frequency: float): | ||
| self.func = lambda frames: WAVEFORMS[waveform]( | ||
| frames / self.frequency * pi * 2 * frequency) | ||
| self.duration = duration | ||
| self.start = 0 | ||
| @BaseDecoder.frequency.getter | ||
| def frequency(self) -> int: return 44100 | ||
| @BaseDecoder.channel_config.getter | ||
| def channel_config(self) -> str: | ||
| return 'Mono' | ||
| @BaseDecoder.sample_type.getter | ||
| def sample_type(self) -> str: | ||
| return '32-bit float' | ||
| @BaseDecoder.length.getter | ||
| def length(self) -> int: return int(self.duration * self.frequency) | ||
| def seek(self, pos: int) -> bool: return False | ||
| @BaseDecoder.loop_points.getter | ||
| def loop_points(self) -> Tuple[int, int]: return 0, 0 | ||
| def read(self, count: int) -> bytes: | ||
| stop = min(self.start + count, self.length) | ||
| data = self.func(arange(self.start, stop)) | ||
| self.start = stop | ||
| return data.astype(float32).tobytes() | ||
| class TypePrinter(Action): | ||
| def __call__(self, parser: ArgumentParser, *args, **kwargs) -> None: | ||
| print('Available waveform types:', *WAVEFORMS, sep='\n') | ||
| parser.exit() | ||
| def play(device: str, waveform: str, | ||
| duration: float, frequency: float) -> None: | ||
| with Device(device) as dev, Context(dev): | ||
| dec = ToneGenerator(waveform, duration, frequency) | ||
| with Buffer.from_decoder(dec, 'tonegen') as buf, buf.play() as src: | ||
| while src.playing: | ||
| sleep() | ||
| if __name__ == '__main__': | ||
| parser = ArgumentParser() | ||
| parser.add_argument('-t', '--types', nargs=0, action=TypePrinter, | ||
| help='print available waveform types in this example') | ||
| parser.add_argument('-w', '--waveform', default='sine', type=str, | ||
| help='waveform to be generated, default to sine') | ||
| parser.add_argument('-d', '--device', default='', help='device name') | ||
| parser.add_argument('-l', '--duration', default=5.0, type=float, | ||
| help='duration, in second') | ||
| parser.add_argument('-f', '--frequency', default=440.0, type=float, | ||
| help='frequency for the wave in hertz, default to 440') | ||
| args = parser.parse_args() | ||
| play(args.device, args.waveform, args.duration, args.frequency) |
| Metadata-Version: 2.1 | ||
| Name: palace | ||
| Version: 0.1.1 | ||
| Version: 0.1.2 | ||
| Summary: Pythonic Audio Library and Codecs Environment | ||
| Home-page: https://github.com/McSinyx/palace | ||
| Author: Nguyễn Gia Phong | ||
| Author-email: vn.mcsinyx@gmail.com | ||
| Author-email: mcsinyx@disroot.org | ||
| License: LGPLv3+ | ||
@@ -9,0 +9,0 @@ Description: # palace |
@@ -15,2 +15,3 @@ CMakeLists.txt | ||
| examples/palace-stdec.py | ||
| examples/palace-tonegen.py | ||
| palace.egg-info/PKG-INFO | ||
@@ -17,0 +18,0 @@ palace.egg-info/SOURCES.txt |
+2
-2
| Metadata-Version: 2.1 | ||
| Name: palace | ||
| Version: 0.1.1 | ||
| Version: 0.1.2 | ||
| Summary: Pythonic Audio Library and Codecs Environment | ||
| Home-page: https://github.com/McSinyx/palace | ||
| Author: Nguyễn Gia Phong | ||
| Author-email: vn.mcsinyx@gmail.com | ||
| Author-email: mcsinyx@disroot.org | ||
| License: LGPLv3+ | ||
@@ -9,0 +9,0 @@ Description: # palace |
+2
-2
| [metadata] | ||
| name = palace | ||
| version = 0.1.1 | ||
| version = 0.1.2 | ||
| url = https://github.com/McSinyx/palace | ||
| author = Nguyễn Gia Phong | ||
| author_email = vn.mcsinyx@gmail.com | ||
| author_email = mcsinyx@disroot.org | ||
| classifiers = | ||
@@ -8,0 +8,0 @@ Development Status :: 3 - Alpha |
+1
-7
@@ -171,9 +171,3 @@ # Cython declarations of alure | ||
| cdef enum DistanceModel: | ||
| INVERSE_CLAMPED 'alure::DistanceModel::InverseClamped' | ||
| LINEAR_CLAMPED 'alure::DistanceModel::LinearClamped' | ||
| EXPONENT_CLAMPED 'alure::DistanceModel::ExponentClamped' | ||
| INVERSE 'alure::DistanceModel::Inverse' | ||
| LINEAR 'alure::DistanceModel::Linear' | ||
| EXPONENT 'alure::DistanceModel::Exponent' | ||
| NONE 'alure::DistanceModel::None' | ||
| pass | ||
@@ -180,0 +174,0 @@ cdef enum Spatialize: |
+9
-0
@@ -50,2 +50,11 @@ // Helper functions and mappings | ||
| const std::map<std::string, alure::DistanceModel> DISTANCE_MODELS { | ||
| {"inverse clamped", alure::DistanceModel::InverseClamped}, | ||
| {"linear clamped", alure::DistanceModel::LinearClamped}, | ||
| {"exponent clamped", alure::DistanceModel::ExponentClamped}, | ||
| {"inverse", alure::DistanceModel::Inverse}, | ||
| {"linear", alure::DistanceModel::Linear}, | ||
| {"exponent", alure::DistanceModel::Exponent}, | ||
| {"none", alure::DistanceModel::None}}; | ||
| // This is ported from alure-reverb example. | ||
@@ -52,0 +61,0 @@ #define DECL(x) { #x, EFX_REVERB_PRESET_##x } |
+4
-2
@@ -25,4 +25,5 @@ # Helper functions and mappings | ||
| from alure cimport (AttributePair, EFXEAXREVERBPROPERTIES, # noqa | ||
| FilterParams, ChannelConfig, SampleType, Vector3) | ||
| from alure cimport ( # noqa | ||
| AttributePair, EFXEAXREVERBPROPERTIES, FilterParams, | ||
| ChannelConfig, SampleType, DistanceModel, Vector3) | ||
@@ -34,2 +35,3 @@ | ||
| cdef const map[string, ChannelConfig] CHANNEL_CONFIGS | ||
| cdef const map[string, DistanceModel] DISTANCE_MODELS | ||
| cdef vector[string] reverb_presets() | ||
@@ -36,0 +38,0 @@ cdef vector[AttributePair] mkattrs(vector[pair[int, int]]) |
| # Source pytest module | ||
| # Copyright (C) 2020 Ngô Ngọc Đức Huy | ||
| # Copyright (C) 2020 Nguyễn Gia Phong | ||
| # Copyright (C) 2020 Ngô Xuân Minh | ||
| # | ||
@@ -22,5 +23,8 @@ # This file is part of palace. | ||
| from palace import current_context, Context, MessageHandler | ||
| from palace import current_context, distance_models, Context, MessageHandler | ||
| from pytest import raises | ||
| from math import inf | ||
| def test_with_context(device): | ||
@@ -52,1 +56,43 @@ """Test if `with` can be used to start a context | ||
| assert current_context().message_handler is context.message_handler | ||
| def test_async_wake_interval(device): | ||
| """Test read-write property async_wake_interval.""" | ||
| with Context(device) as context: | ||
| context.async_wake_interval = 42 | ||
| assert context.async_wake_interval == 42 | ||
| def test_default_resampler_index(device): | ||
| """Test return values default_resampler_index.""" | ||
| with Context(device) as context: | ||
| index = context.default_resampler_index | ||
| assert index >= 0 | ||
| assert len(context.available_resamplers) > index | ||
| def test_doppler_factor(device): | ||
| """Test write property doppler_factor.""" | ||
| with Context(device) as context: | ||
| context.doppler_factor = 4/9 | ||
| context.doppler_factor = 9/4 | ||
| context.doppler_factor = 0 | ||
| context.doppler_factor = inf | ||
| with raises(ValueError): context.doppler_factor = -1 | ||
| def test_speed_of_sound(device): | ||
| """Test write property speed_of_sound.""" | ||
| with Context(device) as context: | ||
| context.speed_of_sound = 5/7 | ||
| context.speed_of_sound = 7/5 | ||
| with raises(ValueError): context.speed_of_sound = 0 | ||
| context.speed_of_sound = inf | ||
| with raises(ValueError): context.speed_of_sound = -1 | ||
| def test_distance_model(device): | ||
| """Test preset values distance_model.""" | ||
| with Context(device) as context: | ||
| for model in distance_models: context.distance_model = model | ||
| with raises(ValueError): context.distance_model = 'EYYYYLMAO' |
@@ -43,3 +43,3 @@ # Source pytest module | ||
| def test_priority(context): | ||
| """Test read-write property group.""" | ||
| """Test read-write property priority.""" | ||
| with Source(context) as source: | ||
@@ -46,0 +46,0 @@ assert source.priority == 0 |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
31
3.33%911
14.74%3171556
-10.38%