I am trying to build graph of Real Time Data and at same time to print it on Label but label not updating till i hit start button.
Here is the .py code:
// import
def get_microphone_level(label_level, stream, store_bool, dt):
global levels
data = stream.read(chunk)
mx = audioop.rms(data, 2)
if store_bool:
if len(levels) >= 100:
levels = []
levels.append(mx)
label_level.text = str(mx)
# print mx
print label_level.text
class Logic(BoxLayout):
label_level = ObjectProperty(Spinner)
select_timer = ObjectProperty(Spinner)
timer = NumericProperty('0.0001')
stream = None
def __init__(self):
super(Logic, self).__init__()
self.plot = SmoothLinePlot(color=[1, 0, 0, 1])
self.stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=chunk)
Clock.schedule_interval(partial(get_microphone_level, self.label_level, self.stream, False), self.timer)
def start(self):
self.ids.graph.add_plot(self.plot)
Clock.schedule_interval(partial(get_microphone_level, self.label_level, self.stream, True), self.timer)
Clock.schedule_interval(self.update_graph, self.timer)
def stop(self):
Clock.unschedule(self.update_graph)
Clock.unschedule(get_microphone_level)
def update_graph(self, dt):
self.plot.points = [(i, j / 5) for i, j in enumerate(levels)]
def update_timer(self, text):
self.timer = float(text)
self.stop()
self.start()
class RealTimeMicrophone(App):
def build(self):
return Builder.load_file("look.kv")
if __name__ == "__main__":
chunk = 2048
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
p = pyaudio.PyAudio()
levels = []
RealTimeMicrophone().run()
Here is .kv:
#:import SmoothLinePlot kivy.garden.graph.SmoothLinePlot
Logic:
select_timer: select_timer
label_level: label_level
BoxLayout:
orientation: "vertical"
BoxLayout:
size_hint_y: .8
Graph:
id: graph
xlabel: "Time (in Second)"
ylabel: "Level"
ymin: 0
ymax: 5000
y_ticks_major: 1
x_ticks_minor: 5
x_ticks_major: 25
BoxLayout:
size_hint_y: .2
orientation: "horizontal"
spacing: 10
BoxLayout:
orientation: "vertical"
spacing: 10
Button:
text: "START"
bold: True
on_press: root.start()
Button:
text: "STOP"
bold: True
on_press: root.stop()
BoxLayout:
orientation: "vertical"
spacing: 10
BoxLayout:
orientation: "horizontal"
Label:
text: 'Current Level:'
Label:
id: label_level
text: '0'
Spinner:
id: select_timer
text: 'Select Timer (in Seconds)'
values: ['0.1', '0.5', '1', '2', '5']
on_text: root.update_timer(self.text)
I created three clock schedule one for Label data, levels collection after set timer, one for graph update.
Is there any problem with calling Clock.schedule_interval from init.
label_level is not set yet in __init__ so you would be better of send self to your function:
This way you don't fix on the wrong value, since each time the function called it will fetch label_level from the Logic instance