Kara-Moon Forum
April 20, 2024, 01:03:46 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: You can go back to the main site here: Kara-Moon site
 
   Home   Help Search Login Register  
Pages: 1 [2]
  Print  
Author Topic: code for patPlectrum.py: A realistic guitar sound  (Read 24380 times)
bvdp
Kara-Moon Master
****
Posts: 1437


WWW
« Reply #15 on: January 02, 2010, 10:05:07 PM »

Ahh, I see the offset problem. This should fix that:

    def doMidiClear(self):
        """ Reset MIDI settings, special hook for stopping strings. """
 
        if self.channel != -1:
            self.grooveFinish(gbl.QperBar * gbl.BperQ)
        PC.doMidiClear(self)

This passes the current end of the bar offset. Then the addNote..() figures the current offset from that.

Seems to be working fine here, now.

Leaving the noteName..() in the plectrum file is fine. Nothing else is calling it.

Look forward to the next installment!
Logged

My online life: http://www.mellowood.ca
louisjb
Jr. Member
*
Posts: 16


« Reply #16 on: January 02, 2010, 11:39:31 PM »

Attached is the latest patPlectrum

No quite right Bob you need to do the following:

  def doMidiClear(self):
        """ Reset MIDI settings, special hook for stopping strings. """
 
        if gbl.mtrks[self.channel].channel != -1:
            self.grooveFinish(0)
        PC.doMidiClear(self)


self.channel has a value of 0 zero, but gbl.mtrks[self.channel].channel has a value of -1 very confusing.


Also passing a offset of zero to self.grooveFinish(0) put the notes off in the right place.


I have also found a BUG with MMA in that it puts the note off (a note on with v=0) on the wrong channel. Please see MMA_CHANNEL_BUG.zip attached.

Louis


* patPlectrum.3.zip (2.94 KB - downloaded 417 times.)
* MMA_CHANNEL_BUG.zip (1.45 KB - downloaded 412 times.)
Logged
bvdp
Kara-Moon Master
****
Posts: 1437


WWW
« Reply #17 on: January 03, 2010, 02:05:54 AM »

Oh, let me clear up 2 things.

the test should be

    def doMidiClear(self):
        """ Reset MIDI settings, special hook for stopping strings. """
 
        if self.channel:
            self.grooveFinish(0)
        PC.doMidiClear(self)

MIDI channels are assigned to self.channel as needed. When a Mtrk() is created the channel number is passed and that is saved, -1, as the midi channel. self.channel is 1-16, the mtrk value is 0-15.

All my fault in suggesting to use -1 in the first place.

The offset I gave was for the end of the current bar. You're right that it should be 0, which is the start of the current bar. Confusion here is that mma keeps track of the current bar TOTAL offset in gbl.tickOffset (which I used originally). But, the routine you're calling is based on the current bar and an offset into that.

Anyway, this should work now.

I will have a look at the other bug. Probably in the morning. Will let you know what's going on. I'm sure there is more that one bug still in MMA!!!!

Best.
Logged

My online life: http://www.mellowood.ca
bvdp
Kara-Moon Master
****
Posts: 1437


WWW
« Reply #18 on: January 03, 2010, 06:58:56 PM »

Okay, I'm flummoxed. I've spent the better part of the morning trying to trace down the problem with all notes not being turned off. I've finally rewritten

Code:
    # endAllVibrations (ie output all outstanding note off)
    def grooveFinish(self, offset):
        print "grooveFinish offset=", getOffset(offset), "Name", self.name, "self.channel=", self.channel, "OnNotes",
        for s in self._vibrating:
            print s.note,
        print

        if not self.channel:
            return

        for stringNo in range(len(self._vibrating)):
            self.endVibration(stringNo, offset)

I don't think the problem is with MMA. Rather it appears that your code in not updating the table listing the ON notes properly.

But, I've looked at that as well. Right now I just don't see it.

Maybe you can have a look as well. But, in the "Fail" file the single note is not being turned off. Here's a cutting from the midi file via mf2t:

MTrk
0 Meta TrkName "Plectrum-Strumminga"
768 PrCh ch=15 p=25
768 On ch=15 n=43 v=90
768 Meta TrkEnd
TrkEnd

Which confirms the debugging code I added to grooveFinish().

Your turn Smiley
Logged

My online life: http://www.mellowood.ca
bvdp
Kara-Moon Master
****
Posts: 1437


WWW
« Reply #19 on: January 03, 2010, 08:42:34 PM »

I think I found it. It's the problem with python and arrays. Kicks me all the time!

