Ignore:
Timestamp:
Sep 16, 2017, 11:55:51 PM (7 years ago)
Author:
Paul Brossier <piem@piem.org>
Branches:
feature/autosink, feature/cnn, feature/cnn_org, feature/constantq, feature/crepe, feature/crepe_org, feature/pitchshift, feature/pydocstrings, feature/timestretch, fix/ffmpeg5, master
Children:
bfbfafa
Parents:
b99e2a5 (diff), cfb7fb7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into dct

File:
1 edited

Legend:

Unmodified
Added
Removed
  • python/lib/aubio/cmd.py

    rb99e2a5 r7b7a58e  
    2121
    2222    subparsers = parser.add_subparsers(title='commands', dest='command',
     23            parser_class= AubioArgumentParser,
    2324            metavar="")
    2425
     26    parser_add_subcommand_help(subparsers)
     27
     28    parser_add_subcommand_onset(subparsers)
     29    parser_add_subcommand_pitch(subparsers)
     30    parser_add_subcommand_beat(subparsers)
     31    parser_add_subcommand_tempo(subparsers)
     32    parser_add_subcommand_notes(subparsers)
     33    parser_add_subcommand_mfcc(subparsers)
     34    parser_add_subcommand_melbands(subparsers)
     35    parser_add_subcommand_quiet(subparsers)
     36    parser_add_subcommand_cut(subparsers)
     37
     38    return parser
     39
     40def parser_add_subcommand_help(subparsers):
     41    # global help subcommand
     42    subparsers.add_parser('help',
     43            help='show help message',
     44            formatter_class = argparse.ArgumentDefaultsHelpFormatter)
     45
     46def parser_add_subcommand_onset(subparsers):
    2547    # onset subcommand
    2648    subparser = subparsers.add_parser('onset',
    2749            help='estimate time of onsets (beginning of sound event)',
    2850            formatter_class = argparse.ArgumentDefaultsHelpFormatter)
    29     parser_add_input(subparser)
    30     parser_add_buf_hop_size(subparser)
     51    subparser.add_input()
     52    subparser.add_buf_hop_size()
    3153    helpstr = "onset novelty function"
    3254    helpstr += " <default|energy|hfc|complex|phase|specdiff|kl|mkl|specflux>"
    33     parser_add_method(subparser, helpstr=helpstr)
    34     parser_add_threshold(subparser)
    35     parser_add_silence(subparser)
    36     parser_add_minioi(subparser)
    37     parser_add_time_format(subparser)
    38     parser_add_verbose_help(subparser)
     55    subparser.add_method(helpstr=helpstr)
     56    subparser.add_threshold()
     57    subparser.add_silence()
     58    subparser.add_minioi()
     59    subparser.add_time_format()
     60    subparser.add_verbose_help()
    3961    subparser.set_defaults(process=process_onset)
    4062
     63def parser_add_subcommand_pitch(subparsers):
    4164    # pitch subcommand
    4265    subparser = subparsers.add_parser('pitch',
    4366            help='estimate fundamental frequency (monophonic)')
    44     parser_add_input(subparser)
    45     parser_add_buf_hop_size(subparser, buf_size=2048)
     67    subparser.add_input()
     68    subparser.add_buf_hop_size(buf_size=2048)
    4669    helpstr = "pitch detection method <default|yinfft|yin|mcomb|fcomb|schmitt>"
    47     parser_add_method(subparser, helpstr=helpstr)
    48     parser_add_threshold(subparser)
    49     parser_add_pitch_unit(subparser)
    50     parser_add_silence(subparser)
    51     parser_add_time_format(subparser)
    52     parser_add_verbose_help(subparser)
     70    subparser.add_method(helpstr=helpstr)
     71    subparser.add_threshold()
     72    subparser.add_pitch_unit()
     73    subparser.add_silence()
     74    subparser.add_time_format()
     75    subparser.add_verbose_help()
    5376    subparser.set_defaults(process=process_pitch)
    5477
     78def parser_add_subcommand_beat(subparsers):
    5579    # beat subcommand
    5680    subparser = subparsers.add_parser('beat',
    5781            help='estimate location of beats')
    58     parser_add_input(subparser)
    59     parser_add_buf_hop_size(subparser, buf_size=1024, hop_size=512)
    60     parser_add_time_format(subparser)
    61     parser_add_verbose_help(subparser)
     82    subparser.add_input()
     83    subparser.add_buf_hop_size(buf_size=1024, hop_size=512)
     84    subparser.add_time_format()
     85    subparser.add_verbose_help()
    6286    subparser.set_defaults(process=process_beat)
    6387
     88def parser_add_subcommand_tempo(subparsers):
    6489    # tempo subcommand
    6590    subparser = subparsers.add_parser('tempo',
    6691            help='estimate overall tempo in bpm')
    67     parser_add_input(subparser)
    68     parser_add_buf_hop_size(subparser, buf_size=1024, hop_size=512)
    69     parser_add_time_format(subparser)
    70     parser_add_verbose_help(subparser)
     92    subparser.add_input()
     93    subparser.add_buf_hop_size(buf_size=1024, hop_size=512)
     94    subparser.add_time_format()
     95    subparser.add_verbose_help()
    7196    subparser.set_defaults(process=process_tempo)
    7297
     98def parser_add_subcommand_notes(subparsers):
    7399    # notes subcommand
    74100    subparser = subparsers.add_parser('notes',
    75101            help='estimate midi-like notes (monophonic)')
    76     parser_add_input(subparser)
    77     parser_add_buf_hop_size(subparser)
    78     parser_add_time_format(subparser)
    79     parser_add_verbose_help(subparser)
     102    subparser.add_input()
     103    subparser.add_buf_hop_size()
     104    subparser.add_time_format()
     105    subparser.add_verbose_help()
    80106    subparser.set_defaults(process=process_notes)
    81107
     108def parser_add_subcommand_mfcc(subparsers):
    82109    # mfcc subcommand
    83110    subparser = subparsers.add_parser('mfcc',
    84111            help='extract Mel-Frequency Cepstrum Coefficients')
    85     parser_add_input(subparser)
    86     parser_add_buf_hop_size(subparser)
    87     parser_add_time_format(subparser)
    88     parser_add_verbose_help(subparser)
     112    subparser.add_input()
     113    subparser.add_buf_hop_size()
     114    subparser.add_time_format()
     115    subparser.add_verbose_help()
    89116    subparser.set_defaults(process=process_mfcc)
    90117
     118def parser_add_subcommand_melbands(subparsers):
    91119    # melbands subcommand
    92120    subparser = subparsers.add_parser('melbands',
    93121            help='extract energies in Mel-frequency bands')
    94     parser_add_input(subparser)
    95     parser_add_buf_hop_size(subparser)
    96     parser_add_time_format(subparser)
    97     parser_add_verbose_help(subparser)
     122    subparser.add_input()
     123    subparser.add_buf_hop_size()
     124    subparser.add_time_format()
     125    subparser.add_verbose_help()
    98126    subparser.set_defaults(process=process_melbands)
    99127
    100     return parser
    101 
    102 def parser_add_input(parser):
    103     parser.add_argument("source_uri", default=None, nargs='?',
    104             help="input sound file to analyse", metavar = "<source_uri>")
    105     parser.add_argument("-i", "--input", dest = "source_uri2",
    106             help="input sound file to analyse", metavar = "<source_uri>")
    107     parser.add_argument("-r", "--samplerate",
    108             metavar = "<freq>", type=int,
    109             action="store", dest="samplerate", default=0,
    110             help="samplerate at which the file should be represented")
    111 
    112 def parser_add_verbose_help(parser):
    113     parser.add_argument("-v","--verbose",
    114             action="count", dest="verbose", default=1,
    115             help="make lots of noise [default]")
    116     parser.add_argument("-q","--quiet",
    117             action="store_const", dest="verbose", const=0,
    118             help="be quiet")
    119 
    120 def parser_add_buf_hop_size(parser, buf_size=512, hop_size=256):
    121     parser.add_argument("-B","--bufsize",
    122             action="store", dest="buf_size", default=buf_size,
    123             metavar = "<size>", type=int,
    124             help="buffer size [default=%d]" % buf_size)
    125     parser.add_argument("-H","--hopsize",
    126             metavar = "<size>", type=int,
    127             action="store", dest="hop_size", default=hop_size,
    128             help="overlap size [default=%d]" % hop_size)
    129 
    130 def parser_add_method(parser, method='default', helpstr='method'):
    131     parser.add_argument("-m","--method",
    132             metavar = "<method>", type=str,
    133             action="store", dest="method", default=method,
    134             help="%s [default=%s]" % (helpstr, method))
    135 
    136 def parser_add_threshold(parser, default=None):
    137     parser.add_argument("-t","--threshold",
    138             metavar = "<threshold>", type=float,
    139             action="store", dest="threshold", default=default,
    140             help="threshold [default=%s]" % default)
    141 
    142 def parser_add_silence(parser):
    143     parser.add_argument("-s", "--silence",
    144             metavar = "<value>", type=float,
    145             action="store", dest="silence", default=-70,
    146             help="silence threshold")
    147 
    148 def parser_add_minioi(parser):
    149     parser.add_argument("-M", "--minioi",
    150             metavar = "<value>", type=str,
    151             action="store", dest="minioi", default="12ms",
    152             help="minimum Inter-Onset Interval")
    153 
    154 def parser_add_pitch_unit(parser, default="Hz"):
    155     help_str = "frequency unit, should be one of Hz, midi, bin, cent"
    156     help_str += " [default=%s]" % default
    157     parser.add_argument("-u", "--pitch-unit",
    158             metavar = "<value>", type=str,
    159             action="store", dest="pitch_unit", default=default,
    160             help=help_str)
    161 
    162 def parser_add_time_format(parser):
    163     helpstr = "select time values output format (samples, ms, seconds)"
    164     helpstr += " [default=seconds]"
    165     parser.add_argument("-T", "--time-format",
    166              metavar='format',
    167              dest="time_format",
    168              default=None,
    169              help=helpstr)
     128def parser_add_subcommand_quiet(subparsers):
     129    # quiet subcommand
     130    subparser = subparsers.add_parser('quiet',
     131            help='extract timestamps of quiet and loud regions')
     132    subparser.add_input()
     133    subparser.add_hop_size()
     134    subparser.add_silence()
     135    subparser.add_time_format()
     136    subparser.add_verbose_help()
     137    subparser.set_defaults(process=process_quiet)
     138
     139def parser_add_subcommand_cut(subparsers):
     140    # quiet subcommand
     141    subparser = subparsers.add_parser('cut',
     142            help='slice at timestamps')
     143    subparser.add_input()
     144    helpstr = "onset novelty function"
     145    helpstr += " <default|energy|hfc|complex|phase|specdiff|kl|mkl|specflux>"
     146    subparser.add_method(helpstr=helpstr)
     147    subparser.add_buf_hop_size()
     148    subparser.add_silence()
     149    subparser.add_threshold(default=0.3)
     150    subparser.add_minioi()
     151    subparser.add_slicer_options()
     152    subparser.add_time_format()
     153    subparser.add_verbose_help()
     154    subparser.set_defaults(process=process_cut)
     155
     156class AubioArgumentParser(argparse.ArgumentParser):
     157
     158    def add_input(self):
     159        self.add_argument("source_uri", default=None, nargs='?',
     160                help="input sound file to analyse", metavar = "<source_uri>")
     161        self.add_argument("-i", "--input", dest = "source_uri2",
     162                help="input sound file to analyse", metavar = "<source_uri>")
     163        self.add_argument("-r", "--samplerate",
     164                metavar = "<freq>", type=int,
     165                action="store", dest="samplerate", default=0,
     166                help="samplerate at which the file should be represented")
     167
     168    def add_verbose_help(self):
     169        self.add_argument("-v","--verbose",
     170                action="count", dest="verbose", default=1,
     171                help="make lots of noise [default]")
     172        self.add_argument("-q","--quiet",
     173                action="store_const", dest="verbose", const=0,
     174                help="be quiet")
     175
     176    def add_buf_hop_size(self, buf_size=512, hop_size=256):
     177        self.add_buf_size(buf_size=buf_size)
     178        self.add_hop_size(hop_size=hop_size)
     179
     180    def add_buf_size(self, buf_size=512):
     181        self.add_argument("-B","--bufsize",
     182                action="store", dest="buf_size", default=buf_size,
     183                metavar = "<size>", type=int,
     184                help="buffer size [default=%d]" % buf_size)
     185
     186    def add_hop_size(self, hop_size=256):
     187        self.add_argument("-H","--hopsize",
     188                metavar = "<size>", type=int,
     189                action="store", dest="hop_size", default=hop_size,
     190                help="overlap size [default=%d]" % hop_size)
     191
     192    def add_method(self, method='default', helpstr='method'):
     193        self.add_argument("-m","--method",
     194                metavar = "<method>", type=str,
     195                action="store", dest="method", default=method,
     196                help="%s [default=%s]" % (helpstr, method))
     197
     198    def add_threshold(self, default=None):
     199        self.add_argument("-t","--threshold",
     200                metavar = "<threshold>", type=float,
     201                action="store", dest="threshold", default=default,
     202                help="threshold [default=%s]" % default)
     203
     204    def add_silence(self):
     205        self.add_argument("-s", "--silence",
     206                metavar = "<value>", type=float,
     207                action="store", dest="silence", default=-70,
     208                help="silence threshold")
     209
     210    def add_minioi(self, default="12ms"):
     211        self.add_argument("-M", "--minioi",
     212                metavar = "<value>", type=str,
     213                action="store", dest="minioi", default=default,
     214                help="minimum Inter-Onset Interval [default=%s]" % default)
     215
     216    def add_pitch_unit(self, default="Hz"):
     217        help_str = "frequency unit, should be one of Hz, midi, bin, cent"
     218        help_str += " [default=%s]" % default
     219        self.add_argument("-u", "--pitch-unit",
     220                metavar = "<value>", type=str,
     221                action="store", dest="pitch_unit", default=default,
     222                help=help_str)
     223
     224    def add_time_format(self):
     225        helpstr = "select time values output format (samples, ms, seconds)"
     226        helpstr += " [default=seconds]"
     227        self.add_argument("-T", "--time-format",
     228                 metavar='format',
     229                 dest="time_format",
     230                 default=None,
     231                 help=helpstr)
     232
     233    def add_slicer_options(self):
     234        self.add_argument("-o","--output", type = str,
     235                metavar = "<outputdir>",
     236                action="store", dest="output_directory", default=None,
     237                help="specify path where slices of the original file should be created")
     238        self.add_argument("--cut-until-nsamples", type = int,
     239                metavar = "<samples>",
     240                action = "store", dest = "cut_until_nsamples", default = None,
     241                help="how many extra samples should be added at the end of each slice")
     242        self.add_argument("--cut-every-nslices", type = int,
     243                metavar = "<samples>",
     244                action = "store", dest = "cut_every_nslices", default = None,
     245                help="how many slices should be groupped together at each cut")
     246        self.add_argument("--cut-until-nslices", type = int,
     247                metavar = "<slices>",
     248                action = "store", dest = "cut_until_nslices", default = None,
     249                help="how many extra slices should be added at the end of each slice")
    170250
    171251# some utilities
     
    177257    return "%f\t" % (1000. * n_frames / float(samplerate))
    178258
    179 def samples2samples(n_frames, samplerate):
     259def samples2samples(n_frames, _samplerate):
    180260    return "%d\t" % n_frames
    181261
     
    200280            optstr = ' '.join(['running', name, 'with options', repr(self.options), '\n'])
    201281            sys.stderr.write(optstr)
    202     def flush(self, n_frames, samplerate):
     282    def flush(self, frames_read, samplerate):
    203283        # optionally called at the end of process
    204284        pass
     
    239319    def __call__(self, block):
    240320        return self.onset(block)
    241     def repr_res(self, res, frames_read, samplerate):
     321    def repr_res(self, res, _frames_read, samplerate):
    242322        if res[0] != 0:
    243323            outstr = self.time2string(self.onset.get_last(), samplerate)
     
    270350    def __call__(self, block):
    271351        return self.tempo(block)
    272     def repr_res(self, res, frames_read, samplerate):
     352    def repr_res(self, res, _frames_read, samplerate):
    273353        if res[0] != 0:
    274354            outstr = self.time2string(self.tempo.get_last(), samplerate)
     
    279359        super(process_tempo, self).__init__(args)
    280360        self.beat_locations = []
    281     def repr_res(self, res, frames_read, samplerate):
     361    def repr_res(self, res, _frames_read, samplerate):
    282362        if res[0] != 0:
    283363            self.beat_locations.append(self.tempo.get_last_s())
     
    363443        sys.stdout.write(fmt_out + '\n')
    364444
     445class process_quiet(default_process):
     446    def __init__(self, args):
     447        self.args = args
     448        valid_opts = ['hop_size', 'silence']
     449        self.parse_options(args, valid_opts)
     450        self.wassilence = 1
     451
     452        if args.silence is not None:
     453            self.silence = args.silence
     454        super(process_quiet, self).__init__(args)
     455
     456    def __call__(self, block):
     457        if aubio.silence_detection(block, self.silence) == 1:
     458            if self.wassilence != 1:
     459                self.wassilence = 1
     460                return 2 # newly found silence
     461            return 1 # silence again
     462        else:
     463            if self.wassilence != 0:
     464                self.wassilence = 0
     465                return -1 # newly found noise
     466            return 0 # noise again
     467
     468    def repr_res(self, res, frames_read, samplerate):
     469        fmt_out = None
     470        if res == -1:
     471            fmt_out = "NOISY: "
     472        if res == 2:
     473            fmt_out = "QUIET: "
     474        if fmt_out is not None:
     475            fmt_out += self.time2string(frames_read, samplerate)
     476            sys.stdout.write(fmt_out + '\n')
     477
     478class process_cut(process_onset):
     479    def __init__(self, args):
     480        super(process_cut, self).__init__(args)
     481        self.slices = []
     482        self.options = args
     483
     484    def __call__(self, block):
     485        ret = super(process_cut, self).__call__(block)
     486        if ret: self.slices.append(self.onset.get_last())
     487        return ret
     488
     489    def flush(self, frames_read, samplerate):
     490        from aubio.cut import _cut_slice
     491        _cut_slice(self.options, self.slices)
     492        duration = float (frames_read) / float(samplerate)
     493        base_info = '%(source_file)s' % {'source_file': self.options.source_uri}
     494        base_info += ' (total %(duration).2fs at %(samplerate)dHz)\n' % \
     495                {'duration': duration, 'samplerate': samplerate}
     496        info = "created %d slices from " % len(self.slices)
     497        info += base_info
     498        sys.stderr.write(info)
     499
    365500def main():
    366501    parser = aubio_parser()
     
    371506    elif 'verbose' in args and args.verbose > 3:
    372507        sys.stderr.write('aubio version ' + aubio.version + '\n')
    373     if 'command' not in args or args.command is None:
     508    if 'command' not in args or args.command is None or args.command in ['help']:
    374509        # no command given, print help and return 1
    375510        parser.print_help()
    376         sys.exit(1)
     511        if args.command and args.command in ['help']:
     512            sys.exit(0)
     513        else:
     514            sys.exit(1)
    377515    elif not args.source_uri and not args.source_uri2:
    378516        sys.stderr.write("Error: a source is required\n")
Note: See TracChangeset for help on using the changeset viewer.