In [1]:
import waloviz as wv

wv.extension()
No description has been provided for this image No description has been provided for this image
In [2]:
# Utilities for playing music

import numpy as np
sr = 8000
notes = {"G": 392.00, "A": 440.00, "B": 493.88, "C": 523.25, "D": 587.33, "E": 659.26, "F": 698.46}

def pause(seconds: float):
    return np.zeros(int(seconds*sr))

def play(note: str, seconds: float):
    pause_seconds = 0.1
    note_seconds = seconds - pause_seconds
    time = np.linspace(0, 2*np.pi*note_seconds, int(sr*note_seconds))
    freq = notes[note]
    sound = np.sin(time*freq)
    pause_samples = int(pause_seconds*sr)
    sound[:pause_samples] = sound[:pause_samples] * np.linspace(0, 1, pause_samples)
    sound[-pause_samples:] = sound[-pause_samples:] * np.linspace(1, 0, pause_samples)
    return np.concatenate([sound, pause(pause_seconds)], axis=-1)
In [3]:
# Playing a happy little melody for a happy little star!

twinkle_melody = np.concatenate([
    play("G", 0.25), play("G", 0.25), 
    play("D", 0.25), play("D", 0.25), 
    play("E", 0.25), play("E", 0.25), 
    play("D", 0.40), pause(0.1),
    play("C", 0.25), play("C", 0.25), 
    play("B", 0.25), play("B", 0.25), 
    play("A", 0.25), play("A", 0.25), 
    play("G", 0.40), pause(0.1),
])

wv.Audio(
    (twinkle_melody, sr), 
    {note: np.ones(2)*freq for note, freq in reversed(notes.items())},
    over_curve_axes={note: "Hz" for note in notes.keys()},
    axes_limits=dict(Hz=(350, 750)),
    minimal=True
)
Out[3]: