在python中从TIMIT数据库读取WAV文件

在python中从TIMIT数据库读取WAV文件,python,audio,scipy,wav,wave,Python,Audio,Scipy,Wav,Wave,我试图从python中的TIMIT数据库读取wav文件,但出现错误: 当我使用wave时: wave.Error: file does not start with RIFF id 当我使用scipy时: ValueError: File format b'NIST'... not understood. 当我使用librosa时,程序卡住了。 我尝试使用sox将其转换为wav: cmd = "sox " + wav_file + " -t wav " + new_wav subproces

我试图从python中的TIMIT数据库读取wav文件,但出现错误:

当我使用wave时:

wave.Error: file does not start with RIFF id
当我使用scipy时:

ValueError: File format b'NIST'... not understood.
当我使用librosa时,程序卡住了。 我尝试使用sox将其转换为wav:

cmd = "sox " + wav_file + " -t wav " + new_wav
subprocess.call(cmd, shell=True)
但这没用。我看到了一个旧的答案,它引用了scikets.audiolab包,但它似乎不再受支持

如何读取这些文件以获得数据数组


谢谢

从命令行发出此命令以验证其是否为wav文件。。。还是不

xxd -b myaudiofile.wav | head
如果它是wav格式,它将显示如下内容

00000000: 01010010 01001001 01000110 01000110 10111100 10101111  RIFF..
00000006: 00000001 00000000 01010111 01000001 01010110 01000101  ..WAVE
0000000c: 01100110 01101101 01110100 00100000 00010000 00000000  fmt ..
00000012: 00000000 00000000 00000001 00000000 00000001 00000000  ......
00000018: 01000000 00011111 00000000 00000000 01000000 00011111  @...@.
0000001e: 00000000 00000000 00000001 00000000 00001000 00000000  ......
00000024: 01100100 01100001 01110100 01100001 10011000 10101111  data..
0000002a: 00000001 00000000 10000001 10000000 10000001 10000000  ......
00000030: 10000001 10000000 10000001 10000000 10000001 10000000  ......
00000036: 10000001 10000000 10000001 10000000 10000001 10000000  ......
请注意,wav文件以字符RIFF开头 哪个是文件使用wav编解码器的强制指示符。。。如果您的系统(我在linux上)没有上面的命令行实用程序:xxd,则使用类似的方法检查wav文件,以确认您看到了RIFF。。。如果没有RIFF,那么它就不是wav文件

下面是wav格式规范的详细信息


您的文件不是WAV文件。显然,这是一个NIST球体文件。“许多LDC语料库包含NIST SPHERE格式的语音文件。”根据描述,文件的前四个字符是
NIST
。这就是scipy错误告诉您的:它不知道如何读取以
NIST
开头的文件

我想如果你想阅读你尝试过的任何库的文件,你必须使用WAV。要使用程序
sph2pipe
强制转换为WAV,请使用命令选项
-f WAV
(或相当于
-f rif
),例如


如果您想要一个适用于文件夹中每个wav文件的通用代码,请运行:

forfiles /s /m *.wav /c "cmd /c sph2pipe -f wav @file @fnameRIFF.wav"

它搜索每一个可以找到并创建一个wav文件的wav文件,scipy和wav都可以用RIFF.wav

这个名字来读取。我已经写了一个python脚本,它可以将所有说话者使用的所有NIST格式的.wav文件从所有方言转换成.wav文件,这些文件可以 n在您的系统上播放

注意:所有方言文件夹都位于./TIMIT/TRAIN/中。您可能需要根据项目结构(或者如果您在Windows上)更改方言路径


请使用sounddevice和soundfile获取 numpy数组数据(和播放)使用以下代码:

导入matplotlib.pyplot作为plt
将声音文件导入为sf
将sounddevice作为sd导入
# https://catalog.ldc.upenn.edu/desc/addenda/LDC93S1.wav
数据,fs=sf.read('LDC93S1.wav')
打印(data.shape,fs)
播放(数据、fs、阻塞=True)
plt.绘图(数据)
plt.show()
输出

(46797,) 16000


一个示例TIMIT数据库wav文件:

我更新了我的答案,并说明了如何使用
-f wav
。递归运行当前目录下所有文件的一种简单方法是
查找-名称'*.WAV'-exec sph2pipe-f WAV{}{}.WAV\。唯一的缺点是,您最终得到的文件以
.WAV.WAV
结尾。您可以尝试使用模块或任何其他libsndfile包装器读取该文件,该包装器应支持NIST格式。这是对sph2pipe的Warren Weckesser解决方案的补充。。。我会把它作为评论,但我还没有所需的声誉。
find-名称'*.WAV'-exec sph2pipe-f WAV{}{}.WAV\如果您不想为文件安装
forfiles
from sphfile import SPHFile

dialects_path = "./TIMIT/TRAIN/"

for dialect in dialects:
    dialect_path = dialects_path + dialect
    speakers = os.listdir(path = dialect_path)
    for speaker in speakers:
        speaker_path =  os.path.join(dialect_path,speaker)        
        speaker_recordings = os.listdir(path = speaker_path)

        wav_files = glob.glob(speaker_path + '/*.WAV')

        for wav_file in wav_files:
            sph = SPHFile(wav_file)
            txt_file = ""
            txt_file = wav_file[:-3] + "TXT"

            f = open(txt_file,'r')
            for line in f:
                words = line.split(" ")
                start_time = (int(words[0])/16000)
                end_time = (int(words[1])/16000)
            print("writing file ", wav_file)
            sph.write_wav(wav_file.replace(".WAV",".wav"),start_time,end_time)    
(46797,) 16000