NativeAngels's picture
Add 3 files
273eb2a verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Song Workout Assistant - Identify Keys & Chords by Ear</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.piano-key {
position: relative;
width: 40px;
height: 160px;
border: 1px solid #333;
border-radius: 0 0 5px 5px;
cursor: pointer;
user-select: none;
display: flex;
justify-content: center;
align-items: flex-end;
padding-bottom: 10px;
font-weight: bold;
transition: all 0.1s;
}
.white-key {
background-color: white;
color: #333;
z-index: 1;
}
.black-key {
width: 28px;
height: 100px;
background-color: #333;
color: white;
margin-left: -14px;
margin-right: -14px;
z-index: 2;
padding-bottom: 5px;
}
.white-key.active {
background-color: #e2e8f0;
box-shadow: inset 0 0 10px rgba(0,0,0,0.3);
}
.black-key.active {
background-color: #111;
box-shadow: inset 0 0 10px rgba(255,255,255,0.2);
}
.chord-box {
width: 60px;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 8px;
font-weight: bold;
transition: all 0.3s;
}
.key-indicator {
width: 120px;
height: 120px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
font-weight: bold;
margin: 0 auto;
transition: all 0.3s;
}
.note-badge {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border-radius: 50%;
margin: 2px;
font-weight: bold;
cursor: pointer;
}
.progression-step {
transition: all 0.3s;
transform: scale(1);
}
.progression-step.active {
transform: scale(1.1);
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.pulse {
animation: pulse 1.5s infinite;
}
</style>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-8">
<header class="text-center mb-12">
<h1 class="text-4xl font-bold text-indigo-800 mb-2">Song Workout Assistant</h1>
<p class="text-lg text-gray-600">Train your ear to identify song keys and chord progressions</p>
</header>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Left Column - Input Section -->
<div class="bg-white rounded-xl shadow-lg p-6">
<h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-music mr-2 text-indigo-600"></i> Note Input
</h2>
<div class="mb-6">
<h3 class="text-lg font-medium text-gray-700 mb-3">Piano Keyboard</h3>
<div class="flex justify-center mb-4">
<div class="flex relative" id="piano-keyboard">
<!-- C to B (one octave) -->
<div class="piano-key white-key" data-note="C">C</div>
<div class="piano-key black-key" data-note="C#">C#</div>
<div class="piano-key white-key" data-note="D">D</div>
<div class="piano-key black-key" data-note="D#">D#</div>
<div class="piano-key white-key" data-note="E">E</div>
<div class="piano-key white-key" data-note="F">F</div>
<div class="piano-key black-key" data-note="F#">F#</div>
<div class="piano-key white-key" data-note="G">G</div>
<div class="piano-key black-key" data-note="G#">G#</div>
<div class="piano-key white-key" data-note="A">A</div>
<div class="piano-key black-key" data-note="A#">A#</div>
<div class="piano-key white-key" data-note="B">B</div>
</div>
</div>
<div class="flex justify-center space-x-2 mb-4">
<button id="play-chord-btn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg flex items-center">
<i class="fas fa-play mr-2"></i> Play Chord
</button>
<button id="clear-notes-btn" class="bg-gray-200 hover:bg-gray-300 text-gray-800 px-4 py-2 rounded-lg flex items-center">
<i class="fas fa-trash-alt mr-2"></i> Clear
</button>
</div>
</div>
<div class="mb-6">
<h3 class="text-lg font-medium text-gray-700 mb-3">Selected Notes</h3>
<div id="selected-notes" class="flex flex-wrap min-h-12 bg-gray-50 rounded-lg p-3 border border-gray-200">
<p class="text-gray-400 italic">Click piano keys or buttons below to add notes</p>
</div>
<div class="grid grid-cols-7 gap-2 mt-3">
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="C">C</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="C#">C#</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="D">D</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="D#">D#</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="E">E</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="F">F</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="F#">F#</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="G">G</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="G#">G#</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="A">A</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="A#">A#</button>
<button class="note-btn bg-white border border-gray-300 rounded p-2 hover:bg-gray-100" data-note="B">B</button>
</div>
</div>
<div>
<h3 class="text-lg font-medium text-gray-700 mb-3">Chord Progression</h3>
<div id="chord-progression" class="flex flex-wrap gap-2 mb-3 min-h-16 bg-gray-50 rounded-lg p-3 border border-gray-200">
<p class="text-gray-400 italic">Add chords to build a progression</p>
</div>
<button id="analyze-progression-btn" class="w-full bg-green-600 hover:bg-green-700 text-white px-4 py-3 rounded-lg font-medium flex items-center justify-center">
<i class="fas fa-search mr-2"></i> Analyze Progression
</button>
</div>
</div>
<!-- Middle Column - Analysis Results -->
<div class="bg-white rounded-xl shadow-lg p-6">
<h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-chart-bar mr-2 text-indigo-600"></i> Analysis Results
</h2>
<div class="mb-8">
<h3 class="text-lg font-medium text-gray-700 mb-3">Detected Chord</h3>
<div id="chord-result" class="flex flex-col items-center justify-center p-6 bg-gray-50 rounded-lg border border-gray-200">
<div id="chord-name" class="text-4xl font-bold text-indigo-700 mb-2">-</div>
<div id="chord-notes" class="text-gray-600">No chord analyzed yet</div>
</div>
</div>
<div class="mb-8">
<h3 class="text-lg font-medium text-gray-700 mb-3">Possible Key</h3>
<div id="key-result" class="flex flex-col items-center justify-center p-6 bg-gray-50 rounded-lg border border-gray-200">
<div id="key-indicator" class="key-indicator bg-gray-200 text-gray-500 mb-3">
?
</div>
<div id="key-info" class="text-center">
<p class="text-gray-600">Play 3 or more notes to detect possible key</p>
<div id="key-chords" class="mt-3 hidden">
<p class="font-medium text-gray-700">Chords in this key:</p>
<div class="flex flex-wrap justify-center gap-1 mt-2" id="key-chords-list"></div>
</div>
</div>
</div>
</div>
<div>
<h3 class="text-lg font-medium text-gray-700 mb-3">Progression Analysis</h3>
<div id="progression-result" class="p-6 bg-gray-50 rounded-lg border border-gray-200">
<div id="likely-key" class="mb-4">
<p class="font-medium text-gray-700">Likely Key:</p>
<p id="progression-key" class="text-xl font-bold text-indigo-700 mt-1">-</p>
</div>
<div id="roman-analysis" class="mb-4">
<p class="font-medium text-gray-700">Roman Numeral Analysis:</p>
<div id="roman-numerals" class="flex flex-wrap gap-2 mt-2"></div>
</div>
<div id="common-progressions" class="hidden">
<p class="font-medium text-gray-700">Common Progressions:</p>
<div class="mt-2 space-y-2">
<div class="p-2 bg-blue-50 rounded border border-blue-100">
<p class="text-blue-800 font-medium">I - V - vi - IV</p>
<p class="text-sm text-blue-600">Popular in pop music (e.g., "Let It Be", "Someone Like You")</p>
</div>
<div class="p-2 bg-blue-50 rounded border border-blue-100">
<p class="text-blue-800 font-medium">ii - V - I</p>
<p class="text-sm text-blue-600">Jazz standard progression</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Right Column - Reference & Help -->
<div class="bg-white rounded-xl shadow-lg p-6">
<h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-book mr-2 text-indigo-600"></i> Music Theory Reference
</h2>
<div class="mb-8">
<h3 class="text-lg font-medium text-gray-700 mb-3">Chord Types</h3>
<div class="space-y-3">
<div class="p-3 bg-purple-50 rounded-lg border border-purple-100">
<p class="font-medium text-purple-800">Major (C)</p>
<p class="text-sm text-purple-600">Root, Major 3rd, Perfect 5th (C-E-G)</p>
</div>
<div class="p-3 bg-purple-50 rounded-lg border border-purple-100">
<p class="font-medium text-purple-800">Minor (Cm)</p>
<p class="text-sm text-purple-600">Root, Minor 3rd, Perfect 5th (C-E♭-G)</p>
</div>
<div class="p-3 bg-purple-50 rounded-lg border border-purple-100">
<p class="font-medium text-purple-800">Dominant 7th (C7)</p>
<p class="text-sm text-purple-600">Major triad + Minor 7th (C-E-G-B♭)</p>
</div>
</div>
</div>
<div class="mb-8">
<h3 class="text-lg font-medium text-gray-700 mb-3">Circle of Fifths</h3>
<div class="flex justify-center">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/33/Circle_of_fifths_deluxe_4.svg/1200px-Circle_of_fifths_deluxe_4.svg.png" alt="Circle of Fifths" class="w-full h-auto rounded-lg border border-gray-200">
</div>
</div>
<div>
<h3 class="text-lg font-medium text-gray-700 mb-3">How to Use</h3>
<div class="space-y-3">
<div class="flex items-start">
<div class="bg-indigo-100 text-indigo-800 rounded-full w-6 h-6 flex items-center justify-center mr-3 mt-1 flex-shrink-0">1</div>
<p class="text-gray-700">Play notes on the piano or click note buttons to build a chord</p>
</div>
<div class="flex items-start">
<div class="bg-indigo-100 text-indigo-800 rounded-full w-6 h-6 flex items-center justify-center mr-3 mt-1 flex-shrink-0">2</div>
<p class="text-gray-700">The app will analyze possible chords and keys</p>
</div>
<div class="flex items-start">
<div class="bg-indigo-100 text-indigo-800 rounded-full w-6 h-6 flex items-center justify-center mr-3 mt-1 flex-shrink-0">3</div>
<p class="text-gray-700">Build a chord progression by adding multiple chords</p>
</div>
<div class="flex items-start">
<div class="bg-indigo-100 text-indigo-800 rounded-full w-6 h-6 flex items-center justify-center mr-3 mt-1 flex-shrink-0">4</div>
<p class="text-gray-700">Analyze the progression to see likely keys and patterns</p>
</div>
</div>
<div class="mt-6 p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
<h4 class="font-medium text-yellow-800 mb-2 flex items-center">
<i class="fas fa-lightbulb mr-2"></i> Ear Training Tip
</h4>
<p class="text-yellow-700">Try to sing the root note of each chord to help identify the key. The note that feels most resolved is often the tonic (key note).</p>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Audio context for playing sounds
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
// Store selected notes and chords
let selectedNotes = [];
let chordProgression = [];
// Musical reference data
const noteFrequencies = {
'C': 261.63, 'C#': 277.18, 'D': 293.66, 'D#': 311.13,
'E': 329.63, 'F': 349.23, 'F#': 369.99, 'G': 392.00,
'G#': 415.30, 'A': 440.00, 'A#': 466.16, 'B': 493.88
};
const chordTypes = {
'major': [0, 4, 7],
'minor': [0, 3, 7],
'diminished': [0, 3, 6],
'augmented': [0, 4, 8],
'sus2': [0, 2, 7],
'sus4': [0, 5, 7],
'7': [0, 4, 7, 10],
'maj7': [0, 4, 7, 11],
'm7': [0, 3, 7, 10],
'm7b5': [0, 3, 6, 10]
};
const keySignatures = {
'C': ['C', 'Dm', 'Em', 'F', 'G', 'Am', 'Bdim'],
'G': ['G', 'Am', 'Bm', 'C', 'D', 'Em', 'F#dim'],
'D': ['D', 'Em', 'F#m', 'G', 'A', 'Bm', 'C#dim'],
'A': ['A', 'Bm', 'C#m', 'D', 'E', 'F#m', 'G#dim'],
'E': ['E', 'F#m', 'G#m', 'A', 'B', 'C#m', 'D#dim'],
'B': ['B', 'C#m', 'D#m', 'E', 'F#', 'G#m', 'A#dim'],
'F#': ['F#', 'G#m', 'A#m', 'B', 'C#', 'D#m', 'E#dim'],
'C#': ['C#', 'D#m', 'E#m', 'F#', 'G#', 'A#m', 'B#dim'],
'F': ['F', 'Gm', 'Am', 'Bb', 'C', 'Dm', 'Edim'],
'Bb': ['Bb', 'Cm', 'Dm', 'Eb', 'F', 'Gm', 'Adim'],
'Eb': ['Eb', 'Fm', 'Gm', 'Ab', 'Bb', 'Cm', 'Ddim'],
'Ab': ['Ab', 'Bbm', 'Cm', 'Db', 'Eb', 'Fm', 'Gdim'],
'Db': ['Db', 'Ebm', 'Fm', 'Gb', 'Ab', 'Bbm', 'Cdim'],
'Gb': ['Gb', 'Abm', 'Bbm', 'Cb', 'Db', 'Ebm', 'Fdim'],
'Cb': ['Cb', 'Dbm', 'Ebm', 'Fb', 'Gb', 'Abm', 'Bbdim'],
'Am': ['Am', 'Bdim', 'C', 'Dm', 'Em', 'F', 'G'],
'Em': ['Em', 'F#dim', 'G', 'Am', 'Bm', 'C', 'D'],
'Bm': ['Bm', 'C#dim', 'D', 'Em', 'F#m', 'G', 'A'],
'F#m': ['F#m', 'G#dim', 'A', 'Bm', 'C#m', 'D', 'E'],
'C#m': ['C#m', 'D#dim', 'E', 'F#m', 'G#m', 'A', 'B'],
'G#m': ['G#m', 'A#dim', 'B', 'C#m', 'D#m', 'E', 'F#'],
'D#m': ['D#m', 'E#dim', 'F#', 'G#m', 'A#m', 'B', 'C#'],
'A#m': ['A#m', 'B#dim', 'C#', 'D#m', 'E#m', 'F#', 'G#'],
'Dm': ['Dm', 'Edim', 'F', 'Gm', 'Am', 'Bb', 'C'],
'Gm': ['Gm', '
</html>