4 커밋

작성자 SHA1 메시지 날짜
  kevin 648e29c4c4 p_ac.py, p_ac.yml : Changes to support Steinway D calibration. 3 년 전
  kevin 011606c5cf rt_note_analysis.py : Change to support stereo signals. 3 년 전
  kevin b4b0973e9a plot_seq.py,plot_seq_1.py : Add new plots. 3 년 전
  kevin 846f1d5aa8 README.md : Update and add new plots. 3 년 전
8개의 변경된 파일282개의 추가작업 그리고 57개의 파일을 삭제
  1. 50
    1
      README.md
  2. BIN
      doc/us_db_takes.png
  3. BIN
      doc/us_db_takes_last.png
  4. 41
    19
      p_ac.py
  5. 28
    28
      p_ac.yml
  6. 1
    1
      plot_seq.py
  7. 157
    7
      plot_seq_1.py
  8. 5
    1
      rt_note_analysis.py

+ 50
- 1
README.md 파일 보기

29
 
29
 
30
 ![Plot Seq 1](doc/do_td_plot.png)
30
 ![Plot Seq 1](doc/do_td_plot.png)
31
 
31
 
32
+Print a specific pitch and take.
33
+
32
 ````
34
 ````
33
-    python plot_seq.py ~/temp/p_ac_3_od p_ac.yml 60 10
35
+    python plot_seq.py p_ac.yml ~/temp/p_ac_3_of td_plot 60 2
34
     
36
     
35
     do_td_plot(inDir,cfg.analysisArgs, pitch, take_id )
37
     do_td_plot(inDir,cfg.analysisArgs, pitch, take_id )
36
 ````
38
 ````
39
 
41
 
40
 ![Multi Usec dB](doc/us_db.png)
42
 ![Multi Usec dB](doc/us_db.png)
41
 
43
 
44
+Plot all the takes for a given pitch
45
+
42
 ````
46
 ````
43
 python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od us_db 84
47
 python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od us_db 84
44
 ````
48
 ````
45
 
49
 
50
+---
51
+
52
+![Overlapping USec dB](doc/us_db_takes.png)
53
+
54
+Plot a specific set of pitches and takes.
55
+
56
+````
57
+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
58
+````
59
+
60
+---
61
+
62
+![Overlapping USec dB](doc/us_db_takes_last.png)
63
+
64
+Plot the last take from a list of pitches.
65
+
66
+````
67
+python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_of us_db_pitch_last 77 78 79 80
68
+````
69
+
46
 
70
 
47
 ---
71
 ---
48
 
72
 
49
 ![Multi Plot 1](doc/multi_plot.png)
73
 ![Multi Plot 1](doc/multi_plot.png)
50
 
74
 
75
+Plot the time domain envelope for a specific set of pitches and takes.
76
+
51
 ````
77
 ````
52
 python plot_seq.py p_ac.yml ~/temp/p_ac_3_od td_multi_plot 60 3 60 4 60 5
78
 python plot_seq.py p_ac.yml ~/temp/p_ac_3_od td_multi_plot 60 3 60 4 60 5
53
 
79
 
57
 
83
 
58
 ![Spectral Ranges](doc/plot_spectral_ranges.png)
84
 ![Spectral Ranges](doc/plot_spectral_ranges.png)
59
 
85
 
86
+Plot the spectrum with harmonic location markers of a specific set of pitches and takes.
87
+
60
 ````
88
 ````
61
 #                                                                 pitch0 takeId0 pitch1 takeId1
89
 #                                                                 pitch0 takeId0 pitch1 takeId1
62
 python plot_seq.py p_ac.yml ~/temp/p_ac_3_od plot_spectral_ranges   60      3       60      4
90
 python plot_seq.py p_ac.yml ~/temp/p_ac_3_od plot_spectral_ranges   60      3       60      4
67
 
95
 
68
 ![Usec dB Spread](doc/us_db_map.png)
96
 ![Usec dB Spread](doc/us_db_map.png)
69
 
97
 
98
+Plot the microsecond variance to achieve a given decibel value.
99
+
70
 ````
100
 ````
71
 python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od us_db_map 84 72
101
 python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od us_db_map 84 72
72
 ````
102
 ````
73
 
103
 
74
 ---
104
 ---
75
 
105
 
