File size: 19,677 Bytes
81dffac
 
 
 
0d0cd81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3980065
0d0cd81
 
 
 
81dffac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3980065
 
ed11f41
81dffac
 
 
 
 
3980065
 
 
ed11f41
81dffac
 
 
 
 
3980065
 
 
ed11f41
81dffac
 
 
 
 
3980065
 
 
ed11f41
81dffac
 
 
 
 
3980065
 
 
ed11f41
81dffac
 
 
 
 
3980065
 
 
ed11f41
81dffac
 
 
 
 
3980065
 
 
ed11f41
81dffac
 
 
 
 
eb5d450
 
 
ed11f41
81dffac
 
 
 
 
eb5d450
 
 
ed11f41
81dffac
 
 
 
 
3980065
 
 
81dffac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3980065
0d0cd81
3980065
0d0cd81
81dffac
 
 
 
 
 
 
 
eb5d450
81dffac
 
3980065
 
 
ed11f41
0d0cd81
 
 
3980065
 
ed11f41
3980065
 
 
 
81dffac
3980065
 
 
 
 
 
ed11f41
3980065
0d0cd81
 
 
3980065
0d0cd81
 
81dffac
 
 
 
 
 
 
3980065
81dffac
 
 
 
 
 
 
 
0d0cd81
81dffac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3980065
eb5d450
ed11f41
efe75f7
ed11f41
eb5d450
3980065
0d0cd81
 
eb5d450
 
 
81dffac
3980065
 
0d0cd81
81dffac
ed11f41
 
eb5d450
 
81dffac
 
 
eb5d450
81dffac
eb5d450
ed11f41
eb5d450
 
0d0cd81
 
 
ed11f41
3980065
0d0cd81
 
 
3980065
 
 
ed11f41
 
0d0cd81
 
 
 
ed11f41
0d0cd81
 
 
 
 
3980065
 
ed11f41
3980065
0d0cd81
 
81dffac
eb5d450
8fbfd87
 
 
 
 
 
 
 
0d0cd81
 
 
 
81dffac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3980065
0d0cd81
efe75f7
81dffac
efe75f7
eb5d450
81dffac
 
 
 
efe75f7
0d0cd81
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
// ═══════════════════════════════════════════════════════════
// FILE: server.js - Complete Backend with Smart Instruments
// ═══════════════════════════════════════════════════════════

const express = require('express');
const multer = require('multer');
const cors = require('cors');
const path = require('path');
const fs = require('fs');
const { exec } = require('child_process');
const util = require('util');
const execPromise = util.promisify(exec);

const app = express();
const PORT = process.env.PORT || 7860;

app.use(cors());
app.use(express.json());

const uploadsDir = path.join(__dirname, 'uploads');
const outputsDir = path.join(__dirname, 'outputs');

if (!fs.existsSync(uploadsDir)) fs.mkdirSync(uploadsDir, { recursive: true });
if (!fs.existsSync(outputsDir)) fs.mkdirSync(outputsDir, { recursive: true });

const storage = multer.diskStorage({
  destination: (req, file, cb) => cb(null, uploadsDir),
  filename: (req, file, cb) => cb(null, `${Date.now()}-${file.originalname}`)
});

const upload = multer({
  storage: storage,
  limits: { fileSize: 50 * 1024 * 1024 }
});

// 🎹 ═══════════════════════════════════════════════════════════
// INSTRUMENT LIBRARY - Categorized by Mood
// ═══════════════════════════════════════════════════════════

