24 from itertools
import imap,chain,izip
29 print >>sys.stderr,
"Error: Numerical Python not found" 33 from scikits.audiolab
import Sndfile
35 print >>sys.stderr,
"Error: Scikits.audiolab not found" 41 print >>sys.stderr,
"Error: purehuff module not found" 46 """group list elements""" 49 l = [v
for _,v
in izip(xrange(n),it)]
55 def arrayformatter(seq,perline=40):
56 """format list output linewise""" 57 return ",\n".join(
",".join(imap(str,s))
for s
in grouper(perline,seq))
59 if __name__ ==
"__main__":
60 from optparse
import OptionParser
61 parser = OptionParser()
62 parser.add_option(
"--bits", type=
"int", default=8, dest=
"bits",help=
"bit resolution")
63 parser.add_option(
"--sndfile", dest=
"sndfile",help=
"input sound file")
64 parser.add_option(
"--hdrfile", dest=
"hdrfile",help=
"output C header file")
65 parser.add_option(
"--name", dest=
"name",help=
"prefix for tables and constants in file")
66 parser.add_option(
"--plothist", type=
"int", default=0, dest=
"plothist",help=
"plot histogram")
67 (options, args) = parser.parse_args()
69 if not options.sndfile:
70 print >>sys.stderr,
"Error: --sndfile argument required" 73 sndf = Sndfile(options.sndfile,
'r') 74 sound = sndf.read_frames(sndf.nframes) 79 if len(sound.shape) > 1:
80 sound = N.mean(sound,axis=1)
83 sound8 = N.clip((sound*(2**(options.bits-1))).astype(int),-2**(options.bits-1),2**(options.bits-1)-1)
85 dsound8 = map(int,chain((sound8[0],),imap(
lambda x: x[1]-x[0],izip(sound8[:-1],sound8[1:]))))
87 print >>sys.stderr,
"min/max: %i/%i"%(N.min(sound8),N.max(sound8))
88 print >>sys.stderr,
"data bits: %i"%(len(sound8)*options.bits)
90 hist = purehuff.histogram(dsound8)
96 print >>sys.stderr,
"Plotting needs pylab" 98 from collections
import defaultdict
99 d = defaultdict(float)
102 x = range(min(d.iterkeys()),max(d.iterkeys())+1)
103 y = [d[xi]
for xi
in x]
105 P.title(
"Histogram of sample differentials, file %s"%os.path.split(options.sndfile)[-1])
106 P.plot(x,y,marker=
'x')
109 hufftree = purehuff.HuffTree(hist)
112 decoder = hufftree.decoder()
114 encoder = hufftree.encoder()
116 enc = encoder(dsound8)
118 print >>sys.stderr,
"encoded bits: %i"%len(enc)
119 print >>sys.stderr,
"ratio: %.0f%%"%((len(enc)*100.)/(len(sound8)*8))
120 print >>sys.stderr,
"decoder length: %.0f words"%(len(decoder.huff))
123 hdrf = file(options.hdrfile,
'wt')
124 print >>hdrf,
"// generated by Mozzi/extras/python/audio2huff.py \n" 125 print >>hdrf,
"#ifndef " + options.name +
"_H_" 126 print >>hdrf,
"#define " + options.name +
"_H_\n" 127 print >>hdrf,
'#if ARDUINO >= 100' 128 print >>hdrf,
'#include "Arduino.h"' 130 print >>hdrf,
'#include "WProgram.h"' 131 print >>hdrf,
'#endif \n' 132 print >>hdrf,
'#include <avr/pgmspace.h>\n \n' 133 print >>hdrf,
"#define " + options.name +
"_SAMPLERATE %i"%fs
134 print >>hdrf,
"#define " + options.name +
"_SAMPLE_BITS %i"%options.bits
135 print >>hdrf,
'int const __attribute__((section(".progmem.data"))) ' + options.name +
'_HUFFMAN[%i] = {\n%s\n};'%(len(decoder.huff),arrayformatter(decoder.huff))
136 print >>hdrf,
'unsigned long const ' + options.name +
'_SOUNDDATA_BITS = %iL;'%len(enc)
137 print >>hdrf,
'unsigned char const __attribute__((section(".progmem.data"))) ' + options.name +
'_SOUNDDATA[] = {\n%s\n};'%arrayformatter(enc.data)
138 print >>hdrf,
"#endif /* " + options.name +
"_H_ */"