Skip to content

Commit

Permalink
variable renaming to follow pythonic convention
Browse files Browse the repository at this point in the history
  • Loading branch information
bydariogamer committed Jun 22, 2022
1 parent e455d86 commit 63e524c
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 77 deletions.
98 changes: 46 additions & 52 deletions bpm_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,84 +45,78 @@ def argmax(signal):
return max_index


def findBPMinRange(corrected_autocorrelation, minBPM, maxBPM, duration, fineAdjustRecursion=3):
def find_bpm_in_range(corrected_autocorrelation, min_bpm, max_bpm, duration, fine_adjust_recursion=3):
length = len(corrected_autocorrelation)
firstOffset = int(60/maxBPM/duration*length)
firstIndex = length//2 + firstOffset
lastOffset = int(60/minBPM/duration*length)
lastIndex = length//2 + lastOffset
first_offset = int(60/max_bpm/duration*length)
first_index = length//2 + first_offset
last_offset = int(60/min_bpm/duration*length)
last_index = length//2 + last_offset

interestingPart = corrected_autocorrelation[firstIndex:lastIndex]
interesting_part = corrected_autocorrelation[first_index:last_index]
n = 1 # uneven integer, not choosing one leads to worse results
ddinterestingPart = np.concatenate([np.zeros(n), np.diff(np.diff(interestingPart, n), n), np.zeros(n)])/(n**2) # dd is the second derivative

indexBeatLength = argmax(interestingPart) + firstOffset
indexBeatLength_dd = argmax(-ddinterestingPart) + firstOffset
BPM = length/indexBeatLength*60/duration
BPM_dd = length/indexBeatLength_dd*60/duration

def temposAreSimilar(a, b):
if abs(a - b) <= 1:
return True
if abs(2 * a - b) <= 1:
return True
if abs(a - 2 * b) <= 1:
return True
return False
dd_interesting_part = np.concatenate([np.zeros(n), np.diff(np.diff(interesting_part, n), n), np.zeros(n)])/(n**2) # dd is the second derivative

index_beat_length = argmax(interesting_part) + first_offset
index_beat_length_dd = argmax(-dd_interesting_part) + first_offset
bpm = length/index_beat_length*60/duration
bpm_dd = length/index_beat_length_dd*60/duration

def tempos_are_similar(a, b):
return abs(a - b) <= 1 or abs(2 * a - b) <= 1 or abs(a - 2 * b) <= 1

