| import gradio as gr |
| import numpy as np |
| import io |
| import tempfile |
| import os |
| from scipy.io import wavfile |
| import speech_recognition as sr |
| import soundfile as sf |
|
|
| |
| MORSE_CODE_DICT = { |
| 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', |
| 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', |
| 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', |
| 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', |
| 'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', |
| '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', |
| '9': '----.', '0': '-----', ' ': '/' |
| } |
| MORSE_TO_CHAR = {v: k for k, v in MORSE_CODE_DICT.items()} |
|
|
| |
| DIT_DURATION = 0.1 |
| DAH_DURATION = 3 * DIT_DURATION |
| SPACE_DURATION = 7 * DIT_DURATION |
| CHAR_SPACE = DIT_DURATION |
| SAMPLE_RATE = 44100 |
|
|
| |
| def decode_morse_from_audio(audio_data, is_file=False): |
| if audio_data is None: |
| return "", "" |
| if is_file: |
| sample_rate, data = wavfile.read(audio_data) |
| else: |
| sample_rate, data = audio_data |
| if len(data.shape) > 1: |
| data = data.mean(axis=1) |
| data = data / np.max(np.abs(data)) |
| |
| threshold = 0.1 |
| signal = data > threshold |
| morse_code, decoded_text = "", "" |
| i = 0 |
| |
| while i < len(signal) - int(SAMPLE_RATE * DIT_DURATION): |
| if signal[i]: |
| start = i |
| while i < len(signal) and signal[i]: |
| i += 1 |
| duration = (i - start) / sample_rate |
| morse_code += "-" if duration >= DAH_DURATION else "." |
| else: |
| start = i |
| while i < len(signal) and not signal[i]: |
| i += 1 |
| pause = (i - start) / sample_rate |
| if pause >= SPACE_DURATION and morse_code: |
| decoded_text += " " |
| morse_code = "" |
| elif pause >= DIT_DURATION and morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| morse_code = "" |
| i += 1 |
| |
| if morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| return morse_code, decoded_text.strip() |
|
|
| |
| def decode_morse_from_text(morse_text): |
| if not morse_text: |
| return "" |
| words = morse_text.split("/") |
| decoded_text = "" |
| for word in words: |
| chars = word.strip().split() |
| for char in chars: |
| decoded_text += MORSE_TO_CHAR.get(char, "?") |
| decoded_text += " " |
| return decoded_text.strip() |
|
|
| |
| def text_to_morse(text): |
| text = text.upper() |
| morse = " ".join(MORSE_CODE_DICT.get(char, "?") for char in text if char in MORSE_CODE_DICT) |
| return morse |
|
|
| |
| def generate_morse_audio(morse): |
| audio = [] |
| frequency = 750 |
| |
| for symbol in morse.split(): |
| if symbol == "/": |
| audio.extend([0] * int(SAMPLE_RATE * SPACE_DURATION)) |
| else: |
| for char in symbol: |
| duration = DAH_DURATION if char == "-" else DIT_DURATION |
| t = np.linspace(0, duration, int(SAMPLE_RATE * duration), False) |
| tone = 0.5 * np.sin(2 * np.pi * frequency * t) |
| audio.extend(tone) |
| audio.extend([0] * int(SAMPLE_RATE * DIT_DURATION)) |
| audio.extend([0] * int(SAMPLE_RATE * CHAR_SPACE)) |
| |
| audio = np.array(audio, dtype=np.float32) |
| with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as temp_file: |
| sf.write(temp_file.name, audio, SAMPLE_RATE, format="wav") |
| return temp_file.name |
|
|
| |
| def speech_to_text(audio_path): |
| recognizer = sr.Recognizer() |
| with sr.AudioFile(audio_path) as source: |
| audio_data = recognizer.record(source) |
| try: |
| return recognizer.recognize_google(audio_data) |
| except sr.UnknownValueError: |
| return "Could not understand audio" |
| except sr.RequestError: |
| return "Speech recognition service unavailable" |
|
|
| |
| def generate_alphabet_html(decoded_text): |
| html = "<div style='font-family: monospace; font-size: 16px;'>" |
| for char in MORSE_CODE_DICT.keys(): |
| color = "red" if char in decoded_text.upper() else "black" |
| html += f"<span style='color: {color}; margin: 5px;'>{char}: {MORSE_CODE_DICT[char]}</span>" |
| if char in "AEIMQUZ": |
| html += "<br>" |
| html += "</div>" |
| return html |
|
|
| |
| def process_input(text=None, speech=None, live_audio=None, upload_audio=None, morse_text=None, morse_speech=None, morse_audio=None): |
| morse_output, text_output, audio_output = "", "", None |
| |
| |
| if text: |
| morse_output = text_to_morse(text) |
| text_output = text |
| audio_output = generate_morse_audio(morse_output) |
| |
| elif speech: |
| transcribed = speech_to_text(speech) |
| morse_output = text_to_morse(transcribed) |
| text_output = transcribed |
| audio_output = generate_morse_audio(morse_output) |
| |
| elif live_audio: |
| |
| morse_output, text_output = decode_morse_from_audio(live_audio, is_file=False) |
| |
| elif upload_audio: |
| |
| morse_output, text_output = decode_morse_from_audio(upload_audio, is_file=True) |
| |
| |
| elif morse_text: |
| morse_output = morse_text |
| text_output = decode_morse_from_text(morse_text) |
| audio_output = generate_morse_audio(morse_text) |
| |
| elif morse_speech: |
| transcribed = speech_to_text(morse_speech).replace("dit", ".").replace("dah", "-").replace("slash", "/") |
| morse_output = transcribed |
| text_output = decode_morse_from_text(transcribed) |
| audio_output = generate_morse_audio(transcribed) |
| |
| elif morse_audio: |
| morse_output, text_output = decode_morse_from_audio(morse_audio, is_file=True) |
| |
| alphabet_html = generate_alphabet_html(text_output) |
| return morse_output, text_output, alphabet_html, audio_output |
|
|
| |
| with gr.Blocks(title="Morse Code Converter") as demo: |
| gr.Markdown("# Morse Code Converter") |
| gr.Markdown("Encode text/speech to Morse, or decode Morse text/speech/audio to text!") |
| |
| |
| with gr.Tab("Encode Text to Morse"): |
| text_input = gr.Textbox(label="Enter Text", placeholder="e.g., HELLO") |
| text_btn = gr.Button("Convert to Morse") |
| with gr.Row(): |
| with gr.Column(): |
| text_morse_out = gr.Textbox(label="Morse Code", interactive=False) |
| text_text_out = gr.Textbox(label="Original Text", interactive=False) |
| text_alphabet = gr.HTML(label="Alphabet (Highlighted)") |
| text_audio = gr.Audio(label="Morse Audio", interactive=False) |
| text_btn.click(fn=process_input, inputs=[text_input], outputs=[text_morse_out, text_text_out, text_alphabet, text_audio]) |
|
|
| with gr.Tab("Encode Speech to Morse"): |
| speech_input = gr.Audio(type="filepath", label="Record Speech (e.g., say 'HELLO')") |
| speech_btn = gr.Button("Convert to Morse") |
| with gr.Row(): |
| with gr.Column(): |
| speech_morse_out = gr.Textbox(label="Morse Code", interactive=False) |
| speech_text_out = gr.Textbox(label="Transcribed Text", interactive=False) |
| speech_alphabet = gr.HTML(label="Alphabet (Highlighted)") |
| speech_audio = gr.Audio(label="Morse Audio", interactive=False) |
| speech_btn.click(fn=process_input, inputs=[speech_input], outputs=[speech_morse_out, speech_text_out, speech_alphabet, speech_audio]) |
|
|
| |
| with gr.Tab("Decode Morse Text"): |
| morse_text_input = gr.Textbox(label="Enter Morse Text", placeholder="e.g., .... . .-.. .-.. ---") |
| morse_text_btn = gr.Button("Decode Morse") |
| with gr.Row(): |
| with gr.Column(): |
| morse_text_morse_out = gr.Textbox(label="Morse Code", interactive=False) |
| morse_text_text_out = gr.Textbox(label="Decoded Text", interactive=False) |
| morse_text_alphabet = gr.HTML(label="Alphabet (Highlighted)") |
| morse_text_audio = gr.Audio(label="Morse Audio", interactive=False) |
| morse_text_btn.click(fn=process_input, inputs=[morse_text_input], outputs=[morse_text_morse_out, morse_text_text_out, morse_text_alphabet, morse_text_audio]) |
|
|
| with gr.Tab("Decode Morse Speech"): |
| morse_speech_input = gr.Audio(type="filepath", label="Record Morse Speech (e.g., say 'dit dit dit dit dit')") |
| morse_speech_btn = gr.Button("Decode Morse") |
| with gr.Row(): |
| with gr.Column(): |
| morse_speech_morse_out = gr.Textbox(label="Transcribed Morse", interactive=False) |
| morse_speech_text_out = gr.Textbox(label="Decoded Text", interactive=False) |
| morse_speech_alphabet = gr.HTML(label="Alphabet (Highlighted)") |
| morse_speech_audio = gr.Audio(label="Morse Audio", interactive=False) |
| morse_speech_btn.click(fn=process_input, inputs=[morse_speech_input], outputs=[morse_speech_morse_out, morse_speech_text_out, morse_speech_alphabet, morse_speech_audio]) |
|
|
| with gr.Tab("Decode Morse Audio"): |
| morse_audio_input = gr.Audio(type="filepath", label="Upload Morse Audio (WAV of beeps)") |
| morse_audio_btn = gr.Button("Decode Morse") |
| with gr.Row(): |
| with gr.Column(): |
| morse_audio_morse_out = gr.Textbox(label="Detected Morse", interactive=False) |
| morse_audio_text_out = gr.Textbox(label="Decoded Text", interactive=False) |
| morse_audio_alphabet = gr.HTML(label="Alphabet (Highlighted)") |
| morse_audio_btn.click(fn=process_input, inputs=[morse_audio_input], outputs=[morse_audio_morse_out, morse_audio_text_out, morse_audio_alphabet, gr.Audio(visible=False)]) |
|
|
| with gr.Tab("Decode Live Morse Audio"): |
| live_audio_input = gr.Audio(type="numpy", label="Live Morse Input (Use Microphone)", streaming=True) |
| with gr.Row(): |
| with gr.Column(): |
| live_morse_out = gr.Textbox(label="Detected Morse", interactive=False) |
| live_text_out = gr.Textbox(label="Decoded Text", interactive=False) |
| live_alphabet = gr.HTML(label="Alphabet (Highlighted)") |
| live_audio_input.stream(fn=process_input, inputs=[live_audio_input], outputs=[live_morse_out, live_text_out, live_alphabet, gr.Audio(visible=False)]) |
|
|
| demo.launch() |
|
|
| ''' |
| import gradio as gr |
| import numpy as np |
| import io |
| import tempfile |
| import os |
| from scipy.io import wavfile |
| import speech_recognition as sr |
| import soundfile as sf |
| |
| # Morse code dictionary (ITU standard) |
| MORSE_CODE_DICT = { |
| 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', |
| 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', |
| 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', |
| 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', |
| 'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', |
| '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', |
| '9': '----.', '0': '-----', ' ': '/' |
| } |
| MORSE_TO_CHAR = {v: k for k, v in MORSE_CODE_DICT.items()} |
| |
| # Morse code timing (in seconds) |
| DIT_DURATION = 0.1 # 100ms for dit |
| DAH_DURATION = 3 * DIT_DURATION # 300ms for dah |
| SPACE_DURATION = 7 * DIT_DURATION # 700ms for word space |
| CHAR_SPACE = DIT_DURATION # Space between characters |
| SAMPLE_RATE = 44100 # Standard audio sample rate |
| |
| # Decode Morse from audio (live or uploaded) |
| def decode_morse_from_audio(audio_data, is_file=False): |
| if audio_data is None: |
| return "", "" |
| |
| if is_file: |
| # For uploaded files, audio_data is a file path |
| sample_rate, data = wavfile.read(audio_data) |
| else: |
| # For live streaming, audio_data is (sample_rate, data) |
| sample_rate, data = audio_data |
| |
| if len(data.shape) > 1: |
| data = data.mean(axis=1) |
| data = data / np.max(np.abs(data)) |
| |
| threshold = 0.1 |
| signal = data > threshold |
| morse_code, decoded_text = "", "" |
| i = 0 |
| |
| while i < len(signal) - int(SAMPLE_RATE * DIT_DURATION): |
| if signal[i]: |
| start = i |
| while i < len(signal) and signal[i]: |
| i += 1 |
| duration = (i - start) / sample_rate |
| morse_code += "-" if duration >= DAH_DURATION else "." |
| else: |
| start = i |
| while i < len(signal) and not signal[i]: |
| i += 1 |
| pause = (i - start) / sample_rate |
| if pause >= SPACE_DURATION and morse_code: |
| decoded_text += " " |
| morse_code = "" |
| elif pause >= DIT_DURATION and morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| morse_code = "" |
| i += 1 |
| |
| if morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| return morse_code, decoded_text.strip() |
| |
| # Convert text to Morse code |
| def text_to_morse(text): |
| text = text.upper() |
| morse = " ".join(MORSE_CODE_DICT.get(char, "?") for char in text if char in MORSE_CODE_DICT) |
| return morse |
| |
| # Generate Morse code audio and save to temporary file |
| def generate_morse_audio(morse): |
| audio = [] |
| frequency = 750 # Hz for Morse tone |
| |
| for symbol in morse.split(): |
| if symbol == "/": |
| audio.extend([0] * int(SAMPLE_RATE * SPACE_DURATION)) |
| else: |
| for char in symbol: |
| duration = DAH_DURATION if char == "-" else DIT_DURATION |
| t = np.linspace(0, duration, int(SAMPLE_RATE * duration), False) |
| tone = 0.5 * np.sin(2 * np.pi * frequency * t) |
| audio.extend(tone) |
| audio.extend([0] * int(SAMPLE_RATE * DIT_DURATION)) # Space between dits/dahs |
| audio.extend([0] * int(SAMPLE_RATE * CHAR_SPACE)) # Space between characters |
| |
| audio = np.array(audio, dtype=np.float32) |
| with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as temp_file: |
| sf.write(temp_file.name, audio, SAMPLE_RATE, format="wav") |
| temp_file_path = temp_file.name |
| return temp_file_path |
| |
| # Speech to text |
| def speech_to_text(audio_path): |
| recognizer = sr.Recognizer() |
| with sr.AudioFile(audio_path) as source: |
| audio_data = recognizer.record(source) |
| try: |
| return recognizer.recognize_google(audio_data) |
| except sr.UnknownValueError: |
| return "Could not understand audio" |
| except sr.RequestError: |
| return "Speech recognition service unavailable" |
| |
| # Highlight alphabet in UI |
| def generate_alphabet_html(decoded_text): |
| html = "<div style='font-family: monospace; font-size: 16px;'>" |
| for char in MORSE_CODE_DICT.keys(): |
| color = "red" if char in decoded_text.upper() else "black" |
| html += f"<span style='color: {color}; margin: 5px;'>{char}: {MORSE_CODE_DICT[char]}</span>" |
| if char in "AEIMQUZ": |
| html += "<br>" |
| html += "</div>" |
| return html |
| |
| # Combined processing function |
| def process_input(text=None, speech=None, live_audio=None, upload_audio=None): |
| morse, decoded_text, audio_output = "", "", None |
| |
| if text: # Text input |
| morse = text_to_morse(text) |
| decoded_text = text |
| audio_output = generate_morse_audio(morse) |
| |
| elif speech: # Speech input |
| text = speech_to_text(speech) |
| morse = text_to_morse(text) |
| decoded_text = text |
| audio_output = generate_morse_audio(morse) |
| |
| elif live_audio: # Live audio input |
| morse, decoded_text = decode_morse_from_audio(live_audio, is_file=False) |
| |
| elif upload_audio: # Uploaded audio file |
| morse, decoded_text = decode_morse_from_audio(upload_audio, is_file=True) |
| |
| alphabet_html = generate_alphabet_html(decoded_text) |
| return morse, decoded_text, alphabet_html, audio_output |
| |
| # Gradio UI with Blocks |
| with gr.Blocks(title="Morse Code Decoder & Generator") as demo: |
| gr.Markdown("# Morse Code Decoder & Generator") |
| gr.Markdown("Decode live or uploaded Morse audio, or generate Morse from text/speech!") |
| |
| with gr.Tab("Decode Live Audio"): |
| audio_input = gr.Audio(type="numpy", label="Live Audio Input (Use Microphone)", streaming=True) |
| with gr.Row(): |
| with gr.Column(): |
| morse_output = gr.Textbox(label="Detected Morse Code", interactive=False) |
| text_output = gr.Textbox(label="Decoded Text", interactive=False) |
| alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| |
| audio_input.stream( |
| fn=process_input, |
| inputs=[audio_input], |
| outputs=[morse_output, text_output, alphabet_display, gr.Audio(visible=False)], |
| ) |
| |
| with gr.Tab("Generate from Text"): |
| text_input = gr.Textbox(label="Enter Text", placeholder="Type here...") |
| generate_btn = gr.Button("Generate Morse") |
| with gr.Row(): |
| with gr.Column(): |
| morse_gen_output = gr.Textbox(label="Morse Code", interactive=False) |
| text_gen_output = gr.Textbox(label="Original Text", interactive=False) |
| gen_alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| audio_playback = gr.Audio(label="Morse Audio Playback", interactive=False) |
| |
| generate_btn.click( |
| fn=process_input, |
| inputs=[text_input], |
| outputs=[morse_gen_output, text_gen_output, gen_alphabet_display, audio_playback] |
| ) |
| |
| with gr.Tab("Generate from Speech"): |
| speech_input = gr.Audio(type="filepath", label="Speak Your Text (Record Audio)") |
| speech_btn = gr.Button("Convert Speech to Morse") |
| with gr.Row(): |
| with gr.Column(): |
| morse_speech_output = gr.Textbox(label="Morse Code", interactive=False) |
| text_speech_output = gr.Textbox(label="Transcribed Text", interactive=False) |
| speech_alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| speech_audio_playback = gr.Audio(label="Morse Audio Playback", interactive=False) |
| |
| speech_btn.click( |
| fn=process_input, |
| inputs=[speech_input], |
| outputs=[morse_speech_output, text_speech_output, speech_alphabet_display, speech_audio_playback] |
| ) |
| |
| with gr.Tab("Decode from Audio Upload"): |
| upload_input = gr.Audio(type="filepath", label="Upload Morse Audio File (WAV)") |
| upload_btn = gr.Button("Decode Morse") |
| with gr.Row(): |
| with gr.Column(): |
| morse_upload_output = gr.Textbox(label="Detected Morse Code", interactive=False) |
| text_upload_output = gr.Textbox(label="Decoded Text", interactive=False) |
| upload_alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| |
| upload_btn.click( |
| fn=process_input, |
| inputs=[upload_input], |
| outputs=[morse_upload_output, text_upload_output, upload_alphabet_display, gr.Audio(visible=False)] |
| ) |
| |
| # Launch the app |
| demo.launch() |
| ''' |
| ''' |
| import gradio as gr |
| import numpy as np |
| import io |
| import tempfile |
| import os |
| from scipy.io import wavfile |
| import speech_recognition as sr |
| import soundfile as sf |
| |
| # Morse code dictionary (ITU standard) |
| MORSE_CODE_DICT = { |
| 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', |
| 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', |
| 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', |
| 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', |
| 'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', |
| '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', |
| '9': '----.', '0': '-----', ' ': '/' |
| } |
| MORSE_TO_CHAR = {v: k for k, v in MORSE_CODE_DICT.items()} |
| |
| # Morse code timing (in seconds) |
| DIT_DURATION = 0.1 # 100ms for dit |
| DAH_DURATION = 3 * DIT_DURATION # 300ms for dah |
| SPACE_DURATION = 7 * DIT_DURATION # 700ms for word space |
| CHAR_SPACE = DIT_DURATION # Space between characters |
| SAMPLE_RATE = 44100 # Standard audio sample rate |
| |
| # Decode Morse from audio |
| def decode_morse_from_audio(audio_data): |
| if audio_data is None: |
| return "", "" |
| sample_rate, data = audio_data |
| if len(data.shape) > 1: |
| data = data.mean(axis=1) |
| data = data / np.max(np.abs(data)) |
| |
| threshold = 0.1 |
| signal = data > threshold |
| morse_code, decoded_text = "", "" |
| i = 0 |
| |
| while i < len(signal) - int(SAMPLE_RATE * DIT_DURATION): |
| if signal[i]: |
| start = i |
| while i < len(signal) and signal[i]: |
| i += 1 |
| duration = (i - start) / sample_rate |
| morse_code += "-" if duration >= DAH_DURATION else "." |
| else: |
| start = i |
| while i < len(signal) and not signal[i]: |
| i += 1 |
| pause = (i - start) / sample_rate |
| if pause >= SPACE_DURATION and morse_code: |
| decoded_text += " " |
| morse_code = "" |
| elif pause >= DIT_DURATION and morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| morse_code = "" |
| i += 1 |
| |
| if morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| return morse_code, decoded_text.strip() |
| |
| # Convert text to Morse code |
| def text_to_morse(text): |
| text = text.upper() |
| morse = " ".join(MORSE_CODE_DICT.get(char, "?") for char in text if char in MORSE_CODE_DICT) |
| return morse |
| |
| # Generate Morse code audio and save to temporary file |
| def generate_morse_audio(morse): |
| audio = [] |
| frequency = 750 # Hz for Morse tone |
| |
| for symbol in morse.split(): |
| if symbol == "/": |
| audio.extend([0] * int(SAMPLE_RATE * SPACE_DURATION)) |
| else: |
| for char in symbol: |
| duration = DAH_DURATION if char == "-" else DIT_DURATION |
| t = np.linspace(0, duration, int(SAMPLE_RATE * duration), False) |
| tone = 0.5 * np.sin(2 * np.pi * frequency * t) |
| audio.extend(tone) |
| audio.extend([0] * int(SAMPLE_RATE * DIT_DURATION)) # Space between dits/dahs |
| audio.extend([0] * int(SAMPLE_RATE * CHAR_SPACE)) # Space between characters |
| |
| audio = np.array(audio, dtype=np.float32) |
| # Save to a temporary file |
| with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as temp_file: |
| sf.write(temp_file.name, audio, SAMPLE_RATE, format="wav") |
| temp_file_path = temp_file.name |
| return temp_file_path |
| |
| # Speech to text |
| def speech_to_text(audio_path): |
| recognizer = sr.Recognizer() |
| with sr.AudioFile(audio_path) as source: |
| audio_data = recognizer.record(source) |
| try: |
| return recognizer.recognize_google(audio_data) |
| except sr.UnknownValueError: |
| return "Could not understand audio" |
| except sr.RequestError: |
| return "Speech recognition service unavailable" |
| |
| # Highlight alphabet in UI |
| def generate_alphabet_html(decoded_text): |
| html = "<div style='font-family: monospace; font-size: 16px;'>" |
| for char in MORSE_CODE_DICT.keys(): |
| color = "red" if char in decoded_text.upper() else "black" |
| html += f"<span style='color: {color}; margin: 5px;'>{char}: {MORSE_CODE_DICT[char]}</span>" |
| if char in "AEIMQUZ": |
| html += "<br>" |
| html += "</div>" |
| return html |
| |
| # Combined processing function with cleanup |
| def process_input(text=None, speech=None, audio=None): |
| morse, decoded_text, audio_output = "", "", None |
| |
| if text: # Text input |
| morse = text_to_morse(text) |
| decoded_text = text |
| audio_output = generate_morse_audio(morse) |
| |
| elif speech: # Speech input |
| text = speech_to_text(speech) |
| morse = text_to_morse(text) |
| decoded_text = text |
| audio_output = generate_morse_audio(morse) |
| |
| elif audio: # Live audio input |
| morse, decoded_text = decode_morse_from_audio(audio) |
| |
| alphabet_html = generate_alphabet_html(decoded_text) |
| return morse, decoded_text, alphabet_html, audio_output |
| |
| # Gradio UI with Blocks |
| with gr.Blocks(title="Morse Code Decoder & Generator") as demo: |
| gr.Markdown("# Morse Code Decoder & Generator") |
| gr.Markdown("Decode live Morse audio, or generate Morse from text/speech!") |
| |
| with gr.Tab("Decode Live Audio"): |
| audio_input = gr.Audio(type="numpy", label="Live Audio Input (Use Microphone)", streaming=True) |
| with gr.Row(): |
| with gr.Column(): |
| morse_output = gr.Textbox(label="Detected Morse Code", interactive=False) |
| text_output = gr.Textbox(label="Decoded Text", interactive=False) |
| alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| |
| audio_input.stream( |
| fn=process_input, |
| inputs=[audio_input], |
| outputs=[morse_output, text_output, alphabet_display, gr.Audio(visible=False)], |
| ) |
| |
| with gr.Tab("Generate from Text"): |
| text_input = gr.Textbox(label="Enter Text", placeholder="Type here...") |
| generate_btn = gr.Button("Generate Morse") |
| with gr.Row(): |
| with gr.Column(): |
| morse_gen_output = gr.Textbox(label="Morse Code", interactive=False) |
| text_gen_output = gr.Textbox(label="Original Text", interactive=False) |
| gen_alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| audio_playback = gr.Audio(label="Morse Audio Playback", interactive=False) |
| |
| generate_btn.click( |
| fn=process_input, |
| inputs=[text_input], |
| outputs=[morse_gen_output, text_gen_output, gen_alphabet_display, audio_playback] |
| ) |
| |
| with gr.Tab("Generate from Speech"): |
| speech_input = gr.Audio(type="filepath", label="Speak Your Text (Record Audio)") |
| speech_btn = gr.Button("Convert Speech to Morse") |
| with gr.Row(): |
| with gr.Column(): |
| morse_speech_output = gr.Textbox(label="Morse Code", interactive=False) |
| text_speech_output = gr.Textbox(label="Transcribed Text", interactive=False) |
| speech_alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| speech_audio_playback = gr.Audio(label="Morse Audio Playback", interactive=False) |
| |
| speech_btn.click( |
| fn=process_input, |
| inputs=[speech_input], |
| outputs=[morse_speech_output, text_speech_output, speech_alphabet_display, speech_audio_playback] |
| ) |
| |
| # Launch the app |
| demo.launch() |
| ''' |
|
|
| ''' |
| import gradio as gr |
| import numpy as np |
| import io |
| from scipy.io import wavfile |
| import speech_recognition as sr |
| import soundfile as sf |
| |
| # Morse code dictionary (ITU standard) |
| MORSE_CODE_DICT = { |
| 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', |
| 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', |
| 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', |
| 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', |
| 'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', |
| '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', |
| '9': '----.', '0': '-----', ' ': '/' |
| } |
| MORSE_TO_CHAR = {v: k for k, v in MORSE_CODE_DICT.items()} |
| |
| # Morse code timing (in seconds) |
| DIT_DURATION = 0.1 # 100ms for dit |
| DAH_DURATION = 3 * DIT_DURATION # 300ms for dah |
| SPACE_DURATION = 7 * DIT_DURATION # 700ms for word space |
| CHAR_SPACE = DIT_DURATION # Space between characters |
| SAMPLE_RATE = 44100 # Standard audio sample rate |
| |
| # Decode Morse from audio |
| def decode_morse_from_audio(audio_data): |
| if audio_data is None: |
| return "", "" |
| sample_rate, data = audio_data |
| if len(data.shape) > 1: |
| data = data.mean(axis=1) |
| data = data / np.max(np.abs(data)) |
| |
| threshold = 0.1 |
| signal = data > threshold |
| morse_code, decoded_text = "", "" |
| i = 0 |
| |
| while i < len(signal) - int(SAMPLE_RATE * DIT_DURATION): |
| if signal[i]: |
| start = i |
| while i < len(signal) and signal[i]: |
| i += 1 |
| duration = (i - start) / sample_rate |
| morse_code += "-" if duration >= DAH_DURATION else "." |
| else: |
| start = i |
| while i < len(signal) and not signal[i]: |
| i += 1 |
| pause = (i - start) / sample_rate |
| if pause >= SPACE_DURATION and morse_code: |
| decoded_text += " " |
| morse_code = "" |
| elif pause >= DIT_DURATION and morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| morse_code = "" |
| i += 1 |
| |
| if morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| return morse_code, decoded_text.strip() |
| |
| # Convert text to Morse code |
| def text_to_morse(text): |
| text = text.upper() |
| morse = " ".join(MORSE_CODE_DICT.get(char, "?") for char in text if char in MORSE_CODE_DICT) |
| return morse |
| |
| # Generate Morse code audio |
| def generate_morse_audio(morse): |
| audio = [] |
| frequency = 750 # Hz for Morse tone |
| |
| for symbol in morse.split(): |
| if symbol == "/": |
| audio.extend([0] * int(SAMPLE_RATE * SPACE_DURATION)) |
| else: |
| for char in symbol: |
| duration = DAH_DURATION if char == "-" else DIT_DURATION |
| t = np.linspace(0, duration, int(SAMPLE_RATE * duration), False) |
| tone = 0.5 * np.sin(2 * np.pi * frequency * t) |
| audio.extend(tone) |
| audio.extend([0] * int(SAMPLE_RATE * DIT_DURATION)) # Space between dits/dahs |
| audio.extend([0] * int(SAMPLE_RATE * CHAR_SPACE)) # Space between characters |
| |
| audio = np.array(audio, dtype=np.float32) |
| buffer = io.BytesIO() |
| sf.write(buffer, audio, SAMPLE_RATE, format="wav") |
| buffer.seek(0) |
| return buffer |
| |
| # Speech to text |
| def speech_to_text(audio_path): |
| recognizer = sr.Recognizer() |
| with sr.AudioFile(audio_path) as source: |
| audio_data = recognizer.record(source) |
| try: |
| return recognizer.recognize_google(audio_data) |
| except sr.UnknownValueError: |
| return "Could not understand audio" |
| except sr.RequestError: |
| return "Speech recognition service unavailable" |
| |
| # Highlight alphabet in UI |
| def generate_alphabet_html(decoded_text): |
| html = "<div style='font-family: monospace; font-size: 16px;'>" |
| for char in MORSE_CODE_DICT.keys(): |
| color = "red" if char in decoded_text.upper() else "black" |
| html += f"<span style='color: {color}; margin: 5px;'>{char}: {MORSE_CODE_DICT[char]}</span>" |
| if char in "AEIMQUZ": |
| html += "<br>" |
| html += "</div>" |
| return html |
| |
| # Combined processing function |
| def process_input(text=None, speech=None, audio=None): |
| morse, decoded_text, audio_output = "", "", None |
| |
| if text: # Text input |
| morse = text_to_morse(text) |
| decoded_text = text |
| audio_output = generate_morse_audio(morse) |
| |
| elif speech: # Speech input |
| text = speech_to_text(speech) |
| morse = text_to_morse(text) |
| decoded_text = text |
| audio_output = generate_morse_audio(morse) |
| |
| elif audio: # Live audio input |
| morse, decoded_text = decode_morse_from_audio(audio) |
| |
| alphabet_html = generate_alphabet_html(decoded_text) |
| return morse, decoded_text, alphabet_html, audio_output |
| |
| # Gradio UI with Blocks |
| with gr.Blocks(title="Morse Code Decoder & Generator") as demo: |
| gr.Markdown("# Morse Code Decoder & Generator") |
| gr.Markdown("Decode live Morse audio, or generate Morse from text/speech!") |
| |
| with gr.Tab("Decode Live Audio"): |
| audio_input = gr.Audio(type="numpy", label="Live Audio Input (Use Microphone)", streaming=True) |
| with gr.Row(): |
| with gr.Column(): |
| morse_output = gr.Textbox(label="Detected Morse Code", interactive=False) |
| text_output = gr.Textbox(label="Decoded Text", interactive=False) |
| alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| |
| audio_input.stream( |
| fn=process_input, |
| inputs=[audio_input], |
| outputs=[morse_output, text_output, alphabet_display, gr.Audio(visible=False)], |
| ) |
| |
| with gr.Tab("Generate from Text"): |
| text_input = gr.Textbox(label="Enter Text", placeholder="Type here...") |
| generate_btn = gr.Button("Generate Morse") |
| with gr.Row(): |
| with gr.Column(): |
| morse_gen_output = gr.Textbox(label="Morse Code", interactive=False) |
| text_gen_output = gr.Textbox(label="Original Text", interactive=False) |
| gen_alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| audio_playback = gr.Audio(label="Morse Audio Playback", interactive=False) |
| |
| generate_btn.click( |
| fn=process_input, |
| inputs=[text_input], |
| outputs=[morse_gen_output, text_gen_output, gen_alphabet_display, audio_playback] |
| ) |
| |
| with gr.Tab("Generate from Speech"): |
| speech_input = gr.Audio(type="filepath", label="Speak Your Text (Record Audio)") |
| speech_btn = gr.Button("Convert Speech to Morse") |
| with gr.Row(): |
| with gr.Column(): |
| morse_speech_output = gr.Textbox(label="Morse Code", interactive=False) |
| text_speech_output = gr.Textbox(label="Transcribed Text", interactive=False) |
| speech_alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| speech_audio_playback = gr.Audio(label="Morse Audio Playback", interactive=False) |
| |
| speech_btn.click( |
| fn=process_input, |
| inputs=[speech_input], |
| outputs=[morse_speech_output, text_speech_output, speech_alphabet_display, speech_audio_playback] |
| ) |
| |
| # Launch the app |
| demo.launch() |
| ''' |
|
|
| ''' |
| import gradio as gr |
| import numpy as np |
| import time |
| from scipy.io import wavfile |
| import io |
| |
| # Morse code dictionary (ITU standard) |
| MORSE_CODE_DICT = { |
| 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', |
| 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', |
| 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', |
| 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', |
| 'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', |
| '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', |
| '9': '----.', '0': '-----', ' ': ' ' |
| } |
| |
| # Reverse dictionary for decoding |
| MORSE_TO_CHAR = {v: k for k, v in MORSE_CODE_DICT.items()} |
| |
| # Function to process audio and detect Morse code (simplified) |
| def decode_morse_from_audio(audio_data): |
| if audio_data is None: |
| return "", "" |
| |
| # Audio comes as (sample_rate, data) from Gradio |
| sample_rate, data = audio_data |
| if len(data.shape) > 1: # Convert stereo to mono if needed |
| data = data.mean(axis=1) |
| |
| # Normalize audio data |
| data = data / np.max(np.abs(data)) |
| |
| # Threshold for detecting signal (tweak as needed) |
| threshold = 0.1 |
| signal = data > threshold |
| |
| # Timing parameters (in samples, adjust based on sample_rate) |
| dit_length = int(sample_rate * 0.1) # 100ms for a dit |
| dah_length = dit_length * 3 # 300ms for a dah |
| space_length = dit_length * 7 # 700ms for word space |
| |
| morse_code = "" |
| decoded_text = "" |
| i = 0 |
| |
| while i < len(signal) - dit_length: |
| if signal[i]: |
| # Measure signal duration |
| start = i |
| while i < len(signal) and signal[i]: |
| i += 1 |
| duration = i - start |
| |
| # Classify as dit or dah |
| if duration >= dah_length: |
| morse_code += "-" |
| elif duration >= dit_length: |
| morse_code += "." |
| |
| # Check for spaces (pauses) |
| else: |
| start = i |
| while i < len(signal) and not signal[i]: |
| i += 1 |
| pause = i - start |
| |
| if pause >= space_length: |
| if morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| decoded_text += " " |
| morse_code = "" |
| elif pause >= dit_length and morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| morse_code = "" |
| |
| i += 1 |
| |
| # Handle any remaining code |
| if morse_code: |
| decoded_text += MORSE_TO_CHAR.get(morse_code, "?") |
| |
| return morse_code, decoded_text.strip() |
| |
| # Function to generate highlighted alphabet UI |
| def generate_alphabet_html(decoded_text): |
| html = "<div style='font-family: monospace; font-size: 16px;'>" |
| for char in MORSE_CODE_DICT.keys(): |
| color = "red" if char in decoded_text.upper() else "black" |
| html += f"<span style='color: {color}; margin: 5px;'>{char}: {MORSE_CODE_DICT[char]}</span>" |
| if char in "AEIMQUZ": |
| html += "<br>" |
| html += "</div>" |
| return html |
| |
| # Gradio streaming function |
| def stream_morse_decoder(audio): |
| morse, text = decode_morse_from_audio(audio) |
| alphabet_html = generate_alphabet_html(text) |
| return morse, text, alphabet_html |
| |
| # Gradio UI with Blocks |
| with gr.Blocks(title="Morse Code Decoder") as demo: |
| gr.Markdown("# Morse Code Decoder") |
| gr.Markdown("Speak or play Morse code into your microphone to decode it live!") |
| |
| with gr.Row(): |
| audio_input = gr.Audio(source="microphone", type="numpy", streaming=True, label="Live Audio Input") |
| |
| with gr.Row(): |
| with gr.Column(): |
| morse_output = gr.Textbox(label="Detected Morse Code", interactive=False) |
| text_output = gr.Textbox(label="Decoded Text", interactive=False) |
| with gr.Column(): |
| alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)") |
| |
| # Event listener for streaming audio |
| audio_input.stream( |
| fn=stream_morse_decoder, |
| inputs=[audio_input], |
| outputs=[morse_output, text_output, alphabet_display], |
| _js="() => { return [navigator.mediaDevices.getUserMedia({ audio: true })];" |
| ) |
| |
| # Launch the app |
| demo.launch() |
| ''' |