#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# wav2png.py -- converts wave files to wave file and spectrogram images
# Copyright (C) 2008 MUSIC TECHNOLOGY GROUP (MTG)
# UNIVERSITAT POMPEU FABRA
#
import ImageFilter, ImageChops, Image, ImageDraw, ImageColor, ImageEnhance
from timeside.core import FixedSizeInputAdapter
-
-
-default_color_schemes = {
- 'default': {
- 'waveform': [(50,0,200), (0,220,80), (255,224,0), (255,0,0)],
- 'spectrogram': [(0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100),
- (224,224,44), (255,60,30), (255,255,255)]
- },
- 'iso': {
- 'waveform': [(0,0,255), (0,255,255), (255,255,0), (255,0,0)],
- 'spectrogram': [(0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100),
- (224,224,44), (255,60,30), (255,255,255)]
- },
- 'purple': {
- 'waveform': [(173,173,173), (147,149,196), (77,80,138), (108,66,0)],
- 'spectrogram': [(0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100),
- (224,224,44), (255,60,30), (255,255,255)]
- },
- 'awdio': {
- 'waveform': [(255,255,255), (255,255,255), (255,255,255), (255,255,255)],
- 'spectrogram': [(0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100),
- (224,224,44), (255,60,30), (255,255,255)]
- },
-}
-
+from color_schemes import default_color_schemes
+from utils import *
class Spectrum(object):
""" FFT based frequency analysis of audio frames."""
return (spectral_centroid, db_spectrum)
-def interpolate_colors(colors, flat=False, num_colors=256):
- """ Given a list of colors, create a larger list of colors interpolating
- the first one. If flatten is True a list of numers will be returned. If
- False, a list of (r,g,b) tuples. num_colors is the number of colors wanted
- in the final list """
-
- palette = []
-
- for i in range(num_colors):
- index = (i * (len(colors) - 1))/(num_colors - 1.0)
- index_int = int(index)
- alpha = index - float(index_int)
-
- if alpha > 0:
- r = (1.0 - alpha) * colors[index_int][0] + alpha * colors[index_int + 1][0]
- g = (1.0 - alpha) * colors[index_int][1] + alpha * colors[index_int + 1][1]
- b = (1.0 - alpha) * colors[index_int][2] + alpha * colors[index_int + 1][2]
- else:
- r = (1.0 - alpha) * colors[index_int][0]
- g = (1.0 - alpha) * colors[index_int][1]
- b = (1.0 - alpha) * colors[index_int][2]
-
- if flat:
- palette.extend((int(r), int(g), int(b)))
- else:
- palette.append((int(r), int(g), int(b)))
-
- return palette
-
class WaveformImage(object):
""" Builds a PIL image representing a waveform of the audio stream.
pass
-class Noise(object):
- """A class that mimics audiolab.sndfile but generates noise instead of reading
- a wave file. Additionally it can be told to have a "broken" header and thus crashing
- in the middle of the file. Also useful for testing ultra-short files of 20 samples."""
-
- def __init__(self, num_frames, has_broken_header=False):
- self.seekpoint = 0
- self.num_frames = num_frames
- self.has_broken_header = has_broken_header
-
- def seek(self, seekpoint):
- self.seekpoint = seekpoint
-
- def get_nframes(self):
- return self.num_frames
-
- def get_samplerate(self):
- return 44100
-
- def get_channels(self):
- return 1
-
- def read_frames(self, frames_to_read):
- if self.has_broken_header and self.seekpoint + frames_to_read > self.num_frames / 2:
- raise IOError()
-
- num_frames_left = self.num_frames - self.seekpoint
- if num_frames_left < frames_to_read:
- will_read = num_frames_left
- else:
- will_read = frames_to_read
- self.seekpoint += will_read
- return numpy.random.random(will_read)*2 - 1
-
-
-# TOOLS
-
-def downsample(vector, factor):
- """
- downsample(vector, factor):
- Downsample (by averaging) a vector by an integer factor.
- """
- if (len(vector) % factor):
- print "Length of 'vector' is not divisible by 'factor'=%d!" % factor
- return 0
- vector.shape = (len(vector)/factor, factor)
- return numpy.mean(vector, axis=1)
-
-
-def smooth(x, window_len=10, window='hanning'):
- """
- Smooth the data using a window with requested size.
-
- This method is based on the convolution of a scaled window with the signal.
- The signal is prepared by introducing reflected copies of the signal
- (with the window size) in both ends so that transient parts are minimized
- in the begining and end part of the output signal.
-
- Parameters
- ----------
- x : numpy.array
- the input signal
- window_len : int
- the dimension of the smoothing window
- window : str
- the type of window from 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'
- flat window will produce a moving average smoothing.
-
- Returns
- -------
- The smoothed signal
-
- See Also
- --------
-
- numpy.hanning, numpy.hamming, numpy.bartlett, numpy.blackman, numpy.convolve
- scipy.signal.lfilter
-
-
- Examples
- --------
-
- >>> import numpy as np
- >>> from timeside.grapher import smooth
- >>> t = np.arange(-2,2,0.1)
- >>> x = np.sin(t)+np.random.randn(len(t))*0.1
- >>> y = smooth(x)
- >>> import matplotlib.pyplot as plt
- >>> plt.plot(x) # doctest: +ELLIPSIS
- [<matplotlib.lines.Line2D object at 0x...>]
- >>> plt.plot(y) # doctest: +ELLIPSIS
- [<matplotlib.lines.Line2D object at 0x...>]
- >>> plt.legend(['Source signal', 'Smoothed signal']) # doctest: +ELLIPSIS
- <matplotlib.legend.Legend object at 0x...>
- >>> plt.show() # doctest: +SKIP
- """
-
- # TODO: the window parameter could be the window itself if an array instead of a string
-
-
- if x.ndim != 1:
- raise ValueError, "smooth only accepts 1 dimension arrays."
-
- if x.size < window_len:
- raise ValueError, "Input vector needs to be bigger than window size."
-
- if window_len < 3:
- return x
-
- if not window in ['flat', 'hanning', 'hamming', 'bartlett', 'blackman']:
- raise ValueError, "Window is on of 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'"
-
- s=numpy.r_[2*x[0]-x[window_len:1:-1], x, 2*x[-1]-x[-1:-window_len:-1]]
-
- if window == 'flat': #moving average
- w = numpy.ones(window_len,'d')
- else:
- w = getattr(numpy, window)(window_len)
-
- y = numpy.convolve(w/w.sum(), s, mode='same')
- return y[window_len-1:-window_len+1]
-
-
-def reduce_opacity(im, opacity):
- """Returns an image with reduced opacity."""
- assert opacity >= 0 and opacity <= 1
- if im.mode != 'RGBA':
- im = im.convert('RGBA')
- else:
- im = im.copy()
- alpha = im.split()[3]
- alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
- im.putalpha(alpha)
- return im
-
-
-def im_watermark(im, inputtext, font=None, color=None, opacity=.6, margin=(30,30)):
- """
- imprints a PIL image with the indicated text in lower-right corner
- """
- if im.mode != "RGBA":
- im = im.convert("RGBA")
- textlayer = Image.new("RGBA", im.size, (0,0,0,0))
- textdraw = ImageDraw.Draw(textlayer)
- textsize = textdraw.textsize(inputtext, font=font)
- textpos = [im.size[i]-textsize[i]-margin[i] for i in [0,1]]
- textdraw.text(textpos, inputtext, font=font, fill=color)
- if opacity != 1:
- textlayer = reduce_opacity(textlayer,opacity)
- return Image.composite(textlayer, im, textlayer)
-
-
if __name__ == "__main__":
import doctest
doctest.testmod()
\ No newline at end of file