1 /*
  2  * 	Copyright (C) 2012-2013 DFKI GmbH
  3  * 	Deutsches Forschungszentrum fuer Kuenstliche Intelligenz
  4  * 	German Research Center for Artificial Intelligence
  5  * 	http://www.dfki.de
  6  * 
  7  * 	Permission is hereby granted, free of charge, to any person obtaining a 
  8  * 	copy of this software and associated documentation files (the 
  9  * 	"Software"), to deal in the Software without restriction, including 
 10  * 	without limitation the rights to use, copy, modify, merge, publish, 
 11  * 	distribute, sublicense, and/or sell copies of the Software, and to 
 12  * 	permit persons to whom the Software is furnished to do so, subject to 
 13  * 	the following conditions:
 14  * 
 15  * 	The above copyright notice and this permission notice shall be included 
 16  * 	in all copies or substantial portions of the Software.
 17  * 
 18  * 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 19  * 	OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 20  * 	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 21  * 	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 22  * 	CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 23  * 	TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 24  * 	SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 25  */
 26 
 27 /**
 28  * @module workers/silenceDetection
 29  */
 30 
 31 var silenceCount = 0, //how many silent blobs have there been in a row now?
 32 	speechCount = 0, //how many blobs have been loud in a row now?
 33 	lastInput = 0, // how long has there been no good loud input?
 34 	recording= false,
 35 	noiseTreshold = 0.1, //the bigger, the more is counted as silent
 36 	sampleRate = 0,
 37 	pauseCount = 3,
 38 	resetCount = 15,
 39 	maxBlobSize = 15,
 40 	blobSizeCount = 0,
 41 	blobNumber = 0;
 42   
 43 self.onmessage = function(e){
 44   switch(e.data.command){
 45     case 'init':
 46       init(e.data.config);
 47       break;
 48     case 'start':
 49       start();
 50       break;
 51     case 'isSilent':
 52       isSilent(e.data.buffer);
 53       break;
 54     case 'stop':
 55       stop();
 56       break;
 57   }
 58 };
 59 /**
 60  * sets the config and echos back
 61  * @param config
 62  * @private
 63  */
 64 function init(config){
 65   if (config.sampleRate)sampleRate = config.sampleRate;
 66   if (config.noiseTreshold) noiseTreshold = config.noiseTreshold;
 67   if (config.pauseCount) pauseCount = config.pauseCount;
 68   if (config.resetCount) resetCount = config.resetCount;
 69   self.postMessage('Silence Detection initialized');
 70 }
 71 
 72 /**
 73  * recieves an audioBlob and decides whether or not there has been a real input (min. 3 loud blobs in a row)
 74  * and a real pause (min. <pauseCount> silent blobs in a row) afterwards. In this case it dictates a pause. 
 75  * If some time has gone by without any real input, it sends a signal to clear the buffers.
 76  * @param inputBuffer
 77  * @private
 78  */
 79 function isSilent(inputBuffer){
 80 	if (recording){
 81 		blobNumber++;
 82 		if (blobNumber==3){
 83 			self.postMessage('Silence detected!');
 84 		}
 85 		var thisSilent = true;
 86 		var bound = 0;
 87 		for (var i = 0; i < inputBuffer.length; i++) {
 88 			if (( inputBuffer[i]> noiseTreshold)||( inputBuffer[i]<0-noiseTreshold)){
 89 				if (inputBuffer[i]>bound) bound= inputBuffer[i];
 90 				thisSilent = false;
 91 			}
 92 		}
 93 		if (thisSilent){
 94 			if (silenceCount>=pauseCount){
 95 				self.postMessage('Silence detected!');
 96 				speechCount = 0;
 97 				silenceCount = 0;
 98 				lastInput = 0;
 99 				blobsizeCount = 0;
100 			}
101 			if (speechCount>=pauseCount){
102 				blobSizeCount++;
103 				silenceCount++;
104 			} 
105 			else {
106 				speechCount = 0;
107 				lastInput++;
108 			}
109 		} 
110 		else {
111 			if (speechCount>=pauseCount){
112 				silenceCount=0;
113 				blobSizeCount++;
114 			} 
115 			else {
116 				speechCount++;
117 				lastInput++;
118 			}
119 		}
120 		if (speechCount>pauseCount){
121 			
122 		}
123 		if (blobSizeCount >= maxBlobSize){
124 			self.postMessage('Send partial!');
125 			blobSizeCount = 0;
126 		}
127 		if (speechCount==0 && lastInput>resetCount){
128 			this.postMessage('clear');
129 			lastInput= 0;
130 		}
131 		
132 	}
133 }
134 
135 /**
136  * resets everything and switches the worker to recording mode.
137  * @private
138  */
139 function start(){
140 	silenceCount=0;
141 	speechCount =0;
142 	lastInput = 0;
143 	recording = true;
144 	self.postMessage('Silence Detection started');
145 	blobNumber = 0;
146 }
147 function stop(){
148 	recording = false;
149 	if (speechCount>0){
150 		self.postMessage('Silence detected!');
151 		speechCount = 0;
152 		silenceCount = 0;
153 		lastInput = 0;
154 		blobsizeCount = 0;
155 	}
156 	self.postMessage('Silence Detection stopped');
157 }
158 
159 
160