{ "metadata": { "name": "", "signature": "sha256:b13b82ab2b72800124dcad04c4a86dec0eacb33450bbbe804429e02c958a32dc" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": [], "source": [ "> This is one of the 100 recipes of the [IPython Cookbook](http://ipython-books.github.io/), the definitive guide to high-performance scientific computing and data science in Python.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 11.7. Creating a sound synthesizer in the notebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. We import NumPy, matplotlib, and various IPython packages and objects." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from IPython.display import Audio, display, clear_output\n", "from IPython.html import widgets\n", "from functools import partial\n", "import matplotlib as mpl\n", "%matplotlib inline\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. We define the sampling rate and the duration of the notes." ] }, { "cell_type": "code", "collapsed": false, "input": [ "rate = 16000.\n", "duration = .5\n", "t = np.linspace(0., duration, rate * duration)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3. We create a function that generates and plays the sound of a note (sine function) at a given frequency, using NumPy and IPython's `Audio` class." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def synth(f):\n", " x = np.sin(f * 2. * np.pi * t)\n", " display(Audio(x, rate=rate, autoplay=True))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "4. Here is the fundamental 440 Hz note." ] }, { "cell_type": "code", "collapsed": false, "input": [ "synth(440)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "5. Now, we generate the note frequencies of our piano. The chromatic scale is obtained by a geometric progression with common ratio $2^{1/12}$." ] }, { "cell_type": "code", "collapsed": false, "input": [ "notes = zip('C,C#,D,D#,E,F,F#,G,G#,A,A#,B,C'.split(','),\n", " 440. * 2 ** (np.arange(3, 17) / 12.))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "6. Finally, we create the piano with the notebook widgets. Each note is a button, and all buttons are contained in an horizontal box container. Clicking on one note plays a sound at the corresponding frequency." ] }, { "cell_type": "code", "collapsed": false, "input": [ "container = widgets.ContainerWidget()\n", "buttons = []\n", "for note, f in notes:\n", " button = widgets.ButtonWidget(description=note)\n", " def on_button_clicked(f, b):\n", " clear_output()\n", " synth(f)\n", " button.on_click(partial(on_button_clicked, f))\n", " button.set_css({'width': '30px', \n", " 'height': '60px',\n", " 'padding': '0',\n", " 'color': ('black', 'white')['#' in note],\n", " 'background': ('white', 'black')['#' in note],\n", " 'border': '1px solid black',\n", " 'float': 'left'})\n", " buttons.append(button)\n", "container.children = buttons\n", "display(container)\n", "container.remove_class('vbox')\n", "container.add_class('hbox')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> You'll find all the explanations, figures, references, and much more in the book (to be released later this summer).\n", "\n", "> [IPython Cookbook](http://ipython-books.github.io/), by [Cyrille Rossant](http://cyrille.rossant.net), Packt Publishing, 2014 (500 pages)." ] } ], "metadata": {} } ] }