if config.DEBUG_BPM_FINDER:
xRange = range(firstOffset, lastOffset)
plt.plot(xRange, interestingPart)
plt.plot(xRange, -ddinterestingPart)
xRange = range(lastOffset)
plt.plot(xRange, corrected_autocorrelation[length//2: length//2 + lastOffset])
plt.scatter(indexBeatLength, interestingPart[indexBeatLength - firstOffset], label=str(BPM) + ' bpm')
plt.scatter(indexBeatLength_dd, -ddinterestingPart[indexBeatLength_dd - firstOffset], label=str(BPM_dd) + ' bpm')
x_range = range(first_offset, last_offset)
plt.plot(x_range, interesting_part)
plt.plot(x_range, -dd_interesting_part)
x_range = range(last_offset)
plt.plot(x_range, corrected_autocorrelation[length//2: length//2 + last_offset])
plt.scatter(index_beat_length, interesting_part[index_beat_length - first_offset], label=str(bpm) + ' bpm')
plt.scatter(index_beat_length_dd, -dd_interesting_part[index_beat_length_dd - first_offset], label=str(bpm_dd) + ' bpm')
plt.legend()
plt.show()

if not temposAreSimilar(indexBeatLength, indexBeatLength_dd):
if not tempos_are_similar(index_beat_length, index_beat_length_dd):
# Compare the quality of the findings by comparing the autocorrelation for 2, 3 and 4 beats
beats = np.array([2, 3, 4])
scores = np.zeros(len(beats))
scores_dd = np.zeros(len(beats))
for i, n in enumerate(beats):
scores[i] = corrected_autocorrelation[length//2 + n*indexBeatLength]
scores_dd[i] = corrected_autocorrelation[length//2 + n*indexBeatLength_dd]
scores[i] = corrected_autocorrelation[length//2 + n*index_beat_length]
scores_dd[i] = corrected_autocorrelation[length//2 + n*index_beat_length_dd]

if sum(scores) > sum(scores_dd):
rough_BPM = BPM
rough_bpm = bpm
else:
rough_BPM = BPM_dd
rough_bpm = bpm_dd

if config.DEBUG_BPM_FINDER:
print(' Non-trivial rhythm')
print(' index:', indexBeatLength, indexBeatLength_dd)
print(' bpm:', BPM, BPM_dd)

xRange = range(lastOffset*2)
plt.plot(xRange, corrected_autocorrelation[length//2: length//2 + lastOffset*2])
plt.scatter(indexBeatLength, interestingPart[indexBeatLength - firstOffset], label=str(BPM) + ' bpm')
plt.scatter(indexBeatLength_dd, -ddinterestingPart[indexBeatLength_dd - firstOffset], label=str(BPM_dd) + ' bpm')
plt.scatter(beats*indexBeatLength, scores, label=str(BPM) + ' bpm beats')
plt.scatter(beats*indexBeatLength_dd, scores_dd, label=str(BPM_dd) + ' bpm beats')
print(' index:', index_beat_length, index_beat_length_dd)
print(' bpm:', bpm, bpm_dd)

x_range = range(last_offset*2)
plt.plot(x_range, corrected_autocorrelation[length//2: length//2 + last_offset*2])
plt.scatter(index_beat_length, interesting_part[index_beat_length - first_offset], label=str(bpm) + ' bpm')
plt.scatter(index_beat_length_dd, -dd_interesting_part[index_beat_length_dd - first_offset], label=str(bpm_dd) + ' bpm')
plt.scatter(beats*index_beat_length, scores, label=str(bpm) + ' bpm beats')
plt.scatter(beats*index_beat_length_dd, scores_dd, label=str(bpm_dd) + ' bpm beats')
plt.legend()
plt.show()
else:
rough_BPM = BPM
rough_bpm = bpm
if config.DEBUG_BPM_FINDER:
print(' Tempos match: ', BPM, BPM_dd)
print(' Tempos match: ', bpm, bpm_dd)

if fineAdjustRecursion and (60/rough_BPM < duration/5):
if fine_adjust_recursion and (60/rough_bpm < duration/5):
variation = 0.08
if config.DEBUG_BPM_FINDER:
print('', fineAdjustRecursion, 'BPM-Range', rough_BPM*0.5*(1-variation), rough_BPM*0.5*(1+variation))
return 2*findBPMinRange(corrected_autocorrelation, rough_BPM*0.5*0.95, rough_BPM*0.5*1.05, duration, fineAdjustRecursion-1)
print('', fine_adjust_recursion, 'bpm-Range', rough_bpm*0.5*(1-variation), rough_bpm*0.5*(1+variation))
return 2*find_bpm_in_range(corrected_autocorrelation, rough_bpm*0.5*0.95, rough_bpm*0.5*1.05, duration, fine_adjust_recursion-1)
else:
return rough_BPM
return rough_bpm


def getBPM(song, duration):
def get_bpm(song, duration):
# Simplify signal
mono_signal= np.mean(song, 1)
# subsample
Expand All @@ -133,7 +127,7 @@ def getBPM(song, duration):
# tempo / autocorrelation
autocorrelation = np.correlate(subsampled, subsampled, 'same')
corrected_autocorr = correct_autocorrelation(autocorrelation, len_subsampled)
BPM = findBPMinRange(corrected_autocorr, config.BPM_FINDER_MINIMUM, config.BPM_FINDER_MAXIMUM, duration, fineAdjustRecursion=3)
bpm = find_bpm_in_range(corrected_autocorr, config.BPM_FINDER_MINIMUM, config.BPM_FINDER_MAXIMUM, duration, fine_adjust_recursion=3)
if config.DEBUG_BPM_FINDER:
print('BPM:', BPM)
return BPM
print('bpm:', bpm)
return bpm
12 changes: 6 additions & 6 deletions level.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ def __init__(self, song: pygame.mixer.Sound, song_name):
self.blocks = []

# Find tempo of the song
BPM = bpm_finder.getBPM(self.array, self.duration)
bpm = bpm_finder.get_bpm(self.array, self.duration)

def adjust_frequency_to_aim(frequency, aim):
while frequency < aim * 0.66:
frequency *= 2
while frequency > aim * 1.33:
frequency /= 2
return frequency
blocks_per_sec = adjust_frequency_to_aim(BPM/60., config.BLOCKS_PER_SECOND_AIM)
blocks_per_sec = adjust_frequency_to_aim(bpm/60., config.BLOCKS_PER_SECOND_AIM)
print('Blocks per second: ', blocks_per_sec, 'that\'s', blocks_per_sec*60, 'bpm')

# Build map from audio
Expand All @@ -45,11 +45,11 @@ def adjust_frequency_to_aim(frequency, aim):
self.blocks *= config.HEIGHT_LEVELS/maximum
self.blocks = self.blocks.clip(min=0, max=config.HEIGHT_LEVELS)
# Clear space at the beginning of the song
start_Blocks = int(config.DISP_HEI/config.VELOCITY_X*blocks_per_sec)
for i in range(start_Blocks-start_Blocks*2//3):
start_blocks = int(config.DISP_HEI/config.VELOCITY_X*blocks_per_sec)
for i in range(start_blocks-start_blocks*2//3):
self.blocks[i] = 0 # free plain
for i in range(start_Blocks-start_Blocks*2//3, start_Blocks): # ramping up to normal map
self.blocks[i] *= float(i)/start_Blocks*3/2-0.5
for i in range(start_blocks-start_blocks*2//3, start_blocks): # ramping up to normal map
self.blocks[i] *= float(i)/start_blocks*3/2-0.5
# Quantize blocks
self.blocks = np.round(self.blocks)

Expand Down
16 changes: 0 additions & 16 deletions main.pyw → main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import colors
import config
from config import DISP_WID, DISP_HEI, BASE_FPS
from pydub import AudioSegment


# INITIALIZE PYGAME
Expand Down Expand Up @@ -62,24 +61,9 @@ def pager(length, cut):
return [slice(i, min(i + cut, length)) for i in range(0, length, cut)]


def transform(path, new_format, replace=False, return_path=False):
audio = AudioSegment.from_file(path)
name = os.path.basename(path).split('.')[0] + '.' + new_format
new_path = os.path.join(os.path.dirname(path), name)
audio.export(new_path, new_format)
if replace:
os.remove(path)
if return_path:
return new_path


SONGS = [] # [song title, path]
add_songs_in_folder(os.path.join(PATH, 'assets', 'songs'), SONGS)

##for song in SONGS:
## if song[0].split('.')[-1].lower() != 'ogg':
## song[1] = transform(song[1], 'ogg', True, True)


# GAME LOOP
state = 'start'
Expand Down
4 changes: 2 additions & 2 deletions obstacle.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ class Obstacle(pygame.Rect):
def __init__(self, initial_x, y, width, height):
"""A Rectangle that will move with time and has an initial position"""

pygame.Rect.__init__(self, initial_x, y, width, height)
super().__init__(initial_x, y, width, height)
self.initial_x = initial_x

def updateOffset(self, offset):
def update_offset(self, offset):
self.x = self.initial_x + offset
2 changes: 1 addition & 1 deletion player.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def update(self, timePassed):
self.collide = False
offset = int(-timePassed * self.vel_x)
for obstacle in self.level.obstacles:
obstacle.updateOffset(offset)
obstacle.update_offset(offset)
if self.rect.colliderect(obstacle):
self.damage()
self.collide = True
Expand Down

0 comments on commit 63e524c

Please sign in to comment.