kaldi sre16/v1中local/make_mx6_calls.pl

#!/usr/bin/perl
use warnings; #sed replacement for -w perl parameter
# Copyright 2017   David Snyder
# Apache 2.0
#
# Prepares the telephone portion of Mixer 6 (LDC2013S03).
# 还有转换了语音格式,自动生成了一些文件,还有检查了一些文件

if (@ARGV != 2) {
  print STDERR "Usage: $0 <path-to-LDC2013S03> <path-to-output>\n";
  print STDERR "e.g. $0 /export/corpora5/LDC/LDC2013S03 data/\n";
  exit(1);
}
# 要求参数必须是两个

($db_base, $out_dir) = @ARGV;

if (! -d "$db_base/mx6_speech/data/ulaw_sphere/") {
  print STDERR "Directory $db_base/mx6_speech/data/ulaw_sphere/ doesn't exist\n";
  exit(1);
}

$out_dir = "$out_dir/mx6_calls";

$tmp_dir = "$out_dir/tmp";
if (system("mkdir -p $tmp_dir") != 0) {
  die "Error making directory $tmp_dir";
}

if (system("mkdir -p $out_dir") != 0) {
  print STDERR "Error making directory $out_dir\n";
  exit(1);
}

=pod 注释
Perl 是 Practical Extraction and Report Language 的缩写,可翻译为 "实用报表提取语言"。
Perl 是一种弱类型语言,所以变量不需要指定类型,Perl 解释器会根据上下文自动选择匹配类型。
Perl 有三个基本的数据类型:标量、数组、哈希。以下是这三种数据类型的说明:
标量 $ 开始, 如$a $b 是两个标量。
数组 @ 开始 , 如 @a @b 是两个数组。可以用下标访问数组内元素。
哈希 % 开始 , %a %b 是两个哈希。类似于python中的dict。
例如 $foo 和 @foo 是两个不同的变量。
变量不需要显式声明类型,在变量赋值后,解释器会自动分配匹配的类型空间。
变量使用等号(=)来赋值
=cut

%call2sph = ();  #  %表示定义了一个哈希,类似python中声明了一个字典,还没有向里面放内容

# 下面打开4个文件,如果打不开就输出die 后面跟的提示,die有点类似warning
open(SUBJECTS, "<$db_base/mx6_speech/docs/mx6_subjs.csv") || die "cannot open $$db_base/mx6_speech/docs/mx6_subjs.csv";
open(SPKR, ">$out_dir/utt2spk") || die "Could not open the output file $out_dir/utt2spk";
open(GNDR, ">$out_dir/spk2gender") || die "Could not open the output file $out_dir/spk2gender";
open(WAV, ">$out_dir/wav.scp") || die "Could not open the output file $out_dir/wav.scp";
open(META, "<$db_base/mx6_speech/docs/mx6_calls.csv") || die "cannot open $db_base/mx6_speech/docs/mx6_calls.csv";

if (system("find $db_base/mx6_speech/data/ulaw_sphere/ -name '*.sph' > $tmp_dir/sph.list") != 0) {
  die "Error getting list of sph files";
}

open(SPHLIST, "<$tmp_dir/sph.list") or die "cannot open wav list";

# 之前一直以为chomp函数只是去掉字符串末尾的\n
# chomp的真正作用是去除字符串末尾的$/,只是因为默认情况下$/为\n,造成chomp就是去除\n的假象;
# @_ 是函数传参时放置参数的数组,可以从中取实参
# $_ 是默认参数的意思,指的是在不指定的情况下,程序处理的上一个变量
# 比如,某个例子是打开一个文本文件,读取每一行,在没有指定参数的情况下,$_指向了从文件中读取的每一行
# Perl中uc和lc函数,两个函数都是把转换之后的字符串作为返回的值,uc是大写,表示upper convert,lc是小写,表示lower convert

while(<SPHLIST>) {
  chomp;
  $sph = $_;   # 标量
  @toks = split("/",$sph);    # 数组
  $sph_id = (split("[./]",$toks[$#toks]))[0];
  $call_id = (split("_", $sph_id))[2];
  $call2sph[$call_id] = $sph;      #  这里对之前定义的哈希,进行了内容的填充
}

while (<SUBJECTS>) {
  chomp;
  $line = $_;
  @toks = split(",", $line);
  $spk = $toks[0];
  $gender = lc $toks[1];
  if ($gender eq "f" or $gender eq "m") {
    print GNDR "$spk $gender\n";
  }
}

$num_good_files = 0;
$num_bad_files = 0;
while (<META>) {
  chomp;
  $line = $_;
  @toks = split(",", $line);
  $call_id = $toks[0];
  ($call_date, $call_time) = split(/_/, $toks[1]);
  $sid_A = $toks[4];
  $sid_B = $toks[12];
  if (-f $call2sph[$call_id]) {
    $utt_A = "${sid_A}_MX6_${call_id}_A";
    $utt_B = "${sid_B}_MX6_${call_id}_B";
    print SPKR "${utt_A} $sid_A\n";           # SPKR 代表一个文件,$out_dir/utt2spk
    print SPKR "${utt_B} $sid_B\n";           # WAV  也代表一个文件,$out_dir/wav.scp
    print WAV "${utt_A} sph2pipe -f wav -p -c 1 $call2sph[$call_id] |\n";  
    # 这里主要调用sph2pipe,这个c++工具来转换语音格式,SPHERE2WAV,电话语音的原始格式是SPHERE的
    print WAV "${utt_B} sph2pipe -f wav -p -c 2 $call2sph[$call_id] |\n";   
    # 能转成功就是good file,不能就是bad file
    $num_good_files++;
  } else {
    print STDERR "Sphere file for $call_id doesn't exist\n";
    $num_bad_files++;
  }
}

print STDERR "Processed $num_good_files utterances; $num_bad_files had missing sphere data.\n";

close(SPHLIST) || die;
close(SUBJECTS) || die;
close(GNDR) || die;
close(SPKR) || die;
close(WAV) || die;
close(META) || die;

# 自动生成spk2utt
if (system(
  "utils/utt2spk_to_spk2utt.pl $out_dir/utt2spk >$out_dir/spk2utt") != 0) {
  die "Error creating spk2utt file in directory $out_dir";
}

# 调用fix_data_dir.sh和validate_data_dir.sh
system("utils/fix_data_dir.sh $out_dir");
if (system("utils/validate_data_dir.sh --no-text --no-feats $out_dir") != 0) {
  die "Error validating directory $out_dir";
}

# system后面括号中的字符串是一个命令,如果返回值非0,则表示在执行该命令的过程中出错,则显示die后面的字符串
# system()会调用fork()产生子进程,由子进程来执行参数string字符串所代表的命令。此命令执行完后随即返回原调用的进程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值