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 os
import random
from datetime import timedelta
from pathlib import Path
from time import sleep
@ -126,8 +125,15 @@ def filter_n_percent(song_name, offset, length, threshold, reduce, show):
return song_data
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"])
@ -273,7 +279,22 @@ def get_freq(song_name, offset, step, songlen, data, display=False):
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 = []
times = []
current_time = offset
@ -306,9 +327,14 @@ def void_freq(song_name, offset, songlen, increment, minfreq, maxfreq, upperthr,
print("Finding global max...")
if(linear == False):
for i in range(len(fft_list)):
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...")
@ -369,40 +395,52 @@ def test_sample(timelist):
print("F")
sleep(timelist[i]-timelist[i-1])
#Offset = 74.582
#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]:
def convert_tuple(datares, freq):
"""
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"
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 = snap(datares, 44100, bpm, 4, 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)
def main():
data = process_song("tetris_4.wav", 0, 160)
print(data)
data = process_song("tetris_4.wav", 160, n_iter_2 = 32)
#print(data)
print("Program finished with return 0")
if __name__ == "__main__":