Here's the first few lines of your code which now work:

Code:

class Plectrum(PC):
    """ Pattern class for a Raw MIDI track. """


    vtype = 'PLECTRUM'
    # We have vibrating strings (a string in python refers to text not a guitar string)
    #_vibrating = []
    #_tuning = []
    #capoFretNo = 0  # The number that the capo is on (0 for open strings)

    def __init__(self, nm):
        PC.__init__(self, nm)
       
        self._vibrating = []
        self._tuning = []
        self.capoFretNo = 0  # The number that the capo is on (0 for open strings)
        self.setTuning("e-- a-- d- g- b- e")

Also, I'd like to change this:

Code:
   def setTuning (self, stringPitchNames):
        """ for standard guitar tuning use setTuning("e-- a-- d- g- b- e") """

        #clear the old tuning
        #del self._tuning[:]
        #del self._vibrating[:]
        self.tuning=[]
        self._vibration=[]

        for pitchName in stringPitchNames.split():
            self.addString(pitchName)


Testing appears to show that this now works Smiley Let me know.
Logged

My online life: http://www.mellowood.ca
louisjb
Jr. Member
*
Posts: 16


« Reply #20 on: January 03, 2010, 10:55:01 PM »

I have changed parse.py and pat.py (and patPlectrum.pat) to get TUNING and CAPO working. just in case you are working on the same thing. but the code is not ready yet.

It might be easier to put your code on subversion. which would make all this much easier. I use sourceForge to host my code.

Regarding the MIDI CHANNEL BUG. the missing Note off is not really missing but rather it has been sent out on the wrong channel. There is a extra note off on channel chan=16. Have you done a comparison between PlectrumTestFail.mma and PlectrumTestWork.mma.

Louis


Logged
bvdp
Kara-Moon Master
****
Posts: 1437


WWW
« Reply #21 on: January 04, 2010, 12:06:34 AM »


Let me know what you're doing on the pat.py and parse.py ... I assume that you're just adding some hooks/functions.

To store you'll also need to modify the ugly tables in pat.py.

Yes, I should use subversion, etc. Let's get this sorted out for now (the hard way) and then another step for me ... I've never used this.

Also, did you apply my patches from earlier. The reason your code wasn't working is that each instance of the guitar track was using the same array for the note storage. Creating the array in __init__() creates a different one for each track. Let me know if this doesn't make sense, or if I'm wrong. BTW, you'll get different results with different computers, etc. depending on how the arrays are/aren't allocated.
Logged

My online life: http://www.mellowood.ca
bvdp
Kara-Moon Master
****
Posts: 1437


WWW
« Reply #22 on: January 05, 2010, 06:34:55 PM »

I'm assuming the Louis is busy making his improvements. But, I had a bit of time today to play and create some real midi files using the plectrum code. I did have to make one change, to the getPgroup() function I had to add:
 
      a.duration = 1

to satisfy some other code. Not sure why it's working with the original test code ... but that is another matter.

Also, I re-tuned the guitar up an octave.

Remember, this is not ready for primetime yet. But, it is very close.

But, I managed to modify my bolero.mma code to use a plectrum track instead of the chord I was using. Changes in sound are subtle, but nice. I've attached 2 midi files. Sound difference should be obvious. Remember, all I changed was one track definition in the library.

Please give a listen and then send some nice comments to Louis!


* magic-is-the-moonlight-plectrum.mid (28.26 KB - downloaded 429 times.)
* magic-is-the-moonlight.mid (21.57 KB - downloaded 421 times.)
Logged

My online life: http://www.mellowood.ca
louisjb
Jr. Member
*
Posts: 16


« Reply #23 on: January 05, 2010, 10:43:05 PM »

Hi Bob,

Thanks for your kind words in your previous post

Ok here is my latest offering.

I have included all the files I have changed since I started (so others can just drop the .py files over the files in MMA from version mma-bin-1.5b) bob this time I have only changed pat.py and parse.py/

Tuning and capo commands now work unlike a real guitar you can have a negative capo value which makes the guitar neck longer! I have improved the chord shape algorithm and improved the chord shape debug print.

i have also allowed some short cut on the Plectrum patterns (I like that name now) so

n-m:v  where n is the start string number and m is the end string number and v is the volume so

"1.0 0 2:50" is the same as ""1.0 0 - - - - 50 -"

"1.0 -5 2-4:80" is the same as ""1.0 -5 - - 80 80 80 -"

"1.0 +5 :90" is the same as ""1.0 +5 90 90 90 90 90 90"

