From: Ismaël Bouya Date: Sun, 17 Jul 2016 11:00:29 +0000 (+0200) Subject: Add new configurations parameters X-Git-Tag: 1.0.0~51 X-Git-Url: https://git.immae.eu/?p=perso%2FImmae%2FProjets%2FPython%2FMusicSampler.git;a=commitdiff_plain;h=75d6cdbac628b57e206cd37808c1d3c7fecbb9eb Add new configurations parameters --- diff --git a/helpers/__init__.py b/helpers/__init__.py index 4b9529d..807aa44 100644 --- a/helpers/__init__.py +++ b/helpers/__init__.py @@ -6,11 +6,7 @@ import math import sounddevice as sd class Config: - def __init__(self, **kwargs): - for arg in kwargs: - setattr(self, arg, kwargs[arg]) - -config = Config(yml_file="config.yml") + pass def path(): if getattr(sys, 'frozen', False): @@ -29,11 +25,37 @@ def parse_args(): sys.argv.extend(kivy_args) - parser = argparse.ArgumentParser(description="A Music Sampler application.") + parser = argparse.ArgumentParser( + description="A Music Sampler application.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument("-c", "--config", default="config.yml", required=False, help="Config file to load") + parser.add_argument("-l", "--latency", + default="high", + required=False, + help="Latency: low, high or number of seconds") + parser.add_argument("-b", "--blocksize", + default=0, + type=int, + required=False, + help="Blocksize: If not 0, the numbe of frames to take at each step for the mixer") + parser.add_argument("-f", "--frame-rate", + default=44100, + type=int, + required=False, + help="Frame rate to play the musics") + parser.add_argument("-x", "--channels", + default=2, + type=int, + required=False, + help="Number of channels to use") + parser.add_argument("-s", "--sample-width", + default=2, + type=int, + required=False, + help="Sample width (number of bytes for each frame)") parser.add_argument("-V", "--version", action="version", help="Displays the current version and exits. Only use in bundled package", @@ -52,7 +74,12 @@ def parse_args(): help="Kivy arguments. All arguments after this are interpreted by Kivy. Pass \"-- --help\" to get Kivy's usage.") args = parser.parse_args(argv) - config.yml_file = args.config + Config.yml_file = args.config + Config.latency = args.latency + Config.blocksize = args.blocksize + Config.frame_rate = args.frame_rate + Config.channels = args.channels + Config.sample_width = args.sample_width class SelectDeviceAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): @@ -71,9 +98,6 @@ def show_version(): else: return "option '-v' can only be used in bundled package" -def yml_file(): - return config.yml_file - def duration_to_min_sec(duration): minutes = int(duration / 60) seconds = int(duration) % 60 diff --git a/helpers/mapping.py b/helpers/mapping.py index 60c7691..8e0265c 100644 --- a/helpers/mapping.py +++ b/helpers/mapping.py @@ -9,7 +9,7 @@ import sys from .music_file import * from .mixer import Mixer -from . import yml_file,gain +from . import Config, gain class Mapping(RelativeLayout): expected_keys = NumericProperty(0) @@ -17,6 +17,7 @@ class Mapping(RelativeLayout): ready_color = ListProperty([1, 165/255, 0, 1]) def __init__(self, **kwargs): + self.mixer = Mixer() self.key_config, self.open_files = self.parse_config() super(Mapping, self).__init__(**kwargs) self._keyboard = Window.request_keyboard(self._keyboard_closed, self) @@ -24,8 +25,6 @@ class Mapping(RelativeLayout): self.running = [] Clock.schedule_interval(self.not_all_keys_ready, 1) - self.mixer = Mixer() - @property def master_gain(self): return gain(self.master_volume) @@ -83,7 +82,7 @@ class Mapping(RelativeLayout): self.running.remove((key, start_time)) def parse_config(self): - stream = open(yml_file(), "r") + stream = open(Config.yml_file, "r") config = yaml.load(stream) stream.close() diff --git a/helpers/mixer.py b/helpers/mixer.py index 9e8179a..d08520a 100644 --- a/helpers/mixer.py +++ b/helpers/mixer.py @@ -2,17 +2,28 @@ import sounddevice as sd import audioop import time -frame_rate = 44100 -channels = 2 -sample_width = 2 +from . import Config + +sample_width = Config.sample_width +def sample_width_to_dtype(sample_width): + if sample_width == 1 or sample_width == 2 or sample_width == 4: + return 'int' + str(8*sample_width) + else: + raise "Unknown sample width" + +def _latency(latency): + if latency == "high" or latency == "low": + return latency + else: + return float(latency) class Mixer: def __init__(self): - self.stream = sd.RawOutputStream(samplerate=frame_rate, - channels=channels, - dtype='int' + str(8*sample_width), # FIXME: ? - latency="high", - blocksize=5000, + self.stream = sd.RawOutputStream(samplerate=Config.frame_rate, + channels=Config.channels, + dtype=sample_width_to_dtype(Config.sample_width), + latency=_latency(Config.latency), + blocksize=Config.blocksize, callback=self.play_callback, ) self.open_files = [] diff --git a/helpers/music_file.py b/helpers/music_file.py index 6da547b..f1aa341 100644 --- a/helpers/music_file.py +++ b/helpers/music_file.py @@ -6,7 +6,7 @@ from transitions.extensions import HierarchicalMachine as Machine import os.path from .lock import Lock -from . import gain +from . import Config, gain file_lock = Lock("file") @@ -48,7 +48,7 @@ class MusicFile(Machine): try: print("Loading « {} »".format(self.name)) db_gain = gain(self.volume_factor * 100) - self.audio_segment = pydub.AudioSegment.from_file(self.filename).set_frame_rate(44100).set_channels(2).set_sample_width(2).apply_gain(db_gain) + self.audio_segment = pydub.AudioSegment.from_file(self.filename).set_frame_rate(Config.frame_rate).set_channels(Config.channels).set_sample_width(Config.sample_width).apply_gain(db_gain) self.audio_segment_frame_width = self.audio_segment.frame_width self.sound_duration = self.audio_segment.duration_seconds except Exception as e: @@ -121,6 +121,7 @@ class MusicFile(Machine): data += new_data nb_frames += new_nb_frames elif nb_frames == 0: + # FIXME: too slow threading.Thread(name = "MSFinishedCallback", target=self.finished_callback).start() return data.ljust(out_data_length, b'\0')