Implement complete search results + dual player UI
Backend Enhancements: - Add ParsedMIDIInfo with track analysis and quality issues - New /api/midi/parse endpoint for MIDI metadata extraction - Enhanced MIDIService with parseMIDI method MIDI Preview Player: - Complete MIDIPlayer class with polyphonic playback - Basic oscillator mapping (bass=square, mid=triangle, high=sine) - Lookahead scheduling with proper cleanup - Automatic stopping when MIDI ends New UI Flow: 1. Search → Results table with metadata 2. Select MIDI → Shows parsed info (duration, tracks, tempo) 3. Dual transport: Preview Original vs Generate Motif 4. Try Next Result button for easy A/B testing Search Results Table: - Title, source, confidence bar, duration, track count - Quality issues display (short duration, few notes, etc.) - Auto-select best result, manual selection available - Visual confidence bars and issue warnings This makes the project feel "real" - you can now: - See exactly what MIDI was found - Verify it's the right song via preview - Compare original vs procedural synthesis - Easily try different results 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,25 @@ interface MIDISearchResult {
|
||||
pageUrl: string;
|
||||
midiUrl: string;
|
||||
confidence: number;
|
||||
parsed?: ParsedMIDIInfo;
|
||||
}
|
||||
|
||||
interface ParsedMIDIInfo {
|
||||
durationSec: number;
|
||||
tempoBpm: number;
|
||||
timeSig?: { num: number; den: number };
|
||||
tracks: TrackInfo[];
|
||||
noteCount: number;
|
||||
issues: string[];
|
||||
}
|
||||
|
||||
interface TrackInfo {
|
||||
id: number;
|
||||
name?: string;
|
||||
program?: number;
|
||||
noteCount: number;
|
||||
channel?: number;
|
||||
register: 'low' | 'mid' | 'high';
|
||||
}
|
||||
|
||||
interface MIDISearchResponse {
|
||||
@@ -50,6 +69,21 @@ export class MIDIService {
|
||||
}
|
||||
}
|
||||
|
||||
async parseMIDI(url: string): Promise<ParsedMIDIInfo | null> {
|
||||
try {
|
||||
const response = await fetch(`${this.baseUrl}/api/midi/parse?u=${encodeURIComponent(url)}`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Parse failed: ${response.status}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('MIDI parse error:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async checkHealth(): Promise<boolean> {
|
||||
try {
|
||||
const response = await fetch(`${this.baseUrl}/health`);
|
||||
@@ -58,4 +92,5 @@ export class MIDIService {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user