Commit c7736283 authored by Owen Campbell's avatar Owen Campbell

getting up to date

parents eb58c7aa bbfdda7b
{ {
"metadata": { "metadata": {
"name": "", "name": "",
"signature": "sha256:c2091c83f372205a4ebcdce326aec16d3effc143ec24d63e1026df692ec4f383" "signature": "sha256:5c2d491824e04ce0a7278e04803f3c8f56c68362ad164e1fa1330afd9cc674f6"
}, },
"nbformat": 3, "nbformat": 3,
"nbformat_minor": 0, "nbformat_minor": 0,
...@@ -66,19 +66,16 @@ ...@@ -66,19 +66,16 @@
"level": 2, "level": 2,
"metadata": {}, "metadata": {},
"source": [ "source": [
"Feature Extraction (work in progress)" "Spectral Feature Extraction and Classification"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"1. [Feature Extraction](notebooks/feature_extraction.ipynb)\n",
"1. [Spectral Features](notebooks/spectral_features.ipynb)\n", "1. [Spectral Features](notebooks/spectral_features.ipynb)\n",
"1. [Tonal Descriptors: Pitch and Chroma](notebooks/)\n",
"1. [Beat Tracking](notebooks/beat_tracking.ipynb)\n",
"1. [Tempo Estimation](notebooks/tempo_estimation.ipynb)\n",
"1. [Mel-Frequency Ceptral Coefficients](notebooks/mfcc.ipynb)\n", "1. [Mel-Frequency Ceptral Coefficients](notebooks/mfcc.ipynb)\n",
"1. [K-Nearest Neighbor](notebooks/knn.ipynb)\n",
"1. [Exercise: Instrument Classification using K-NN](exercises/knn_instrument_classification.ipynb)" "1. [Exercise: Instrument Classification using K-NN](exercises/knn_instrument_classification.ipynb)"
] ]
}, },
...@@ -87,20 +84,31 @@ ...@@ -87,20 +84,31 @@
"level": 2, "level": 2,
"metadata": {}, "metadata": {},
"source": [ "source": [
"Machine Learning (work in progress)" "More (work in progress)"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"1. [K-Nearest Neighbor](notebooks/knn.ipynb)\n", "1. [Tonal Descriptors: Pitch and Chroma](notebooks/)\n",
"1. [Feature Extraction](notebooks/feature_extraction.ipynb)\n",
"1. [Beat Tracking](notebooks/beat_tracking.ipynb)\n",
"1. [Tempo Estimation](notebooks/tempo_estimation.ipynb)\n",
"1. [K-Means Clustering](notebooks/kmeans.ipynb)\n", "1. [K-Means Clustering](notebooks/kmeans.ipynb)\n",
"1. [Nonnegative Matrix Factorization](notebooks/nmf.ipynb)\n", "1. [Nonnegative Matrix Factorization](notebooks/nmf.ipynb)\n",
"1. [Cross Validation](notebooks/cross_validation.ipynb)\n", "1. [Cross Validation](notebooks/cross_validation.ipynb)\n",
"1. [Exercise: Unsupervised Instrument Classification using K-Means](exercises/)\n", "1. [Exercise: Unsupervised Instrument Classification using K-Means](exercises/)\n",
"1. [Exercise: Source Separation using NMF](exercises/nmf_source_separation.ipynb)" "1. [Exercise: Source Separation using NMF](exercises/nmf_source_separation.ipynb)"
] ]
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
} }
], ],
"metadata": {} "metadata": {}
......
{ {
"metadata": { "metadata": {
"name": "", "name": "",
"signature": "sha256:acdbb21211e509f92197f1505242fdab716b14fe5434b6af6ac4f453c4e7606c" "signature": "sha256:c18acfb58e847f8024390a467d0b4ecd17445242efddf05612ef24a19c90e563"
}, },
"nbformat": 3, "nbformat": 3,
"nbformat_minor": 0, "nbformat_minor": 0,
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"prompt_number": 16 "prompt_number": 2
}, },
{ {
"cell_type": "code", "cell_type": "code",
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"prompt_number": 17 "prompt_number": 3
}, },
{ {
"cell_type": "code", "cell_type": "code",
...@@ -126,7 +126,7 @@ ...@@ -126,7 +126,7 @@
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"prompt_number": 18 "prompt_number": 4
}, },
{ {
"cell_type": "heading", "cell_type": "heading",
...@@ -166,21 +166,21 @@ ...@@ -166,21 +166,21 @@
{ {
"metadata": {}, "metadata": {},
"output_type": "pyout", "output_type": "pyout",
"prompt_number": 15, "prompt_number": 5,
"text": [ "text": [
"<matplotlib.text.Text at 0x3968210>" "<matplotlib.text.Text at 0x47e3150>"
] ]
}, },
{ {
"metadata": {}, "metadata": {},
"output_type": "display_data", "output_type": "display_data",
"png": "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\nAABJRU5ErkJggg==\n", "png": "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\ngg==\n",
"text": [ "text": [
"<matplotlib.figure.Figure at 0x395f350>" "<matplotlib.figure.Figure at 0x47ddd50>"
] ]
} }
], ],
"prompt_number": 15 "prompt_number": 5
}, },
{ {
"cell_type": "heading", "cell_type": "heading",
...@@ -191,244 +191,346 @@ ...@@ -191,244 +191,346 @@
] ]
}, },
{ {
"cell_type": "code", "cell_type": "markdown",
"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",
"\n",
"snare_files = ['Bass_Drum_%02d_V01.WAV' % n\n",
" for n in range(1,11)]\n",
"\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": {}, "metadata": {},
"outputs": [ "source": [
{ "For training, see [Training Data](#Training-Data) below.\n",
"output_type": "stream", "\n",
"stream": "stdout", "For more on K-NN, see the [notebook on K-NN](../notebooks/knn.ipynb)."
"text": [
"https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/Bass_Drum_01_V01.WAV\n",
"https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/Bass_Drum_02_V01.WAV"
] ]
}, },
{ {
"output_type": "stream", "cell_type": "heading",
"stream": "stdout", "level": 2,
"text": [ "metadata": {},
"\n", "source": [
"https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/Bass_Drum_03_V01.WAV" "Step 4: Run the Classifier"
] ]
}, },
{ {
"output_type": "stream", "cell_type": "heading",
"stream": "stdout", "level": 2,
"text": [ "metadata": {},
"\n", "source": [
"https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/Bass_Drum_04_V01.WAV" "Step 5: Sonify the Classifier Output"
] ]
}, },
{ {
"output_type": "stream", "cell_type": "markdown",
"stream": "stdout", "metadata": {},
"text": [ "source": [
"\n", "Play a \"beep\" for each detected kick drum."
"https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/Bass_Drum_05_V01.WAV"
] ]
}, },
{ {
"output_type": "stream", "cell_type": "code",
"stream": "stdout", "collapsed": false,
"text": [ "input": [
"\n", "from essentia.standard import AudioOnsetsMarker\n",
"https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/Bass_Drum_06_V01.WAV" "AudioOnsetsMarker?"
] ],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 6
}, },
{ {
"output_type": "stream", "cell_type": "markdown",
"stream": "stdout", "metadata": {},
"text": [ "source": [
"\n", "Play a \"beep\" for each detected snare drum."
"https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/Bass_Drum_07_V01.WAV"
] ]
}, },
{ {
"output_type": "stream", "cell_type": "code",
"stream": "stdout", "collapsed": false,
"text": [ "input": [
"\n", "from essentia.standard import AudioOnsetsMarker\n",
"https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/Bass_Drum_08_V01.WAV" "AudioOnsetsMarker?"
] ],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
}, },
{ {
"output_type": "stream", "cell_type": "heading",
"stream": "stdout", "level": 2,
"text": [ "metadata": {},
"\n", "source": [
"https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/Bass_Drum_09_V01.WAV" "Bonus"
] ]
}, },
{ {
"output_type": "stream", "cell_type": "markdown",
"stream": "stdout", "metadata": {},
"text": [ "source": [
"In addition to the MFCCs, extract the following features:\n",
"\n", "\n",
"https://ccrma.stanford.edu/workshops/mir2014/audio/drum%%20samples/kicks/Bass_Drum_10_V01.WAV" "- spectral centroid\n",
"- spectral spread\n",
"- spectral skewness\n",
"- spectral kurtosis. "
] ]
}, },
{ {
"output_type": "stream", "cell_type": "code",
"stream": "stdout", "collapsed": false,
"text": [ "input": [
"\n", "from essentia.standard import CentralMoments, DistributionShape\n",
"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", "DistributionShape?"
"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": 32 "language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 8
}, },
{ {
"cell_type": "heading", "cell_type": "markdown",
"level": 2,
"metadata": {}, "metadata": {},
"source": [ "source": [
"Step 4: Run the Classifier" "Re-train the classifier, and re-run the classifier over the test audio signal. Do the results change?"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [] "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", "cell_type": "heading",
"level": 2, "level": 2,
"metadata": {}, "metadata": {},
"source": [ "source": [
"Step 5: Sonify the Classifier Output" "Training Data"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Play a \"beep\" for each detected kick drum." "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", "cell_type": "code",
"collapsed": false, "collapsed": false,
"input": [ "input": [
"from essentia.standard import AudioOnsetsMarker\n", "import urllib2\n",
"AudioOnsetsMarker?" "\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", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"prompt_number": 6 "prompt_number": 10
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Play a \"beep\" for each detected snare drum." "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", "cell_type": "code",
"collapsed": false, "collapsed": false,
"input": [ "input": [
"from essentia.standard import AudioOnsetsMarker\n", "snares_URL = \"https://ccrma.stanford.edu/workshops/mir2014/SnareCorpus.txt\"\n",
"AudioOnsetsMarker?" "snare_file_list = [audio_file_URL for audio_file_URL in process_corpus(snares_URL)]"
], ],
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"prompt_number": 7 "prompt_number": 11
},
{
"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": 12
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Read a training set of drum samples. For each test signal, extract MFCCs, and use `mean` to obtain one MFCC vector per signal.\n", "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:"
"\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."
] ]
}, },
{ {
"cell_type": "heading", "cell_type": "code",
"level": 2, "collapsed": false,
"input": [
"snare_URL = snare_file_list[0]\n",
"snare_URL"
],
"language": "python",
"metadata": {}, "metadata": {},
"source": [ "outputs": [
"Bonus" {
"metadata": {},
"output_type": "pyout",
"prompt_number": 13,
"text": [
"'https://ccrma.stanford.edu/workshops/mir2014/audio/drum%20samples/snares/SNARE_01_01.WAV'"
] ]
}
],
"prompt_number": 13
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"In addition to the MFCCs, extract the following features:\n", "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", "\n",
"- spectral centroid\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:"
"- spectral spread\n",
"- spectral skewness\n",
"- spectral kurtosis. "
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"collapsed": false, "collapsed": false,
"input": [ "input": [
"from essentia.standard import CentralMoments, DistributionShape\n", "import numpy as np\n",
"DistributionShape?" "\n",
"number_of_files = 20\n",
"number_of_features = 5\n",
"features_snare = np.zeros([number_of_files, number_of_features])"
], ],
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"prompt_number": 3 "prompt_number": 14
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Re-train the classifier, and re-run the classifier over the test audio signal. Do the results change?" " 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": "markdown", "cell_type": "code",
"collapsed": false,
"input": [
"import urllib\n",
"from essentia.standard import MonoLoader\n",
"\n",
"sample_rate = 44100\n",
"urllib.urlretrieve(snare_URL, filename='/tmp/localfile.wav')\n",
"audio = MonoLoader(filename = '/tmp/localfile.wav', sampleRate = sample_rate)()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 15
},
{
"cell_type": "heading",
"level": 2,
"metadata": {}, "metadata": {},
"source": [ "source": [
"Repeat the steps above for the following audio files:" "Appendix"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"collapsed": false, "collapsed": false,
"input": [ "input": [
"url = 'https://ccrma.stanford.edu/workshops/mir2014/audio/CongaGroove-mono.wav'\n", "from urlparse import urljoin\n",
"url = 'https://ccrma.stanford.edu/workshops/mir2014/audio/125BOUNC-mono.WAV'" "\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", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
"prompt_number": 2 {
"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": {} "metadata": {}
......
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
"source": [ "source": [
"- 2009 [[full list](https://ccrma.stanford.edu/wiki/MIR_workshop_2009/Participants)]: Luke Dahl, Mike Gao, Craig Hanson, Jorge Herrera, Denis Lebel, Sang Won Lee, Gautham Mysore, Jeremy Sawruk, Hwan Shim, Diana Siwiak, Steve Tjoa, Elie Noune, James Hughes, Stefan Tomic, Lisa Lim, Fred Barrett\n", "- 2009 [[full list](https://ccrma.stanford.edu/wiki/MIR_workshop_2009/Participants)]: Luke Dahl, Mike Gao, Craig Hanson, Jorge Herrera, Denis Lebel, Sang Won Lee, Gautham Mysore, Jeremy Sawruk, Hwan Shim, Diana Siwiak, Steve Tjoa, Elie Noune, James Hughes, Stefan Tomic, Lisa Lim, Fred Barrett\n",
"- 2011: Chris Colatos, Jeff Albert, Kamlesh Lakshminarayanan, Sean Zhang, Eli Stine, David Bird, Gina Collecchia, Dekun Zou, Bill Paseman, John Amuedo\n", "- 2011: Chris Colatos, Jeff Albert, Kamlesh Lakshminarayanan, Sean Zhang, Eli Stine, David Bird, Gina Collecchia, Dekun Zou, Bill Paseman, John Amuedo\n",
"- 2014: Owen Campbell, (Add your name here! Fork this repo on GitHub, and send a pull request.)" "- 2014: (Krishna Kumar, ... Add your name here! Fork this repo on GitHub, and send a pull request.)"
] ]
} }
], ],
......
This source diff could not be displayed because it is too large. You can view the blob instead.
{ {
"metadata": { "metadata": {
"name": "", "name": "",
"signature": "sha256:3e21fdc85c366449b7dce6c5e6e1aedf32f06eb49d2a03663f8375eaccbea6e3" "signature": "sha256:319b465b5be6a89b194af42e27ece8ad415727e2aab733ccd86cd4378d4f6a86"
}, },
"nbformat": 3, "nbformat": 3,
"nbformat_minor": 0, "nbformat_minor": 0,
...@@ -23,190 +23,73 @@ ...@@ -23,190 +23,73 @@
"For classification, we're going to be using the new features in our arsenal: cherishing those \"spectral moments\" (centroid, bandwidth, skewness, kurtosis) and also examining other spectral statistics." "For classification, we're going to be using the new features in our arsenal: cherishing those \"spectral moments\" (centroid, bandwidth, skewness, kurtosis) and also examining other spectral statistics."
] ]
}, },
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Training Data"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "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", "*Moments* is a term used in physics and statistics. There are raw moments and central moments. The first raw moment is known as the mean. The second central moment is known as the variance."
"\n",
"Let's define a function to retrieve a list of URLs from a text file."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "heading",
"collapsed": false, "level": 2,
"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": 4
},
{
"cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "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." "`essentia.standard.Centroid`"
] ]
}, },
{
"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": 5
},
{
"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": 6
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "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:" "To compute the spectral centroid, we will use [`essentia.standard.Centroid`](http://essentia.upf.edu/documentation/reference/std_Centroid.html):"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"collapsed": false, "collapsed": false,
"input": [ "input": [
"snare_URL = snare_file_list[0]\n", "import essentia\n",
"snare_URL" "from essentia.standard import Spectrum, Centroid\n",
"spectrum = Spectrum()\n",
"centroid = Centroid()\n",
"x = essentia.array(randn(1024))\n",
"X = spectrum(x)\n",
"spectral_centroid = centroid(X)\n",
"print spectral_centroid"
], ],
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"metadata": {}, "output_type": "stream",
"output_type": "pyout", "stream": "stdout",
"prompt_number": 7,
"text": [ "text": [
"'https://ccrma.stanford.edu/workshops/mir2014/audio/drum%20samples/snares/SNARE_01_01.WAV'" "0.510950088501\n"
] ]
} }
], ],
"prompt_number": 7 "prompt_number": 46
},
{
"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": [
"import numpy as np\n",
"\n",
"number_of_files = 20\n",
"number_of_features = 5\n",
"features_snare = np.zeros([number_of_files, number_of_features])"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 8
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
" For example, when populated, features_snare might look like:\n", "This value is normalized between 0 and 1. If 0, then the centroid is at zero. If 1, then the centroid is all the way to the \"right\", i.e., equal to `fs/2`, the Nyquist frequency, or the highest frequency a digital signal can possibly have."
" \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\n",
"\n",
"sample_rate = 44100\n",
"urllib.urlretrieve(snare_URL, filename='/tmp/localfile.wav')\n",
"audio = MonoLoader(filename = '/tmp/localfile.wav', sampleRate = sample_rate)()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 9
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Here's an example of how to feature extract the first frame from the current audio file, using Essentia's [ZeroCrossingRate](http://essentia.upf.edu/documentation/reference/streaming_ZeroCrossingRate.html) and [CentralMoments](http://essentia.upf.edu/documentation/reference/std_CentralMoments.html) classes..." "Here is a sanity check:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"collapsed": false, "collapsed": false,
"input": [ "input": [
"from essentia.standard import ZeroCrossingRate, CentralMoments, Spectrum, Windowing, Centroid\n", "sum((X/sum(X))*linspace(0, 1, len(X)))"
"zcr = ZeroCrossingRate()\n",
"hamming_window = Windowing(type = 'hamming') # we need to window the frame to avoid FFT artifacts.\n",
"spectrum = Spectrum()\n",
"central_moments = CentralMoments()\n",
"spectral_centroid = Centroid()\n",
"\n",
"frame_size = 0.100 * sample_rate # 100ms\n",
"file_index = 0 # to process a single file, this will be your file loop iteration\n",
"\n",
"current_frame = audio[0 : frame_size]\n",
"features_snare[file_index, 0] = zcr(current_frame)\n",
"spectral_magnitude = spectrum(hamming_window(current_frame))\n",
"centroid = spectral_centroid(spectral_magnitude)\n",
"\n",
"# Spectral centroid in normalised bandwidth (i.e fraction of Nyquist frequency).\n",
"centroid"
], ],
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
...@@ -214,130 +97,87 @@ ...@@ -214,130 +97,87 @@
{ {
"metadata": {}, "metadata": {},
"output_type": "pyout", "output_type": "pyout",
"prompt_number": 10, "prompt_number": 47,
"text": [ "text": [
"0.22001729905605316" "0.51095009882361531"
] ]
} }
], ],
"prompt_number": 10 "prompt_number": 47
}, },
{ {
"cell_type": "code", "cell_type": "heading",
"collapsed": false, "level": 2,
"input": [
"# Centroid in spectral coefficient indices.\n",
"centroid * spectral_magnitude.shape[0]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {}, "metadata": {},
"output_type": "pyout", "source": [
"prompt_number": 11, "`essentia.standard.CentralMoments`"
"text": [
"485.3581617176533"
] ]
}
],
"prompt_number": 11
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Essentia can make things seem a little magical, here is how the centroid would be calculated:" "The first step to computing the other three spectral moments (spread, skewness, and kurtosis) is to compute the central moments of a spectrum:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"collapsed": false, "collapsed": false,
"input": [ "input": [
"# Normalize the spectral magnitude\n", "from essentia.standard import CentralMoments\n",
"norm_spectral_mag = spectral_magnitude / np.sum(spectral_magnitude)\n", "central_moments = CentralMoments()\n",
"# Make index vector\n", "print central_moments(X)"
"indices = np.arange(norm_spectral_mag.shape[0])\n",
"\n",
"# Centroid, in spectral coefficient indices.\n",
"my_centroid = np.sum(norm_spectral_mag * indices)\n",
"my_centroid"
], ],
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"metadata": {}, "output_type": "stream",
"output_type": "pyout", "stream": "stdout",
"prompt_number": 12,
"text": [ "text": [
"485.13728477961195" "[ 1.00000000e+00 0.00000000e+00 8.45586956e-02 -9.95449489e-04\n",
" 1.29118226e-02]\n"
] ]
} }
], ],
"prompt_number": 12 "prompt_number": 48
}, },
{ {
"cell_type": "code", "cell_type": "heading",
"collapsed": false, "level": 2,
"input": [
"# Now we use the magnitude of the spectrum to compute a 5 element array, corresponding to:\n",
"# zeroth central moment (1.0)\n",
"# first central moment (Not the centroid, which is the first moment!)\n",
"# bandwidth\n",
"# skew\n",
"# kurtosis.\n",
"spectral_moments = central_moments(spectral_magnitude)\n",
"spectral_moments"
],
"language": "python",
"metadata": {}, "metadata": {},
"outputs": [ "source": [
"`essentia.standard.DistributionShape`"
]
},
{ {
"cell_type": "markdown",
"metadata": {}, "metadata": {},
"output_type": "pyout", "source": [
"prompt_number": 13, "To compute the spectral spread, skewness, and kurtosis, we use [`essentia.standard.DistributionShape`](http://essentia.upf.edu/documentation/reference/std_DistributionShape.html):"
"text": [
"array([ 1. , 0. , 0.04079479, 0.00723291, 0.00497805], dtype=float32)"
] ]
}
],
"prompt_number": 13
}, },
{ {
"cell_type": "code", "cell_type": "code",
"collapsed": false, "collapsed": false,
"input": [ "input": [
"# Remember the zeroth column of features_snare is the ZCR.\n", "from essentia.standard import DistributionShape\n",
"features_snare[file_index, 1] = centroid\n", "distributionshape = DistributionShape()\n",
"features_snare[file_index, 2:5] = spectral_moments[2:5]\n", "spectral_moments = distributionshape(central_moments(X))\n",
"features_snare[file_index]" "print spectral_moments"
], ],
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"metadata": {}, "output_type": "stream",
"output_type": "pyout", "stream": "stdout",
"prompt_number": 14,
"text": [ "text": [
"array([ 0.1292517 , 0.2200173 , 0.04079479, 0.00723291, 0.00497805])" "(0.08455869555473328, -0.04048385098576546, -1.1941944360733032)\n"
] ]
} }
], ],
"prompt_number": 14 "prompt_number": 49
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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": {} "metadata": {}
......
...@@ -9,6 +9,9 @@ from sklearn import cross_validation ...@@ -9,6 +9,9 @@ from sklearn import cross_validation
from sklearn.neighbors import KNeighborsClassifier from sklearn.neighbors import KNeighborsClassifier
from sklearn import preprocessing from sklearn import preprocessing
import urllib2 # the lib that handles the url stuff import urllib2 # the lib that handles the url stuff
import urllib
from essentia.standard import MonoLoader
from essentia.standard import ZeroCrossingRate, CentralMoments, Spectrum, Windowing, Centroid
# Here are examples of how scaling functions would be written, however nowdays SciKit # Here are examples of how scaling functions would be written, however nowdays SciKit
# Learn will do it for you with the MinMaxScaler! # Learn will do it for you with the MinMaxScaler!
...@@ -86,9 +89,10 @@ def crossValidateKNN(features, labels): ...@@ -86,9 +89,10 @@ def crossValidateKNN(features, labels):
errors[foldIndex] = matches.mean() errors[foldIndex] = matches.mean()
print('cross validation error: %f' % errors.mean()) print('cross validation error: %f' % errors.mean())
print('cross validation accuracy: %f' % (1.0 - errors.mean())) print('cross validation accuracy: %f' % (1.0 - errors.mean()))
return errors
def processCorpus(corpusURL): def process_corpus(corpusURL):
"""Read a list of files to process from the text file at corpusURL. Return a list of URLs""" """Read a list of files to process from the text file at corpusURL. Return a list of URLs"""
# Open and read each line # Open and read each line
urlListTextData = urllib2.urlopen(corpusURL) # it's a file like object and works just like a file urlListTextData = urllib2.urlopen(corpusURL) # it's a file like object and works just like a file
...@@ -96,6 +100,39 @@ def processCorpus(corpusURL): ...@@ -96,6 +100,39 @@ def processCorpus(corpusURL):
yield fileURL.rstrip() yield fileURL.rstrip()
# return [fileURL.rstrip() for fileURL in urlListTextData] # return [fileURL.rstrip() for fileURL in urlListTextData]
# audioFileURLs = processCorpus("https://ccrma.stanford.edu/workshops/mir2014/SmallCorpus.txt") # audioFileURLs = process_corpus("https://ccrma.stanford.edu/workshops/mir2014/SmallCorpus.txt")
# for audioFileURL in processCorpus("https://ccrma.stanford.edu/workshops/mir2014/SmallCorpus.txt"): # for audioFileURL in process_corpus("https://ccrma.stanford.edu/workshops/mir2014/SmallCorpus.txt"):
# print audioFileURL # print audioFileURL
def spectral_features(filelist):
"""
Given a list of files, retrieve them, analyse the first 100mS of each file and return
a feature table.
"""
number_of_files = len(filelist)
number_of_features = 5
features = np.zeros([number_of_files, number_of_features])
sample_rate = 44100
for file_index, url in enumerate(filelist):
print url
urllib.urlretrieve(url, filename='/tmp/localfile.wav')
audio = MonoLoader(filename = '/tmp/localfile.wav', sampleRate = sample_rate)()
zcr = ZeroCrossingRate()
hamming_window = Windowing(type = 'hamming') # we need to window the frame to avoid FFT artifacts.
spectrum = Spectrum()
central_moments = CentralMoments()
spectral_centroid = Centroid()
frame_size = int(round(0.100 * sample_rate)) # 100ms
# Only do the first frame for now.
# TODO we should generate values for the entire file, probably by averaging the features.
current_frame = audio[0 : frame_size]
features[file_index, 0] = zcr(current_frame)
spectral_magnitude = spectrum(hamming_window(current_frame))
centroid = spectral_centroid(spectral_magnitude)
spectral_moments = central_moments(spectral_magnitude)
features[file_index, 1] = centroid
features[file_index, 2:5] = spectral_moments[2:5]
return features
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment