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
|
// This is the core JavaScript for the Spectrogram Editor.
// It handles file loading (.spec), visualization, tool interaction, and saving.
// --- Global Variables ---
let currentSpecData = null; // Stores the parsed spectrogram data
let dctSize = 512; // Default DCT size, read from header
// --- File Handling ---
const specFileInput = document.getElementById('specFileInput');
specFileInput.addEventListener('change', handleFileSelect);
async function handleFileSelect(event) {
const file = event.target.files[0];
if (!file) {
return;
}
try {
const buffer = await file.arrayBuffer();
const dataView = new DataView(buffer);
// Parse SPEC header
const header = {
magic: String.fromCharCode(...new Uint8Array(buffer.slice(0, 4))),
version: dataView.getInt32(4, true),
dct_size: dataView.getInt32(8, true),
num_frames: dataView.getInt32(12, true)
};
if (header.magic !== "SPEC" || header.version !== 1) {
console.error("Invalid SPEC file format.");
alert("Invalid SPEC file format. Please load a valid .spec file.");
return;
}
dctSize = header.dct_size;
const dataStart = 16;
const numBytes = header.num_frames * header.dct_size * sizeof(float);
const spectralDataFloat = new Float32Array(buffer, dataStart, header.num_frames * header.dct_size);
currentSpecData = {
header: header,
data: spectralDataFloat
};
console.log("Loaded SPEC file:", header);
drawSpectrogram(currentSpecData);
} catch (error) {
console.error("Error loading SPEC file:", error);
alert("Failed to load SPEC file. Check console for details.");
}
}
// --- Spectrogram Visualization ---
const canvas = document.getElementById('spectrogramCanvas');
const ctx = canvas.getContext('2d');
function drawSpectrogram(specData) {
if (!specData || !specData.data) {
console.warn("No spectrogram data to draw.");
return;
}
const width = canvas.width = window.innerWidth * 0.7; // Example dimensions
const height = canvas.height = 400; // Example dimensions
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, width, height);
const numFrames = specData.header.num_frames;
const binsPerFrame = specData.data.length / numFrames;
if (numFrames === 0 || binsPerFrame === 0) {
console.warn("Spectrogram has no frames or invalid data.");
return;
}
// Simplified visualization: draw a few lines to represent frames
const frameWidth = width / numFrames;
ctx.strokeStyle = '#000000';
ctx.lineWidth = 1;
ctx.beginPath();
// Draw a simplified representation of the first frame
const frameIndex = 0;
const frameDataStart = frameIndex * dctSize;
const maxVal = 1.0; // Assume normalization or known range for now
for (let i = 0; i < dctSize; ++i) {
const value = specData.data[frameDataStart + i];
const x = (i / dctSize) * width;
const y = height - (Math.abs(value) / maxVal) * height * 0.5; // Simplified scaling
if (i === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
}
ctx.stroke();
}
// --- Tool Interactions ---
const lineToolButton = document.getElementById('lineTool');
const ellipseToolButton = document.getElementById('ellipseTool');
const noiseToolButton = document.getElementById('noiseTool');
lineToolButton.addEventListener('click', () => console.log('Line tool selected'));
ellipseToolButton.addEventListener('click', () => console.log('Ellipse tool selected'));
noiseToolButton.addEventListener('click', () => console.log('Noise tool selected'));
// TODO: Implement canvas event listeners for drawing shapes
// TODO: Implement shape parameter controls
// TODO: Implement save/load JSON
// TODO: Implement .spec export
// Initial setup for canvas size (can be updated on window resize)
window.addEventListener('resize', () => {
// Re-draw or re-initialize canvas size if needed
if (currentSpecData) {
drawSpectrogram(currentSpecData);
}
});
|