Advertisement
sesquiipedalian

Untitled

Mar 5th, 2023
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.56 KB | None | 0 0
  1. import numpy as np
  2. import scipy.signal as signal
  3. import scipy.fftpack as fft
  4. import wave
  5.  
  6. def stretch(signal, rate, window_size, h):
  7.     # Параметры алгоритма
  8.     factor = rate
  9.     window_size = int(window_size)
  10.     hop_size = int(window_size // h)
  11.  
  12.     # Фазовая информация
  13.     phase = np.zeros(window_size)
  14.     hanning_window = np.hanning(window_size)
  15.  
  16.     # Получение фазовой разности
  17.     def get_phase_diff(x_fft, y_fft):
  18.         angle_x = np.angle(x_fft)
  19.         angle_y = np.angle(y_fft)
  20.         return angle_y - angle_x
  21.  
  22.     # Реалзация алгоритма phase vocoder
  23.     resampled = signal
  24.     time_steps = np.arange(0, resampled.size - window_size, hop_size) / float(resampled.size)
  25.     w = 2 * np.pi * signal.hamming(window_size)
  26.  
  27.     # Разбиваем аудиозапись на окна
  28.     for t in time_steps:
  29.         # Применяем оконную функцию и получаем FFT
  30.         fft_window = fft.fft(w * resampled[int(t * resampled.size): int(t * resampled.size) + window_size])
  31.         fft_window = np.abs(fft_window) * np.exp(1j * phase)
  32.  
  33.         # Получаем амплитуду и фазу нового сигнала
  34.         ifft_window = fft.ifft(fft_window).real
  35.         ifft_window *= hanning_window
  36.         resampled[int(t * resampled.size) + hop_size: int(t * resampled.size) + window_size] += ifft_window[hop_size:]
  37.  
  38.         # Обновляем фазовую информацию
  39.         phase_diff = get_phase_diff(fft_window, fft.fft(w * resampled[int(t * resampled.size) + hop_size: int(t * resampled.size) + window_size + hop_size]))
  40.         phase_diff = np.angle(phase_diff)
  41.         phase = (phase + phase_diff) % (2 * np.pi)
  42.  
  43.     # Применяем растяжение/сжатие
  44.     resampled = signal.resample(resampled, int(len(resampled) // factor))
  45.     return resampled.astype(np.float32)
  46.  
  47. def change_speed(filename, rate):
  48.     # Чтение wav-файла
  49.     with wave.open(filename, 'rb') as wave_file:
  50.         signal = np.frombuffer(wave_file.readframes(-1), dtype='int16')
  51.  
  52.     # Определение параметров алгоритма
  53.     window_size = 2**13
  54.     h = 4
  55.  
  56.     # Применение алгоритма phase vocoder
  57.     stretched_signal = stretch(signal, rate, window_size, h)
  58.  
  59.     # Запись нового wav-файла
  60.     with wave.open('output.wav', 'wb') as wave_file:
  61.         wave_file.setparams(wave_file.getparams())
  62.         wave_file.writeframes(stretched_signal.tobytes())
  63.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement