[py] move cut_slice from cut to cmd to avoid cyclic import
[aubio.git] / python / lib / aubio / cut.py
1 #! /usr/bin/env python
2
3 """ this file was written by Paul Brossier
4   it is released under the GNU/GPL license.
5 """
6
7 import sys
8 from aubio.cmd import AubioArgumentParser, _cut_slice
9
10 def aubio_cut_parser():
11     parser = AubioArgumentParser()
12     parser.add_input()
13     parser.add_argument("-O", "--onset-method",
14             action="store", dest="onset_method", default='default',
15             metavar = "<onset_method>",
16             help="onset detection method [default=default] \
17                     complexdomain|hfc|phase|specdiff|energy|kl|mkl")
18     # cutting methods
19     parser.add_argument("-b", "--beat",
20             action="store_true", dest="beat", default=False,
21             help="slice at beat locations")
22     """
23     parser.add_argument("-S", "--silencecut",
24             action="store_true", dest="silencecut", default=False,
25             help="use silence locations")
26     parser.add_argument("-s", "--silence",
27             metavar = "<value>",
28             action="store", dest="silence", default=-70,
29             help="silence threshold [default=-70]")
30             """
31     # algorithm parameters
32     parser.add_buf_hop_size()
33     parser.add_argument("-t", "--threshold", "--onset-threshold",
34             metavar = "<threshold>", type=float,
35             action="store", dest="threshold", default=0.3,
36             help="onset peak picking threshold [default=0.3]")
37     parser.add_argument("-c", "--cut",
38             action="store_true", dest="cut", default=False,
39             help="cut input sound file at detected labels")
40     parser.add_minioi()
41
42     """
43     parser.add_argument("-D", "--delay",
44             action = "store", dest = "delay", type = float,
45             metavar = "<seconds>", default=0,
46             help="number of seconds to take back [default=system]\
47                     default system delay is 3*hopsize/samplerate")
48     parser.add_argument("-C", "--dcthreshold",
49             metavar = "<value>",
50             action="store", dest="dcthreshold", default=1.,
51             help="onset peak picking DC component [default=1.]")
52     parser.add_argument("-L", "--localmin",
53             action="store_true", dest="localmin", default=False,
54             help="use local minima after peak detection")
55     parser.add_argument("-d", "--derivate",
56             action="store_true", dest="derivate", default=False,
57             help="derivate onset detection function")
58     parser.add_argument("-z", "--zerocross",
59             metavar = "<value>",
60             action="store", dest="zerothres", default=0.008,
61             help="zero-crossing threshold for slicing [default=0.00008]")
62     # plotting functions
63     parser.add_argument("-p", "--plot",
64             action="store_true", dest="plot", default=False,
65             help="draw plot")
66     parser.add_argument("-x", "--xsize",
67             metavar = "<size>",
68             action="store", dest="xsize", default=1.,
69             type=float, help="define xsize for plot")
70     parser.add_argument("-y", "--ysize",
71             metavar = "<size>",
72             action="store", dest="ysize", default=1.,
73             type=float, help="define ysize for plot")
74     parser.add_argument("-f", "--function",
75             action="store_true", dest="func", default=False,
76             help="print detection function")
77     parser.add_argument("-n", "--no-onsets",
78             action="store_true", dest="nplot", default=False,
79             help="do not plot detected onsets")
80     parser.add_argument("-O", "--outplot",
81             metavar = "<output_image>",
82             action="store", dest="outplot", default=None,
83             help="save plot to output.{ps,png}")
84     parser.add_argument("-F", "--spectrogram",
85             action="store_true", dest="spectro", default=False,
86             help="add spectrogram to the plot")
87     """
88     parser.add_slicer_options()
89     parser.add_verbose_help()
90     return parser
91
92
93 def _cut_analyze(options):
94     hopsize = options.hop_size
95     bufsize = options.buf_size
96     samplerate = options.samplerate
97     source_uri = options.source_uri
98
99     # analyze pass
100     from aubio import onset, tempo, source
101
102     s = source(source_uri, samplerate, hopsize)
103     if samplerate == 0:
104         samplerate = s.samplerate
105         options.samplerate = samplerate
106
107     if options.beat:
108         o = tempo(options.onset_method, bufsize, hopsize,
109                 samplerate=samplerate)
110     else:
111         o = onset(options.onset_method, bufsize, hopsize,
112                 samplerate=samplerate)
113         if options.minioi:
114             if options.minioi.endswith('ms'):
115                 o.set_minioi_ms(int(options.minioi[:-2]))
116             elif options.minioi.endswith('s'):
117                 o.set_minioi_s(int(options.minioi[:-1]))
118             else:
119                 o.set_minioi(int(options.minioi))
120     o.set_threshold(options.threshold)
121
122     timestamps = []
123     total_frames = 0
124     while True:
125         samples, read = s()
126         if o(samples):
127             timestamps.append(o.get_last())
128             if options.verbose:
129                 print("%.4f" % o.get_last_s())
130         total_frames += read
131         if read < hopsize:
132             break
133     del s
134     return timestamps, total_frames
135
136 def main():
137     parser = aubio_cut_parser()
138     options = parser.parse_args()
139     if not options.source_uri and not options.source_uri2:
140         sys.stderr.write("Error: no file name given\n")
141         parser.print_help()
142         sys.exit(1)
143     elif options.source_uri2 is not None:
144         options.source_uri = options.source_uri2
145
146     # analysis
147     timestamps, total_frames = _cut_analyze(options)
148
149     # print some info
150     duration = float(total_frames) / float(options.samplerate)
151     base_info = '%(source_uri)s' % {'source_uri': options.source_uri}
152     base_info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % \
153             {'duration': duration, 'samplerate': options.samplerate}
154
155     info = "found %d timestamps in " % len(timestamps)
156     info += base_info
157     sys.stderr.write(info)
158
159     if options.cut:
160         _cut_slice(options, timestamps)
161         info = "created %d slices from " % len(timestamps)
162         info += base_info
163         sys.stderr.write(info)