const INSTRUMENTS = {
  // πŸ’” SAD INSTRUMENTS
  sad_piano: {
    name: "Sad Piano",
    mood: "sad",
    command: "aevalsrc='0.13*sin(2*PI*(220+5*sin(0.08*t))*t)*exp(-0.15*mod(t,4))':d=12,aecho=0.7:0.85:600:0.35,lowpass=f=3000"
  },
  melancholic_violin: {
    name: "Melancholic Violin",
    mood: "sad",
    command: "aevalsrc='0.12*sin(2*PI*330*t)*sin(2*PI*0.3*t)*exp(-0.1*mod(t,5))':d=12,vibrato=f=0.15:d=0.5,aecho=0.6:0.8:500:0.3"
  },
  lonely_cello: {
    name: "Lonely Cello",
    mood: "sad",
    command: "aevalsrc='0.14*sin(2*PI*165*t)*sin(2*PI*0.2*t)':d=12,chorus=0.4:0.7:40:0.3:0.2:2,lowpass=f=2500"
  },
  tearful_flute: {
    name: "Tearful Flute",
    mood: "sad",
    command: "aevalsrc='0.11*sin(2*PI*440*t)*sin(2*PI*1.5*t)*exp(-0.2*mod(t,3))':d=12,aecho=0.5:0.75:400:0.3,vibrato=f=0.2:d=0.4"
  },

  // ❀️ ROMANTIC INSTRUMENTS
  romantic_piano: {
    name: "Romantic Piano",
    mood: "romantic",
    command: "aevalsrc='0.12*(sin(2*PI*330*t)+sin(2*PI*415*t))*exp(-0.12*mod(t,3.5))':d=12,aecho=0.6:0.8:450:0.35,chorus=0.3:0.6:35:0.25:0.15:2"
  },
  love_strings: {
    name: "Love Strings",
    mood: "romantic",
    command: "aevalsrc='0.13*(sin(2*PI*440*t)+sin(2*PI*554*t))*sin(2*PI*0.4*t)':d=12,vibrato=f=0.18:d=0.45,aecho=0.5:0.7:350:0.3"
  },
  gentle_harp: {
    name: "Gentle Harp",
    mood: "romantic",
    command: "aevalsrc='0.11*sin(2*PI*(660+8*sin(0.15*t))*t)*exp(-0.25*mod(t,2.5))':d=12,chorus=0.4:0.7:45:0.3:0.2:2,aecho=0.6:0.8:300:0.35"
  },
  sweet_bells: {
    name: "Sweet Bells",
    mood: "romantic",
    command: "aevalsrc='0.09*sin(2*PI*880*t)*exp(-0.4*mod(t,2))':d=12,aecho=0.5:0.75:250:0.4,vibrato=f=0.12:d=0.3"
  },

  // πŸ’”β€οΈ SAD ROMANTIC MIX
  bittersweet_piano: {
    name: "Bittersweet Piano",
    mood: "sad_romantic",
    command: "aevalsrc='0.13*(sin(2*PI*247*t)+sin(2*PI*330*t))*exp(-0.15*mod(t,4))*(1+0.3*sin(0.5*t))':d=12,aecho=0.7:0.85:500:0.35,vibrato=f=0.1:d=0.4"
  },
  nostalgic_violin: {
    name: "Nostalgic Violin",
    mood: "sad_romantic",
    command: "aevalsrc='0.12*sin(2*PI*370*t)*sin(2*PI*0.35*t)*(1+0.2*sin(0.3*t))':d=12,chorus=0.5:0.75:40:0.3:0.2:2,aecho=0.6:0.8:450:0.3"
  },
  heartbreak_strings: {
    name: "Heartbreak Strings",
    mood: "sad_romantic",
    command: "aevalsrc='0.13*(sin(2*PI*220*t)+sin(2*PI*330*t))*exp(-0.1*mod(t,5))':d=12,vibrato=f=0.15:d=0.5,lowpass=f=3500"
  },

  // πŸŒ™ AMBIENT/DREAMY INSTRUMENTS
  dreamy_pad: {
    name: "Dreamy Pad",
    mood: "ambient",
    command: "aevalsrc='0.11*(sin(2*PI*165*t)+sin(2*PI*220*t)+sin(2*PI*330*t))':d=12,aphaser=in_gain=0.4:out_gain=0.7:delay=3:decay=0.4:speed=0.25,aecho=0.5:0.7:400:0.3"
  },
  ethereal_synth: {
    name: "Ethereal Synth",
    mood: "ambient",
    command: "aevalsrc='0.1*(sin(2*PI*220*t)+sin(2*PI*277*t))*sin(2*PI*0.5*t)':d=12,chorus=0.6:0.85:50:0.4:0.25:2,aecho=0.6:0.8:500:0.3"
  },
  celestial_bells: {
    name: "Celestial Bells",
    mood: "ambient",
    command: "aevalsrc='0.09*(sin(2*PI*880*t)+sin(2*PI*1108*t))*exp(-0.3*t)':d=12,aecho=0.7:0.9:600:0.4,aphaser=in_gain=0.3:out_gain=0.6:delay=2:decay=0.3:speed=0.2"
  },

  // 🎸 CHILL/LOFI INSTRUMENTS
  lofi_guitar: {
    name: "LoFi Guitar",
    mood: "chill",
    command: "aevalsrc='0.12*sin(2*PI*196*t)*exp(-0.3*mod(t,3))*(1+0.15*random(0))':d=12,chorus=0.5:0.7:40:0.25:0.15:2,lowpass=f=4000"
  },
  jazzy_piano: {
    name: "Jazzy Piano",
    mood: "chill",
    command: "aevalsrc='0.11*(sin(2*PI*262*t)+sin(2*PI*330*t))*exp(-0.2*mod(t,2.5))':d=12,vibrato=f=0.18:d=0.4,aecho=0.4:0.6:300:0.25"
  },
  smooth_sax: {
    name: "Smooth Saxophone",
    mood: "chill",
    command: "aevalsrc='0.12*sin(2*PI*294*t)*sin(2*PI*2*t)':d=12,vibrato=f=0.25:d=0.5,chorus=0.4:0.7:45:0.3:0.2:2"
  },

  // ⚑ UPBEAT/ENERGETIC INSTRUMENTS
  bright_synth: {
    name: "Bright Synth",
    mood: "upbeat",
    command: "aevalsrc='0.11*(sin(2*PI*440*t)+sin(2*PI*554*t)+sin(2*PI*659*t))':d=12,chorus=0.6:0.8:50:0.35:0.25:2,highpass=f=200"
  },
  sparkle_bells: {
    name: "Sparkle Bells",
    mood: "upbeat",
    command: "aevalsrc='0.1*(sin(2*PI*1320*t)+sin(2*PI*1760*t))*exp(-0.5*mod(t,1.5))':d=12,aecho=0.4:0.6:150:0.3,highpass=f=500"
  },
  happy_piano: {
    name: "Happy Piano",
    mood: "upbeat",
    command: "aevalsrc='0.11*(sin(2*PI*523*t)+sin(2*PI*659*t))*exp(-0.25*mod(t,2))':d=12,chorus=0.5:0.7:40:0.3:0.2:2"
  }
};

