Skip to content

Commit

Permalink
beat detection in sequence editor
Browse files Browse the repository at this point in the history
  • Loading branch information
dfaker committed Jun 23, 2023
1 parent c4538b7 commit 5a96974
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 31 deletions.
10 changes: 8 additions & 2 deletions src/cutselectionUi.py
Original file line number Diff line number Diff line change
Expand Up @@ -850,8 +850,14 @@ def playbackSpeedCallback(self, *args):

def dragPreviewPosCallback(self, *args):
try:
value = float(self.dragPreviewPosVar.get())
self.frameTimeLineFrame.setDragPreviewPos(value)
value = self.dragPreviewPosVar.get()
mode = 'abs'
if '%' in value:
value = value.strip().replace('%','')
mode = 'percent'
value = float(value)

self.frameTimeLineFrame.setDragPreviewPos(value,mode)
except Exception as e:
logging.error('Exception dragPreviewPosCallback',exc_info=e)

Expand Down
155 changes: 135 additions & 20 deletions src/modalWindows.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,27 @@

import mpv

import numpy as np

import re


def read_pgm(inbuffer, byteorder='>'):
buffer = inbuffer[::]
try:
header, width, height, maxval = re.search(
b"(^P6\s(?:\s*#.*[\r\n])*"
b"(\d+)\s(?:\s*#.*[\r\n])*"
b"(\d+)\s(?:\s*#.*[\r\n])*"
b"(\d+)\s(?:\s*#.*[\r\n]\s)*)", buffer).groups()
except AttributeError:
raise ValueError("Not a raw PGM file: '%s'" % filename)
return np.frombuffer(buffer,
dtype='u1' if int(maxval) < 256 else byteorder+'u2',
count=int(width)*int(height)*3,
offset=len(header)
).reshape((int(height), int(width), 3))

class AdvancedDropModal(tk.Toplevel):

