##| Copyright: (C) 2019-2020 Kevin Larke ##| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file. import types import numpy as np from rms_analysis import audio_harm_rms from rms_analysis import audio_rms from rms_analysis import locate_peak_indexes from rms_analysis import measure_duration_ms class RT_Analyzer: def __init__(self): self.td_dur_ms = 0 self.td_db = 0 self.hm_dur_ms = 0 self.hm_db = 0 def analyze_note( self, audioDev, midi_pitch, begTimeMs, endTimeMs, anlArgD ): td_dur_ms = 0 td_db = 0 hm_dur_ms = 0 hm_db = 0 decay_pct = 50.0 result = audioDev.linear_buffer() if result: sigV = result.value # convert the audio signal vector to contain only the first (left) channel if len(sigV.shape)>1: sigV = sigV[:,0].squeeze() anlArgs = types.SimpleNamespace(**anlArgD) rmsDbV, rms_srate, binHz = audio_harm_rms( audioDev.srate, np.squeeze(sigV), anlArgs.rmsWndMs, anlArgs.rmsHopMs, anlArgs.dbLinRef, midi_pitch, anlArgs.harmCandN, anlArgs.harmN ) pkIdxL = locate_peak_indexes( rmsDbV, rms_srate, [( begTimeMs, endTimeMs)] ) if len(pkIdxL) > 0: end_idx = int(round(endTimeMs * rms_srate / 1000.0)) if end_idx > pkIdxL[0]: hm_dur_ms = measure_duration_ms( rmsDbV, rms_srate, pkIdxL[0], end_idx, decay_pct ) hm_db = rmsDbV[ pkIdxL[0] ] tdRmsDbV, rms0_srate = audio_rms( audioDev.srate, np.squeeze(sigV), anlArgs.rmsWndMs, anlArgs.rmsHopMs, anlArgs.dbLinRef ) tdPkIdxL = locate_peak_indexes( tdRmsDbV, rms0_srate, [( begTimeMs, endTimeMs)] ) if len(tdPkIdxL): end_idx = int(round(endTimeMs * rms0_srate / 1000.0)) if end_idx > tdPkIdxL[0]: td_dur_ms = measure_duration_ms( tdRmsDbV, rms0_srate, tdPkIdxL[0], end_idx, decay_pct ) td_db = tdRmsDbV[ tdPkIdxL[0] ] td_d_ms = td_dur_ms - self.td_dur_ms td_d_db = td_db - self.td_db hm_d_ms = hm_dur_ms - self.hm_dur_ms hm_d_db = hm_db - self.hm_db print("DUR: %5.2f %5.2f d:%5.2f %5.2f dB | %i %i d:%i %i ms" % (hm_db, td_db, hm_d_db, td_d_db, hm_dur_ms, td_dur_ms, hm_d_ms, td_d_ms) ) self.td_dur_ms = td_dur_ms self.td_db = td_db self.hm_dur_ms = hm_dur_ms self.hm_db = hm_db