Advancements

This commit is contained in:
Alexandre 2024-05-28 20:48:57 +02:00
parent 32d25d9826
commit b212c86a00
1 changed files with 65 additions and 27 deletions

View File

@ -11,7 +11,6 @@ import heapq
import scipy import scipy
import os import os
import random import random
from datetime import timedelta
from pathlib import Path from pathlib import Path
from time import sleep from time import sleep
@ -126,8 +125,15 @@ def filter_n_percent(song_name, offset, length, threshold, reduce, show):
return song_data return song_data
def filter_n_percent_serial(song_name, offset, n_iter, step, threshold): def filter_n_percent_serial(song_name, offset, n_iter, step, threshold):
# threshold is in ]0, 100] """
# filter data associated with song_name to keep only the highest threshold% values song_name : string
offset : int
n_iter : int (number of turns)
step : int (length of each small segment)
threshold : int (is in ]0, 100])
filter data associated with song_name to keep only the highest threshold% values
"""
subprocess.run(["ffmpeg", "-ss", str(offset), "-t", str(offset+step*n_iter), "-i", song_name, "crop.wav"]) subprocess.run(["ffmpeg", "-ss", str(offset), "-t", str(offset+step*n_iter), "-i", song_name, "crop.wav"])
@ -273,7 +279,22 @@ def get_freq(song_name, offset, step, songlen, data, display=False):
return frequencies return frequencies
def void_freq(song_name, offset, songlen, increment, minfreq, maxfreq, upperthr, ampthr, ampfreq, ampval, leniency, write, output_file="trimmed.wav"): def void_freq(song_name, offset, songlen, increment, minfreq, maxfreq, upperthr, ampthr, ampfreq, ampval, leniency, write, linear, output_file="trimmed.wav"):
"""
song_name : string
offset : int
songlen : int (length of the part that will be filtered, starting from offset)
increment : float (technical parameter)
minfreq and maxfreq : every frequency in [minfreq, maxfreq] will be voided
upperthr : every frequency above upperthr will be voided
ampthr : every frequency with amplitude under MAX/ampthr (aka amplitudes under (100/ampthr)% of the max will be voided
ampfreq, leniency (if linear is false), linear : technical parameters
ampval : int
- if linear is false, then this willbe the maximum amplification possible
- if linear is true, this is the multiplier (Amp <- Amp * (ampval * frequency + leniency))
write : bool (should be set to True)
output_file : technical
"""
fft_list = [] fft_list = []
times = [] times = []
current_time = offset current_time = offset
@ -306,9 +327,14 @@ def void_freq(song_name, offset, songlen, increment, minfreq, maxfreq, upperthr,
print("Finding global max...") print("Finding global max...")
for i in range(len(fft_list)): if(linear == False):
for j in range(len(fft_list[i])): for i in range(len(fft_list)):
fft_list[i][j] *= (1 + ampval/max(1, np.abs(pfreq[j] - ampfreq))) for j in range(len(fft_list[i])):
fft_list[i][j] *= (1 + ampval/max(1, np.abs(pfreq[j] - ampfreq)))
else:
for i in range(len(fft_list)):
for j in range(len(fft_list[i])):
fft_list[i][j] *= (ampval*pfreq[j] + leniency)
print("Trimming...") print("Trimming...")
@ -369,40 +395,52 @@ def test_sample(timelist):
print("F") print("F")
sleep(timelist[i]-timelist[i-1]) sleep(timelist[i]-timelist[i-1])
#Offset = 74.582 def convert_tuple(datares, freq):
#BPM = 178
#Length = 48*60/BPM-0.01
#Offset = 0
#BPM = 180
#Length = 48*60/BPM-0.01
#Offset = 7
#BPM = 140
#Length = 32*60/BPM-0.01
def convert_tuple(datares, freq) -> tuple[timedelta, int, float]:
""" """
Takes datares and converts it to a list of tuples (amplitude, time in ms) Takes datares and converts it to a list of tuples (amplitude, time in ms)
""" """
return [(timedelta(milliseconds=i), datares[i], freq[i]) for i in range(len(datares)) if datares[i] > 0] return [(i, datares[i], freq[i]) for i in range(len(datares)) if datares[i] > 0]
def get_songlen(filename):
"""
retrieves the length of the song in seconds
"""
sample_rate, global_data = wavfile.read(filename)
return (len(global_data)/sample_rate)
def process_song(filename, bpm, offset=0, div_len_factor=1, n_iter_2=-1, threshold=0.5, divisor=4):
"""
filename : string (name of the song)
offset : int [+] (song mapping will start from this time in seconds, default is 0)
bpm : int [+]
div_len_factor : float [+] (the length multiplier of each segment, default is 1)
n_iter : int [+*] (the number of iterations, default is -1 (maps the whole music))
threshold : int [0, 100] (used by the filter function to only keep the largest threshold% of timing points, default is 0.5)
divisor : int [+] (beat divisor used to snap the notes, default is 4)
"""
div_len = div_len_factor*60/bpm-0.01
n_iter = n_iter_2
if(n_iter == -1):
song_len = get_songlen(filename)
n_iter = int(song_len/div_len)-1
def process_song(filename, offset, bpm, div_len_factor=60, n_iter=48, threshold=0.5, divisor=4):
div_len = div_len_factor/bpm-0.01
filtered_name = f"{filename}_trimmed.wav" filtered_name = f"{filename}_trimmed.wav"
void_freq(filename, offset, offset+div_len*(n_iter+1)+0.01, 4*60/bpm, minfreq=0, maxfreq=330, upperthr=5000, ampthr=60, ampfreq = 1200, ampval = 7.27, leniency = 0.005, write=True, output_file=filtered_name)
void_freq(filename, offset, offset+div_len*(n_iter+1)+0.01, 4*60/bpm, minfreq=0, maxfreq=330, upperthr=5000, ampthr=60, ampfreq = 1200, ampval = 5.0, leniency = 0.005, write=True, linear=False, output_file=filtered_name)
#void_freq(filename, offset, offset+div_len*(n_iter+1)+0.01, 4*60/bpm, minfreq=0, maxfreq=330, upperthr=2500, ampthr=60, ampfreq = 1200, ampval = 1/2000, leniency = 0.0, write=True, linear=True, output_file=filtered_name)
datares = filter_n_percent_serial(filtered_name, offset, n_iter, div_len, threshold) datares = filter_n_percent_serial(filtered_name, offset, n_iter, div_len, threshold)
datares = snap(datares, 44100, bpm, 4, True) datares = snap(datares, 44100, bpm, 4, True)
frequencies = get_freq(filtered_name, offset, div_len, div_len*n_iter, datares, True) frequencies = get_freq(filtered_name, offset, div_len, div_len*n_iter, datares, True)
Path(f"{filename}_trimmed.wav").unlink() #Path(f"{filename}_trimmed.wav").unlink()
return convert_tuple(datares, frequencies) return convert_tuple(datares, frequencies)
def main(): def main():
data = process_song("tetris_4.wav", 0, 160) data = process_song("tetris_4.wav", 160, n_iter_2 = 32)
print(data) #print(data)
print("Program finished with return 0") print("Program finished with return 0")
if __name__ == "__main__": if __name__ == "__main__":