Play Along is a very simple python tool for helping synchronise jam band performances.

The bottom left, shows the current bar (root note and scale) while the bottom-right shows the next bar to give some warning of what to play next.

Simply adjust the progression to whatever you wish and run; feel free to change the BPM or beats per bar.

Pygame Dependency

playalong.py on it’s default configuration (12 bar blues, quick to four, 7ths only before a key change)
from __future__ import division
import pygame, sys
from pygame.locals import *
from time import time
pygame.font.init()
myfont = pygame.font.SysFont('Arial', 30)
W,H=600,400
resolution=W,H
BGCOL=(128,128,128)

def twelve(N1="C",N2="F",N3="G",quicktofour=True,allseven=True,scale=" blues scale"):
    C1,C2,C3=[x+"7" for x in [N1,N2,N3]]
    if allseven:
        return [(C1,N1+scale),(C2,N2+scale) if quicktofour else (C1,N1+scale),(C1,N1+scale),(C1,N1+scale),
                (C2,N2+scale),(C2,N2+scale),(C1,N1+scale),(C1,N1+scale),
                (C3,N3+scale),(C2,N2+scale),(C1,N1+scale),(C3,N3+scale)]
    else:
        return [(N1,N1+scale),(N2,N2+scale) if quicktofour else (N1,N1+scale),(N1,N1+scale),(C1,N1+scale),
                (N2,N2+scale),(C2,N2+scale),(N1,N1+scale),(C1,N1+scale),
                (C3,N3+scale),(C2,N2+scale),(C1,N1+scale),(C3,N3+scale)]
#Remove the hash on desired progression only(#)
#progression=[("C","C Major"),("G","G Major"),("Am","A Minor"),("F","F Major")]###POP PROGRESSION 1
#progression=[("C","C Major"),("Dm","D Minor"),("Am","A Minor"),("G","G Major")]###POP PROGRESSION 2
#progression=twelve(scale="Mixo-Blues")#12 Bar Blues All 7ths mixo-blues(hybrid)
progression=twelve(scale="minor pentatonic",allseven=False)#12 Bar Blues Minor Pentatonic
BeatsPerMinute=120
BeatsPerBar=4
BarsPerMinute=BeatsPerMinute*1.0/BeatsPerBar
SecondsPerBar=60/BarsPerMinute

def currenttime():
    current=time()
    relative=current-start
    return (int(relative/SecondsPerBar),(relative%SecondsPerBar)/SecondsPerBar)
    
def drawscreen(DISPLAY):#currentchord,nextchord,currentscale,nextscale
    DISPLAY.fill(BGCOL)
    pygame.draw.rect(DISPLAY,(0,0,0),(25,25,550,275))
    Bar,Pos=currenttime()
    Bar=Bar-1
    
    linex=25+Pos*550
    for i in range(1,4):
        x=25+i/4.0*550
        pygame.draw.line(DISPLAY,(128,128,128),(x,25),(x,300),width=2)
    pygame.draw.line(DISPLAY,(255,255,255),(linex,25),(linex,300),width=6)
    #beat3
    #beat4
    if Bar>=0:
        textsurfacel1 = myfont.render(progression[Bar%len(progression)][0], False, (255,255,255))
        textsurfacer1 = myfont.render(progression[(Bar+1)%len(progression)][0], False, (255,255,255))
        textsurfacel2 = myfont.render(progression[Bar%len(progression)][1], False, (255,255,255))
        textsurfacer2 = myfont.render(progression[(Bar+1)%len(progression)][1], False, (255,255,255))        
        DISPLAY.blit(textsurfacel1,(0,300))
        DISPLAY.blit(textsurfacer1,(460,300))
        DISPLAY.blit(textsurfacel2,(0,350))
        DISPLAY.blit(textsurfacer2,(460,350))
    else:
        textsurface = myfont.render("STARTS ON "+progression[0][1], False, (255,255,255))        
        DISPLAY.blit(textsurface,(0,300))
        
        
start=time()
def main():
    global start
    pygame.init()
    DISPLAY=pygame.display.set_mode(resolution,0,32)
    start=time()
    while True:
        for event in pygame.event.get():
            if event.type==QUIT:
                pygame.quit()
                sys.exit()
        drawscreen(DISPLAY)
        pygame.display.update()
main()    
Back to top