From 777d75ee9daedc65e37f4b15e924feb2f6b6dcb6 Mon Sep 17 00:00:00 2001 From: flavio Date: Tue, 31 Jul 2012 13:10:22 +0000 Subject: Modularization of the mouth --- diff --git a/activity.py b/activity.py index b9d78b5..7761ad1 100644 --- a/activity.py +++ b/activity.py @@ -44,9 +44,9 @@ from gettext import gettext as _ import eye import glasses -import mouth -import fft_mouth -import waveform_mouth +from mouth import Mouth +from mouth import FFTMouth +from mouth import WaveformMouth import voice import face import brain @@ -394,10 +394,10 @@ class SpeakActivity(activity.Activity): facebar = Gtk.Toolbar() self.mouth_shape_combo = ComboBox() - self.mouth_shape_combo.append_item(mouth.Mouth, _("Simple")) - self.mouth_shape_combo.append_item(waveform_mouth.WaveformMouth, + self.mouth_shape_combo.append_item(Mouth, _("Simple")) + self.mouth_shape_combo.append_item(WaveformMouth, _("Waveform")) - self.mouth_shape_combo.append_item(fft_mouth.FFTMouth, _("Frequency")) + self.mouth_shape_combo.append_item(FFTMouth, _("Frequency")) self.mouth_shape_combo.set_active(0) mouth_shape_toolitem = ToolWidget( diff --git a/face.py b/face.py index 9768157..7dd0498 100644 --- a/face.py +++ b/face.py @@ -32,10 +32,10 @@ import sugar3.graphics.style as style import espeak import eye import glasses -import mouth +from mouth import Mouth +from mouth import FFTMouth +from mouth import WaveformMouth import voice -import fft_mouth -import waveform_mouth logger = logging.getLogger('speak') @@ -49,14 +49,14 @@ class Status(): self.rate = espeak.RATE_MAX / 2 self.eyes = [eye.Eye] * 2 - self.mouth = mouth.Mouth + self.mouth = Mouth def serialize(self): eyes = {eye.Eye: 1, glasses.Glasses: 2} - mouths = {mouth.Mouth: 1, - fft_mouth.FFTMouth: 2, - waveform_mouth.WaveformMouth: 3} + mouths = {Mouth: 1, + FFTMouth: 2, + WaveformMouth: 3} return cjson.encode({ 'voice': {'language': self.voice.language, @@ -69,9 +69,9 @@ class Status(): def deserialize(self, buf): eyes = {1: eye.Eye, 2: glasses.Glasses} - mouths = {1: mouth.Mouth, - 2: fft_mouth.FFTMouth, - 3: waveform_mouth.WaveformMouth} + mouths = {1: Mouth, + 2: FFTMouth, + 3: WaveformMouth} data = cjson.decode(buf) self.voice = voice.Voice(data['voice']['language'], diff --git a/fft_mouth.py b/fft_mouth.py deleted file mode 100644 index 1fae0cf..0000000 --- a/fft_mouth.py +++ /dev/null @@ -1,121 +0,0 @@ -# Speak.activity -# A simple front end to the espeak text-to-speech engine on the XO laptop -# http://wiki.laptop.org/go/Speak -# -# Copyright (C) 2008 Joshua Minor -# This file is part of Speak.activity -# -# Parts of Speak.activity are based on code from Measure.activity -# Copyright (C) 2007 Arjun Sarwal - arjun@laptop.org -# -# Speak.activity is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Speak.activity is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Speak.activity. If not, see . - -# This code is a stripped down version of the fft view from Measure - -from mouth import * - -# Newer OLPC builds (and Fedora) have numpy instead of numeric: -try: - from numpy.oldnumeric import ceil - from numpy.fft import * -except: - from Numeric import ceil - from FFT import * - - -class FFTMouth(Mouth): - def __init__(self, audioSource, fill_color): - - Mouth.__init__(self, audioSource, fill_color) - - self.peaks = [] - - self.y_mag = 1.7 - self.freq_range = 70 - self.draw_interval = 1 - self.num_of_points = 105 - - self.stop = False - - #constant to multiply with self.param2 while scaling values - self.y_mag_bias_multiplier = 1 - - self.fftx = [] - - self.scaleX = "10" - self.scaleY = "10" - - def processBuffer(self, rect): - self.param1 = rect.height / 65536.0 - self.param2 = rect.height / 2.0 - - if(self.stop == False): - - Fs = 48000 - nfft = 65536 - self.newest_buffer = self.newest_buffer[0:256] - self.fftx = fft(self.newest_buffer, 256, -1) - - self.fftx = self.fftx[0:self.freq_range * 2] - self.draw_interval = rect.width / (self.freq_range * 2.) - - NumUniquePts = ceil((nfft + 1) / 2) - self.buffers = abs(self.fftx) * 0.02 - self.y_mag_bias_multiplier = 0.1 - self.scaleX = "hz" - self.scaleY = "" - - if(len(self.buffers) == 0): - return False - - # Scaling the values - val = [] - for i in self.buffers: - temp_val_float = float(self.param1 * i * self.y_mag) +\ - self.y_mag_bias_multiplier * self.param2 - - if(temp_val_float >= rect.height): - temp_val_float = rect.height - 25 - if(temp_val_float <= 0): - temp_val_float = 25 - val.append(temp_val_float) - - self.peaks = val - - def do_draw(self, context): - rect = self.get_allocation() - - self.processBuffer(rect) - - # background - context.set_source_rgba(*self.fill_color.get_rgba()) - context.paint() - - # Draw the waveform - context.set_line_width(min(rect.height / 10.0, 10)) - context.set_source_rgb(0, 0, 0) - count = 0 - for peak in self.peaks: - context.line_to(rect.width / 2 + count, - rect.height / 2 - peak) - count += self.draw_interval - context.stroke() - count = 0 - for peak in self.peaks: - context.line_to(rect.width / 2 - count, - rect.height / 2 - peak) - count += self.draw_interval - context.stroke() - - return True diff --git a/mouth.py b/mouth.py index 693d0ca..136ec7b 100644 --- a/mouth.py +++ b/mouth.py @@ -28,6 +28,13 @@ from gi.repository import Gdk from struct import unpack import numpy.core +try: + from numpy.oldnumeric import ceil + from numpy.fft import * +except: + from Numeric import ceil + from FFT import * + class Mouth(Gtk.DrawingArea): @@ -94,3 +101,133 @@ class Mouth(Gtk.DrawingArea): context.stroke() return True + +class WaveformMouth(Mouth): + def __init__(self, audioSource, fill_color): + + Mouth.__init__(self, audioSource, fill_color) + + self.buffer_size = 100 + self.peaks = [] + + self.stop = False + + self.y_mag_bias_multiplier = 1 + self.y_mag = 0.7 + + def do_draw(self, context): + rect = self.get_allocation() + self.param1 = rect.height / 65536.0 + self.param2 = rect.height / 2.0 + + # background + context.set_source_rgba(*self.fill_color.get_rgba()) + context.paint() + + # Draw the waveform + context.set_line_width(min(rect.height / 10.0, 10)) + count = 0 + buflen = float(len(self.main_buffers)) + for value in self.main_buffers: + peak = float(self.param1 * value * self.y_mag) +\ + self.y_mag_bias_multiplier * self.param2 + + if peak >= rect.height: + peak = rect.height + if peak <= 0: + peak = 0 + + x = count / buflen * rect.width + context.line_to(x, rect.height - peak) + + count += 1 + context.set_source_rgb(0, 0, 0) + context.stroke() + + return True + +class FFTMouth(Mouth): + def __init__(self, audioSource, fill_color): + + Mouth.__init__(self, audioSource, fill_color) + + self.peaks = [] + + self.y_mag = 1.7 + self.freq_range = 70 + self.draw_interval = 1 + self.num_of_points = 105 + + self.stop = False + + #constant to multiply with self.param2 while scaling values + self.y_mag_bias_multiplier = 1 + + self.fftx = [] + + self.scaleX = "10" + self.scaleY = "10" + + def processBuffer(self, rect): + self.param1 = rect.height / 65536.0 + self.param2 = rect.height / 2.0 + + if(self.stop == False): + + Fs = 48000 + nfft = 65536 + self.newest_buffer = self.newest_buffer[0:256] + self.fftx = fft(self.newest_buffer, 256, -1) + + self.fftx = self.fftx[0:self.freq_range * 2] + self.draw_interval = rect.width / (self.freq_range * 2.) + + NumUniquePts = ceil((nfft + 1) / 2) + self.buffers = abs(self.fftx) * 0.02 + self.y_mag_bias_multiplier = 0.1 + self.scaleX = "hz" + self.scaleY = "" + + if(len(self.buffers) == 0): + return False + + # Scaling the values + val = [] + for i in self.buffers: + temp_val_float = float(self.param1 * i * self.y_mag) +\ + self.y_mag_bias_multiplier * self.param2 + + if(temp_val_float >= rect.height): + temp_val_float = rect.height - 25 + if(temp_val_float <= 0): + temp_val_float = 25 + val.append(temp_val_float) + + self.peaks = val + + def do_draw(self, context): + rect = self.get_allocation() + + self.processBuffer(rect) + + # background + context.set_source_rgba(*self.fill_color.get_rgba()) + context.paint() + + # Draw the waveform + context.set_line_width(min(rect.height / 10.0, 10)) + context.set_source_rgb(0, 0, 0) + count = 0 + for peak in self.peaks: + context.line_to(rect.width / 2 + count, + rect.height / 2 - peak) + count += self.draw_interval + context.stroke() + count = 0 + for peak in self.peaks: + context.line_to(rect.width / 2 - count, + rect.height / 2 - peak) + count += self.draw_interval + context.stroke() + + return True \ No newline at end of file diff --git a/waveform_mouth.py b/waveform_mouth.py deleted file mode 100644 index 04d2c45..0000000 --- a/waveform_mouth.py +++ /dev/null @@ -1,71 +0,0 @@ -# Speak.activity -# A simple front end to the espeak text-to-speech engine on the XO laptop -# http://wiki.laptop.org/go/Speak -# -# Copyright (C) 2008 Joshua Minor -# This file is part of Speak.activity -# -# Parts of Speak.activity are based on code from Measure.activity -# Copyright (C) 2007 Arjun Sarwal - arjun@laptop.org -# -# Speak.activity is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Speak.activity is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Speak.activity. If not, see . - -# This code is a stripped down version of the waveform view from Measure - -from mouth import * - - -class WaveformMouth(Mouth): - def __init__(self, audioSource, fill_color): - - Mouth.__init__(self, audioSource, fill_color) - - self.buffer_size = 100 - self.peaks = [] - - self.stop = False - - self.y_mag_bias_multiplier = 1 - self.y_mag = 0.7 - - def do_draw(self, context): - rect = self.get_allocation() - self.param1 = rect.height / 65536.0 - self.param2 = rect.height / 2.0 - - # background - context.set_source_rgba(*self.fill_color.get_rgba()) - context.paint() - - # Draw the waveform - context.set_line_width(min(rect.height / 10.0, 10)) - count = 0 - buflen = float(len(self.main_buffers)) - for value in self.main_buffers: - peak = float(self.param1 * value * self.y_mag) +\ - self.y_mag_bias_multiplier * self.param2 - - if peak >= rect.height: - peak = rect.height - if peak <= 0: - peak = 0 - - x = count / buflen * rect.width - context.line_to(x, rect.height - peak) - - count += 1 - context.set_source_rgb(0, 0, 0) - context.stroke() - - return True -- cgit v0.9.1