{
 "metadata": {
  "name": "",
  "signature": "sha256:eaf3c7682d4b7de77074a247b83c31a5dd8257441eb59f23d9951f0ae352f13e"
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "Exercise: Instrument Classification using K-NN"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "This is an *exercise* notebook. It's a playground for your Python code. Feel free to write and execute your code without fear.\n",
      "\n",
      "When you see a cell that looks like this:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "plot?"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 1
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "that is a cue to use a particular command, in this case, `plot`. Run the cell to see documentation for that command. (To quickly close the Help window, press `q`.) \n",
      "\n",
      "For more documentation, visit the links in the Help menu above. Also see the other notebooks; all the exercises here are covered somewhere else in separate notebooks."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "This exercise is loosely based upon \"Lab 1\" from previous MIR workshops ([2010](https://ccrma.stanford.edu/workshops/mir2010/Lab1_2010.pdf))."
     ]
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Goals"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "1. Extract spectral features from an audio signal.\n",
      "2. Train a K-Nearest Neighbor classifier.\n",
      "3. Use the classifier to classify beats in a drum loop."
     ]
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Step 1: Retrieve Audio, Detect Onsets, and Segment"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "[Follow the same steps here.](feature_sonification.ipynb#Step-1:-Retrieve-Audio)\n",
      "\n",
      "1. Download the file `simpleLoop.wav` onto your local machine.\n",
      "1. Save the audio signal into an array.\n",
      "1. Find the times, in seconds, when onsets occur in the audio signal.\n",
      "1. Save into an array, `segments`, 100-ms segments beginning at each onset."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import urllib\n",
      "url = 'https://ccrma.stanford.edu/workshops/mir2014/audio/simpleLoop.wav'\n",
      "urllib.urlretrieve?"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 2
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from essentia.standard import MonoLoader\n",
      "MonoLoader?"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 3
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "fs = 44100\n",
      "frame_sz = int(0.1*fs)\n",
      "import essentia\n",
      "segments = essentia.array([rand(frame_sz), rand(frame_sz)]) # placeholder"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 4
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Step 2: Extract MFCCs"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "For each segment, compute the MFCCs."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from essentia.standard import MFCC, Spectrum, Windowing\n",
      "hamming_window = Windowing(type='hamming')\n",
      "spectrum = Spectrum()  # we just want the magnitude spectrum\n",
      "mfcc = MFCC()\n",
      "\n",
      "mfccs = array([mfcc(spectrum(hamming_window(frame)))[1]\n",
      "               for frame in segments])\n",
      "\n",
      "imshow(mfccs[:,1:].T, origin='lower', aspect='auto', interpolation='nearest') # Ignore the 0th MFCC\n",
      "yticks(range(12), range(1,13)) # Ignore the 0th MFCC\n",
      "ylabel('MFCC Coefficient Index')\n",
      "xlabel('Segment Index')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 5,
       "text": [
        "<matplotlib.text.Text at 0x47e3150>"
       ]
      },
      {
       "metadata": {},
       "output_type": "display_data",
       "png": "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\ngg==\n",
       "text": [
        "<matplotlib.figure.Figure at 0x47ddd50>"
       ]
      }
     ],
     "prompt_number": 5
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Step 3: Train K-NN Classifier"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "For training, see [Training Data](#Training-Data) below.\n",
      "\n",
      "For more on K-NN, see the [notebook on K-NN](../notebooks/knn.ipynb)."
     ]
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Step 4: Run the Classifier"
     ]
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Step 5: Sonify the Classifier Output"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Play a \"beep\" for each detected kick drum."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from essentia.standard import AudioOnsetsMarker\n",
      "AudioOnsetsMarker?"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 6
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Play a \"beep\" for each detected snare drum."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from essentia.standard import AudioOnsetsMarker\n",
      "AudioOnsetsMarker?"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 7
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Bonus"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "In addition to the MFCCs, extract the following features:\n",
      "\n",
      "- spectral centroid\n",
      "- spectral spread\n",
      "- spectral skewness\n",
      "- spectral kurtosis. "
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from essentia.standard import CentralMoments, DistributionShape\n",
      "DistributionShape?"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 8
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Re-train the classifier, and re-run the classifier over the test audio signal. Do the results change?"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Repeat the steps above for the following audio files:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "url = 'https://ccrma.stanford.edu/workshops/mir2014/audio/CongaGroove-mono.wav'\n",
      "url = 'https://ccrma.stanford.edu/workshops/mir2014/audio/125BOUNC-mono.WAV'"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 9
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Training Data"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "First, we want to analyze and feature extract a small collection of audio samples - storing their feature data as our \"training data\".  The commands below read all of the drum example .wav files from the MIR web site into an array, `snare_file_list`.  \n",
      "\n",
      "Let's define a function to retrieve a list of URLs from a text file."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import urllib2\n",
      "\n",
      "def process_corpus(corpus_URL):\n",
      "    \"\"\"Read a list of files to process from the text file at corpusURL. Return a list of URLs\"\"\" \n",
      "    # Open and read each line\n",
      "    url_list_text_data = urllib2.urlopen(corpus_URL) # it's a file like object and works just like a file\n",
      "    for file_URL in url_list_text_data: # files are iterable\n",
      "        yield file_URL.rstrip()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 1
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Use these commands to read in a list of filenames (samples) in a directory, replacing the URL with a URL to a list of URLs (one per line) indicating where the audio / drum samples are stored."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "snares_URL = \"https://ccrma.stanford.edu/workshops/mir2014/SnareCorpus.txt\"\n",
      "snare_file_list = [audio_file_URL for audio_file_URL in process_corpus(snares_URL)]"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 2
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "kicks_URL = \"https://ccrma.stanford.edu/workshops/mir2014/KickCorpus.txt\"\n",
      "kick_file_list = [audio_file_URL for audio_file_URL in process_corpus(kicks_URL)]"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 3
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "To access the filenames contained in the array, use the square brackets [ ] to get to the element that you want to access. For example, to access the text URL file name of the first file in the list, you would type:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "snare_URL = snare_file_list[0]\n",
      "snare_URL"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 5,
       "text": [
        "'https://ccrma.stanford.edu/workshops/mir2014/audio/drum%20samples/snares/SNARE_01_01.WAV'"
       ]
      }
     ],
     "prompt_number": 5
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "When we feature extract a sample collection, we need to sequentially access audio files, segment them (or not), and feature extract them.  Loading a lot of audio files into memory is not always a feasible or desirable operation, so you will create a loop which loads an audio file, feature extracts it, and closes  the audio file.  Note that the only information that we retain in memory are the features that are extracted.\n",
      "\n",
      "Create a loop which reads in an audio file, extracts the zero crossing rate, and some spectral statistics. You can use the \"in\" operator to retrieve each audio file URL from process_corpus(), as used above. The feature information for each audio file (the \"feature vector\") should be stored as a feature array, with columns being the features and rows for each file. For example:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from essentia.standard import ZeroCrossingRate\n",
      "zcr = ZeroCrossingRate()\n",
      "\n",
      "\n",
      "number_of_files = 20\n",
      "number_of_features = 5\n",
      "features_snare = []"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 14
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      " For example, when populated, features_snare might look like:\n",
      " \n",
      "    features_snare =\n",
      "\n",
      "             0.5730    1.9183    2.9713    0.0004  0.0002\n",
      "             0.4750    1.4834    2.4463    0.0004  0.0012\n",
      "             0.5900    2.2857    3.1788    0.0003  0.0041\n",
      "             0.5090    1.6622    2.6369    0.0004  0.0051\n",
      "             0.4860    1.4758    2.2085    0.0004  0.0021\n",
      "             0.6060    2.2119    3.2798    0.0004  0.0651\n",
      "             0.4990    2.0607    2.7654    0.0004  0.0721\n",
      "             0.6360    2.3153    3.0256    0.0003  0.0221\n",
      "             0.5490    2.0137    3.0342    0.0004  0.0016\n",
      "             0.5900    2.2857    3.1788    0.0003  0.0012\n",
      " \n",
      " Within your loop, here's a reminder how to read in your wav files, using an array of audio file URLs:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import urllib\n",
      "from essentia.standard import MonoLoader, ZeroCrossingRate, Centroid, CentralMoments, DistributionShape, Spectrum, Windowing\n",
      "hamming_window = Windowing(type='hamming')\n",
      "zcr = ZeroCrossingRate()\n",
      "centroid = Centroid()\n",
      "spectrum = Spectrum()\n",
      "centralmoments = CentralMoments()\n",
      "distributionshape = DistributionShape()\n",
      "\n",
      "fs = 44100\n",
      "features_table = []\n",
      "for url in snare_file_list + kick_file_list:\n",
      "    urllib.urlretrieve(url, filename='/tmp/localfile.wav')\n",
      "    audio = MonoLoader(filename = '/tmp/localfile.wav', sampleRate = fs)() \n",
      "    frame = audio[:int(0.2*fs)]\n",
      "    feature_vector = []\n",
      "    feature_vector.append( zcr(frame) )\n",
      "    spectral_magnitude = spectrum(hamming_window(frame))\n",
      "    feature_vector.append( centroid(spectral_magnitude) )\n",
      "    spectral_moments = distributionshape(centralmoments(spectral_magnitude))\n",
      "    feature_vector.extend( spectral_moments )\n",
      "    features_table.append( feature_vector )\n",
      "\n",
      "\n",
      "features_table = array(features_table)\n",
      "print features_table"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "[[  1.62471652e-01   2.36405745e-01   4.00112346e-02   7.53566146e-01\n",
        "   -1.77525520e-01]\n",
        " [  1.16666667e-01   2.21813351e-01   3.49240005e-02   6.74486637e-01\n",
        "   -4.22939777e-01]\n",
        " [  1.21882088e-01   2.16630742e-01   3.44936140e-02   6.97950125e-01\n",
        "   -4.12385702e-01]\n",
        " [  9.18367356e-02   2.04460323e-01   3.14886980e-02   8.07589829e-01\n",
        "   -6.42979145e-02]\n",
        " [  1.61904767e-01   2.71532953e-01   4.19509038e-02   5.50324261e-01\n",
        "   -4.77055550e-01]\n",
        " [  1.30045354e-01   2.28676051e-01   3.80903184e-02   8.45433593e-01\n",
        "   -2.10921764e-02]\n",
        " [  1.40249431e-01   2.51602560e-01   4.26780917e-02   7.59979486e-01\n",
        "   -2.06123590e-01]\n",
        " [  1.52721092e-01   2.53082067e-01   4.44976576e-02   7.05894053e-01\n",
        "   -2.62273788e-01]\n",
        " [  1.33673474e-01   2.60320574e-01   4.03219834e-02   6.03728771e-01\n",
        "   -3.55994463e-01]\n",
        " [  1.17913835e-01   2.16710851e-01   3.01928632e-02   8.90169322e-01\n",
        "    4.26502228e-01]\n",
        " [  6.80272095e-03   5.47488108e-02   1.58221014e-02   3.10297251e+00\n",
        "    1.05381603e+01]\n",
        " [  5.44217695e-03   3.13566811e-02   7.53624039e-03   4.57224989e+00\n",
        "    2.59836254e+01]\n",
        " [  4.08163248e-03   1.71935484e-02   2.87185842e-03   7.22230673e+00\n",
        "    7.60733871e+01]\n",
        " [  4.30838997e-03   4.21788730e-02   1.12768942e-02   3.60826254e+00\n",
        "    1.51811485e+01]\n",
        " [  6.12244895e-03   3.37548926e-02   1.01857409e-02   4.76424742e+00\n",
        "    2.65034351e+01]\n",
        " [  5.55555569e-03   2.49018725e-02   6.05471013e-03   5.12525940e+00\n",
        "    3.25076065e+01]\n",
        " [  5.32879820e-03   2.85752080e-02   7.12108333e-03   5.20154762e+00\n",
        "    3.39053345e+01]\n",
        " [  4.30838997e-03   3.50905433e-02   9.30536166e-03   4.14755917e+00\n",
        "    2.00502682e+01]\n",
        " [  5.89569146e-03   3.92675437e-02   8.93500820e-03   3.75893021e+00\n",
        "    1.77870655e+01]\n",
        " [  5.78231271e-03   2.72752997e-02   7.65201543e-03   5.09223413e+00\n",
        "    3.01892776e+01]]\n"
       ]
      }
     ],
     "prompt_number": 20
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from sklearn import preprocessing\n",
      "import numpy as np\n",
      "\n",
      "scaler = preprocessing.MinMaxScaler(feature_range = (-1, 1))\n",
      "training_features = scaler.fit_transform(features_table)\n",
      "\n",
      "scaler.get_params()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 33,
       "text": [
        "{'copy': True, 'feature_range': (-1, 1)}"
       ]
      }
     ],
     "prompt_number": 33
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from sklearn.neighbors import KNeighborsClassifier\n",
      "\n",
      "model_snare = KNeighborsClassifier(n_neighbors = 1)\n",
      "model_snare.fit(training_features, concatenate([zeros(10), ones(10)]))"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 29,
       "text": [
        "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n",
        "           n_neighbors=1, p=2, weights='uniform')"
       ]
      }
     ],
     "prompt_number": 29
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "\n",
      "print model_snare.predict(training_features[-1])"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "[ 1.]\n"
       ]
      }
     ],
     "prompt_number": 32
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Appendix"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from urlparse import urljoin\n",
      "\n",
      "kick_files = ['Bass_Drum_%02d_V01.WAV' % n\n",
      "              for n in range(1,11)]\n",
      "\n",
      "snare_files = ['Bass_Drum_%02d_V01.WAV' % n\n",
      "              for n in range(1,11)]\n",
      "\n",
      "for kick_file in kick_files:\n",
      "    url = urljoin('https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/', kick_file)\n",
      "    urllib.urlretrieve(url, filename=kick_file)\n",
      "#kicks = [MonoLoader(filename=filename) for filename in kick_files]\n",
      "#snares = [MonoLoader(filename=filename) for filename in kick_files]\n",
      "\n",
      "%ls"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "Bass_Drum_01_V01.WAV  Bass_Drum_04_V01.WAV  Bass_Drum_07_V01.WAV  Bass_Drum_10_V01.WAV                 nmf_source_separation.ipynb\r\n",
        "Bass_Drum_02_V01.WAV  Bass_Drum_05_V01.WAV  Bass_Drum_08_V01.WAV  feature_sonification.ipynb\r\n",
        "Bass_Drum_03_V01.WAV  Bass_Drum_06_V01.WAV  Bass_Drum_09_V01.WAV  knn_instrument_classification.ipynb\r\n"
       ]
      }
     ],
     "prompt_number": 16
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Archived material:\n",
      "\n",
      "Read a training set of drum samples. For each test signal, extract MFCCs, and use `mean` to obtain one MFCC vector per signal.\n",
      "\n",
      "Train a K-NN classifier using test signals. When training, discard the 0th MFCC coefficient, because it only represents the energy in the frame and does not add any discriminative power. \n",
      "\n",
      "\n",
      "\n",
      "For each segment in the test audio signal, feed it into the trained K-NN classifier, and save the label.\n",
      "\n",
      "4.  First, extract all of the feature data for the kick drums and store it in a feature array.  (For my example, above, I'd put it in \"features_kick\")\n",
      "\n",
      "5.  Next, extract all of the feature data for the snares, storing them in a different array. \n",
      "Again, the kick and snare features should be separated in two different arrays!\n",
      " \n",
      "OK, no more help.  The rest is up to you!"
     ]
    }
   ],
   "metadata": {}
  }
 ]
}