Exemple #1
0
def block_mix_wavs(wavpath_a,
                   wavpath_b,
                   out_wavpath,
                   a_gain=1.,
                   b_gain=1.,
                   block_size=4096,
                   mute_left=False):
    '''
    Mix two wav files, applying gains to each
    '''
    wav_a = PySndfile(wavpath_a, 'r')
    wav_b = PySndfile(wavpath_b, 'r')

    out_wav = PySndfile(out_wavpath, 'w', construct_format('wav', 'pcm16'),
                        wav_a.channels(), wav_a.samplerate())

    i = 0
    while i < wav_a.frames():
        if i + block_size > wav_a.frames():
            block_size = wav_a.frames() - i
        x1 = wav_a.read_frames(block_size)
        x2 = wav_b.read_frames(block_size)
        x1[:, :2] *= a_gain
        x2 *= b_gain
        if x1.shape[1] == 3:
            y = np.zeros(x1.shape)
            y[:, 0] = x1[:, 0] + x2
            y[:, 1] = x1[:, 1] + x2
            y[:, 2] = x1[:, 2]
            if mute_left:
                y[:, 0] = 0.0
        else:
            y = x1 + x2
        out_wav.write_frames(y)
        i += block_size
Exemple #2
0
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
Exemple #3
0
def _getFormat(extension: str, encoding: str):
    assert extension[0] == "."
    fmt, bits = encoding[:3], int(encoding[3:])
    assert fmt in ('pcm', 'flt') and bits in (8, 16, 24, 32)
    extension = extension[1:]
    if extension == 'aif':
        extension = 'aiff'
    fmt = "%s%d" % ({'pcm': 'pcm', 'flt': 'float'}[fmt], bits)
    return pysndfile.construct_format(extension, fmt)
Exemple #4
0
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
Exemple #5
0
 def __init__(self,
              fn,
              samplerate,
              filefmt='wav',
              datafmt='pcm16',
              channels=1):
     fmt = construct_format(filefmt, datafmt)
     self.sf = PySndfile(fn,
                         mode='w',
                         format=fmt,
                         channels=channels,
                         samplerate=samplerate)
Exemple #6
0
def _getFormat(extension:str, encoding:str):
    assert extension[0] == "."
    fmt, bits = encoding[:3], int(encoding[3:])
    assert fmt in ('pcm', 'flt') and bits in (8, 16, 24, 32)
    extension = extension[1:]
    if extension == 'aif':
        extension = 'aiff'
    fmt = "%s%d" % (
        {'pcm': 'pcm', 
         'flt': 'float'}[fmt],
        bits
    )
    return pysndfile.construct_format(extension, fmt)
Exemple #7
0
 def _getSndfileFormat(self, extension, encoding):
     assert extension in self.filetypes
     fmt, bits = encoding[:3], int(encoding[3:])
     assert fmt in ('pcm', 'flt') and bits in (8, 16, 24, 32)
     extension = extension[1:]
     if extension == 'aif':
         extension = 'aiff'
     fmt = "%s%d" % (
         {'pcm': 'pcm', 
          'flt': 'float'}[fmt],
         bits
     )
     pysndfile = self.get_backend()
     return pysndfile.construct_format(extension, fmt)
Exemple #8
0
def _sndfile_format(extension, encoding):
    if isinstance(encoding, str):
        samplekind = encoding[:-2]
        bits = int(encoding[-2:])
    elif isinstance(encoding, tuple):
        samplekind, bits = encoding
    else:
        raise TypeError("encoding should be a string ('float32') or a tuple like ('float', 32)"
                        f" but got {encoding} of type {type(encoding)}")
    assert samplekind in {'float', 'pcm'}
    assert bits in {16, 24, 32, 64}
    if extension[0] == '.':
        extension = extension[1:]
    if extension == 'aif':
        extension = 'aiff'
    fmt = f"{samplekind}{bits}"
    return pysndfile.construct_format(extension, fmt)
