def __enter__(self): """Allow AudioFile object to be opened by 'with' statements""" self.logger.debug("Opening soundfile {0}".format(self.filepath)) if self.mode == 'r': if not os.path.exists(self.filepath): raise IOError( "Cannot open {0} for reading as it cannot be " "found.".format(self.filepath) ) self.pysndfile_object = pysndfile.PySndfile( self.filepath, mode=self.mode ) self.samplerate = self.get_samplerate() self.format = self.get_format() self.channels = self.get_channels() self.frames = self.get_frames() return self else: self.pysndfile_object = pysndfile.PySndfile( self.filepath, mode=self.mode, format=self.format, channels=self.channels, samplerate=self.samplerate ) return self
def main(): files = [ ("left ear", "left_ear.wav"), ("right ear", "right_ear.wav"), ] fig = plt.figure() for label, fname in files: sndfile = pysndfile.PySndfile(fname, 'r') if sndfile.channels() != 1: raise RuntimeError('please only load mono files') Fs = sndfile.samplerate() signal = sndfile.read_frames() time = np.arange(len(signal)) / float(Fs) plt.plot(time, signal, label=label) plt.legend(loc='lower center', ncol=2) plt.xlim([0.04, 0.07]) plt.xlabel('time / s') plt.ylabel('amplitude') plt.suptitle('Comparison of Left and Right Ear Responses') #plt.tight_layout() plt.show() if render: plt.savefig('binaural_signals.svg', bbox_inches='tight', dpi=96, format='svg')
def sndreadmono(path: str, chan: int = 0, contiguous=True) -> t.Tuple[np.ndarray, int]: """ Read a sound file as mono. If the soundfile is multichannel, the indicated channel `chan` is returned. path: str The path to the soundfile chan: int The channel to return if the file is multichannel contiuous: bool If True, it is ensured that the returned array is contiguous This should be set to True if the samples are to be passed to `analyze`, which expects a contiguous array Returns: a tuple (samples:np.ndarray, sr:int) """ snd = pysndfile.PySndfile(path) data = snd.read_frames(snd.frames()) sr = snd.samplerate() if len(data.shape) == 1: mono = data else: mono = data[:, chan] if contiguous: mono = np.ascontiguousarray(mono) return (mono, sr)
def save_wave(self, filename): # outinfo = pysndfile.construct_format(samplerate=self.samplerate, # channels=1, # format=(pysndfile.SF_FORMAT_WAV | pysndfile.SF_FORMAT_PCM_16), # sections=1, # seekable=1) o_sfile = pysndfile.PySndfile(filename, mode="w", format='wav') self.sfile.seek(self.f_start, 0) r = self.sfile.readf_double( self.f_end - self.f_start) # read the sound file from f_start to f_end r = r / max(abs(r)) # to be between 0 and 1 ? # deal with stereo ch = self.sfile.info.channels # we force into mono by recalling the method we used for the extraction if ch == 2: if self.method == 2: nr = 0.5 * (r[::2] + r[1::2]) else: nr = r[self.method::2] else: nr = r o_sfile.write_frames(nr)
def save(self, filename, buffersize=0b10000000000): """Saves an audio instance to a file. Parameters ---------- filename : str System disk path in which the file will be saved. buffsize : int, optional Number of bytes stored in memory buffer while reading and writing. Only used if the filename to write has been created opening from a file in disk. """ with snd.PySndfile( filename, "w", format=65536 | 2, channels=self.n_channels, samplerate=self.fps, ) as target_file: target_file.set_strings(self.metadata or {}) if self.filename: for frames in self.iter_chunks(buffersize=buffersize): target_file.write_frames(frames) else: target_file.write_frames(self.dataframes) self.filename = filename
def modal_analysis(fnames, max_frequency, room_dim=None): plt.figure() for fname in fnames: sndfile = pysndfile.PySndfile(fname, 'r') if sndfile.channels() != 1: raise RuntimeError('please only load mono files') n = sndfile.frames() sr = sndfile.samplerate() samples = sndfile.read_frames() fft = np.abs(np.fft.rfft(samples)) freqs = np.fft.rfftfreq(n, d=1. / sr) mask = freqs < max_frequency fft = 20 * np.log10(fft[mask]) freqs = freqs[mask] plt.plot(freqs, fft, label=os.path.basename(fname)) if room_dim is not None: ranges = [[(x / i) ** 2 for x in range(10)] for i in room_dim] all_frequencies = [(SPEED_OF_SOUND / 2) * np.sqrt(a + b + c) for a, b, c in itertools.product(*ranges)] filtered_frequencies = [i for i in all_frequencies if i < max_frequency] for f in filtered_frequencies: plt.axvline(f) plt.legend() plt.show()
def sndwrite(samples: np.ndarray, sr: int, path: str, encoding=None) -> None: """ samples: the samples to write sr: the samplerate path: the outfile to write the samples to (the extension will determine the format) encoding: the encoding of the samples. If None, a default is used, according to the extension of the outfile given. Otherwise, a tuple like ('float', 32) or ('pcm', 24) is expected (also a string of the form "float32" is supported). Of course, not all encodings are supported by each format """ ext = os.path.splitext(path)[1].lower() if encoding is None: encoding = { '.wav': ('float', 32), '.aif': ('float', 32), '.flac': ('pcm', 24) }.get(ext) if encoding is None: raise ValueError(f"format {ext} not supported") fmt = _sndfile_format(ext, encoding) numchannels = 1 if len(samples.shape) == 1 else samples.shape[-1] snd = pysndfile.PySndfile(path, mode='w', format=fmt, channels=numchannels, samplerate=sr) snd.write_frames(samples) snd.writeSync()
def get_max_level(filename): max_value = 0 buffer_size = 4096 audio_file = pysndfile.PySndfile(filename, 'r') n_samples_left = audio_file.frames() while n_samples_left: to_read = min(buffer_size, n_samples_left) try: samples = audio_file.read_frames(to_read) except RuntimeError: # this can happen with a broken header break # convert to mono by selecting left channel only if audio_file.channels() > 1: samples = samples[:, 0] max_value = max(max_value, numpy.abs(samples).max()) n_samples_left -= to_read audio_file.close() return max_value
def read(cls, filename: str, start=0., end=0.) -> Sample: """ Read samples from `filename`. Args: filename: the filename of the soundfile start: the time to start reading end: the end time to stop reading (0 to read until the end) Returns: a Sample """ sndfile = pysndfile.PySndfile(filename) sr = sndfile.samplerate() if end == 0: endsample = sndfile.frames() else: endsample = int(sr * end) assert endsample < sndfile.frames() if start > 0: startsample = int(start * sr) sndfile.seek(startsample) else: startsample = 0 samples = sndfile.read_frames(endsample - startsample) return cls(samples, samplerate=sr)
def do_plot(ax, image_source_file, waveguide_file, absorption, max_frequency, room_dim): ax.set_title('Absorption: ' + str(absorption)) ax.set_xlabel('frequency / Hz') ax.set_ylabel('magnitude / dB') if room_dim is not None: ranges = [[(x / i) ** 2 for x in range(10)] for i in room_dim] all_frequencies = [(SPEED_OF_SOUND / 2) * np.sqrt(a + b + c) for a, b, c in itertools.product(*ranges)] filtered_frequencies = [i for i in all_frequencies if i < max_frequency] for f in filtered_frequencies: ax.axvline(f, color="0.75") for fname, label in [(image_source_file, 'image source'), (waveguide_file, 'waveguide')]: sndfile = pysndfile.PySndfile(fname, 'r') if sndfile.channels() != 1: raise RuntimeError('please only load mono files') n = sndfile.frames() sr = sndfile.samplerate() samples = sndfile.read_frames() fft = np.abs(np.fft.rfft(samples)) freqs = np.fft.rfftfreq(n, d=1. / sr) mask = freqs < max_frequency fft = 20 * np.log10(fft[mask]) freqs = freqs[mask] ax.plot(freqs, fft, label=label)
def __init__(self, fname): self.sfile = pysndfile.PySndfile(fname, 'r') if self.sfile.info.frames == 0: # if number of frames in the wav file is equal to 0 raise IOError, '%s not a correct wav file' % fname self.samplerate = self.sfile.info.samplerate # sample rate = sound file sample rate self.frames = self.sfile.info.frames # number of frames self.wav = self.sfile.readf_double(self.frames) self.sfile.close()
def get_specgram_data(fname): sndfile = pysndfile.PySndfile(fname, 'r') if sndfile.channels() != 1: raise RuntimeError('please only load mono files') Fs = sndfile.samplerate() signal = sndfile.read_frames() pxx, freq, time = mlab.specgram(signal, NFFT=4096, Fs=Fs) return pxx, freq, time
def plt_file(ax, file_name, name): sndfile = pysndfile.PySndfile(file_name, 'r') if sndfile.channels() != 1: raise RuntimeError('please only load mono files') Fs = sndfile.samplerate() signal = sndfile.read_frames() time = np.arange(len(signal)) / float(Fs) ax.plot(time, signal) ax.text(0.001, 0.75, name)
def __init__(self, fname, f_size, timemax=-1): self.sfile = pysndfile.PySndfile(fname, 'r') if self.sfile.info.frames == 0: # if number of frames in the wav file is equal to 0 raise IOError, '%s not a correct wav file' % fname self.offset = 0 # current offset self.samplerate = self.sfile.info.samplerate # sample rate = sound file sample rate self.frames = self.sfile.info.frames # number of frames self.f_size = f_size self.last_time = -1 # flag for interrupted call self.nchunk = 0 self.c_sounds = []
def _wavwriter(outfile, sr=44100, bits=32): ext = os.path.splitext(outfile)[1][1:][:3].lower() assert bits in (32, 64) assert ext in ('wav', 'aif') encoding = "float%d" % bits fmt = pysndfile.construct_format(ext, encoding) f = pysndfile.PySndfile(outfile, mode="w", format=fmt, channels=1, samplerate=sr) return f
def sndwrite(samples, sr, sndfile, encoding=None): """ encoding: 'pcm8', 'pcm16', 'pcm24', 'pcm32', 'flt32'. None to use a default based on the given extension """ ext = os.path.splitext(sndfile)[1].lower() if encoding is None: encoding = _defaultEncodingForExtension(ext) fmt = _getFormat(ext, encoding) snd = pysndfile.PySndfile(sndfile, mode='w', format=fmt, channels=_numchannels(samples), samplerate=sr) snd.write_frames(samples) snd.writeSync()
def __init__(self, fname, offset=0): """ Main init method :param fname: wav file name path :param offset: starting time """ # keep only the filename self.fname = fname.split('/')[-1] self.frames = [] # load file self.sfile = pysndfile.PySndfile(fname, 'r') self.samplerate = self.sfile.samplerate() f_offset = np.floor(offset * self.samplerate) self.sfile.seek(f_offset, 0) # keep trakc of chunks loaded self.nchunk = 0
def main(): files = [ ("near (1m)", "large.wav", [1]), ("far (11.8m)", "large_spaced.wav", [np.sqrt(2**2 + 10**2 + 6**2)]), ] fig, axes = plt.subplots(nrows=len(files), sharex=True) cmap = plt.get_cmap('viridis') for (label, fname, distances), ax in zip(files, axes): sndfile = pysndfile.PySndfile(fname, 'r') if sndfile.channels() != 1: raise RuntimeError('please only load mono files') Fs = sndfile.samplerate() signal = sndfile.read_frames() time = np.arange(len(signal)) / float(Fs) ax.plot(time, signal) ax.set_xlim([0, 0.05]) ax.set_title(label) ax.set_xlabel('time / s') ax.set_ylabel('amplitude') for dist in distances: time = dist / 340.0 ax.axvline(time, linestyle='dotted', color='red') ax.text(time + 0.0005, -0.3, str.format('{0:.3g} s', time)) plt.suptitle( 'Differences in Direct Contribution Time for Different Source/Receiver Spacings' ) plt.tight_layout() plt.subplots_adjust(top=0.9) plt.show() if render: plt.savefig('spacing_signals.svg', bbox_inches='tight', dpi=96, format='svg')
def from_file(cls, filename): """Open a sound from a file. Parameters ---------- filename : str File path in the disk to open. Returns ------- :py:class:`waves.Sound` :py:class:`waves.Sound` instance. Raises ------ FileNotFoundError If the file does not exists in the provided path. IsADirectoryError If the provided path points to a directory. Examples -------- >>> from waves import Sound >>> >>> Sound.from_file("tests/files/stereo.wav") <waves.sound.main.Sound object at ...> >>> >>> Sound.from_file("tests/files/mono.wav") <waves.sound.main.Sound object at ...> """ try: return cls.from_sndbuffer(snd.PySndfile(filename, "r")) except OSError as err: if "No such file or directory" in str(err): if os.path.isdir(filename): raise IsADirectoryError( f"'{filename}' is a directory") from None raise FileNotFoundError( f"'{filename}' file not found") from None raise err
def sndread(sndfile, start=0, end=0): ext = os.path.splitext(sndfile)[1] if ext == '.mp3': return _sndread_mp3(sndfile, start=start, end=end) sf = pysndfile.PySndfile(sndfile) sr = sf.samplerate() duration = sf.frames() / sr if end <= 0: end = duration - end if start >= end: raise ValueError(f"Asked to read 0 frames: start={start}, end={end}") if start > 0: if start > duration: raise ValueError( f"Asked to read after end of file (start={start}, duration={duration}" ) sf.seek(int(start * sr)) frames = sf.read_frames(int((end - start) * sr)) return frames, sr
def open_sndfile_to_write(filename: str, channels=1, samplerate=48000, bits: int = None) -> pysndfile.PySndfile: """ The format is inferred from the extension (wav, aiff, flac, etc.) if bits is given, it is used. otherwise it is inferred from the format """ encodings = { 'wav': { 16: "pcm16", 24: "pcm24", 32: "float32" }, 'aif': { 16: "pcm16", 24: "pcm24", 32: "float32", }, 'flac': { 16: "pcm16", 24: "pcm24", 32: "pcm24" } } base, ext = os.path.splitext(filename) ext = ext[1:].lower() if not ext or ext not in encodings: raise ValueError(f"The extension ({ext}) is not supported") encoding = encodings[ext].get(bits) if encoding is None: raise ValueError(f"no format possible for {ext} with {bits} bits") fmt = pysndfile.construct_format(ext, encoding) return pysndfile.PySndfile(filename, 'w', format=fmt, channels=channels, samplerate=samplerate)
def rename_file(self, filename): """ Renames the audio file associated with the object to the name specified as an argument Arguments: - filename: the new path of the audio file. """ # TODO: Consider the race condition here. Is this a problem? # Check name doesn't already exist if os.path.exists(filename): raise ValueError("The filepath: {0} is an already existing file") # Check name is a valid file path if not os.path.exists(os.path.dirname(filename)): raise ValueError("The filepath: {0} does not point to an existing " "directory".format(filename)) # Check name has the same extension as previous file old_ext = os.path.splitext(self.filepath)[1] new_ext = os.path.splitext(filename)[1] if old_ext != new_ext: raise ValueError("The renamed file's extension ({0})" "must be the same as the original extension" "({1})".format(old_ext, new_ext)) # Delete pysndfile object seek = self.get_seek_position() del self.pysndfile_object # Rename file os.rename(self.filepath, filename) # Reinitialize pysndfile object self.pysndfile_object = pysndfile.PySndfile( filename, mode='r', format=self.format, samplerate=self.samplerate, channels=self.channels ) self.filepath = filename # Re-set seek position to previous position self.seek(seek, 0)
def __init__(self, input_filename, fft_size, window_function=numpy.hanning): max_level = get_max_level(input_filename) self.audio_file = pysndfile.PySndfile(input_filename, 'r') self.nframes = self.audio_file.frames() self.samplerate = self.audio_file.samplerate() self.fft_size = fft_size self.window = window_function(self.fft_size) self.spectrum_range = None self.lower = 100 self.higher = 22050 self.lower_log = math.log10(self.lower) self.higher_log = math.log10(self.higher) self.clip = lambda val, low, high: min(high, max(low, val)) # figure out what the maximum value is for an FFT doing the FFT of a DC signal fft = numpy.fft.rfft(numpy.ones(fft_size) * self.window) max_fft = (numpy.abs(fft)).max() # set the scale to normalized audio and normalized FFT self.scale = 1.0 / max_level / max_fft if max_level > 0 else 1
def _read_pysndfile(filename): f = pysndfile.PySndfile(filename) nframes = f.frames() data = f.read_frames(nframes) return data, f.samplerate()
import pysndfile import numpy as np inputText = input("Enter an input sentence: ") inputWords = inputText.split() #razdvaja riječi i sprema u words outputFile = './sentences/' + inputText #ime izlazne datoteke sentenceObject = pysndfile.PySndfile( outputFile, 'rw', pysndfile.construct_format('wav', 'float64'), 1, 16000 ) #kreira novu datoteku u koju će zapisivati(format se mora proslijediti u obliku integera koji kreira funkcija construct_format iz stringova koji joj se zadaju) #za svaku riječ iz ulazne rečenice for word in inputWords: wordFilePath = './words/' + word #pronađe riječ u bazi wordObject = pysndfile.PySndfile( wordFilePath) #stvara objekt iz trenutne riječi wordData = wordObject.read_frames( ) #čita i privremeno pohranjuje data iz objekta sentenceObject.write_frames( wordData) #zapisuje gore pohranjene podatke na kraj izlazne datoteke
def _init_f(self): if not self.f: self.f = snd.PySndfile(self.filename, "r") else: self.f.seek(0, mode="r")
def main(): fig, ax = plt.subplots(nrows=2, sharex=False) cmap = plt.get_cmap('viridis') sndfile = pysndfile.PySndfile('vault.wav', 'r') if sndfile.channels() != 1: raise RuntimeError('please only load mono files') Fs = sndfile.samplerate() signal = sndfile.read_frames() NFFT = 2048 pxx, freq, time = mlab.specgram(signal, NFFT=NFFT, noverlap=NFFT / 2, Fs=Fs) def do_impulse_plot(): time = np.arange(len(signal)) / float(Fs) ax[0].plot(time, signal) ax[0].set_xlim([0, 0.1]) ax[0].set_xlabel('time / s') ax[0].set_ylabel('amplitude') time = 7.12 / 340.0 ax[0].axvline(time, linestyle='dotted', color='red') ax[0].text( time + 0.0005, -0.5, str.format('{0:.3g} s (earliest possible diffraction time)', time)) def do_spec_plot(): Z = 10 * np.log10(pxx) vmin = -200 vmax = np.nanmax(Z) im = ax[1].pcolormesh(time, freq, Z, cmap=cmap, vmin=vmin, vmax=vmax, rasterized=True) ax[1].set_xlim([0, 1]) ax[1].set_ylim(20, 20000) ax[1].set_yscale('log') ax[1].set_xlabel('time / s') ax[1].set_ylabel('frequency / Hz') cb = fig.colorbar(im) cb.set_label('dB') do_impulse_plot() do_spec_plot() plt.suptitle('Early Response in Vault Model') plt.tight_layout() plt.subplots_adjust(top=0.9) plt.show() if render: plt.savefig('vault_response.svg', bbox_inches='tight', dpi=96, format='svg')