evaluate this app code: <script type="module">
        import * as Tone from 'https://cdn.skypack.dev/tone@14.7.77';
        import { Midi } from 'https://esm.sh/@tonejs/midi@2.0.28';

        const TRACK_INSTRUMENTS = {
            bassline: {
                type: 'bass',
                settings: {
                    oscillator: { type: 'triangle' },
                    envelope: {
                        attack: 0.05,
                        decay: 0.2,
                        sustain: 0.8,
                        release: 1
                    },
                    filter: {
                        Q: 2,
                        type: 'lowpass',
                        rolloff: -24
                    }
                }
            },
            melody: {
                type: 'piano',
                settings: {
                    oscillator: { type: 'triangle' },
                    envelope: {
                        attack: 0.02,
                        decay: 0.1,
                        sustain: 0.3,
                        release: 0.8
                    }
                }
            },
            chord: {
                type: 'pad',
                settings: {
                    oscillator: { type: 'sine' },
                    envelope: {
                        attack: 0.1,
                        decay: 0.2,
                        sustain: 0.5,
                        release: 1.5
                    }
                }
            },
            arpeggio: {
                type: 'synth',
                settings: {
                    oscillator: { type: 'sawtooth' },
                    envelope: {
                        attack: 0.01,
                        decay: 0.1,
                        sustain: 0.2,
                        release: 0.4
                    }
                }
            },
            mixed: {
                type: 'multi',
                settings: {
                    bass: {
                        type: 'bass',
                        settings: {
                            oscillator: { type: 'triangle' },
                            envelope: {
                                attack: 0.05,
                                decay: 0.2,
                                sustain: 0.8,
                                release: 1
                            },
                            filter: {
                                Q: 2,
                                type: 'lowpass',
                                rolloff: -24
                            }
                        }
                    },
                    melody: {
                        type: 'piano',
                        settings: {
                            oscillator: { type: 'triangle' },
                            envelope: {
                                attack: 0.02,
                                decay: 0.1,
                                sustain: 0.3,
                                release: 0.8
                            }
                        }
                    },
                    chord: {
                        type: 'pad',
                        settings: {
                            oscillator: { type: 'sine' },
                            envelope: {
                                attack: 0.1,
                                decay: 0.2,
                                sustain: 0.5,
                                release: 1.5
                            }
                        }
                    },
                    arpeggio: {
                        type: 'synth',
                        settings: {
                            oscillator: { type: 'sawtooth' },
                            envelope: {
                                attack: 0.01,
                                decay: 0.1,
                                sustain: 0.2,
                                release: 0.4
                            }
                        }
                    }
                }
            }
        };

        class AudioEngine {
            constructor() {
                this.initializeEngine();
            }

            initializeEngine() {
                this.instruments = new Map();
                this.isPlaying = false;
                this.loop = null;
                this.transportListener = null;

                Object.entries(TRACK_INSTRUMENTS).forEach(([trackType, config]) => {
                    let instrument;
                    switch(config.type) {
                        case 'bass':
                            instrument = new Tone.Synth(config.settings).toDestination();
                            instrument.volume.value = -6;
                            break;
                        case 'piano':
                            instrument = new Tone.PolySynth(Tone.Synth, {
                                ...config.settings,
                                polyphony: 8
                            }).toDestination();
                            break;
                        case 'pad':
                            instrument = new Tone.PolySynth(Tone.Synth, {
                                ...config.settings,
                                polyphony: 6
                            }).toDestination();
                            break;
                        case 'synth':
                            instrument = new Tone.PolySynth(Tone.Synth, {
                                ...config.settings,
                                polyphony: 4
                            }).toDestination();
                            break;
                    }
                    this.instruments.set(trackType, instrument);
                });

                this.transportListener = () => {
                    this.isPlaying = false;
                };
                Tone.Transport.on('stop', this.transportListener);
            }

            dispose() {
                if (this.loop) {
                    this.loop.dispose();
                    this.loop = null;
                }
                
                if (this.transportListener) {
                    Tone.Transport.off('stop', this.transportListener);
                    this.transportListener = null;
                }

                this.instruments.forEach(instrument => {
                    if (instrument) {
                        instrument.dispose();
                    }
                });
                this.instruments.clear();

                Tone.Transport.stop();
                this.isPlaying = false;
            }

            async start() {
                await Tone.start();
                Tone.Transport.start();
                this.isPlaying = true;
            }

            stop() {
                try {
                    if (this.loop) {
                        this.loop.dispose();
                        this.loop = null;
                    }

                    if (Tone.Transport.state !== 'stopped') {
                        Tone.Transport.stop();
                    }

                    this.instruments.forEach((instrument, type) => {
                        try {
                            if (instrument && typeof instrument.releaseAll === 'function') {
                                instrument.releaseAll();
                            }
                        } catch (err) {
                            console.warn(`Failed to release instrument ${type}:`, err);
                        }
                    });
                    
                    this.isPlaying = false;
                } catch (error) {
                    console.error('Error stopping playback:', error);
                    this.isPlaying = false;
                }
            }

            playNotes(notes, now, trackType = 'melody') {
                if (trackType === 'mixed') {
                    const bassNotes = notes.filter(note => 
                        Tone.Frequency(note.name).toMidi() < 48
                    );
                    const chordNotes = notes.filter(note => 
                        Tone.Frequency(note.name).toMidi() >= 48 && 
                        Tone.Frequency(note.name).toMidi() < 60
                    );
                    const melodyNotes = notes.filter(note => 
                        Tone.Frequency(note.name).toMidi() >= 60 && 
                        Tone.Frequency(note.name).toMidi() < 72
                    );
                    const arpeggioNotes = notes.filter(note => 
                        Tone.Frequency(note.name).toMidi() >= 72
                    );

                    if (bassNotes.length) this.playNotes(bassNotes, now, 'bassline');
                    if (chordNotes.length) this.playNotes(chordNotes, now, 'chord');
                    if (melodyNotes.length) this.playNotes(melodyNotes, now, 'melody');
                    if (arpeggioNotes.length) this.playNotes(arpeggioNotes, now, 'arpeggio');
                    return;
                }

                const instrument = this.instruments.get(trackType);
                if (!instrument) return;

                const totalDuration = Math.max(...notes.map(note => note.time + note.duration));
                const playMode = document.getElementById('play-mode').value;
                
                if (playMode === 'single') {
                    notes.forEach(note => {
                        instrument.triggerAttackRelease(
                            note.name,
                            note.duration,
                            now + note.time,
                            note.velocity
                        );
                    });

                    // Stop after single playthrough
                    setTimeout(() => {
                        this.stop();
                    }, totalDuration * 1000 + 100);
                } else {
                    // Loop mode
                    this.loop = new Tone.Loop((time) => {
                        notes.forEach(note => {
                            instrument.triggerAttackRelease(
                                note.name,
                                note.duration,
                                time + note.time,
                                note.velocity
                            );
                        });
                    }, totalDuration).start(0);
                }
            }
        }

        class UIManager {
            constructor() {
                this.statusContainer = document.getElementById('status-container');
                this.activeTimeout = null;
            }

            showMessage(message, type = 'info') {
                if (this.activeTimeout) {
                    clearTimeout(this.activeTimeout);
                    this.activeTimeout = null;
                }

                const messageDiv = document.createElement('div');
                messageDiv.className = `status-message ${type}-message`;
                messageDiv.textContent = message;
                
                this.statusContainer.innerHTML = '';
                this.statusContainer.appendChild(messageDiv);

                if (type !== 'loading') {
                    this.activeTimeout = setTimeout(() => {
                        messageDiv.remove();
                        this.activeTimeout = null;
                    }, 5000);
                }
            }

            showLoading() {
                this.showMessage('Generating MIDI...', 'loading');
            }

            hideLoading() {
                const loadingMessage = this.statusContainer.querySelector('.loading-message');
                if (loadingMessage) {
                    loadingMessage.remove();
                }
            }

            updateButtonStates(enabled) {
                const playButton = document.getElementById('play');
                const stopButton = document.getElementById('stop');
                const downloadButton = document.getElementById('download');

                if (playButton) playButton.disabled = !enabled;
                if (stopButton) stopButton.disabled = !enabled;
                if (downloadButton) downloadButton.disabled = !enabled;
            }

            dispose() {
                if (this.activeTimeout) {
                    clearTimeout(this.activeTimeout);
                    this.activeTimeout = null;
                }
                if (this.statusContainer) {
                    this.statusContainer.innerHTML = '';
                }
            }
        }

        class MIDIGenerator {
            constructor() {
                this.currentMidi = null;
                this.audioEngine = new AudioEngine();
                this.ui = new UIManager();
                this.messageTimeouts = new Set();
                this.boundEventListeners = new Map();
                this.visualizerInterval = null;
                
                this.boundHandleGenerate = this.handleGenerate.bind(this);
                this.boundHandlePlay = this.handlePlay.bind(this);
                this.boundHandleStop = this.handleStop.bind(this);
                this.boundHandleDownload = this.handleDownload.bind(this);
                this.boundHandleReset = this.handleReset.bind(this);
                
                this.initializeEventListeners();
                this.setupPageLifecycle();
            }

            initializeEventListeners() {
                this.boundEventListeners.set('generate', ['click', this.boundHandleGenerate]);
                this.boundEventListeners.set('play', ['click', this.boundHandlePlay]);
                this.boundEventListeners.set('stop', ['click', this.boundHandleStop]);
                this.boundEventListeners.set('download', ['click', this.boundHandleDownload]);
                this.boundEventListeners.set('reset', ['click', this.boundHandleReset]);
                
                this.boundEventListeners.forEach((value, key) => {
                    document.getElementById(key)?.addEventListener(value[0], value[1]);
                });
            }

            setupPageLifecycle() {
                window.addEventListener('beforeunload', () => this.cleanup());
                document.addEventListener('visibilitychange', () => {
                    if (document.hidden) {
                        this.handleStop();
                    }
                });
            }

            cleanup() {
                this.messageTimeouts.forEach(timeout => clearTimeout(timeout));
                this.messageTimeouts.clear();

                this.boundEventListeners.forEach((value, key) => {
                    document.getElementById(key)?.removeEventListener(value[0], value[1]);
                });
                this.boundEventListeners.clear();

                if (this.visualizerInterval) {
                    clearInterval(this.visualizerInterval);
                    this.visualizerInterval = null;
                }

                this.audioEngine.dispose();

                const visualizer = document.getElementById('visualizer');
                if (visualizer) {
                    visualizer.innerHTML = '';
                }

                this.currentMidi = null;
            }

            async generateMIDIFromAPI(prompt) {
                try {
                    const url = `https://text.pollinations.ai/generate/${encodeURIComponent(prompt)}?model=midijourney`;

                    console.log('Requesting URL:', url);

                    const response = await fetch(url);
                    if (!response.ok) {
                        throw new Error(`Server error: ${response.status} ${response.statusText}`);
                    }

                    const text = await response.text();
                    console.log('Raw API response:', text);

                    let title = '';
                    const titleMatch = text.match(/title:\s*(.+)/);
                    if (titleMatch) {
                        title = titleMatch[1].trim();
                    }

                    const lines = text.split('\n');
                    let notationData = [];
                    let isNotation = false;

                    for (let line of lines) {
                        if (line.includes('notation: |-')) {
                            isNotation = true;
                            continue;
                        }
                        if (isNotation && line.trim()) {
                            if (!line.includes('pitch,')) {
                                notationData.push(line.trim());
                            }
                        }
                    }

                    if (notationData.length === 0) {
                        throw new Error('No valid notation data found in response');
                    }

                    const notes = notationData.map(line => {
                        try {
                            const parts = line.split(',').map(val => parseFloat(val.trim()));
                            if (parts.length >= 4) {
                                const pitch = parts[0];
                                const time = parts[1];
                                const duration = parts[2];
                                const velocity = parts[3];
                                
                                if (!isNaN(pitch) && !isNaN(time) && !isNaN(duration) && !isNaN(velocity)) {
                                    const noteName = Tone.Frequency(pitch, "midi").toNote();
                                    console.log(`Parsed note: ${noteName} at time ${time}`);
                                    return {
                                        name: noteName,
                                        time: time,
                                        duration: duration,
                                        velocity: velocity / 127
                                    };
                                }
                            }
                            console.warn('Invalid note data:', line);
                            return null;
                        } catch (err) {
                            console.error('Error parsing note:', err);
                            return null;
                        }
                    }).filter(note => note !== null);

                    if (notes.length === 0) {
                        throw new Error('Failed to parse any valid notes from notation');
                    }

                    console.log('Parsed notes:', notes);
                    const midi = this.createMIDI(notes);
                    midi.header.name = title;
                    
                    if (title) {
                        this.ui.showMessage(`Generated "${title}"`, 'success');
                    }

                    return midi;
                } catch (error) {
                    console.error('API Error:', error);
                    throw error;
                }
            }

            createMIDI(notes) {
                const midi = new Midi();

                const track = midi.addTrack();

                const bpm = document.getElementById('bpm').value || 120;
                midi.header.setTempo(bpm);

                notes.forEach(note => {
                    track.addNote({
                        name: note.name,
                        time: note.time,
                        duration: note.duration,
                        velocity: note.velocity
                    });
                });

                return midi;
            }

            constructPrompt() {
                const trackType = document.getElementById('track-type').value;
                const style = document.getElementById('style').value || 'house';
                const mood = document.getElementById('mood').value;
                const key = document.getElementById('key').value;
                const timeSignature = document.getElementById('time-signature').value;
                const scaleType = document.getElementById('scale-type').value;
                const bpm = document.getElementById('bpm').value;
                const duration = document.getElementById('duration').value;

                const rhythmicComplexity = document.getElementById('rhythmic-complexity').value;
                const syncopation = document.getElementById('syncopation').value;

                return `${trackType} in the style of ${style}, ${mood} mood, in key ${key} using ${scaleType} scale with ${timeSignature} time signature at ${bpm} BPM for ${duration} bars. ${rhythmicComplexity} rhythmic complexity, and ${syncopation} syncopation.`;
            }

            visualizeMIDI() {
                const visualizer = document.getElementById('visualizer');
                visualizer.innerHTML = '';
                
                if (!this.currentMidi) return;
                
                const staffContainer = document.createElement('div');
                staffContainer.className = 'staff-container';
                
                for (let i = 0; i < 5; i++) {
                    const staffLine = document.createElement('div');
                    staffLine.className = 'staff-line';
                    staffLine.style.top = `${20 + i * 20}px`;
                    staffContainer.appendChild(staffLine);
                }
                
                const playhead = document.createElement('div');
                playhead.className = 'playhead';
                playhead.style.left = '0px';
                staffContainer.appendChild(playhead);
                
                const track = this.currentMidi.tracks[0];
                if (!track) return;
                
                const maxTime = Math.max(...track.notes.map(n => n.time + n.duration));
                const timeScale = (visualizer.clientWidth - 40) / maxTime;
                
                const pitches = track.notes.map(n => n.midi);
                const minPitch = Math.min(...pitches);
                const maxPitch = Math.max(...pitches);
                const pitchRange = maxPitch - minPitch;
                const pitchScale = (visualizer.clientHeight - 40) / pitchRange;
                
                track.notes.forEach(note => {
                    const noteEl = document.createElement('div');
                    noteEl.className = 'note';
                    noteEl.style.left = `${note.time * timeScale + 20}px`;
                    noteEl.style.width = `${Math.max(20, note.duration * timeScale)}px`;
                    noteEl.style.top = `${visualizer.clientHeight - ((note.midi - minPitch) * pitchScale) - 28}px`;
                    
                    const opacity = 0.4 + (note.velocity * 0.6);
                    const hue = (note.midi % 12) * 30;
                    noteEl.style.background = `linear-gradient(to right, 
                        hsla(${hue}, 70%, 60%, ${opacity}),
                        hsla(${hue + 30}, 70%, 60%, ${opacity}))`;
                    
                    noteEl.title = `Note: ${note.name}
Duration: ${note.duration.toFixed(2)}s
Velocity: ${Math.round(note.velocity * 100)}%
Time: ${note.time.toFixed(2)}s`;

                    noteEl.addEventListener('click', () => {
                        const instrument = this.audioEngine.instruments.get(
                            document.getElementById('track-type').value
                        );
                        if (instrument) {
                            instrument.triggerAttackRelease(note.name, note.duration, undefined, note.velocity);
                        }
                    });

                    noteEl.setAttribute('data-time', note.time);
                    noteEl.setAttribute('data-duration', note.duration);
                    noteEl.setAttribute('data-velocity', note.velocity);
                    noteEl.setAttribute('data-note', note.name);

                    staffContainer.appendChild(noteEl);
                });

                const beatsPerBar = parseInt(document.getElementById('time-signature').value);
                const bpm = parseInt(document.getElementById('bpm').value);
                const beatDuration = 60 / bpm;
                const totalBeats = Math.ceil(maxTime / beatDuration);

                for (let i = 0; i < totalBeats; i++) {
                    const beatMarker = document.createElement('div');
                    beatMarker.className = 'staff-line';
                    beatMarker.style.left = `${(i * beatDuration * timeScale) + 20}px`;
                    beatMarker.style.width = '1px';
                    beatMarker.style.height = '100%';
                    beatMarker.style.background = i % beatsPerBar === 0 ? 
                        'rgba(0, 255, 157, 0.3)' : 
                        'rgba(0, 255, 157, 0.1)';
                    staffContainer.appendChild(beatMarker);
                }

                visualizer.appendChild(staffContainer);
                this.setupPlaybackSync(staffContainer, timeScale);
            }

            setupPlaybackSync(container, timeScale) {
                if (this.visualizerInterval) {
                    clearInterval(this.visualizerInterval);
                }

                const playhead = container.querySelector('.playhead');
                const notes = container.querySelectorAll('.note');
                
                this.visualizerInterval = Tone.Transport.scheduleRepeat((time) => {
                    const currentTime = Tone.Transport.seconds;
                    if (playhead) {
                        playhead.style.left = `${(currentTime * timeScale) + 20}px`;
                    }
                    
                    notes.forEach(note => {
                        const noteTime = parseFloat(note.getAttribute('data-time'));
                        const noteDuration = parseFloat(note.getAttribute('data-duration'));
                        
                        if (currentTime >= noteTime && currentTime <= noteTime + noteDuration) {
                            note.classList.add('active');
                        } else {
                            note.classList.remove('active');
                        }
                    });
                }, 0.05);
            }

            async handleGenerate() {
                this.ui.showLoading();
                
                try {
                    const prompt = this.constructPrompt();
                    console.log('Sending prompt:', prompt);

                    this.currentMidi = await this.generateMIDIFromAPI(prompt);
                    
                    if (!this.currentMidi) {
                        throw new Error('Failed to generate MIDI data');
                    }
                    
                    if (!this.currentMidi.tracks || !this.currentMidi.tracks[0] || !this.currentMidi.tracks[0].notes.length) {
                        throw new Error('Generated MIDI contains no notes');
                    }
                    
                    this.visualizeMIDI();
                    this.ui.updateButtonStates(true);
                    this.ui.showMessage('MIDI generated successfully!', 'success');
                    
                } catch (error) {
                    console.error('Generation Error:', error);
                    this.ui.showMessage(`Generation failed: ${error.message}`, 'error');
                    this.currentMidi = null;
                    this.ui.updateButtonStates(false);
                } finally {
                    this.ui.hideLoading();
                }
            }

            async handlePlay() {
                if (!this.currentMidi || this.audioEngine.isPlaying) return;
                
                try {
                    await this.audioEngine.start();
                    const notes = this.currentMidi.tracks[0].notes;
                    const trackType = document.getElementById('track-type').value;
                    const playMode = document.getElementById('play-mode').value;
                    
                    this.audioEngine.playNotes(notes, Tone.now(), trackType);
                    this.ui.showMessage(
                        `Playing ${trackType} (${playMode === 'loop' ? 'Loop' : 'Single'} Mode)...`, 
                        'success'
                    );
                } catch (error) {
                    console.error('Playback Error:', error);
                    this.ui.showMessage('Playback failed', 'error');
                    this.handleStop();
                }
            }

            handleStop() {
                this.audioEngine.stop();
                const playhead = document.querySelector('.playhead');
                if (playhead) playhead.style.left = '0px';
                document.querySelectorAll('.note').forEach(note => note.classList.remove('active'));
                this.ui.showMessage('Playback stopped', 'info');
            }

            handleDownload() {
                if (!this.currentMidi) return;

                let filename = this.currentMidi.header.name;
                if (!filename) {
                    const trackType = document.getElementById('track-type').value;
                    const style = document.getElementById('style').value || 'default';
                    const key = document.getElementById('key').value;
                    const bpm = document.getElementById('bpm').value;
                    filename = `${trackType}-${style}-${key}-${bpm}bpm`;
                }

                filename = filename.toLowerCase()
                    .replace(/[^a-z0-9-]/g, '-')
                    .replace(/-+/g, '-')
                    + '.mid';

                const midiData = this.currentMidi.toArray();
                const blob = new Blob([midiData], { type: 'audio/midi' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = filename;
                a.click();
                URL.revokeObjectURL(url);
            }

            handleReset() {
                this.handleStop();
                this.currentMidi = null;
                this.ui.updateButtonStates(false);
                const visualizer = document.getElementById('visualizer');
                visualizer.innerHTML = '';
                
                document.getElementById('track-type').value = 'bassline';
                document.getElementById('style').value = '';
                document.getElementById('mood').value = 'uplifting';
                document.getElementById('key').value = 'C';
                document.getElementById('time-signature').value = '4/4';
                document.getElementById('scale-type').value = 'major';
                document.getElementById('bpm').value = '120';
                document.getElementById('duration').value = '4';
                
                this.ui.statusContainer.innerHTML = '';
                this.ui.showMessage('Application reset to default settings', 'success');
            }
        }

        document.addEventListener('DOMContentLoaded', () => {
            window.midiGenerator = new MIDIGenerator();
        });
    </script>