This makes putting in guitar finger picking patterns really easy.

Bob I have made the changes in your previous post (sorry I did not read it properly the first time round). It all seems to work pretty well now. There are just a few minor issues that need to be sorted out but that wait a few days now.

I think we should start a new thread and start collecting up different strumming and finger picking patterns that sound as much like a real guitar as possible. I would be interested to here what others can do.

Oops, I nearly forgot the attachment!

Louis 

* patPlectrum4.zip (44.78 KB - downloaded 424 times.)
Logged
bvdp
Kara-Moon Master
****
Posts: 1437


WWW
« Reply #24 on: January 06, 2010, 01:51:07 AM »

Okay. Getting late here too, so I'll have to look at the new code tomorrow.

A couple of points came up when I was doing the bolero thing this morning:

1. I think that you should honor the Octave setting. Set the neck patterns to be zero based and then add the current octave setting to them. Easy that way to do silly things like a 5 string, strumming bass guitar. Seriously, it does make it easier to make 1+ or 1- changes.

2. Do you need a strum variable in the sequence definition? There already is a strum setting. I suppose that the way you have it set you could have a different value for each pattern in a sequence, but I wonder it that'll be an issue?

3. The .duration setting is needed by the documentation routines, esp. for drawing the little graphs. We can just stick in a dummy value, but I'm not sure what to do for the graphs? Would be nice to have it calculated to "fill out the bar" somehow. Not sure how that would work.

4. And could we add a defualt to setting code? I'm thinking that if you have (your example from above):

 1.0 +5 90 90 90 90 90 90

the parser should be able to handle 

  1.0 +5 90

and fill the remaining strings with 90.

Same for a "-".

Okay?

I'll let you know tomorrow on the current changes.

Thanks for the time on this. I'll have to start some docs later this week to keep pace with you!

Later,
« Last Edit: January 06, 2010, 01:53:45 AM by bvdp » Logged

My online life: http://www.mellowood.ca
bvdp
Kara-Moon Master
****
Posts: 1437


WWW
« Reply #25 on: January 06, 2010, 07:02:22 PM »

A few minor changes:

in pat.py I've changed 2 functions as follows. Just to generate proper error messages:

Code:
    def setPlectrumTuning(self, ln):
        """ This method does nothing in the base class but it is
            overriden in the derived class"""
       
        error("TUNING not permitted in %s tracks." % self.vtype)


    def setPlectrumCapo(self, ln):
        """ This method does nothing in the base class but it is
            overriden in the derived class"""

        error("CAPO not permitted in %s tracks." % self.vtype)


in patPlectrum.py

Code:
   def getPgroup(self, ev):
        """ Get group for rawmid pattern.

            Fields - start, length, note, volume

        """

        if len(ev) < 3:  # we need offset, strum and at least one pattern
            error("There must be n groups of 3 or more in a pattern definition, "
                  "not <%s>" % ' '.join(ev) )
       
        a = struct()
        a.duration = 0   # this is a dummy value to keep docs happy
        a.offset   = self.setBarOffset(ev[0])
        a.strum = stoi(ev[1], "Strum in Plectrum definition not int")

        self.decodePlectrumPatterns(a, ev[2:] )

        return a

This is a error catcher for args, and sets the duration.

I think we can avoid some calls in parse.py for the new functions. I'll look at that later.

Also, we need some storage for the neck setups (cappo and tuning) in pat.py. And we need to decide if the cappo and tuning settings are global (ie forever, regardless of groove), per bar or per sequence. I'd suggest that we treat them just like anything else in mma and have the option to have them saved in grooves. But, I really don't see a need to have different settings for each bar in a sequence (plus, that does complicate the parser a bit) ... mind you, we can do that for just about every other setting so why not for this as well?? Comments?

I'm thinking that a merge with my main source tree is getting very close. I'd like to get the minor things figured out, then I can write some docs and do the merge. At that point I'll put up a new devel release and wait for comments?

Okay?
Logged

My online life: http://www.mellowood.ca
louisjb
Jr. Member
*
Posts: 16


« Reply #26 on: January 06, 2010, 10:53:16 PM »

Ok bob,

Here is may latest offering. I think i have completed everything that I want to do with it now. Including improving the chord shape algorithm. It now tries to put the 7th or the top note any chord with four notes up nearest to the top string. previously it just search for the notes nearest the guitar nut . I have got the + - prefix working on the chords. see:

Code:

            chordBarreFretNo = 0
            if ct.name.startswith('+'):
                chordBarreFretNo = 12
            if ct.name.startswith('-'):
                chordBarreFretNo = -12
