Skip to content

Commit

Permalink
Clean up and improve testing
Browse files Browse the repository at this point in the history
  • Loading branch information
mmcauliffe committed Aug 13, 2021
1 parent 75798c2 commit c68ac0a
Show file tree
Hide file tree
Showing 13 changed files with 133 additions and 354 deletions.
5 changes: 4 additions & 1 deletion montreal_forced_aligner/command_line/adapt.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,15 @@ def adapt_model(args, unknown_args=None):
training_config = acoustic_model.adaptation_config()
logger.debug('ADAPT TRAINING CONFIG:')
log_config(logger, training_config)
audio_dir = None
if args.audio_directory:
audio_dir = args.audio_directory
try:
corpus = AlignableCorpus(args.corpus_directory, data_directory,
speaker_characters=args.speaker_characters,
num_jobs=args.num_jobs, sample_rate=align_config.feature_config.sample_frequency,
logger=logger, use_mp=align_config.use_mp, punctuation=align_config.punctuation,
clitic_markers=align_config.clitic_markers)
clitic_markers=align_config.clitic_markers, audio_directory=audio_dir)
if corpus.issues_check:
logger.warning('Some issues parsing the corpus were detected. '
'Please run the validator to get more information.')
Expand Down
5 changes: 4 additions & 1 deletion montreal_forced_aligner/command_line/align.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,15 @@ def align_corpus(args, unknown_args=None):
os.makedirs(args.output_directory, exist_ok=True)
acoustic_model = AcousticModel(args.acoustic_model_path, root_directory=model_directory)
acoustic_model.log_details(logger)
audio_dir = None
if args.audio_directory:
audio_dir = args.audio_directory
try:
corpus = AlignableCorpus(args.corpus_directory, data_directory,
speaker_characters=args.speaker_characters,
num_jobs=args.num_jobs, sample_rate=align_config.feature_config.sample_frequency,
logger=logger, use_mp=align_config.use_mp, punctuation=align_config.punctuation,
clitic_markers=align_config.clitic_markers)
clitic_markers=align_config.clitic_markers, audio_directory=audio_dir)
if corpus.issues_check:
logger.warning('Some issues parsing the corpus were detected. '
'Please run the validator to get more information.')
Expand Down
6 changes: 6 additions & 0 deletions montreal_forced_aligner/command_line/mfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ def unfix_path():
'default is to use directory names')
align_parser.add_argument('-t', '--temp_directory', type=str, default='',
help='Temporary directory root to use for aligning, default is ~/Documents/MFA')
align_parser.add_argument('-a', '--audio_directory', type=str, default='',
help='Audio directory root to use for finding audio files')
align_parser.add_argument('-j', '--num_jobs', type=int, default=3,
help='Number of cores to use while aligning')
align_parser.add_argument('-v', '--verbose', help="Print more information during alignment", action='store_true')
Expand All @@ -94,6 +96,8 @@ def unfix_path():
'default is to use directory names')
adapt_parser.add_argument('-t', '--temp_directory', type=str, default='',
help='Temporary directory root to use for aligning, default is ~/Documents/MFA')
adapt_parser.add_argument('-a', '--audio_directory', type=str, default='',
help='Audio directory root to use for finding audio files')
adapt_parser.add_argument('-j', '--num_jobs', type=int, default=3,
help='Number of cores to use while aligning')
adapt_parser.add_argument('-v', '--verbose', help="Print more information during alignment", action='store_true')
Expand All @@ -115,6 +119,8 @@ def unfix_path():
'default is to use directory names')
train_parser.add_argument('-t', '--temp_directory', type=str, default='',
help='Temporary directory root to use for aligning, default is ~/Documents/MFA')
train_parser.add_argument('-a', '--audio_directory', type=str, default='',
help='Audio directory root to use for finding audio files')
train_parser.add_argument('-j', '--num_jobs', type=int, default=3,
help='Number of cores to use while aligning')
train_parser.add_argument('-v', '--verbose', help="Output debug messages about alignment", action='store_true')
Expand Down
5 changes: 4 additions & 1 deletion montreal_forced_aligner/command_line/train_and_align.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,15 @@ def align_corpus(args, unknown_args=None):
os.makedirs(data_directory, exist_ok=True)
model_directory = os.path.join(data_directory, 'acoustic_models')
os.makedirs(args.output_directory, exist_ok=True)
audio_dir = None
if args.audio_directory:
audio_dir = args.audio_directory
try:
corpus = AlignableCorpus(args.corpus_directory, data_directory, speaker_characters=args.speaker_characters,
num_jobs=getattr(args, 'num_jobs', 3),
sample_rate=align_config.feature_config.sample_frequency,
debug=getattr(args, 'debug', False), logger=logger, use_mp=align_config.use_mp,
punctuation=align_config.punctuation, clitic_markers=align_config.clitic_markers)
punctuation=align_config.punctuation, clitic_markers=align_config.clitic_markers, audio_directory=audio_dir)
if corpus.issues_check:
logger.warning('Some issues parsing the corpus were detected. '
'Please run the validator to get more information.')
Expand Down
4 changes: 2 additions & 2 deletions montreal_forced_aligner/command_line/transcribe.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ def transcribe_corpus(args, unknown_args):
punctuation=transcribe_config.punctuation,
clitic_markers=transcribe_config.clitic_markers,
compound_markers=transcribe_config.compound_markers,
multilingual_ipa=transcribe_config.multilingual_ipa)
multilingual_ipa=acoustic_model.meta['multilingual_ipa'])
else:
dictionary = Dictionary(args.dictionary_path, data_directory, logger=logger,
punctuation=transcribe_config.punctuation,
clitic_markers=transcribe_config.clitic_markers,
compound_markers=transcribe_config.compound_markers,
multilingual_ipa=transcribe_config.multilingual_ipa)
multilingual_ipa=acoustic_model.meta['multilingual_ipa'])
acoustic_model.validate(dictionary)
begin = time.time()
t = Transcriber(corpus, dictionary, acoustic_model, language_model, transcribe_config,
Expand Down
199 changes: 2 additions & 197 deletions montreal_forced_aligner/features/processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ def mfcc_func(directory, job_name, mfcc_options):
copy_proc.communicate()

utt_lengths_proc = subprocess.Popen([thirdparty_binary('feat-to-len'),
'scp:' + raw_scp_path, 'ark,t:'+ lengths_path],
stderr=log_file)
'scp:' + raw_scp_path, 'ark,t:' + lengths_path],
stderr=log_file)
utt_lengths_proc.communicate()


Expand Down Expand Up @@ -127,198 +127,3 @@ def compute_vad(directory, num_jobs, use_mp, vad_config=None):
run_mp(compute_vad_func, jobs, log_directory)
else:
run_non_mp(compute_vad_func, jobs, log_directory)


def apply_cmvn_func(directory, job_name, config):
normed_scp_path = os.path.join(directory, config.raw_feature_id + '.{}.scp'.format(job_name))
normed_ark_path = os.path.join(directory, config.raw_feature_id + '.{}.ark'.format(job_name))
with open(os.path.join(directory, 'log', 'norm.{}.log'.format(job_name)), 'w') as log_file:
utt2spk_path = os.path.join(directory, 'utt2spk.{}'.format(job_name))
cmvn_path = os.path.join(directory, 'cmvn.{}.scp'.format(job_name))
feats_path = os.path.join(directory, 'feats.{}.scp'.format(job_name))
if not os.path.exists(normed_scp_path):
cmvn_proc = subprocess.Popen([thirdparty_binary('apply-cmvn'),
'--utt2spk=ark:' + utt2spk_path,
'scp:' + cmvn_path,
'scp:' + feats_path,
'ark,scp:{},{}'.format(normed_ark_path, normed_scp_path)],
stderr=log_file
)
cmvn_proc.communicate()


def apply_cmvn(directory, num_jobs, config):
log_directory = os.path.join(directory, 'log')
os.makedirs(log_directory, exist_ok=True)
jobs = [(directory, x, config)
for x in range(num_jobs)]
if config.use_mp:
run_mp(apply_cmvn_func, jobs, log_directory)
else:
run_non_mp(apply_cmvn_func, jobs, log_directory)


