The world of digital audio processing offers a myriad of possibilities. One intriguing experiment is to combine the audio spectrum of two songs to produce a unique amalgamation of sounds. In this article, we'll walk you through how to combine the spectra of two YouTube songs, apply modifications, and recreate an audio file from the modified spectrum.
The audio spectrum provides a representation of a sound in terms of the frequencies that constitute it. By using the Fourier Transform, we can convert a time-domain signal (audio waveform) into its frequency-domain representation.
To begin, we will extract the audio from two YouTube links and represent each song's audio in terms of its amplitude spectrum and phase spectrum.
import numpy as np
def get_spectrum(y):
spectrum = np.fft.fft(y)
amplitude = np.abs(spectrum)
phase = np.angle(spectrum)
return amplitude, phase
The amplitude gives the magnitude of each frequency, and the phase gives the angle (or phase shift) of each frequency component.
After extracting the amplitude and phase spectra of both songs, we'll combine their amplitude spectra. To do this, we average the amplitudes of the corresponding frequencies of the two songs. If the songs have different lengths, we'll pad the shorter song with zeros to match the length of the longer one.
def combine_spectrums(amplitude1, amplitude2):
combined_amplitude = (amplitude1 + amplitude2) / 2
return combined_amplitude
Now, for a touch of creativity! We'll attenuate the frequencies above a certain cutoff frequency in our combined spectrum. This acts as a basic low-pass filter, emphasizing the lower frequencies and muting the higher ones.
def modify_spectrum(amplitude, cutoff_frequency, sr):
frequencies = np.fft.fftfreq(len(amplitude), 1 / sr)
amplitude[frequencies > cutoff_frequency] *= 0.1
return amplitude
With our modified amplitude spectrum in hand, we can use the inverse Fourier transform to recreate the time-domain signal, producing our new audio.
def inverse_transform(amplitude, phase):
complex_spectrum = amplitude * np.exp(1j * phase)
y_recreated = np.fft.ifft(complex_spectrum).real
return y_recreated
We'll then save this recreated audio as a .wav file, ready for playback!