Source code for pliers.stimuli.audio

''' Classes that represent audio clips. '''

from moviepy.audio.io.AudioFileClip import AudioFileClip
from moviepy.video.io.ffmpeg_reader import ffmpeg_parse_infos

from .base import Stim


[docs]class AudioStim(Stim): ''' Represents an audio clip. Args: filename (str): Path to audio file. onset (float): Optional onset of the audio file (in seconds) with respect to some more general context or timeline the user wishes to keep track of. sampling_rate (int): Sampling rate of clip, in hertz. url (str): Optional url to read contents from. clip (AudioFileClip): Optional moviepy AudioFileClip to initialize from. order (int): Optional sequential index of the AudioStim within some containing context. ''' _default_file_extension = '.wav'
[docs] def __init__(self, filename=None, onset=None, sampling_rate=None, url=None, clip=None, order=None): if url is not None: filename = url self.filename = filename if clip: self.sampling_rate = clip.fps self.clip = clip else: self.sampling_rate = sampling_rate if not self.sampling_rate: self.sampling_rate = self.get_sampling_rate(self.filename) self._load_clip() # Small default buffer isn't ideal, but moviepy has persistent issues # with some files otherwise; see # https://github.com/Zulko/moviepy/issues/246 self.data = self.clip.to_soundarray(buffersize=1000) duration = self.clip.duration if self.data.ndim > 1: # Average channels to make data mono self.data = self.data.mean(axis=1) super().__init__( filename, onset=onset, duration=duration, order=order, url=url)
def _load_clip(self): self.clip = AudioFileClip(self.filename, fps=self.sampling_rate)
[docs] @staticmethod def get_sampling_rate(filename): ''' Use moviepy/FFMPEG to get the sampling rate ''' infos = ffmpeg_parse_infos(filename) fps = infos.get('audio_fps', 44100) if fps == 'unknown': fps = 44100 return fps
def __getstate__(self): d = self.__dict__.copy() d['clip'] = None return d def __setstate__(self, d): self.__dict__ = d self._load_clip()
[docs] def save(self, path): ''' Save clip data to file. Args: path (str): Filename to save audio data to. ''' self.clip.write_audiofile(path, fps=self.sampling_rate)