// 🎯 ═══════════════════════════════════════════════════════════
// SMART EFFECT CONFIGURATIONS - Each effect has mood-matched instruments
// ═══════════════════════════════════════════════════════════

const EFFECTS = {
  lofi: {
    name: "LoFi Hip Hop",
    description: "Vintage warmth with jazzy chill vibes",
    baseCommand: `-af "asetrate=44100*0.90,aresample=44100,bass=g=5:f=85:width_type=h:width=100,treble=g=-3:f=8000,equalizer=f=200:t=q:width=1.5:g=-2,equalizer=f=1000:t=q:width=2:g=2,acompressor=threshold=-20dB:ratio=3:attack=10:release=120:makeup=3,vibrato=f=0.2:d=0.4,highpass=f=70,lowpass=f=4500,volume=1.3"`,
    instrumentVolume: 0.14,
    // LoFi uses chill + some sad romantic vibes
    instrumentMoods: ["chill", "sad_romantic", "ambient"]
  },
  
  slowed_reverb: {
    name: "Slowed + Reverb",
    description: "Dreamy slow with sad romantic atmosphere",
    baseCommand: `-af "atempo=0.90,asetrate=44100*0.95,aresample=44100,bass=g=4:f=80:width_type=h:width=120,aecho=0.8:0.88:250:0.5,aecho=0.7:0.78:400:0.4,aecho=0.6:0.68:600:0.3,equalizer=f=100:t=q:width=2:g=3.5,equalizer=f=4000:t=q:width=4:g=-4,acompressor=threshold=-20dB:ratio=2:attack=15:release=200:makeup=2,highpass=f=50,lowpass=f=7000,volume=1.4"`,
    instrumentVolume: 0.13,
    // Slowed+Reverb is emotional - sad, romantic, sad_romantic mix
    instrumentMoods: ["sad", "romantic", "sad_romantic", "ambient"]
  },
  
  nightcore: {
    name: "Nightcore",
    description: "High energy with bright sparkling sounds",
    baseCommand: `-af "atempo=1.30,asetrate=44100*1.18,aresample=44100,treble=g=6:f=5000:width_type=h:width=3000,bass=g=-3:f=100,equalizer=f=2000:t=q:width=2:g=2.5,equalizer=f=6000:t=q:width=3:g=4,equalizer=f=10000:t=q:width=4:g=5,acompressor=threshold=-18dB:ratio=3:attack=3:release=30:makeup=4,highpass=f=120,volume=1.4"`,
    instrumentVolume: 0.11,
    // Nightcore is upbeat and energetic
    instrumentMoods: ["upbeat", "romantic"]
  },
  
  vaporwave: {
    name: "Vaporwave",
    description: "Retro nostalgic with dreamy sad vibes",
    baseCommand: `-af "asetrate=44100*0.82,aresample=44100,equalizer=f=300:t=q:width=2:g=4,equalizer=f=1500:t=q:width=3:g=-2,equalizer=f=6000:t=q:width=4:g=-4,aphaser=in_gain=0.5:out_gain=0.75:delay=4:decay=0.5:speed=0.2,chorus=0.6:0.85:55:0.4:0.25:2,vibrato=f=0.12:d=0.5,aecho=0.5:0.65:180:0.35,acompressor=threshold=-20dB:ratio=2.5:attack=12:release=150:makeup=2,highpass=f=70,lowpass=f=5500,volume=1.2"`,
    instrumentVolume: 0.13,
    // Vaporwave is nostalgic - sad_romantic + ambient
    instrumentMoods: ["sad_romantic", "ambient", "sad"]
  },
  
  "8d_audio": {
    name: "8D Audio",
    description: "Immersive 360Β° with ambient dreamy layers",
    baseCommand: `-af "apulsator=hz=0.08:mode=sine:width=0.9,extrastereo=m=3:c=1,aecho=0.7:0.85:100:0.35,haas=level_in=1:level_out=1.1:side_gain=0.9:middle_source=mid,bass=g=3:f=85,acompressor=threshold=-18dB:ratio=2:attack=10:release=100:makeup=2,highpass=f=60,volume=1.2"`,
    instrumentVolume: 0.12,
    // 8D is immersive - ambient + romantic
    instrumentMoods: ["ambient", "romantic", "sad_romantic"]
  },
  
  bass_boosted: {
    name: "Bass Boosted",
    description: "Heavy bass with deep atmospheric tones",
    baseCommand: `-af "bass=g=18:f=55:width_type=o:width=1.5,bass=g=14:f=95:width_type=h:width=90,equalizer=f=35:t=q:width=1.2:g=12,equalizer=f=75:t=q:width=1.5:g=10,equalizer=f=140:t=q:width=2:g=8,equalizer=f=500:t=q:width=2:g=-3,equalizer=f=4000:t=q:width=4:g=-6,volume='mod(t,31):if(lt(MOD,15),0.4,if(lt(MOD,18),0.05,if(lt(MOD,26),0.5+0.0625*(MOD-18),1.5)))':eval=frame,acompressor=threshold=-22dB:ratio=8:attack=3:release=40:makeup=8,tremolo=f=0.15:d=0.3,highpass=f=28,alimiter=limit=0.95:attack=5:release=50"`,
    instrumentVolume: 0.09,
    // Bass boosted - deep ambient + chill
    instrumentMoods: ["ambient", "chill"]
  },
  
  ambient: {
    name: "Ambient Chill",
    description: "Ethereal meditation with sad peaceful vibes",
    baseCommand: `-af "asetrate=44100*0.94,aresample=44100,aecho=0.6:0.8:200:0.4,aecho=0.5:0.7:400:0.3,chorus=0.6:0.85:50:0.4:0.25:2,aphaser=in_gain=0.5:out_gain=0.8:delay=3:decay=0.4:speed=0.2,equalizer=f=1500:t=q:width=3:g=-2,equalizer=f=6000:t=q:width=4:g=-4,acompressor=threshold=-18dB:ratio=2:attack=15:release=200:makeup=3,highpass=f=50,lowpass=f=9000,volume=1.5"`,
    instrumentVolume: 0.15,
    // Ambient - all ambient + sad moods
    instrumentMoods: ["ambient", "sad", "sad_romantic"]
  },
  
  tiktok_lofi: {
    name: "TikTok LoFi",
    description: "Viral style with modern romantic chill",
    baseCommand: `-af "asetrate=44100*0.88,aresample=44100,bass=g=6:f=90:width_type=h:width=100,treble=g=-4:f=7500,equalizer=f=200:t=q:width=1.8:g=-1.5,equalizer=f=800:t=q:width=2:g=2,equalizer=f=3000:t=q:width=3:g=-2,acompressor=threshold=-20dB:ratio=4:attack=5:release=100:makeup=4,vibrato=f=0.2:d=0.5,chorus=0.5:0.8:45:0.3:0.2:2,highpass=f=70,lowpass=f=5000,volume=1.35"`,
    instrumentVolume: 0.13,
    // TikTok LoFi - chill + romantic
    instrumentMoods: ["chill", "romantic", "sad_romantic"]
  },
  
  chill_lofi: {
    name: "Chill LoFi",
    description: "Study vibes with jazzy peaceful atmosphere",
    baseCommand: `-af "asetrate=44100*0.92,aresample=44100,bass=g=5:f=88:width_type=h:width=90,treble=g=-4:f=7000,equalizer=f=250:t=q:width=2:g=-1.5,equalizer=f=1000:t=q:width=2.5:g=1.2,equalizer=f=3500:t=q:width=3:g=-2.5,acompressor=threshold=-21dB:ratio=3:attack=10:release=140:makeup=2.5,vibrato=f=0.15:d=0.45,chorus=0.4:0.8:45:0.28:0.18:2,aecho=0.4:0.6:150:0.25,highpass=f=70,lowpass=f=5000,volume=1.2"`,
    instrumentVolume: 0.12,
    // Chill LoFi - pure chill + ambient
    instrumentMoods: ["chill", "ambient"]
  }
};

