Object to calculate swing


#1

This is part of an ongoing process to build a series of patterns that are useful for ‘groovebox’ style patterns. This is for a root pattern that provides bar/beat/time awareness for it’s children. As part of that obviously I wanted to make sure swing is supported, so I’ve been working on that. This isn’t the actual code (still working on that), but wanted to share the prototype object that calculates whether ‘swing’ duration for the current beat in case people find it useful (this value is then used to update the duration in the event that is sent to the server):

(~swing = (\calcNewBeat : {|self, beat, dur, remainingDur| beat + (dur - remainingDur)},
  \swingBeatPos : {|self, currBeat, swingBase| currBeat - currBeat.trunc( 2 * swingBase)},
  \adjFstBeat : {|self, dur, swingAmount| dur * 2 * swingAmount},
  \adjSndBeat : {|self, dur, swingAmount| dur * 2 * (1 - swingAmount)},
  \calcSwingDur : {|self,dur, currBeat, swingAmount, swingBase| 
    var lower, higher;
    lower = min(dur, max(0, 0.5 - self.swingBeatPos(currBeat, swingBase)));
    higher = max(0, (dur-lower).clip2(0.5));
    [self.adjFstBeat(lower, swingAmount) + self.adjSndBeat(higher, swingAmount), lower+higher];
  },
  \calcNonSwingDur : {|self, dur, currBeat, swingBase| 
    min(dur, 1 - self.swingBeatPos(currBeat, swingBase));
  },
  \atSwingBeatStart : {|self,beat, swingBase| beat % (2 * swingBase) == 0},
  \isSwingBeat : {|self, dur, swingBase, swingThreshold| 
    if (dur >= (2 * swingBase)){
      false
    }{
      if (dur absdif: swingBase <= swingThreshold)
      {
        true;
      }{
        false
      }
    };
  },
  
  \onSwingBeat : false,
  
  \swingEvent : {|self, currBeat, dur, swingBase=0.5, swingAmount=0.7, swingThreshold=0.0|
    
    var remainingDur = dur;
    var swingDur = 0;
        
    while({remainingDur.round(0.001) > 0.0},{
      if(self.atSwingBeatStart(currBeat, swingBase))
      {
        self.onSwingBeat = self.isSwingBeat(remainingDur.round(0.001), swingBase, swingThreshold);
      };
      
      if(self.onSwingBeat){
        var actualSwingDur, logicalDur;
        # actualSwingDur, logicalDur = self.calcSwingDur(remainingDur, currBeat, swingAmount, swingBase);
        remainingDur = remainingDur - logicalDur;
        swingDur = swingDur + actualSwingDur;
        logicalDur.postln;
        currBeat = currBeat + logicalDur;
      }{
        var logicalDur = self.calcNonSwingDur(remainingDur, currBeat, swingBase);
        remainingDur = remainingDur - logicalDur;
        swingDur = logicalDur + swingDur;
        currBeat = currBeat + logicalDur;
      };
      
    });
    currBeat.postln;
    self.beat = currBeat;
    
    swingDur;
  }
)
)

#2

Incidentally I tend not to use this style of code for finished stuff, but I find it useful when I’m developing code.


#3

There has been an old thread on this back in 2013:

https://www.listarc.bham.ac.uk/lists/sc-users-2013/msg26689.html

You could also have a look at James’ suggestion, this was quite appreciated then:

https://www.listarc.bham.ac.uk/lists/sc-users-2013/msg26761.html


#4

… well, this was in the same thread, there have been some older appraoches I was refering to via nabble, but I can’t find them at the moment.


#5

Yeah I’ve looked at those before, but they always had issues for me that meant that they weren’t 100% reliable. This works for my purposes, but that’s partly because I’m attacking this problem from a different angle. The code is here:

with some rough (mostly for my own memory) documentation here:

This is still in progress, so don’t expect it to work atm (this is still not tested). But it’s basically a way of creating beat/swing aware pbinds.


#6

Just seen that James has included this in the Pattern Guide also:

http://doc.sccode.org/Tutorials/A-Practical-Guide/PG_Cookbook08_Swing.html