problems with midi programming in python

Discussion in 'Python' started by sreekant, Jul 6, 2006.

  1. sreekant

    sreekant Guest

    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
    sreekant, Jul 6, 2006
    #1
    1. Advertising

  2. sreekant

    Guest

    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 6, 2006
    #2
    1. Advertising

  3. sreekant

    Simon Forman Guest

    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
    Simon Forman, Jul 6, 2006
    #3
  4. sreekant

    sreekant Guest

    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,
    >
    sreekant, Jul 6, 2006
    #4
  5. sreekant

    sreekant Guest

    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
    sreekant, Jul 6, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Hugo Villeneuve

    Java MIDI output device to MIDI Yoke.

    Hugo Villeneuve, Jul 4, 2003, in forum: Java
    Replies:
    0
    Views:
    939
    Hugo Villeneuve
    Jul 4, 2003
  2. CazT
    Replies:
    1
    Views:
    909
    Doug Schwartz
    Mar 3, 2004
  3. Michael
    Replies:
    6
    Views:
    376
    Kevin Buffardi
    Oct 28, 2003
  4. Gilly
    Replies:
    6
    Views:
    425
    Ken Starks
    May 4, 2008
  5. Asbjørn Bjørnstad
    Replies:
    0
    Views:
    433
    Asbjørn Bjørnstad
    Oct 9, 2008
Loading...

Share This Page