def setup(self, channels=None, samplerate=None, blocksize=None, totalframes=None): super(Grapher, self).setup(channels, samplerate, blocksize, totalframes) self.sample_rate = samplerate self.higher_freq = self.sample_rate / 2 self.block_size = blocksize self.total_frames = totalframes self.image = Image.new("RGBA", (self.image_width, self.image_height), self.bg_color) self.samples_per_pixel = self.total_frames / float(self.image_width) self.buffer_size = int(round(self.samples_per_pixel, 0)) self.pixels_adapter = FixedSizeInputAdapter(self.buffer_size, 1, pad=False) self.pixels_adapter_totalframes = self.pixels_adapter.blocksize( self.total_frames) self.spectrum = Spectrum(self.fft_size, self.sample_rate, self.block_size, self.total_frames, self.lower_freq, self.higher_freq, numpy.hanning) self.pixel = self.image.load() self.draw = ImageDraw.Draw(self.image)
def testPadding(self): "Test automatic padding support" adapter = FixedSizeInputAdapter(4, 2, pad=True) self.assertEqual(len(self.data) + 2, adapter.blocksize(len(self.data))) self.assertIOEquals(adapter, self.data[0:21], False, [ self.data[0:4], self.data[4:8], self.data[8:12], self.data[12:16], self.data[16:20] ], False) self.assertIOEquals(adapter, self.data[21:22], True, [[[20, 42], [21, 43], [0, 0], [0, 0]]], True)
def testTwoChannels(self): "Test simple stream with two channels" adapter = FixedSizeInputAdapter(4, 2) self.assertEquals(len(self.data), adapter.blocksize(len(self.data))) self.assertIOEquals(adapter, self.data[0:1], False, []) self.assertIOEquals(adapter, self.data[1:5], False, [self.data[0:4]], False) self.assertIOEquals(adapter, self.data[5:12], False, [self.data[4:8], self.data[8:12]], False) self.assertIOEquals(adapter, self.data[12:13], False, []) self.assertIOEquals(adapter, self.data[13:14], False, []) self.assertIOEquals(adapter, self.data[14:18], False, [self.data[12:16]], False) self.assertIOEquals(adapter, self.data[18:20], False, [self.data[16:20]], False) self.assertIOEquals(adapter, self.data[20:21], False, []) self.assertIOEquals(adapter, self.data[21:22], True, [self.data[20:22]], True)
def testSizeMultiple(self): "Test a stream which contain a multiple number of buffers" adapter = FixedSizeInputAdapter(4, 2) self.assertIOEquals(adapter, self.data[0:20], True, [self.data[0:4], self.data[4:8], self.data[8:12], self.data[12:16], self.data[16:20]], True)
def testPadding(self): "Test automatic padding support" adapter = FixedSizeInputAdapter(4, 2, pad=True) self.assertEquals(len(self.data) + 2, adapter.blocksize(len(self.data))) self.assertIOEquals(adapter, self.data[0:21], False, [self.data[0:4], self.data[4:8], self.data[8:12], self.data[12:16], self.data[16:20]], False) self.assertIOEquals(adapter, self.data[21:22], True, [[ [20, 42], [21, 43], [0, 0], [0, 0] ]], True)
def setup(self, channels=None, samplerate=None, blocksize=None, totalframes=None): super(Grapher, self).setup( channels, samplerate, blocksize, totalframes) self.sample_rate = samplerate self.higher_freq = self.sample_rate / 2 self.block_size = blocksize self.total_frames = totalframes self.image = Image.new( "RGBA", (self.image_width, self.image_height), self.bg_color) self.samples_per_pixel = self.total_frames / float(self.image_width) self.buffer_size = int(round(self.samples_per_pixel, 0)) self.pixels_adapter = FixedSizeInputAdapter( self.buffer_size, 1, pad=False) self.pixels_adapter_totalframes = self.pixels_adapter.blocksize( self.total_frames) self.spectrum = Spectrum( self.fft_size, self.sample_rate, self.block_size, self.total_frames, self.lower_freq, self.higher_freq, numpy.hanning) self.pixel = self.image.load() self.draw = ImageDraw.Draw(self.image)
class Grapher(Processor): ''' Generic abstract class for the graphers ''' type = 'grapher' fft_size = 0x1000 frame_cursor = 0 pixel_cursor = 0 lower_freq = 20 implements(IGrapher) abstract() def __init__(self, width=1024, height=256, bg_color=None, color_scheme='default'): super(Grapher, self).__init__() self.bg_color = bg_color self.color_scheme = color_scheme self.graph = None self.image_width = width self.image_height = height self.bg_color = bg_color self.color_scheme = color_scheme self.previous_x, self.previous_y = None, None @staticmethod def id(): return "generic_grapher" @staticmethod def name(): return "Generic grapher" def set_colors(self, bg_color, color_scheme): self.bg_color = bg_color self.color_color_scheme = color_scheme def setup(self, channels=None, samplerate=None, blocksize=None, totalframes=None): super(Grapher, self).setup(channels, samplerate, blocksize, totalframes) self.sample_rate = samplerate self.higher_freq = self.sample_rate / 2 self.block_size = blocksize self.total_frames = totalframes self.image = Image.new("RGBA", (self.image_width, self.image_height), self.bg_color) self.samples_per_pixel = self.total_frames / float(self.image_width) self.buffer_size = int(round(self.samples_per_pixel, 0)) self.pixels_adapter = FixedSizeInputAdapter(self.buffer_size, 1, pad=False) self.pixels_adapter_totalframes = self.pixels_adapter.blocksize( self.total_frames) self.spectrum = Spectrum(self.fft_size, self.sample_rate, self.block_size, self.total_frames, self.lower_freq, self.higher_freq, numpy.hanning) self.pixel = self.image.load() self.draw = ImageDraw.Draw(self.image) @interfacedoc def render(self, output=None): if output: try: self.image.save(output) except AttributeError: print "Pixel %s x %d" % (self.image_width, self.image_height) self.image.savefig(output, dpi=341) return return self.image def watermark(self, text, font=None, color=(255, 255, 255), opacity=.6, margin=(5, 5)): self.image = im_watermark(self.image, text, color=color, opacity=opacity, margin=margin) def draw_peaks(self, x, peaks, line_color): """Draw 2 peaks at x""" y1 = self.image_height * 0.5 - peaks[0] * (self.image_height - 4) * 0.5 y2 = self.image_height * 0.5 - peaks[1] * (self.image_height - 4) * 0.5 if self.previous_y: self.draw.line([self.previous_x, self.previous_y, x, y1, x, y2], line_color) else: self.draw.line([x, y1, x, y2], line_color) self.draw_anti_aliased_pixels(x, y1, y2, line_color) self.previous_x, self.previous_y = x, y2 def draw_peaks_inverted(self, x, peaks, line_color): """Draw 2 inverted peaks at x""" y1 = self.image_height * 0.5 - peaks[0] * (self.image_height - 4) * 0.5 y2 = self.image_height * 0.5 - peaks[1] * (self.image_height - 4) * 0.5 if self.previous_y and x < self.image_width - 1: if y1 < y2: self.draw.line((x, 0, x, y1), line_color) self.draw.line((x, self.image_height, x, y2), line_color) else: self.draw.line((x, 0, x, y2), line_color) self.draw.line((x, self.image_height, x, y1), line_color) else: self.draw.line((x, 0, x, self.image_height), line_color) self.draw_anti_aliased_pixels(x, y1, y2, line_color) self.previous_x, self.previous_y = x, y1 def draw_anti_aliased_pixels(self, x, y1, y2, color): """ vertical anti-aliasing at y1 and y2 """ y_max = max(y1, y2) y_max_int = int(y_max) alpha = y_max - y_max_int if alpha > 0.0 and alpha < 1.0 and y_max_int + 1 < self.image_height: current_pix = self.pixel[int(x), y_max_int + 1] r = int((1 - alpha) * current_pix[0] + alpha * color[0]) g = int((1 - alpha) * current_pix[1] + alpha * color[1]) b = int((1 - alpha) * current_pix[2] + alpha * color[2]) self.pixel[x, y_max_int + 1] = (r, g, b) y_min = min(y1, y2) y_min_int = int(y_min) alpha = 1.0 - (y_min - y_min_int) if alpha > 0.0 and alpha < 1.0 and y_min_int - 1 >= 0: current_pix = self.pixel[x, y_min_int - 1] r = int((1 - alpha) * current_pix[0] + alpha * color[0]) g = int((1 - alpha) * current_pix[1] + alpha * color[1]) b = int((1 - alpha) * current_pix[2] + alpha * color[2]) self.pixel[x, y_min_int - 1] = (r, g, b) def draw_peaks_contour(self): contour = self.contour.copy() contour = smooth(contour, window_len=16) contour = normalize(contour) # Scaling #ratio = numpy.mean(contour)/numpy.sqrt(2) ratio = 1 contour = normalize(numpy.expm1(contour / ratio)) * (1 - 10**-6) # Spline #contour = cspline1d(contour) #contour = cspline1d_eval(contour, self.x, dx=self.dx1, x0=self.x[0]) if self.symetry: height = int(self.image_height / 2) else: height = self.image_height # Multicurve rotating for i in range(0, self.ndiv): self.previous_x, self.previous_y = None, None bright_color = int(255 * (1 - float(i) / (self.ndiv * 2))) bright_color = 255 - bright_color + self.color_offset #line_color = self.color_lookup[int(self.centroids[j]*255.0)] line_color = (bright_color, bright_color, bright_color) # Linear #contour = contour*(1.0-float(i)/self.ndiv) #contour = contour*(1-float(i)/self.ndiv) # Cosinus contour = contour * \ numpy.arccos(float(i) / self.ndiv) * 2 / numpy.pi #contour = self.contour*(1-float(i)*numpy.arccos(float(i)/self.ndiv)*2/numpy.pi/self.ndiv) #contour = contour + ((1-contour)*2/numpy.pi*numpy.arcsin(float(i)/self.ndiv)) curve = (height - 1) * contour #curve = contour*(height-2)/2+height/2 for x in self.x: x = int(x) y = curve[x] if not x == 0: if not self.symetry: self.draw.line( [self.previous_x, self.previous_y, x, y], line_color) self.draw_anti_aliased_pixels(x, y, y, line_color) else: self.draw.line([ self.previous_x, self.previous_y + height, x, y + height ], line_color) self.draw_anti_aliased_pixels(x, y + height, y + height, line_color) self.draw.line([ self.previous_x, -self.previous_y + height, x, -y + height ], line_color) self.draw_anti_aliased_pixels(x, -y + height, -y + height, line_color) else: if not self.symetry: self.draw.point((x, y), line_color) else: self.draw.point((x, y + height), line_color) self.previous_x, self.previous_y = x, y
class Grapher(Processor): ''' Generic abstract class for the graphers ''' type = 'grapher' fft_size = 0x1000 frame_cursor = 0 pixel_cursor = 0 lower_freq = 20 implements(IGrapher) abstract() def __init__(self, width=1024, height=256, bg_color=None, color_scheme='default'): super(Grapher, self).__init__() self.bg_color = bg_color self.color_scheme = color_scheme self.graph = None self.image_width = width self.image_height = height self.bg_color = bg_color self.color_scheme = color_scheme self.previous_x, self.previous_y = None, None @staticmethod def id(): return "generic_grapher" @staticmethod def name(): return "Generic grapher" def set_colors(self, bg_color, color_scheme): self.bg_color = bg_color self.color_color_scheme = color_scheme def setup(self, channels=None, samplerate=None, blocksize=None, totalframes=None): super(Grapher, self).setup( channels, samplerate, blocksize, totalframes) self.sample_rate = samplerate self.higher_freq = self.sample_rate / 2 self.block_size = blocksize self.total_frames = totalframes self.image = Image.new( "RGBA", (self.image_width, self.image_height), self.bg_color) self.samples_per_pixel = self.total_frames / float(self.image_width) self.buffer_size = int(round(self.samples_per_pixel, 0)) self.pixels_adapter = FixedSizeInputAdapter( self.buffer_size, 1, pad=False) self.pixels_adapter_totalframes = self.pixels_adapter.blocksize( self.total_frames) self.spectrum = Spectrum( self.fft_size, self.sample_rate, self.block_size, self.total_frames, self.lower_freq, self.higher_freq, numpy.hanning) self.pixel = self.image.load() self.draw = ImageDraw.Draw(self.image) @interfacedoc def render(self, output=None): if output: try: self.image.save(output) except AttributeError: print "Pixel %s x %d" % (self.image_width, self.image_height) self.image.savefig(output, dpi=341) return return self.image def watermark(self, text, font=None, color=(255, 255, 255), opacity=.6, margin=(5, 5)): self.image = im_watermark( self.image, text, color=color, opacity=opacity, margin=margin) def draw_peaks(self, x, peaks, line_color): """Draw 2 peaks at x""" y1 = self.image_height * 0.5 - peaks[0] * (self.image_height - 4) * 0.5 y2 = self.image_height * 0.5 - peaks[1] * (self.image_height - 4) * 0.5 if self.previous_y: self.draw.line( [self.previous_x, self.previous_y, x, y1, x, y2], line_color) else: self.draw.line([x, y1, x, y2], line_color) self.draw_anti_aliased_pixels(x, y1, y2, line_color) self.previous_x, self.previous_y = x, y2 def draw_peaks_inverted(self, x, peaks, line_color): """Draw 2 inverted peaks at x""" y1 = self.image_height * 0.5 - peaks[0] * (self.image_height - 4) * 0.5 y2 = self.image_height * 0.5 - peaks[1] * (self.image_height - 4) * 0.5 if self.previous_y and x < self.image_width - 1: if y1 < y2: self.draw.line((x, 0, x, y1), line_color) self.draw.line((x, self.image_height, x, y2), line_color) else: self.draw.line((x, 0, x, y2), line_color) self.draw.line((x, self.image_height, x, y1), line_color) else: self.draw.line((x, 0, x, self.image_height), line_color) self.draw_anti_aliased_pixels(x, y1, y2, line_color) self.previous_x, self.previous_y = x, y1 def draw_anti_aliased_pixels(self, x, y1, y2, color): """ vertical anti-aliasing at y1 and y2 """ y_max = max(y1, y2) y_max_int = int(y_max) alpha = y_max - y_max_int if alpha > 0.0 and alpha < 1.0 and y_max_int + 1 < self.image_height: current_pix = self.pixel[int(x), y_max_int + 1] r = int((1 - alpha) * current_pix[0] + alpha * color[0]) g = int((1 - alpha) * current_pix[1] + alpha * color[1]) b = int((1 - alpha) * current_pix[2] + alpha * color[2]) self.pixel[x, y_max_int + 1] = (r, g, b) y_min = min(y1, y2) y_min_int = int(y_min) alpha = 1.0 - (y_min - y_min_int) if alpha > 0.0 and alpha < 1.0 and y_min_int - 1 >= 0: current_pix = self.pixel[x, y_min_int - 1] r = int((1 - alpha) * current_pix[0] + alpha * color[0]) g = int((1 - alpha) * current_pix[1] + alpha * color[1]) b = int((1 - alpha) * current_pix[2] + alpha * color[2]) self.pixel[x, y_min_int - 1] = (r, g, b) def draw_peaks_contour(self): contour = self.contour.copy() contour = smooth(contour, window_len=16) contour = normalize(contour) # Scaling #ratio = numpy.mean(contour)/numpy.sqrt(2) ratio = 1 contour = normalize(numpy.expm1(contour / ratio)) * (1 - 10 ** -6) # Spline #contour = cspline1d(contour) #contour = cspline1d_eval(contour, self.x, dx=self.dx1, x0=self.x[0]) if self.symetry: height = int(self.image_height / 2) else: height = self.image_height # Multicurve rotating for i in range(0, self.ndiv): self.previous_x, self.previous_y = None, None bright_color = int(255 * (1 - float(i) / (self.ndiv * 2))) bright_color = 255 - bright_color + self.color_offset #line_color = self.color_lookup[int(self.centroids[j]*255.0)] line_color = (bright_color, bright_color, bright_color) # Linear #contour = contour*(1.0-float(i)/self.ndiv) #contour = contour*(1-float(i)/self.ndiv) # Cosinus contour = contour * \ numpy.arccos(float(i) / self.ndiv) * 2 / numpy.pi #contour = self.contour*(1-float(i)*numpy.arccos(float(i)/self.ndiv)*2/numpy.pi/self.ndiv) #contour = contour + ((1-contour)*2/numpy.pi*numpy.arcsin(float(i)/self.ndiv)) curve = (height - 1) * contour #curve = contour*(height-2)/2+height/2 for x in self.x: x = int(x) y = curve[x] if not x == 0: if not self.symetry: self.draw.line( [self.previous_x, self.previous_y, x, y], line_color) self.draw_anti_aliased_pixels(x, y, y, line_color) else: self.draw.line( [self.previous_x, self.previous_y + height, x, y + height], line_color) self.draw_anti_aliased_pixels( x, y + height, y + height, line_color) self.draw.line( [self.previous_x, -self.previous_y + height, x, -y + height], line_color) self.draw_anti_aliased_pixels( x, -y + height, -y + height, line_color) else: if not self.symetry: self.draw.point((x, y), line_color) else: self.draw.point((x, y + height), line_color) self.previous_x, self.previous_y = x, y