def select_voiced_func(directory, job_name, apply_cmn):
feats_path = os.path.join(directory, 'feats.{}.scp'.format(job_name))
vad_scp_path = os.path.join(directory, 'vad.{}.scp'.format(job_name))
voiced_scp_path = os.path.join(directory, 'feats_voiced.{}.scp'.format(job_name))
voiced_ark_path = os.path.join(directory, 'feats_voiced.{}.ark'.format(job_name))
with open(os.path.join(directory, 'log', 'select-voiced.{}.log'.format(job_name)), 'w') as log_file:
deltas_proc = subprocess.Popen([thirdparty_binary('add-deltas'),
'scp:' + feats_path,
'ark:-'
], stdout=subprocess.PIPE, stderr=log_file)
if apply_cmn:
cmvn_proc = subprocess.Popen([thirdparty_binary('apply-cmvn-sliding'),
'--norm-vars=false',
'--center=true',
'--cmn-window=300',
'ark:-', 'ark:-'],
stdin=deltas_proc.stdout, stdout=subprocess.PIPE, stderr=log_file)
select_proc = subprocess.Popen([thirdparty_binary('select-voiced-frames'),
'ark:-',
'scp,s,cs:' + vad_scp_path,
'ark,scp:{},{}'.format(voiced_ark_path, voiced_scp_path)],
stdin=cmvn_proc.stdout, stderr=log_file)
else:
select_proc = subprocess.Popen([thirdparty_binary('select-voiced-frames'),
'ark:-',
'scp,s,cs:' + vad_scp_path,
'ark,scp:{},{}'.format(voiced_ark_path, voiced_scp_path)],
stdin=deltas_proc.stdout, stderr=log_file)
select_proc.communicate()


def select_voiced(directory, num_jobs, config, apply_cmn=False):
log_directory = os.path.join(directory, 'log')
os.makedirs(log_directory, exist_ok=True)
jobs = [(directory, x, apply_cmn)
for x in range(num_jobs)]
if config.use_mp:
run_mp(select_voiced_func, jobs, log_directory)
else:
run_non_mp(select_voiced_func, jobs, log_directory)


def compute_ivector_features_func(directory, job_name, apply_cmn):
feats_path = os.path.join(directory, 'feats.{}.scp'.format(job_name))
out_feats_scp_path = os.path.join(directory, 'feats_for_ivector.{}.scp'.format(job_name))
out_feats_ark_path = os.path.join(directory, 'feats_for_ivector.{}.ark'.format(job_name))

with open(os.path.join(directory, 'log', 'cmvn_sliding.{}.log'.format(job_name)), 'w') as log_file:
if apply_cmn:
deltas_proc = subprocess.Popen([thirdparty_binary('add-deltas'),
'scp:' + feats_path,
'ark:-'
], stdout=subprocess.PIPE, stderr=log_file)

cmvn_proc = subprocess.Popen([thirdparty_binary('apply-cmvn-sliding'),
'--norm-vars=false',
'--center=true',
'--cmn-window=300',
'ark:-', 'ark,scp:{},{}'.format(out_feats_ark_path, out_feats_scp_path)],
stdin=deltas_proc.stdout, stdout=subprocess.PIPE, stderr=log_file)
cmvn_proc.communicate()
else:
deltas_proc = subprocess.Popen([thirdparty_binary('add-deltas'),
'scp:' + feats_path,
'ark,scp:{},{}'.format(out_feats_ark_path, out_feats_scp_path)
], stderr=log_file)
deltas_proc.communicate()


def compute_ivector_features(directory, num_jobs, config, apply_cmn=False):
log_directory = os.path.join(directory, 'log')
os.makedirs(log_directory, exist_ok=True)
jobs = [(directory, x, apply_cmn)
for x in range(num_jobs)]
if config.use_mp:
run_mp(compute_ivector_features_func, jobs, log_directory)
else:
run_non_mp(compute_ivector_features_func, jobs, log_directory)


