Sophie

Sophie

distrib > Mandriva > current > i586 > by-pkgid > ae0a4f27f26602dc31c3bf35e18b5b19 > files > 433

python-enthought-chaco-3.4.0-2mdv2010.2.i586.rpm

#!/usr/bin/env python
"""
This plot displays the audio spectrum from the microphone.

Based on updating_plot.py
"""
# Major library imports
import pyaudio
from numpy import zeros, linspace, short, fromstring, hstack, transpose
from scipy import fft

# Enthought library imports
from enthought.chaco.default_colormaps import jet
from enthought.enable.api import Window, Component, ComponentEditor
from enthought.traits.api import HasTraits, Instance
from enthought.traits.ui.api import Item, Group, View, Handler
from enthought.enable.example_support import DemoFrame, demo_main
from enthought.pyface.timer.api import Timer

# Chaco imports
from enthought.chaco.api import Plot, ArrayPlotData, HPlotContainer

NUM_SAMPLES = 1024
SAMPLING_RATE = 11025
SPECTROGRAM_LENGTH = 100

#============================================================================
# Create the Chaco plot.
#============================================================================

def _create_plot_component(obj):
    # Setup the spectrum plot
    frequencies = linspace(0.0, float(SAMPLING_RATE)/2, num=NUM_SAMPLES/2)
    obj.spectrum_data = ArrayPlotData(frequency=frequencies)
    empty_amplitude = zeros(NUM_SAMPLES/2)
    obj.spectrum_data.set_data('amplitude', empty_amplitude)

    obj.spectrum_plot = Plot(obj.spectrum_data)
    obj.spectrum_plot.plot(("frequency", "amplitude"), name="Spectrum",
                           color="red")
    obj.spectrum_plot.padding = 50
    obj.spectrum_plot.title = "Spectrum"
    spec_range = obj.spectrum_plot.plots.values()[0][0].value_mapper.range
    spec_range.low = 0.0
    spec_range.high = 5.0
    obj.spectrum_plot.index_axis.title = 'Frequency (hz)'
    obj.spectrum_plot.value_axis.title = 'Amplitude'

    # Time Series plot
    times = linspace(0.0, float(NUM_SAMPLES)/SAMPLING_RATE, num=NUM_SAMPLES)
    obj.time_data = ArrayPlotData(time=times)
    empty_amplitude = zeros(NUM_SAMPLES)
    obj.time_data.set_data('amplitude', empty_amplitude)

    obj.time_plot = Plot(obj.time_data)
    obj.time_plot.plot(("time", "amplitude"), name="Time", color="blue")
    obj.time_plot.padding = 50
    obj.time_plot.title = "Time"
    obj.time_plot.index_axis.title = 'Time (seconds)'
    obj.time_plot.value_axis.title = 'Amplitude'
    time_range = obj.time_plot.plots.values()[0][0].value_mapper.range
    time_range.low = -0.2
    time_range.high = 0.2

    # Spectrogram plot
    spectrogram_data = zeros(( NUM_SAMPLES/2, SPECTROGRAM_LENGTH))
    obj.spectrogram_plotdata = ArrayPlotData()
    obj.spectrogram_plotdata.set_data('imagedata', spectrogram_data)
    spectrogram_plot = Plot(obj.spectrogram_plotdata)
    max_time = float(SPECTROGRAM_LENGTH * NUM_SAMPLES) / SAMPLING_RATE
    max_freq = float(SAMPLING_RATE / 2)
    spectrogram_plot.img_plot('imagedata',
                              name='Spectrogram',
                              xbounds=(0, max_time),
                              ybounds=(0, max_freq),
                              colormap=jet,
                              )
    range_obj = spectrogram_plot.plots['Spectrogram'][0].value_mapper.range
    range_obj.high = 5
    range_obj.low = 0.0
    spectrogram_plot.title = 'Spectrogram'
    obj.spectrogram_plot = spectrogram_plot

    container = HPlotContainer()
    container.add(obj.spectrum_plot)
    container.add(obj.time_plot)
    container.add(spectrogram_plot)

    return container

