Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@

## Logs
src/logs/*

## Trained Models
src/models/trained_models/separation/*
src/models/trained_models/transcription/*

## Datasets
# Ignore all files in these specific directories
/src/data/processed/test/model1/*
/src/data/processed/test/model2/*
/src/data/processed/train/model1/*
/src/data/processed/train/model2/*
/src/data/raw/model1/*
/src/data/raw/model2/*
src/data/processed/test/model1/*
src/data/processed/test/model2/*
src/data/processed/train/model1/*
src/data/processed/train/model2/*
src/data/raw/model1/*
src/data/raw/model2/*

# Except the directory structures
!/src/data/processed/test/model1/.gitkeep
Expand Down
12 changes: 8 additions & 4 deletions src/config/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# ----------

# Model 1 Constants
MODEL1_SUBSET = "V2"
MODEL1_SUBSET = "V5"
MODEL1_BASE_PATH = f"../data/raw/model1/{MODEL1_SUBSET}"
MODEL1_TRAIN_FOLDER_PATH = "../data/processed/train/model1"
MODEL1_TRAIN_FILE_NAME = f"mix_bass_train_data_{MODEL1_SUBSET}-TRAIN"
Expand Down Expand Up @@ -38,7 +38,11 @@
TRAINED_MODEL2_SAVE_PATH = "../models/trained_models/transcription/mark1.pt"

# Visualisation and Testing constants
TRAINED_AUDIO_FILE_PATH = "../visualization/audio/trained_audio"
PRED_AUDIO_FILE_PATH = "../visualization/audio/predicted_audio"
VISUALIZATION_SAVE_PATH = "../visualization/spectrograms/outputs"
TRAINED_AUDIO_FILE_PATH = (
"../../../../Bachelor Thesis/thesis/audio outputs/trained audio"
)
PRED_AUDIO_FILE_PATH = (
"../../../../Bachelor Thesis/thesis/audio outputs/predicted audio"
)
VISUALIZATION_SAVE_PATH = "../../../../Bachelor Thesis/thesis/spectrograms"
PRED_MIDI_FILE_PATH = "../visualization/midi/predicted_midi"
4 changes: 2 additions & 2 deletions src/config/fourierparameters.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"n_fft": 2048,
"n_mels": 128,
"hop_length": 3308,
"hop_length": 512,
"sample_rate": 44100,
"track_seconds_considered": 30,
"audio_amplitude_threshold": 0.0001
"audio_amplitude_threshold": 0.0000001
}
6 changes: 3 additions & 3 deletions src/config/hyperparameters_separation.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"learning_rate": 0.0001,
"n_epochs": 10,
"hidden_dim": 512,
"n_epochs": 250,
"hidden_dim": 1024,
"n_layers": 3,
"dropout_rate": 0.3
"dropout_rate": 0.1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import numpy as np


class DecibelNormalizer:
def __init__(self, array):
self.array = array
self.min_val = None
self.max_val = None

def normalize(self):
# Convert spectrogram magnitudes to decibels
epsilon = 1e-10 # small constant to avoid log(0)
self.array = 20 * np.log10(np.maximum(self.array, epsilon))

# Find min and max values in the dB-scaled array
self.min_val, self.max_val = np.min(self.array), np.max(self.array)

# Avoid division-by-zero error in case of all same elements
if self.min_val == self.max_val:
self.array[:] = 0
else:
self.array = (self.array - self.min_val) / (self.max_val - self.min_val)

return self.array

def get_min_max(self):
return self.min_val, self.max_val

def denormalize(self, min_val, max_val):
if min_val is not None and max_val is not None:

# Apply the inverse of min-max normalization
self.array = (self.array * (max_val - min_val)) + min_val

# Convert decibels back to linear scale
self.array = 10 ** (self.array / 20.0)

return self.array
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
convert_t_dict_key_to_numpy_arrays,
convert_to_recarray,
)
from src.data_manipulation.__helpers__.normalization.mix_bass_data_normalizer import (
Normalizer,
from src.data_manipulation.__helpers__.normalization.decibel_normalizer import (
DecibelNormalizer,
)
from src.transformers.audio_to_freq_time_analysis import audio_to_freq_time_analysis

Expand Down Expand Up @@ -36,8 +36,8 @@ def production_audio_to_dict(file_name, input_path):
t_dict = convert_t_dict_key_to_numpy_arrays(dictionary=t_dict, keys=["x", "y"])

# Normalize the data
norm_x = Normalizer(t_dict["x"])
t_dict["x"], t_dict["min_max_amplitudes"] = (
norm_x = DecibelNormalizer(t_dict["x"])
t_dict["x"], t_dict["x_min_max_amplitudes"] = (
norm_x.normalize(),
norm_x.get_min_max(),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
savez_numpy_data,
convert_to_recarray,
)
from src.data_manipulation.__helpers__.normalization.mix_bass_data_normalizer import (
Normalizer,
from src.data_manipulation.__helpers__.normalization.decibel_normalizer import (
DecibelNormalizer,
)
from src.data_manipulation.__helpers__.truncator.mix_bass_data_truncator import (
data_truncator,
Expand Down Expand Up @@ -111,16 +111,12 @@ def mixed_signal_to_dict(base_path, files_to_transform, save_file_path, pause=Fa
t_dict = convert_t_dict_key_to_numpy_arrays(dictionary=t_dict, keys=["x", "y"])

# Normalize the data
norm_x = Normalizer(t_dict["x"])
t_dict["x"], t_dict["min_max_amplitudes"] = (
norm_x.normalize(),
norm_x.get_min_max(),
)
norm_y = Normalizer(t_dict["y"])
t_dict["y"], t_dict["min_max_amplitudes"] = (
norm_y.normalize(),
norm_y.get_min_max(),
)
norm_x = DecibelNormalizer(t_dict["x"])
t_dict["x"] = norm_x.normalize()
t_dict["x_min_max_amplitudes"] = norm_x.get_min_max()
norm_y = DecibelNormalizer(t_dict["y"])
t_dict["y"] = norm_y.normalize()
t_dict["y_min_max_amplitudes"] = norm_y.get_min_max()

# Transform to recarray
t_dict_recarray = convert_to_recarray(data_dict=t_dict)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
convert_to_recarray,
savez_numpy_data,
)
from src.data_manipulation.__helpers__.normalization.mix_bass_data_normalizer import (
Normalizer,
from src.data_manipulation.__helpers__.normalization.decibel_normalizer import (
DecibelNormalizer,
)
from src.data_manipulation.__helpers__.truncator.mix_bass_data_truncator import (
data_truncator,
Expand Down Expand Up @@ -95,8 +95,8 @@ def bass_and_midi_to_dict(base_path, files_to_transform, save_file_path, pause=F
t_dict = convert_t_dict_key_to_numpy_arrays(dictionary=t_dict, keys=["x", "y"])

# Normalize the data
norm_x = Normalizer(t_dict["x"])
t_dict["x"], t_dict["min_max_amplitudes"] = (
norm_x = DecibelNormalizer(t_dict["x"])
t_dict["x"], t_dict["x_min_max_amplitudes"] = (
norm_x.normalize(),
norm_x.get_min_max(),
)
Expand Down
77 changes: 4 additions & 73 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,80 +15,11 @@


def main():
while True:
choice = (
input(
"@@@@@@ Would you like to create new models before processing your audio? @@@@@@\n"
'@@@@@@ WARNING: Selecting "yes" requires training/testing datasets to be present in the '
"data/raw/model1 and data/raw/model2 folders. @@@@@@\n"
'@@@@@@ Selecting "no" will use the pre-existing mark1 models instead. [Y/N]:'
)
.strip()
.lower()
)

if choice in ["yes", "y"]:
# Trains and tests both models separately
print()
print("@@@@@@ SEPARATION TRAINING/TESTING START @@@@@@")
separation_manager()
print()
print("@@@@@@ TRANSCRIPTION TRAINING/TESTING START @@@@@@")
transcription_manager()
print()
print("@@@@@@ MODELS SUCCESSFULLY CREATED @@@@@@")
break

elif choice in ["no", "n"]:
break

else:
print("Please enter a valid input. Either [Y/N] or [Yes/No].")

try:
input_folder = f"{PATH_TO_AUDIO}/{PRODUCTION_INPUT_FOLDER_PATH}"
if not os.listdir(input_folder):
print("No input files present in input folder. Programm terminated.")
return
for track in os.listdir(f"{input_folder}"):
if track.endswith(".wav"):
print()
print(f"@@@@ USING MODELS ON SELECTED TRACK: {track} @@@@")
input_file_path = (
f"{PATH_TO_AUDIO}/{PRODUCTION_INPUT_FOLDER_PATH}/{track}"
)
output_file_path = (
f"{PATH_TO_AUDIO}/{PRODUCTION_OUTPUT_FOLDER_PATH}/{track}"
)

print("@@ Pre-Processing... @@")
# Pre-process the audio into correct spectrogram format
processed_input = transform_data(
flag="production input",
file_name=track,
input_file_path=input_file_path,
)

print("@@ Separating and transcribing... @@")
# Pass processed audio through both models
output = use_models_on_audio(processed_input)

print("@@ Post-Processing... @@")
# Post-process the midi-spectrogram into pure midi format and save it
piano_roll_to_midi(
piano_roll=output,
output_file_path=output_file_path,
tag="",
mix_names=["mix_name"],
flag="production",
)

else:
print(f"@@@@ {track} is not a .wav file. Skipping... @@@@")
except Exception as e:
raise Exception(
f"An error occurred while processing the production audio files: {e}"
)
print("@@@@@@ SEPARATION TRAINING/TESTING START @@@@@@")
separation_manager()
print()
print("@@@@@@ MODEL SUCCESSFULLY CREATED @@@@@@")


if __name__ == "__main__":
Expand Down
27 changes: 0 additions & 27 deletions src/models/__helpers__/visualize_for_evaluation.py

This file was deleted.

31 changes: 31 additions & 0 deletions src/models/__helpers__/visualize_for_testing_evaluation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from src.config.constants import VISUALIZATION_SAVE_PATH
from src.visualization.spectrograms.visualize_spectrogram import visualize_spectrogram


def visualize_for_testing_evaluation(y_pred, y_test, x_test, data, tag):
# Convert tensor back into numpy array
y_pred_for_visualization = y_pred.detach().cpu().numpy()
x_test_for_visualization = x_test.detach().cpu().numpy()
y_test_for_visualization = y_test.detach().cpu().numpy()

visualize_spectrogram(
save_folder_path=VISUALIZATION_SAVE_PATH,
mel_spectrogram=x_test_for_visualization[0],
mix_name=data["mix_name"],
tag=tag,
label="x_test",
)
visualize_spectrogram(
save_folder_path=VISUALIZATION_SAVE_PATH,
mel_spectrogram=y_pred_for_visualization[0],
mix_name=data["mix_name"],
tag=tag,
label="y_pred",
)
visualize_spectrogram(
save_folder_path=VISUALIZATION_SAVE_PATH,
mel_spectrogram=y_test_for_visualization[0],
mix_name=data["mix_name"],
tag=tag,
label="y_test",
)
41 changes: 41 additions & 0 deletions src/models/__helpers__/visualize_for_training_evaluation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from src.config.constants import VISUALIZATION_SAVE_PATH, TRAINED_AUDIO_FILE_PATH
from src.transformers.freq_time_analysis_to_audio import freq_time_analysis_to_audio
from src.visualization.spectrograms.visualize_spectrogram import visualize_spectrogram


def visualize_for_training_evaluation(outputs, x, y, data, flag, tag):
# Convert tensor back into numpy array
outputs_for_visualization = outputs.detach().cpu().numpy()
x_train_for_visualization = x.detach().cpu().numpy()
y_train_for_visualization = y.detach().cpu().numpy()

visualize_spectrogram(
save_folder_path=VISUALIZATION_SAVE_PATH,
mel_spectrogram=x_train_for_visualization[0],
mix_name=data["mix_name"],
tag=tag,
label="x_train",
)
visualize_spectrogram(
save_folder_path=VISUALIZATION_SAVE_PATH,
mel_spectrogram=y_train_for_visualization[0],
mix_name=data["mix_name"],
tag=tag,
label="y_train",
)
visualize_spectrogram(
save_folder_path=VISUALIZATION_SAVE_PATH,
mel_spectrogram=outputs_for_visualization[0],
mix_name=data["mix_name"],
tag=tag,
label="y_output",
)

if flag:
freq_time_analysis_to_audio(
mel_spectrogram_array=outputs_for_visualization[:3],
output_file_path=TRAINED_AUDIO_FILE_PATH,
mix_names=data["mix_name"],
min_max_amplitudes=data["y_min_max_amplitudes"],
tag=tag,
)
Loading