def generate_spliced_features_func(directory, raw_feature_id, config, job_name):
normed_scp_path = os.path.join(directory, raw_feature_id + '.{}.scp'.format(job_name))
spliced_feature_id = raw_feature_id + '_spliced'
ark_path = os.path.join(directory, spliced_feature_id + '.{}.ark'.format(job_name))
scp_path = os.path.join(directory, spliced_feature_id + '.{}.scp'.format(job_name))
log_path = os.path.join(directory, 'log', 'lda.{}.log'.format(job_name))
with open(log_path, 'a') as log_file:
splice_feats_proc = subprocess.Popen([thirdparty_binary('splice-feats'),
'--left-context={}'.format(config['splice_left_context']),
'--right-context={}'.format(config['splice_right_context']),
'scp:' + normed_scp_path,
'ark,scp:{},{}'.format(ark_path, scp_path)],
stderr=log_file)
splice_feats_proc.communicate()


def generate_spliced_features(directory, num_jobs, config):
log_directory = os.path.join(directory, 'log')
os.makedirs(log_directory, exist_ok=True)
jobs = [(directory, config.raw_feature_id, config.splice_options, x)
for x in range(num_jobs)]
if config.use_mp:
run_mp(generate_spliced_features_func, jobs, log_directory)
else:
run_non_mp(generate_spliced_features_func, jobs, log_directory)


def add_deltas_func(directory, job_name, config):
normed_scp_path = os.path.join(directory, config.raw_feature_id + '.{}.scp'.format(job_name))
ark_path = os.path.join(directory, config.feature_id + '.{}.ark'.format(job_name))
scp_path = os.path.join(directory, config.feature_id + '.{}.scp'.format(job_name))
with open(os.path.join(directory, 'log', 'add_deltas.{}.log'.format(job_name)), 'w') as log_file:
if config.fmllr_path is not None and os.path.exists(config.fmllr_path):
deltas_proc = subprocess.Popen([thirdparty_binary('add-deltas'),
'scp:' + normed_scp_path, 'ark:-'],
stderr=log_file,
stdout=subprocess.PIPE)
trans_proc = subprocess.Popen([thirdparty_binary('transform-feats'),
'ark:' + config.fmllr_path, 'ark:-',
'ark,scp:{},{}'.format(ark_path, scp_path)],
stdin=deltas_proc.stdout,
stderr=log_file)
trans_proc.communicate()
else:
deltas_proc = subprocess.Popen([thirdparty_binary('add-deltas'),
'scp:' + normed_scp_path, 'ark,scp:{},{}'.format(ark_path, scp_path)],
stderr=log_file)
deltas_proc.communicate()


def add_deltas(directory, num_jobs, config):
log_directory = os.path.join(directory, 'log')
os.makedirs(log_directory, exist_ok=True)
jobs = [(directory, x, config)
for x in range(num_jobs)]
if config.use_mp:
run_mp(add_deltas_func, jobs, log_directory)
else:
run_non_mp(add_deltas_func, jobs, log_directory)


def apply_lda_func(directory, spliced_feature_id, feature_id, lda_path, job_name):
normed_scp_path = os.path.join(directory, spliced_feature_id + '.{}.scp'.format(job_name))
ark_path = os.path.join(directory, feature_id + '.{}.ark'.format(job_name))
scp_path = os.path.join(directory, feature_id + '.{}.scp'.format(job_name))
log_path = os.path.join(directory, 'log', 'lda.{}.log'.format(job_name))
with open(log_path, 'a') as log_file:
transform_feats_proc = subprocess.Popen([thirdparty_binary("transform-feats"),
lda_path,
'scp:'+ normed_scp_path,
'ark,scp:{},{}'.format(ark_path, scp_path)],
stderr=log_file)
transform_feats_proc.communicate()


def apply_lda(directory, num_jobs, config):
log_directory = os.path.join(directory, 'log')
os.makedirs(log_directory, exist_ok=True)
jobs = [(directory, config.spliced_feature_id, config.feature_id, config.lda_path, x)
for x in range(num_jobs)]
if config.use_mp and False: # Looks to be threaded
run_mp(apply_lda_func, jobs, log_directory)
else:
run_non_mp(apply_lda_func, jobs, log_directory)
Loading

0 comments on commit c68ac0a

Please sign in to comment.