Exemple #9
0
def write(name, vec, rate=44100, format="aiff", enc='pcm16'):
    """
    Write datavector to aiff file using amplerate and encoding as specified
    """
    nchans = len(vec.shape)
    if nchans != 1:
        nchans = vec.shape[1]
    sf = PySndfile(name,
                   "w",
                   format=construct_format(formt, enc),
                   channels=nchans,
                   samplerate=rate)

    nf = sf.write_frames(vec)

    if nf != vec.shape[0]:
        raise IOError("sndio.write::error::writing of samples failed")
    return nf
Exemple #10
0
def block_process_wav(wavpath, out_wavpath, func, block_size=4096, **args):
    '''
    Mix two wav files, applying gains to each
    '''
    wav = PySndfile(wavpath, 'r')

    out_wav = PySndfile(out_wavpath, 'w', construct_format('wav', 'pcm16'),
                        wav.channels(), wav.samplerate())

    i = 0
    while i < wav.frames():
        if i + block_size > wav.frames():
            block_size = wav.frames() - i
        x = wav.read_frames(block_size)
        y = func(x, **args)
        out_wav.write_frames(y)
        i += block_size
    del out_wav
Exemple #11
0
 def __init__(self, filename=None):
     self.filename = filename
     self.history = history.History()
     self.changed = Signal()
     if filename == None:
         # empty sound
         self.frames = numpy.array([])
         self.samplerate = 44100
         self._saved_revision = None
         self._format = pysndfile.construct_format('wavex', 'pcm24')
     else:
         filename = os.path.expanduser(filename)
         f = pysndfile.PySndfile(filename)
         nframes = f.frames()
         self.frames = f.read_frames(nframes)
         self.samplerate = f.samplerate()
         self._format = f.format()
         self._saved_revision = self.history.revision()
Exemple #12
0
def _sndfile_format(extension, encoding):
    if isinstance(encoding, str):
        samplekind = encoding[:-2]
        bits = int(encoding[-2:])
    elif isinstance(encoding, tuple):
        samplekind, bits = encoding
    else:
        raise TypeError(
            "encoding should be a string ('float32') or a tuple like ('float', 32)"
            f" but got {encoding} of type {type(encoding)}")
    assert samplekind in {'float', 'pcm'}
    assert bits in {16, 24, 32, 64}
    if extension[0] == '.':
        extension = extension[1:]
    if extension == 'aif':
        extension = 'aiff'
    fmt = f"{samplekind}{bits}"
    return pysndfile.construct_format(extension, fmt)
Exemple #13
0
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)
Exemple #14
0
def write(name, data, rate=44100, format="aiff", enc='pcm16') :
    """
    Write datavector to sndfile using samplerate, format and encoding as specified
    valid format strings are all the keys in the dict pysndfile.fileformat_name_to_id
    valid encodings are those that are supported by the selected format
    from the list of keys in pysndfile.encoding_name_to_id.
    """
    nchans = len(data.shape)
    if nchans == 2 :
        nchans = data.shape[1]
    elif nchans != 1:
        raise RuntimeError("error:sndio.write:can only be called with vectors or matrices ")

    sf  = PySndfile(name, "w",
                    format=construct_format(format, enc),
                    channels = nchans, samplerate = rate)
    
    nf = sf.write_frames(data)

    if nf != data.shape[0]:
        raise IOError("sndio.write::error::writing of samples failed")
    return nf
Exemple #15
0
    def gen_default_wav(path, overwrite_existing=False, mode='w', channels=1):
        """
        Convenience method that creates a wav file with the following spec at
        the path given:

        - Samplerate: 44.1Khz

        - Bit rate: 24Bit
        """
        if os.path.exists(path):
            if not overwrite_existing:
                raise IOError(
                    ''.join(("File: \"", path, "\" already exists."))
                )
            else:
                os.remove(path)

        return AudioFile(
            path,
            mode,
            format=pysndfile.construct_format("wav", "pcm24"),
            channels=channels,
            samplerate=44100
        ).open()
