Skip to content

Commit

Permalink
the system works great now, but it's really slow
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrk committed May 6, 2010
1 parent 60db57b commit 4524a0a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 36 deletions.
47 changes: 11 additions & 36 deletions madwave.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,14 @@
import mad
from PIL import Image, ImageDraw
import struct
import mp3decoder

import sys

image_width = 800
image_height = 100

madfile = mad.MadFile(sys.argv[1])

# load the entire thing into memory
bytes = ""
while True:
buf = madfile.read()
if buf is None:
break
for i in range(len(buf)):
bytes += buf[i]

print "done loading"

channel_count = madfile.mode()
sample_size = 2
frame_size = sample_size * channel_count
byte_count = len(bytes)
frame_count = byte_count / frame_size
#byte_count = frame_count * frame_size

sample_min = -pow(2, 8*sample_size-1)+1
sample_max = pow(2, 8*sample_size-1)
sample_range = float(sample_max - sample_min)

frames_per_pixel = frame_count / float(image_width)
mp3 = mp3decoder.Mp3Decoder(sys.argv[1])
sample_range = float(mp3.sample_max - mp3.sample_min)
frames_per_pixel = mp3.frame_count / float(image_width)

image = Image.new("RGBA", (image_width, image_height), (255, 255, 255, 0))
draw = ImageDraw.Draw(image)
Expand All @@ -44,16 +21,14 @@
end = int((x+1) * frames_per_pixel)

# get the min and max of this range
min = sample_max
max = sample_min
min = mp3.sample_max
max = mp3.sample_min
# for each frame from start to end
i = start
while i < end:
offset = i * frame_size
lvalue = struct.unpack("h", bytes[offset:offset+sample_size])[0]
offset += sample_size
rvalue = struct.unpack("h", bytes[offset:offset+sample_size])[0]
value = (lvalue + rvalue) / 2.0
frame = mp3.frame(i)
# average the channels
value = float(sum(frame)) / len(frame)

if value < min:
min = value
Expand All @@ -63,8 +38,8 @@
i += 1

# translate into y pixel coord
y_min = int(round((min - sample_min) / sample_range * (image_height-1)))
y_max = int(round((max - sample_min) / sample_range * (image_height-1)))
y_min = int(round((min - mp3.sample_min) / sample_range * (image_height-1)))
y_max = int(round((max - mp3.sample_min) / sample_range * (image_height-1)))

# draw
draw.line(((x, y_min), (x, y_max)), (0,0,0,255))
Expand Down
38 changes: 38 additions & 0 deletions mp3decoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import mad
import struct

class Mp3Decoder:
"""
This class depends on an mp3 library and provides methods for accessing
metadata and samples.
Can only read forwards. You may never access a frame before a frame
you've already accessed.
"""
def __init__(self, file):
self.madfile = mad.MadFile(file)
# calculations
self.channel_count = self.madfile.mode()
self.sample_size = 2
self.pack_char = "h" # depends on self.sample_size
self.frame_size = self.sample_size * self.channel_count
self.byte_count = int(self.madfile.total_time() / 1000.0 * self.madfile.samplerate() * self.frame_size)
self.frame_count = self.byte_count / self.frame_size

self.sample_min = -pow(2, 8*self.sample_size-1)+1
self.sample_max = pow(2, 8*self.sample_size-1)

self.offset = 0
self.buf = self.madfile.read()

def frame(self, index):
"""
returns a tuple with a value for each channel
"""
while index * self.frame_size >= self.offset+len(self.buf):
self.buf = self.madfile.read()
if self.buf is None:
return None
self.offset += len(self.buf)
frame_offset = index * self.frame_size - self.offset
return struct.unpack(self.pack_char*self.channel_count, self.buf[frame_offset:frame_offset+self.frame_size])

0 comments on commit 4524a0a

Please sign in to comment.