Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ thread: To decide whether accomplish the inference at the main thread or another

device: Type of device being used. Cuda or cpu (by default).

beat_callback: A function, which is called when a beat is detected. It is called with True for a downbeat and with False for a normal beat. Only available in streaming mode. Defaults to printing _*beat!_ for a downbeat and _beat!_ for a non-downbeat.

Installation command:
---------------------

Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
REQUIRED_PACKAGES = [
'numpy',
'cython',
'librosa>=0.8.0',
'numba==0.54.1', # Manually specified here as librosa incorrectly states that it is compatible with the latest version of numba although 0.50.0 is not compatible.
'librosa>=0.10.1',
'numba>=0.58.1', # Manually specified here as librosa incorrectly states that it is compatible with the latest version of numba although 0.50.0 is not compatible.
'scipy',
'mido>=1.2.6',
'pytest',
Expand Down
4 changes: 2 additions & 2 deletions src/BeatNet/BeatNet.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class BeatNet:
'''


def __init__(self, model, mode='online', inference_model='PF', plot=[], thread=False, device='cpu'):
def __init__(self, model, mode='online', inference_model='PF', plot=[], thread=False, device='cpu', beat_callback=lambda is_downbeat: print("*beat!" if is_downbeat else "beat!")):
self.model = model
self.mode = mode
self.inference_model = inference_model
Expand All @@ -64,7 +64,7 @@ def __init__(self, model, mode='online', inference_model='PF', plot=[], thread=F
self.proc = LOG_SPECT(sample_rate=self.log_spec_sample_rate, win_length=self.log_spec_win_length,
hop_size=self.log_spec_hop_length, n_bands=[24], mode = self.mode)
if self.inference_model == "PF": # instantiating a Particle Filter decoder - Is Chosen for online inference
self.estimator = particle_filter_cascade(beats_per_bar=[], fps=50, plot=self.plot, mode=self.mode)
self.estimator = particle_filter_cascade(beats_per_bar=[], fps=50, plot=self.plot, mode=self.mode, beat_callback=beat_callback)
elif self.inference_model == "DBN": # instantiating an HMM decoder - Is chosen for offline inference
self.estimator = DBNDownBeatTrackingProcessor(beats_per_bar=[2, 3, 4], fps=50)
else:
Expand Down
8 changes: 5 additions & 3 deletions src/BeatNet/particle_filtering_cascade.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ def __init__(self, beats_per_bar=[], particle_size=PARTICLE_SIZE, down_particle_
min_bpm=MIN_BPM, max_bpm=MAX_BPM, num_tempi=NUM_TEMPI, min_beats_per_bar=MIN_BEAT_PER_BAR,
max_beats_per_bar=MAX_BEAT_PER_BAR, offset=OFFSET, ig_threshold=IG_THRESHOLD, lambda_b=LAMBDA_B,
lambda_d=LAMBDA_D, observation_lambda_b=OBSERVATION_LAMBDA_B, observation_lambda_d=OBSERVATION_LAMBDA_D,
fps=None, plot=False, mode=None, **kwargs):
fps=None, plot=False, mode=None, beat_callback=lambda is_downbeat: print("*beat!" if is_downbeat else "beat!"),
**kwargs):
self.particle_size = particle_size
self.down_particle_size = down_particle_size
self.particle_filter = []
Expand All @@ -141,6 +142,7 @@ def __init__(self, beats_per_bar=[], particle_size=PARTICLE_SIZE, down_particle_
self.offset = offset
self.ig_threshold = ig_threshold
self.mode = mode
self.beat_callback = beat_callback
# convert timing information to construct a beat state space
min_interval = 60. * fps / max_bpm
max_interval = 60. * fps / min_bpm
Expand Down Expand Up @@ -284,11 +286,11 @@ def process(self, activations):
if self.down_max in self.st2.first_states[0] and self.path[-1][1] !=1 and both_activations[i][1]>0.4:
self.path = np.append(self.path, [[self.offset + self.counter * self.T, 1]], axis=0)
if self.mode == 'stream' or self.mode == 'realtime':
print("*beat!")
self.beat_callback(True)
elif (activations[i]>0.4) :
self.path = np.append(self.path, [[self.offset + self.counter * self.T, 2]], axis=0)
if self.mode == 'stream' or self.mode == 'realtime':
print("beat!")
self.beat_callback(False)
#librosa.clicks(times=None, frames=None, sr=22050, hop_length=512, click_freq=440.0, click_duration=0.1, click=None, length=None)
if 'downbeat_particles' in self.plot:
self.downbeat_particles_plot()
Expand Down