Exemple #16
0
def testSound():
    from copy import copy
    import gum
    testdir = gum.basedir + '/data/test'
    snd = Sound()

    # synthesize a sine wave
    from math import sin
    SR = 44100
    f0 = 440
    time = 5
    sine = [sin(2 * 3.14 * f0/SR * x) for x in range(time * SR)]
    start, end = 2*SR, 4*SR
    sine2 = copy(sine)
    snd.frames = numpy.array(copy(sine))
    del sine2[start:end]
    snd.cut(start, end)
    assert snd.frames.tolist() == sine2

    snd.history.undo()
    assert snd.frames.tolist() == sine
    snd.history.undo()
    assert snd.frames.tolist() == sine
    snd.history.redo()
    assert snd.frames.tolist() == sine2

    clip = snd.copy(start, end)
    snd.paste(0, 0, clip)
    assert snd.frames.tolist() == sine2[start:end] + sine2
    snd.history.undo()
    assert snd.frames.tolist() == sine2
    snd.history.redo()
    assert snd.frames.tolist() == sine2[start:end] + sine2

    # test with a mono file
    snd = Sound(testdir + "/test1.wav")
    assert snd.frames != []
    start = 4444
    end = 55555
    data = snd.frames.tolist()
    data2 = snd.frames.tolist()
    del data2[start:end]
    snd.cut(start, end)
    assert snd.frames.tolist() == data2
    snd.history.undo()
    assert snd.frames.tolist() == data
    snd.history.undo()
    assert snd.frames.tolist() == data
    snd.history.redo()
    assert snd.frames.tolist() == data2
    clip = snd.copy(start, end)
    snd.paste(0, 0, clip)
    assert snd.frames.tolist() == data2[start:end] + data2
    snd.history.undo()
    assert snd.frames.tolist() == data2
    snd.paste(0, 0, clip)
    assert snd.frames.tolist() == data2[start:end] + data2

    # test with a stereo file
    snd = Sound(testdir + "/test2.wav")
    assert snd.frames.tolist() != []
    start = 4444
    end = 55555
    data = copy(snd.frames.tolist())
    data2 = copy(snd.frames.tolist())
    del data2[start:end]
    snd.cut(start, end)
    assert snd.frames.tolist() == data2
    snd.history.undo()
    assert snd.frames.tolist() == data
    snd.history.undo()
    assert snd.frames.tolist() == data
    snd.history.redo()
    assert snd.frames.tolist() == data2
    clip = snd.copy(start, end)
    snd.paste(0, 0, clip)
    assert snd.frames.tolist() == data2[start:end] + data2
    snd.history.undo()
    assert snd.frames.tolist() == data2
    snd.paste(0, 0, clip)
    assert snd.frames.tolist() == data2[start:end] + data2

    # test save_as()
    import os
    snd = Sound(testdir + "/test1.wav")
    outfile = "/tmp/test.wav"
    snd.save_as(outfile)
    assert os.path.exists(outfile)
    assert snd.filename == outfile
    snd2 = Sound(outfile)
    assert abs((snd.frames - snd2.frames).max()) < 0.0001 # quantization errors!
    os.remove(outfile)

    snd = Sound(testdir + "/test2.wav")
    outfile = "/tmp/test2.wav"
    snd.save_as(outfile)
    assert os.path.exists(outfile)
    assert snd.filename == outfile
    snd2 = Sound(outfile)
    assert snd.frames.size == snd2.frames.size
    assert abs((snd.frames - snd2.frames).flatten().max()) == 0
    os.remove(outfile)

    # Preserve file format when saving
    snd = Sound(testdir + "/test3.wav")
    outfile = "/tmp/test3.wav"
    snd.save_as(outfile)
    snd2 = Sound(outfile)
    assert snd2._format == pysndfile.construct_format('wavex', 'pcm24')
    assert snd.samplerate == 48000
    os.remove(outfile)
    

    # test cut
    snd = Sound()
    snd.frames = numpy.array([1, 2, 3, 4])
    clip = snd.cut(1, 3)
    assert snd.frames.tolist() == [1, 4]
    snd.undo()
    assert snd.frames.tolist() == [1, 2, 3, 4]
    # clip is a copy
    clip[0] = 9
    assert snd.frames.tolist() == [1, 2, 3, 4]

    # test copy
    snd = Sound()
    snd.frames = numpy.array([1, 2, 3, 4])
    clip = snd.copy(1, 3)
    assert clip.tolist() == [2, 3]
    # clip is a copy
    clip[0] = 9
    assert snd.frames.tolist() == [1, 2, 3, 4]

    # test paste
    snd = Sound()
    snd.frames = numpy.array([1, 2, 3, 4])
    clip = numpy.array([22, 33])
    snd.paste(1, 3, clip)
    assert snd.frames.tolist() == [1, 22, 33, 4]
    snd.undo()
    assert snd.frames.tolist() == [1, 2, 3, 4]
    snd.paste(1, 1, clip)
    assert snd.frames.tolist() == [1, 22, 33, 2, 3, 4]
    #
    # paste a stereo clip into a mono file
    snd.frames = numpy.array([1, 2, 3, 4])
    clip = numpy.array([[30, 10], [40, 20]])
    snd.paste(1, 3, clip)
    assert snd.frames.tolist() == [1, 20, 30, 4]
    snd.undo()
    assert snd.frames.tolist() == [1, 2, 3, 4]
    snd.paste(1, 1, clip)
    assert snd.frames.tolist() == [1, 20, 30, 2, 3, 4]
    # pasting in empty sound: keep it stereo
    snd.frames = numpy.array([])
    snd.paste(1, 2, clip)
    assert snd.frames.ndim == 2
    #
    # paste a mono clip into a stereo file
    snd.frames = numpy.array([[1, 1], [2, 2], [3, 3], [4, 4]])
    clip = numpy.array([22, 33])
    snd.paste(1, 3, clip)
    assert snd.frames.tolist() == [[1, 1], [22, 22], [33, 33], [4, 4]]
    snd.undo()
    assert snd.frames.tolist() == [[1, 1], [2, 2], [3, 3], [4, 4]]
    snd.paste(1, 1, clip)
    assert snd.frames.tolist() == [[1, 1], [22, 22], [33, 33],\
                                                        [2, 2], [3, 3], [4, 4]]
    # pasting in empty sound: keep it mono
    snd.frames = numpy.array([])
    snd.paste(1, 2, clip)
    assert snd.frames.ndim == 1

    # test mix
    snd = Sound()
    snd.frames = numpy.array([1, 2, 3, 4])
    clip = numpy.array([2, 3])
    snd.mix(1, 3, clip)
    assert snd.frames.tolist() == [1, 4, 6, 4]
    snd.undo()
    assert snd.frames.tolist() == [1, 2, 3, 4]
    #
    # clip smaller than selection
    snd = Sound()
    snd.frames = numpy.array([1, 2, 3, 4])
    clip = numpy.array([2])
    snd.mix(1, 3, clip)
    assert snd.frames.tolist() == [1, 4, 3, 4]
    snd.undo()
    assert snd.frames.tolist() == [1, 2, 3, 4]
    #
    # must not go behind selection
    clip = numpy.array([2, 3, 4])
    snd.mix(1, 3, clip)
    assert snd.frames.tolist() == [1, 4, 6, 4]
    snd.undo()
    assert snd.frames.tolist() == [1, 2, 3, 4]
    #
    clip = numpy.array([2, 3])
    snd.mix(1, 1, clip)
    assert snd.frames.tolist() == [1, 4, 6, 4]
    snd.undo()
    assert snd.frames.tolist() == [1, 2, 3, 4]
    #
    # mix() may extend sound length when there is no selection.
    clip = numpy.array([2, 3, 4, 5])
    snd.mix(1, 1, clip)
    assert snd.frames.tolist() == [1, 4, 6, 8, 5]
    snd.undo()
    assert snd.frames.tolist() == [1, 2, 3, 4]
    #
    # stereo too
    snd = Sound()
    snd.frames = numpy.array([[1, 1], [2, 2], [3, 3], [4, 4]])
    clip = numpy.array([[2, 2], [3, 3]])
    snd.mix(1, 3, clip)
    assert snd.frames.tolist() == [[1, 1], [4, 4], [6, 6], [4, 4]]
    snd.undo()
    assert snd.frames.tolist() == [[1, 1], [2, 2], [3, 3], [4, 4]]
    #
    snd = Sound()
    snd.frames = numpy.array([[1, 1], [2, 1], [3, 2], [4, 4]])
    clip = numpy.array([[2, 2], [3, 3]])
    snd.mix(1, 1, clip) # no selection
    assert snd.frames.tolist() == [[1, 1], [4, 3], [6, 5], [4, 4]]
    snd.undo()
    assert snd.frames.tolist() == [[1, 1], [2, 1], [3, 2], [4, 4]]
    #
    # mix a stereo clip into a mono file
    snd.frames = numpy.array([1, 2, 3, 4])
    clip = numpy.array([[30, 10], [40, 20]])
    snd.mix(1, 3, clip)
    assert snd.frames.tolist() == [1, 22, 33, 4]
    #
    # mix a mono clip into a stereo file
    snd.frames = numpy.array([[1, 1], [2, 2], [3, 3], [4, 4]])
    clip = numpy.array([20, 30])
    snd.mix(1, 3, clip)
    assert snd.frames.tolist() == [[1, 1], [22, 22], [33, 33], [4, 4]]

    # Do not crash when saving with None as filename
    snd = Sound()
    try:
        snd.save()
    except:
        print "OK"
    else:
        assert False

    # expand user symbol
    from gum.lib import mock
    def fake_sndfile(filename):
        assert '~' not in filename
        return mock.Fake()
    orig = pysndfile.PySndfile
    pysndfile.PySndfile = fake_sndfile
    Sound("~/sound.wav")
    pysndfile.PySndfile = orig