106
+![Resample](doc/resample_pulse_times.png)
107
+
108
+Analyze all takes for given pitch and show the mean us/db curve and
109
+places where resampling may be necessary.
110
+
111
+````
112
+python plot_seq.py p_ac.yml ~/temp/p_ac_3_of resample_pulse_times 84
113
+````
114
+
115
+
116
+---
117
+
76
 ![Min Max](doc/min_max_db.png)
118
 ![Min Max](doc/min_max_db.png)
77
 
119
 
120
+Plot the min and max decibel values for specified pitches.
121
+
78
 ````
122
 ````
79
 python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od min_max 36 48 60 72 84
123
 python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od min_max 36 48 60 72 84
80
 ````
124
 ````
83
 
127
 
84
 ![Min Max 2](doc/min_max_db_2.png)
128
 ![Min Max 2](doc/min_max_db_2.png)
85
 
129
 
130
+Plot the min and max decibel values for specified pitches.
131
+
86
 ````
132
 ````
87
 #                                                        pitch0 pitch1 pitch2 pitch3 pitch4 takeId
133
 #                                                        pitch0 pitch1 pitch2 pitch3 pitch4 takeId
88
 python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od min_max_2   36     48      60     72     84     2
134
 python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od min_max_2   36     48      60     72     84     2
91
 ---
137
 ---
92
 ![Manual dB](doc/manual_db.png)
138
 ![Manual dB](doc/manual_db.png)
93
 
139
 
140
+Plot the min and max decibel values for specified set of manually corrected pitches.
141
+
142
+
94
 ````
143
 ````
95
 python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od manual_db
144
 python plot_seq_1.py p_ac.yml ~/temp/p_ac_3_od manual_db
96
 ````
145
 ````

BIN
doc/us_db_takes.png 파일 보기


BIN
doc/us_db_takes_last.png 파일 보기


+ 41
- 19
p_ac.py 파일 보기

58
         self.eventTimeL = [[0,0]  for _ in range(len(pulseUsL))] # initialize the event time         
58
         self.eventTimeL = [[0,0]  for _ in range(len(pulseUsL))] # initialize the event time         
59
         self.beginMs    = ms
59
         self.beginMs    = ms
60
         self.playOnlyFl = playOnlyFl
60
         self.playOnlyFl = playOnlyFl
61
-
62
-
61
+                    
63
         # kpl if not playOnlyFl:
62
         # kpl if not playOnlyFl:
64
         self.audio.record_enable(True)   # start recording audio
63
         self.audio.record_enable(True)   # start recording audio
64
+
65
+        print("Hold Delay from end of attack:",cfg.defaultHoldDelayUsecs)                    
66
+        self.api.set_hold_delay(pitch,cfg.defaultHoldDelayUsecs)
65
         
67
         
66
         self.tick(ms)                    # play the first note
68
         self.tick(ms)                    # play the first note
67
         
69
         
123
         
125
         
124
     def _get_duty_cycle( self, pulseUsec ):
126
     def _get_duty_cycle( self, pulseUsec ):
125
         return self.holdDutyPctD[ pulseUsec ]
127
         return self.holdDutyPctD[ pulseUsec ]
126
-    
127
-        dutyPct = self.holdDutyPctL[0][1]
128
-        for refUsec,refDuty in self.holdDutyPctL:
129
-            if pulseUsec < refUsec:
130
-                break
131
-            dutyPct = refDuty
132
-
133
-        return dutyPct
134
             
128
             
135
     def _set_duty_cycle( self, pitch, pulseUsec ):
129
     def _set_duty_cycle( self, pitch, pulseUsec ):
136
 
130
 
131
+        
137
         dutyPct = self._get_duty_cycle( pulseUsec )
132
         dutyPct = self._get_duty_cycle( pulseUsec )
138
 
133
 
139
         if dutyPct != self.prevHoldDutyPct:
134
         if dutyPct != self.prevHoldDutyPct:
267
                 #self.pulseUsL,_,_ = form_resample_pulse_time_list( outDir, self.cfg.analysisArgs )
262
                 #self.pulseUsL,_,_ = form_resample_pulse_time_list( outDir, self.cfg.analysisArgs )
268
                 self.pulseUsL = get_resample_points_wrap( baseDir, pitch, self.cfg.analysisArgs )
