By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,569 Members | 1,321 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,569 IT Pros & Developers. It's quick & easy.

problems with midi programming in python

P: n/a
Hi folks

I hope someone here might be able to help. I scavenged some info and
even code from the net and am trying to write a module that reads a text
file and spits out a midi file.

So far I managed to make it work to the level of reading a text file
with appropriate notes, octaves, transposing, volume, aftertouch,
polyphony, channeltouch etc.

However I am stuck at writing notes longer than 127 decimal number.

The code I am using is below. I didn't post the whole code to keep it
brief. If it is ok I will post the whole.

###########################################
def note_on(self, time, channel, note, velocity):
return varLen(time) + [0x90 + channel, note, velocity]

def varLen(value):
# Big endian variable byte word
# as defined by the midi standard
result = []
while value:
result.append((value & 0x7F) | 0x80)
value = value >7
if len(result) == 0:
return [0]
else:
result[len(result)-1] -= 128
result.reverse()
return result
#############################################

note_on should accept time,channel,note and velocity as decimals.

Note and velocity are not a problem as their numbers are small.

If I want to put a note that lasts say longer than 127, fluidsynth moans
saying unexpected eof or unexpected byte 0xfe.

What I would like to do is, to be able to
note_on(1500,1,60,120)
1500 being the problem.

Midi file standard says that time is written as a variable length
entity. so if 1500 does not fit in a byte it should then use as many
bytes as needed, but all bytes except last one have their msb set to 1
to show there is more to come.

Below is the output of mftext for a working and nonworking midi files
respectively.
############## playing a single 'a' note ############ working fine ###
Header format=1 ntrks=2 division=24
Track start
Time=0 Tempo, microseconds-per-MIDI-quarter-note=500000
Time=0 Time signature=4/4 MIDI-clocks/click=24
32nd-notes/24-MIDI-clocks=8
Time=0 Meta event, end of track
Track end
Track start
Time=0 Program, chan=1 program=1
Time=0 Note on, chan=1 pitch=57 vol=127
Time=127 Note off, chan=1 pitch=57 vol=0
Time=127 Meta event, end of track
Track end
################################################## ####

######### playing a single a note, with double the 127 duration##
########not working########################################### #
Header format=1 ntrks=2 division=24
Track start
Time=0 Tempo, microseconds-per-MIDI-quarter-note=500000
Time=0 Time signature=4/4 MIDI-clocks/click=24
32nd-notes/24-MIDI-clocks=8
Time=0 Meta event, end of track
Track end
Track start
Time=0 Program, chan=1 program=1
Time=0 Note on, chan=1 pitch=57 vol=127
Error: unexpected byte: 0xfe
################################################## #######

What am I doing wrong!!!!!!

Help appreciated.
ta
sree
Jul 5 '06 #1
Share this Question
Share on Google+
4 Replies


P: n/a
sreekant wrote:
Hi folks

I hope someone here might be able to help. I scavenged some info and
even code from the net and am trying to write a module that reads a text
file and spits out a midi file.

So far I managed to make it work to the level of reading a text file
with appropriate notes, octaves, transposing, volume, aftertouch,
polyphony, channeltouch etc.

However I am stuck at writing notes longer than 127 decimal number.

The code I am using is below. I didn't post the whole code to keep it
brief. If it is ok I will post the whole.

###########################################
def note_on(self, time, channel, note, velocity):
return varLen(time) + [0x90 + channel, note, velocity]

def varLen(value):
# Big endian variable byte word
# as defined by the midi standard
result = []
while value:
result.append((value & 0x7F) | 0x80)
value = value >7
if len(result) == 0:
return [0]
else:
result[len(result)-1] -= 128
result.reverse()
return result
#############################################

note_on should accept time,channel,note and velocity as decimals.

Note and velocity are not a problem as their numbers are small.

If I want to put a note that lasts say longer than 127, fluidsynth moans
saying unexpected eof or unexpected byte 0xfe.

What I would like to do is, to be able to
note_on(1500,1,60,120)
1500 being the problem.

Midi file standard says that time is written as a variable length
entity. so if 1500 does not fit in a byte it should then use as many
bytes as needed, but all bytes except last one have their msb set to 1
to show there is more to come.

Below is the output of mftext for a working and nonworking midi files
respectively.
############## playing a single 'a' note ############ working fine ###
Header format=1 ntrks=2 division=24
Track start
Time=0 Tempo, microseconds-per-MIDI-quarter-note=500000
Time=0 Time signature=4/4 MIDI-clocks/click=24
32nd-notes/24-MIDI-clocks=8
Time=0 Meta event, end of track
Track end
Track start
Time=0 Program, chan=1 program=1
Time=0 Note on, chan=1 pitch=57 vol=127
Time=127 Note off, chan=1 pitch=57 vol=0
Time=127 Meta event, end of track
Track end
################################################## ####

######### playing a single a note, with double the 127 duration##
########not working########################################### #
Header format=1 ntrks=2 division=24
Track start
Time=0 Tempo, microseconds-per-MIDI-quarter-note=500000
Time=0 Time signature=4/4 MIDI-clocks/click=24
32nd-notes/24-MIDI-clocks=8
Time=0 Meta event, end of track
Track end
Track start
Time=0 Program, chan=1 program=1
Time=0 Note on, chan=1 pitch=57 vol=127
Error: unexpected byte: 0xfe
################################################## #######

What am I doing wrong!!!!!!

Help appreciated.
ta
sree
Here's a snippit which does work:

def intToVarNumber(x):
""" Convert INT to a variable length MIDI value. """

lst = chr(x & 0x7f)
while 1:
x = x >7
if x:
lst = chr((x & 0x7f) | 0x80) + lst
else:
return lst

See my program MMA for lots of ugly tricks.
http://users.xplornet.com/~bvdp/mma

Best,

Jul 5 '06 #2

P: n/a
Not related to your actual question, but note:
if len(result) == 0:
empty lists test as False, so this can just be
if not result:


and
result[len(result)-1] -= 128
you can index lists with negative ints, backwards from the end of the
list, so this can be
result[-1] -= 128

Those are two of my favorite things about python. :-)
Peace,
~Simon

Jul 6 '06 #3

P: n/a
Total godsend. Had to reverse the list but now it works perfectly.

Not only it solved the problem of longer notes but also that of rests.

If you don't terribly mind, during the development of this particular
program , I would love to ask for help.

If that is ok with you, please reply to
sreekant UNDER_SCORE At Yahoo DhoTT Com

Thanks
sree
Here's a snippit which does work:

def intToVarNumber(x):
""" Convert INT to a variable length MIDI value. """

lst = chr(x & 0x7f)
while 1:
x = x >7
if x:
lst = chr((x & 0x7f) | 0x80) + lst
else:
return lst

See my program MMA for lots of ugly tricks.
http://users.xplornet.com/~bvdp/mma

Best,
Jul 6 '06 #4

P: n/a
Simon Forman wrote:
Not related to your actual question, but note:
> if len(result) == 0:

empty lists test as False, so this can just be
> if not result:

and
> result[len(result)-1] -= 128

you can index lists with negative ints, backwards from the end of the
list, so this can be
> result[-1] -= 128


Those are two of my favorite things about python. :-)
Peace,
~Simon
I love python. However, not so shamefully, the above isn't my code. I am
not that good :-(

I scavenged most of the bit shifting code from the net. I am ok with
most of the data structures but bit shifting flies past my head, too far
above.

Ta
sree
Jul 6 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.