Package echonest :: Package remix :: Package support :: Package midi :: Module DataTypeConverters
[hide private]
[frames] | no frames]

Source Code for Module echonest.remix.support.midi.DataTypeConverters

  1  # -*- coding: ISO-8859-1 -*-
 
  2  
 
  3  from struct import pack, unpack 
  4  
 
  5  """
 
  6  This module contains functions for reading and writing the special data types
 
  7  that a midi file contains.
 
  8  """ 
  9  
 
 10  """
 
 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
 
 14  """ 
 15  
 
 16  
 
 17  
 
18 -def getNibbles(byte):
19 """ 20 Returns hi and lo bits in a byte as a tuple 21 >>> getNibbles(142) 22 (8, 14) 23 24 Asserts byte value in byte range 25 >>> getNibbles(256) 26 Traceback (most recent call last): 27 ... 28 ValueError: Byte value out of range 0-255: 256 29 """ 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)
33 34
35 -def setNibbles(hiNibble, loNibble):
36 """ 37 Returns byte with value set according to hi and lo bits 38 Asserts hiNibble and loNibble in range(16) 39 >>> setNibbles(8, 14) 40 142 41 42 >>> setNibbles(8, 16) 43 Traceback (most recent call last): 44 ... 45 ValueError: Nible value out of range 0-15: (8, 16) 46 """ 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
50 51 52
53 -def readBew(value):
54 """ 55 Reads string as big endian word, (asserts len(value) in [1,2,4]) 56 >>> readBew('aáâã') 57 1642193635L 58 >>> readBew('aá') 59 25057 60 """ 61 return unpack('>%s' % {1:'B', 2:'H', 4:'L'}[len(value)], value)[0]
62 63
64 -def writeBew(value, length):
65 """ 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)) 69 25057 70 >>> readBew(writeBew(1642193635L, 4)) 71 1642193635L 72 """ 73 return pack('>%s' % {1:'B', 2:'H', 4:'L'}[length], value)
74 75 76 77 """ 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. 82 """ 83 84
85 -def readVar(value):
86 """ 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 91 >>> readVar('€@') 92 64 93 >>> readVar('áâãa') 94 205042145 95 """ 96 sum = 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 100 return sum
101 102 103
104 -def varLen(value):
105 """ 106 Returns the the number of bytes an integer will be when 107 converted to varlength 108 """ 109 if value <= 127: 110 return 1 111 elif value <= 16383: 112 return 2 113 elif value <= 2097151: 114 return 3 115 else: 116 return 4
117 118
119 -def writeVar(value):
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)
125 126
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)] 130 bytes.reverse() 131 return bytes
132 133
134 -def toBytes(value):
135 "Turns a string into a list of byte values" 136 return unpack('%sB' % len(value), value)
137 138
139 -def fromBytes(value):
140 "Turns a list of bytes into a string" 141 if not value: 142 return '' 143 return pack('%sB' % len(value), *value)
144 145 146 147 if __name__ == '__main__': 148 149 # print to7bits(0, 3) 150 # print to7bits(127, 3) 151 # print to7bits(255, 3) 152 # print to7bits(65536, 3) 153 154 # simple test cases 155 156 # print 'getHiLoHex', getNibbles(16) 157 # print 'setHiLoHex', setNibbles(1,0) 158 # 159 # print 'readBew', readBew('aáâã') 160 # print 'writeBew', writeBew(1642193635, 4) 161 # 162 # print 'varLen', varLen(1) 163 # 164 print 'readVar', readVar('€@') 165 print 'writeVar', writeVar(8192) 166 167 print 'readVar', readVar('áâãa') 168 print 'writeVar', writeVar(205058401) 169 # 170 # vartest = '\x82\xF7\x80\x00' 171 # print 'toBytes', toBytes(vartest) 172 # print 'fromBytes', fromBytes([48, 49, 50,]) 173 174 175 # instr = '\xFF\xFF\xFF\x00' 176 # print 'readVar', readVar(instr) 177 # inst2 = 268435455 178 # print inst2 179 # print writeVar(inst2) 180 # print writeVar(readVar(instr)) 181 182 s1 = 0x00000000 183 print '%08X -' % s1, '00', writeVar(s1) 184 s2 = 0x00000040 185 print '%08X -' % s2, '40', writeVar(s2) 186 s3 = 0x0000007F 187 print '%08X -' % s3, '7F', writeVar(s3) 188 s4 = 0x00000080 189 print '%08X -' % s4, '81 00', writeVar(s4) 190 s5 = 0x00002000 191 print '%08X -' % s5, 'C0 00', writeVar(s5) 192 s6 = 0x00003FFF 193 print '%08X -' % s6, 'FF 7F', writeVar(s6) 194 s7 = 0x00004000 195 print '%08X -' % s7, '81 80 00', writeVar(s7) 196 s8 = 0x00100000 197 print '%08X -' % s8, 'C0 80 00', writeVar(s8) 198 s9 = 0x001FFFFF 199 print '%08X -' % s9, 'FF FF 7F', writeVar(s9) 200 s10 = 0x00200000 201 print '%08X -' % s10, '81 80 80 00', writeVar(s10) 202 s11 = 0x08000000 203 print '%08X -' % s11, 'C0 80 80 00', writeVar(s11) 204 s12 = 0x0FFFFFFF 205 print '%08X -' % s12, 'FF FF FF 7F', writeVar(s12) 206