// Shared JavaScript across all pages // Audio context for audio visualization let audioContext = null; // Initialize app document.addEventListener('DOMContentLoaded', function() { console.log('Algorithmic Harmony Maestro loaded'); // Check for audio context support if (window.AudioContext || window.webkitAudioContext) { audioContext = new (window.AudioContext || window.webkitAudioContext)(); } // Utility function for formatting time function formatTime(seconds) { const mins = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${mins}:${secs.toString().padStart(2, '0')}`; } // API integration functions class MusicAPI { static async generateTrack(prompt, metadata) { try { // Simulate API call to generative music service const response = await fetch('/api/generate', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ prompt: prompt, metadata: metadata, platform: 'suno' // or 'udio', 'mubert' }) }); if (!response.ok) throw new Error('Generation failed'); return await response.json(); } catch (error) { console.error('Generation error:', error); throw error; } } static async analyzeTrack(audioFile) { try { const formData = new FormData(); formData.append('audio', audioFile); const response = await fetch('/api/analyze', { method: 'POST', body: formData }); if (!response.ok) throw new Error('Analysis failed'); return await response.json(); } catch (error) { console.error('Analysis error:', error); throw error; } } static async getPlatformTags(genre, mood) { try { const response = await fetch(`/api/tags?genre=${genre}&mood=${mood}`); if (!response.ok) throw new Error('Tag fetch failed'); return await response.json(); } catch (error) { console.error('Tag fetch error:', error); return { spotify: ['Chill Vibes', 'Deep Focus'], soundcloud: [genre, mood, 'instrumental'] }; } } } // Local storage management class StorageManager { static saveProject(projectData) { const projects = this.getProjects(); projects.push({ id: Date.now().toString(), ...projectData, createdAt: new Date().toISOString() }); localStorage.setItem('music_projects', JSON.stringify(projects)); } static getProjects() { return JSON.parse(localStorage.getItem('music_projects') || '[]'); } static deleteProject(projectId) { const projects = this.getProjects().filter(p => p.id !== projectId); localStorage.setItem('music_projects', JSON.stringify(projects)); } } // Voice recognition class VoiceRecognition { constructor() { this.recognition = null; this.isListening = false; if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; this.recognition = new SpeechRecognition(); this.recognition.continuous = false; this.recognition.interimResults = false; } } startListening(onResult, onError) { if (!this.recognition) { onError('Voice recognition not supported in this browser'); return; } this.recognition.onresult = (event) => { const transcript = event.results[0][0].transcript; onResult(transcript); }; this.recognition.onerror = (event) => { onError(event.error); }; this.recognition.start(); this.isListening = true; } stopListening() { if (this.recognition && this.isListening) { this.recognition.stop(); this.isListening = false; } } } // Random prompt generator using configured AI API class RandomPromptGenerator { static async generateRandomPrompts() { const settings = JSON.parse(localStorage.getItem('ai_settings') || '{}'); const provider = settings.preferredProvider || 'deepseek'; if (provider === 'deepseek' && settings.deepseekApiKey) { try { const response = await fetch('https://api.deepseek.com/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${settings.deepseekApiKey}` }, body: JSON.stringify({ model: 'deepseek-chat', messages: [ { role: 'user', content: 'Generate 5 diverse and creative music track descriptions for AI music generation. Include different genres like electronic, pop, rock, hip-hop, and experimental styles. Format as a JSON array of strings.' } ], max_tokens: 500, temperature: 0.9 }) }); if (!response.ok) { throw new Error('Deepseek API request failed'); } const data = await response.json(); return JSON.parse(data.choices[0].message.content); } catch (error) { console.error('Deepseek prompt generation error:', error); // Fall through to OpenAI or fallback } } if (provider === 'openai' && settings.openaiApiKey) { try { const response = await fetch('https://api.openai.com/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${settings.openaiApiKey}` }, body: JSON.stringify({ model: settings.openaiModel || 'gpt-3.5-turbo', messages: [ { role: 'user', content: 'Generate 5 diverse and creative music track descriptions for AI music generation. Include different genres like electronic, pop, rock, hip-hop, and experimental styles. Format as a JSON array of strings.' } ], max_tokens: 500, temperature: 0.9 }) }); if (!response.ok) { throw new Error('OpenAI API request failed'); } const data = await response.json(); return JSON.parse(data.choices[0].message.content); } catch (error) { console.error('OpenAI prompt generation error:', error); // Fall through to fallback } } // Return fallback prompts if no API configured or both failed return [ "Dreamy synthwave with nostalgic 80s vibes and pulsating arpeggios, perfect for night driving', "Emotional piano ballad with heartfelt male vocals and string accompaniment, cinematic quality', "Hard-hitting trap beat with 808 bass and crisp hi-hats, perfect for urban radio play', "Ambient soundscape with field recordings and atmospheric pads, meditation and relaxation focus", "Funky disco track with groovy bassline and brass stabs, dance floor energy optimized', "Acoustic folk song with fingerpicking guitar and harmonizing vocals, campfire intimate feel" ]; } } // Export for use in other modules window.MusicAPI = MusicAPI; window.StorageManager = StorageManager; window.VoiceRecognition = VoiceRecognition; window.RandomPromptGenerator = RandomPromptGenerator;