263
                 self.pulseUsL = get_resample_points_wrap( baseDir, pitch, self.cfg.analysisArgs )
269
 
264
 
265
+
270
             holdDutyPctL = self.cfg.calibrateArgs['holdDutyPctD'][pitch]
266
             holdDutyPctL = self.cfg.calibrateArgs['holdDutyPctD'][pitch]
271
             
267
             
268
+            
272
             if playOnlyFl:
269
             if playOnlyFl:
273
-                self.pulseUsL,_,holdDutyPctL = form_final_pulse_list( outDir,  pitch,  self.cfg.analysisArgs, take_id=None )
270
+
271
+                self.pulseUsL,_,holdDutyPctL = form_final_pulse_list( baseDir,  pitch,  self.cfg.analysisArgs, take_id=None )
274
 
272
 
275
                 noteN = cfg.analysisArgs['auditionNoteN']
273
                 noteN = cfg.analysisArgs['auditionNoteN']
276
                 self.pulseUsL   = [ self.pulseUsL[ int(round(i*126.0/(noteN-1)))] for i in range(noteN) ]
274
                 self.pulseUsL   = [ self.pulseUsL[ int(round(i*126.0/(noteN-1)))] for i in range(noteN) ]
277
 
275
 
276
+                
278
             else:
277
             else:
279
                 outDir = os.path.join( outDir, str(outDir_id) )
278
                 outDir = os.path.join( outDir, str(outDir_id) )
280
 
279
 
339
                 self.audio_dev_list(0)
338
                 self.audio_dev_list(0)
340
             
339
             
341
         else:
340
         else:
341
+            print("The cfg file has no audio stanza. No audio device will be initialized.")
342
             self.audioDev = None
342
             self.audioDev = None
343
 
343
 
344
         if True:
344
         if True:
368
                 self.calibrate = None #Calibrate( cfg.calibrateArgs, self.audioDev, self.midiDev, self.api )
368
                 self.calibrate = None #Calibrate( cfg.calibrateArgs, self.audioDev, self.midiDev, self.api )
369
 
369
 
370
                 self.midiFilePlayer = MidiFilePlayer( cfg, self.api, self.midiDev, cfg.midiFileFn )
370
                 self.midiFilePlayer = MidiFilePlayer( cfg, self.api, self.midiDev, cfg.midiFileFn )
371
-    
371
+
372
         return res
372
         return res
373
 
373
 
374
     def tick( self, ms ):
374
     def tick( self, ms ):
389
             self.midiFilePlayer.tick(ms)
389
             self.midiFilePlayer.tick(ms)
390
 
390
 
391
     def audio_dev_list( self, ms ):
391
     def audio_dev_list( self, ms ):
392
-        portL = self.audioDev.get_port_list( True )
393
-
394
-        for port in portL:
395
-            print("chs:%4i label:%s" % (port['chN'],port['label']))
396
 
392
 
393
+        if self.audioDev is not None:
394
+            portL = self.audioDev.get_port_list( True )
395
+        
396
+            for port in portL:
397
+                print("chs:%4i label:%s" % (port['chN'],port['label']))
398
+        
397
     def midi_dev_list( self, ms ):
399
     def midi_dev_list( self, ms ):
398
         d = self.midiDev.get_port_list( True )
400
         d = self.midiDev.get_port_list( True )
399
 
401
 
411
         self.cal_keys.start(  ms, pitchL, cfg.full_pulseL )
413
         self.cal_keys.start(  ms, pitchL, cfg.full_pulseL )
412
 
414
 
413
     def play_keys_start( self, ms, pitchRangeL ):
415
     def play_keys_start( self, ms, pitchRangeL ):
414
-        chordL = [ [pitch]  for pitch in range(pitchRangeL[0], pitchRangeL[1]+1)]
416
+        chordL = [ pitch  for pitch in range(pitchRangeL[0], pitchRangeL[1]+1)]
415
         self.cal_keys.start(  ms, chordL, cfg.full_pulseL, playOnlyFl=True )
417
         self.cal_keys.start(  ms, chordL, cfg.full_pulseL, playOnlyFl=True )
416
 
418
 
417
     def keyboard_start_pulse_idx( self, ms, argL ):
419
     def keyboard_start_pulse_idx( self, ms, argL ):
709
     return ap.parse_args()