def __init__(self, master=None, dataDestination=None, *args):
Expand Down Expand Up @@ -566,6 +587,9 @@ def __init__(self, uiParent=None, master=None, controller=None, sequencedClips=[

"Spectrum - Bass Boost Norm - Log:Log":"bass=g=3:f=110:w=0.6,showspectrumpic=s={width}x80:legend=0:fscale=log:scale=log",

"Spectrum - Bass Isolate - Log:Log":"acompressor=threshold=.5:ratio=5:2:attack=0.01:release=0.01,showspectrumpic=s={width}x80:legend=0:fscale=log:scale=log",


"Waves":"asplit[sa][sb],[sa]showwavespic=s={width}x80:colors=5C5CAE:filter=peak[pa],[sb]showwavespic=s={width}x80:colors=b8b8dc:filter=average[pb],[pa][pb]overlay=0:0",
"Waves - Middle pass filter":"asplit[sa][sb],[sa]showwavespic=s={width}x80:colors=5C5CAE:filter=peak[pa],[sb]highpass=f=200,lowpass=f=3000,showwavespic=s={width}x80:colors=b8b8dc:filter=average[pb],[pa][pb]overlay=0:0",
"Waves - Compressor":"asplit[sa][sb],[sa]showwavespic=s={width}x80:colors=5C5CAE:filter=peak[pa],[sb]acompressor=threshold=.5:ratio=5:2:attack=0.01:release=0.01,showwavespic=s={width}x80:colors=b8b8dc:filter=average[pb],[pa][pb]overlay=0:0",
Expand Down Expand Up @@ -633,14 +657,15 @@ def __init__(self, uiParent=None, master=None, controller=None, sequencedClips=[
self.columnconfigure(6, weight=1)
self.columnconfigure(7, weight=1)

self.columnconfigure(8, weight=1)



self.tickColours=["#a9f9b9","#7dc4ed","#f46350","#edc1a6","#dfff91","#0f21e0","#f73dc8","#8392db","#72dbb4","#cc8624","#88ed71","#d639be"]

self.player = mpv.MPV(loop='inf',
mute=False,
volume=0,
log_handler=print,
loglevel='debug',
autofit_larger='1280', wid=str(self.playerwid))

Expand Down Expand Up @@ -701,7 +726,13 @@ def __init__(self, uiParent=None, master=None, controller=None, sequencedClips=[
self.entrypostAudioOverrideDelay.grid(row=3,column=7,columnspan=2, sticky='ew')
self.entrypostAudioOverrideDelay.bind('<MouseWheel>',self.checkCtrl)
self.dubOffsetVar.trace('w',self.valueChangeCallback)



self.entryalign = ttk.Button(self,text='Auto-Align',command=self.alignToBeats,width=40)
self.entryalign['padding']=1
Tooltip(self.entryalign,text='Snap all visible markers to the closest beat.')
self.entryalign.grid(row=3,column=9,sticky='ew')

self.labelTransDuration = ttk.Label(self)
self.labelTransDuration.config(anchor='e', padding='2', text='Transition Duration')
self.labelTransDuration.grid(row=4,column=0,sticky='ew')
Expand Down Expand Up @@ -751,6 +782,11 @@ def __init__(self, uiParent=None, master=None, controller=None, sequencedClips=[
self.entrypauseOnLoseFocus = ttk.Checkbutton(self,text='Pause on Focus switch',onvalue=True, offvalue=False,variable=self.pauseOnLoseFocusVar)
self.entrypauseOnLoseFocus.grid(row=4,column=8,sticky='ew',columnspan=1)

self.dynamicSublipDurVar = tk.BooleanVar()
self.dynamicSublipDurVar.set(True)
self.dynamicSublipDur = ttk.Checkbutton(self,text='Dynamic Subclip Dur',onvalue=True, offvalue=False,variable=self.dynamicSublipDurVar)
self.dynamicSublipDur.grid(row=4,column=9,sticky='ew',columnspan=1)


try:
self.uiParent.attributes('-topmost', True)
Expand All @@ -777,8 +813,10 @@ def __init__(self, uiParent=None, master=None, controller=None, sequencedClips=[
self.lastSpectraDubDelay=0
self.lastSpectraZoomFactor=1
self.canvasSpectraImg=None
self.canvasSpectraData=None
self.waveAsPicImage=None

self.imgo = None
self.spectrumWorkLock = threading.Lock()

self.draggingTickIndex=None
Expand Down Expand Up @@ -1006,8 +1044,6 @@ def generateSpectrum_async(self,force=False):
except:
pass
newTotalDuration = (self.xCoordToSeconds(orig_width)-self.xCoordToSeconds(0))



if force or (orig_startoffset == startoffset and orig_currentTotalDuration == newTotalDuration and orig_width == self.timeline_canvas.winfo_width()):

Expand All @@ -1016,6 +1052,9 @@ def generateSpectrum_async(self,force=False):
self.lastSpectraDubDelay = float(self.dubOffsetVar.get())
self.lastSpectraZoomFactor=self.timelineZoomFactor

self.canvasSpectraData = outs
self.imgo = None

if self.waveAsPicImage is None:
self.waveAsPicImage = tk.PhotoImage(data=outs)
else:
Expand All @@ -1027,6 +1066,51 @@ def generateSpectrum_async(self,force=False):
self.timeline_canvas.coords(self.canvasSpectraImg,0,orig_height-80)

self.timeline_canvas.lower(self.canvasSpectraImg)

def alignToBeats(self):
if self.imgo is None:
self.imgo = np.mean(read_pgm(self.canvasSpectraData )[:,:,:],axis=(0,2))**2

n= 30
for tx,tidx in self.tickXpos[::-1]:
tx = int(tx)
xl = [float(x) for x in self.imgo[tx-n:tx+n]]
xl = [x* (len(xl)-abs((i-len(xl)/2)) ) for i,x in enumerate(xl)]

am = np.argmax(xl)
xpos = int(tx-n+am)
timestamp = self.xCoordToSeconds(xpos)
self.updateRegionsOnDrag(tidx,timestamp)


self.timeline_canvas.delete('dragTick')
self.timeline_canvas.delete('ticksLine{}'.format(tidx))


self.timeline_canvas.create_polygon( xpos, 20+20+2,
xpos-7, 20+20+2+5,
xpos, 20+20+2+11,
xpos+7, 20+20+2+5,
fill='white',tags='dragTick')

self.timeline_canvas.create_line(xpos, 20+0,
xpos, 200,fill='white',tags='dragTick')
fadeDist = 0

try:
fadeDur = float(self.fadeVar.get())
fadeDist = self.secondsToXcoord(fadeDur/2)-self.secondsToXcoord(0)
except:
pass

if fadeDist > 0:
self.timeline_canvas.create_line(xpos-fadeDist, 20+0,
xpos-fadeDist, 20+200,
fill='blue',tags='dragTick')
self.timeline_canvas.create_line(xpos+fadeDist, 20+0,
xpos+fadeDist, 20+200,
fill='blue',tags='dragTick')
self.recalculateEDLTimings()


def speedChange(self,*args):
Expand Down Expand Up @@ -1131,7 +1215,28 @@ def setDragDur(self,dur):
def timelineMousePress(self,e):

ctrl = (e.state & 0x4) != 0
pressSeconds = self.xCoordToSeconds(e.x)
shift = (e.state & 0x1) != 0

xpos = e.x

if not shift:
n= 20
try:
if self.imgo is None:
self.imgo = np.mean(read_pgm(self.canvasSpectraData )[:,:,:],axis=(0,2))**2


xl = [float(x) for x in self.imgo[e.x-n:e.x+n]]
xl = [x* (len(xl)-abs((i-len(xl)/2)) ) for i,x in enumerate(xl)]

am = np.argmax(xl)

xpos = int(e.x-n+am)
print(e.x,am,xpos)
except Exception as imgoe:
print(imgoe)

pressSeconds = self.xCoordToSeconds(xpos)


if ctrl:
Expand Down Expand Up @@ -1202,18 +1307,20 @@ def timelineMousePress(self,e):
break
elif self.draggingTickIndex is not None:



self.timeline_canvas.delete('dragTick')
self.timeline_canvas.delete('ticksLine{}'.format(self.draggingTickIndex))


self.timeline_canvas.create_polygon( e.x, 20+20+2,
e.x-7, 20+20+2+5,
e.x, 20+20+2+11,
e.x+7, 20+20+2+5,
self.timeline_canvas.create_polygon( xpos, 20+20+2,
xpos-7, 20+20+2+5,
xpos, 20+20+2+11,
xpos+7, 20+20+2+5,
fill='white',tags='dragTick')

self.timeline_canvas.create_line(e.x, 20+0,
e.x, 200,fill='white',tags='dragTick')
self.timeline_canvas.create_line(xpos, 20+0,
xpos, 200,fill='white',tags='dragTick')
fadeDist = 0

try:
Expand All @@ -1223,22 +1330,22 @@ def timelineMousePress(self,e):
pass

if fadeDist > 0:
self.timeline_canvas.create_line(e.x-fadeDist, 20+0,
e.x-fadeDist, 20+200,
self.timeline_canvas.create_line(xpos-fadeDist, 20+0,
xpos-fadeDist, 20+200,
fill='blue',tags='dragTick')
self.timeline_canvas.create_line(e.x+fadeDist, 20+0,
e.x+fadeDist, 20+200,
self.timeline_canvas.create_line(xpos+fadeDist, 20+0,
xpos+fadeDist, 20+200,
fill='blue',tags='dragTick')


elif e.type == tk.EventType.ButtonRelease:
if self.draggingBlockIndex is not None:
tagretId=0
for tx,tidx in self.tickXpos[::-1]:
print(e.x,tx,tidx)
if e.x>tx:

if xpos>tx:
tagretId=tidx+1
print('tagretId=tidx',e.x,tx,tidx)
print('tagretId=tidx',xpos,tx,tidx)
break

if tagretId != self.draggingBlockIndex:
Expand Down Expand Up @@ -1274,9 +1381,9 @@ def timelineMousePress(self,e):
if self.currentTotalDuration is None:
self.player.command('seek','0','absolute-percent','exact')
else:
seekTarget = min(max(0,self.xCoordToSeconds(e.x)),self.currentTotalDuration)
seekTarget = min(max(0,self.xCoordToSeconds(xpos)),self.currentTotalDuration)
try:
self.player.command('seek',self.xCoordToSeconds(e.x),'absolute','exact')
self.player.command('seek',self.xCoordToSeconds(xpos),'absolute','exact')
except Exception as e:
print(e)
try:
Expand Down Expand Up @@ -1406,10 +1513,16 @@ def recalculateEDLTimings(self,rid=None,pos=None,seekAfter=None):
audioFilename=None

tickCounter=0

entries=0
totaldur=0

for sv in self.sequencedClips:
fn = sv.filename
start = sv.s
end = sv.e
entries+=1
totaldur+=end-start

if rid is not None and rid==sv.rid:
print(rid,sv.rid)
Expand All @@ -1430,6 +1543,8 @@ def recalculateEDLTimings(self,rid=None,pos=None,seekAfter=None):

edlstr += '%{}%{},{},{}\n'.format(len(fn.encode('utf8')),fn,start,end-start)

if self.dynamicSublipDurVar.get() and entries>0:
self.setDragDur(totaldur/entries)

timelineWidth = self.timeline_canvas.winfo_width()

Expand Down
31 changes: 22 additions & 9 deletions src/timeLineSelectionFrameUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ def __init__(self, master, controller, globalOptions={}, *args, **kwargs):

self.timelineZoomFactor=1.0
self.dragPreviewPos=0.1
self.dragPreviewMode='abs'
self.currentZoomRangeMidpoint=0.5

self.tempRangePreviewDurationLabel = self.timeline_canvas.create_text(0, 0, text='',fill="#69bfdb")
Expand Down Expand Up @@ -665,8 +666,9 @@ def incrementEndpointPosition(self,increment,markerrid,pos):
self.seekto(endTarget-0.001)
break

def setDragPreviewPos(self,value):
def setDragPreviewPos(self,value,mode):
self.dragPreviewPos = value
self.dragPreviewMode = mode

def reconfigure(self,e):
self.setUiDirtyFlag()
Expand Down Expand Up @@ -799,17 +801,22 @@ def timelineMousewheel(self,e):
if ((st+en)/2) > e.x:
# Closer to End
newX-=qw
if self.dragPreviewMode == 'abs':
dragoffset = self.dragPreviewPos
else:
dragoffset = (ens-sts)*(self.dragPreviewPos/100)

if ctrl:
self.controller.seekTo( ((targetSeconds+((ens-sts)/2))) - self.dragPreviewPos )
self.controller.seekTo( ((targetSeconds+((ens-sts)/2))) - dragoffset )
else:
self.controller.seekTo( ((targetSeconds-((ens-sts)/2))) + self.dragPreviewPos )
self.controller.seekTo( ((targetSeconds-((ens-sts)/2))) + dragoffset )
else:
# Closer to Start
newX+=qw
if ctrl:
self.controller.seekTo( ((targetSeconds-((ens-sts)/2))) + self.dragPreviewPos )
self.controller.seekTo( ((targetSeconds-((ens-sts)/2))) + dragoffset )
else:
self.controller.seekTo( ((targetSeconds+((ens-sts)/2))) - self.dragPreviewPos )
self.controller.seekTo( ((targetSeconds+((ens-sts)/2))) - dragoffset )


self.correctMouseXPosition(newX)
Expand Down Expand Up @@ -996,20 +1003,26 @@ def timelineMousePress(self,e):
elif pos == 'e':
self.controller.seekTo( targetSeconds-0.001 )
elif pos == 'm':

if self.dragPreviewMode == 'abs':
dragoffset = self.dragPreviewPos
else:
dragoffset = (oe-os)*(self.dragPreviewPos/100)

if self.initialShiftStart == 'End':
if ctrl:
targetSeconds = targetSeconds+((oe-os)/2)
self.controller.seekTo( targetSeconds-self.dragPreviewPos )
self.controller.seekTo( targetSeconds-dragoffset )
else:
targetSeconds = targetSeconds-((oe-os)/2)
self.controller.seekTo( targetSeconds+self.dragPreviewPos )
self.controller.seekTo( targetSeconds+dragoffset )
else:
if ctrl:
targetSeconds = targetSeconds-((oe-os)/2)
self.controller.seekTo( targetSeconds+self.dragPreviewPos )
self.controller.seekTo( targetSeconds+dragoffset )
else:
targetSeconds = targetSeconds+((oe-os)/2)
self.controller.seekTo( targetSeconds-self.dragPreviewPos )
self.controller.seekTo( targetSeconds-dragoffset )

if e.type == tk.EventType.ButtonPress:
if e.num==3:
Expand Down

0 comments on commit 5a96974

Please sign in to comment.