<commit_before>function SoundKeyMatching(options) {
	var samplingHandler = function() {};	// 샘플을 추출했을 때 알려줄 핸들러
	var debugHandler = function(message) {};	// 디버그 메시지를 출력
	var samplingFunction = null;
	var matchingFunction = null;
	var matchingData = [];	// 비교가 필요한 데이터들과 매칭결과를 알려줄 핸들러들
	var opt = applyOption(options);
		
	var info = {
		volumeLevel: 0,	// 현재 전체 볼륨 레벨
		maxLevel: 0,	// 최대 level
		afterMaxLevel: 0,	// 최대 level 이후 몇 번의 주기가 지났는가?
		sampleCount: 0,	// 샘플 추출 횟수
	};
	var maxLevelSampleData = null;	// 최대 level 일 때의 샘플링 데이터
	
	// call periodically while do sampling
	// 반복적으로 호출해줘야 함 (초당 5~10회 추천)
	this.doSampling = function(data) {
		info.afterMaxLevel++;

		// 볼륨 크기를 구해서
		info.volumeLevel = 0;
		for (var i in data) {
			info.volumeLevel += data[i];
		}
		if (info.volumeLevel > opt.minSamplingVolumeLevel &&
			info.volumeLevel > info.maxLevel) {
			info.maxLevel = info.volumeLevel;
			info.afterMaxLevel = 0;
			maxLevelSampleData = samplingFunction(data);
		}
		
		// 최대 level 이 한동안 갱신되지 않는다면 샘플이 완료된 것으로 간주하고 추출
		if (info.afterMaxLevel > opt.sampleEndingCheck &&
			info.maxLevel > opt.minSamplingVolumeLevel) {
			this.samplingHandler(maxLevelSampleData);
			info.sampleCount++;
			info.maxLevel = 0;
			maxLevelSampleData = null;
		}
		
		debug();
	}
	
	// 옵션 설정
	function applyOption(option) {
		if (option === undefined) {
			option = SoundKeyMatching.createOptions();
		}
		switch (option.samplingType) {
			case 1:	// volume level 검출 (테스트용)
				samplingFunction = getSampleFromData1;
				matchingFunction = matchSample1;
				break;
			case 2:	// peak 와 내리막 검출
				samplingFunction = getSampleFromData2;
				matchingFunction = matchSample2;
				break;
			case 3:	// 이동평균 peak 검출
				samplingFunction = getSampleFromData3;
				matchingFunction = matchSample3;
				break;
			default:
				break;
		}
		
		return option;
	}
	
	// 디버그 메시지 출력
	function debug() {
		var msg = "";
		for (var key in info) {
			msg += key + ":" + info[key] + "\n";
		}
		debugHandler(msg);
	}
	
	// call periodically while do matching
	// 반복적으로 호출해줘야 함 (초당 5~10회 추천)
	this.doMatching = function(data) {
		for (var i in matchingData) {
			var matchingItem = matchingData[i];
			if (matchingFunction(matchingItem.sample, data)) {
				matchingItem.handler(matchingItem.context);
			}
		}
	}
	
	// 디버그용 메시지 출력 핸들러
	this.setDebugHandler = function(handler) {
		debugHandler = handler;
	}
	
	// 샘플을 추출했을 때 호출할 핸들러를 등록
	this.setSamplingHandler = function(handler) {
		this.samplingHandler = handler;
	}
	
	// 샘플과 샘플이 매칭되었을 때 호출할 핸들러를 등록
	this.addMatch = function(sampleData, matchingHandler, contextData) {
		matchingData.push({sample: sampleData, handler: matchingHandler, context: contextData});
	}
	
	// volume level 검출
	function getSampleFromData1(data) {
		var sample = {};
		var volumeLevel = 0;
		for (var i in data) {
			volumeLevel += data[i];
		}
		sample.volume = volumeLevel;
		return sample;
	}
	
	// peak 와 내리막 검출
	function getSampleFromData2(data) {
		var sample = {};
		var freqLevel = 0;
		var maxFreqIndex = null;
		var maxFreqLevel = 0;
		var afterMaxFreqLevel = 0;
		var peakCount = 0;
		
		// 모든 주파수 데이터를 순회하며
		for (var i in data) {
			afterMaxFreqLevel++;
			
			freqLevel = data[i];
			// 주파수 별 레벨 봉우리(peak)를 찾는다.
			if (freqLevel > maxFreqLevel &&
				freqLevel > opt.minPeakLevel) {
				maxFreqIndex = i;
				maxFreqLevel = freqLevel;
				afterMaxFreqLevel = 0;
			}
			
			// 봉우리가 한동안 갱신되지 않으면 진짜 봉우리로 인정
			if (maxFreqLevel > opt.minPeakLevel &&
				afterMaxFreqLevel > opt.peakEndingCheck) {
				sample[maxFreqIndex] = maxFreqLevel;
				peakCount++;
				maxFreqIndex = null;
				maxFreqLevel = 0;
			}
		}
		
		if (peakCount == 0) {
			sample = null;;
		} else {
			sample.size = peakCount;
		}
		return sample;
	}
	
	// 이동평균 peak 검출
	function getSampleFromData3(data) {
		var sample = {};
		var freqLevel = 0;
		var maxFreqIndex = null;
		var maxFreqLevel = 0;
		var afterMaxFreqLevel = 0;
		var peakCount = 0;
		
		var freqQueue = [];
		var freqSum = 0;
		for (var i = 0; i < opt.avgRange; i++) {
			freqQueue.push(0);
		}
		
		// 모든 주파수 데이터를 순회하며
		for (var i in data) {
			afterMaxFreqLevel++;
			
			freqLevel = data[i];
			// 주파수 별 레벨 봉우리(peak)를 찾는다.
			if (freqLevel > maxFreqLevel &&
				freqLevel > opt.minPeakLevel) {
				maxFreqIndex = i;
				maxFreqLevel = freqLevel;
				afterMaxFreqLevel = 0;
			}
			
			// 봉우리가 한동안 갱신되지 않으면 진짜 봉우리로 인정
			if (maxFreqLevel > opt.minPeakLevel &&
				afterMaxFreqLevel > opt.peakEndingCheck) {
				sample[maxFreqIndex] = maxFreqLevel;<commit_msg>Update soundkeymatching.js<commit_after>function SoundKeyMatching(options) {
	var samplingHandler = function() {};	// 샘플을 추출했을 때 알려줄 핸들러
	var debugHandler = function(message) {};	// 디버그 메시지를 출력
	var samplingFunction = null;
	var matchingFunction = null;
	var matchingData = [];	// 비교가 필요한 데이터들과 매칭결과를 알려줄 핸들러들
	var opt = applyOption(options);
	
	var info = {
		volumeLevel: 0,	// 현재 전체 볼륨 레벨
		maxLevel: 0,	// 최대 level
		afterMaxLevel: 0,	// 최대 level 이후 몇 번의 주기가 지났는가?
		sampleCount: 0,	// 샘플 추출 횟수
	};
	var maxLevelSampleData = null;	// 최대 level 일 때의 샘플링 데이터
	
	// call periodically while do sampling
	// 반복적으로 호출해줘야 함 (초당 5~10회 추천)
	this.doSampling = function(data) {
		info.afterMaxLevel++;

		// 볼륨 크기를 구해서
		info.volumeLevel = 0;
		for (var i in data) {
			info.volumeLevel += data[i];
		}
		if (info.volumeLevel > opt.minSamplingVolumeLevel &&
			info.volumeLevel > info.maxLevel) {
			info.maxLevel = info.volumeLevel;
			info.afterMaxLevel = 0;
			maxLevelSampleData = samplingFunction(data, info.volumeLevel);
		}
		
		// 최대 level 이 한동안 갱신되지 않는다면 샘플이 완료된 것으로 간주하고 추출
		if (info.afterMaxLevel > opt.sampleEndingCheck &&
			info.maxLevel > opt.minSamplingVolumeLevel) {
			this.samplingHandler(maxLevelSampleData);
			info.sampleCount++;
			info.maxLevel = 0;
			maxLevelSampleData = null;
		}
		
		debug();
	}
	
	// 옵션 설정
	function applyOption(option) {
		if (option === undefined) {
			option = SoundKeyMatching.createOptions();
		}
		switch (option.samplingType) {
			case 1:	// volume level 검출 (테스트용)
				samplingFunction = getSampleFromData1;
				matchingFunction = matchSample1;
				break;
			case 2:	// peak 와 내리막 검출
				samplingFunction = getSampleFromData2;
				matchingFunction = matchSample2;
				break;
			case 3:	// 이동평균 peak 검출
				samplingFunction = getSampleFromData3;
				matchingFunction = matchSample3;
				break;
			default:
				break;
		}
		
		return option;
	}
	
	// 디버그 메시지 출력
	function debug() {
		var msg = "";
		for (var key in info) {
			msg += key + ":" + info[key] + "\n";
		}
		debugHandler(msg);
	}
	
	// call periodically while do matching
	// 반복적으로 호출해줘야 함 (초당 5~10회 추천)
	this.doMatching = function(data) {
		for (var i in matchingData) {
			var matchingItem = matchingData[i];
			if (matchingFunction(matchingItem.sample, data)) {
				matchingItem.handler(matchingItem.context);
			}
		}
	}
	
	// 디버그용 메시지 출력 핸들러
	this.setDebugHandler = function(handler) {
		debugHandler = handler;
	}
	
	// 샘플을 추출했을 때 호출할 핸들러를 등록
	this.setSamplingHandler = function(handler) {
		this.samplingHandler = handler;
	}
	
	// 샘플과 샘플이 매칭되었을 때 호출할 핸들러를 등록
	this.addMatch = function(sampleData, matchingHandler, contextData) {
		matchingData.push({sample: sampleData, handler: matchingHandler, context: contextData});
	}
	
	// volume level 검출
	function getSampleFromData1(data, volume) {
		var sample = {};
		sample.volume = volume;
		return sample;
	}
	
	// peak 와 내리막 검출
	function getSampleFromData2(data, volume) {
		var sample = {};
		var freqLevel = 0;
		var maxFreqIndex = null;
		var maxFreqLevel = 0;
		var afterMaxFreqLevel = 0;
		var peakCount = 0;
		
		// 모든 주파수 데이터를 순회하며
		for (var i in data) {
			afterMaxFreqLevel++;
			
			freqLevel = data[i];
			// 주파수 별 레벨 봉우리(peak)를 찾는다.
			if (freqLevel > maxFreqLevel &&
				freqLevel > opt.minPeakLevel) {
				maxFreqIndex = i;
				maxFreqLevel = freqLevel;
				afterMaxFreqLevel = 0;
			}
			
			// 봉우리가 한동안 갱신되지 않으면 진짜 봉우리로 인정
			if (maxFreqLevel > opt.minPeakLevel &&
				afterMaxFreqLevel > opt.peakEndingCheck) {
				sample[maxFreqIndex] = maxFreqLevel;
				peakCount++;
				maxFreqIndex = null;
				maxFreqLevel = 0;
			}
		}
		
		if (peakCount == 0) {
			sample = null;;
		} else {
			sample.size = peakCount;
			sample.volume = volume;
		}
		return sample;
	}
	
	// 이동평균 peak 검출
	function getSampleFromData3(data, volume) {
		var sample = {};
		var freqLevel = 0;
		var maxFreqIndex = null;
		var maxFreqLevel = 0;
		var afterMaxFreqLevel = 0;
		var peakCount = 0;
		
		var freqQueue = [];
		var freqSum = 0;
		for (var i = 0; i < opt.avgRange; i++) {
			freqQueue.push(0);
		}
		
		// 모든 주파수 데이터를 순회하며
		for (var i in data) {
			afterMaxFreqLevel++;
			
			freqLevel = data[i];
			// 주파수 별 레벨 봉우리(peak)를 찾는다.
			if (freqLevel > maxFreqLevel &&
				freqLevel > opt.minPeakLevel) {
				maxFreqIndex = i;
				maxFreqLevel = freqLevel;
				afterMaxFreqLevel = 0;
			}
			
			// 봉우리가 한동안 갱신되지 않으면 진짜 봉우리로 인정
			if (maxFreqLevel > opt.minPeakLevel &&
				afterMaxFreqLevel > opt.peakEndingCheck) {
				sample[maxFreqIndex] = maxFreqLevel;
{'fraction_non_alphanumeric': 0.1122923588039867, 'fraction_numerical': 0.008970099667774087, 'mean_word_length': 2.918004338394794, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '939979', 'n_tokens_mistral': 4487, 'n_tokens_neox': 4360, 'n_words': 856}