711
     return ap.parse_args()
710
     
712
     
711
             
713
             
712
-    
714
+def create_logger():
715
+    import multiprocessing, logging
716
+    logger = multiprocessing.get_logger()
717
+    logger.setLevel(logging.INFO)
718
+    formatter = logging.Formatter(\
719
+        '[%(asctime)s| %(levelname)s| %(processName)s] %(message)s')
720
+    handler = logging.FileHandler('/home/kevin/temp/p_ac_log.txt')
721
+    handler.setFormatter(formatter)
722
+
723
+    # this bit will make sure you won't have 
724
+    # duplicated messages in the output
725
+    if not len(logger.handlers): 
726
+        logger.addHandler(handler)
727
+    return logger
728
+
713
 if __name__ == "__main__":
729
 if __name__ == "__main__":
730
+
731
+
732
+    from multiprocessing import Pool
733
+    logger = create_logger()
734
+    logger.info('Starting pooling')
735
+    #p = Pool()
714
     
736
     
715
-    logging.basicConfig()
737
+    #logging.basicConfig()
716
 
738
 
717
     #mplog = multiprocessing.log_to_stderr()
739
     #mplog = multiprocessing.log_to_stderr()
718
     #mplog.setLevel(logging.INFO)
740
     #mplog.setLevel(logging.INFO)

+ 28
- 28
p_ac.yml 파일 보기

25
     prescaler_usec: 16,
25
     prescaler_usec: 16,
26
     pwm_div: 5,
26
     pwm_div: 5,
27
     serial_sync_timeout_ms: 10000,
27
     serial_sync_timeout_ms: 10000,
28
-
28
+    
29
 
29
 
30
     # MeasureSeq args
30
     # MeasureSeq args
31
-    outDir: "~/temp/p_ac_3_oe",
31
+    outDir: "~/temp/p_ac_3_of",
32
     noteDurMs: 500,
32
     noteDurMs: 500,
33
     pauseDurMs: 500,
33
     pauseDurMs: 500,
34
     reversePulseListFl: True,
34
     reversePulseListFl: True,
37
     silentNoteMaxPulseUs: 15000,
37
     silentNoteMaxPulseUs: 15000,
38
     silentNoteMinDurMs: 180, #250,
38
     silentNoteMinDurMs: 180, #250,
39
 
39
 
40
+    defaultHoldDelayUsecs: 1000,
41
+
40
     # Midi file player
42
     # Midi file player
41
     midiFileFn: "/home/kevin/media/audio/midi/txt/round4.txt",
43
     midiFileFn: "/home/kevin/media/audio/midi/txt/round4.txt",
42
     
44
     
87
 
89
 
88
     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 ],
90
     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 ],
89
 
91
 
90
-    # 60,72
91
     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 ],
92
     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 ],
92
 
93
 
93
-    # 48,36,85
94
     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 ],
94
     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 ],
95
 
95
 
96
-    # 84
97
-    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  ],
96
+    # 60,72,84    
97
+    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  ],
98
 
98
 
99
     # RMS analysis args
99
     # RMS analysis args