// 🎲 Smart Random Instrument Selector
function getSmartInstruments(effectType, count = 2) {
  const effect = EFFECTS[effectType];
  if (!effect || !effect.instrumentMoods) {
    return getRandomInstruments(count);
  }

  // Get instruments that match the effect's moods
  const matchingInstruments = Object.keys(INSTRUMENTS).filter(key => 
    effect.instrumentMoods.includes(INSTRUMENTS[key].mood)
  );

  // Shuffle and select
  const shuffled = matchingInstruments.sort(() => Math.random() - 0.5);
  const selected = [];
  
  for (let i = 0; i < Math.min(count, shuffled.length); i++) {
    selected.push(shuffled[i]);
  }
  
  return selected;
}

// Fallback random selector
function getRandomInstruments(count = 2) {
  const instrumentKeys = Object.keys(INSTRUMENTS);
  const shuffled = instrumentKeys.sort(() => Math.random() - 0.5);
  return shuffled.slice(0, count);
}

// πŸ₯ Health Check
app.get('/', (req, res) => {
  res.json({
    status: 'online',
    message: '🎡 LoFi Remix API v3.1 - Smart Mood-Based Instruments',
    version: '3.1',
    features: [
      '9 unique effects',
      'Smart mood-based instrument selection',
      '20+ instruments across 5 moods',
      'Sad, Romantic, Sad-Romantic, Ambient, Chill, Upbeat'
    ],
    total_effects: Object.keys(EFFECTS).length,
    total_instruments: Object.keys(INSTRUMENTS).length,
    instrument_moods: ['sad', 'romantic', 'sad_romantic', 'ambient', 'chill', 'upbeat']
  });
});