Exemple #17
0
def wav_format_code(encoding=None):
    """Calculate the format code for 'pcm16' encoded 'wav' files."""
    if not encoding:
        encoding = 'pcm16'
    return construct_format('wav', encoding)
Exemple #18
0
def main():
    stim_dir = "../behavioural_stim/stimulus"
    wav_dir = "../behavioural_stim/stimulus/wav"
    base_dir = "../behavioural_stim/stimulus/wav/sentence-lists/"
    noise_dir = "../behavioural_stim/stimulus/wav/noise/"
    out_dir = "./out"
    dir_must_exist(base_dir)
    dir_must_exist(out_dir)
    dir_must_exist(wav_dir)
    dir_must_exist(noise_dir)

    noise_filepath = "../behavioural_stim/stimulus/wav/noise/noise_norm.wav"

    folders = os.listdir(base_dir)
    folders = natsorted(folders)[1:15]
    folders = list(zip(folders[::2], folders[1::2]))
    calc_potential_max(base_dir, noise_filepath, out_dir)
    n_questions = 4
    fs = 44100

    for ind, (list_folder_1, list_folder_2) in enumerate(folders):
        out_folder_name = 'Stim_{}'.format(ind)
        out_folder = os.path.join(out_dir, out_folder_name)
        delete_if_exists(out_folder)
        dir_must_exist(out_folder)
        out_wav_path = os.path.join(out_folder, "stim.wav")
        out_csv_path = os.path.join(out_folder, "markers.csv")
        out_rms_path = os.path.join(out_folder, "rms.npy")
        out_q_path = [
            os.path.join(out_folder, "questions_{}.csv".format(x))
            for x in range(n_questions)
        ]
        out_wav = PySndfile(out_wav_path, 'w',
                            construct_format('wav', 'pcm16'), 3, 44100)
        list_1_wav = globDir(os.path.join(base_dir, list_folder_1), '*.wav')
        list_2_wav = globDir(os.path.join(base_dir, list_folder_2), '*.wav')
        list_1_csv = globDir(os.path.join(base_dir, list_folder_1), '*.csv')
        list_2_csv = globDir(os.path.join(base_dir, list_folder_2), '*.csv')
        merged_wavs = list_1_wav + list_2_wav
        merged_csvs = list_1_csv + list_2_csv
        words = []
        for c in merged_csvs:
            with open(c, 'r') as csvfile:
                for line in csv.reader(csvfile):
                    words.append(line)
        c = list(zip(merged_wavs, words))
        shuffle(c)
        merged_wavs, words = zip(*c)
        sum_sqrd = 0.
        n = 0
        with open(out_csv_path, 'w') as csvfile, ExitStack() as stack:
            # Open all question files
            qfiles = [
                stack.enter_context(open(qfile, 'w')) for qfile in out_q_path
            ]
            writer = csv.writer(csvfile)
            qwriters = [csv.writer(qfile) for qfile in qfiles]

            counter = 0
            stim_count = len(merged_wavs)
            stim_count_half = stim_count // 2
            q_inds = np.array([
                sample(range(0, stim_count_half), n_questions),
                sample(range(stim_count_half, stim_count - 1), n_questions)
            ]).T
            a = 0
            silence = np.zeros((88200, 3))
            idx = np.arange(0, silence.shape[0])
            trigger = gen_trigger(idx, 2., 0.01, fs)
            silence[:, 2] = trigger
            out_wav.write_frames(silence)
            for ind, (wav, txt) in enumerate(zip(merged_wavs, words)):
                csv_line = [counter]
                silence = np.zeros((int(
                    np.random.uniform(int(0.3 * 44100), int(0.4 * 44100),
                                      1)), 3))
                idx = np.arange(counter, counter + silence.shape[0])
                trigger = gen_trigger(idx, 2., 0.01, fs)
                silence[:, 2] = trigger
                out_wav.write_frames(silence)
                counter += silence.shape[0]
                csv_line.append(counter)
                csv_line.append("#")
                writer.writerow(csv_line)
                csv_line = [counter]
                x, fs, enc = sndio.read(wav)
                sum_sqrd += np.sum(x**2)
                n += x.size

                y = np.vstack([x, x, np.zeros(x.size)]).T
                idx = np.arange(counter, counter + y.shape[0])
                trigger = gen_trigger(idx, 2., 0.01, fs)
                y[:, 2] = trigger
                out_wav.write_frames(y)
                counter += y.shape[0]
                csv_line.append(counter)
                csv_line.append(" ".join(txt))
                writer.writerow(csv_line)
                if ind in q_inds:
                    writer_ind = int(np.where(ind == q_inds)[0])
                    blank_ind = randint(0, len(txt) - 1)
                    q_list = copy(txt)
                    q_list[blank_ind] = '_'
                    qwriters[writer_ind].writerow(
                        [" ".join(q_list), txt[blank_ind]])
                    a += 1
            if a != 8:
                pdb.set_trace()

            csv_line = [counter]
            silence = np.zeros(
                (int(np.random.uniform(int(0.3 * 44100), int(0.4 * 44100),
                                       1)), 3))
            idx = np.arange(counter, counter + silence.shape[0])
            trigger = gen_trigger(idx, 2., 0.01, fs)
            silence[:, 2] = trigger
            out_wav.write_frames(silence)
            counter += silence.size
            csv_line.append(counter)
            csv_line.append("#")
            writer.writerow(csv_line)
            rms = np.sqrt(sum_sqrd / n)
            np.save(out_rms_path, rms)

            x, fs, enc = sndio.read(out_wav_path)