_stream = None
def get_audio_data():
    global _stream
    if _stream is None:
        pa = pyaudio.PyAudio()
        _stream = pa.open(format=pyaudio.paInt16, channels=1, rate=SAMPLING_RATE,
                     input=True, frames_per_buffer=NUM_SAMPLES)
    audio_data  = fromstring(_stream.read(NUM_SAMPLES), dtype=short)
    normalized_data = audio_data / 32768.0
    return (abs(fft(normalized_data))[:NUM_SAMPLES/2], normalized_data)


# HasTraits class that supplies the callable for the timer event.
class TimerController(HasTraits):

    def onTimer(self, *args):
        spectrum, time = get_audio_data()
        self.spectrum_data.set_data('amplitude', spectrum)
        self.time_data.set_data('amplitude', time)
        spectrogram_data = self.spectrogram_plotdata.get_data('imagedata')
        spectrogram_data = hstack((spectrogram_data[:,1:],
                                   transpose([spectrum])))

        self.spectrogram_plotdata.set_data('imagedata', spectrogram_data)
        self.spectrum_plot.request_redraw()
        return

#============================================================================
# Attributes to use for the plot view.
size = (900,500)
title = "Audio Spectrum"

#============================================================================
# Demo class that is used by the demo.py application.
#============================================================================

class DemoHandler(Handler):

    def closed(self, info, is_ok):
        """ Handles a dialog-based user interface being closed by the user.
        Overridden here to stop the timer once the window is destroyed.
        """

        info.object.timer.Stop()
        return

class Demo(HasTraits):

    plot = Instance(Component)

    controller = Instance(TimerController, ())

    timer = Instance(Timer)

    traits_view = View(
                    Group(
                        Item('plot', editor=ComponentEditor(size=size),
                             show_label=False),
                        orientation = "vertical"),
                    resizable=True, title=title,
                    width=size[0], height=size[1],
                    handler=DemoHandler
                    )

    def __init__(self, **traits):
        super(Demo, self).__init__(**traits)
        self.plot = _create_plot_component(self.controller)

    def edit_traits(self, *args, **kws):
        # Start up the timer! We should do this only when the demo actually
        # starts and not when the demo object is created.
        self.timer = Timer(20, self.controller.onTimer)
        return super(Demo, self).edit_traits(*args, **kws)

    def configure_traits(self, *args, **kws):
        # Start up the timer! We should do this only when the demo actually
        # starts and not when the demo object is created.
        self.timer = Timer(20, self.controller.onTimer)
        return super(Demo, self).configure_traits(*args, **kws)

popup = Demo()

#============================================================================
# Stand-alone frame to display the plot.
#============================================================================

from enthought.etsconfig.api import ETSConfig

if ETSConfig.toolkit == "wx":

    import wx
    class PlotFrame(DemoFrame):

        def _create_window(self):

            self.controller = TimerController()
            container = _create_plot_component(self.controller)
            # Bind the exit event to the onClose function which will force the
            # example to close. The PyAudio package causes problems that normally
            # prevent the user from closing the example using the 'X' button.
            # NOTE: I believe it is sufficient to just stop the timer-Vibha.
            self.Bind(wx.EVT_CLOSE, self.onClose)

            # Set the timer to generate events to us
            timerId = wx.NewId()
            self.timer = wx.Timer(self, timerId)
            self.Bind(wx.EVT_TIMER, self.controller.onTimer, id=timerId)
            self.timer.Start(20.0, wx.TIMER_CONTINUOUS)

            # Return a window containing our plots
            return Window(self, -1, component=container)

        def onClose(self, event):
            #sys.exit()
            self.timer.Stop()
            event.Skip()

elif ETSConfig.toolkit == "qt4":

    from enthought.qt import QtGui, QtCore

    class PlotFrame(DemoFrame):
        def _create_window(self):
            self.controller = TimerController()
            container = _create_plot_component(self.controller)

            # start a continuous timer
            self.timer = QtCore.QTimer()
            self.timer.timeout.connect(self.controller.onTimer)
            self.timer.start(20)

            return Window(self, -1, component=container)

        def closeEvent(self, event):
            # stop the timer
            if getattr(self, "timer", None):
                self.timer.stop()
            return super(PlotFrame, self).closeEvent(event)

if __name__ == "__main__":
    try:
        demo_main(PlotFrame, size=size, title=title)
    finally:
        if _stream is not None:
            _stream.close()