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;
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;
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;
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.
6. `SPEED_R` that specifies the speed used when reading the tape.
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`
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.
......
......@@ -15,7 +15,4 @@ SPEED_W: 7.5
STANDARD_R: "CCIR"
# Reading tape speed [ips].
# Accepted values: (3.75, 7.5, 15, 30)
SPEED_R: 15
# Enable plotting filter frequency responses
# Accepted values: (true, false)
PLOTS: false
\ No newline at end of file
SPEED_R: 15
\ No newline at end of file
......@@ -10,7 +10,6 @@ It identifies and restore portions of the Preservation Audio File, providing:
"""
import array
import matplotlib.pyplot as plt
import numpy as np
import os
import shutil
......@@ -20,7 +19,7 @@ from argparse import ArgumentParser, RawTextHelpFormatter
from control import c2d, TransferFunction
from numpy import ndarray
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"
__copyright__ = "Copyright 2022, Audio Innova S.r.l."
......@@ -48,7 +47,7 @@ class CC:
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.
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]:
3) str specifying the equalization standard 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;
6) float specifying the speed used when the tape was read;
7) bool specifying if filter figures should be plotted.
6) float specifying the speed used when the tape was read.
"""
if len(sys.argv) > 1:
......@@ -120,12 +118,6 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]:
speed_w = float(args.speed_w)
standard_r = args.equalization_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:
# Read configuration file
config = object
......@@ -149,9 +141,6 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]:
if 'SPEED_R' not in config:
print(CC.RED + 'SPEED_R key not found in config.yaml!' + CC.END)
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:
print(CC.RED + 'config.yaml file not found!' + CC.END)
quit(os.EX_NOINPUT)
......@@ -161,13 +150,7 @@ def get_arguments() -> tuple[str, str, str, float, str, float, bool]:
speed_w = config['SPEED_W']
standard_r = config['STANDARD_R']
speed_r = config['SPEED_R']
plots = False
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
return working_path, files_name, standard_w, speed_w, standard_r, speed_r
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
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;
: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 paf: ndarray specifying the raw audio data of the Preservation Audio File,
:param fs: int specifying the operational sampling frequency,
:param plots: bool specifying if filter plots should be displayed.
:param fs: int specifying the operational sampling frequency.
:return: the corrected audio as a Restored Audio File.
"""
# Analog transfer function
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
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...
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
......@@ -772,38 +717,11 @@ def correction(a: array, b: array, paf: ndarray, fs: int, plots: bool) -> ndarra
# Analog transfer function
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
hp_d = c2d(hp_a, 1 / fs, 'bilinear')
num_d = hp_d.num[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...')
# Filter Preservation Audio File
raf = lfilter(num_d, den_d, paf, axis=0)
......@@ -855,7 +773,7 @@ def main():
print("You are using Python version: " + sys.version)
# 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
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():
# Correction phase
if len(a) != 0:
# 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')
else:
# 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