Midi Clef Karaoke Player Instant
.clef-indicator font-size: 18px; font-weight: bold; margin-bottom: 10px; text-align: center; color: #ffd700; </style> </head> <body> <div class="container"> <div class="player"> <div class="controls"> <input type="file" id="midiFileInput" accept=".mid,.midi"> <button id="playBtn">▶ Play</button> <button id="pauseBtn">⏸ Pause</button> <button id="stopBtn">⏹ Stop</button> </div> <div class="clef-indicator" id="clefIndicator">Clef: --</div> <div class="staff-container"> <canvas id="staffCanvas" width="900" height="300"></canvas> </div> <div class="lyrics" id="lyricsDisplay">🎵 Load a MIDI file to start 🎵</div> <div class="info"> 🎹 Supports karaoke MIDI files with lyrics | Clef auto-detected | Scrolling notes </div> </div> </div>
parseMIDIData() this.notes = []; this.lyrics = []; this.midiData.tracks.forEach((track, trackIndex) => let currentTime = 0; let currentLyric = ''; track.forEach(event => ); ); // Sort notes by start time this.notes.sort((a, b) => a.startTime - b.startTime); this.lyrics.sort((a, b) => a.time - b.time); console.log(`Loaded $this.notes.length notes, $this.lyrics.length lyrics`);
button:active transform: translateY(0);
initEventListeners() document.getElementById('midiFileInput').addEventListener('change', (e) => this.loadMIDI(e)); document.getElementById('playBtn').addEventListener('click', () => this.play()); document.getElementById('pauseBtn').addEventListener('click', () => this.pause()); document.getElementById('stopBtn').addEventListener('click', () => this.stop()); midi clef karaoke player
updateLyrics() const currentTime = this.isPlaying ? (performance.now() - this.startTime) / 1000 : this.currentPauseTime; const currentLyric = this.lyrics.filter(l => l.time <= currentTime).pop(); if (currentLyric) document.getElementById('lyricsDisplay').innerHTML = `🎤 $currentLyric.text 🎤`;
.player background: #0f0f1a; border-radius: 20px; padding: 20px; box-shadow: inset 0 1px 3px rgba(255,255,255,0.1), 0 10px 20px rgba(0,0,0,0.5);
<script src="https://cdn.jsdelivr.net/npm/midijs@0.2.1/build/MIDI.js"></script> <script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script> <script> // Main implementation class MIDIClefKaraokePlayer constructor() this.midiData = null; this.audioContext = null; this.isPlaying = false; this.startTime = 0; this.currentPauseTime = 0; this.notes = []; this.lyrics = []; this.clef = 'treble'; // treble or bass this.canvas = document.getElementById('staffCanvas'); this.ctx = this.canvas.getContext('2d'); this.animationId = null; this.scrollOffset = 0; .clef-indicator font-size: 18px
.staff-container background: #fff9e8; border-radius: 15px; padding: 20px; margin-bottom: 20px; overflow-x: auto; position: relative; box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
const arrayBuffer = await file.arrayBuffer(); this.midiData = new MIDI.File(arrayBuffer); this.parseMIDIData(); this.detectClef(); this.drawStaff(); document.getElementById('lyricsDisplay').innerHTML = '🎤 Ready to play 🎤';
.container background: rgba(255,255,255,0.1); backdrop-filter: blur(10px); border-radius: 30px; padding: 25px; box-shadow: 0 20px 40px rgba(0,0,0,0.3); border: 1px solid rgba(255,255,255,0.2); input type="file" id="midiFileInput" accept=".mid
playMIDINotes() let currentIndex = 0; const scheduleNotes = () => if (!this.isPlaying) return; const now = (performance.now() - this.startTime) / 1000; while (currentIndex < this.notes.length && this.notes[currentIndex].startTime <= now + 0.1) const note = this.notes[currentIndex]; const midiNote = note.pitch; const velocity = note.velocity / 127; const duration = note.duration; MIDI.noteOn(0, midiNote, velocity, 0); MIDI.noteOff(0, midiNote, duration); currentIndex++; requestAnimationFrame(scheduleNotes); ; scheduleNotes();
.controls display: flex; gap: 15px; margin-bottom: 20px; flex-wrap: wrap; justify-content: center;
async initAudio() window.webkitAudioContext)(); await MIDI.loadPlugin( soundfontUrl: "https://cdn.jsdelivr.net/npm/midijs-soundfonts@1.0.0/FluidR3_GM/", instrument: "acoustic_grand_piano", onprogress: (state, progress) => console.log('Loading soundfont:', progress), onsuccess: () => console.log('Soundfont loaded') );