波形を生成し音色を聞き比べる (2)#
import numpy as np
import matplotlib.pyplot as plt
import libfmp.b
import libfmp.c1
def plot_spectrogram(x, Fs=11025, N=4096, H=2048, figsize=(4, 2)):
"""Computation and subsequent plotting of the spectrogram of a signal
Notebook: C1/C1S3_Timbre.ipynb
Args:
x: Signal (waveform) to be analyzed
Fs: Sampling rate (Default value = 11025)
N: FFT length (Default value = 4096)
H: Hopsize (Default value = 2048)
figsize: Size of the figure (Default value = (4, 2))
"""
# N, H = 2048, 1024
X = librosa.stft(x, n_fft=N, hop_length=H, win_length=N, window=np.hanning) # not 'hamming'
Y = np.abs(X)
plt.figure(figsize=figsize)
librosa.display.specshow(librosa.amplitude_to_db(Y, ref=np.max),
y_axis='linear', x_axis='time', sr=Fs, hop_length=H) # cmap='gray_r'
plt.ylim([0, 3000])
# plt.colorbar(format='%+2.0f dB')
plt.xlabel('Time (seconds)')
plt.ylabel('Frequency (Hz)')
plt.tight_layout()
plt.show()
import librosa
import IPython.display as ipd
Fs = 11025
dur = 4
freq = 261.626
amp = 0.5
figsize = (8, 2)
num_samples = int(Fs * dur)
正弦波 (sinusoid) を生成する#
x, t = libfmp.c1.generate_sinusoid(dur=dur, Fs=Fs, amp=amp, freq=freq)
plot_spectrogram(x, Fs=Fs, N=1024, H=256, figsize=(4, 3))

トレモロを加える#
def generate_sinusoid_tremolo(dur=5, Fs=1000, amp=0.5, freq=440, trem_amp=0.1, trem_rate=5):
"""Generation of a sinusoid signal with tremolo
Notebook: C1/C1S3_Timbre.ipynb
Args:
dur (float): Duration (in seconds) (Default value = 5)
Fs (scalar): Sampling rate (Default value = 1000)
amp (float): Amplitude of sinusoid (Default value = 0.5)
freq (float): Frequency (Hz) of sinusoid (Default value = 440)
trem_amp (float): Amplitude of the amplitude oscillation (Default value = 0.1)
trem_rate (float): Rate (Hz) of the amplitude oscillation (Default value = 5)
Returns:
x (np.ndarray): Generated signal
t (np.ndarray): Time axis (in seconds)
"""
num_samples = int(Fs * dur)
t = np.arange(num_samples) / Fs
amps = amp + trem_amp * np.sin(t * 2 * np.pi * trem_rate)
x = amps * np.sin(2*np.pi*(freq*t))
return x, t
x_trem, t = generate_sinusoid_tremolo(dur=dur, Fs=Fs, amp=amp, freq=freq, trem_amp=0.3, trem_rate=5)
libfmp.b.plot_signal(x_trem, Fs=Fs, figsize=figsize, ylabel='Amplitude', title='Sinusoid with tremolo')
plt.ylim([-0.9, 0.9])
plt.show()

libfmp.b.plot_signal(x_trem, Fs=Fs, figsize=figsize, ylabel='Amplitude', title='Sinusoid with tremolo')
plt.ylim([-0.9, 0.9])
plt.xlim([0, 1])
plt.show()

libfmp.b.plot_signal(x_trem, Fs=Fs, figsize=figsize, ylabel='Amplitude', title='Sinusoid with tremolo')
plt.ylim([-0.9, 0.9])
plt.xlim([0, .5])
plt.show()

plot_spectrogram(x_trem, Fs=Fs, N=1024, H=256, figsize=(4, 3))

ipd.display(ipd.Audio(data=x_trem, rate=Fs))
ビブラートを加える#
def generate_sinusoid_vibrato(dur=5, Fs=1000, amp=0.5, freq=440, vib_amp=1, vib_rate=5):
"""Generation of a sinusoid signal with vibrato
Notebook: C1/C1S3_Timbre.ipynb
Args:
dur (float): Duration (in seconds) (Default value = 5)
Fs (scalar): Sampling rate (Default value = 1000)
amp (float): Amplitude of sinusoid (Default value = 0.5)
freq (float): Frequency (Hz) of sinusoid (Default value = 440)
vib_amp (float): Amplitude (Hz) of the frequency oscillation (Default value = 1)
vib_rate (float): Rate (Hz) of the frequency oscillation (Default value = 5)
Returns:
x (np.ndarray): Generated signal
t (np.ndarray): Time axis (in seconds)
"""
num_samples = int(Fs * dur)
t = np.arange(num_samples) / Fs
freq_vib = freq + vib_amp * np.sin(t * 2 * np.pi * vib_rate)
phase_vib = np.zeros(num_samples)
for i in range(1, num_samples):
phase_vib[i] = phase_vib[i-1] + 2 * np.pi * freq_vib[i-1] / Fs
x = amp * np.sin(phase_vib)
return x, t
x_vib, t = generate_sinusoid_vibrato(dur=dur, Fs=Fs, amp=amp, freq=freq, vib_amp=10, vib_rate=5)
libfmp.b.plot_signal(x_vib, Fs=Fs, figsize=figsize, ylabel='Amplitude', title='Sinusoid with vibrato')
plt.ylim([-0.9, 0.9])
plt.show()

libfmp.b.plot_signal(x_vib, Fs=Fs, figsize=figsize, ylabel='Amplitude', title='Sinusoid with vibrato')
plt.ylim([-0.9, 0.9])
plt.xlim([0, 1])
plt.show()

libfmp.b.plot_signal(x_vib, Fs=Fs, figsize=figsize, ylabel='Amplitude', title='Sinusoid with vibrato')
plt.ylim([-0.9, 0.9])
plt.xlim([0, .1])
plt.show()

plot_spectrogram(x_vib, Fs=Fs, N=1024, H=256, figsize=(4, 3))

ipd.display(ipd.Audio(data=x_vib, rate=Fs))
ADSRを加える#
import libfmp.b
import libfmp.c1
%matplotlib inline
def compute_adsr(len_A=10, len_D=10, len_S=60, len_R=10, height_A=1.0, height_S=0.5):
"""Computation of idealized ADSR model
Notebook: C1/C1S3_Timbre.ipynb
Args:
len_A (int): Length (samples) of A phase (Default value = 10)
len_D (int): Length (samples) of D phase (Default value = 10)
len_S (int): Length (samples) of S phase (Default value = 60)
len_R (int): Length (samples) of R phase (Default value = 10)
height_A (float): Height of A phase (Default value = 1.0)
height_S (float): Height of S phase (Default value = 0.5)
Returns:
curve_ADSR (np.ndarray): ADSR model
"""
curve_A = np.arange(len_A) * height_A / len_A
curve_D = height_A - np.arange(len_D) * (height_A - height_S) / len_D
curve_S = np.ones(len_S) * height_S
curve_R = height_S * (1 - np.arange(1, len_R + 1) / len_R)
curve_ADSR = np.concatenate((curve_A, curve_D, curve_S, curve_R))
return curve_ADSR
curve_ADSR = compute_adsr(len_A=int(x.size*0.3), len_D=int(x.size*0.3), len_S=int(x.size*0.3), len_R=int(x.size*0.1), height_A=1.0, height_S=0.8)
libfmp.b.plot_signal(curve_ADSR, figsize=(4,2.5), ylabel='Amplitude', title='ADSR model', color='red')
plt.show()

x_vib.size, curve_ADSR.size
(44100, 44100)
x_vib *= curve_ADSR
libfmp.b.plot_signal(x_vib, Fs=Fs, figsize=figsize, ylabel='Amplitude', title='Sinusoid')
plt.ylim([-0.9, 0.9])
plt.show()

libfmp.b.plot_signal(x_vib, Fs=Fs, figsize=figsize, ylabel='Amplitude', title='Sinusoid')
plt.ylim([-0.9, 0.9])
plt.xlim([0, 1])
plt.show()

libfmp.b.plot_signal(x_vib, Fs=Fs, figsize=figsize, ylabel='Amplitude', title='Sinusoid')
plt.ylim([-0.9, 0.9])
plt.xlim([0, .1])
plt.show()

ipd.display(ipd.Audio(data=x_vib, rate=Fs))
plot_spectrogram(x_vib, Fs=Fs, N=1024, H=256, figsize=(4, 3))

バイオリンの波形を生成する#
t = np.arange(num_samples) / Fs
x = np.arange(num_samples) / Fs
for i in range(1, 12):
x_vib, t = generate_sinusoid_vibrato(dur=dur, Fs=Fs, amp=8/(i**(4/3)), freq=freq*i, vib_amp=i*2, vib_rate=5)
x += x_vib * curve_ADSR
plot_spectrogram(x, Fs=Fs, N=1024, H=256, figsize=(4, 3))

ipd.display(ipd.Audio(data=x, rate=Fs))
x_violin, Fs = librosa.load('./FMP_C1_F23_Violin.wav', sr=Fs)
plot_spectrogram(x_violin, Fs=Fs, N=1024, H=256, figsize=(4, 3))

ipd.display(ipd.Audio(data=x_violin, rate=Fs))