import os
import torch
import torchaudio
from IPython.display import Audio
import numpy as np
from scipy.fft import fft, ifft
import matplotlib.pyplot as plt
import pandas as pd
import scipy
import random
from collections import Counter
from tqdm import tqdm
from matplotlib.pyplot import imshow
import Phase_Vocoder as pv
import yin_pitch_prediction as yin
wav_path = '/Users/ginoprasad/autotune/m4a_files/grapevine.m4a'
sample, sample_rate = torchaudio.load(wav_path)
sample = sample[0].numpy()
sample = sample[int(sample_rate*20):int(sample_rate*44)]
Audio(sample, rate=sample_rate)
def notes_in_scale(root, major=True):
pattern = [True, False, True, False, True, True, False, True, False, True, False, True]
scale = pd.DataFrame(yin.prelim_notes)[0]
index = list(scale).index(root)
if not major:
index += 3
index %= len(scale)
scale = np.concatenate([scale[index:], scale[:index]])[pattern]
# print(scale)
return [x for x in yin.notes if any(x[1][:-1] == y for y in scale)]
yin.W = 100 / yin.sample_rate
yin.min_frequency = 70
yin.max_frequency = 200
scale = notes_in_scale('D#', major=False)
frequencies = []
prev_analysis = np.zeros((pv.W//2)+1)
prev_shifted = np.zeros_like(prev_analysis)
output = np.zeros_like(sample)
for start_index in tqdm(range(0, len(sample), pv.H)):
splice = sample[start_index:start_index+pv.W]
if len(splice) < pv.W:
break
freq = yin.pitch_predict(splice)
closest_index = np.argmin(np.abs(pd.DataFrame(scale)[0] - freq)) if freq is not None else None
closest = pd.DataFrame(scale)[0][closest_index] if closest_index is not None else None
if freq is None:
processed_splice = splice
else:
frequencies.append(freq)
R = closest / freq
processed_splice, prev_analysis, prev_shifted = pv.pitch_shift(splice, R, prev_analysis, prev_shifted)
output[start_index:start_index+len(splice)] += (pv.hann_window[:len(splice)] * processed_splice)
100%|█████████████████████▉| 5993/6000 [00:44<00:00, 134.29it/s]
Audio(output, rate=sample_rate)
song_name = 'grapevine'
torchaudio.save(f'/Users/ginoprasad/Downloads/{song_name}.wav', torch.Tensor(np.expand_dims(sample, 0)), sample_rate=sample_rate)
torchaudio.save(f'/Users/ginoprasad/Downloads/autotuned_{song_name}.wav', torch.Tensor(np.expand_dims(output, 0)), sample_rate=sample_rate)