// 🎡 Process Audio
app.post('/process', upload.single('audio'), async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ 
        success: false,
        error: 'No audio file uploaded'
      });
    }

    const effectType = req.body.effect || 'lofi';
    const addInstruments = req.body.instruments !== 'false';
    
    if (!EFFECTS[effectType]) {
      fs.unlinkSync(req.file.path);
      return res.status(400).json({ 
        success: false,
        error: `Unknown effect: ${effectType}`,
        available_effects: Object.keys(EFFECTS)
      });
    }

    const inputPath = req.file.path;
    const outputFilename = `${effectType}-${Date.now()}.mp3`;
    const outputPath = path.join(outputsDir, outputFilename);

    const effect = EFFECTS[effectType];
    console.log(`🎡 Processing: ${effect.name}`);
    console.log(`πŸ“ ${effect.description}`);
    console.log(`🎭 Moods: ${effect.instrumentMoods?.join(', ') || 'default'}`);

    let ffmpegCommand;
    let usedInstruments = [];

    if (addInstruments) {
      // 🎲 Smart selection - 2 instruments matching effect mood
      const selectedKeys = getSmartInstruments(effectType, 2);
      usedInstruments = selectedKeys.map(key => ({
        id: key,
        name: INSTRUMENTS[key].name,
        mood: INSTRUMENTS[key].mood
      }));

      console.log(`🎹 Instruments: ${usedInstruments.map(i => `${i.name} (${i.mood})`).join(', ')}`);

      // Generate instruments
      const inst1Path = path.join(outputsDir, `inst1-${Date.now()}.wav`);
      const inst2Path = path.join(outputsDir, `inst2-${Date.now()}.wav`);

      await execPromise(`ffmpeg -f lavfi -i "${INSTRUMENTS[selectedKeys[0]].command}" -t 12 -y "${inst1Path}"`);
      await execPromise(`ffmpeg -f lavfi -i "${INSTRUMENTS[selectedKeys[1]].command}" -t 12 -y "${inst2Path}"`);

      // Mix with smart volume
      const vol = effect.instrumentVolume;
      ffmpegCommand = `ffmpeg -i "${inputPath}" -stream_loop -1 -i "${inst1Path}" -stream_loop -1 -i "${inst2Path}" -filter_complex "[1]volume=${vol}[i1];[2]volume=${vol}[i2];[0][i1][i2]amix=inputs=3:duration=first:dropout_transition=2,${effect.baseCommand.replace('-af "', '').replace('"', '')}" -ar 44100 -b:a 192k -y "${outputPath}"`;

      // Cleanup
      setTimeout(() => {
        [inst1Path, inst2Path].forEach(p => {
          if (fs.existsSync(p)) fs.unlinkSync(p);
        });
      }, 5000);

    } else {
      ffmpegCommand = `ffmpeg -i "${inputPath}" -threads 0 ${effect.baseCommand} -ar 44100 -b:a 192k -y "${outputPath}"`;
    }

    console.log(`βš™οΈ Processing...`);

    const startTime = Date.now();
    await execPromise(ffmpegCommand, {
      maxBuffer: 50 * 1024 * 1024
    });
    const processingTime = ((Date.now() - startTime) / 1000).toFixed(2);

    fs.unlinkSync(inputPath);

    const stats = fs.statSync(outputPath);
    const fileSizeKB = (stats.size / 1024).toFixed(2);

    console.log(`βœ… Done: ${fileSizeKB}KB in ${processingTime}s`);

    res.json({
      success: true,
      message: `Processed with ${effect.name}`,
      downloadUrl: `/download/${outputFilename}`,
      filename: outputFilename,
      effect: {
        id: effectType,
        name: effect.name,
        description: effect.description,
        moods: effect.instrumentMoods || []
      },
      instruments: addInstruments ? usedInstruments : [],
      output: {
        size_kb: fileSizeKB
      },
      processing_time_seconds: processingTime
    });

  } catch (error) {
    console.error('❌ Error:', error);
    
    if (req.file && fs.existsSync(req.file.path)) {
      fs.unlinkSync(req.file.path);
    }

    res.status(500).json({
      success: false,
      error: 'Processing failed',
      details: error.message
    });
  }
});

