problems with midi programming in python

S

sreekant

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
 
B

bvdp

sreekant said:
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,
 
S

Simon Forman

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
 
S

sreekant

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
 
S

sreekant

Simon said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top