100
     analysisArgs: {
100
     analysisArgs: {
249
           minMeasDurMs: 140,             # minimum candidate note duration
249
           minMeasDurMs: 140,             # minimum candidate note duration
250
           tolDbPct: 2.0,                 # tolerance as a percent of targetDb above/below used to form match db window
250
           tolDbPct: 2.0,                 # tolerance as a percent of targetDb above/below used to form match db window
251
           maxPulseUs: 45000,             # max. allowable pulse us
251
           maxPulseUs: 45000,             # max. allowable pulse us
252
-          minPulseUs:  8000,             # min. allowable pulse us
252
+          minPulseUs:  2000,             # min. allowable pulse us
253
           initPulseUs: 15000,            # pulseUs for first note
253
           initPulseUs: 15000,            # pulseUs for first note
254
           minMatchN: 3,                  # at least 3 candidate notes must be within tolDbPct to move on to a new targetDb
254
           minMatchN: 3,                  # at least 3 candidate notes must be within tolDbPct to move on to a new targetDb
255
           maxAttemptN: 30,               # give up if more than 20 candidate notes fail for a given targetDb
255
           maxAttemptN: 30,               # give up if more than 20 candidate notes fail for a given targetDb
269
           33: [[0, 40]],
269
           33: [[0, 40]],
270
           34: [[0, 40]],
270
           34: [[0, 40]],
271
           35: [[0, 40]],
271
           35: [[0, 40]],
272
-          36: [[0, 45]],
272
+          36: [[0, 40]],
273
           37: [[0, 40]],
273
           37: [[0, 40]],
274
           38: [[0, 40]],
274
           38: [[0, 40]],
275
           39: [[0, 40]],
275
           39: [[0, 40]],
292
           56: [[0, 40]],
292
           56: [[0, 40]],
293
           57: [[0, 40]],
293
           57: [[0, 40]],
294
           58: [[0, 40]],
294
           58: [[0, 40]],
295
-          59: [[0, 40]],
296
-          60: [[0, 50]],
297
-          61: [[0, 43]],
298
-          62: [[0, 43]],
299
-          63: [[0, 43]],
300
-          64: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
295
+          59: [[0, 45]],
296
+          60: [[0, 40],[10000,50]],
297
+          61: [[0, 40],[10000,50]],
298
+          62: [[0, 40],[10000,50]],
299
+          63: [[0, 40],[10000,50]],
300
+          64: [[0, 40],[10000,50]],
301
           65: [[0, 99]],              
301
           65: [[0, 99]],              
302
           66: [[0, 40]],
302
           66: [[0, 40]],
303
           67: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
303
           67: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
305
           69: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
305
           69: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
306
           70: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
306
           70: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
307
           71: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
307
           71: [[0, 40],[14000, 45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
308
-          72: [[0, 45],[11000, 65] ],
309
-          73: [[0, 45],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
310
-          74: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
311
-          75: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
312
-          76: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
313
-          77: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
314
-          78: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
315
-          79: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
316
-          80: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
317
-          81: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
318
-          82: [[0, 40],[14000,45],[15000,50],[16000,55],[17000,60],[18000,65],[19000,55]],
319
-          83: [[0, 42]],
320
-          84: [[0, 42],[10000,50],[11000,60]], 
321
-          85: [[0, 42],[9000,45],[10000,50],[11000,60]],
308
+          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] ],
309
+          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] ],
310
+          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] ],
311
+          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] ],
312
+          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] ],
313
+          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] ],
314
+          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] ],
315
+          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] ],
316
+          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] ],
317
+          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] ],
318
+          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] ],
319
+          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] ],
320
+          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] ],
321
+          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] ],
322
           86: [[0, 40]],
322
           86: [[0, 40]],
323
           87: [[0, 40]],
323
           87: [[0, 40]],
324
           88: [[0, 40]],
324
           88: [[0, 40]],

+ 1
- 1
plot_seq.py 파일 보기

296
     
296
     
297
     fig,axL = plt.subplots(2,1,gridspec_kw={'height_ratios': [2, 1]})
297
     fig,axL = plt.subplots(2,1,gridspec_kw={'height_ratios': [2, 1]})
298
 
298
 
299
-    axL[0].plot(pulseUsL,rmsDbV,marker='.' )
299
+    axL[0].plot(pulseUsL,rmsDbV,marker='.',color="red" )
300
 
300
 
301
     #plot_curve( ax, velTblUsL,velTblDbL)
301
     #plot_curve( ax, velTblUsL,velTblDbL)
302
     
302
     

+ 157
- 7
plot_seq_1.py 파일 보기

39
     return zip(db_outL,us_outL,dur_outL,tid_outL)
39
     return zip(db_outL,us_outL,dur_outL,tid_outL)
40
 
40
 
41
 
41
 
42
-def get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD ):
42
+def get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD, takeId=None ):
43
 
43
 
44
     inDir = os.path.join(inDir,"%i" % (midi_pitch))
44
     inDir = os.path.join(inDir,"%i" % (midi_pitch))
45
 
45
 
46
-    takeDirL =  os.listdir(inDir)
46
+    takeIdL = [] 
47
+    if takeId is not None:
48
+        takeIdL.append(takeId)
49
+    else:
50
+        takeDirL =  os.listdir(inDir)
51
+        
52
+        # for each take in this directory
53
+        for take_folder in takeDirL:            
54
+            takeIdL.append(int(take_folder))
55
+
47
 
56
 
48
     pkL = []
57
     pkL = []
