source: interfaces/python/aubioinput.py @ c85da04

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since c85da04 was 1f8e522, checked in by Paul Brossier <piem@piem.org>, 15 years ago

aubioinput.py: use uridecodebin, add run method, return 1 on error

  • Property mode set to 100644
File size: 4.3 KB
Line 
1#! /usr/bin/python
2
3import pygst
4pygst.require('0.10')
5import gst
6import gobject
7gobject.threads_init ()
8
9def gst_buffer_to_numpy_array(buffer, chan):
10    import numpy
11    samples = numpy.frombuffer(buffer.data, dtype=numpy.float32) 
12    samples.resize([len(samples)/chan, chan])
13    return samples.T
14
15class AubioSink(gst.BaseSink):
16    _caps = gst.caps_from_string('audio/x-raw-float, \
17                    rate=[ 1, 2147483647 ], \
18                    channels=[ 1, 2147483647 ], \
19                    endianness={ 1234, 4321 }, \
20                    width=32')
21
22    __gsttemplates__ = ( 
23            gst.PadTemplate ("sink",
24                gst.PAD_SINK,
25                gst.PAD_ALWAYS,
26                _caps),
27            )
28
29    def __init__(self, name, process):
30        self.__gobject_init__()
31        self.set_name(name)
32        self.process = process
33        self.adapter = gst.Adapter()
34        self.set_property('sync', False)
35        self.pos = 0
36
37    def set_property(self, name, value): 
38        if name == 'hopsize':
39            # blocksize is in byte, convert from hopsize
40            from struct import calcsize
41            self.set_property('blocksize', value * calcsize('f'))
42        else:
43            super(gst.BaseSink, self).set_property(name, value)
44
45    def do_render(self, buffer):
46        blocksize = self.get_property('blocksize')
47        caps = buffer.get_caps()
48        chan = caps[0]['channels']
49        self.adapter.push(buffer)
50        while self.adapter.available() >= blocksize:
51            block = self.adapter.take_buffer(blocksize)
52            v = gst_buffer_to_numpy_array(block, chan)
53            if self.process:
54                self.process(v, self.pos)
55            self.pos += 1   
56        return gst.FLOW_OK
57
58gobject.type_register(AubioSink)
59
60class aubioinput(gst.Bin):
61
62    ret = 0
63
64    def __init__(self, uri, process = None, hopsize = 512,
65            caps = None):
66        if uri.startswith('/'):
67            from urllib import quote
68            uri = 'file://'+quote(uri)
69        src = gst.element_factory_make('uridecodebin')
70        src.set_property('uri', uri)
71        src.connect('pad-added', self.source_pad_added_cb)
72        conv = gst.element_factory_make('audioconvert')
73        self.conv = conv
74        rsmpl = gst.element_factory_make('audioresample')
75        capsfilter = gst.element_factory_make('capsfilter')
76        if caps:
77            capsfilter.set_property('caps', gst.caps_from_string(caps))
78        sink = AubioSink("AubioSink", process = process)
79        sink.set_property('hopsize', hopsize) # * calcsize('f'))
80
81        self.pipeline = gst.Pipeline()
82
83        self.bus = self.pipeline.get_bus()
84        self.bus.add_signal_watch()
85        self.bus.connect('message', self.on_eos)
86
87        self.apad = conv.get_pad('sink')
88
89        self.pipeline.add(src, conv, rsmpl, capsfilter, sink)
90
91        gst.element_link_many(conv, rsmpl, capsfilter, sink)
92
93        self.mainloop = gobject.MainLoop()
94        self.pipeline.set_state(gst.STATE_PLAYING)
95
96    def run(self):
97        self.mainloop.run()
98        return self.ret
99
100    def source_pad_added_cb(self, src, pad):
101        name = pad.get_caps()[0].get_name()
102        if name == 'audio/x-raw-float' or name == 'audio/x-raw-int':
103            pad.link(self.conv.get_pad("sink"))
104
105    def source_pad_removed_cb(self, src, pad):
106        pad.unlink(self.conv.get_pad("sink"))
107
108    def on_eos(self, bus, msg):
109        if msg.type == gst.MESSAGE_EOS:
110            self.bus.remove_signal_watch()
111            self.pipeline.set_state(gst.STATE_PAUSED)
112            self.mainloop.quit()
113        elif msg.type == gst.MESSAGE_ERROR:
114            print "ERROR", msg.parse_error()
115            self.bus.remove_signal_watch()
116            self.pipeline.set_state(gst.STATE_PAUSED)
117            self.mainloop.quit()
118            self.ret = 1 # set return value to 1 in case of error
119
120if __name__ == '__main__':
121    import sys
122    if len(sys.argv) < 2:
123        print "Usage: %s <filename>" % sys.argv[0]
124        sys.exit(1)
125    for filename in sys.argv[1:]:
126        peak = [0.] # use a mutable
127        def process(buf, hop):
128            peak[0] = max( peak[0], abs(buf.max()) )
129        a = aubioinput(filename, process = process, hopsize = 512)
130        if a.run() == 0: # only display the results if no
131            print "Finished reading %s, peak value is %f" % (filename, max(peak))
Note: See TracBrowser for help on using the repository browser.