波形を生成し音色を聞き比べる (2)#

C1S3_Timbre

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))
../../_images/3c435eb2581087d8dbc8e0a7db793dbfdcb76873769e78bf13bfc19e3105ce62.png

トレモロを加える#

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()
../../_images/a7cc1f3efab4ad02db1ed260f5d393426ec83fa1d871fe35afc54c0f3054a32e.png
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()
../../_images/b81351de5a40f1a87aa0c05d8426f8cc93fa3a3c59505c292043b1f9c6fad18b.png
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()
../../_images/30c1966119f8467798bde2f92dde07a3306ad084c0685babb3fccc5b2c897863.png
plot_spectrogram(x_trem, Fs=Fs, N=1024, H=256, figsize=(4, 3))
../../_images/71ee733f810870e711549c026c3db9d312b3ace37d0dba8975a4db362a05b1e9.png
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()
../../_images/ea991f9872336a2e32c042553c70033474d66ac74a7f7f118523addb31c9fb6c.png
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()
../../_images/425ee7d69dad63945b7fc4652f2ad5b3089d6a84abd235eeb4c750c6b093acf4.png
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()
../../_images/90704bd53e353305003c1ac9a244c3a1f698f32f1fdc7e3cf80d579689493d01.png
plot_spectrogram(x_vib, Fs=Fs, N=1024, H=256, figsize=(4, 3))
../../_images/4a1adb5587e6f5c4340e83cee7443440bebc788382af7e015d5abedcd6f712bb.png
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()
../../_images/91cca2cc84f2f71993d41c1027c486d4c6561cb6e180d1b170ef9ac38f2635af.png
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()
../../_images/3356f2268fae873ed68af61547d8262c801769954ca77f4a9dd6c432a511e215.png
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()
../../_images/cd6a849468573c906c9cd1933a0186f727f9e22fd81e0955fd4fc3c42b09ec96.png
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()
../../_images/82aa0217725b27211c9c1caf1f5fca951aa1c970acda1e792d970f650d7f6c43.png
ipd.display(ipd.Audio(data=x_vib, rate=Fs))
plot_spectrogram(x_vib, Fs=Fs, N=1024, H=256, figsize=(4, 3))
../../_images/e68f8e20a547f1f6ed2f765ba79216592b423d343e6bd00e58ae8958284f120b.png

バイオリンの波形を生成する#

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))
../../_images/2ffcadd88608f82cbd40d9f0245356680cedb91b0c645b4553fd3525e7ba683a.png
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))
../../_images/d4ccb5f0c0950e9b81e680ab0dc0d3014d44d184eadf4f83556751ab39fbcc61.png
ipd.display(ipd.Audio(data=x_violin, rate=Fs))