Source code for pumpp.task.event
#!/usr/bin/env python
# -*- enconding: utf-8 -*-
'''Instantaneous event coding'''
import numpy as np
import jams
from .base import BaseTaskTransformer
__all__ = ['BeatTransformer']
[docs]class BeatTransformer(BaseTaskTransformer):
'''Task transformation for beat tracking
Attributes
----------
name : str
The name of this transformer
sr : number > 0
The audio sampling rate
hop_length : int > 0
The hop length for annotation frames
'''
[docs] def __init__(self, name='beat', sr=22050, hop_length=512):
super(BeatTransformer, self).__init__(name=name,
namespace='beat',
sr=sr, hop_length=hop_length)
self.register('beat', [None], np.bool)
self.register('downbeat', [None], np.bool)
self.register('mask_downbeat', [1], np.bool)
def transform_annotation(self, ann, duration):
'''Apply the beat transformer
Parameters
----------
ann : jams.Annotation
The input annotation
duration : number > 0
The duration of the audio
Returns
-------
data : dict
data['beat'] : np.ndarray, shape=(n, 1)
Binary indicator of beat/non-beat
data['downbeat'] : np.ndarray, shape=(n, 1)
Binary indicator of downbeat/non-downbeat
mask_downbeat : bool
True if downbeat annotations are present
'''
mask_downbeat = False
intervals, values = ann.data.to_interval_values()
values = np.asarray(values)
beat_events = intervals[:, 0]
beat_labels = np.ones((len(beat_events), 1))
idx = (values == 1)
if np.any(idx):
downbeat_events = beat_events[idx]
downbeat_labels = np.ones((len(downbeat_events), 1))
mask_downbeat = True
else:
downbeat_events = np.zeros(0)
downbeat_labels = np.zeros((0, 1))
target_beat = self.encode_events(duration,
beat_events,
beat_labels)
target_downbeat = self.encode_events(duration,
downbeat_events,
downbeat_labels)
return {'beat': target_beat,
'downbeat': target_downbeat,
'mask_downbeat': mask_downbeat}
def inverse(self, encoded, downbeat=None, duration=None):
'''Inverse transformation for beats and optional downbeats'''
ann = jams.Annotation(namespace=self.namespace, duration=duration)
beat_times = [t for t, _ in self.decode_events(encoded) if _]
if downbeat is not None:
downbeat_times = set([t for t, _ in self.decode_events(downbeat)
if _])
pickup_beats = len([t for t in beat_times
if t < min(downbeat_times)])
else:
downbeat_times = set()
pickup_beats = 0
value = - pickup_beats - 1
for beat in beat_times:
if beat in downbeat_times:
value = 1
else:
value += 1
ann.append(time=beat, duration=0, value=value)
return ann