├── .gitignore ├── LICENSE ├── README.md ├── demo ├── Arpeggio.ogg └── demo.js ├── package.json ├── pitch.js └── test ├── multi.js ├── noise.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules/* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Mikola Lysenko 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | detect-pitch 2 | ============ 3 | Detects the pitch of a signal using the autocorrelation method. 4 | 5 | ## Example 6 | 7 | ```javascript 8 | var detectPitch = require('detect-pitch') 9 | 10 | var n = 1024 11 | var ω = 2.0 * Math.PI / n 12 | 13 | //Initialize signal 14 | var signal = new Float32Array(n) 15 | for(var i=0; i 1 35 | } 36 | 37 | function findPeriod(x, lo, hi, threshold) { 38 | var smallest = 1.0 39 | var period = 0 40 | for(var i=lo; i+2 1.0) { 51 | continue 52 | } 53 | var ymin = y1 + 0.25 * Math.pow(y0 - y2, 2) / denom 54 | if(ymin < smallest) { 55 | var f0 = i + s + 1 56 | if(aperiodic(f0, period)) { 57 | smallest = ymin 58 | period = f0 59 | } 60 | } 61 | } 62 | } 63 | if(smallest < 1.0 - threshold) { 64 | return period 65 | } 66 | return 0.0 67 | } 68 | 69 | function detectPitch(signal, threshold) { 70 | threshold = threshold || 0.0 71 | 72 | var xs 73 | if(signal.shape) { 74 | xs = signal.shape[0] 75 | } else { 76 | xs = signal.length 77 | } 78 | 79 | var n = bits.nextPow2(2*xs) 80 | 81 | var i, j, k 82 | var re_arr = pool.mallocFloat(n) 83 | var im_arr = pool.mallocFloat(n) 84 | var X = ndarray(re_arr, [n], [1], 0) 85 | var Y = ndarray(im_arr, [n], [1], 0) 86 | 87 | //Initialize array depending on if it is a typed array 88 | if(signal.shape) { 89 | ops.assign(X.hi(xs), signal) 90 | } else { 91 | re_arr.set(signal) 92 | } 93 | 94 | //Compute magnitude 95 | var magnitude = 0.0 96 | for(var i=0; i>>1, threshold) 119 | 120 | //Free temporary arrays 121 | pool.freeFloat(re_arr) 122 | pool.freeFloat(im_arr) 123 | 124 | return period 125 | } 126 | module.exports = detectPitch 127 | -------------------------------------------------------------------------------- /test/multi.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | var detectPitch = require("../pitch.js") 4 | 5 | function runTest(t, n, freq_list, phase_list, amplitude_list) { 6 | var signal = new Float32Array(n) 7 | var omega = 2.0 * Math.PI / n 8 | 9 | for(var i=0; i