Compare commits
4 Commits
121905e743
...
648e29c4c4
Author | SHA1 | Date | |
---|---|---|---|
|
648e29c4c4 | ||
|
011606c5cf | ||
|
b4b0973e9a | ||
|
846f1d5aa8 |
51
README.md
51
README.md
@ -29,8 +29,10 @@ Capture note 60 and 61 using the full_pulseL[] and holdDutyPctD{} from the p_ac.
|
|||||||
|
|
||||||
![Plot Seq 1](doc/do_td_plot.png)
|
![Plot Seq 1](doc/do_td_plot.png)
|
||||||
|
|
||||||
|
Print a specific pitch and take.
|
||||||
|
|
||||||
````
|
````
|
||||||
python plot_seq.py ~/temp/p_ac_3_od p_ac.yml 60 10
|
python plot_seq.py p_ac.yml ~/temp/p_ac_3_of td_plot 60 2
|
||||||
|
|
||||||
do_td_plot(inDir,cfg.analysisArgs, pitch, take_id )
|
do_td_plot(inDir,cfg.analysisArgs, pitch, take_id )
|
||||||
````
|
````
|
||||||
@ -39,15 +41,39 @@ Capture note 60 and 61 using the full_pulseL[] and holdDutyPctD{} from the p_ac.
|
|||||||
|
|
||||||
![Multi Usec dB](doc/us_db.png)
|
![Multi Usec dB](doc/us_db.png)
|
||||||
|
|
||||||
|
Plot all the takes for a given pitch
|
||||||
|
|
||||||
````
|
````
|
||||||
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od us_db 84
|
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od us_db 84
|
||||||
````
|
````
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
![Overlapping USec dB](doc/us_db_takes.png)
|
||||||
|
|
||||||
|
Plot a specific set of pitches and takes.
|
||||||
|
|
||||||
|
````
|
||||||
|
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_of us_db_pitch_take 75 0 76 0 77 0 78 0 72 10 73 1 74 1
|
||||||
|
````
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
![Overlapping USec dB](doc/us_db_takes_last.png)
|
||||||
|
|
||||||
|
Plot the last take from a list of pitches.
|
||||||
|
|
||||||
|
````
|
||||||
|
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_of us_db_pitch_last 77 78 79 80
|
||||||
|
````
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
![Multi Plot 1](doc/multi_plot.png)
|
![Multi Plot 1](doc/multi_plot.png)
|
||||||
|
|
||||||
|
Plot the time domain envelope for a specific set of pitches and takes.
|
||||||
|
|
||||||
````
|
````
|
||||||
python plot_seq.py p_ac.yml ~/temp/p_ac_3_od td_multi_plot 60 3 60 4 60 5
|
python plot_seq.py p_ac.yml ~/temp/p_ac_3_od td_multi_plot 60 3 60 4 60 5
|
||||||
|
|
||||||
@ -57,6 +83,8 @@ plot_seq.py `do_td_multi_plot(inDir,cfg.analysisArgs,[(36,4), (48,2)] )
|
|||||||
|
|
||||||
![Spectral Ranges](doc/plot_spectral_ranges.png)
|
![Spectral Ranges](doc/plot_spectral_ranges.png)
|
||||||
|
|
||||||
|
Plot the spectrum with harmonic location markers of a specific set of pitches and takes.
|
||||||
|
|
||||||
````
|
````
|
||||||
# pitch0 takeId0 pitch1 takeId1
|
# pitch0 takeId0 pitch1 takeId1
|
||||||
python plot_seq.py p_ac.yml ~/temp/p_ac_3_od plot_spectral_ranges 60 3 60 4
|
python plot_seq.py p_ac.yml ~/temp/p_ac_3_od plot_spectral_ranges 60 3 60 4
|
||||||
@ -67,14 +95,30 @@ python plot_seq.py p_ac.yml ~/temp/p_ac_3_od plot_spectral_ranges 60 3
|
|||||||
|
|
||||||
![Usec dB Spread](doc/us_db_map.png)
|
![Usec dB Spread](doc/us_db_map.png)
|
||||||
|
|
||||||
|
Plot the microsecond variance to achieve a given decibel value.
|
||||||
|
|
||||||
````
|
````
|
||||||
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od us_db_map 84 72
|
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od us_db_map 84 72
|
||||||
````
|
````
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
![Resample](doc/resample_pulse_times.png)
|
||||||
|
|
||||||
|
Analyze all takes for given pitch and show the mean us/db curve and
|
||||||
|
places where resampling may be necessary.
|
||||||
|
|
||||||
|
````
|
||||||
|
python plot_seq.py p_ac.yml ~/temp/p_ac_3_of resample_pulse_times 84
|
||||||
|
````
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
![Min Max](doc/min_max_db.png)
|
![Min Max](doc/min_max_db.png)
|
||||||
|
|
||||||
|
Plot the min and max decibel values for specified pitches.
|
||||||
|
|
||||||
````
|
````
|
||||||
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od min_max 36 48 60 72 84
|
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od min_max 36 48 60 72 84
|
||||||
````
|
````
|
||||||
@ -83,6 +127,8 @@ python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od min_max 36 48 60 72 84
|
|||||||
|
|
||||||
![Min Max 2](doc/min_max_db_2.png)
|
![Min Max 2](doc/min_max_db_2.png)
|
||||||
|
|
||||||
|
Plot the min and max decibel values for specified pitches.
|
||||||
|
|
||||||
````
|
````
|
||||||
# pitch0 pitch1 pitch2 pitch3 pitch4 takeId
|
# pitch0 pitch1 pitch2 pitch3 pitch4 takeId
|
||||||
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od min_max_2 36 48 60 72 84 2
|
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od min_max_2 36 48 60 72 84 2
|
||||||
@ -91,6 +137,9 @@ python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od min_max_2 36 48 60
|
|||||||
---
|
---
|
||||||
![Manual dB](doc/manual_db.png)
|
![Manual dB](doc/manual_db.png)
|
||||||
|
|
||||||
|
Plot the min and max decibel values for specified set of manually corrected pitches.
|
||||||
|
|
||||||
|
|
||||||
````
|
````
|
||||||
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od manual_db
|
python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od manual_db
|
||||||
````
|
````
|
||||||
|
BIN
doc/us_db_takes.png
Normal file
BIN
doc/us_db_takes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 137 KiB |
BIN
doc/us_db_takes_last.png
Normal file
BIN
doc/us_db_takes_last.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 92 KiB |
46
p_ac.py
46
p_ac.py
@ -59,10 +59,12 @@ class AttackPulseSeq:
|
|||||||
self.beginMs = ms
|
self.beginMs = ms
|
||||||
self.playOnlyFl = playOnlyFl
|
self.playOnlyFl = playOnlyFl
|
||||||
|
|
||||||
|
|
||||||
# kpl if not playOnlyFl:
|
# kpl if not playOnlyFl:
|
||||||
self.audio.record_enable(True) # start recording audio
|
self.audio.record_enable(True) # start recording audio
|
||||||
|
|
||||||
|
print("Hold Delay from end of attack:",cfg.defaultHoldDelayUsecs)
|
||||||
|
self.api.set_hold_delay(pitch,cfg.defaultHoldDelayUsecs)
|
||||||
|
|
||||||
self.tick(ms) # play the first note
|
self.tick(ms) # play the first note
|
||||||
|
|
||||||
def stop(self, ms):
|
def stop(self, ms):
|
||||||
@ -124,16 +126,9 @@ class AttackPulseSeq:
|
|||||||
def _get_duty_cycle( self, pulseUsec ):
|
def _get_duty_cycle( self, pulseUsec ):
|
||||||
return self.holdDutyPctD[ pulseUsec ]
|
return self.holdDutyPctD[ pulseUsec ]
|
||||||
|
|
||||||
dutyPct = self.holdDutyPctL[0][1]
|
|
||||||
for refUsec,refDuty in self.holdDutyPctL:
|
|
||||||
if pulseUsec < refUsec:
|
|
||||||
break
|
|
||||||
dutyPct = refDuty
|
|
||||||
|
|
||||||
return dutyPct
|
|
||||||
|
|
||||||
def _set_duty_cycle( self, pitch, pulseUsec ):
|
def _set_duty_cycle( self, pitch, pulseUsec ):
|
||||||
|
|
||||||
|
|
||||||
dutyPct = self._get_duty_cycle( pulseUsec )
|
dutyPct = self._get_duty_cycle( pulseUsec )
|
||||||
|
|
||||||
if dutyPct != self.prevHoldDutyPct:
|
if dutyPct != self.prevHoldDutyPct:
|
||||||
@ -267,14 +262,18 @@ class CalibrateKeys:
|
|||||||
#self.pulseUsL,_,_ = form_resample_pulse_time_list( outDir, self.cfg.analysisArgs )
|
#self.pulseUsL,_,_ = form_resample_pulse_time_list( outDir, self.cfg.analysisArgs )
|
||||||
self.pulseUsL = get_resample_points_wrap( baseDir, pitch, self.cfg.analysisArgs )
|
self.pulseUsL = get_resample_points_wrap( baseDir, pitch, self.cfg.analysisArgs )
|
||||||
|
|
||||||
|
|
||||||
holdDutyPctL = self.cfg.calibrateArgs['holdDutyPctD'][pitch]
|
holdDutyPctL = self.cfg.calibrateArgs['holdDutyPctD'][pitch]
|
||||||
|
|
||||||
|
|
||||||
if playOnlyFl:
|
if playOnlyFl:
|
||||||
self.pulseUsL,_,holdDutyPctL = form_final_pulse_list( outDir, pitch, self.cfg.analysisArgs, take_id=None )
|
|
||||||
|
self.pulseUsL,_,holdDutyPctL = form_final_pulse_list( baseDir, pitch, self.cfg.analysisArgs, take_id=None )
|
||||||
|
|
||||||
noteN = cfg.analysisArgs['auditionNoteN']
|
noteN = cfg.analysisArgs['auditionNoteN']
|
||||||
self.pulseUsL = [ self.pulseUsL[ int(round(i*126.0/(noteN-1)))] for i in range(noteN) ]
|
self.pulseUsL = [ self.pulseUsL[ int(round(i*126.0/(noteN-1)))] for i in range(noteN) ]
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
outDir = os.path.join( outDir, str(outDir_id) )
|
outDir = os.path.join( outDir, str(outDir_id) )
|
||||||
|
|
||||||
@ -339,6 +338,7 @@ class App:
|
|||||||
self.audio_dev_list(0)
|
self.audio_dev_list(0)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
print("The cfg file has no audio stanza. No audio device will be initialized.")
|
||||||
self.audioDev = None
|
self.audioDev = None
|
||||||
|
|
||||||
if True:
|
if True:
|
||||||
@ -389,6 +389,8 @@ class App:
|
|||||||
self.midiFilePlayer.tick(ms)
|
self.midiFilePlayer.tick(ms)
|
||||||
|
|
||||||
def audio_dev_list( self, ms ):
|
def audio_dev_list( self, ms ):
|
||||||
|
|
||||||
|
if self.audioDev is not None:
|
||||||
portL = self.audioDev.get_port_list( True )
|
portL = self.audioDev.get_port_list( True )
|
||||||
|
|
||||||
for port in portL:
|
for port in portL:
|
||||||
@ -411,7 +413,7 @@ class App:
|
|||||||
self.cal_keys.start( ms, pitchL, cfg.full_pulseL )
|
self.cal_keys.start( ms, pitchL, cfg.full_pulseL )
|
||||||
|
|
||||||
def play_keys_start( self, ms, pitchRangeL ):
|
def play_keys_start( self, ms, pitchRangeL ):
|
||||||
chordL = [ [pitch] for pitch in range(pitchRangeL[0], pitchRangeL[1]+1)]
|
chordL = [ pitch for pitch in range(pitchRangeL[0], pitchRangeL[1]+1)]
|
||||||
self.cal_keys.start( ms, chordL, cfg.full_pulseL, playOnlyFl=True )
|
self.cal_keys.start( ms, chordL, cfg.full_pulseL, playOnlyFl=True )
|
||||||
|
|
||||||
def keyboard_start_pulse_idx( self, ms, argL ):
|
def keyboard_start_pulse_idx( self, ms, argL ):
|
||||||
@ -709,10 +711,30 @@ def parse_args():
|
|||||||
return ap.parse_args()
|
return ap.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def create_logger():
|
||||||
|
import multiprocessing, logging
|
||||||
|
logger = multiprocessing.get_logger()
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
formatter = logging.Formatter(\
|
||||||
|
'[%(asctime)s| %(levelname)s| %(processName)s] %(message)s')
|
||||||
|
handler = logging.FileHandler('/home/kevin/temp/p_ac_log.txt')
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
|
||||||
|
# this bit will make sure you won't have
|
||||||
|
# duplicated messages in the output
|
||||||
|
if not len(logger.handlers):
|
||||||
|
logger.addHandler(handler)
|
||||||
|
return logger
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
logging.basicConfig()
|
|
||||||
|
from multiprocessing import Pool
|
||||||
|
logger = create_logger()
|
||||||
|
logger.info('Starting pooling')
|
||||||
|
#p = Pool()
|
||||||
|
|
||||||
|
#logging.basicConfig()
|
||||||
|
|
||||||
#mplog = multiprocessing.log_to_stderr()
|
#mplog = multiprocessing.log_to_stderr()
|
||||||
#mplog.setLevel(logging.INFO)
|
#mplog.setLevel(logging.INFO)
|
||||||
|
54
p_ac.yml
54
p_ac.yml
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
|
|
||||||
# MeasureSeq args
|
# MeasureSeq args
|
||||||
outDir: "~/temp/p_ac_3_oe",
|
outDir: "~/temp/p_ac_3_of",
|
||||||
noteDurMs: 500,
|
noteDurMs: 500,
|
||||||
pauseDurMs: 500,
|
pauseDurMs: 500,
|
||||||
reversePulseListFl: True,
|
reversePulseListFl: True,
|
||||||
@ -37,6 +37,8 @@
|
|||||||
silentNoteMaxPulseUs: 15000,
|
silentNoteMaxPulseUs: 15000,
|
||||||
silentNoteMinDurMs: 180, #250,
|
silentNoteMinDurMs: 180, #250,
|
||||||
|
|
||||||
|
defaultHoldDelayUsecs: 1000,
|
||||||
|
|
||||||
# Midi file player
|
# Midi file player
|
||||||
midiFileFn: "/home/kevin/media/audio/midi/txt/round4.txt",
|
midiFileFn: "/home/kevin/media/audio/midi/txt/round4.txt",
|
||||||
|
|
||||||
@ -87,14 +89,12 @@
|
|||||||
|
|
||||||
full_pulse20L: [ 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250, 3500, 3750, 4000, 4250, 4500, 4750, 5000, 5250, 5500, 5750, 6000, 6250, 6500, 6750, 7000, 7250, 7500, 7750, 8000, 8250, 8500, 8750, 9000, 9250, 9500, 9750, 10000, 10250, 10500, 10750, 11000, 11250, 11500, 11750, 12000, 12250, 12500, 12750, 13000, 13500, 14000, 14500, 15000, 15500 ],
|
full_pulse20L: [ 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250, 3500, 3750, 4000, 4250, 4500, 4750, 5000, 5250, 5500, 5750, 6000, 6250, 6500, 6750, 7000, 7250, 7500, 7750, 8000, 8250, 8500, 8750, 9000, 9250, 9500, 9750, 10000, 10250, 10500, 10750, 11000, 11250, 11500, 11750, 12000, 12250, 12500, 12750, 13000, 13500, 14000, 14500, 15000, 15500 ],
|
||||||
|
|
||||||
# 60,72
|
|
||||||
full_pulse21L: [ 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250, 3500, 3750, 4000, 4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000, 8500, 9000, 10000, 11000, 12000, 13000, 14000, 15000, 16000, 17000, 18000, 19000 ],
|
full_pulse21L: [ 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250, 3500, 3750, 4000, 4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000, 8500, 9000, 10000, 11000, 12000, 13000, 14000, 15000, 16000, 17000, 18000, 19000 ],
|
||||||
|
|
||||||
# 48,36,85
|
|
||||||
full_pulse22L: [ 3500, 3750, 4000, 4250, 4500, 4750, 5000, 5250, 5500, 5750, 6000, 6250, 6500, 6750, 7000, 7500, 8000, 8500, 9000, 9500, 10000, 10500, 11000, 12000, 12500, 13000, 14000, 15000, 16000, 17000, 18000, 19000 ],
|
full_pulse22L: [ 3500, 3750, 4000, 4250, 4500, 4750, 5000, 5250, 5500, 5750, 6000, 6250, 6500, 6750, 7000, 7500, 8000, 8500, 9000, 9500, 10000, 10500, 11000, 12000, 12500, 13000, 14000, 15000, 16000, 17000, 18000, 19000 ],
|
||||||
|
|
||||||
# 84
|
# 60,72,84
|
||||||
full_pulseL: [ 2000, 2250, 2500,2750, 3000, 3250, 3500, 3750, 4000, 4250, 4500, 4750, 5000, 5250, 5500, 5750, 6000, 6250, 6500, 6750, 7000, 7500, 8000, 8500, 9000, 9500, 10000, 10500, 11000, 12000, 12500, 13000, 14000, 15000, 16000 ],
|
full_pulseL: [ 2000, 2250, 2500,2750, 3000, 3250, 3500, 3750, 4000, 4250, 4500, 4750, 5000, 5250, 5500, 5750, 6000, 6250, 6500, 6750, 7000, 7500, 8000, 8500, 9000, 9500, 10000, 10500, 11000, 11500, 12000, 12500, 13000, 14000, 15000, 16000, 17000, 18000, 19000, 20000, 22000 ],
|
||||||
|
|
||||||
# RMS analysis args
|
# RMS analysis args
|
||||||
analysisArgs: {
|
analysisArgs: {
|
||||||
@ -249,7 +249,7 @@
|
|||||||
minMeasDurMs: 140, # minimum candidate note duration
|
minMeasDurMs: 140, # minimum candidate note duration
|
||||||
tolDbPct: 2.0, # tolerance as a percent of targetDb above/below used to form match db window
|
tolDbPct: 2.0, # tolerance as a percent of targetDb above/below used to form match db window
|
||||||
maxPulseUs: 45000, # max. allowable pulse us
|
maxPulseUs: 45000, # max. allowable pulse us
|
||||||
minPulseUs: 8000, # min. allowable pulse us
|
minPulseUs: 2000, # min. allowable pulse us
|
||||||
initPulseUs: 15000, # pulseUs for first note
|
initPulseUs: 15000, # pulseUs for first note
|
||||||
minMatchN: 3, # at least 3 candidate notes must be within tolDbPct to move on to a new targetDb
|
minMatchN: 3, # at least 3 candidate notes must be within tolDbPct to move on to a new targetDb
|
||||||
maxAttemptN: 30, # give up if more than 20 candidate notes fail for a given targetDb
|
maxAttemptN: 30, # give up if more than 20 candidate notes fail for a given targetDb
|
||||||
@ -269,7 +269,7 @@
|
|||||||
33: [[0, 40]],
|
33: [[0, 40]],
|
||||||
34: [[0, 40]],
|
34: [[0, 40]],
|
||||||
35: [[0, 40]],
|
35: [[0, 40]],
|
||||||
36: [[0, 45]],
|
36: [[0, 40]],
|
||||||
37: [[0, 40]],
|
37: [[0, 40]],
|
||||||
38: [[0, 40]],
|
38: [[0, 40]],
|
||||||
39: [[0, 40]],
|
39: [[0, 40]],
|
||||||
@ -292,12 +292,12 @@
|
|||||||
56: [[0, 40]],
|
56: [[0, 40]],
|
||||||
57: [[0, 40]],
|
57: [[0, 40]],
|
||||||
58: [[0, 40]],
|
58: [[0, 40]],
|
||||||
59: [[0, 40]],
|
59: [[0, 45]],
|
||||||
60: [[0, 50]],
|
60: [[0, 40],[10000,50]],
|
||||||
61: [[0, 43]],
|
61: [[0, 40],[10000,50]],
|
||||||
62: [[0, 43]],
|
62: [[0, 40],[10000,50]],
|
||||||
63: [[0, 43]],
|
63: [[0, 40],[10000,50]],
|
||||||
64: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
64: [[0, 40],[10000,50]],
|
||||||
65: [[0, 99]],
|
65: [[0, 99]],
|
||||||
66: [[0, 40]],
|
66: [[0, 40]],
|
||||||
67: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
67: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
||||||
@ -305,20 +305,20 @@
|
|||||||
69: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
69: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
||||||
70: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
70: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
||||||
71: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
71: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
||||||
72: [[0, 45],[11000, 65] ],
|
72: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
73: [[0, 45],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
73: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
74: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
74: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
75: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
75: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
76: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
76: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
77: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
77: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
78: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
78: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
79: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
79: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
80: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
80: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
81: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
81: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
82: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
|
82: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
83: [[0, 42]],
|
83: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
84: [[0, 42],[10000,50],[11000,60]],
|
84: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
85: [[0, 42],[9000,45],[10000,50],[11000,60]],
|
85: [[0, 42],[8000,44],[9000,46],[10000, 48],[11000,50],[12000,52],[13000,54],[14000,56],[15000,58],[16000,60],[17000,60],[18000,60],[19000,60],[20000,60] ],
|
||||||
86: [[0, 40]],
|
86: [[0, 40]],
|
||||||
87: [[0, 40]],
|
87: [[0, 40]],
|
||||||
88: [[0, 40]],
|
88: [[0, 40]],
|
||||||
|
@ -296,7 +296,7 @@ def plot_resample_pulse_times( inDir, analysisArgsD, midi_pitch, printDir="" ):
|
|||||||
|
|
||||||
fig,axL = plt.subplots(2,1,gridspec_kw={'height_ratios': [2, 1]})
|
fig,axL = plt.subplots(2,1,gridspec_kw={'height_ratios': [2, 1]})
|
||||||
|
|
||||||
axL[0].plot(pulseUsL,rmsDbV,marker='.' )
|
axL[0].plot(pulseUsL,rmsDbV,marker='.',color="red" )
|
||||||
|
|
||||||
#plot_curve( ax, velTblUsL,velTblDbL)
|
#plot_curve( ax, velTblUsL,velTblDbL)
|
||||||
|
|
||||||
|
160
plot_seq_1.py
160
plot_seq_1.py
@ -39,12 +39,21 @@ def fit_to_reference( pkL, refTakeId ):
|
|||||||
return zip(db_outL,us_outL,dur_outL,tid_outL)
|
return zip(db_outL,us_outL,dur_outL,tid_outL)
|
||||||
|
|
||||||
|
|
||||||
def get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD ):
|
def get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD, takeId=None ):
|
||||||
|
|
||||||
inDir = os.path.join(inDir,"%i" % (midi_pitch))
|
inDir = os.path.join(inDir,"%i" % (midi_pitch))
|
||||||
|
|
||||||
|
takeIdL = []
|
||||||
|
if takeId is not None:
|
||||||
|
takeIdL.append(takeId)
|
||||||
|
else:
|
||||||
takeDirL = os.listdir(inDir)
|
takeDirL = os.listdir(inDir)
|
||||||
|
|
||||||
|
# for each take in this directory
|
||||||
|
for take_folder in takeDirL:
|
||||||
|
takeIdL.append(int(take_folder))
|
||||||
|
|
||||||
|
|
||||||
pkL = []
|
pkL = []
|
||||||
|
|
||||||
refTakeId = None
|
refTakeId = None
|
||||||
@ -52,9 +61,7 @@ def get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD ):
|
|||||||
dbRefL = None
|
dbRefL = None
|
||||||
|
|
||||||
# for each take in this directory
|
# for each take in this directory
|
||||||
for take_folder in takeDirL:
|
for take_number in takeIdL:
|
||||||
|
|
||||||
take_number = int(take_folder)
|
|
||||||
|
|
||||||
if refTakeId is None:
|
if refTakeId is None:
|
||||||
refTakeId = take_number
|
refTakeId = take_number
|
||||||
@ -324,8 +331,98 @@ def plot_us_db_curves( ax, inDir, keyMapD, midi_pitch, analysisArgsD, plotResamp
|
|||||||
|
|
||||||
ax.set_ylabel( "%i %s %s" % (midi_pitch, keyMapD[midi_pitch]['type'],keyMapD[midi_pitch]['class']))
|
ax.set_ylabel( "%i %s %s" % (midi_pitch, keyMapD[midi_pitch]['type'],keyMapD[midi_pitch]['class']))
|
||||||
|
|
||||||
|
|
||||||
|
def plot_us_db_take_curve( ax, inDir, keyMapD, midi_pitch, takeId, analysisArgsD ):
|
||||||
|
|
||||||
|
usL, dbL, durMsL, takeIdL, holdDutyPctL = get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD['rmsAnalysisArgs'] )
|
||||||
|
|
||||||
|
reUsL, reDbL, noiseL, resampleL, skipL, firstAudibleIdx, firstNonSkipIdx = get_resample_points( usL, dbL, durMsL, takeIdL, analysisArgsD['resampleMinDurMs'], analysisArgsD['resampleMinDb'], analysisArgsD['resampleNoiseLimitPct'] )
|
||||||
|
|
||||||
|
# plot first audible and non-skip position
|
||||||
|
if False:
|
||||||
|
|
||||||
|
if firstNonSkipIdx is not None:
|
||||||
|
ax.plot( usL[firstNonSkipIdx], dbL[firstNonSkipIdx], markersize=15, marker='+', linestyle='None', color='red')
|
||||||
|
|
||||||
|
if firstAudibleIdx is not None:
|
||||||
|
ax.plot( usL[firstAudibleIdx], dbL[firstAudibleIdx], markersize=15, marker='*', linestyle='None', color='red')
|
||||||
|
|
||||||
|
# plot the resample points
|
||||||
|
if plotResamplePointsFl:
|
||||||
|
ax.plot( reUsL, reDbL, markersize=13, marker='x', linestyle='None', color='green')
|
||||||
|
|
||||||
|
# plot the noisy sample positions
|
||||||
|
if noiseL:
|
||||||
|
nUsL,nDbL = zip(*noiseL)
|
||||||
|
ax.plot( nUsL, nDbL, marker='o', markersize=9, linestyle='None', color='black')
|
||||||
|
|
||||||
|
# plot the noisy sample positions and the neighbors included in the noisy region
|
||||||
|
if resampleL:
|
||||||
|
nUsL,nDbL = zip(*resampleL)
|
||||||
|
ax.plot( nUsL, nDbL, marker='+', markersize=8, linestyle='None', color='red')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# plot actual sample points
|
||||||
|
|
||||||
|
elbow_us = None
|
||||||
|
elbow_db = None
|
||||||
|
elbow_len = None
|
||||||
|
|
||||||
|
usL,dbL,takeIdL = zip(*[(us,dbL[i],takeIdL[i]) for i,us in enumerate(usL) if usMax is None or us <= usMax])
|
||||||
|
|
||||||
|
if plotTakesFl:
|
||||||
|
for takeId in list(set(takeIdL)):
|
||||||
|
|
||||||
|
# get the us,db points included in this take
|
||||||
|
xL,yL = zip(*[(usL[i],dbL[i]) for i in range(len(usL)) if takeIdL[i]==takeId ])
|
||||||
|
|
||||||
|
ax.plot(xL,yL, marker='.',label=takeId)
|
||||||
|
|
||||||
|
for i,(x,y) in enumerate(zip(xL,yL)):
|
||||||
|
ax.text(x,y,str(i))
|
||||||
|
|
||||||
|
|
||||||
|
#if elbow_len is None or len(xL) > elbow_len:
|
||||||
|
if takeId+1 == len(set(takeIdL)):
|
||||||
|
elbow_us,elbow_db = elbow.find_elbow(xL,yL)
|
||||||
|
elbow_len = len(xL)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
ax.plot(usL, dbL, marker='.')
|
||||||
|
|
||||||
|
ax.plot([elbow_us],[elbow_db],marker='*',markersize=12,color='red',linestyle='None')
|
||||||
|
|
||||||
|
# plot the skip points in yellow
|
||||||
|
if False:
|
||||||
|
if skipL:
|
||||||
|
nUsL,nDbL = zip(*skipL)
|
||||||
|
ax.plot( nUsL, nDbL, marker='.', linestyle='None', color='yellow')
|
||||||
|
|
||||||
|
# plot the locations where the hold duty cycle changes with vertical black lines
|
||||||
|
for us_duty in holdDutyPctL:
|
||||||
|
us,duty = tuple(us_duty)
|
||||||
|
if us > 0:
|
||||||
|
ax.axvline(us,color='black')
|
||||||
|
|
||||||
|
# plot the 'minDb' reference line
|
||||||
|
ax.axhline(analysisArgsD['resampleMinDb'] ,color='black')
|
||||||
|
|
||||||
|
if os.path.isfile("minInterpDb.json"):
|
||||||
|
with open("minInterpDb.json","r") as f:
|
||||||
|
r = json.load(f)
|
||||||
|
if midi_pitch in r['pitchL']:
|
||||||
|
ax.axhline( r['minDbL'][ r['pitchL'].index(midi_pitch) ], color='blue' )
|
||||||
|
ax.axhline( r['maxDbL'][ r['pitchL'].index(midi_pitch) ], color='blue' )
|
||||||
|
|
||||||
|
ax.set_ylabel( "%i %s %s" % (midi_pitch, keyMapD[midi_pitch]['type'],keyMapD[midi_pitch]['class']))
|
||||||
|
|
||||||
|
|
||||||
def plot_us_db_curves_main( inDir, cfg, pitchL, plotTakesFl=True, usMax=None, printDir="" ):
|
def plot_us_db_curves_main( inDir, cfg, pitchL, plotTakesFl=True, usMax=None, printDir="" ):
|
||||||
|
|
||||||
|
|
||||||
analysisArgsD = cfg.analysisArgs
|
analysisArgsD = cfg.analysisArgs
|
||||||
keyMapD = { d['midi']:d for d in cfg.key_mapL }
|
keyMapD = { d['midi']:d for d in cfg.key_mapL }
|
||||||
axN = len(pitchL)
|
axN = len(pitchL)
|
||||||
@ -336,6 +433,7 @@ def plot_us_db_curves_main( inDir, cfg, pitchL, plotTakesFl=True, usMax=None, pr
|
|||||||
fig.set_size_inches(18.5, 10.5*axN)
|
fig.set_size_inches(18.5, 10.5*axN)
|
||||||
|
|
||||||
for ax,midi_pitch in zip(axL,pitchL):
|
for ax,midi_pitch in zip(axL,pitchL):
|
||||||
|
|
||||||
plot_us_db_curves( ax,inDir, keyMapD, midi_pitch, analysisArgsD, plotTakesFl=plotTakesFl, usMax=usMax )
|
plot_us_db_curves( ax,inDir, keyMapD, midi_pitch, analysisArgsD, plotTakesFl=plotTakesFl, usMax=usMax )
|
||||||
|
|
||||||
if plotTakesFl:
|
if plotTakesFl:
|
||||||
@ -346,6 +444,54 @@ def plot_us_db_curves_main( inDir, cfg, pitchL, plotTakesFl=True, usMax=None, pr
|
|||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
def _plot_us_db_takes( inDir, cfg, pitchL, takeIdL, printDir="", printFn="" ):
|
||||||
|
|
||||||
|
assert( len(pitchL) == len(takeIdL) )
|
||||||
|
|
||||||
|
analysisArgsD = cfg.analysisArgs
|
||||||
|
keyMapD = { d['midi']:d for d in cfg.key_mapL }
|
||||||
|
fig,ax = plt.subplots(1,1)
|
||||||
|
|
||||||
|
fig.set_size_inches(18.5, 10.5)
|
||||||
|
|
||||||
|
for midi_pitch,takeId in zip(pitchL,takeIdL):
|
||||||
|
|
||||||
|
usL, dbL, durMsL, _, holdDutyPctL = get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD['rmsAnalysisArgs'], takeId=takeId )
|
||||||
|
|
||||||
|
ax.plot(usL,dbL, marker='.',label="%i:%i %s %s" % (midi_pitch,takeId,keyMapD[midi_pitch]['class'],keyMapD[midi_pitch]['type']))
|
||||||
|
|
||||||
|
# for i,(x,y) in enumerate(zip(usL,dbL)):
|
||||||
|
# ax.text(x,y,str(i))
|
||||||
|
|
||||||
|
|
||||||
|
if printDir:
|
||||||
|
plt.savefig(os.path.join(printDir,printFn),format="png")
|
||||||
|
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
def plot_us_db_takes( inDir, cfg, pitchL, printDir=""):
|
||||||
|
|
||||||
|
takeIdL = None
|
||||||
|
takeIdL = [ pitchL[i] for i in range(1,len(pitchL),2) ]
|
||||||
|
pitchL = [ pitchL[i] for i in range(0,len(pitchL),2) ]
|
||||||
|
|
||||||
|
return _plot_us_db_takes( inDir, cfg, pitchL, takeIdL, printDir, "us_db_takes.png")
|
||||||
|
|
||||||
|
def plot_us_db_takes_last( inDir, cfg, pitchL, printDir ):
|
||||||
|
|
||||||
|
takeIdL = []
|
||||||
|
for pitch in pitchL:
|
||||||
|
|
||||||
|
inDirL = os.listdir( os.path.join(inDir,str(pitch)))
|
||||||
|
|
||||||
|
inDirL = sorted(inDirL)
|
||||||
|
|
||||||
|
takeIdL.append( int(inDirL[-1]) )
|
||||||
|
|
||||||
|
return _plot_us_db_takes( inDir, cfg, pitchL, takeIdL, printDir, "us_db_takes_last.png")
|
||||||
|
|
||||||
|
|
||||||
def plot_all_noise_curves( inDir, cfg, pitchL=None ):
|
def plot_all_noise_curves( inDir, cfg, pitchL=None ):
|
||||||
|
|
||||||
pitchFolderL = os.listdir(inDir)
|
pitchFolderL = os.listdir(inDir)
|
||||||
@ -800,7 +946,7 @@ def gen_vel_map( inDir, cfg, minMaxDbFn, dynLevelN, cacheFn ):
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
printDir =os.path.expanduser( "~/src/picadae_ac_3/doc")
|
printDir = None #os.path.expanduser( "~/src/picadae_ac_3/doc")
|
||||||
cfgFn = sys.argv[1]
|
cfgFn = sys.argv[1]
|
||||||
inDir = sys.argv[2]
|
inDir = sys.argv[2]
|
||||||
mode = sys.argv[3]
|
mode = sys.argv[3]
|
||||||
@ -814,6 +960,10 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
if mode == 'us_db':
|
if mode == 'us_db':
|
||||||
plot_us_db_curves_main( inDir, cfg, pitchL, plotTakesFl=True,usMax=None, printDir=printDir )
|
plot_us_db_curves_main( inDir, cfg, pitchL, plotTakesFl=True,usMax=None, printDir=printDir )
|
||||||
|
elif mode == 'us_db_pitch_take':
|
||||||
|
plot_us_db_takes( inDir, cfg, pitchL, printDir=printDir)
|
||||||
|
elif mode == 'us_db_pitch_last':
|
||||||
|
plot_us_db_takes_last( inDir, cfg, pitchL, printDir=printDir)
|
||||||
elif mode == 'noise':
|
elif mode == 'noise':
|
||||||
plot_all_noise_curves( inDir, cfg, pitchL )
|
plot_all_noise_curves( inDir, cfg, pitchL )
|
||||||
elif mode == 'min_max':
|
elif mode == 'min_max':
|
||||||
|
@ -30,11 +30,15 @@ class RT_Analyzer:
|
|||||||
|
|
||||||
if result:
|
if result:
|
||||||
|
|
||||||
|
|
||||||
sigV = result.value
|
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)
|
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 )
|
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)] )
|
pkIdxL = locate_peak_indexes( rmsDbV, rms_srate, [( begTimeMs, endTimeMs)] )
|
||||||
|
Loading…
Reference in New Issue
Block a user