From c8c5f740d331e1f5855ed1db9c0c53c3f76fd5cd Mon Sep 17 00:00:00 2001 From: dev-jam Date: Mon, 6 Jun 2022 14:33:28 +0200 Subject: [PATCH] fixed period size bug --- .../audio_low_latency_play.py | 86 ++++++------------- .../audio_low_latency_play_init.py | 23 ++--- .../audio_low_latency_play_start.py | 74 ++++++---------- .../audio_low_latency_record_init.py | 8 +- .../audio_low_latency_record_start.py | 2 +- 5 files changed, 69 insertions(+), 124 deletions(-) diff --git a/opensesame_plugins/audio_low_latency_play/audio_low_latency_play.py b/opensesame_plugins/audio_low_latency_play/audio_low_latency_play.py index 7087dbe..c6e101d 100644 --- a/opensesame_plugins/audio_low_latency_play/audio_low_latency_play.py +++ b/opensesame_plugins/audio_low_latency_play/audio_low_latency_play.py @@ -215,11 +215,10 @@ def run(self): self.show_message(u'Initializing audio playback') - if self.ram_cache == u'No': - self.play_file(self.device, self.wav_file, self.period_size, delay) + if self.ram_cache == u'no': + self.play(self.device, self.wav_file, self.period_size, delay) elif self.ram_cache == u'yes': - self.play_data(self.device, self.wav_file_data, self.data_size, delay) - + self.play(self.device, self.wav_file, self.data_size, delay, self.wav_file_data) elif self.dummy_mode == u'yes': self.set_stimulus_onset() @@ -228,58 +227,17 @@ def run(self): raise osexception(u'Error with dummy mode!') - def play_file(self, stream, wav_file, chunk, delay): - - # Read data from wave - data = wav_file.readframes(chunk) - - if self.delay_check: - if delay >= 1: - self.show_message(u'Delaying audio playback for %d ms' % (delay)) - self.clock.sleep(delay) - self.show_message(u'Delay done') - - start_time = self.set_stimulus_onset() - - self.show_message(u'Starting audio playback') + def play(self, stream, wav_file, chunk, delay, wav_data=None): - while len(data) > 0: - - # write data to device - stream.write(data) + start = 0 + if self.ram_cache == u'no': # Read data from wave data = wav_file.readframes(chunk) + elif self.ram_cache == u'yes': + data = wav_data[start:start+chunk] - # check for stop/pause/resume key - if self.pause_resume != u'' or self.stop != u'': - self.check_keys() - - while self.play_execute_pause == 1 and self.play_continue == 1: - if self.pause_resume != u'' or self.stop != u'': - self.check_keys() - - if self.play_continue == 0: - break - elif self.duration_check: - if self.clock.time() - start_time >= self.duration: - break - - if self.play_continue == 0: - break - elif self.duration_check: - if self.clock.time() - start_time >= self.duration: - self.show_message(u'Audio stopped, duration exceeded') - break - - self.set_stimulus_offset() - - wav_file.close() - - self.show_message(u'Finished audio playback') - - - def play_data(self, stream, wav_data, chunk, delay): + self.show_message(u'Chunk size: %d bytes' % (len(data))) if self.delay_check: if delay >= 1: @@ -291,10 +249,21 @@ def play_data(self, stream, wav_data, chunk, delay): self.show_message(u'Starting audio playback') - for start in range(0,len(wav_data),chunk): + while len(data) > 0: # write data to device - stream.write(wav_data[start:start+chunk]) + stream.write(data) + + if self.ram_cache == u'no': + # Read data from wave + data = wav_file.readframes(chunk) + elif self.ram_cache == u'yes': + if len(wav_data) >= start+chunk: + data = wav_data[start:start+chunk] + elif len(wav_data) < start+chunk: + data = wav_data[start:len(wav_data)] + + start += chunk # check for stop/pause/resume key if self.pause_resume != u'' or self.stop != u'': @@ -308,17 +277,14 @@ def play_data(self, stream, wav_data, chunk, delay): break elif self.duration_check: if self.clock.time() - start_time >= self.duration: - break - - if self.play_continue == 0: - break - elif self.duration_check: - if self.clock.time() - start_time >= self.duration: - self.show_message(u'Audio stopped, duration exceeded') + self.show_message(u'Audio playback stopped, duration exceeded') break self.set_stimulus_offset() + if self.ram_cache == u'no': + wav_file.close() + self.show_message(u'Finished audio playback') diff --git a/opensesame_plugins/audio_low_latency_play_init/audio_low_latency_play_init.py b/opensesame_plugins/audio_low_latency_play_init/audio_low_latency_play_init.py index 58c01f3..7e4d189 100644 --- a/opensesame_plugins/audio_low_latency_play_init/audio_low_latency_play_init.py +++ b/opensesame_plugins/audio_low_latency_play_init/audio_low_latency_play_init.py @@ -59,7 +59,7 @@ def reset(self): self.var.bitdepth = str(16) self.var.samplerate = str(44100) self.var.channels = str(2) - self.var.period_size = 128 + self.var.period_size = 1024 self.experiment.audio_low_latency_play_module_list = list() self.experiment.audio_low_latency_play_device_dict = dict() @@ -167,7 +167,7 @@ def init_var(self): else: raise osexception(u'Period size value should be a integer') - self.frame_size = self.bitdepth * self.channels + self.frame_size = self.bitdepth * self.channels // 8 self.data_size = self.frame_size * self.period_size self.period_size_time = round(float(self.period_size) / float(self.samplerate) * 1000, 1) @@ -230,12 +230,6 @@ def prepare(self): import alsaaudio self.device_index = self.experiment.audio_low_latency_play_device_dict[self.pyalsaaudio_module_name].index(self.device_name) - # self.device = alsaaudio.PCM(type=alsaaudio.PCM_PLAYBACK, - # device=self.device_name, - # channels=self.channels, - # rate=self.samplerate, - # periodsize=self.period_size) - self.device = alsaaudio.PCM(type=alsaaudio.PCM_PLAYBACK, device=self.device_name) channels_set = self.device.setchannels(self.channels) @@ -261,6 +255,14 @@ def prepare(self): except Exception as e: error_msg_list.append(error_msg_bitdepth) + # self.device = alsaaudio.PCM(type=alsaaudio.PCM_PLAYBACK, + # format=format_audio, + # device=self.device_name, + # channels=self.channels, + # rate=self.samplerate, + # periodsize=self.period_size) + + if channels_set != self.channels: error_msg_list.append(u'%d channel(s) not supported\n' % (self.channels)) if samplerate_set != self.samplerate: @@ -344,7 +346,8 @@ def prepare(self): self.period_size = self.device.bufsize() self.period_size_time = round(float(self.period_size) / float(self.samplerate) * 1000, 1) - self.data_size = self.frame_size * self.period_size + self.data_size = self.frame_size * self.period_size // 8 + #self.data_size = self.frame_size * self.period_size self.experiment.audio_low_latency_play_period_size = self.period_size self.experiment.audio_low_latency_play_data_size = self.data_size @@ -353,7 +356,7 @@ def prepare(self): print('Overruling period size with hardware buffer for OSS4, using: ' + str(self.period_size) + ' frames or ' + str(self.period_size_time) + 'ms') self.experiment.audio_low_latency_play_device = self.device - #self.experiment.cleanup_functions.append(self.close) + self.experiment.cleanup_functions.append(self.close) self.python_workspace[u'audio_low_latency_play'] = self.experiment.audio_low_latency_play_device diff --git a/opensesame_plugins/audio_low_latency_play_start/audio_low_latency_play_start.py b/opensesame_plugins/audio_low_latency_play_start/audio_low_latency_play_start.py index 33f4b47..d1cce49 100644 --- a/opensesame_plugins/audio_low_latency_play_start/audio_low_latency_play_start.py +++ b/opensesame_plugins/audio_low_latency_play_start/audio_low_latency_play_start.py @@ -126,7 +126,6 @@ def prepare(self): error_msg = u'Duration must be a string named sound or a an integer greater than 1' - try: self.show_message(u'\n') self.show_message(u'Loading sound file: '+self.filename+' ...') @@ -222,12 +221,13 @@ def run(self): self.kb.flush() self.show_message(u'Initializing audio playback') + self.experiment.audio_low_latency_play_locked = 1 if self.ram_cache == u'no': - self.experiment.audio_low_latency_play_thread = threading.Thread(target=self.play_file, args=(self.device, self.wav_file, self.period_size, delay)) + self.experiment.audio_low_latency_play_thread = threading.Thread(target=self.play, args=(self.device, self.wav_file, self.period_size, delay)) elif self.ram_cache == u'yes': - self.experiment.audio_low_latency_play_thread = threading.Thread(target=self.play_data, args=(self.device, self.wav_file_data, self.data_size, delay)) + self.experiment.audio_low_latency_play_thread = threading.Thread(target=self.play, args=(self.device, self.wav_file, self.data_size, delay, self.wav_file_data)) self.experiment.audio_low_latency_play_thread.start() @@ -238,12 +238,19 @@ def run(self): raise osexception(u'Error with dummy mode!') - def play_file(self, stream, wav_file, chunk, delay): + def play(self, stream, wav_file, chunk, delay, wav_data=None): self.experiment.audio_low_latency_play_thread_running = 1 - # Read data from wave - data = wav_file.readframes(chunk) + start = 0 + + if self.ram_cache == u'no': + # Read data from wave + data = wav_file.readframes(chunk) + elif self.ram_cache == u'yes': + data = wav_data[start:start+chunk] + + self.show_message(u'Chunk size: %d bytes' % (len(data))) if self.delay_check: if delay >= 1: @@ -260,8 +267,16 @@ def play_file(self, stream, wav_file, chunk, delay): # write data to device stream.write(data) - # Read data from wave - data = wav_file.readframes(chunk) + if self.ram_cache == u'no': + # Read data from wave + data = wav_file.readframes(chunk) + elif self.ram_cache == u'yes': + if len(wav_data) >= start+chunk: + data = wav_data[start:start+chunk] + elif len(wav_data) < start+chunk: + data = wav_data[start:len(wav_data)] + + start += chunk # check for stop/pause/resume key if self.pause_resume != u'' or self.stop != u'': @@ -280,47 +295,8 @@ def play_file(self, stream, wav_file, chunk, delay): self.set_stimulus_offset() - wav_file.close() - - self.show_message(u'Finished audio playback') - self.experiment.audio_low_latency_play_locked = 0 - - - def play_data(self, stream, wav_data, chunk, delay): - - self.experiment.audio_low_latency_play_thread_running = 1 - - if self.delay_check: - if delay >= 1: - self.show_message(u'Delaying audio playback for %d ms' % (delay)) - self.clock.sleep(delay) - self.show_message(u'Delay done') - - start_time = self.set_stimulus_onset() - - self.show_message(u'Starting audio playback') - - for start in range(0,len(wav_data),chunk): - - # write data to device - stream.write(wav_data[start:start+chunk]) - - # check for stop/pause/resume key - if self.pause_resume != u'' or self.stop != u'': - self.check_keys() - - while self.experiment.audio_low_latency_play_execute_pause == 1 and self.experiment.audio_low_latency_play_continue == 1: - if self.pause_resume != u'' or self.stop != u'': - self.check_keys() - - if self.experiment.audio_low_latency_play_continue == 0: - break - elif self.duration_check: - if self.clock.time() - start_time >= self.duration: - self.show_message(u'Audio stopped, duration exceeded') - break - - self.set_stimulus_offset() + if self.ram_cache == u'no': + wav_file.close() self.show_message(u'Finished audio playback') self.experiment.audio_low_latency_play_locked = 0 diff --git a/opensesame_plugins/audio_low_latency_record_init/audio_low_latency_record_init.py b/opensesame_plugins/audio_low_latency_record_init/audio_low_latency_record_init.py index c9886d2..3f7407f 100644 --- a/opensesame_plugins/audio_low_latency_record_init/audio_low_latency_record_init.py +++ b/opensesame_plugins/audio_low_latency_record_init/audio_low_latency_record_init.py @@ -59,7 +59,7 @@ def reset(self): self.var.bitdepth = str(16) self.var.samplerate = str(44100) self.var.channels = str(2) - self.var.period_size = 128 + self.var.period_size = 1024 self.experiment.audio_low_latency_record_module_list = list() self.experiment.audio_low_latency_record_device_dict = dict() @@ -169,7 +169,7 @@ def init_var(self): raise osexception(u'Period size value should be a integer') self.frame_size = self.bitdepth * self.channels - self.data_size = self.frame_size * self.period_size + self.data_size = self.frame_size * self.period_size // 8 self.period_size_time = round(float(self.period_size) / float(self.samplerate) * 1000, 1) self.experiment.audio_low_latency_record_dummy_mode = self.dummy_mode @@ -344,7 +344,7 @@ def prepare(self): self.period_size = self.device.bufsize() self.period_size_time = round(float(self.period_size) / float(self.samplerate) * 1000, 1) - self.data_size = self.frame_size * self.period_size + self.data_size = self.frame_size * self.period_size // 8 self.experiment.audio_low_latency_record_period_size = self.period_size self.experiment.audio_low_latency_record_data_size = self.data_size @@ -353,7 +353,7 @@ def prepare(self): print('Overruling period size with hardware buffer for OSS4, using: ' + str(self.period_size) + ' frames or ' + str(self.period_size_time) + 'ms') self.experiment.audio_low_latency_record_device = self.device - #self.experiment.cleanup_functions.append(self.close) + self.experiment.cleanup_functions.append(self.close) self.python_workspace[u'audio_low_latency_record'] = self.experiment.audio_low_latency_record_device elif self.dummy_mode == u'yes': diff --git a/opensesame_plugins/audio_low_latency_record_start/audio_low_latency_record_start.py b/opensesame_plugins/audio_low_latency_record_start/audio_low_latency_record_start.py index 609f1cc..d7ad022 100644 --- a/opensesame_plugins/audio_low_latency_record_start/audio_low_latency_record_start.py +++ b/opensesame_plugins/audio_low_latency_record_start/audio_low_latency_record_start.py @@ -284,7 +284,7 @@ def process_data(self, stream, wav_file, chunk, frames): desc: Process data. """ - + # Read data from device if self.module == self.experiment.pyalsaaudio_module_name: l, data = stream.read()