This is one of the 100 recipes of the IPython Cookbook, the definitive guide to high-performance scientific computing and data science in Python.
You need to download the Piano dataset on the book's website. (http://ipython-books.github.io)
This dataset contains synthetized piano notes obtained on archive.org
(CC0 1.0 Universal licence). (https://archive.org/details/SynthesizedPianoNotes)
import numpy as np
import os
from IPython.display import Audio, display, clear_output
from IPython.html import widgets
from functools import partial
<audio>
element.dir = 'data/synth'
# This is the list of notes.
notes = 'C,C#,D,D#,E,F,F#,G,G#,A,A#,B,C'.split(',')
def play(note, octave=0):
"""This function displays an HTML Audio element
that plays automatically when it appears."""
f = os.path.join(dir,
"piano_{i}.mp3".format(i=note+12*octave))
clear_output()
display(Audio(filename=f, autoplay=True))
piano
will contain 12 buttons for the 12 notes.piano = widgets.ContainerWidget()
octave_slider = widgets.IntSliderWidget()
octave_slider.max = 1
octave_slider
ButtonWidget
object. Then, we specify a callback function that plays the corresponding note (given by an index) at a given octave (given by the current value of the octave slider). Finally, we set the CSS of each button, notably the white or black color.buttons = []
for i, note in enumerate(notes):
button = widgets.ButtonWidget(description=note)
def on_button_clicked(i, _):
play(i+1, octave_slider.value)
button.on_click(partial(on_button_clicked, i))
button.set_css({'width': '30px',
'height': '60px',
'padding': '0',
'color': ('black',
'white')['#' in note],
'background': ('white', 'black')['#' in note],
'border': '1px solid black',
'float': 'left'})
buttons.append(button)
piano
container contains the buttons, and the main container (container
) contains the slider and the piano.piano.children = buttons
container = widgets.ContainerWidget()
container.children = [octave_slider,
piano]
By default, widgets are organized vertically within a container. Here, the octave slider will be above the piano.
display(container)
piano.remove_class('vbox')
piano.add_class('hbox')
Within the piano, we want all notes to be arranged horizontally. We do this by replacing the default vbox
CSS class by the hbox
class.
You'll find all the explanations, figures, references, and much more in the book (to be released later this summer).
IPython Cookbook, by Cyrille Rossant, Packt Publishing, 2014 (500 pages).