2023-04-01 15:02:53 +08:00
|
|
|
import ffmpeg
|
|
|
|
|
import numpy as np
|
2023-07-23 03:47:53 +00:00
|
|
|
|
2023-07-21 20:36:54 +07:00
|
|
|
import os
|
2023-07-27 11:04:45 +07:00
|
|
|
import sys
|
|
|
|
|
|
2023-07-30 16:00:56 +07:00
|
|
|
from shlex import quote as RQuote
|
2023-07-26 06:24:23 +07:00
|
|
|
import random
|
2023-04-15 20:44:24 +09:00
|
|
|
|
2023-07-29 00:23:52 +07:00
|
|
|
import csv
|
2023-07-25 05:53:47 +07:00
|
|
|
|
2023-07-27 11:04:45 +07:00
|
|
|
platform_stft_mapping = {
|
2023-07-30 16:00:56 +07:00
|
|
|
'linux': 'stftpitchshift',
|
|
|
|
|
'darwin': 'stftpitchshift',
|
|
|
|
|
'win32': 'stftpitchshift.exe',
|
2023-07-27 11:04:45 +07:00
|
|
|
}
|
2023-07-25 05:53:47 +07:00
|
|
|
|
2023-07-27 11:04:45 +07:00
|
|
|
stft = platform_stft_mapping.get(sys.platform)
|
2023-07-28 23:45:47 +00:00
|
|
|
|
2023-07-29 00:23:52 +07:00
|
|
|
def CSVutil(file, rw, type, *args):
|
2023-07-30 16:00:56 +07:00
|
|
|
if type == 'formanting':
|
|
|
|
|
if rw == 'r':
|
2023-07-29 00:23:52 +07:00
|
|
|
with open(file) as fileCSVread:
|
|
|
|
|
csv_reader = list(csv.reader(fileCSVread))
|
|
|
|
|
return (
|
2023-07-30 16:00:56 +07:00
|
|
|
csv_reader[0][0], csv_reader[0][1], csv_reader[0][2]
|
|
|
|
|
) if csv_reader is not None else (lambda: exec('raise ValueError("No data")'))()
|
2023-07-29 00:23:52 +07:00
|
|
|
else:
|
|
|
|
|
if args:
|
|
|
|
|
doformnt = args[0]
|
|
|
|
|
else:
|
|
|
|
|
doformnt = False
|
|
|
|
|
qfr = args[1] if len(args) > 1 else 1.0
|
|
|
|
|
tmb = args[2] if len(args) > 2 else 1.0
|
2023-07-30 16:00:56 +07:00
|
|
|
with open(file, rw, newline='') as fileCSVwrite:
|
|
|
|
|
csv_writer = csv.writer(fileCSVwrite, delimiter=',')
|
2023-07-29 00:23:52 +07:00
|
|
|
csv_writer.writerow([doformnt, qfr, tmb])
|
2023-07-30 16:00:56 +07:00
|
|
|
elif type == 'stop':
|
2023-07-29 00:23:52 +07:00
|
|
|
stop = args[0] if args else False
|
2023-07-30 16:00:56 +07:00
|
|
|
with open(file, rw, newline='') as fileCSVwrite:
|
|
|
|
|
csv_writer = csv.writer(fileCSVwrite, delimiter=',')
|
2023-07-29 00:23:52 +07:00
|
|
|
csv_writer.writerow([stop])
|
2023-04-15 20:44:24 +09:00
|
|
|
|
2023-07-21 20:36:54 +07:00
|
|
|
def load_audio(file, sr, DoFormant, Quefrency, Timbre):
|
2023-07-26 23:01:10 +07:00
|
|
|
converted = False
|
2023-07-30 16:00:56 +07:00
|
|
|
DoFormant, Quefrency, Timbre = CSVutil('csvdb/formanting.csv', 'r', 'formanting')
|
2023-03-31 17:54:38 +08:00
|
|
|
try:
|
2023-04-15 20:44:24 +09:00
|
|
|
file = (
|
|
|
|
|
file.strip(" ").strip('"').strip("\n").strip('"').strip(" ")
|
2023-07-30 16:00:56 +07:00
|
|
|
)
|
2023-07-23 03:47:53 +00:00
|
|
|
file_formanted = file.strip(" ").strip('"').strip("\n").strip('"').strip(" ")
|
2023-07-30 16:00:56 +07:00
|
|
|
|
|
|
|
|
if (DoFormant.lower() == 'true'):
|
|
|
|
|
numerator = round(random.uniform(1,4), 4)
|
|
|
|
|
|
2023-07-25 00:23:56 +07:00
|
|
|
if not file.endswith(".wav"):
|
2023-07-30 16:00:56 +07:00
|
|
|
|
2023-07-26 06:24:23 +07:00
|
|
|
if not os.path.isfile(f"{file_formanted}.wav"):
|
2023-07-26 23:01:10 +07:00
|
|
|
converted = True
|
2023-07-30 16:00:56 +07:00
|
|
|
#print(f"\nfile = {file}\n")
|
|
|
|
|
#print(f"\nfile_formanted = {file_formanted}\n")
|
2023-07-26 06:24:23 +07:00
|
|
|
converting = (
|
2023-07-30 16:00:56 +07:00
|
|
|
ffmpeg.input(file_formanted, threads = 0)
|
|
|
|
|
.output(f"{RQuote(file_formanted)}.wav")
|
2023-07-26 06:24:23 +07:00
|
|
|
.run(
|
2023-07-30 16:00:56 +07:00
|
|
|
cmd=["ffmpeg", "-nostdin"], capture_stdout=True, capture_stderr=True
|
2023-07-26 06:24:23 +07:00
|
|
|
)
|
2023-07-25 00:23:56 +07:00
|
|
|
)
|
2023-07-26 06:24:23 +07:00
|
|
|
else:
|
|
|
|
|
pass
|
2023-07-30 16:00:56 +07:00
|
|
|
file_formanted = f"{file_formanted}.wav" if not file_formanted.endswith(".wav") else file_formanted
|
|
|
|
|
|
2023-07-26 06:24:23 +07:00
|
|
|
print(f" · Formanting {file_formanted}...\n")
|
2023-07-30 16:00:56 +07:00
|
|
|
|
|
|
|
|
command = (
|
|
|
|
|
f'{RQuote(stft)} -i "{RQuote(file_formanted)}" -q "{RQuote(Quefrency)}" '
|
|
|
|
|
f'-t "{RQuote(Timbre)}" -o "{RQuote(file_formanted)}FORMANTED_{RQuote(str(numerator))}.wav"'
|
2023-07-23 03:47:53 +00:00
|
|
|
)
|
2023-07-30 16:00:56 +07:00
|
|
|
os.system(command)
|
|
|
|
|
|
2023-07-26 06:24:23 +07:00
|
|
|
print(f" · Formanted {file_formanted}!\n")
|
2023-07-30 16:00:56 +07:00
|
|
|
|
2023-07-21 20:36:54 +07:00
|
|
|
out, _ = (
|
2023-07-30 16:00:56 +07:00
|
|
|
ffmpeg.input(f"{file_formanted}FORMANTED_{str(numerator)}.wav", threads=0)
|
2023-07-21 20:36:54 +07:00
|
|
|
.output("-", format="f32le", acodec="pcm_f32le", ac=1, ar=sr)
|
2023-07-23 03:47:53 +00:00
|
|
|
.run(
|
|
|
|
|
cmd=["ffmpeg", "-nostdin"], capture_stdout=True, capture_stderr=True
|
|
|
|
|
)
|
2023-07-21 20:36:54 +07:00
|
|
|
)
|
2023-07-23 03:47:53 +00:00
|
|
|
|
2023-07-30 16:00:56 +07:00
|
|
|
try: os.remove(f"{file_formanted}FORMANTED_{str(numerator)}.wav")
|
|
|
|
|
except Exception as e: pass; print(f"couldn't remove formanted type of file due to {e}")
|
|
|
|
|
|
2023-07-21 20:36:54 +07:00
|
|
|
else:
|
|
|
|
|
out, _ = (
|
|
|
|
|
ffmpeg.input(file, threads=0)
|
|
|
|
|
.output("-", format="f32le", acodec="pcm_f32le", ac=1, ar=sr)
|
2023-07-23 03:47:53 +00:00
|
|
|
.run(
|
|
|
|
|
cmd=["ffmpeg", "-nostdin"], capture_stdout=True, capture_stderr=True
|
|
|
|
|
)
|
2023-07-21 20:36:54 +07:00
|
|
|
)
|
2023-04-01 16:42:19 +08:00
|
|
|
except Exception as e:
|
|
|
|
|
raise RuntimeError(f"Failed to load audio: {e}")
|
2023-07-30 16:00:56 +07:00
|
|
|
|
2023-07-26 23:01:10 +07:00
|
|
|
if converted:
|
2023-07-30 16:00:56 +07:00
|
|
|
try: os.remove(file_formanted)
|
|
|
|
|
except Exception as e: pass; print(f"Couldn't remove converted type of file due to {e}")
|
2023-07-26 23:01:10 +07:00
|
|
|
converted = False
|
2023-07-30 16:00:56 +07:00
|
|
|
|
2023-04-24 20:35:56 +08:00
|
|
|
return np.frombuffer(out, np.float32).flatten()
|
2023-08-02 02:47:17 +07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_audio_duration(file):
|
|
|
|
|
try:
|
|
|
|
|
# Strip whitespaces and unnecessary characters from the file name
|
|
|
|
|
file = file.strip(" ").strip('"').strip("\n").strip('"').strip(" ")
|
|
|
|
|
|
|
|
|
|
# Probe the audio file for information
|
|
|
|
|
probe = ffmpeg.probe(file)
|
|
|
|
|
|
|
|
|
|
# Extract the duration from the probe result
|
|
|
|
|
duration = float(probe['streams'][0]['duration'])
|
|
|
|
|
|
|
|
|
|
# If the duration is less than 0.75 seconds, print the message and exit the loop
|
|
|
|
|
if duration < 0.76:
|
|
|
|
|
print(
|
|
|
|
|
f"\n------------\n"
|
|
|
|
|
f"Audio file, {file.split('/')[-1]}, under ~0.76s detected - file is too short. Target at least 1-2s for best results."
|
|
|
|
|
f"\n------------\n\n"
|
|
|
|
|
)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
except Exception as e:
|
|
|
|
|
raise RuntimeError(f"Failed to check audio duration: {e}")
|