Commit 8ceb5875 authored by Nadir Dalla Pozza's avatar Nadir Dalla Pozza
Browse files

Plots removed

parent e1615572
...@@ -38,11 +38,7 @@ to plot filter frequency response; ...@@ -38,11 +38,7 @@ to plot filter frequency response;
3. `STANDARD_W` that specifies the equalisation standard used to record the tape; 3. `STANDARD_W` that specifies the equalisation standard used to record the tape;
4. `SPEED_W` that specifies the speed used when recording the tape; 4. `SPEED_W` that specifies the speed used when recording the tape;
5. `STANDARD_R` that specifies the equalisation standard used to read the tape; 5. `STANDARD_R` that specifies the equalisation standard used to read the tape;
6. `SPEED_R` that specifies the speed used when reading the tape; 6. `SPEED_R` that specifies the speed used when reading the tape.
7. `FS` that specifies the sampling frequency to be used for the filters and the impulse responses.
This parameter won't be considered if `FILES_NAME` parameter is not an empty string;
8. `BPS` that specifies the bits-per-sample to be used when saving the filter impulse response as WAV;
9. `PLOTS` that specifies if the plots of the frequency response should be shown.
To execute the script without issues, the inner structure of the `WORKING_PATH` directory shall be like: To execute the script without issues, the inner structure of the `WORKING_PATH` directory shall be like:
``` ```
...@@ -112,7 +108,7 @@ With this structure, `FILES_NAME` parameter could be equal to `File1` or `File2` ...@@ -112,7 +108,7 @@ With this structure, `FILES_NAME` parameter could be equal to `File1` or `File2`
You can now launch the *Tape Audio Restoration* from the command line with: You can now launch the *Tape Audio Restoration* from the command line with:
``` ```
python3 main.py python3 tapeAudioRestoration.py
``` ```
Useful log information will be displayed during execution, requiring occasional interaction. Useful log information will be displayed during execution, requiring occasional interaction.
......
...@@ -15,7 +15,4 @@ SPEED_W: 7.5 ...@@ -15,7 +15,4 @@ SPEED_W: 7.5
STANDARD_R: "CCIR" STANDARD_R: "CCIR"
# Reading tape speed [ips]. # Reading tape speed [ips].
# Accepted values: (3.75, 7.5, 15, 30) # Accepted values: (3.75, 7.5, 15, 30)
SPEED_R: 15 SPEED_R: 15
# Enable plotting filter frequency responses \ No newline at end of file
# Accepted values: (true, false)
PLOTS: false
\ No newline at end of file
...@@ -10,7 +10,6 @@ It identifies and restore portions of the Preservation Audio File, providing: ...@@ -10,7 +10,6 @@ It identifies and restore portions of the Preservation Audio File, providing:
""" """
import array import array
import matplotlib.pyplot as plt
import numpy as np import numpy as np
import os import os
import shutil import shutil
...@@ -20,7 +19,7 @@ from argparse import ArgumentParser, RawTextHelpFormatter ...@@ -20,7 +19,7 @@ from argparse import ArgumentParser, RawTextHelpFormatter
from control import c2d, TransferFunction from control import c2d, TransferFunction
from numpy import ndarray from numpy import ndarray
from scipy.io import wavfile from scipy.io import wavfile
from scipy.signal import freqs, freqz, tf2zpk, zpk2tf, lfilter from scipy.signal import tf2zpk, zpk2tf, lfilter
__author__ = "Nadir Dalla Pozza" __author__ = "Nadir Dalla Pozza"
__copyright__ = "Copyright 2022, Audio Innova S.r.l." __copyright__ = "Copyright 2022, Audio Innova S.r.l."
...@@ -48,7 +47,7 @@ class CC: ...@@ -48,7 +47,7 @@ class CC:
END = '\033[0m' END = '\033[0m'
def get_arguments() -> tuple[str, str, str, float, str, float, bool]: def get_arguments() -> tuple[str, str, str, float, str, float]:
""" """
Method to obtain arguments from config.yaml file or command line. Method to obtain arguments from config.yaml file or command line.
Default config.yaml, ignored if a command line argument is passed. Default config.yaml, ignored if a command line argument is passed.
...@@ -58,8 +57,7 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]: ...@@ -58,8 +57,7 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]:
3) str specifying the equalization standard used when the tape was recorded; 3) str specifying the equalization standard used when the tape was recorded;
4) float specifying the speed used when the tape was recorded; 4) float specifying the speed used when the tape was recorded;
5) str specifying the equalization standard used when the tape was read; 5) str specifying the equalization standard used when the tape was read;
6) float specifying the speed used when the tape was read; 6) float specifying the speed used when the tape was read.
7) bool specifying if filter figures should be plotted.
""" """
if len(sys.argv) > 1: if len(sys.argv) > 1:
...@@ -120,12 +118,6 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]: ...@@ -120,12 +118,6 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]:
speed_w = float(args.speed_w) speed_w = float(args.speed_w)
standard_r = args.equalization_r standard_r = args.equalization_r
speed_r = float(args.speed_r) speed_r = float(args.speed_r)
plots = False
if args.plot_figures in ('true', 'True'):
plots = True
elif args.plot_figures not in ('false', 'False'):
print(CC.RED + 'Invalid PLOT input argument!' + CC.END)
quit(os.EX_CONFIG)
else: else:
# Read configuration file # Read configuration file
config = object config = object
...@@ -149,9 +141,6 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]: ...@@ -149,9 +141,6 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]:
if 'SPEED_R' not in config: if 'SPEED_R' not in config:
print(CC.RED + 'SPEED_R key not found in config.yaml!' + CC.END) print(CC.RED + 'SPEED_R key not found in config.yaml!' + CC.END)
quit(os.EX_CONFIG) quit(os.EX_CONFIG)
if 'PLOTS' not in config:
print(CC.RED + 'PLOTS key not found in config.yaml!' + CC.END)
quit(os.EX_CONFIG)
except FileNotFoundError: except FileNotFoundError:
print(CC.RED + 'config.yaml file not found!' + CC.END) print(CC.RED + 'config.yaml file not found!' + CC.END)
quit(os.EX_NOINPUT) quit(os.EX_NOINPUT)
...@@ -161,13 +150,7 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]: ...@@ -161,13 +150,7 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]:
speed_w = config['SPEED_W'] speed_w = config['SPEED_W']
standard_r = config['STANDARD_R'] standard_r = config['STANDARD_R']
speed_r = config['SPEED_R'] speed_r = config['SPEED_R']
plots = False return working_path, files_name, standard_w, speed_w, standard_r, speed_r
if config['PLOTS'] in (True, 'true', 'True'):
plots = True
elif config['PLOTS'] not in (False, 'false', 'False'):
print(CC.RED + 'Invalid PLOT input argument!' + CC.END)
quit(os.EX_CONFIG)
return working_path, files_name, standard_w, speed_w, standard_r, speed_r, plots
def check_input(working_path: str, files_name: str, standard_w: str, speed_w: float, standard_r: str, speed_r: float) -> tuple[str, str, str, str]: def check_input(working_path: str, files_name: str, standard_w: str, speed_w: float, standard_r: str, speed_r: float) -> tuple[str, str, str, str]:
...@@ -698,61 +681,23 @@ def get_correction_filter(standard_w: str, speed_w: float, standard_r: str, spee ...@@ -698,61 +681,23 @@ def get_correction_filter(standard_w: str, speed_w: float, standard_r: str, spee
return a, b, fs, case return a, b, fs, case
def correction(a: array, b: array, paf: ndarray, fs: int, plots: bool) -> ndarray: def correction(a: array, b: array, paf: ndarray, fs: int) -> ndarray:
""" """
Apply a correction filter to a Preservation Audio File; Apply a correction filter to a Preservation Audio File;
:param a: array of coefficients, specifying the numerator of filter transfer function, :param a: array of coefficients, specifying the numerator of filter transfer function,
:param b: array of coefficients, specifying in the denominator of filter transfer function, :param b: array of coefficients, specifying in the denominator of filter transfer function,
:param paf: ndarray specifying the raw audio data of the Preservation Audio File, :param paf: ndarray specifying the raw audio data of the Preservation Audio File,
:param fs: int specifying the operational sampling frequency, :param fs: int specifying the operational sampling frequency.
:param plots: bool specifying if filter plots should be displayed.
:return: the corrected audio as a Restored Audio File. :return: the corrected audio as a Restored Audio File.
""" """
# Analog transfer function # Analog transfer function
h_a = TransferFunction(a, b) h_a = TransferFunction(a, b)
# Analog frequency vector
w_a = np.logspace(np.log10(1), np.log10(fs * np.pi), 5000)
if plots:
# Analog filter frequency response
w_t, h_t = freqs(a, b, worN=w_a)
# Plot analog graph
# - Magnitude
plt.subplot(2, 1, 1)
plt.semilogx(w_t / (2 * np.pi), 20 * np.log10(abs(h_t)))
plt.xlim([1, 24000])
plt.xlabel('Frequency')
plt.ylim([-40, 40])
plt.ylabel('Amplitude response [dB]')
plt.grid(True)
# - Phase
plt.subplot(2, 1, 2)
plt.semilogx(w_t / (2 * np.pi), np.angle(h_t) * 180 / np.pi)
plt.xlim([1, 24000])
plt.xlabel('Frequency')
plt.ylabel('Phase [deg]')
plt.grid(True)
# Digital transfer function through bilinear digitisation # Digital transfer function through bilinear digitisation
h_d = c2d(h_a, 1 / fs, 'bilinear') h_d = c2d(h_a, 1 / fs, 'bilinear')
num_d = h_d.num[0][0] # Inspect Hd.num to see why [0][0] is needed... num_d = h_d.num[0][0] # Inspect Hd.num to see why [0][0] is needed...
den_d = h_d.den[0][0] # Same story here den_d = h_d.den[0][0] # Same story here
# Digital frequency vector
w_d = np.logspace(np.log10(1), np.log10(fs / 2), 5000)
if plots:
# Digital filter frequency response
w_n, h_n = freqz(num_d, den_d, worN=w_d, fs=fs)
# Plot digital graph
# - Magnitude
plt.subplot(2, 1, 1)
plt.semilogx(w_n, 20 * np.log10(abs(h_n)), '--')
plt.legend(['Analog', 'Bilinear'])
# - Phase
plt.subplot(2, 1, 2)
plt.semilogx(w_n, np.angle(h_n) * 180 / np.pi, '--')
plt.legend(['Analog', 'Bilinear'])
# Pole check # Pole check
...@@ -772,38 +717,11 @@ def correction(a: array, b: array, paf: ndarray, fs: int, plots: bool) -> ndarra ...@@ -772,38 +717,11 @@ def correction(a: array, b: array, paf: ndarray, fs: int, plots: bool) -> ndarra
# Analog transfer function # Analog transfer function
hp_a = TransferFunction(ap, bp) hp_a = TransferFunction(ap, bp)
if plots:
# Analog filter frequency response
wp_t, hp_t = freqs(ap, bp, worN=w_a)
# Plot analog graph
# - Magnitude
plt.subplot(2, 1, 1)
plt.semilogx(wp_t / (2 * np.pi), 20 * np.log10(abs(hp_t)))
# - Phase
plt.subplot(2, 1, 2)
plt.semilogx(wp_t / (2 * np.pi), np.angle(hp_t) * 180 / np.pi)
# Digital transfer function through bilinear digitisation # Digital transfer function through bilinear digitisation
hp_d = c2d(hp_a, 1 / fs, 'bilinear') hp_d = c2d(hp_a, 1 / fs, 'bilinear')
num_d = hp_d.num[0][0] num_d = hp_d.num[0][0]
den_d = hp_d.den[0][0] den_d = hp_d.den[0][0]
if plots:
# Digital filter frequency response
wp_n, hp_n = freqz(num_d, den_d, worN=w_d, fs=fs)
# Plot digital graph
# - Magnitude
plt.subplot(2, 1, 1)
plt.semilogx(wp_n, 20 * np.log10(abs(hp_n)), '--')
plt.legend(['Analog', 'Bilinear', 'Pole - Analog', 'Pole - Digital'])
# - Phase
plt.subplot(2, 1, 2)
plt.semilogx(wp_n, np.angle(hp_n) * 180 / np.pi, '--')
plt.legend(['Analog', 'Bilinear', 'Pole - Analog', 'Pole - Digital'])
if plots:
plt.show()
print('\nFiltering Preservation Audio File...') print('\nFiltering Preservation Audio File...')
# Filter Preservation Audio File # Filter Preservation Audio File
raf = lfilter(num_d, den_d, paf, axis=0) raf = lfilter(num_d, den_d, paf, axis=0)
...@@ -855,7 +773,7 @@ def main(): ...@@ -855,7 +773,7 @@ def main():
print("You are using Python version: " + sys.version) print("You are using Python version: " + sys.version)
# Get the input from config.yaml or command line # Get the input from config.yaml or command line
working_path, files_name, standard_w, speed_w, standard_r, speed_r, plots = get_arguments() working_path, files_name, standard_w, speed_w, standard_r, speed_r = get_arguments()
# Check if input is correct # Check if input is correct
paf_path, temp_path, standard_w, standard_r = check_input(working_path, files_name, standard_w, speed_w, standard_r, speed_r) paf_path, temp_path, standard_w, standard_r = check_input(working_path, files_name, standard_w, speed_w, standard_r, speed_r)
...@@ -885,7 +803,7 @@ def main(): ...@@ -885,7 +803,7 @@ def main():
# Correction phase # Correction phase
if len(a) != 0: if len(a) != 0:
# Not all cases present a correction filter! # Not all cases present a correction filter!
raf = correction(paf, a, b, fs, plots) raf = correction(paf, a, b, fs)
save_file(raf, fs, temp_path, '1') save_file(raf, fs, temp_path, '1')
else: else:
# Just save Restored Audio File, but with modified fs # Just save Restored Audio File, but with modified fs
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment