def play_excerpt(input_file, duration=5, use_fade=False, remove_silence=False): """Play an excerpt of an audio file. Parameters ---------- input_file : str Audio file to play. duration : float Length of excerpt in seconds. use_fade : bool If true, apply a fade in and fade out. remove_silence: bool If true, forces entire segment to have sound by removing silence. """ ext = util.fileext(input_file) tmp_file = util.temp_file(ext) if remove_silence: remove_silence(input_file, tmp_file) else: tmp_file = input_file if not use_fade: play(tmp_file, end_t=duration) else: tmp_file2 = util.temp_file(ext) fade(tmp_file, tmp_file2, fade_in_time=0.5, fade_out_time=1) play(tmp_file2, end_t=duration)
def trim(input_file, output_file, start_time, end_time): """Excerpt a clip from an audio file, given a start and end time. Parameters ---------- input_file : str Sound file to trim. output_file : str File for writing output. start_time : float Start time of the clip. end_time : float End time of the clip. Returns ------- status : bool True on success. """ assert start_time >= 0, "The value for 'start_time' must be positive." assert end_time >= 0, "The value for 'end_time' must be positive." inplace = not bool(output_file) if inplace: output_file = util.temp_file(os.path.splitext(input_file)[-1]) status = _sox(['sox', input_file, output_file, 'trim', '%0.8f' % start_time, '%0.8f' % (end_time - start_time)]) if inplace: os.rename(output_file, input_file) return status
def test_trim(self): output_file = util.temp_file(formats.WAVE) self.assert_( sox.trim(input_file=self.input_file, output_file=output_file, start_time=0, end_time=0.1), "Conversion failed.")
def test_trim_inplace(self): another_file = util.temp_file(formats.WAVE) shutil.copy(self.input_file, another_file) self.assert_( sox.trim(input_file=another_file, output_file=None, start_time=0, end_time=0.1), "Conversion failed.") self.assert_(os.path.exists(another_file))
def test_convert_samplerate(self): output_file = util.temp_file(formats.WAVE) self.assert_( sox.convert(input_file=self.input_file, output_file=output_file, samplerate=self.samplerate / 2, channels=self.channels, bytedepth=self.bytedepth), "Conversion with different samplerate failed.") wav_handle = wave.open(output_file, mode='r') self.assertEqual(self.samplerate / 2, wav_handle.getframerate(), "Samplerate conversion failed.")
def __init__(self, filepath, samplerate=None, channels=None, bytedepth=None, mode="r"): """Base class for interfacing with audio files. When writing audio files, samplerate, channels, and bytedepth must be specified. Otherwise, these parameters may be None when reading to use the default values of the audio file. Parameters ---------- filepath : str Absolute path to a sound file. Does not need to exist (yet). samplerate : float, default=None Samplerate for the audio file. channels : int, default=None Number of channels for the audio file. bytedepth : int, default=None bytedepth (in bytes) of the returned file. For example, CD-quality audio has a bytedepth of 2 (16-bit). mode : str, default='r' Open the file for [r]eading or [w]riting. """ logging.debug(util.classy_print(AudioFile, "Constructor.")) if not sox.is_valid_file_format(filepath): raise ValueError("Cannot handle this filetype: {}" "".format(filepath)) if mode == "w": # TODO: If/raise assert samplerate, "Writing audiofiles requires a samplerate." assert channels, "Writing audiofiles requires channels." assert bytedepth, "Writing audiofiles requires a bytedepth." self._filepath = filepath self._wave_handle = None self._temp_filepath = util.temp_file(formats.WAVE) self._mode = mode logging.debug(util.classy_print(AudioFile, "Opening wave file.")) self.__get_handle__(self.filepath, samplerate, channels, bytedepth) logging.debug(util.classy_print(AudioFile, "Success!")) if self.duration == 0: warnings.warn("Caution: You have opened an empty sound file!")
def convert(input_file, output_file, samplerate=None, channels=None, bytedepth=None): """Converts one audio file to another on disk. Parameters ---------- input_file : str Input file to convert. output_file : str Output file to writer. samplerate : float, default=None Desired samplerate. If None, defaults to the same as input. channels : int, default=None Desired channels. If None, defaults to the same as input. bytedepth : int, default=None Desired bytedepth. If None, defaults to the same as input. Returns ------- status : bool True on success. """ args = ['sox', '--no-dither', input_file] if bytedepth: assert bytedepth in [1, 2, 3, 4, 8] args += ['-b%d' % (bytedepth * 8)] if channels: args += ['-c %d' % channels] if output_file is None: output_file = util.temp_file(formats.WAVE) args += [output_file] if samplerate: args += ['rate', '-I', '%f' % samplerate] return _sox(args)
def write(filepath, signal, samplerate=44100, bytedepth=2): """Write an audio signal to disk. Parameters ---------- filepath: str Path to an audio file. signal : np.ndarray, ndim in [1,2] Audio signal to write to disk. samplerate: scalar, or None for file's default Samplerate for the returned audio signal. bytedepth : int, default=2 Number of bytes for the audio signal; must be 2. """ if bytedepth != 2: raise NotImplementedError("Currently only 16-bit audio is supported.") tmp_file = util.temp_file(formats.WAVE) if formats.WAVE == os.path.splitext(filepath)[-1].strip('.'): tmp_file = filepath signal = np.asarray(signal) signal = signal.reshape(-1, 1) if signal.ndim == 1 else signal fp = wave.open(tmp_file, 'w') fp.setnchannels(signal.shape[-1]) fp.setsampwidth(bytedepth) fp.setframerate(samplerate) fp.writeframes(util.array_to_byte_string(signal, bytedepth)) fp.close() if tmp_file != filepath: sox.convert(tmp_file, filepath)