49
 
58
 
52
     dbRefL = None
61
     dbRefL = None
53
 
62
 
54
     # for each take in this directory
63
     # for each take in this directory
55
-    for take_folder in takeDirL:
56
-
57
-        take_number = int(take_folder)
64
+    for take_number in takeIdL:
58
 
65
 
59
         if refTakeId is None:
66
         if refTakeId is None:
60
             refTakeId = take_number
67
             refTakeId = take_number
66
         for db,us,stats in zip(r.pkDbL,r.pkUsL,r.statsL):
73
         for db,us,stats in zip(r.pkDbL,r.pkUsL,r.statsL):
67
             pkL.append( (db,us,stats.durMs,take_number) )
74
             pkL.append( (db,us,stats.durMs,take_number) )
68
 
75
 
69
-
76
+            
70
     pkUsL        = []
77
     pkUsL        = []
71
     pkDbL        = []
78
     pkDbL        = []
72
     durMsL       = []
79
     durMsL       = []
323
                 ax.axhline( r['maxDbL'][ r['pitchL'].index(midi_pitch) ], color='blue' )
330
                 ax.axhline( r['maxDbL'][ r['pitchL'].index(midi_pitch) ], color='blue' )
324
     
331
     
325
     ax.set_ylabel( "%i %s %s" % (midi_pitch, keyMapD[midi_pitch]['type'],keyMapD[midi_pitch]['class']))
332
     ax.set_ylabel( "%i %s %s" % (midi_pitch, keyMapD[midi_pitch]['type'],keyMapD[midi_pitch]['class']))
333
+
334
+
335
+def plot_us_db_take_curve( ax, inDir, keyMapD, midi_pitch, takeId, analysisArgsD ):
336
+
337
+    usL, dbL, durMsL, takeIdL, holdDutyPctL = get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD['rmsAnalysisArgs'] )
338
+
339
+    reUsL, reDbL, noiseL, resampleL, skipL, firstAudibleIdx, firstNonSkipIdx  = get_resample_points( usL, dbL, durMsL, takeIdL, analysisArgsD['resampleMinDurMs'], analysisArgsD['resampleMinDb'], analysisArgsD['resampleNoiseLimitPct'] )
340
+
341
+    # plot first audible and non-skip position
342
+    if False:
343
+    
344
+        if firstNonSkipIdx is not None:
345
+            ax.plot( usL[firstNonSkipIdx], dbL[firstNonSkipIdx], markersize=15, marker='+', linestyle='None', color='red')
346
+
347
+        if firstAudibleIdx is not None:
348
+            ax.plot( usL[firstAudibleIdx], dbL[firstAudibleIdx], markersize=15, marker='*', linestyle='None', color='red')
349
+
350
+        # plot the resample points
351
+        if plotResamplePointsFl:
352
+            ax.plot( reUsL, reDbL, markersize=13, marker='x', linestyle='None', color='green')
353
+
354
+        # plot the noisy sample positions
355
+        if noiseL:
356
+            nUsL,nDbL = zip(*noiseL)
357
+            ax.plot( nUsL, nDbL, marker='o', markersize=9, linestyle='None', color='black')
358
+
359
+        # plot the noisy sample positions and the neighbors included in the noisy region
360
+        if resampleL:
361
+            nUsL,nDbL    = zip(*resampleL)
362
+            ax.plot( nUsL, nDbL, marker='+', markersize=8, linestyle='None', color='red')
363
+
364
+
365
+        
366
+    # plot actual sample points
367
+
368
+    elbow_us  = None
369
+    elbow_db  = None
370
+    elbow_len = None
371
+
372
+    usL,dbL,takeIdL = zip(*[(us,dbL[i],takeIdL[i]) for i,us in enumerate(usL) if usMax is None or us <= usMax])
373
+    
374
+    if plotTakesFl:
375
+        for takeId in list(set(takeIdL)):
376
+
377
+            # get the us,db points included in this take
378
+            xL,yL = zip(*[(usL[i],dbL[i]) for i in range(len(usL)) if takeIdL[i]==takeId  ])
379
+            
380
+            ax.plot(xL,yL, marker='.',label=takeId)
381
+            
382
+            for i,(x,y) in enumerate(zip(xL,yL)):
383
+                ax.text(x,y,str(i))
384
+
385
+
386
+            #if elbow_len is None or len(xL) > elbow_len:
387
+            if takeId+1 == len(set(takeIdL)):
388
+                elbow_us,elbow_db = elbow.find_elbow(xL,yL)
389
+                elbow_len = len(xL)
390
+                
391
+            
392
+            
393
+    else:
394
+        ax.plot(usL, dbL, marker='.')
395
+
396
+    ax.plot([elbow_us],[elbow_db],marker='*',markersize=12,color='red',linestyle='None')
397
+        
398
+    # plot the skip points in yellow
399
+    if False:
400
+        if skipL:
401
+            nUsL,nDbL    = zip(*skipL)
402
+            ax.plot( nUsL, nDbL, marker='.', linestyle='None', color='yellow')
403
+
404
+    # plot the locations where the hold duty cycle changes with vertical black lines
405
+    for us_duty in holdDutyPctL:
406
+        us,duty = tuple(us_duty)
407
+        if us > 0:
408
+            ax.axvline(us,color='black')
409
+
410
+    # plot the 'minDb' reference line
411
+    ax.axhline(analysisArgsD['resampleMinDb'] ,color='black')
412
+
413
+    if os.path.isfile("minInterpDb.json"):
414
+        with open("minInterpDb.json","r") as f:
415
+            r = json.load(f)
416
+            if midi_pitch  in r['pitchL']:
417
+                ax.axhline( r['minDbL'][ r['pitchL'].index(midi_pitch) ], color='blue' )
418
+                ax.axhline( r['maxDbL'][ r['pitchL'].index(midi_pitch) ], color='blue' )
419
+    
420
+    ax.set_ylabel( "%i %s %s" % (midi_pitch, keyMapD[midi_pitch]['type'],keyMapD[midi_pitch]['class']))
421
+
326
     
