nightfury commited on
Commit
549ee96
·
verified ·
1 Parent(s): f22bd8f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +219 -0
app.py CHANGED
@@ -26,6 +26,225 @@ SPACE_DURATION = 7 * DIT_DURATION # 700ms for word space
26
  CHAR_SPACE = DIT_DURATION # Space between characters
27
  SAMPLE_RATE = 44100 # Standard audio sample rate
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  # Decode Morse from audio
30
  def decode_morse_from_audio(audio_data):
31
  if audio_data is None:
 
26
  CHAR_SPACE = DIT_DURATION # Space between characters
27
  SAMPLE_RATE = 44100 # Standard audio sample rate
28
 
29
+ # Decode Morse from audio (live or uploaded)
30
+ def decode_morse_from_audio(audio_data, is_file=False):
31
+ if audio_data is None:
32
+ return "", ""
33
+
34
+ if is_file:
35
+ # For uploaded files, audio_data is a file path
36
+ sample_rate, data = wavfile.read(audio_data)
37
+ else:
38
+ # For live streaming, audio_data is (sample_rate, data)
39
+ sample_rate, data = audio_data
40
+
41
+ if len(data.shape) > 1:
42
+ data = data.mean(axis=1)
43
+ data = data / np.max(np.abs(data))
44
+
45
+ threshold = 0.1
46
+ signal = data > threshold
47
+ morse_code, decoded_text = "", ""
48
+ i = 0
49
+
50
+ while i < len(signal) - int(SAMPLE_RATE * DIT_DURATION):
51
+ if signal[i]:
52
+ start = i
53
+ while i < len(signal) and signal[i]:
54
+ i += 1
55
+ duration = (i - start) / sample_rate
56
+ morse_code += "-" if duration >= DAH_DURATION else "."
57
+ else:
58
+ start = i
59
+ while i < len(signal) and not signal[i]:
60
+ i += 1
61
+ pause = (i - start) / sample_rate
62
+ if pause >= SPACE_DURATION and morse_code:
63
+ decoded_text += " "
64
+ morse_code = ""
65
+ elif pause >= DIT_DURATION and morse_code:
66
+ decoded_text += MORSE_TO_CHAR.get(morse_code, "?")
67
+ morse_code = ""
68
+ i += 1
69
+
70
+ if morse_code:
71
+ decoded_text += MORSE_TO_CHAR.get(morse_code, "?")
72
+ return morse_code, decoded_text.strip()
73
+
74
+ # Convert text to Morse code
75
+ def text_to_morse(text):
76
+ text = text.upper()
77
+ morse = " ".join(MORSE_CODE_DICT.get(char, "?") for char in text if char in MORSE_CODE_DICT)
78
+ return morse
79
+
80
+ # Generate Morse code audio and save to temporary file
81
+ def generate_morse_audio(morse):
82
+ audio = []
83
+ frequency = 750 # Hz for Morse tone
84
+
85
+ for symbol in morse.split():
86
+ if symbol == "/":
87
+ audio.extend([0] * int(SAMPLE_RATE * SPACE_DURATION))
88
+ else:
89
+ for char in symbol:
90
+ duration = DAH_DURATION if char == "-" else DIT_DURATION
91
+ t = np.linspace(0, duration, int(SAMPLE_RATE * duration), False)
92
+ tone = 0.5 * np.sin(2 * np.pi * frequency * t)
93
+ audio.extend(tone)
94
+ audio.extend([0] * int(SAMPLE_RATE * DIT_DURATION)) # Space between dits/dahs
95
+ audio.extend([0] * int(SAMPLE_RATE * CHAR_SPACE)) # Space between characters
96
+
97
+ audio = np.array(audio, dtype=np.float32)
98
+ with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as temp_file:
99
+ sf.write(temp_file.name, audio, SAMPLE_RATE, format="wav")
100
+ temp_file_path = temp_file.name
101
+ return temp_file_path
102
+
103
+ # Speech to text
104
+ def speech_to_text(audio_path):
105
+ recognizer = sr.Recognizer()
106
+ with sr.AudioFile(audio_path) as source:
107
+ audio_data = recognizer.record(source)
108
+ try:
109
+ return recognizer.recognize_google(audio_data)
110
+ except sr.UnknownValueError:
111
+ return "Could not understand audio"
112
+ except sr.RequestError:
113
+ return "Speech recognition service unavailable"
114
+
115
+ # Highlight alphabet in UI
116
+ def generate_alphabet_html(decoded_text):
117
+ html = "<div style='font-family: monospace; font-size: 16px;'>"
118
+ for char in MORSE_CODE_DICT.keys():
119
+ color = "red" if char in decoded_text.upper() else "black"
120
+ html += f"<span style='color: {color}; margin: 5px;'>{char}: {MORSE_CODE_DICT[char]}</span>"
121
+ if char in "AEIMQUZ":
122
+ html += "<br>"
123
+ html += "</div>"
124
+ return html
125
+
126
+ # Combined processing function
127
+ def process_input(text=None, speech=None, live_audio=None, upload_audio=None):
128
+ morse, decoded_text, audio_output = "", "", None
129
+
130
+ if text: # Text input
131
+ morse = text_to_morse(text)
132
+ decoded_text = text
133
+ audio_output = generate_morse_audio(morse)
134
+
135
+ elif speech: # Speech input
136
+ text = speech_to_text(speech)
137
+ morse = text_to_morse(text)
138
+ decoded_text = text
139
+ audio_output = generate_morse_audio(morse)
140
+
141
+ elif live_audio: # Live audio input
142
+ morse, decoded_text = decode_morse_from_audio(live_audio, is_file=False)
143
+
144
+ elif upload_audio: # Uploaded audio file
145
+ morse, decoded_text = decode_morse_from_audio(upload_audio, is_file=True)
146
+
147
+ alphabet_html = generate_alphabet_html(decoded_text)
148
+ return morse, decoded_text, alphabet_html, audio_output
149
+
150
+ # Gradio UI with Blocks
151
+ with gr.Blocks(title="Morse Code Decoder & Generator") as demo:
152
+ gr.Markdown("# Morse Code Decoder & Generator")
153
+ gr.Markdown("Decode live or uploaded Morse audio, or generate Morse from text/speech!")
154
+
155
+ with gr.Tab("Decode Live Audio"):
156
+ audio_input = gr.Audio(type="numpy", label="Live Audio Input (Use Microphone)", streaming=True)
157
+ with gr.Row():
158
+ with gr.Column():
159
+ morse_output = gr.Textbox(label="Detected Morse Code", interactive=False)
160
+ text_output = gr.Textbox(label="Decoded Text", interactive=False)
161
+ alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)")
162
+
163
+ audio_input.stream(
164
+ fn=process_input,
165
+ inputs=[audio_input],
166
+ outputs=[morse_output, text_output, alphabet_display, gr.Audio(visible=False)],
167
+ )
168
+
169
+ with gr.Tab("Generate from Text"):
170
+ text_input = gr.Textbox(label="Enter Text", placeholder="Type here...")
171
+ generate_btn = gr.Button("Generate Morse")
172
+ with gr.Row():
173
+ with gr.Column():
174
+ morse_gen_output = gr.Textbox(label="Morse Code", interactive=False)
175
+ text_gen_output = gr.Textbox(label="Original Text", interactive=False)
176
+ gen_alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)")
177
+ audio_playback = gr.Audio(label="Morse Audio Playback", interactive=False)
178
+
179
+ generate_btn.click(
180
+ fn=process_input,
181
+ inputs=[text_input],
182
+ outputs=[morse_gen_output, text_gen_output, gen_alphabet_display, audio_playback]
183
+ )
184
+
185
+ with gr.Tab("Generate from Speech"):
186
+ speech_input = gr.Audio(type="filepath", label="Speak Your Text (Record Audio)")
187
+ speech_btn = gr.Button("Convert Speech to Morse")
188
+ with gr.Row():
189
+ with gr.Column():
190
+ morse_speech_output = gr.Textbox(label="Morse Code", interactive=False)
191
+ text_speech_output = gr.Textbox(label="Transcribed Text", interactive=False)
192
+ speech_alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)")
193
+ speech_audio_playback = gr.Audio(label="Morse Audio Playback", interactive=False)
194
+
195
+ speech_btn.click(
196
+ fn=process_input,
197
+ inputs=[speech_input],
198
+ outputs=[morse_speech_output, text_speech_output, speech_alphabet_display, speech_audio_playback]
199
+ )
200
+
201
+ with gr.Tab("Decode from Audio Upload"):
202
+ upload_input = gr.Audio(type="filepath", label="Upload Morse Audio File (WAV)")
203
+ upload_btn = gr.Button("Decode Morse")
204
+ with gr.Row():
205
+ with gr.Column():
206
+ morse_upload_output = gr.Textbox(label="Detected Morse Code", interactive=False)
207
+ text_upload_output = gr.Textbox(label="Decoded Text", interactive=False)
208
+ upload_alphabet_display = gr.HTML(label="Morse Alphabet (Highlighted)")
209
+
210
+ upload_btn.click(
211
+ fn=process_input,
212
+ inputs=[upload_input],
213
+ outputs=[morse_upload_output, text_upload_output, upload_alphabet_display, gr.Audio(visible=False)]
214
+ )
215
+
216
+ # Launch the app
217
+ demo.launch()
218
+
219
+ '''
220
+ import gradio as gr
221
+ import numpy as np
222
+ import io
223
+ import tempfile
224
+ import os
225
+ from scipy.io import wavfile
226
+ import speech_recognition as sr
227
+ import soundfile as sf
228
+
229
+ # Morse code dictionary (ITU standard)
230
+ MORSE_CODE_DICT = {
231
+ 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.',
232
+ 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..',
233
+ 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.',
234
+ 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-',
235
+ 'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--',
236
+ '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..',
237
+ '9': '----.', '0': '-----', ' ': '/'
238
+ }
239
+ MORSE_TO_CHAR = {v: k for k, v in MORSE_CODE_DICT.items()}
240
+
241
+ # Morse code timing (in seconds)
242
+ DIT_DURATION = 0.1 # 100ms for dit
243
+ DAH_DURATION = 3 * DIT_DURATION # 300ms for dah
244
+ SPACE_DURATION = 7 * DIT_DURATION # 700ms for word space
245
+ CHAR_SPACE = DIT_DURATION # Space between characters
246
+ SAMPLE_RATE = 44100 # Standard audio sample rate
247
+
248
  # Decode Morse from audio
249
  def decode_morse_from_audio(audio_data):
250
  if audio_data is None: