Source code for scripts.resample

import os
from multiprocessing import cpu_count

from src.utils.parallel import parallel_process
from nussl import AudioSignal
import os
import glob
from multiprocessing import cpu_count
from . import cmd, document_parser
from argparse import ArgumentParser

import shutil
import logging

[docs]def resample_audio_file(original_path, resample_path, sample_rate, verbose=False): """ Resamples an audio file at one path and places it at another path at a specified sample rate. Args: original_path (str): Path of audio file to be resampled. resample_path (str): Path to save resampled audio file to. sample_rate (int): Sample rate to resample audio file to. """ audio_signal = AudioSignal(original_path) resample = True if os.path.exists(resample_path): resampled_signal = AudioSignal(resample_path) resample = resampled_signal.sample_rate != sample_rate if resample: if verbose: logging.info( f'{original_path} @ {audio_signal.sample_rate} -> {resample_path} @ {sample_rate}' ) audio_signal.resample(sample_rate) audio_signal.write_audio_to_file(resample_path)
[docs]def ig_f(dir, files): """ Filter for making sure something is a file. Args: dir (str): Directory to filter to only look for files. files (list): List of items to filter. Returns: list: Filtered list. """ return [f for f in files if os.path.isfile(os.path.join(dir, f))]
[docs]def resample(input_path, output_path, sample_rate, num_workers=1, audio_extensions=['.wav', '.mp3', '.aac']): """ Resamples a folder of audio files into a copy of the same folder with the same structure but with every audio file replaced with a resampled version of that audio file. Relative paths to the audio file from the root of the folder will be the same. Args: input_path (str): Root of folder where all audio files will be resampled. output_path (str): Root of folder where all resampled files will be placed. Will match the same structure as the input_path folder structure. sample_rate (int): Sample rate to resample files to. num_workers (int, optional): How many workers to use in parallel to resample files. Defaults to 1. audio_extensions (list, optional): Audio extensions to look for in the input_path. Matching ones will be resampled and placed in the output_path at the same relative location. Defaults to ['.wav', '.mp3', '.aac']. """ try: shutil.copytree(input_path, output_path, ignore=ig_f) except: pass input_audio_files = [] for ext in audio_extensions: input_audio_files += glob.glob( f"{input_path}/**/*{ext}", recursive=True ) output_audio_files = [ x.replace(input_path, output_path) for x in input_audio_files ] arguments = [ { 'original_path': input_audio_files[i], 'resample_path': output_audio_files[i][:-4] + '.wav', 'sample_rate': sample_rate, 'verbose': False if i > 0 else True } for i in range(len(input_audio_files)) ] parallel_process( arguments, resample_audio_file, n_jobs=min(num_workers, cpu_count()), front_num=1, use_kwargs=True, )
[docs]@document_parser('resample', 'scripts.resample.resample') def build_parser(): parser = ArgumentParser() parser.add_argument( '--input_path', type=str, help="""Root of folder where all audio files will be resampled.""" ) parser.add_argument( '--output_path', type=str, help="""Root of folder where all resampled files will be placed. Will match the same structure as the input_path folder structure.""" ) parser.add_argument( '--sample_rate', type=int, help="""Sample rate to resample files to.""" ) parser.add_argument( '--num_workers', type=int, help="""How many workers to use in parallel to resample files.""", default=1 ) parser.add_argument( '--audio_extensions', nargs='+', help="""Audio extensions to look for in the input_path. Matching ones will be resampled and placed in the output_path at the same relative location.""", default=['.wav', '.mp3', '.aac'] ) return parser
if __name__ == '__main__': cmd(resample, build_parser)