422
     
327
 def plot_us_db_curves_main( inDir, cfg, pitchL, plotTakesFl=True, usMax=None, printDir="" ):
423
 def plot_us_db_curves_main( inDir, cfg, pitchL, plotTakesFl=True, usMax=None, printDir="" ):
328
 
424
 
425
+    
329
     analysisArgsD = cfg.analysisArgs
426
     analysisArgsD = cfg.analysisArgs
330
     keyMapD       = { d['midi']:d for d in cfg.key_mapL }
427
     keyMapD       = { d['midi']:d for d in cfg.key_mapL }
331
     axN           = len(pitchL)
428
     axN           = len(pitchL)
336
     fig.set_size_inches(18.5, 10.5*axN)
433
     fig.set_size_inches(18.5, 10.5*axN)
337
 
434
 
338
     for ax,midi_pitch in zip(axL,pitchL):
435
     for ax,midi_pitch in zip(axL,pitchL):
436
+        
339
         plot_us_db_curves( ax,inDir, keyMapD, midi_pitch, analysisArgsD, plotTakesFl=plotTakesFl, usMax=usMax )
437
         plot_us_db_curves( ax,inDir, keyMapD, midi_pitch, analysisArgsD, plotTakesFl=plotTakesFl, usMax=usMax )
340
 
438
 
341
     if plotTakesFl:
439
     if plotTakesFl:
346
         
444
         
347
     plt.show()
445
     plt.show()
348
 
446
 
