import gradio as gr import numpy as np import tempfile from scipy.io import wavfile import speech_recognition as sr import soundfile as sf # Morse code dictionary 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()} # Timing constants DIT_DURATION = 0.1 DAH_DURATION = 3 * DIT_DURATION SPACE_DURATION = 7 * DIT_DURATION CHAR_SPACE = DIT_DURATION SAMPLE_RATE = 44100 # Decode Morse from audio beeps 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() # Decode Morse from text 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() # Encode text to Morse def text_to_morse(text): text = text.upper() return " ".join(MORSE_CODE_DICT.get(char, "?") for char in text if char in MORSE_CODE_DICT) # Generate Morse audio 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 # 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: return "Speech recognition failed" # Highlight alphabet def generate_alphabet_html(text): html = "
" for char in MORSE_CODE_DICT.keys(): color = "red" if char in text.upper() else "black" html += f"{char}: {MORSE_CODE_DICT[char]}" if char in "AEIMQUZ": html += "
" html += "
" return html # Encoding functions def encode_text_to_morse(text): morse = text_to_morse(text) audio = generate_morse_audio(morse) return morse, text, generate_alphabet_html(text), audio def encode_speech_to_morse(audio_path): text = speech_to_text(audio_path) morse = text_to_morse(text) audio = generate_morse_audio(morse) return morse, text, generate_alphabet_html(text), audio # Decoding functions def decode_morse_text(morse_text): text = decode_morse_from_text(morse_text) audio = generate_morse_audio(morse_text) return morse_text, text, generate_alphabet_html(text), audio def decode_morse_speech(audio_path): transcribed = speech_to_text(audio_path).replace("dit", ".").replace("dah", "-").replace("slash", "/") text = decode_morse_from_text(transcribed) audio = generate_morse_audio(transcribed) return transcribed, text, generate_alphabet_html(text), audio def decode_morse_audio(audio_path): morse, text = decode_morse_from_audio(audio_path, is_file=True) return morse, text, generate_alphabet_html(text), None def decode_live_morse(audio_data): morse, text = decode_morse_from_audio(audio_data, is_file=False) return morse, text, generate_alphabet_html(text), None # Gradio UI with gr.Blocks(title="Morse Code Converter") as demo: gr.Markdown("# Morse Code Converter") gr.Markdown("Encode to Morse or decode Morse from text, speech, or audio!") 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") 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=encode_text_to_morse, 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") 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=encode_speech_to_morse, 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") 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=decode_morse_text, 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") 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=decode_morse_speech, 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") 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=decode_morse_audio, inputs=[morse_audio_input], outputs=[morse_audio_morse_out, morse_audio_text_out, morse_audio_alphabet]) with gr.Tab("Decode Live Morse"): live_audio_input = gr.Audio(type="numpy", label="Live Morse Input (Use Microphone)", streaming=True) 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=decode_live_morse, inputs=[live_audio_input], outputs=[live_morse_out, live_text_out, live_alphabet]) demo.launch()