produces this
Code:
     Plectrum  +C  chord  [12, 16, 19]
    64 | - - - - - - - - - - - * - - - - - - - 1  76
    59 | - - - - - - - - - - - : * - - - - - - 0  72
    55 | - - - - - - - - - - - * - - - - - - - 2  67
    50 | - - - - - - - - - - - : - * - - - - - 1  64
    45 | - - - - - - - - - - - : - - * - - - - 0  60
    40 | - - - - - - - - - - - * - - - - - - - 1  52


       Plectrum  -D  chord  [-10, -6, -3]
    64 : - * - - - - - - - - - | - - - - - - - - - - - - - - - - - - - 1  54
    59 : - - * - - - - - - - - | - - - - - - - - - - - - - - - - - - - 0  50
    55 : - * - - - - - - - - - | - - - - - - - - - - - - - - - - - - - 2  45
    50 * - - - - - - - - - - - | - - - - - - - - - - - - - - - - - - - 0  38
    45 * - - - - - - - - - - - | - - - - - - - - - - - - - - - - - - - 2  33
    40 : - * - - - - - - - - - | - - - - - - - - - - - - - - - - - - - 1  30



I would still like to have the ability to put in barred guitar codes as my code already handles it.  Guitarist often move up the fret board when playing.

Maybe we could use something like "Gmaj:barre5" which is preferable to "^5Gmaj" that I suggested earlier. All your other patterns would ignore the everything after and including the trailing ':'. Please note there is no transposing here it is still a Gmaj chord (but played using a different chord shape further up the neck.)

So my code is finished now the only thing I can thing that I can think of that is outstanding is handling very wide strums values like 150 and so the notes overlap a the next and previous strum. I have tested and it seems to cause no major problems. so it is Ok to merge now. Please make all your suggested changes first to PLECTRUM as I have not done so.

Answering you points Capo and tuning should be stored like everything else in mma. I think I implemented this when I changed pat.py and parse.py.

bob>1. I think that you should honor the Octave setting.

I think this will only add confusion as we can change the pitch with tuning and also the capo settings (
octave can be achieved with a +12 or a -12 capo (yes negative capos  are allowed) using the OCTIVE variable should in my opinion print a warning when attempted.

bob> 2. Do you need a strum variable.

No I think the strum variable should be disallowed with plectrum to avoid confusion  (print a warning when attempted).

bob> the parser should be able to handle "1.0 +5 90"

Done

Please be a aware that doing a "1.0 +5 90" causes half the notes to be played BEFORE the beat. (I think you send a program change on the beat when starting up a new groove. so the first few notes may be played as a piano sound.)

Finally I think we could drop the trailing \ at the end of each line. I don't think it is needed when the { and } mark the beginning and end of the of the sequence.

By the way I really like that magic-is-the-moonlight-plectrum.mid, it really fills out the whole sound now. It is great hear my code working for real. (By the way perhaps it could do with some "up strums" to sound more natural - unless that was an effect you deliberately intended)

Louis


 

* patPlectrum.5.py.zip (4.16 KB - downloaded 423 times.)
Logged
bvdp
Kara-Moon Master
****
Posts: 1437


WWW
« Reply #27 on: January 08, 2010, 10:17:00 PM »

Louis and I have taken this discussion private ... a tad quicker for both of us.

Here's the schedule on this:

 1. We're doing some code cleanup and just plain old "making sure it works". No new features.
 2. I'll write some docs which I'm sure will take us back to (1)
 3. Once the docs and code have settled down, I'll modify some of the existing grooves to
     take advantage of the plectrum tracks. This will be limited to things using guitars and banjos.
     I have to be careful since we don't want to change existing grooves, just enhance them. And,
     I hope we don't go back to (1) too many times Smiley
 4. We'll do a devel release. I'm hoping to do this by the end of January or very early in Feb.
 
After that point we've got a few enhancements planned. Major one being able to specify capo settings on a per chord basis.

And, then I hope we can do a 1.6 release in the early spring.

Comments and suggestions are welcome!
Logged

My online life: http://www.mellowood.ca
bvdp
Kara-Moon Master
****
Posts: 1437


WWW
« Reply #28 on: February 15, 2010, 12:26:51 AM »

Just to be neat and tidy, this thread has been very useful! A new version of mma is the result! Don't forget to check the new examples page at

   http://mellowood.ca/mma/examples.html
Logged

My online life: http://www.mellowood.ca
Pages: 1 [2]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.055 seconds with 19 queries.