Continuator / working_interaction.py
pachet's picture
trying end phrase detection and processing with python
3aa7092
import gradio as gr
from fastapi import FastAPI, Request
import json
# THIS VERSION WORKS
# AND SENDS BACK A NOTE A FIFTH HIGHER THAN THE INPUT NOT ON THE SELECTED PORT
#
# ✅ Create FastAPI App
app = FastAPI()
# ✅ MIDI Processing Function in Python
@app.post("/midi_input")
async def process_midi(request: Request):
try:
midi_data = await request.json()
note = midi_data["note"]
velocity = midi_data["velocity"]
print(f"🎹 Received MIDI Note: {note}, Velocity: {velocity}")
# 🚀 Process MIDI data (example: Transpose + Generate New Notes)
generated_note = (note + 5) % 128 # Transpose up by 3 semitones
generated_velocity = min(velocity + 10, 127) # Increase velocity slightly
# ✅ Send MIDI Response Back to Client
return {
"status": "success",
"generated_note": generated_note,
"generated_velocity": generated_velocity,
"original_note": note
}
except Exception as e:
print(f"🚨 Error processing MIDI: {str(e)}")
return {"status": "error", "message": str(e)}
# ✅ JavaScript to Capture and Send MIDI Data
midi_js = """
<script>
let midiAccess = null;
let selectedInput = null;
let selectedOutput = null;
// ✅ Request MIDI Access
navigator.requestMIDIAccess()
.then(access => {
console.log("✅ MIDI Access Granted!");
midiAccess = access;
updateMIDIDevices();
midiAccess.onstatechange = updateMIDIDevices;
})
.catch(err => console.error("🚨 MIDI API Error:", err));
// ✅ Update MIDI Input & Output Menus
function updateMIDIDevices() {
let inputSelect = document.getElementById("midiInput");
let outputSelect = document.getElementById("midiOutput");
if (!inputSelect || !outputSelect) {
console.error("❌ MIDI dropdowns not found!");
return;
}
// Clear existing options
inputSelect.innerHTML = '<option value="">Select MIDI Input</option>';
outputSelect.innerHTML = '<option value="">Select MIDI Output</option>';
// Populate MIDI Input Devices
midiAccess.inputs.forEach((input, key) => {
let option = document.createElement("option");
option.value = key;
option.textContent = input.name || `MIDI Input ${key}`;
inputSelect.appendChild(option);
});
// Populate MIDI Output Devices
midiAccess.outputs.forEach((output, key) => {
let option = document.createElement("option");
option.value = key;
option.textContent = output.name || `MIDI Output ${key}`;
outputSelect.appendChild(option);
});
console.log("🎛 Updated MIDI Input & Output devices.");
}
// ✅ Handle MIDI Input Selection
function selectMIDIInput() {
let inputSelect = document.getElementById("midiInput");
let inputId = inputSelect.value;
if (selectedInput) {
selectedInput.onmidimessage = null;
}
if (midiAccess.inputs.has(inputId)) {
selectedInput = midiAccess.inputs.get(inputId);
selectedInput.onmidimessage = handleMIDIMessage;
console.log(`🎤 MIDI Input Selected: ${selectedInput.name}`);
}
}
// ✅ Handle MIDI Output Selection
function selectMIDIOutput() {
let outputSelect = document.getElementById("midiOutput");
let outputId = outputSelect.value;
if (midiAccess.outputs.has(outputId)) {
selectedOutput = midiAccess.outputs.get(outputId);
console.log(`🎹 MIDI Output Selected: ${selectedOutput.name}`);
}
}
// ✅ Play a MIDI Note Sent Back from Python
function playMIDINote(note, velocity) {
if (!selectedOutput) {
console.warn("⚠️ No MIDI output selected.");
return;
}
let noteOnMessage = [0x90, note, velocity]; // Note On
let noteOffMessage = [0x80, note, 0]; // Note Off
console.log(`🎵 Playing Generated MIDI Note ${note}, Velocity ${velocity}`);
try {
selectedOutput.send(noteOnMessage);
setTimeout(() => {
selectedOutput.send(noteOffMessage);
console.log(`🔇 Note Off ${note}`);
}, 500);
} catch (error) {
console.error("🚨 Error playing MIDI note:", error);
}
}
// ✅ Send MIDI Data to Python
// ✅ Handle Incoming MIDI Messages and Send to Python
function handleMIDIMessage(event) {
let originalNote = event.data[1];
let velocity = event.data[2];
let midiData = {
note: originalNote,
velocity: velocity
};
console.log(`🎤 MIDI Input: Note ${originalNote}, Velocity ${velocity}`);
// ✅ Send MIDI data to Python backend
fetch("/midi_input", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(midiData)
})
.then(response => response.json())
.then(data => {
console.log("📨 MIDI sent to Python. Response:", data);
// ✅ Play the generated MIDI response
if (data.status === "success") {
playMIDINote(data.generated_note, data.generated_velocity);
}
})
.catch(error => console.error("🚨 Error sending MIDI data:", error));
}
// ✅ Attach Generate Button Event
function attachButtonEvent() {
let generateButton = document.getElementById("generateButton");
if (generateButton) {
console.log("✅ Generate button found! Attaching event listener...");
generateButton.addEventListener("click", function () {
console.log("🎹 Generate button clicked.");
if (!selectedOutput) {
alert("⚠️ Please select a MIDI Output first!");
return;
}
let randomNote = 60 + Math.floor(Math.random() * 12); // Random note from C4 to B4
console.log(`🎵 Generating MIDI Note: ${randomNote}`);
playMIDINote(randomNote, 100);
});
} else {
console.log("⏳ Waiting for button to be available...");
setTimeout(attachButtonEvent, 500); // Try again in 500ms
}
}
// ✅ Ensure the Button and Menus Are Loaded
window.onload = function() {
console.log("✅ Page fully loaded. Checking for elements...");
updateMIDIDevices();
attachButtonEvent();
};
</script>
<!-- 🎛 MIDI Input & Output Selection -->
<div>
<label for="midiInput">MIDI Input: </label>
<select id="midiInput" onchange="selectMIDIInput()"></select>
<label for="midiOutput">MIDI Output: </label>
<select id="midiOutput" onchange="selectMIDIOutput()"></select>
</div>
<!-- 🎶 "Generate MIDI" Button -->
<button id="generateButton">🎵 Generate MIDI Note</button>
"""
# ✅ Inject JavaScript and HTML
with gr.Blocks() as demo:
gr.HTML(midi_js)
# ✅ Mount FastAPI with Gradio
app = gr.mount_gradio_app(app, demo, path="/")
# ✅ Run the app
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)