def create_original_spectrograms(self, samples, n, species_wav_input_dir, species_spectrogram_output_dir): samples = random.sample(samples, int(n)) # choose n from all samples for sample_name in samples: SoundProcessor.create_spectrogram(sample_name, species_wav_input_dir, species_spectrogram_output_dir, n_mels=128)
def test_create_one_spectro(self): # Test creating one spectrogram from an audio # file. Ensure that sample rate, duration, and # species are included int the destination spectrogram # .png file: audio_path = os.path.join(self.cur_dir, 'audio_aug_tst_data/DYSMEN_S/dys1.mp3') (aud, sr) = SoundProcessor.load_audio(audio_path) with tempfile.NamedTemporaryFile(suffix='.png', prefix='spectro', dir='/tmp', delete=True) as fd: SoundProcessor.create_spectrogram(aud, sr, fd.name, info={'species': 'DYSMEN_C'}) _spectro, info = SoundProcessor.load_spectrogram(fd.name) truth = {'sr': '22050', 'duration': '10.8', 'species': 'DYSMEN_C'} self.assertDictEqual(info, truth)
def create_new_sample(self, sample_name, paths, num_augs=1): (species_wav_input_dir, species_wav_output_dir, species_spectrogram_output_dir) = paths aug_choices = np.random.choice(self.AUDIO_AUG_NAMES, size=num_augs, p=self.P_DIST, replace=False) # input(f"Aug choices: {aug_choices}") # Warping must be done after all the other augmentations take place, # after spectrogram is created warp = False if "warp" in aug_choices: warp = True aug_choices = aug_choices.tolist() # print(f"Aug chioces as list: {aug_choices}") aug_choices.remove("warp") # print(f"Aug chioces after: {aug_choices}") for i in range(len(aug_choices)): # print(aug_choices) aug_name = aug_choices[i] if i != 0: # if not first augmentation, then, source wav is in output wav directory species_wav_input_dir = species_wav_output_dir if aug_name == "add_noise": # Add_noise; which noise to add will be chosen at random updated_name = SoundProcessor.add_background( sample_name, self.NOISE_PATH, species_wav_input_dir, species_wav_output_dir, len_noise_to_add=5.0) elif aug_name == "time_shift": updated_name = SoundProcessor.time_shift( sample_name, species_wav_input_dir, species_wav_output_dir) sample_name = updated_name # create new spectrogram if augmented if len(aug_choices) != 0: sample_name = SoundProcessor.create_spectrogram( sample_name, species_wav_output_dir, species_spectrogram_output_dir, n_mels=128) if warp: #warp # if len(aug_choices) +1 > 1: # input(f"num_augs = {len(aug_choices) +1} for {sample_name}") sample_name = sample_name[:-len(".wav")] + ".png" # Above: if sample is unaugmented to this point, sample_name will be # *.wav. Since SoundProcessor.warp_spectrogram expects sample_name to be *.png, we # replace extension. If augmented and sample_name is already *.png, # there is no change. warped_name = SoundProcessor.warp_spectrogram( sample_name, species_spectrogram_output_dir, species_spectrogram_output_dir) # if warp is not the only augmentation, # we do not want spectrogram before warp if len(aug_choices) != 0: assert (warped_name != sample_name) fname = os.path.join(species_spectrogram_output_dir, sample_name) os.remove(fname)
def chop_one_audio_file(self, in_dir, species, spectro_fname, out_dir, window_len = 5): """ Generates window_len second sound file snippets and associated spectrograms from sound files of arbitrary length. Performs a time shift on all the wav files in the species directories. The shift is 'rolling' such that no information is lost. :param in_dir: directory of the audio file to chop :type file_name: str :param species: the directory names of the species to modify the wav files of. If species=None, all subdirectories will be processed. :type species: {None | [str]} :param spectro_fname: basefile name of audio file to chop :type spectro_fname: str :param out_dir: root directory under which spectrogram and audio snippets will be saved (in different subdirs) :type out_dir: str """ orig, sample_rate = librosa.load(os.path.join(in_dir, species, spectro_fname)) length = int(librosa.get_duration(orig, sample_rate)) for start_time in range(length - window_len): fpath = Path(spectro_fname) window_name = f"{fpath.stem}_sw-start{str(start_time)}" window_file_name = str(Path.joinpath(fpath.parent, window_name)) outfile_spectro = os.path.join(out_dir, 'spectrograms/', species, f"{window_file_name}.png") outfile_audio = os.path.join(out_dir, 'wav-files', species, f"{window_file_name}.{'wav'}") spectro_done = os.path.exists(outfile_spectro) audio_done = os.path.exists(outfile_audio) if spectro_done and audio_done and WhenAlreadyDone.SKIP: # No brainer no need to even read the audio excerpt: continue if spectro_done and not audio_done and not self.generate_wav_files: continue # Need an audio snippet either for # a spectrogram or wav file: window_audio, sr = librosa.load(os.path.join(in_dir, species, spectro_fname), offset=start_time, duration=window_len) if not spectro_done or (spectro_done and self.overwrite_policy != WhenAlreadyDone.SKIP): SoundProcessor.create_spectrogram(window_audio,sr,outfile_spectro) if self.generate_wav_files: if audio_done and self.overwrite_policy == WhenAlreadyDone.SKIP: continue else: sf.write(outfile_audio, window_audio, sr)