1. Ian George
  2. sketchbook

Source

sketchbook / tuneview / main.py

 #! /usr/bin/env python
#display
from __future__ import division
import math
import pygame
import random
from pygame.time import get_ticks

#analysis
from scikits import audiolab
from scipy import fftpack, absolute, log10
from numpy import average

# Wav file, should be 44100hkz mono
audio_file = 'louis.wav'
  
# Window dimensions
screen_width = 1000
screen_height = 500
line_colour = 255,255,255

# Vis options
bottom_line = 475
refresh_rate = 100
vert_scale = 10
keep_freq_range = 0.5

clock = pygame.time.Clock()
surf = pygame.display.set_mode((screen_width, screen_height))

class SignalVis(object):
    def __init__(self, filename, frame_interval, points):
        """
        filename - pretty obvious :) currently only working with wavs
        frame_interval - frame size for analysis in ms
        """
        self.data, self.fs, self.encoding = audiolab.wavread(filename)
        self.frame_bits = int(frame_interval/1000 * self.fs)
        self.points = points

    def next(self):
        while len(self.data) > 0:
            X = fftpack.rfft(self.data[:self.frame_bits])
            #Xdb = 50*log10(absolute(X))
            #Xdb = X
            points_to_keep = self.frame_bits *  keep_freq_range # discard top 25% of frequency because it's rather dull
            interval = int(points_to_keep / self.points)
            X = X[:(self.points * interval)]
            X.shape = (self.points, interval)
            self.data = self.data[self.frame_bits:]
            yield [average(chunk) for chunk in X]

def get_time_since(ticks):
    return get_ticks() - ticks

running = True
vis = SignalVis(audio_file, refresh_rate, 200)
pygame.mixer.init()
pygame.mixer.music.load(audio_file)
pygame.mixer.music.play()
local_time = 0

for line_data in vis.next():
    #blank screen
    surf.fill((0,0,0))
    for x in xrange(len(line_data)):
        f_val = math.fabs(int(line_data[x]) * vert_scale)+1
        surf.fill(line_colour, (x*5, bottom_line-f_val, 5, f_val))
    
    # waste a bit of time until we get to the next refresh interval
    while get_time_since(local_time) < refresh_rate:
        pass
    local_time = get_ticks()
    pygame.display.flip()