source: interfaces/python/aubioinput.py @ ab59067

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

aubioinput.py: flush last frame, no resizing in mono

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