wip
This commit is contained in:
parent
d804d781c6
commit
407a5228bf
1 changed files with 24 additions and 19 deletions
43
process
43
process
|
@ -3,7 +3,7 @@ import os
|
||||||
import datetime
|
import datetime
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import soundfile
|
import soundfile as sf
|
||||||
from scipy.fft import rfft, rfftfreq
|
from scipy.fft import rfft, rfftfreq
|
||||||
import shutil
|
import shutil
|
||||||
import traceback
|
import traceback
|
||||||
|
@ -36,20 +36,20 @@ def process_recording(filename):
|
||||||
|
|
||||||
# get data and metadata from recording
|
# get data and metadata from recording
|
||||||
path = os.path.join(RECORDINGS_DIR, filename)
|
path = os.path.join(RECORDINGS_DIR, filename)
|
||||||
sound, samplerate = soundfile.read(path)
|
soundfile = sf.SoundFile(path)
|
||||||
|
samplerate = soundfile.samplerate
|
||||||
samples_per_block = int(BLOCK_SECONDS * samplerate)
|
samples_per_block = int(BLOCK_SECONDS * samplerate)
|
||||||
overlapping_samples = int(samples_per_block * BLOCK_OVERLAP_FACTOR)
|
overlapping_samples = int(samples_per_block * BLOCK_OVERLAP_FACTOR)
|
||||||
|
|
||||||
# chache data about current event
|
sample_num = 0
|
||||||
current_event = None
|
current_event = None
|
||||||
|
|
||||||
# read blocks of audio data with overlap from sound variable
|
while sample_num < len(soundfile):
|
||||||
sample_num = 0
|
soundfile.seek(sample_num)
|
||||||
while sample_num < len(sound):
|
block = soundfile.read(frames=samples_per_block, dtype='float32', always_2d=False)
|
||||||
# get block of audio data
|
|
||||||
block_start = sample_num
|
if len(block) == 0:
|
||||||
block_end = min(sample_num + samples_per_block, len(sound))
|
break
|
||||||
block = sound[block_start:block_end]
|
|
||||||
|
|
||||||
# calculate FFT
|
# calculate FFT
|
||||||
labels = rfftfreq(len(block), d=1/samplerate)
|
labels = rfftfreq(len(block), d=1/samplerate)
|
||||||
|
@ -102,7 +102,8 @@ def process_recording(filename):
|
||||||
current_event['duration'] = duration
|
current_event['duration'] = duration
|
||||||
print(f'🔊 {current_event['start_at'].strftime('%Y-%m-%d %H:%M:%S')} ({duration:.1f}s): {current_event['start_freq']:.1f}Hz->{current_event['end_freq']:.1f}Hz @{current_event['max_amplitude']:.0f}rDB')
|
print(f'🔊 {current_event['start_at'].strftime('%Y-%m-%d %H:%M:%S')} ({duration:.1f}s): {current_event['start_freq']:.1f}Hz->{current_event['end_freq']:.1f}Hz @{current_event['max_amplitude']:.0f}rDB')
|
||||||
|
|
||||||
write_event(current_event=current_event, sound=sound, samplerate=samplerate)
|
# read full audio clip again for writing
|
||||||
|
write_event(current_event=current_event, soundfile=soundfile, samplerate=samplerate)
|
||||||
|
|
||||||
current_event = None
|
current_event = None
|
||||||
sample_num += DETECTION_DISTANCE_BLOCKS * samples_per_block
|
sample_num += DETECTION_DISTANCE_BLOCKS * samples_per_block
|
||||||
|
@ -111,27 +112,31 @@ def process_recording(filename):
|
||||||
|
|
||||||
|
|
||||||
# write a spectrogram using the sound from start to end of the event
|
# write a spectrogram using the sound from start to end of the event
|
||||||
def write_event(current_event, sound, samplerate):
|
def write_event(current_event, soundfile, samplerate):
|
||||||
|
# date and filename
|
||||||
|
event_date = current_event['start_at'] - datetime.timedelta(seconds=PLOT_PADDING_START_SECONDS)
|
||||||
|
filename_prefix = event_date.strftime('%Y-%m-%d_%H-%M-%S.%f%z')
|
||||||
|
|
||||||
|
# event clip
|
||||||
event_start_sample = current_event['start_sample'] - samplerate * PLOT_PADDING_START_SECONDS
|
event_start_sample = current_event['start_sample'] - samplerate * PLOT_PADDING_START_SECONDS
|
||||||
event_end_sample = current_event['end_sample'] + samplerate * PLOT_PADDING_END_SECONDS
|
event_end_sample = current_event['end_sample'] + samplerate * PLOT_PADDING_END_SECONDS
|
||||||
event_clip = sound[event_start_sample:event_end_sample]
|
total_samples = event_end_sample - event_start_sample
|
||||||
event = current_event['start_at'] - datetime.timedelta(seconds=PLOT_PADDING_START_SECONDS)
|
soundfile.seek(event_start_sample)
|
||||||
filename_prefix = current_event['start_at'].strftime('%Y-%m-%d_%H-%M-%S.%f%z')
|
event_clip = soundfile.read(frames=total_samples, dtype='float32', always_2d=False)
|
||||||
|
|
||||||
# write flac
|
# write flac
|
||||||
flac_path = os.path.join(DETECTIONS_DIR, f"{filename_prefix}.flac")
|
flac_path = os.path.join(DETECTIONS_DIR, f"{filename_prefix}.flac")
|
||||||
soundfile.write(flac_path, event_clip, samplerate, format='FLAC')
|
sf.write(flac_path, event_clip, samplerate, format='FLAC')
|
||||||
|
|
||||||
# write spectrogram
|
# write spectrogram
|
||||||
plt.figure(figsize=(8, 6))
|
plt.figure(figsize=(8, 6))
|
||||||
plt.specgram(event_clip, Fs=samplerate, NFFT=samplerate, noverlap=samplerate//2, cmap='inferno', vmin=-100, vmax=-10)
|
plt.specgram(event_clip, Fs=samplerate, NFFT=samplerate, noverlap=samplerate//2, cmap='inferno', vmin=-100, vmax=-10)
|
||||||
plt.title(f"Bootshorn @{event.strftime('%Y-%m-%d %H:%M:%S%z')}")
|
plt.title(f"Bootshorn @{event_date.strftime('%Y-%m-%d %H:%M:%S%z')}")
|
||||||
plt.xlabel(f"Time {current_event['duration']:.1f}s")
|
plt.xlabel(f"Time {current_event['duration']:.1f}s")
|
||||||
plt.ylabel(f"Frequency {current_event['start_freq']:.1f}Hz -> {current_event['end_freq']:.1f}Hz")
|
plt.ylabel(f"Frequency {current_event['start_freq']:.1f}Hz -> {current_event['end_freq']:.1f}Hz")
|
||||||
plt.colorbar(label="Intensity (rDB)")
|
plt.colorbar(label="Intensity (rDB)")
|
||||||
plt.ylim(50, 1000)
|
plt.ylim(50, 1000)
|
||||||
spectrogram_path = os.path.join(DETECTIONS_DIR, f"{filename_prefix}.png")
|
plt.savefig(os.path.join(DETECTIONS_DIR, f"{filename_prefix}.png"))
|
||||||
plt.savefig(spectrogram_path)
|
|
||||||
plt.close()
|
plt.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue