problems with midi programming in python

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • sreekant

    #1

    problems with midi programming in python

    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,no te 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
  • bvdp@xplornet.com

    #2
    Re: problems with midi programming in python

    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,no te 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.


    Best,

    Comment

    • Simon Forman

      #3
      Re: problems with midi programming in python

      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

      Comment

      • sreekant

        #4
        Re: problems with midi programming in python

        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.

        >
        Best,
        >

        Comment

        • sreekant

          #5
          Re: problems with midi programming in python

          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

          Comment

          Working...