Exemple #19
0
    s_r = nsgt.backward(c)

    t2 = cputime()
    times.append(t2-t1)

norm = lambda x: np.sqrt(np.sum(np.abs(np.square(x))))
rec_err = norm(s-s_r)/norm(s)
print("Reconstruction error: %.3e"%rec_err)
print("Calculation time: %.3f±%.3fs (min=%.3f s)"%(np.mean(times), np.std(times)/2, np.min(times)))

if args.output:
    print("Writing audio file '%s'"%args.output)
    if Sndfile is not None:
        sf = Sndfile(args.output, mode='w', format=Format('wav','pcm24'), channels=1, samplerate=fs)
    else:
        sf = PySndfile(args.output, mode='w', format=construct_format('wav','pcm24'), channels=1, samplerate=fs)
    sf.write_frames(s_r)
    sf.close()
    print("Done")

if args.plot:
    print("Preparing plot")
    import matplotlib.pyplot as pl
    # interpolate CQT to get a grid
    hf = -1 if args.real else len(c)//2
    if not args.matrixform:
        x = np.linspace(0, Ls, 2000)
        grid = interpolate(map(np.abs, c[2:hf]), Ls)(x).T
    else:
        grid = np.abs(c[2:hf])
    np.log10(grid, out=grid)
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