447
+def _plot_us_db_takes( inDir, cfg, pitchL, takeIdL, printDir="", printFn="" ):
448
+    
449
+    assert( len(pitchL) == len(takeIdL) )
450
+    
451
+    analysisArgsD = cfg.analysisArgs
452
+    keyMapD       = { d['midi']:d for d in cfg.key_mapL }
453
+    fig,ax       = plt.subplots(1,1)
454
+        
455
+    fig.set_size_inches(18.5, 10.5)
456
+
457
+    for midi_pitch,takeId in zip(pitchL,takeIdL):
458
+
459
+        usL, dbL, durMsL, _, holdDutyPctL = get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD['rmsAnalysisArgs'], takeId=takeId )
460
+
461
+        ax.plot(usL,dbL, marker='.',label="%i:%i %s %s" % (midi_pitch,takeId,keyMapD[midi_pitch]['class'],keyMapD[midi_pitch]['type']))
462
+
463
+        # for i,(x,y) in enumerate(zip(usL,dbL)):
464
+        #    ax.text(x,y,str(i))
465
+
466
+
467
+    if printDir:
468
+        plt.savefig(os.path.join(printDir,printFn),format="png")
469
+        
470
+    plt.legend()
471
+    plt.show()
472
+    
473
+def plot_us_db_takes( inDir, cfg, pitchL, printDir=""):
474
+
475
+    takeIdL = None
476
+    takeIdL = [ pitchL[i] for i in range(1,len(pitchL),2) ]
477
+    pitchL  = [ pitchL[i] for i in range(0,len(pitchL),2) ]
478
+
479
+    return _plot_us_db_takes( inDir, cfg, pitchL, takeIdL, printDir, "us_db_takes.png")
480
+
481
+def plot_us_db_takes_last( inDir, cfg, pitchL, printDir ):
482
+
483
+    takeIdL = []
484
+    for pitch in pitchL:
485
+
486
+        inDirL = os.listdir( os.path.join(inDir,str(pitch)))
487
+
488
+        inDirL = sorted(inDirL)
489
+        
490
+        takeIdL.append( int(inDirL[-1]) )
491
+
492
+    return _plot_us_db_takes( inDir, cfg, pitchL, takeIdL, printDir, "us_db_takes_last.png")
493
+    
494
+    
349
 def plot_all_noise_curves( inDir, cfg, pitchL=None ):
495
 def plot_all_noise_curves( inDir, cfg, pitchL=None ):
350
 
496
 
351
     pitchFolderL = os.listdir(inDir)
497
     pitchFolderL = os.listdir(inDir)
800
     
946
     
801
 if __name__ == "__main__":
947
 if __name__ == "__main__":
802
 
948
 
803
-    printDir =os.path.expanduser( "~/src/picadae_ac_3/doc")
949
+    printDir = None #os.path.expanduser( "~/src/picadae_ac_3/doc")
804
     cfgFn   = sys.argv[1]
950
     cfgFn   = sys.argv[1]
805
     inDir   = sys.argv[2]
951
     inDir   = sys.argv[2]
806
     mode    = sys.argv[3]
952
     mode    = sys.argv[3]
814
 
960
 
815
     if mode == 'us_db':
961
     if mode == 'us_db':
816
         plot_us_db_curves_main( inDir, cfg, pitchL, plotTakesFl=True,usMax=None, printDir=printDir )
962
         plot_us_db_curves_main( inDir, cfg, pitchL, plotTakesFl=True,usMax=None, printDir=printDir )
963
+    elif mode == 'us_db_pitch_take':
964
+        plot_us_db_takes( inDir, cfg, pitchL, printDir=printDir)
965
+    elif mode == 'us_db_pitch_last':
966
+        plot_us_db_takes_last( inDir, cfg, pitchL, printDir=printDir)
817
     elif mode == 'noise':
967
     elif mode == 'noise':
818
         plot_all_noise_curves( inDir, cfg, pitchL )
968
         plot_all_noise_curves( inDir, cfg, pitchL )
819
     elif mode == 'min_max':
969
     elif mode == 'min_max':

+ 5
- 1
rt_note_analysis.py 파일 보기

30
 
30
 
31
         if result:
31
         if result:
32
 
32
 
33
-
34
             sigV = result.value
33
             sigV = result.value
35
 
34
 
35
+            # convert the audio signal vector to contain only the first (left) channel
36
+            if len(sigV.shape)>1:
37
+                sigV = sigV[:,0].squeeze()
38
+            
36
             anlArgs = types.SimpleNamespace(**anlArgD)
39
             anlArgs = types.SimpleNamespace(**anlArgD)
40
+            
37
 
41
 
38
             rmsDbV, rms_srate, binHz = audio_harm_rms( audioDev.srate, np.squeeze(sigV), anlArgs.rmsWndMs, anlArgs.rmsHopMs, anlArgs.dbLinRef, midi_pitch, anlArgs.harmCandN, anlArgs.harmN  )
42
             rmsDbV, rms_srate, binHz = audio_harm_rms( audioDev.srate, np.squeeze(sigV), anlArgs.rmsWndMs, anlArgs.rmsHopMs, anlArgs.dbLinRef, midi_pitch, anlArgs.harmCandN, anlArgs.harmN  )
39
 
43
 

Loading…
취소
저장