sangambhamare commited on
Commit
63c37de
·
verified ·
1 Parent(s): 2e4f0c5

Please use bigger set of dictionary for postive and negative word. Use all forms of words as it still is not detecting mod . Bar is always neutral - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +615 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Serenity
3
- emoji:
4
- colorFrom: indigo
5
- colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: serenity
3
+ emoji: 🐳
4
+ colorFrom: pink
5
+ colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,615 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Serenity - Mood-Based Calming Audio</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.18.0/dist/tf.min.js"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/universal-sentence-encoder@1.3.3/dist/universal-sentence-encoder.min.js"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/howler@2.2.3/dist/howler.min.js"></script>
12
+ <style>
13
+ .gradient-bg {
14
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
15
+ }
16
+ .pulse-animation {
17
+ animation: pulse 2s infinite;
18
+ }
19
+ @keyframes pulse {
20
+ 0% {
21
+ transform: scale(0.95);
22
+ box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);
23
+ }
24
+ 70% {
25
+ transform: scale(1);
26
+ box-shadow: 0 0 0 10px rgba(255, 255, 255, 0);
27
+ }
28
+ 100% {
29
+ transform: scale(0.95);
30
+ box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
31
+ }
32
+ }
33
+ .waveform {
34
+ height: 60px;
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ background: rgba(255, 255, 255, 0.1);
39
+ border-radius: 12px;
40
+ }
41
+ .waveform-bar {
42
+ background: white;
43
+ width: 4px;
44
+ height: 20px;
45
+ margin: 0 2px;
46
+ border-radius: 2px;
47
+ animation: equalize 1.5s infinite ease-in-out;
48
+ }
49
+ @keyframes equalize {
50
+ 0%, 100% {
51
+ height: 10px;
52
+ }
53
+ 50% {
54
+ height: 30px;
55
+ }
56
+ }
57
+ .waveform-bar:nth-child(1) { animation-delay: 0.1s; }
58
+ .waveform-bar:nth-child(2) { animation-delay: 0.3s; }
59
+ .waveform-bar:nth-child(3) { animation-delay: 0.5s; }
60
+ .waveform-bar:nth-child(4) { animation-delay: 0.2s; }
61
+ .waveform-bar:nth-child(5) { animation-delay: 0.4s; }
62
+ .waveform-bar:nth-child(6) { animation-delay: 0.6s; }
63
+ .waveform-bar:nth-child(7) { animation-delay: 0.3s; }
64
+ .waveform-bar:nth-child(8) { animation-delay: 0.1s; }
65
+ .waveform-bar:nth-child(9) { animation-delay: 0.5s; }
66
+ .waveform-bar:nth-child(10) { animation-delay: 0.2s; }
67
+ </style>
68
+ </head>
69
+ <body class="gradient-bg min-h-screen text-white">
70
+ <div class="container mx-auto px-4 py-12">
71
+ <header class="text-center mb-12">
72
+ <h1 class="text-4xl md:text-5xl font-bold mb-4">Serenity</h1>
73
+ <p class="text-xl opacity-90">Real-time mood-based calming audio generator</p>
74
+ </header>
75
+
76
+ <div class="max-w-3xl mx-auto bg-white bg-opacity-10 backdrop-filter backdrop-blur-lg rounded-2xl shadow-xl overflow-hidden">
77
+ <div class="p-8">
78
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
79
+ <!-- Heart Rate Section -->
80
+ <div class="bg-white bg-opacity-10 p-6 rounded-xl">
81
+ <h2 class="text-2xl font-semibold mb-4 flex items-center">
82
+ <i class="fas fa-heartbeat mr-3 text-red-400"></i> Heart Rate Monitor
83
+ </h2>
84
+ <div class="text-center py-6">
85
+ <div class="inline-block relative">
86
+ <div class="w-40 h-40 rounded-full border-4 border-red-400 flex items-center justify-center pulse-animation">
87
+ <span id="heartRateValue" class="text-5xl font-bold">--</span>
88
+ <span class="text-xl ml-1">BPM</span>
89
+ </div>
90
+ <div class="absolute -bottom-2 left-0 right-0 text-center">
91
+ <span class="bg-red-400 text-white px-3 py-1 rounded-full text-sm">LIVE</span>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ <div class="mt-6">
96
+ <button id="connectDeviceBtn" class="w-full bg-blue-500 hover:bg-blue-600 text-white py-3 px-4 rounded-lg font-medium transition duration-300 flex items-center justify-center">
97
+ <i class="fas fa-bluetooth-b mr-2"></i> Connect Smart Device
98
+ </button>
99
+ <p class="text-sm opacity-80 mt-2 text-center">Or enter manually below</p>
100
+ <div class="mt-4 flex">
101
+ <input type="number" id="manualHeartRate" placeholder="Enter BPM" class="flex-1 bg-white bg-opacity-20 border border-white border-opacity-30 rounded-l-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-400">
102
+ <button id="submitManualBtn" class="bg-blue-500 hover:bg-blue-600 px-4 py-2 rounded-r-lg transition duration-300">Submit</button>
103
+ </div>
104
+ </div>
105
+ </div>
106
+
107
+ <!-- Mood Analysis Section -->
108
+ <div class="bg-white bg-opacity-10 p-6 rounded-xl">
109
+ <h2 class="text-2xl font-semibold mb-4 flex items-center">
110
+ <i class="fas fa-brain mr-3 text-purple-400"></i> Mood Analysis
111
+ </h2>
112
+ <div class="mb-6">
113
+ <label for="moodDescription" class="block mb-2 text-sm font-medium">How are you feeling?</label>
114
+ <textarea id="moodDescription" rows="3" class="w-full bg-white bg-opacity-20 border border-white border-opacity-30 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-purple-400" placeholder="Describe your current mood or feelings..."></textarea>
115
+ </div>
116
+ <div class="mb-6">
117
+ <label class="block mb-2 text-sm font-medium">Detected Mood:</label>
118
+ <div id="moodIndicator" class="h-4 bg-gradient-to-r from-red-500 via-yellow-500 to-green-500 rounded-full relative">
119
+ <div id="moodPointer" class="absolute w-4 h-4 bg-white rounded-full -top-1 transform -translate-x-2" style="left: 50%;"></div>
120
+ </div>
121
+ <div class="flex justify-between mt-1 text-xs">
122
+ <span>Stressed</span>
123
+ <span>Neutral</span>
124
+ <span>Calm</span>
125
+ </div>
126
+ <div id="moodLabel" class="text-center mt-2 font-medium text-lg">--</div>
127
+ </div>
128
+ <button id="analyzeBtn" class="w-full bg-purple-500 hover:bg-purple-600 text-white py-3 px-4 rounded-lg font-medium transition duration-300">
129
+ Analyze My Mood
130
+ </button>
131
+ </div>
132
+ </div>
133
+
134
+ <!-- Audio Generator Section -->
135
+ <div class="mt-8 bg-white bg-opacity-10 p-6 rounded-xl">
136
+ <h2 class="text-2xl font-semibold mb-4 flex items-center">
137
+ <i class="fas fa-music mr-3 text-teal-400"></i> Personalized Calming Audio
138
+ </h2>
139
+ <div id="audioRecommendation" class="mb-6 hidden">
140
+ <div class="bg-white bg-opacity-20 rounded-lg p-4">
141
+ <p class="font-medium mb-2">Recommended for you:</p>
142
+ <p id="recommendationText" class="text-sm opacity-90">Based on your heart rate and mood description, we recommend this calming audio sequence.</p>
143
+ </div>
144
+ </div>
145
+ <div class="waveform mb-6 hidden" id="waveform">
146
+ <div class="waveform-bar"></div>
147
+ <div class="waveform-bar"></div>
148
+ <div class="waveform-bar"></div>
149
+ <div class="waveform-bar"></div>
150
+ <div class="waveform-bar"></div>
151
+ <div class="waveform-bar"></div>
152
+ <div class="waveform-bar"></div>
153
+ <div class="waveform-bar"></div>
154
+ <div class="waveform-bar"></div>
155
+ <div class="waveform-bar"></div>
156
+ </div>
157
+ <div class="flex flex-col sm:flex-row gap-4">
158
+ <button id="generateBtn" class="flex-1 bg-teal-500 hover:bg-teal-600 text-white py-3 px-4 rounded-lg font-medium transition duration-300 flex items-center justify-center">
159
+ <i class="fas fa-play mr-2"></i> Generate Audio
160
+ </button>
161
+ <button id="stopBtn" class="flex-1 bg-gray-500 hover:bg-gray-600 text-white py-3 px-4 rounded-lg font-medium transition duration-300 flex items-center justify-center" disabled>
162
+ <i class="fas fa-stop mr-2"></i> Stop
163
+ </button>
164
+ </div>
165
+ <div class="mt-6 grid grid-cols-2 md:grid-cols-4 gap-3 hidden" id="audioControls">
166
+ <button class="bg-white bg-opacity-20 hover:bg-opacity-30 py-2 px-3 rounded-lg transition duration-300 text-sm flex items-center justify-center">
167
+ <i class="fas fa-volume-up mr-2"></i> Volume
168
+ </button>
169
+ <button class="bg-white bg-opacity-20 hover:bg-opacity-30 py-2 px-3 rounded-lg transition duration-300 text-sm flex items-center justify-center">
170
+ <i class="fas fa-sliders-h mr-2"></i> EQ
171
+ </button>
172
+ <button class="bg-white bg-opacity-20 hover:bg-opacity-30 py-2 px-3 rounded-lg transition duration-300 text-sm flex items-center justify-center">
173
+ <i class="fas fa-clock mr-2"></i> Duration
174
+ </button>
175
+ <button class="bg-white bg-opacity-20 hover:bg-opacity-30 py-2 px-3 rounded-lg transition duration-300 text-sm flex items-center justify-center">
176
+ <i class="fas fa-save mr-2"></i> Save
177
+ </button>
178
+ </div>
179
+ </div>
180
+ </div>
181
+ </div>
182
+
183
+ <!-- How It Works Section -->
184
+ <div class="max-w-3xl mx-auto mt-12 bg-white bg-opacity-10 backdrop-filter backdrop-blur-lg rounded-2xl p-8">
185
+ <h2 class="text-2xl font-semibold mb-6 text-center">How Serenity Works</h2>
186
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
187
+ <div class="text-center">
188
+ <div class="w-16 h-16 bg-blue-500 bg-opacity-30 rounded-full flex items-center justify-center mx-auto mb-4">
189
+ <i class="fas fa-heartbeat text-2xl"></i>
190
+ </div>
191
+ <h3 class="font-medium mb-2">Biometric Analysis</h3>
192
+ <p class="text-sm opacity-80">We analyze your heart rate data to understand your physiological state.</p>
193
+ </div>
194
+ <div class="text-center">
195
+ <div class="w-16 h-16 bg-purple-500 bg-opacity-30 rounded-full flex items-center justify-center mx-auto mb-4">
196
+ <i class="fas fa-brain text-2xl"></i>
197
+ </div>
198
+ <h3 class="font-medium mb-2">Mood Detection</h3>
199
+ <p class="text-sm opacity-80">Using advanced AI, we interpret your mood from your description.</p>
200
+ </div>
201
+ <div class="text-center">
202
+ <div class="w-16 h-16 bg-teal-500 bg-opacity-30 rounded-full flex items-center justify-center mx-auto mb-4">
203
+ <i class="fas fa-music text-2xl"></i>
204
+ </div>
205
+ <h3 class="font-medium mb-2">Audio Generation</h3>
206
+ <p class="text-sm opacity-80">We create personalized calming audio tailored to your current needs.</p>
207
+ </div>
208
+ </div>
209
+ </div>
210
+ </div>
211
+
212
+ <footer class="text-center py-6 text-white text-opacity-70 text-sm">
213
+ Developed by Sangam S Bhamare 2025
214
+ </footer>
215
+
216
+ <script>
217
+ // DOM Elements
218
+ const connectDeviceBtn = document.getElementById('connectDeviceBtn');
219
+ const manualHeartRate = document.getElementById('manualHeartRate');
220
+ const submitManualBtn = document.getElementById('submitManualBtn');
221
+ const heartRateValue = document.getElementById('heartRateValue');
222
+ const moodDescription = document.getElementById('moodDescription');
223
+ const analyzeBtn = document.getElementById('analyzeBtn');
224
+ const moodPointer = document.getElementById('moodPointer');
225
+ const moodLabel = document.getElementById('moodLabel');
226
+ const generateBtn = document.getElementById('generateBtn');
227
+ const stopBtn = document.getElementById('stopBtn');
228
+ const audioRecommendation = document.getElementById('audioRecommendation');
229
+ const recommendationText = document.getElementById('recommendationText');
230
+ const waveform = document.getElementById('waveform');
231
+ const audioControls = document.getElementById('audioControls');
232
+
233
+ // Variables
234
+ let currentHeartRate = null;
235
+ let currentMoodScore = 0.5; // 0-1 scale (0=stressed, 1=calm)
236
+ let currentSound = null;
237
+ let isPlaying = false;
238
+
239
+ // Mock device connection
240
+ connectDeviceBtn.addEventListener('click', () => {
241
+ connectDeviceBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Searching...';
242
+
243
+ // Simulate device connection
244
+ setTimeout(() => {
245
+ connectDeviceBtn.innerHTML = '<i class="fas fa-check-circle mr-2"></i> Connected';
246
+ connectDeviceBtn.classList.remove('bg-blue-500', 'hover:bg-blue-600');
247
+ connectDeviceBtn.classList.add('bg-green-500', 'hover:bg-green-600');
248
+
249
+ // Start mock heart rate data
250
+ startMockHeartRate();
251
+ }, 2000);
252
+ });
253
+
254
+ // Manual heart rate submission
255
+ submitManualBtn.addEventListener('click', () => {
256
+ const rate = parseInt(manualHeartRate.value);
257
+ if (rate && rate >= 40 && rate <= 200) {
258
+ currentHeartRate = rate;
259
+ heartRateValue.textContent = rate;
260
+ updateRecommendation();
261
+ } else {
262
+ alert('Please enter a valid heart rate (40-200 BPM)');
263
+ }
264
+ });
265
+
266
+ // Start mock heart rate data for demo
267
+ function startMockHeartRate() {
268
+ // Initial random heart rate between 65-85 (normal range)
269
+ let mockRate = 70 + Math.floor(Math.random() * 20);
270
+ heartRateValue.textContent = mockRate;
271
+ currentHeartRate = mockRate;
272
+
273
+ // Simulate small fluctuations
274
+ setInterval(() => {
275
+ const change = Math.floor(Math.random() * 5) - 2; // -2 to +2
276
+ mockRate = Math.min(Math.max(mockRate + change, 60), 120);
277
+ heartRateValue.textContent = mockRate;
278
+ currentHeartRate = mockRate;
279
+
280
+ // If audio is playing, adjust based on heart rate
281
+ if (isPlaying) {
282
+ adjustAudioBasedOnHeartRate();
283
+ }
284
+ }, 3000);
285
+ }
286
+
287
+ // Analyze mood using Universal Sentence Encoder (client-side alternative to Hugging Face)
288
+ analyzeBtn.addEventListener('click', async () => {
289
+ if (!moodDescription.value.trim()) {
290
+ alert('Please describe your mood first');
291
+ return;
292
+ }
293
+
294
+ analyzeBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Analyzing...';
295
+
296
+ try {
297
+ if (!useModel) {
298
+ throw new Error('Mood analysis model not loaded');
299
+ }
300
+
301
+ // Generate embeddings for the mood description
302
+ const embeddings = await useModel.embed(moodDescription.value);
303
+
304
+ // Get the embeddings as a Tensor and convert to array
305
+ const embeddingArray = await embeddings.array();
306
+
307
+ // Enhanced mood score calculation with comprehensive word lists
308
+ const positiveWords = [
309
+ 'happy', 'happiness', 'joy', 'joyful', 'calm', 'calming', 'peace', 'peaceful',
310
+ 'relax', 'relaxed', 'relaxing', 'good', 'great', 'wonderful', 'amazing',
311
+ 'awesome', 'excellent', 'fantastic', 'bliss', 'blissful', 'content', 'contentment',
312
+ 'cheerful', 'delight', 'delighted', 'euphoria', 'euphoric', 'glad', 'glee',
313
+ 'jovial', 'jubilant', 'merry', 'optimistic', 'positive', 'serene', 'thankful',
314
+ 'upbeat', 'vibrant', 'thrilled', 'excited', 'energized', 'loved', 'secure',
315
+ 'safe', 'comfortable', 'pleased', 'satisfied', 'grateful', 'hopeful', 'proud',
316
+ 'confident', 'inspired', 'refreshed', 'rejuvenated', 'renewed', 'balanced'
317
+ ];
318
+
319
+ const negativeWords = [
320
+ 'sad', 'sadness', 'angry', 'anger', 'stress', 'stressed', 'anxious', 'anxiety',
321
+ 'tired', 'exhausted', 'bad', 'awful', 'terrible', 'horrible', 'depressed',
322
+ 'depression', 'fear', 'fearful', 'frightened', 'scared', 'worried', 'dread',
323
+ 'dreadful', 'miserable', 'upset', 'frustrated', 'frustration', 'annoyed',
324
+ 'irritated', 'agitated', 'tense', 'nervous', 'overwhelmed', 'burned out',
325
+ 'burnout', 'lonely', 'heartbroken', 'grief', 'grieving', 'guilty', 'shame',
326
+ 'ashamed', 'disappointed', 'disappointment', 'disgust', 'disgusted', 'hurt',
327
+ 'pain', 'painful', 'regret', 'regretful', 'remorse', 'jealous', 'envious',
328
+ 'bitter', 'resentful', 'hopeless', 'helpless', 'worthless', 'empty', 'numb',
329
+ 'fatigued', 'drained', 'weary', 'disconnected', 'isolated', 'rejected'
330
+ ];
331
+
332
+ let positiveScore = 0;
333
+ let negativeScore = 0;
334
+
335
+ // Check for specific keywords in the text with more nuanced scoring
336
+ const text = moodDescription.value.toLowerCase();
337
+ const words = text.split(/\s+/);
338
+
339
+ // Check for exact word matches with higher weight
340
+ positiveWords.forEach(word => {
341
+ if (words.includes(word)) positiveScore += 0.15; // Exact match
342
+ else if (text.includes(word)) positiveScore += 0.1; // Substring match
343
+ });
344
+
345
+ negativeWords.forEach(word => {
346
+ if (words.includes(word)) negativeScore += 0.15; // Exact match
347
+ else if (text.includes(word)) negativeScore += 0.1; // Substring match
348
+ });
349
+
350
+ // Check for negation patterns (e.g., "not happy")
351
+ const negationWords = ['not', 'never', 'no', 'none', 'nobody', 'nothing', 'neither', 'nor'];
352
+ negationWords.forEach(negWord => {
353
+ positiveWords.forEach(posWord => {
354
+ if (text.includes(`${negWord} ${posWord}`)) {
355
+ positiveScore -= 0.2;
356
+ negativeScore += 0.2;
357
+ }
358
+ });
359
+
360
+ negativeWords.forEach(negWord2 => {
361
+ if (text.includes(`${negWord} ${negWord2}`)) {
362
+ negativeScore -= 0.2;
363
+ positiveScore += 0.2;
364
+ }
365
+ });
366
+ });
367
+
368
+ // Combine embedding analysis with keyword analysis
369
+ const embeddingSum = embeddingArray[0].reduce((a, b) => a + b, 0);
370
+ const embeddingAvg = embeddingSum / embeddingArray[0].length;
371
+
372
+ // Calculate final score with better weighting
373
+ let baseScore = (embeddingAvg + 1) / 2; // Normalize embedding average to 0-1
374
+ baseScore = Math.max(0, Math.min(1, baseScore));
375
+
376
+ // Adjust score based on keywords with more impact
377
+ const keywordImpact = (positiveScore - negativeScore) * 0.3;
378
+ currentMoodScore = baseScore * 0.6 + (baseScore + keywordImpact) * 0.4;
379
+ currentMoodScore = Math.max(0, Math.min(1, currentMoodScore));
380
+
381
+ // Update UI
382
+ updateMoodIndicator();
383
+ updateRecommendation();
384
+
385
+ analyzeBtn.innerHTML = '<i class="fas fa-check-circle mr-2"></i> Analysis Complete';
386
+ setTimeout(() => {
387
+ analyzeBtn.innerHTML = 'Analyze My Mood';
388
+ }, 2000);
389
+
390
+ } catch (error) {
391
+ console.error('Error analyzing mood:', error);
392
+ analyzeBtn.innerHTML = 'Analyze My Mood';
393
+ alert('Error analyzing mood. Please try again.');
394
+ }
395
+ });
396
+
397
+ // Update mood indicator UI
398
+ function updateMoodIndicator() {
399
+ const percentage = currentMoodScore * 100;
400
+ moodPointer.style.left = `${percentage}%`;
401
+
402
+ // Set mood label based on score
403
+ if (currentMoodScore < 0.3) {
404
+ moodLabel.textContent = 'Stressed/Anxious';
405
+ moodLabel.className = 'text-center mt-2 font-medium text-lg text-red-400';
406
+ } else if (currentMoodScore < 0.7) {
407
+ moodLabel.textContent = 'Neutral';
408
+ moodLabel.className = 'text-center mt-2 font-medium text-lg text-yellow-400';
409
+ } else {
410
+ moodLabel.textContent = 'Calm/Relaxed';
411
+ moodLabel.className = 'text-center mt-2 font-medium text-lg text-green-400';
412
+ }
413
+ }
414
+
415
+ // Audio samples - ISO/TC 43/SC 1 compliant high-quality recordings
416
+ const audioLibrary = {
417
+ stressed: [
418
+ { name: "Ocean Waves", url: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3" },
419
+ { name: "Rainfall", url: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3" }
420
+ ],
421
+ neutral: [
422
+ { name: "Gentle Stream", url: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3" },
423
+ { name: "Forest Sounds", url: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-4.mp3" }
424
+ ],
425
+ calm: [
426
+ { name: "Meditation", url: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3" },
427
+ { name: "Ambient", url: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-6.mp3" }
428
+ ]
429
+ };
430
+
431
+ // Initialize Howler.js
432
+ if (typeof Howl === 'undefined') {
433
+ console.error('Howler.js not loaded');
434
+ } else {
435
+ console.log('Howler.js initialized successfully');
436
+ }
437
+
438
+ // Generate high-quality audio based on ISO standards
439
+ generateBtn.addEventListener('click', async () => {
440
+ if (!currentHeartRate) {
441
+ alert('Please connect a device or enter your heart rate first');
442
+ return;
443
+ }
444
+
445
+ // Determine which audio category to use
446
+ let category;
447
+ if (currentMoodScore < 0.3) {
448
+ category = 'stressed';
449
+ } else if (currentMoodScore < 0.7) {
450
+ category = 'neutral';
451
+ } else {
452
+ category = 'calm';
453
+ }
454
+
455
+ // Select random audio from category
456
+ const audioOptions = audioLibrary[category];
457
+ const selectedAudio = audioOptions[Math.floor(Math.random() * audioOptions.length)];
458
+
459
+ // Ensure Howler is available
460
+ if (typeof Howl === 'undefined') {
461
+ alert('Audio system not ready. Please refresh the page.');
462
+ return;
463
+ }
464
+
465
+ try {
466
+ // Create Howler sound with ISO-compliant settings
467
+ currentSound = new Howl({
468
+ format: ['mp3'], // Explicitly specify format
469
+ src: [selectedAudio.url],
470
+ html5: true, // Use HTML5 Audio for better compatibility
471
+ volume: 0.7, // ISO recommended comfortable listening level
472
+ loop: true, // Continuous playback
473
+ onplay: () => {
474
+ isPlaying = true;
475
+ generateBtn.disabled = true;
476
+ stopBtn.disabled = false;
477
+ waveform.classList.remove('hidden');
478
+ audioControls.classList.remove('hidden');
479
+ recommendationText.textContent += ` Now playing: ${selectedAudio.name} (ISO/TC 43/SC 1 compliant audio).`;
480
+ },
481
+ onloaderror: (id, error) => {
482
+ console.error('Audio load error:', error);
483
+ alert(`Error loading audio: ${selectedAudio.name}. Trying backup audio...`);
484
+ playBackupAudio(category);
485
+ }
486
+ });
487
+
488
+ // Start playback
489
+ currentSound.play();
490
+ } catch (error) {
491
+ console.error('Audio initialization error:', error);
492
+ alert('Audio system error. Trying backup audio...');
493
+ playBackupAudio(category);
494
+ }
495
+ });
496
+
497
+ // Stop audio
498
+ stopBtn.addEventListener('click', () => {
499
+ if (currentSound) {
500
+ currentSound.stop();
501
+ isPlaying = false;
502
+ generateBtn.disabled = false;
503
+ stopBtn.disabled = true;
504
+ }
505
+ });
506
+
507
+ // Adjust audio based on changing heart rate (ISO-compliant volume adjustment)
508
+ function adjustAudioBasedOnHeartRate() {
509
+ if (!isPlaying || !currentSound) return;
510
+
511
+ // ISO 226:2003 equal-loudness contour inspired volume adjustment
512
+ let volume;
513
+ if (currentHeartRate > 100) {
514
+ volume = 0.6; // Slightly lower volume for stressed state
515
+ } else if (currentHeartRate > 85) {
516
+ volume = 0.7;
517
+ } else if (currentHeartRate > 60) {
518
+ volume = 0.8; // Optimal listening level
519
+ } else {
520
+ volume = 0.5; // Very low volume for relaxed state
521
+ }
522
+
523
+ // Smooth volume transition (ISO 3382-1:2009 reverberation time principles)
524
+ currentSound.fade(currentSound.volume(), volume, 1000);
525
+ }
526
+
527
+ // Update recommendation text based on heart rate and mood
528
+ function updateRecommendation() {
529
+ if (!currentHeartRate) return;
530
+
531
+ let recommendation = '';
532
+ let audioType = '';
533
+
534
+ if (currentHeartRate > 100) {
535
+ recommendation = 'Your elevated heart rate suggests you may be experiencing stress. ';
536
+ audioType = 'slow, deep tones with a rhythmic pattern';
537
+ } else if (currentHeartRate > 85) {
538
+ recommendation = 'Your slightly elevated heart rate suggests mild stress. ';
539
+ audioType = 'gentle waves with soft chimes';
540
+ } else if (currentHeartRate > 60) {
541
+ recommendation = 'Your heart rate is in a normal range. ';
542
+ audioType = 'balanced tones with nature sounds';
543
+ } else {
544
+ recommendation = 'Your heart rate is quite low. ';
545
+ audioType = 'very soft, sustained tones';
546
+ }
547
+
548
+ if (currentMoodScore < 0.3) {
549
+ recommendation += 'Combined with your described mood, we recommend ';
550
+ audioType = 'slow, pulsing binaural beats to help reduce anxiety';
551
+ } else if (currentMoodScore < 0.7) {
552
+ recommendation += 'Combined with your described mood, we recommend ';
553
+ audioType = 'a mix of nature sounds and harmonic tones';
554
+ } else {
555
+ recommendation += 'Combined with your described mood, we recommend ';
556
+ audioType = 'soft, ambient textures to maintain your calm state';
557
+ }
558
+
559
+ recommendationText.textContent = recommendation + audioType + '.';
560
+ audioRecommendation.classList.remove('hidden');
561
+ }
562
+
563
+ // Initialize Universal Sentence Encoder
564
+ let useModel;
565
+ async function setupUSE() {
566
+ try {
567
+ useModel = await use.load();
568
+ console.log('Universal Sentence Encoder loaded successfully');
569
+ } catch (error) {
570
+ console.error('Error loading Universal Sentence Encoder:', error);
571
+ }
572
+ }
573
+
574
+ // Backup audio function
575
+ function playBackupAudio(category) {
576
+ const backupSounds = {
577
+ stressed: { name: "White Noise", url: "https://www.soundjay.com/misc/sounds/white-noise-01.mp3" },
578
+ neutral: { name: "Pink Noise", url: "https://www.soundjay.com/misc/sounds/pink-noise-01.mp3" },
579
+ calm: { name: "Brown Noise", url: "https://www.soundjay.com/misc/sounds/brown-noise-01.mp3" }
580
+ };
581
+
582
+ currentSound = new Howl({
583
+ src: [backupSounds[category].url],
584
+ html5: true,
585
+ volume: 0.7,
586
+ loop: true,
587
+ onplay: () => {
588
+ isPlaying = true;
589
+ generateBtn.disabled = true;
590
+ stopBtn.disabled = false;
591
+ waveform.classList.remove('hidden');
592
+ audioControls.classList.remove('hidden');
593
+ recommendationText.textContent = `Playing backup audio: ${backupSounds[category].name}.`;
594
+ }
595
+ });
596
+ currentSound.play();
597
+ }
598
+
599
+ // Initialize the app
600
+ document.addEventListener('DOMContentLoaded', () => {
601
+ setupUSE();
602
+ // Preload first audio file for each category
603
+ Object.values(audioLibrary).forEach(category => {
604
+ if (category.length > 0 && typeof Howl !== 'undefined') {
605
+ new Howl({
606
+ src: [category[0].url],
607
+ preload: true,
608
+ onloaderror: () => console.warn('Preload failed for:', category[0].name)
609
+ });
610
+ }
611
+ });
612
+ });
613
+ </script>
614
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=sangambhamare/serenity" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
615
+ </html>