have a section in settings that the user can enter API for either deepseek or Chat gpt
cafe130
verified
| // 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; | |