|
|
|
@ -20,31 +20,29 @@ import csv
|
|
|
|
|
import os
|
|
|
|
|
from typing import List
|
|
|
|
|
|
|
|
|
|
import paddle
|
|
|
|
|
import tqdm
|
|
|
|
|
from yacs.config import CfgNode
|
|
|
|
|
|
|
|
|
|
from paddlespeech.s2t.utils.log import Log
|
|
|
|
|
from paddlespeech.vector.training.seeding import seed_everything
|
|
|
|
|
logger = Log(__name__).getlog()
|
|
|
|
|
from paddleaudio import load as load_audio
|
|
|
|
|
from paddleaudio import save as save_wav
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_chunks(seg_dur, audio_id, audio_duration):
|
|
|
|
|
num_chunks = int(audio_duration / seg_dur) # all in milliseconds
|
|
|
|
|
from paddlespeech.s2t.utils.log import Log
|
|
|
|
|
from paddlespeech.vector.utils.utils import get_chunks
|
|
|
|
|
|
|
|
|
|
chunk_lst = [
|
|
|
|
|
audio_id + "_" + str(i * seg_dur) + "_" + str(i * seg_dur + seg_dur)
|
|
|
|
|
for i in range(num_chunks)
|
|
|
|
|
]
|
|
|
|
|
return chunk_lst
|
|
|
|
|
logger = Log(__name__).getlog()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_audio_info(wav_file: str,
|
|
|
|
|
def get_chunks_list(wav_file: str,
|
|
|
|
|
split_chunks: bool,
|
|
|
|
|
base_path: str,
|
|
|
|
|
chunk_duration: float=3.0) -> List[List[str]]:
|
|
|
|
|
"""Get the single audio file info
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
wav_file (list): the wav audio file and get this audio segment info list
|
|
|
|
|
split_chunks (bool): audio split flag
|
|
|
|
|
base_path (str): the audio base path
|
|
|
|
|
chunk_duration (float): the chunk duration.
|
|
|
|
|
if set the split_chunks, we split the audio into multi-chunks segment.
|
|
|
|
|
"""
|
|
|
|
|
waveform, sr = load_audio(wav_file)
|
|
|
|
|
audio_id = wav_file.split("/rir_noise/")[-1].split(".")[0]
|
|
|
|
|
audio_duration = waveform.shape[0] / sr
|
|
|
|
@ -57,13 +55,16 @@ def get_audio_info(wav_file: str,
|
|
|
|
|
s, e = chunk.split("_")[-2:] # Timestamps of start and end
|
|
|
|
|
start_sample = int(float(s) * sr)
|
|
|
|
|
end_sample = int(float(e) * sr)
|
|
|
|
|
new_wav_file = os.path.join(base_path,
|
|
|
|
|
audio_id + f'_chunk_{idx+1:02}.wav')
|
|
|
|
|
save_wav(waveform[start_sample:end_sample], sr, new_wav_file)
|
|
|
|
|
# id, duration, new_wav
|
|
|
|
|
ret.append([chunk, chunk_duration, new_wav_file])
|
|
|
|
|
|
|
|
|
|
# currently, all vector csv data format use one representation
|
|
|
|
|
# id, duration, wav, start, stop, spk_id
|
|
|
|
|
ret.append([
|
|
|
|
|
chunk, audio_duration, wav_file, start_sample, end_sample,
|
|
|
|
|
"noise"
|
|
|
|
|
])
|
|
|
|
|
else: # Keep whole audio.
|
|
|
|
|
ret.append([audio_id, audio_duration, wav_file])
|
|
|
|
|
ret.append(
|
|
|
|
|
[audio_id, audio_duration, wav_file, 0, waveform.shape[0], "noise"])
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -71,12 +72,20 @@ def generate_csv(wav_files,
|
|
|
|
|
output_file: str,
|
|
|
|
|
base_path: str,
|
|
|
|
|
split_chunks: bool=True):
|
|
|
|
|
print(f'Generating csv: {output_file}')
|
|
|
|
|
header = ["id", "duration", "wav"]
|
|
|
|
|
"""Prepare the csv file according the wav files
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
wav_files (list): all the audio list to prepare the csv file
|
|
|
|
|
output_file (str): the output csv file
|
|
|
|
|
config (CfgNode): yaml configuration content
|
|
|
|
|
split_chunks (bool): audio split flag
|
|
|
|
|
"""
|
|
|
|
|
logger.info(f'Generating csv: {output_file}')
|
|
|
|
|
header = ["utt_id", "duration", "wav", "start", "stop", "lab_id"]
|
|
|
|
|
csv_lines = []
|
|
|
|
|
for item in tqdm.tqdm(wav_files):
|
|
|
|
|
csv_lines.extend(
|
|
|
|
|
get_audio_info(
|
|
|
|
|
get_chunks_list(
|
|
|
|
|
item, base_path=base_path, split_chunks=split_chunks))
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(os.path.dirname(output_file)):
|
|
|
|
@ -91,11 +100,12 @@ def generate_csv(wav_files,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def prepare_data(args, config):
|
|
|
|
|
# stage0: set the cpu device,
|
|
|
|
|
# all data prepare process will be done in cpu mode
|
|
|
|
|
paddle.device.set_device("cpu")
|
|
|
|
|
# set the random seed, it is a must for multiprocess training
|
|
|
|
|
seed_everything(config.seed)
|
|
|
|
|
"""Convert the jsonline format to csv format
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
args (argparse.Namespace): scripts args
|
|
|
|
|
config (CfgNode): yaml configuration content
|
|
|
|
|
"""
|
|
|
|
|
# if external config set the skip_prep flat, we will do nothing
|
|
|
|
|
if config.skip_prep:
|
|
|
|
|
return
|
|
|
|
@ -119,6 +129,7 @@ def prepare_data(args, config):
|
|
|
|
|
noise_files.append(os.path.join(base_path, noise_file))
|
|
|
|
|
|
|
|
|
|
csv_path = os.path.join(args.data_dir, 'csv')
|
|
|
|
|
logger.info(f"csv path: {csv_path}")
|
|
|
|
|
generate_csv(
|
|
|
|
|
rir_files, os.path.join(csv_path, 'rir.csv'), base_path=base_path)
|
|
|
|
|
generate_csv(
|
|
|
|
|