-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy paththread.js
More file actions
125 lines (103 loc) · 3.38 KB
/
thread.js
File metadata and controls
125 lines (103 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
let crepeModule;
let isInitialized = false;
const ANALYSIS_INTERVAL = 250;
onmessage = function(e) {
const data = e.data;
switch(data.command) {
case 'INIT':
initializeWasm(data.wasmUrl);
break;
case 'ANALYZE':
if (!isInitialized) {
postMessage({
type: 'ERROR',
message: 'WASM module not initialized'
});
return;
}
analyzePitch(data.audioData, data.testFrequency);
break;
case 'CLEANUP':
if (isInitialized && crepeModule._cleanup) {
crepeModule._cleanup();
}
break;
}
};
function initializeWasm(wasmUrl) {
importScripts(wasmUrl);
CrepeModule({
onRuntimeInitialized: function() {
console.log("[Worker] WASM runtime initialized");
}
}).then(module => {
crepeModule = module;
isInitialized = true;
console.log("[Worker] CREPE module loaded successfully");
postMessage({
type: 'INIT_COMPLETE'
});
}).catch(err => {
console.error("[Worker] Failed to load CREPE module:", err);
postMessage({
type: 'ERROR',
message: 'Failed to load CREPE module: ' + err.message
});
});
}
function analyzePitch(audioData, testFrequency) {
try {
const startTime = performance.now();
audioData = new Float32Array(audioData);
const bufferBytes = audioData.length * 4;
const inputPtr = crepeModule._malloc(bufferBytes);
if (!inputPtr) {
postMessage({
type: 'ERROR',
message: 'Failed to allocate memory in WASM'
});
return;
}
crepeModule.HEAPF32.set(audioData, inputPtr / 4);
const resultPtr = crepeModule._analyse_audio(inputPtr, audioData.length);
crepeModule._free(inputPtr);
if (!resultPtr) {
postMessage({
type: 'ERROR',
message: 'Null result from WASM module'
});
return;
}
const numFrames = crepeModule.HEAPF32[resultPtr/4];
if (numFrames <= 0) {
crepeModule._free(resultPtr);
postMessage({
type: 'ERROR',
message: 'No frames returned from analysis'
});
return;
}
const results = [];
for (let i = 0; i < numFrames; i++) {
const baseIndex = resultPtr/4 + 1 + i*3;
results.push({
pitch: crepeModule.HEAPF32[baseIndex],
confidence: crepeModule.HEAPF32[baseIndex + 1],
time: crepeModule.HEAPF32[baseIndex + 2]
});
}
crepeModule._free(resultPtr);
const processingTime = performance.now() - startTime;
postMessage({
type: 'ANALYSIS_COMPLETE',
results: results,
testFrequency: testFrequency,
processingTime: processingTime
});
} catch (error) {
postMessage({
type: 'ERROR',
message: 'Error in pitch analysis: ' + error.message
});
}
}