def analyze(cls, events: List[CorpusEvent], metadata: Metadata) -> List[CorpusEvent]: if not FeatureUtils.is_valid_audio(events, metadata): raise FeatureError( f"Feature '{cls.__name__}' does not support content of " f"type {metadata.content_type.__class__.__name__}") metadata: AudioMetadata = typing.cast(AudioMetadata, metadata) # TODO: Pass rather than hard-code yin_frames: np.ndarray = librosa.yin(metadata.foreground_data, fmin=50, fmax=4186, sr=metadata.sr, frame_length=2048, hop_length=metadata.hop_length) yin_midipitches: np.ndarray = np.round( 12 * np.log2(yin_frames / 8.175798915643707)) for event in events: onset_frame: int = librosa.time_to_frames( event.onset, sr=metadata.sr, hop_length=metadata.hop_length) end_frame: int = librosa.time_to_frames( event.onset + event.duration, sr=metadata.sr, hop_length=metadata.hop_length) hist, _ = np.histogram(yin_midipitches[onset_frame:end_frame], bins=128, range=(0, 128)) pitch: int = int(np.argmax(hist)) event.set_feature(cls(value=pitch)) return events
def analyze(cls, events: List[MidiCorpusEvent], metadata: MidiMetadata) -> List[MidiCorpusEvent]: if FeatureUtils.is_valid_midi(events, metadata): for event in events: event.set_feature(cls(value=len(event.notes))) return events raise FeatureError( f"Feature '{cls.__name__}' does not support content of " f"type {metadata.content_type.__class__.__name__}")
def analyze(cls, events: List[MidiCorpusEvent], metadata: MidiMetadata) -> List[MidiCorpusEvent]: """ raises: FeatureError if invalid MIDI content """ if FeatureUtils.is_valid_midi(events, metadata): for event in events: event.set_feature(cls(int(min([n.pitch for n in event.notes])))) return events raise FeatureError( f"Feature '{cls.__name__}' does not support content of " f"type {metadata.content_type.__class__.__name__}")
def analyze(cls, events: List[CorpusEvent], metadata: Metadata) -> List[CorpusEvent]: if FeatureUtils.is_valid_midi(events, metadata): events: List[MidiCorpusEvent] metadata: MidiMetadata cls._analyze_midi(events, metadata) elif FeatureUtils.is_valid_audio(events, metadata): events: List[AudioCorpusEvent] metadata: AudioMetadata cls._analyze_audio(events, metadata) else: raise FeatureError(f"Feature '{cls.__name__}' does not support content of type {metadata.content_type}") return events
def analyze(cls, events: List[MidiCorpusEvent], metadata: MidiMetadata) -> List[MidiCorpusEvent]: if FeatureUtils.is_valid_midi(events, metadata): for event in events: band_distribution: np.ndarray = np.zeros(OctaveBands.NUM_BANDS, dtype=float) octaves: List[int] = [ int(note.pitch // 12) for note in event.notes ] for octave in octaves: band_distribution[octave] += 1.0 max_val: float = np.max(band_distribution) if max_val > 0: band_distribution /= max_val event.set_feature(cls(value=band_distribution)) return events raise FeatureError( f"Feature '{cls.__name__}' does not support content of " f"type {metadata.content_type.__class__.__name__}")
def get_feature(self, feature_type: Type[FeatureValue]) -> FeatureValue: """Raises KeyError""" try: return self.features[feature_type] except ValueError as e: raise FeatureError(f"Corpus does not have feature of type '{feature_type}'") from e