// πŸ“₯ Download
app.get('/download/:filename', (req, res) => {
  const filename = req.params.filename;
  const filePath = path.join(outputsDir, filename);

  if (!fs.existsSync(filePath)) {
    return res.status(404).json({ 
      success: false,
      error: 'File not found'
    });
  }

  console.log(`πŸ“₯ Download: ${filename}`);

  res.download(filePath, filename, (err) => {
    if (!err) {
      setTimeout(() => {
        if (fs.existsSync(filePath)) {
          fs.unlinkSync(filePath);
          console.log(`πŸ—‘οΈ Cleaned: ${filename}`);
        }
      }, 10000);
    }
  });
});

// πŸŽ›οΈ Get Effects Info
app.get('/effects', (req, res) => {
  res.json({
    total: Object.keys(EFFECTS).length,
    effects: Object.keys(EFFECTS).map(key => ({
      id: key,
      name: EFFECTS[key].name,
      description: EFFECTS[key].description,
      moods: EFFECTS[key].instrumentMoods || []
    }))
  });
});

// 🎹 Get Instruments Info
app.get('/instruments', (req, res) => {
  const byMood = {};
  
  Object.keys(INSTRUMENTS).forEach(key => {
    const inst = INSTRUMENTS[key];
    if (!byMood[inst.mood]) {
      byMood[inst.mood] = [];
    }
    byMood[inst.mood].push({
      id: key,
      name: inst.name
    });
  });

  res.json({
    total: Object.keys(INSTRUMENTS).length,
    by_mood: byMood,
    all: Object.keys(INSTRUMENTS).map(key => ({
      id: key,
      name: INSTRUMENTS[key].name,
      mood: INSTRUMENTS[key].mood
    }))
  });
});

// πŸš€ Start Server
app.listen(PORT, '0.0.0.0', () => {
  console.log('═══════════════════════════════════════════════');
  console.log('πŸš€ LoFi Remix API v3.1 - SMART INSTRUMENTS');
  console.log('═══════════════════════════════════════════════');
  console.log(`πŸ“ Server: http://0.0.0.0:${PORT}`);
  console.log(`⚑ Effects: ${Object.keys(EFFECTS).length}`);
  console.log(`🎹 Instruments: ${Object.keys(INSTRUMENTS).length}`);
  console.log(`🎭 Moods: Sad, Romantic, Sad-Romantic, Ambient, Chill, Upbeat`);
  console.log(`🎲 Smart mood-based selection!`);
  console.log('═══════════════════════════════════════════════');
});