MoodBeats: AI-Powered Music from Biosignals
Build Skills for the AI-Augmented Future
Why This Matters Now
Gen AI isn’t just changing music—it’s creating new opportunities at the intersection of tech and human experience. Master the skills that matter:
- A) Adaptive AI Design – Learn how to structure responsive, mood-adaptive music pipelines.
- B) Critical Evaluation of ML & LLM Outputs – Analyze emotion classification accuracy, relevance of music output, and model biases.
- C) Rapid Prototyping with Multi-Model Systems – Combine biosignal classifiers with music generation APIs to create seamless experiences.
The Challenge
Build a prototype that uses public biosignal datasets (like EEG, ECG, or mood tags) to classify emotion and generate dynamic music playlists using AI.
Focus Areas:
Data-Driven Design – Build on existing datasets, no wearables required.
Mood-to-Music Mapping – Explore how different biosignals can drive music selection.
User-Centered Utility – Could this work as a productivity tool? A calming aid? A creative experience?
Logistics
- Teams: 3–5 members (final teams formed via AIVIA™ Evaluations)
- Timeline: July 7–25 (free mentorship provided in this window)
- Deliverables: A working prototype + 5-minute demo presentation
- Awards Announced: August 4–8
Judging Criteria
Skill Mastery: Skill demonstration (A/B/C competencies)
Practical Utility: Would users actually find value in it?
Creativity: Did you approach biosignal-to-music mapping in an unexpected or compelling way?
Final judging rubric and prize tiers will be announced by the end of May
Mockup by Claude—full artifact here. React code available below.
import { useState } from 'react';
import { Music, Activity, Heart, Brain, BarChart2, Play, List, FileText, Zap, Settings, Bookmark, HelpCircle, User } from 'lucide-react';
const MoodBeatsDashboard = () => {
const [activeTab, setActiveTab] = useState('dashboard');
const [currentMood, setCurrentMood] = useState('calm');
const [playlistGenerated, setPlaylistGenerated] = useState(true);
// Sample data for visualizations
const moodData = [
{ time: '9:00', value: 0.2, mood: 'calm' },
{ time: '10:00', value: 0.3, mood: 'calm' },
{ time: '11:00', value: 0.7, mood: 'energetic' },
{ time: '12:00', value: 0.8, mood: 'energetic' },
{ time: '13:00', value: 0.5, mood: 'focused' },
{ time: '14:00', value: 0.4, mood: 'focused' },
{ time: '15:00', value: 0.2, mood: 'calm' },
];
const samplePlaylists = {
calm: [
{ title: 'Ocean Waves', duration: '3:45', intensity: 'low' },
{ title: 'Forest Ambience', duration: '4:21', intensity: 'low' },
{ title: 'Gentle Rain', duration: '5:12', intensity: 'medium' },
{ title: 'Meditation Flow', duration: '6:30', intensity: 'low' },
],
energetic: [
{ title: 'Upbeat Rhythm', duration: '2:55', intensity: 'high' },
{ title: 'Dance Vibes', duration: '3:15', intensity: 'high' },
{ title: 'Energy Flow', duration: '4:02', intensity: 'medium' },
{ title: 'Power Up', duration: '3:48', intensity: 'high' },
],
focused: [
{ title: 'Deep Focus', duration: '5:20', intensity: 'medium' },
{ title: 'Concentration', duration: '4:45', intensity: 'medium' },
{ title: 'Study Beat', duration: '3:30', intensity: 'medium' },
{ title: 'Flow State', duration: '6:15', intensity: 'low' },
]
};
const biosignalOptions = [
{ id: 'eeg', name: 'EEG (Brain Activity)', icon: <Brain size={18} /> },
{ id: 'ecg', name: 'ECG (Heart Rate)', icon: <Heart size={18} /> },
{ id: 'gsr', name: 'GSR (Skin Response)', icon: <Activity size={18} /> },
{ id: 'manual', name: 'Manual Selection', icon: <User size={18} /> }
];
const [activeBiosignal, setActiveBiosignal] = useState('eeg');
const handleGeneratePlaylist = () => {
// Simulate playlist generation
setPlaylistGenerated(true);
};
return (
<div className="flex flex-col h-screen bg-gradient-to-br from-indigo-900 to-purple-900">
{/* Header */}
<header className="bg-black bg-opacity-30 p-4 flex justify-between items-center">
<div className="flex items-center space-x-2">
<Music className="text-purple-400" size={32} />
<div>
<h1 className="text-white text-xl font-bold">MoodBeats</h1>
<p className="text-purple-200 text-xs">AI-Powered Music from Biosignals</p>
</div>
</div>
<div className="flex space-x-2">
<button className="bg-purple-600 hover:bg-purple-700 text-white px-4 py-1 rounded-full text-sm">
Sign In
</button>
<button className="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-1 rounded-full text-sm">
Sign Up
</button>
</div>
</header>
{/* Main Content */}
<div className="flex flex-1 overflow-hidden">
{/* Sidebar */}
<div className="w-64 bg-black bg-opacity-50 text-white p-4">
<div className="mb-6">
<h3 className="text-purple-300 uppercase text-xs font-bold mb-2">Main</h3>
<ul className="space-y-1">
<li>
<button
onClick={() => setActiveTab('dashboard')}
className={`flex items-center w-full p-2 rounded-lg ${activeTab === 'dashboard' ? 'bg-purple-700' : 'hover:bg-purple-800 hover:bg-opacity-50'}`}
>
<BarChart2 size={18} className="mr-2" />
<span>Dashboard</span>
</button>
</li>
<li>
<button
onClick={() => setActiveTab('playlists')}
className={`flex items-center w-full p-2 rounded-lg ${activeTab === 'playlists' ? 'bg-purple-700' : 'hover:bg-purple-800 hover:bg-opacity-50'}`}
>
<List size={18} className="mr-2" />
<span>My Playlists</span>
</button>
</li>
<li>
<button
onClick={() => setActiveTab('analysis')}
className={`flex items-center w-full p-2 rounded-lg ${activeTab === 'analysis' ? 'bg-purple-700' : 'hover:bg-purple-800 hover:bg-opacity-50'}`}
>
<Activity size={18} className="mr-2" />
<span>Mood Analysis</span>
</button>
</li>
</ul>
</div>
<div className="mb-6">
<h3 className="text-purple-300 uppercase text-xs font-bold mb-2">Biosignal Source</h3>
<ul className="space-y-1">
{biosignalOptions.map(option => (
<li key={option.id}>
<button
onClick={() => setActiveBiosignal(option.id)}
className={`flex items-center w-full p-2 rounded-lg ${activeBiosignal === option.id ? 'bg-indigo-700' : 'hover:bg-indigo-800 hover:bg-opacity-50'}`}
>
{option.icon}
<span className="ml-2">{option.name}</span>
</button>
</li>
))}
</ul>
</div>
<div>
<h3 className="text-purple-300 uppercase text-xs font-bold mb-2">Tools</h3>
<ul className="space-y-1">
<li>
<button className="flex items-center w-full p-2 rounded-lg hover:bg-purple-800 hover:bg-opacity-50">
<Settings size={18} className="mr-2" />
<span>Settings</span>
</button>
</li>
<li>
<button className="flex items-center w-full p-2 rounded-lg hover:bg-purple-800 hover:bg-opacity-50">
<HelpCircle size={18} className="mr-2" />
<span>Help</span>
</button>
</li>
</ul>
</div>
</div>
{/* Main Content Area */}
<div className="flex-1 overflow-auto">
{activeTab === 'dashboard' && (
<div className="p-6">
<h2 className="text-white text-2xl font-bold mb-6">Your Mood Dashboard</h2>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Current Mood Card */}
<div className="bg-black bg-opacity-40 rounded-xl p-6 backdrop-filter backdrop-blur-sm">
<div className="flex justify-between items-start">
<div>
<h3 className="text-purple-300 text-sm font-medium">Current Mood</h3>
<div className="flex items-baseline mt-1">
<h2 className="text-white text-3xl font-bold capitalize">{currentMood}</h2>
<span className="ml-2 text-indigo-300 text-sm">based on {activeBiosignal.toUpperCase()} data</span>
</div>
</div>
<div className={`w-12 h-12 rounded-full flex items-center justify-center ${
currentMood === 'calm' ? 'bg-blue-600' :
currentMood === 'energetic' ? 'bg-red-600' : 'bg-green-600'
}`}>
{currentMood === 'calm' ? <Brain size={24} /> :
currentMood === 'energetic' ? <Activity size={24} /> : <Brain size={24} />}
</div>
</div>
<div className="mt-4">
<div className="h-24 bg-gradient-to-r from-indigo-900 to-purple-900 rounded-lg relative overflow-hidden">
{/* Simplified mood visualization */}
<div className="absolute inset-0 flex items-end">
{moodData.map((data, index) => (
<div
key={index}
className={`w-1/7 mx-px ${
data.mood === 'calm' ? 'bg-blue-500' :
data.mood === 'energetic' ? 'bg-red-500' : 'bg-green-500'
}`}
style={{ height: `${data.value * 100}%` }}
/>
))}
</div>
{/* Time labels */}
<div className="absolute bottom-0 inset-x-0 flex justify-between px-2 pb-1">
{moodData.map((data, index) => (
<span key={index} className="text-white text-xs opacity-70">{data.time}</span>
))}
</div>
</div>
</div>
<div className="mt-4">
<button
onClick={handleGeneratePlaylist}
className="w-full bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 text-white py-3 px-4 rounded-lg font-medium flex items-center justify-center"
>
<Zap size={18} className="mr-2" />
Generate Mood-Based Playlist
</button>
</div>
</div>
{/* Current Playlist Card */}
<div className="bg-black bg-opacity-40 rounded-xl p-6 backdrop-filter backdrop-blur-sm">
<div className="flex justify-between items-center mb-4">
<h3 className="text-purple-300 text-sm font-medium">
{playlistGenerated ? 'Your Generated Playlist' : 'Playlist Will Appear Here'}
</h3>
<div className="text-indigo-300 text-xs">
{playlistGenerated ? 'Based on your current mood' : ''}
</div>
</div>
{playlistGenerated ? (
<div className="space-y-2 mt-2">
{samplePlaylists[currentMood].map((track, index) => (
<div key={index} className="bg-purple-900 bg-opacity-40 rounded-lg p-3 flex items-center">
<div className="w-8 h-8 bg-gradient-to-br from-indigo-500 to-purple-600 rounded-md flex items-center justify-center mr-3">
<Music size={16} className="text-white" />
</div>
<div className="flex-1">
<h4 className="text-white font-medium">{track.title}</h4>
<div className="flex items-center text-xs text-purple-300">
<span>{track.duration}</span>
<span className="mx-2">•</span>
<span className="capitalize">{track.intensity} intensity</span>
</div>
</div>
<button className="w-8 h-8 bg-purple-600 hover:bg-purple-700 rounded-full flex items-center justify-center">
<Play size={16} className="text-white ml-0.5" />
</button>
</div>
))}
<button className="w-full mt-4 border border-purple-500 text-purple-300 hover:bg-purple-900 hover:bg-opacity-30 py-2 px-4 rounded-lg font-medium flex items-center justify-center">
<Bookmark size={18} className="mr-2" />
Save This Playlist
</button>
</div>
) : (
<div className="h-64 flex items-center justify-center">
<div className="text-center">
<Music size={48} className="text-purple-500 mx-auto mb-3 opacity-50" />
<p className="text-purple-300">Generate a playlist based on your mood</p>
</div>
</div>
)}
</div>
</div>
{/* Bottom Section - Mood-Music Mapping */}
<div className="mt-6 bg-black bg-opacity-40 rounded-xl p-6 backdrop-filter backdrop-blur-sm">
<h3 className="text-purple-300 text-sm font-medium mb-4">Mood-to-Music Mapping</h3>
<div className="grid grid-cols-3 gap-4">
<div className="bg-blue-900 bg-opacity-30 p-4 rounded-lg">
<div className="flex items-center mb-2">
<div className="w-8 h-8 bg-blue-600 rounded-full flex items-center justify-center mr-2">
<Brain size={18} className="text-white" />
</div>
<h4 className="text-white font-medium">Calm</h4>
</div>
<p className="text-blue-200 text-sm">Slow tempo, ambient sounds, gentle melodies with minimal percussion</p>
</div>
<div className="bg-red-900 bg-opacity-30 p-4 rounded-lg">
<div className="flex items-center mb-2">
<div className="w-8 h-8 bg-red-600 rounded-full flex items-center justify-center mr-2">
<Activity size={18} className="text-white" />
</div>
<h4 className="text-white font-medium">Energetic</h4>
</div>
<p className="text-red-200 text-sm">Upbeat tempo, strong rhythms, dynamic range with energizing progression</p>
</div>
<div className="bg-green-900 bg-opacity-30 p-4 rounded-lg">
<div className="flex items-center mb-2">
<div className="w-8 h-8 bg-green-600 rounded-full flex items-center justify-center mr-2">
<Brain size={18} className="text-white" />
</div>
<h4 className="text-white font-medium">Focused</h4>
</div>
<p className="text-green-200 text-sm">Medium tempo, consistent patterns, minimal vocals with harmonic stability</p>
</div>
</div>
</div>
</div>
)}
{activeTab === 'playlists' && (
<div className="p-6">
<h2 className="text-white text-2xl font-bold mb-6">Your Saved Playlists</h2>
{/* Playlists content would go here */}
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
{['Morning Focus', 'Afternoon Energy', 'Evening Calm', 'Deep Work'].map((name, index) => (
<div key={index} className="bg-black bg-opacity-40 rounded-xl p-4 backdrop-filter backdrop-blur-sm">
<div className="aspect-square bg-gradient-to-br from-indigo-600 to-purple-700 rounded-lg mb-3 flex items-center justify-center">
<Music size={64} className="text-white opacity-50" />
</div>
<h3 className="text-white font-medium">{name}</h3>
<p className="text-purple-300 text-sm">Generated on April 15, 2025</p>
</div>
))}
</div>
</div>
)}
{activeTab === 'analysis' && (
<div className="p-6">
<h2 className="text-white text-2xl font-bold mb-6">Mood Analysis</h2>
{/* Analysis content would go here */}
<div className="bg-black bg-opacity-40 rounded-xl p-6 backdrop-filter backdrop-blur-sm">
<h3 className="text-purple-300 text-sm font-medium mb-4">Weekly Mood Patterns</h3>
<div className="h-64 bg-purple-900 bg-opacity-30 rounded-lg flex items-center justify-center">
<p className="text-purple-300">Mood analysis visualization would appear here</p>
</div>
</div>
</div>
)}
</div>
</div>
{/* Footer */}
<footer className="bg-black bg-opacity-70 text-purple-300 p-3 text-center text-xs">
<p>© 2025 MoodBeats - AI-Powered Music from Biosignals | Hackathon Project</p>
</footer>
</div>
);
};
export default MoodBeatsDashboard;