Index: python/lib/aubio/cmd.py
===================================================================
--- python/lib/aubio/cmd.py	(revision b7208f8424f035a2b3de69185d4a6de2b081c980)
+++ python/lib/aubio/cmd.py	(revision af98cb873a053e057961f756b65e25ae0ba27d3b)
@@ -162,17 +162,4 @@
 # some utilities
 
-def parse_options(args, valid_opts):
-    options = {k :v for k,v in vars(args).items() if k in valid_opts}
-    return options
-
-def remap_pvoc_options(options):
-    # remap buf_size to win_s, hop_size to hop_s
-    # FIXME: adjust python/ext/py-phasevoc.c to understand buf_size/hop_size
-    options['win_s'] = options['buf_size']
-    del options['buf_size']
-    options['hop_s'] = options['hop_size']
-    del options['hop_size']
-    return options
-
 def samples2seconds(n_frames, samplerate):
     return "%f\t" % (n_frames / float(samplerate))
@@ -205,10 +192,27 @@
             sys.stderr.write(optstr)
     def flush(self, n_frames, samplerate):
+        # optionally called at the end of process
         pass
+
+    def parse_options(self, args, valid_opts):
+        # get any valid options found in a dictionnary of arguments
+        options = {k :v for k,v in vars(args).items() if k in valid_opts}
+        self.options = options
+
+    def remap_pvoc_options(self, options):
+        # FIXME: we need to remap buf_size to win_s, hop_size to hop_s
+        # adjust python/ext/py-phasevoc.c to understand buf_size/hop_size
+        if 'buf_size' in options:
+            options['win_s'] = options['buf_size']
+            del options['buf_size']
+        if 'hop_size' in options:
+            options['hop_s'] = options['hop_size']
+            del options['hop_size']
+        self.options = options
 
 class process_onset(default_process):
     valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate']
     def __init__(self, args):
-        self.options = parse_options(args, self.valid_opts)
+        self.parse_options(args, self.valid_opts)
         self.onset = aubio.onset(**self.options)
         if args.threshold is not None:
@@ -234,5 +238,5 @@
     valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate']
     def __init__(self, args):
-        self.options = parse_options(args, self.valid_opts)
+        self.parse_options(args, self.valid_opts)
         self.pitch = aubio.pitch(**self.options)
         if args.threshold is not None:
@@ -250,5 +254,5 @@
     valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate']
     def __init__(self, args):
-        self.options = parse_options(args, self.valid_opts)
+        self.parse_options(args, self.valid_opts)
         self.tempo = aubio.tempo(**self.options)
         super(process_beat, self).__init__(args)
@@ -276,5 +280,5 @@
     valid_opts = ['method', 'hop_size', 'buf_size', 'samplerate']
     def __init__(self, args):
-        self.options = parse_options(args, self.valid_opts)
+        self.parse_options(args, self.valid_opts)
         self.notes = aubio.notes(**self.options)
         super(process_notes, self).__init__(args)
@@ -296,13 +300,15 @@
 class process_mfcc(default_process):
     def __init__(self, args):
-        valid_opts = ['hop_size', 'buf_size']
-        options = parse_options(args, valid_opts)
-        self.options = remap_pvoc_options(options)
-        self.pv = aubio.pvoc(**options)
-
-        valid_opts = ['buf_size', 'n_filters', 'n_coeffs', 'samplerate']
-        options = parse_options(args, valid_opts)
-        self.mfcc = aubio.mfcc(**options)
-        self.options.update(options)
+        valid_opts1 = ['hop_size', 'buf_size']
+        self.parse_options(args, valid_opts1)
+        self.remap_pvoc_options(self.options)
+        self.pv = aubio.pvoc(**self.options)
+
+        valid_opts2 = ['buf_size', 'n_filters', 'n_coeffs', 'samplerate']
+        self.parse_options(args, valid_opts2)
+        self.mfcc = aubio.mfcc(**self.options)
+
+        # remember all options
+        self.parse_options(args, list(set(valid_opts1 + valid_opts2)))
 
         super(process_mfcc, self).__init__(args)
@@ -320,14 +326,12 @@
         self.args = args
         valid_opts = ['hop_size', 'buf_size']
-        options = parse_options(args, valid_opts)
-        options = remap_pvoc_options(options)
-        self.pv = aubio.pvoc(**options)
+        self.parse_options(args, valid_opts)
+        self.remap_pvoc_options(self.options)
+        self.pv = aubio.pvoc(**self.options)
 
         valid_opts = ['buf_size', 'n_filters']
-        options = {k :v for k,v in vars(args).items() if k in valid_opts}
-        # FIXME
-        options['win_s'] = options['buf_size']
-        del options['buf_size']
-        self.filterbank = aubio.filterbank(**options)
+        self.parse_options(args, valid_opts)
+        self.remap_pvoc_options(self.options)
+        self.filterbank = aubio.filterbank(**self.options)
         self.filterbank.set_mel_coeffs_slaney(args.samplerate)
 
@@ -362,4 +366,6 @@
         with aubio.source(args.source_uri, hop_size=args.hop_size,
                 samplerate=args.samplerate) as a_source:
+            # always update args.samplerate to native samplerate, in case
+            # source was opened with args.samplerate=0
             args.samplerate = a_source.samplerate
             # create the processor for this subcommand
