27 from itertools 
import imap,chain,izip
 
   32     print >>sys.stderr, 
"Error: Numerical Python not found" 
   36     from scikits.audiolab 
import Sndfile
 
   38     print >>sys.stderr, 
"Error: scikits.audiolab not found" 
   44     print >>sys.stderr, 
"Error: purehuff module not found" 
   48     """group list elements""" 
   51         l = [v 
for _,v 
in izip(xrange(n),it)]
 
   57 def arrayformatter(seq,perline=40):
 
   58     """format list output linewise""" 
   59     return ",\n".join(
",".join(imap(str,s)) 
for s 
in grouper(perline,seq))
 
   61 if __name__ == 
"__main__":
 
   62     from optparse 
import OptionParser
 
   63     parser = OptionParser()
 
   64     parser.add_option(
"--bits", type=
"int", default=8, dest=
"bits",help=
"bit resolution")
 
   65     parser.add_option(
"--sndfile", dest=
"sndfile",help=
"input sound file")
 
   66     parser.add_option(
"--hdrfile", dest=
"hdrfile",help=
"output C header file")
 
   67     parser.add_option(
"--name", dest=
"name",help=
"prefix for tables and constants in file")
 
   68     parser.add_option(
"--plothist", type=
"int", default=0, dest=
"plothist",help=
"plot histogram")
 
   69     (options, args) = parser.parse_args()
 
   71     if not options.sndfile:
 
   72         print >>sys.stderr,
"Error: --sndfile argument required" 
   75     sndf = Sndfile(options.sndfile,
'r')
 
   76     sound = sndf.read_frames(sndf.nframes)
 
   81     if len(sound.shape) > 1:
 
   82         sound = N.mean(sound,axis=1)
 
   85     sound8 = N.clip((sound*(2**(options.bits-1))).astype(int),-2**(options.bits-1),2**(options.bits-1)-1)
 
   87     dsound8 = map(int,chain((sound8[0],),imap(
lambda x: x[1]-x[0],izip(sound8[:-1],sound8[1:]))))
 
   89     print >>sys.stderr,
"min/max: %i/%i"%(N.min(sound8),N.max(sound8))
 
   90     print >>sys.stderr,
"data bits: %i"%(len(sound8)*options.bits)
 
   92     hist = purehuff.histogram(dsound8)
 
   98             print >>sys.stderr, 
"Plotting needs pylab" 
  100         from collections 
import defaultdict
 
  101         d = defaultdict(float)
 
  104         x = range(min(d.iterkeys()),max(d.iterkeys())+1)
 
  105         y = [d[xi] 
for xi 
in x]
 
  107         P.title(
"Histogram of sample differentials, file %s"%os.path.split(options.sndfile)[-1])
 
  108         P.plot(x,y,marker=
'x')
 
  111     hufftree = purehuff.HuffTree(hist)
 
  114     decoder = hufftree.decoder()
 
  116     encoder = hufftree.encoder()
 
  118     enc = encoder(dsound8)
 
  120     print >>sys.stderr,
"encoded bits: %i"%len(enc)
 
  121     print >>sys.stderr,
"ratio: %.0f%%"%((len(enc)*100.)/(len(sound8)*8))
 
  122     print >>sys.stderr,
"decoder length: %.0f words"%(len(decoder.huff))
 
  125         hdrf = file(options.hdrfile,
'wt')
 
  126         print >>hdrf,
"// generated by Mozzi/extras/python/audio2huff.py \n" 
  127         print >>hdrf,
"#ifndef " + options.name + 
"_H_" 
  128         print >>hdrf,
"#define " + options.name + 
"_H_\n" 
  129         print >>hdrf,
'#if ARDUINO >= 100' 
  130         print >>hdrf,
'#include <Arduino.h>\n' 
  131         print >>hdrf,
'#include "mozzi_pgmspace.h"\n \n' 
  132         print >>hdrf,
"#define " + options.name + 
"_SAMPLERATE %i"%fs
 
  133         print >>hdrf,
"#define " + options.name + 
"_SAMPLE_BITS %i"%options.bits
 
  134         print >>hdrf,
'CONSTTABLE_STORAGE(int) ' + options.name + 
'_HUFFMAN[%i] = {\n%s\n};'%(len(decoder.huff),arrayformatter(decoder.huff))
 
  135         print >>hdrf,
'unsigned long const ' + options.name + 
'_SOUNDDATA_BITS = %iL;'%len(enc)
 
  136         print >>hdrf,
'CONSTTABLE_STORAGE(unsigned char) ' + options.name + 
'_SOUNDDATA[] = {\n%s\n};'%arrayformatter(enc.data)
 
  137         print >>hdrf,
"#endif /* " + options.name + 
"_H_ */"