如何使用Tensorflow API重新采样音频文件

时间:2018-01-13 18:48:39

标签: python audio tensorflow tensorflow-datasets

我使用tf.data.Dataset作为tensorflow中的管道来读取和转换音频。 我想添加音频重采样以减少过度拟合。我搜索了一种方法来重新采样python / tensorflow中的文件,我发现python只有像resampy这样的解决方案。它工作得很好,但它减慢了我的pipline 10次,因为我不得不使用tf.py_func来运行它。我的音频文件长1秒,速率为16000,下面是我的代码进行重新采样,然后填充或剪辑生成的数组:

def _resample(pcm, label):
    if resample_range < 1e-8:
        return pcm, label

    import resampy
    desired_samples=16000
    def clip_o_pad(pcm):
        margin = pcm.shape[0] - desired_samples + 2
        if margin > 0:
            out = pcm[margin // 2: (pcm.shape[0] - margin // 2)]
        elif margin < 0:
            out = np.pad(clip, -margin // 2, 'constant', constant_values=(0))
        else:
            out = pcm
        return out[:desired_samples]

    def _resample_py(pcm):
        pcm = pcm.reshape(desired_samples)
        new_rate = np.random.randint(desired_samples*(1-resample_range), desired_samples*(1+resample_range))
        resampled = resampy.resample(pcm, desired_samples, new_rate)
        out = clip_o_pad(resampled)
        out = out.reshape(desired_samples,1)
        return out

    return tf.py_func(_resample_py, [pcm], pcm.dtype), label

你知道张量流中的任何库/函数,它允许我在纯张量流图中做同样的事情(即不使用py_func)

1 个答案:

答案 0 :(得分:0)

经过一些谷歌搜索后,我注意到tf.contrib.ffmpeg.decode_audio可以进行重新采样。

然而,改变我的pipline以使用上述程序并没有提高我的管道速度。显然,减速是由重新采样而不是使用tf.py_func:/引起的。加载200个示例需要200毫秒而不重新采样,5200毫秒使用resamply和py_func,5700毫秒使用ffmepg和纯张量流代码。

如果有人发现它有用,上面的代码重写为tensorflow如下:

import tensorflow as tf

def _decode_n_resample(data, label):
    min_rate = desired_samples * (1 - resample_range)
    max_rate = desired_samples * (1 - resample_range)
    if min_rate < max_rate:
        samples_per_second = tf.random_uniform([], min_rate, max_rate, dtype=tf.int32)
    else:
        samples_per_second = desired_samples
    pcm = tf.contrib.ffmpeg.decode_audio(data, file_format='wav', samples_per_second=samples_per_second,
                                         channel_count=1)


    number_of_samples = tf.shape(pcm)[0]
    samples_to_pad = desired_samples - number_of_samples

    padding = tf.cond(samples_to_pad > 0,
                      lambda : tf.to_int64([[tf.floor(samples_to_pad/2), tf.ceil(samples_to_pad/2)], [0, 0]]),
                      lambda : tf.to_int64([[0, 0], [0, 0]]))

    padded_pcm = tf.pad(
        pcm,
        padding,
        mode='CONSTANT')

    sliced_pcm = tf.slice(padded_pcm, [0, 0], [desired_samples, -1])

    return sliced_pcm, label