1 # -*- coding: ISO-8859-1 -*-
3 from struct
import pack
, unpack
6 This module contains functions for reading and writing the special data types
7 that a midi file contains.
11 nibbles are four bits. A byte consists of two nibles.
12 hiBits==0xF0, loBits==0x0F Especially used for setting
13 channel and event in 1. byte of musical midi events
20 Returns hi and lo bits in a byte as a tuple
24 Asserts byte value in byte range
26 Traceback (most recent call last):
28 ValueError: Byte value out of range 0-255: 256
30 if not 0 <= byte
<= 255:
31 raise ValueError('Byte value out of range 0-255: %s' % byte
)
32 return (byte
>> 4 & 0xF, byte
& 0xF)
35 def setNibbles(hiNibble
, loNibble
):
37 Returns byte with value set according to hi and lo bits
38 Asserts hiNibble and loNibble in range(16)
43 Traceback (most recent call last):
45 ValueError: Nible value out of range 0-15: (8, 16)
47 if not (0 <= hiNibble
<= 15) or not (0 <= loNibble
<= 15):
48 raise ValueError('Nible value out of range 0-15: (%s, %s)' % (hiNibble
, loNibble
))
49 return (hiNibble
<< 4) + loNibble
55 Reads string as big endian word, (asserts len(value) in [1,2,4])
61 return unpack('>%s' % {1:'B', 2:'H', 4:'L'}[len(value
)], value
)[0]
64 def writeBew(value
, length
):
66 Write int as big endian formatted string, (asserts length in [1,2,4])
67 Difficult to print the result in doctest, so I do a simple roundabout test.
68 >>> readBew(writeBew(25057, 2))
70 >>> readBew(writeBew(1642193635L, 4))
73 return pack('>%s' % {1:'B', 2:'H', 4:'L'}[length
], value
)
78 Variable Length Data (varlen) is a data format sprayed liberally throughout
79 a midi file. It can be anywhere from 1 to 4 bytes long.
80 If the 8'th bit is set in a byte another byte follows. The value is stored
81 in the lowest 7 bits of each byte. So max value is 4x7 bits = 28 bits.
87 Converts varlength format to integer. Just pass it 0 or more chars that
88 might be a varlen and it will only use the relevant chars.
89 use varLen(readVar(value)) to see how many bytes the integer value takes.
90 asserts len(value) >= 0
97 for byte
in unpack('%sB' % len(value
), value
):
98 sum = (sum << 7) + (byte
& 0x7F)
99 if not 0x80 & byte
: break # stop after last byte
106 Returns the the number of bytes an integer will be when
107 converted to varlength
113 elif value
<= 2097151:
120 "Converts an integer to varlength format"
121 sevens
= to_n_bits(value
, varLen(value
))
122 for i
in range(len(sevens
)-1):
123 sevens
[i
] = sevens
[i
] |
0x80
124 return fromBytes(sevens
)
127 def to_n_bits(value
, length
=1, nbits
=7):
128 "returns the integer value as a sequence of nbits bytes"
129 bytes
= [(value
>> (i
*nbits
)) & 0x7F for i
in range(length
)]
135 "Turns a string into a list of byte values"
136 return unpack('%sB' % len(value
), value
)
139 def fromBytes(value
):
140 "Turns a list of bytes into a string"
143 return pack('%sB' % len(value
), *value
)
147 if __name__
== '__main__':
149 # print to7bits(0, 3)
150 # print to7bits(127, 3)
151 # print to7bits(255, 3)
152 # print to7bits(65536, 3)
156 # print 'getHiLoHex', getNibbles(16)
157 # print 'setHiLoHex', setNibbles(1,0)
159 # print 'readBew', readBew('aáâã')
160 # print 'writeBew', writeBew(1642193635, 4)
162 # print 'varLen', varLen(1)
164 print 'readVar', readVar('\80@')
165 print 'writeVar', writeVar(8192)
167 print 'readVar', readVar('áâãa')
168 print 'writeVar', writeVar(205058401)
170 # vartest = '\x82\xF7\x80\x00'
171 # print 'toBytes', toBytes(vartest)
172 # print 'fromBytes', fromBytes([48, 49, 50,])
175 # instr = '\xFF\xFF\xFF\x00'
176 # print 'readVar', readVar(instr)
179 # print writeVar(inst2)
180 # print writeVar(readVar(instr))
183 print '%08X -' % s1
, '00', writeVar(s1
)
185 print '%08X -' % s2
, '40', writeVar(s2
)
187 print '%08X -' % s3
, '7F', writeVar(s3
)
189 print '%08X -' % s4
, '81 00', writeVar(s4
)
191 print '%08X -' % s5
, 'C0 00', writeVar(s5
)
193 print '%08X -' % s6
, 'FF 7F', writeVar(s6
)
195 print '%08X -' % s7
, '81 80 00', writeVar(s7
)
197 print '%08X -' % s8
, 'C0 80 00', writeVar(s8
)
199 print '%08X -' % s9
, 'FF FF 7F', writeVar(s9
)
201 print '%08X -' % s10
, '81 80 80 00', writeVar(s10
)
203 print '%08X -' % s11
, 'C0 80 80 00', writeVar(s11
)
205 print '%08X -' % s12
, 'FF FF FF 7F', writeVar(s12
)