def test_select_features(): my_file_struct = FileStruct(os.path.join("fixtures", "chirp.mp3")) feature = Features.select_features("pcp", my_file_struct, False, True) assert isinstance(feature, PCP) assert feature.feat_type == FeatureTypes.framesync feature = Features.select_features("mfcc", my_file_struct, False, False) assert isinstance(feature, MFCC) assert feature.feat_type == FeatureTypes.est_beatsync feature = Features.select_features("cqt", my_file_struct, True, False) assert isinstance(feature, CQT) assert feature.feat_type == FeatureTypes.ann_beatsync
def compute_all_features(file_struct, framesync): """Computes all features for the given file.""" for feature_id in msaf.features_registry: logging.info("Computing %s for file %s" % (feature_id, file_struct.audio_file)) feats = Features.select_features(feature_id, file_struct, False, framesync) feats.features
def process_track(file_struct, boundaries_id, labels_id, config, annotator_id=0): """Prepares the parameters, runs the algorithms, and saves results. Parameters ---------- file_struct: `msaf.io.FileStruct` FileStruct containing the paths of the input files (audio file, features file, reference file, output estimation file). boundaries_id: str Identifier of the boundaries algorithm to use ("gt" for ground truth). labels_id: str Identifier of the labels algorithm to use (None for not labeling). config: dict Dictionary containing the custom parameters of the algorithms to use. annotator_id: int Annotator identificator in the ground truth. Returns ------- est_times: np.array List of estimated times for the segment boundaries. est_labels: np.array List of all the labels associated segments. """ logging.info("Segmenting %s" % file_struct.audio_file) # Get features config["features"] = Features.select_features(config["feature"], file_struct, config["annot_beats"], config["framesync"]) # Get estimations est_times, est_labels = run_algorithms(file_struct, boundaries_id, labels_id, config, annotator_id=annotator_id) # Save logging.info("Writing results in: %s" % file_struct.est_file) io.save_estimations(file_struct, est_times, est_labels, boundaries_id, labels_id, **config) return est_times, est_labels
def test_no_gt_flat_bounds(): """Make sure the results are empty if there is not ground truth found.""" feature = "pcp" annot_beats = False framesync = False file_struct = msaf.io.FileStruct(audio_file) file_struct.features_file = msaf.config.features_tmp_file config = {} config["features"] = Features.select_features( feature, file_struct, annot_beats, framesync) est_times, est_labels = msaf.run.run_flat(file_struct, None, None, None, config, 0) assert(not est_times) assert(not est_labels)
def test_no_gt_flat_bounds(): """Make sure the results are empty if there is not ground truth found.""" feature = "pcp" annot_beats = False framesync = False file_struct = msaf.io.FileStruct(audio_file) file_struct.features_file = msaf.config.features_tmp_file config = {} config["features"] = Features.select_features(feature, file_struct, annot_beats, framesync) est_times, est_labels = msaf.run.run_flat(file_struct, None, None, None, config, 0) assert (not est_times) assert (not est_labels)
def _test_run_msaf(bound_id, label_id, hier=False): config = msaf.io.get_configuration(feature, annot_beats, framesync, bound_id, label_id) config["hier"] = hier config["features"] = Features.select_features( feature, file_struct, annot_beats, framesync) est_times, est_labels = msaf.run.run_algorithms( file_struct, bound_id, label_id, config) # Take the first level if hierarchy algorithm if hier: est_times = est_times[0] est_labels = est_labels[0] npt.assert_almost_equal(est_times[0], 0.0, decimal=2) assert len(est_times) - 1 == len(est_labels) npt.assert_almost_equal(est_times[-1], config["features"].dur, decimal=2)
def _test_run_msaf(bound_id, label_id, hier=False): config = msaf.io.get_configuration(feature, annot_beats, framesync, bound_id, label_id) config["hier"] = hier config["features"] = Features.select_features(feature, file_struct, annot_beats, framesync) est_times, est_labels = msaf.run.run_algorithms( file_struct, bound_id, label_id, config) # Take the first level if hierarchy algorithm if hier: est_times = est_times[0] est_labels = est_labels[0] npt.assert_almost_equal(est_times[0], 0.0, decimal=2) assert len(est_times) - 1 == len(est_labels) npt.assert_almost_equal(est_times[-1], config["features"].dur, decimal=2)
def process_track(file_struct, boundaries_id, labels_id, config, annotator_id=0): """Prepares the parameters, runs the algorithms, and saves results. Parameters ---------- file_struct: `msaf.io.FileStruct` FileStruct containing the paths of the input files (audio file, features file, reference file, output estimation file). boundaries_id: str Identifier of the boundaries algorithm to use ("gt" for ground truth). labels_id: str Identifier of the labels algorithm to use (None for not labeling). config: dict Dictionary containing the custom parameters of the algorithms to use. annotator_id: int Annotator identificator in the ground truth. Returns ------- est_times: np.array List of estimated times for the segment boundaries. est_labels: np.array List of all the labels associated segments. """ logging.info("Segmenting %s" % file_struct.audio_file) # Get features config["features"] = Features.select_features( config["feature"], file_struct, config["annot_beats"], config["framesync"]) # Get estimations est_times, est_labels = run_algorithms(file_struct, boundaries_id, labels_id, config, annotator_id=annotator_id) # Save logging.info("Writing results in: %s" % file_struct.est_file) io.save_estimations(file_struct, est_times, est_labels, boundaries_id, labels_id, **config) return est_times, est_labels
def test_run_algorithms(): """Test running all the algorithms.""" bound_ids = msaf.io.get_all_boundary_algorithms() label_ids = msaf.io.get_all_label_algorithms() # Add ground truth to boundary id bound_ids += ["gt"] # Add None to labels label_ids += [None] # Config params feature = "pcp" annot_beats = False framesync = False file_struct = msaf.io.FileStruct(audio_file) file_struct.features_file = msaf.config.features_tmp_file # Running all algorithms on a file that is too short for bound_id in bound_ids: for label_id in label_ids: config = msaf.io.get_configuration(feature, annot_beats, framesync, bound_id, label_id) config["hier"] = False config["features"] = Features.select_features( feature, file_struct, annot_beats, framesync) est_times, est_labels = msaf.run.run_algorithms( file_struct, bound_id, label_id, config) assert len(est_times) == 2 assert len(est_labels) == 1 npt.assert_almost_equal(est_times[0], 0.0, decimal=2) npt.assert_almost_equal(est_times[-1], config["features"].dur, decimal=2) # Commpute and save features for long audio file file_struct = msaf.io.FileStruct(long_audio_file) file_struct.features_file = msaf.config.features_tmp_file def _test_run_msaf(bound_id, label_id, hier=False): config = msaf.io.get_configuration(feature, annot_beats, framesync, bound_id, label_id) config["hier"] = hier config["features"] = Features.select_features( feature, file_struct, annot_beats, framesync) est_times, est_labels = msaf.run.run_algorithms( file_struct, bound_id, label_id, config) # Take the first level if hierarchy algorithm if hier: est_times = est_times[0] est_labels = est_labels[0] npt.assert_almost_equal(est_times[0], 0.0, decimal=2) assert len(est_times) - 1 == len(est_labels) npt.assert_almost_equal(est_times[-1], config["features"].dur, decimal=2) # Running all boundary algorithms on a relatively long file for bound_id in bound_ids: if bound_id == "gt": continue yield (_test_run_msaf, bound_id, None, False) # Combining boundaries with labels for bound_id in bound_ids: if bound_id == "gt" or bound_id == "example": continue for label_id in label_ids: yield (_test_run_msaf, bound_id, label_id, False) # Test the hierarchical algorithms hier_ids = ["olda", "scluster"] for hier_bounds_id in hier_ids: for hier_labels_id in hier_ids: if hier_labels_id == "olda": hier_labels_id = "fmc2d" yield (_test_run_msaf, hier_bounds_id, hier_labels_id, True)
def test_global_compute_features(): my_file_struct = FileStruct(os.path.join("fixtures", "chirp.mp3")) feats = Features(my_file_struct, 11025, 1024, FeatureTypes.framesync) feats.compute_features()
def test_wrong_select_features(): Features.select_features("cqt", None, True, True)
def process(in_path, annot_beats=False, feature="pcp", framesync=False, boundaries_id=msaf.config.default_bound_id, labels_id=msaf.config.default_label_id, hier=False, sonify_bounds=False, plot=False, n_jobs=4, annotator_id=0, config=None, out_bounds="out_bounds.wav", out_sr=22050): """Main process to segment a file or a collection of files. Parameters ---------- in_path: str Input path. If a directory, MSAF will function in collection mode. If audio file, MSAF will be in single file mode. annot_beats: bool Whether to use annotated beats or not. Only available in collection mode. feature: str String representing the feature to be used (e.g. pcp, mfcc, tonnetz) framesync: str Whether to use framesync features or not (default: False -> beatsync) boundaries_id: str Identifier of the boundaries algorithm (use "gt" for groundtruth) labels_id: str Identifier of the labels algorithm (use None to not compute labels) hier : bool Whether to compute a hierarchical or flat segmentation. sonify_bounds: bool Whether to write an output audio file with the annotated boundaries or not (only available in Single File Mode). plot: bool Whether to plot the boundaries and labels against the ground truth. n_jobs: int Number of processes to run in parallel. Only available in collection mode. annotator_id: int Annotator identificator in the ground truth. config: dict Dictionary containing custom configuration parameters for the algorithms. If None, the default parameters are used. out_bounds: str Path to the output for the sonified boundaries (only in single file mode, when sonify_bounds is True. out_sr : int Sampling rate for the sonified bounds. Returns ------- results : list List containing tuples of (est_times, est_labels) of estimated boundary times and estimated labels. If labels_id is None, est_labels will be a list of -1. """ # Seed random to reproduce results np.random.seed(123) # Set up configuration based on algorithms parameters if config is None: config = io.get_configuration(feature, annot_beats, framesync, boundaries_id, labels_id) config["features"] = None # Save multi-segment (hierarchical) configuration config["hier"] = hier if not os.path.exists(in_path): raise NoAudioFileError("File or directory does not exists, %s" % in_path) if os.path.isfile(in_path): # Single file mode # Get (if they exitst) or compute features file_struct = msaf.io.FileStruct(in_path) # Use temporary file in single mode file_struct.features_file = msaf.config.features_tmp_file # Get features config["features"] = Features.select_features( feature, file_struct, annot_beats, framesync) # And run the algorithms est_times, est_labels = run_algorithms(file_struct, boundaries_id, labels_id, config, annotator_id=annotator_id) if sonify_bounds: logging.info("Sonifying boundaries in %s..." % out_bounds) audio_hq, sr = librosa.load(in_path, sr=out_sr) utils.sonify_clicks(audio_hq, est_times, out_bounds, out_sr) if plot: plotting.plot_one_track(file_struct, est_times, est_labels, boundaries_id, labels_id) # TODO: Only save if needed # Save estimations # msaf.utils.ensure_dir(os.path.dirname(file_struct.est_file)) # io.save_estimations(file_struct, est_times, est_labels, # boundaries_id, labels_id, **config) return est_times, est_labels else: # Collection mode file_structs = io.get_dataset_files(in_path) return Parallel(n_jobs=n_jobs)(delayed(process_track)( file_struct, boundaries_id, labels_id, config, annotator_id=annotator_id) for file_struct in file_structs[:])
def test_global_get_id(): Features.get_id()
def process(in_path, annot_beats=False, feature="pcp", framesync=False, boundaries_id=msaf.config.default_bound_id, labels_id=msaf.config.default_label_id, hier=False, sonify_bounds=False, plot=False, n_jobs=4, annotator_id=0, config=None, out_bounds="out_bounds.wav", out_sr=22050, output_file=None): """Main process to segment a file or a collection of files. Parameters ---------- in_path: str Input path. If a directory, MSAF will function in collection mode. If audio file, MSAF will be in single file mode. annot_beats: bool Whether to use annotated beats or not. feature: str String representing the feature to be used (e.g. pcp, mfcc, tonnetz) framesync: str Whether to use framesync features or not (default: False -> beatsync) boundaries_id: str Identifier of the boundaries algorithm (use "gt" for groundtruth) labels_id: str Identifier of the labels algorithm (use None to not compute labels) hier : bool Whether to compute a hierarchical or flat segmentation. sonify_bounds: bool Whether to write an output audio file with the annotated boundaries or not (only available in Single File Mode). plot: bool Whether to plot the boundaries and labels against the ground truth. n_jobs: int Number of processes to run in parallel. Only available in collection mode. annotator_id: int Annotator identificator in the ground truth. config: dict Dictionary containing custom configuration parameters for the algorithms. If None, the default parameters are used. out_bounds: str Path to the output for the sonified boundaries (only in single file mode, when sonify_bounds is True. out_sr : int Sampling rate for the sonified bounds. Returns ------- results : list List containing tuples of (est_times, est_labels) of estimated boundary times and estimated labels. If labels_id is None, est_labels will be a list of -1. """ # Seed random to reproduce results np.random.seed(123) # Set up configuration based on algorithms parameters if config is None: config = io.get_configuration(feature, annot_beats, framesync, boundaries_id, labels_id) config["features"] = None # Save multi-segment (hierarchical) configuration config["hier"] = hier if not os.path.exists(in_path): raise NoAudioFileError("File or directory does not exists, %s" % in_path) if os.path.isfile(in_path): # Single file mode # Get (if they exitst) or compute features file_struct = msaf.io.FileStruct(in_path) # Use temporary file in single mode file_struct.features_file = msaf.config.features_tmp_file # Get features config["features"] = Features.select_features(feature, file_struct, annot_beats, framesync) # And run the algorithms est_times, est_labels = run_algorithms(file_struct, boundaries_id, labels_id, config, annotator_id=annotator_id) if sonify_bounds: logging.info("Sonifying boundaries in %s..." % out_bounds) audio_hq, sr = librosa.load(in_path, sr=out_sr) utils.sonify_clicks(audio_hq, est_times, out_bounds, out_sr) if plot: custom_plotting.plot_one_track(file_struct, est_times, est_labels, boundaries_id, labels_id, output_file=output_file) # TODO: Only save if needed # Save estimations msaf.utils.ensure_dir(os.path.dirname(file_struct.est_file)) io.save_estimations(file_struct, est_times, est_labels, boundaries_id, labels_id, **config) return est_times, est_labels else: # Collection mode file_structs = io.get_dataset_files(in_path) return Parallel(n_jobs=n_jobs)( delayed(process_track)(file_struct, boundaries_id, labels_id, config, annotator_id=annotator_id) for file_struct in file_structs[:])
def test_run_algorithms(): """Test running all the algorithms.""" bound_ids = msaf.io.get_all_boundary_algorithms() label_ids = msaf.io.get_all_label_algorithms() # Add ground truth to boundary id bound_ids += ["gt"] # Add None to labels label_ids += [None] # Config params feature = "pcp" annot_beats = False framesync = False file_struct = msaf.io.FileStruct(audio_file) file_struct.features_file = msaf.config.features_tmp_file # Running all algorithms on a file that is too short for bound_id in bound_ids: for label_id in label_ids: print("bound_id: %s,\tlabel_id: %s" % (bound_id, label_id)) config = msaf.io.get_configuration(feature, annot_beats, framesync, bound_id, label_id) config["hier"] = False config["features"] = Features.select_features( feature, file_struct, annot_beats, framesync) est_times, est_labels = msaf.run.run_algorithms( file_struct, bound_id, label_id, config) assert len(est_times) == 2 assert len(est_labels) == 1 npt.assert_almost_equal(est_times[0], 0.0, decimal=2) npt.assert_almost_equal(est_times[-1], config["features"].dur, decimal=2) # Commpute and save features for long audio file file_struct = msaf.io.FileStruct(long_audio_file) file_struct.features_file = msaf.config.features_tmp_file def _test_run_msaf(bound_id, label_id, hier=False): print("bound_id: %s,\tlabel_id: %s" % (bound_id, label_id)) config = msaf.io.get_configuration(feature, annot_beats, framesync, bound_id, label_id) config["hier"] = hier config["features"] = Features.select_features(feature, file_struct, annot_beats, framesync) est_times, est_labels = msaf.run.run_algorithms( file_struct, bound_id, label_id, config) # Take the first level if hierarchy algorithm if hier: est_times = est_times[0] est_labels = est_labels[0] npt.assert_almost_equal(est_times[0], 0.0, decimal=2) assert len(est_times) - 1 == len(est_labels) npt.assert_almost_equal(est_times[-1], config["features"].dur, decimal=2) # Running all boundary algorithms on a relatively long file # Combining boundaries with labels for bound_id in bound_ids: if bound_id == "gt": continue for label_id in label_ids: yield (_test_run_msaf, bound_id, label_id, False) # Test the hierarchical algorithms hier_ids = ["olda", "scluster"] for hier_bounds_id in hier_ids: for hier_labels_id in hier_ids: if hier_labels_id == "olda": hier_labels_id = "fmc2d" yield (_test_run_msaf, hier_bounds_id, hier_labels_id, True)