Skip to content

Commit

Permalink
fixed period size bug
Browse files Browse the repository at this point in the history
  • Loading branch information
dev-jam committed Jun 6, 2022
1 parent 3add93d commit c8c5f74
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 124 deletions.
86 changes: 26 additions & 60 deletions opensesame_plugins/audio_low_latency_play/audio_low_latency_play.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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:
Expand All @@ -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'':
Expand All @@ -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')


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)
Expand All @@ -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:
Expand Down Expand Up @@ -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
Expand All @@ -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


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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+' ...')
Expand Down Expand Up @@ -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()

Expand All @@ -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:
Expand All @@ -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'':
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit c8c5f74

Please sign in to comment.