def handle(self, dbs, *args, **options): # Correct false wav info for af in AudioFile.objects.all(): wav_file_path = wav_path(af, 'wav') fs, length = get_wav_info(wav_file_path) if fs != af.fs or length != af.length: print( 'Correct file {}, originally length={} fs={}, now length={}, fs={}' .format(af.name, af.length, af.fs, length, fs)) af.fs = fs af.length = length af.save() conns = None try: conns = get_dbconf(dbs) for pop in conns: conn = conns[pop] cur = conn.cursor() bitrate = 16 song_cur = conn.cursor( cursor_factory=psycopg2.extras.RealDictCursor) song_cur.execute( 'select w.framesize, w.stereo, w.samplerate, w.ssizeinbits, w.songid, s.name ' 'from wavs w join songdata s on w.songid=s.id where w.ssizeinbits={}' .format(bitrate)) songs = song_cur.fetchall() for song in songs: song_name = song['name'] # Import WAV data and save as WAV and MP3 files wav_file_path = '/tmp/{}'.format(song_name) mp3_file_path = '/tmp/{}.mp3'.format(song_name) fs, length = import_pcm(song, cur, song_name, wav_file_path, mp3_file_path) fs1, length1 = get_wav_info(wav_file_path) if fs != fs1 or length != length1: print('-------SHIT--------') print( 'Song {} length = {} fs = {} time = {}, length1 = {} fs1 = {} time1 = {}' .format(song_name, length, fs, length / fs, length1, fs1, length1 / fs1)) finally: for dbconf in conns: conn = conns[dbconf] if conn is not None: conn.close()
def extract_segment_feature_for_audio_file(wav_file_path, segs_info, feature, **kwargs): fs, length = get_wav_info(wav_file_path) args = dict(wav_file_path=wav_file_path, fs=fs, start=0, end=None, center=False, order=44) for v, k in kwargs.items(): args[v] = k extractor = feature_extractors[feature.name] tids = [] fvals = [] for tid, beg, end, nfft, noverlap, lpf, hpf in segs_info: args['start'] = beg args['end'] = end args['nfft'] = nfft args['noverlap'] = noverlap args['lpf'] = lpf args['hpf'] = hpf args['win_length'] = nfft feature_value = extractor(args) tids.append(tid) fvals.append(feature_value) return tids, fvals
def extract_spectrogram(audio_file, segs_info): """ Extract raw sepectrograms for all segments (Not the masked spectrogram from Luscinia) of an audio file :param audio_file: :return: """ filepath = wav_path(audio_file) fs, duration = get_wav_info(filepath) if not os.path.isfile(filepath): raise CustomAssertionError("File {} not found".format(audio_file.name)) for tid, start, end in segs_info: seg_spect_path = get_abs_spect_path(tid) ensure_parent_folder_exists(seg_spect_path) sig = read_segment(filepath, beg_ms=start, end_ms=end, mono=True, normalised=True, return_fs=False, retype=True, winlen=window_size) _, _, s = signal.stft(sig, fs=fs, window=window, noverlap=noverlap, nfft=window_size, return_onesided=True) spect = np.abs(s * scale) height, width = np.shape(spect) spect = np.flipud(spect) spect = np.log10(spect) spect = ((spect - global_min_spect_pixel) / interval64) spect[np.isinf(spect)] = 0 spect = spect.astype(np.int) spect = spect.reshape((width * height, ), order='C') spect[spect >= 64] = 63 spect_rgb = np.empty((height, width, 3), dtype=np.uint8) spect_rgb[:, :, 0] = cm_red[spect].reshape((height, width)) * 255 spect_rgb[:, :, 1] = cm_green[spect].reshape((height, width)) * 255 spect_rgb[:, :, 2] = cm_blue[spect].reshape((height, width)) * 255 # roi_start = int(start / duration_ms * width) # roi_end = int(np.ceil(end / duration_ms * width)) # seg_spect_rgb = file_spect_rgb[:, roi_start:roi_end, :] seg_spect_img = Image.fromarray(spect_rgb) seg_spect_img.save(seg_spect_path, format='PNG') celerylogger.info('spectrogram {} created'.format(seg_spect_path))
def _test_single_file(self, filepath): fs, length = wavfile.get_wav_info(filepath) try: with contextlib.closing(wave.open(filepath, 'r')) as f: correct_length = f.getnframes() correct_fs = f.getframerate() self.assertEqual(fs, correct_fs) self.assertEqual(length, correct_length) except wave.Error as e: warning( 'Library wave is unable to read file {}. Error is: {}'.format( filepath, e))
def wav_2_mono(file, **kwargs): """ Read a wav file and return fs and first channel's data stream. The data is normalised to be equivalent to Matlab's `audioread(...)` function :param file: :return: fs and signal """ data = wavfile.read_segment(file, **kwargs) if len(np.shape(data)) > 1: data = data[:, 0] fs, _ = get_wav_info(file) return fs, data
def add_noc_to_audio_files(apps, schema_editor): """ """ db_alias = schema_editor.connection.alias audio_file_model = apps.get_model('koe', 'AudioFile') original_audio_files = audio_file_model.objects.using(db_alias).filter( original=None) inoriginal_audio_files = audio_file_model.objects.using(db_alias).exclude( original=None) afid_to_noc = {} slashed_url = os.path.join(settings.MEDIA_URL, 'audio/wav/{}', '{}.wav') unslashed_url = slashed_url[1:] wav_path_template = os.path.join(settings.BASE_DIR, unslashed_url) sys.stdout.write('\n') sys.stdout.write( '\tAdding number of channels to {} original AudioFiles...'.format( len(original_audio_files))) for audio_file in original_audio_files: database_id = audio_file.database.id file_name = audio_file.name file_path = wav_path_template.format(database_id, file_name) if os.path.isfile(file_path): _, _, noc = get_wav_info(file_path, return_noc=True) else: noc = 1 afid_to_noc[audio_file.id] = noc audio_file.noc = noc bulk_update(original_audio_files, update_fields=['noc'], batch_size=10000) sys.stdout.write('Done\n') sys.stdout.write( '\tAdding number of channels to {} dependent AudioFiles...'.format( len(inoriginal_audio_files))) for audio_file in inoriginal_audio_files: original_afid = audio_file.original.id audio_file.noc = afid_to_noc[original_afid] bulk_update(inoriginal_audio_files, update_fields=['noc'], batch_size=10000)
def import_pcm(song, cur, audio_file, wav_file_path=None, compressed_url=None): if wav_file_path is None: wav_file_path = wav_path(audio_file) if compressed_url is None: compressed_url = audio_path(audio_file, settings.AUDIO_COMPRESSED_FORMAT) if not os.path.isfile(wav_file_path): # print('Importing {}'.format(song_name)) song_id = song['songid'] cur.execute('select wav from wavs where songid={};'.format(song_id)) data = cur.fetchone() raw_pcm = str_to_bytes(data[0]) nchannels = song['stereo'] bitrate = int(song['ssizeinbits']) fs = int(song['samplerate']) byte_per_frame = int(bitrate / 8) nframes_all_channel = int(len(raw_pcm) / byte_per_frame) nframes_per_channel = int(nframes_all_channel / nchannels) length = nframes_per_channel ensure_parent_folder_exists(wav_file_path) if bitrate == 24: array1 = np.frombuffer(raw_pcm, dtype=np.ubyte) array2 = array1.reshape((nframes_per_channel, nchannels, byte_per_frame)).astype(np.uint8) wf.write_24b(wav_file_path, fs, array2) else: data = array.array('i', raw_pcm) sound = pydub.AudioSegment(data=data, sample_width=byte_per_frame, frame_rate=fs, channels=nchannels) sound.export(wav_file_path, 'wav') else: fs, length = get_wav_info(wav_file_path) if not os.path.isfile(compressed_url): ensure_parent_folder_exists(compressed_url) sound = pydub.AudioSegment.from_wav(wav_file_path) sound.export(compressed_url, format=settings.AUDIO_COMPRESSED_FORMAT) return fs, length
def _import_and_convert_audio_file(database, file, max_fs, real_fs=None, audio_file=None, track=None, start=None, end=None): file_already_exists = False if isinstance(file, BufferedWriter): file_already_exists = True name_ext = os.path.basename(file.name) else: name_ext = file.name if name_ext.lower().endswith('.wav'): name_no_ext = name_ext[:-4] else: name_no_ext = name_ext # Need a unique name (database-wide) for new file if audio_file is None: is_unique = not AudioFile.objects.filter(database=database, name=name_no_ext).exists() if not is_unique: raise CustomAssertionError( 'File {} already exists'.format(name_no_ext)) elif audio_file.name != name_no_ext: raise CustomAssertionError( 'Impossible! File name in your table and in the database don\'t match' ) wav_name = data_path('audio/wav/{}'.format(database.id), '{}.wav'.format(name_no_ext)) name_compressed = data_path( 'audio/{}/{}'.format(settings.AUDIO_COMPRESSED_FORMAT, database.id), '{}.{}'.format(name_no_ext, settings.AUDIO_COMPRESSED_FORMAT)) fake_wav_name = wav_name + '.bak' if not file_already_exists: with open(wav_name, 'wb') as wav_file: wav_file.write(file.read()) _fs, length, noc = get_wav_info(wav_name, return_noc=True) # If real_fs is provided, it is absolute -- otherwise it is what we can really read from the file if real_fs is None: real_fs = _fs fake_fs = None # If real_fs is not what we read from the file, then the file is fake, and we must restore the original file # to do that we rename the wav file that we just stored (which is fake) to .bak, then change the sample rate # back to the original and store the original file as .wav if real_fs != _fs: os.rename(wav_name, fake_wav_name) change_fs_without_resampling(fake_wav_name, real_fs, wav_name) audio = pydub.AudioSegment.from_file(fake_wav_name) os.remove(fake_wav_name) # Otherwise, if real_fs is more than max_fs, we must create a fake file for the sake of converting to mp3: elif real_fs > max_fs: fake_fs = max_fs change_fs_without_resampling(wav_name, fake_fs, fake_wav_name) audio = pydub.AudioSegment.from_file(fake_wav_name) os.remove(fake_wav_name) # Otherwise the file is ordinary - no need to fake it else: audio = pydub.AudioSegment.from_file(wav_name) ensure_parent_folder_exists(name_compressed) audio.export(name_compressed, format=settings.AUDIO_COMPRESSED_FORMAT) if audio_file is None: if track is None: track = AudioTrack.objects.get_or_create(name='TBD')[0] individual = Individual.objects.get_or_create(name='TBD')[0] audio_file = AudioFile(name=name_no_ext, length=length, fs=real_fs, database=database, track=track, start=start, end=end, fake_fs=fake_fs, added=timezone.now(), noc=noc, individual=individual) audio_file.save() if track.name == 'TBD': track.name = str(audio_file.id) track.save() individual.name = str(audio_file.id) individual.save() else: audio_file.start = start audio_file.end = end audio_file.length = length audio_file.save() return audio_file