1 """Utilities needed for encoding/decoding MIDI data.
2
3 """
4
6 """
7 Reads a variable-length value from a stream as used in MIDI data.
8 Pops all the bytes that form a part of the value and returns the
9 decoded numeric value.
10
11 """
12 NEXTBYTE = 1
13 value = 0
14 while NEXTBYTE:
15 chr = ord(data.next())
16
17 if not (chr & 0x80):
18
19 NEXTBYTE = 0
20
21 chr = chr & 0x7f
22
23 value = value << 7
24
25 value += chr
26 return value
27
29 """
30 Encodes the given numeric value as a MIDI variable-length value
31 and returns the data as a string that should be written to a
32 data stream to represent that value.
33
34 """
35 if value>=pow(2,28):
36 raise ValueError("A varlen must be less than 2^28")
37 chr1 = chr(value & 0x7F)
38 value >>= 7
39 if value:
40 chr2 = chr((value & 0x7F) | 0x80)
41 value >>= 7
42 if value:
43 chr3 = chr((value & 0x7F) | 0x80)
44 value >>= 7
45 if value:
46 chr4 = chr((value & 0x7F) | 0x80)
47 res = chr4 + chr3 + chr2 + chr1
48 else:
49 res = chr3 + chr2 + chr1
50 else:
51 res = chr2 + chr1
52 else:
53 res = chr1
54 return res
55
56
58 "reads a hex value as a string, returns an integer"
59 value = ''
60
61 length = len(hexstring) / 2
62
63 for i in range(length):
64 byte = '0x'+hexstring[2*i]+hexstring[2*i+1]
65 byte = int(byte,16)
66
67
68 binstring = bin(int(byte))
69 binstring = binstring[2:]
70 binstring = '0'*(8-len(binstring))+binstring
71 binstring = binstring[1:]
72
73 value+=binstring
74
75 value='0b'+value
76 value=int(value,2)
77
78 return value
79
80
82 for value in xrange(0x0FFFFFFF):
83 if not (value % 0xFFFF):
84 print hex(value)
85 datum = write_varlen(value)
86 newvalue = read_varlen(iter(datum))
87 if value != newvalue:
88 hexstr = str.join('', map(hex, map(ord, datum)))
89 print "%s != %s (hex: %s)" % (value, newvalue, hexstr)
90