# dedenc.py

a guest
Feb 17th, 2017
166
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. # ported from my own shining.py
2. rate = 10485.76
3. vol = 3.2
4.
5. import argparse, math, wave, random
6.
7. # tree building
8. class HuffTree:
9.     def __init__(self,a,b,c):
10.         self.val = a
11.         self.left = b
12.         self.right = c
13.
14. class HuffLeaf:
15.     def __init__(self,a,b):
16.         self.val = a
17.         self.id = b
18.
19. def readsamp(src,pos,size,chs): # returns a value between -0.5 and 0.5
20.     t = 0
21.     for i in range(chs):
22.         tt = 0
23.         for j in range(size):
24.             tt = tt + (ord(src[pos+i*size+j]) << (j * 8))
25.         if size == 1: # 8-bit samples are usually unsigned
26.             tt = tt - 128 # negative
27.         elif tt > 256**size/2-1: tt = tt - 256**size # negative
28.         t = t + tt
29.     return t / chs / 256.0**size
30.
31. # cubic spline interpolation
32. def cuinterpo(s,n):
33.     nn = int(n)
34.     p0 = s[nn]
35.     p1 = s[nn+1]
36.     m0 = (s[nn+1]-s[nn-1])/2
37.     m1 = (s[nn+2]-s[nn])/2
38.     t1 = math.modf(n)[0]
39.     t2 = math.pow(t1,2)
40.     t3 = math.pow(t1,3)
41.     return (2*t3-3*t2+1)*p0+(t3-2*t2+t1)*m0+(-2*t3+3*t2)*p1+(t3-t2)*m1
42.
43. def writetree(tree,jrcnt,bits,dict):
44.     le = tree.left
45.     ri = tree.right
46.     if isinstance(le,HuffTree) and isinstance(ri,HuffTree):
47.         jrcnt = jrcnt+9
48.         res,jrcnt2 = writetree(le,jrcnt,bits+"0",dict)
49.         res2,jrcnt3 = writetree(ri,0,bits+"1",dict)
50.         if(jrcnt2-jrcnt > 127):
51.             outs = chr(0xe0+((jrcnt2-jrcnt)>>8))+chr((jrcnt2-jrcnt)%0x100)+res+res2
52.             jrcnt = jrcnt+1
53.         else: outs = chr(jrcnt2-jrcnt)+res+res2
54.         jrcnt = jrcnt2+jrcnt3
55.     elif isinstance(le,HuffTree) and isinstance(ri,HuffLeaf):
56.         jrcnt = jrcnt+10
57.         dict[ri.id] = bits+"1"
58.         res,jrcnt = writetree(le,jrcnt,bits+"0",dict)
59.         outs = chr(0x80+ri.id)+res
60.     else:
61.         jrcnt = jrcnt+13
62.         dict[le.id] = bits+"0"
63.         dict[ri.id] = bits+"1"
64.         outs = chr(0xc0+ri.id)+chr(le.id)
65.     return (outs,jrcnt)
66.
67. def wavtoded(fd,ra,ch,wi):
68.     fdd = []
69.     fdl = []
70.
71.     for i in range(0,len(fd),wi*ch): # amplify
72.         t = readsamp(fd, i, wi, ch)
73.         fdd.append(t * vol)
74.     fdd = fdd + [0.0]*2
75.
76.     if abs(ra-rate)/rate > 0.05:
77.         for i in range(0,int((len(fdd)-2)*rate/ra)): # stretch
78.             fdl.append(cuinterpo(fdd,i*ra/rate))
79.     else: fdl = fdd
80.
81.     for i in range(0,len(fdl)): # convert
82.         fdl[i] = min(max(fdl[i]+(8.0/15.0),0),1.0)
83.
84.     # TPDF dither
85.     last = 8
86.     tp = []
87.     freq = {}
88.     random.seed(3490487757541254948)
89.     for i in fdl:
90.         ev = int(i*15)
91.         er = i*15.0 - ev
92.         eo = 0.0
93.         if er < 0.5: eo = 2.0*er*er
94.         else: eo = 1.0-(2.0*(1.0-er)*(1.0-er))
95.         if eo > random.random(): ev = ev+1
96.         ew = (ev-last)%16
97.         tp.append(ew)
98.         if ew not in freq: freq[ew] = 0
99.         freq[ew] = freq[ew] + 1
100.         last = ev
101.     while len(tp) % 32 != 0: tp.append(0)
102.
103.     qu = []
104.     for i in freq.keys(): qu.append(HuffLeaf(freq[i],i))
105.     while len(qu) > 1:
106.         qu = sorted(qu, lambda x,y: cmp(x.val,y.val))
107.         le = qu.pop(0)
108.         ri = qu.pop(0)
109.         if isinstance(le,HuffLeaf) and isinstance(ri,HuffTree):
110.             tmp = ri
111.             ri = le
112.             le = tmp
113.         qu.append(HuffTree(le.val+ri.val,le,ri))
114.
115.     # tree writing
116.     code = {}
117.     ls = writetree(qu[0],0,"",code)[0] + chr(0xff)
118.
119.     # compression
120.     ou = ""
121.     for i in range(len(tp)): ou = ou + code[tp[i]]
122.     while len(ou) % 8 != 0: ou = ou + "1"
123.
124.     ls = ls + chr((len(tp)/32)%256) + chr((len(tp)/32)>>8)
125.     for i in range(0,len(ou),8): ls = ls + chr(int(ou[i:i+8],2))
126.     return ls
127.
128. if __name__ == "__main__":
129.     parser = argparse.ArgumentParser()
130.     parser.add_argument('fi', metavar='in', type=argparse.FileType('rb'), help='Input file name')
131.     parser.add_argument('fo', metavar='out', type=argparse.FileType('wb'), help='Output file name')
132.     nsp = parser.parse_args()
133.
134.     fl = wave.open(nsp.fi,"rb")
135.     nf = fl.getnframes()
136.     ous = wavtoded(fl.readframes(nf), fl.getframerate(), fl.getnchannels(), fl.getsampwidth())
137.     fl.close()
138.     nsp.fo.write(ous)
139.     nsp.fo.close()
RAW Paste Data