Spaces:
Sleeping
Sleeping
File size: 5,513 Bytes
495ab87 85d57e6 427d509 0c2ec94 e17912f 7d8a53d 0c2ec94 a4fc946 495ab87 7d8a53d 1bf845b 21a72bc 7d8a53d 21a72bc e17912f 21a72bc 0c2ec94 21a72bc e17912f 21a72bc 7d8a53d e17912f 1bf845b e17912f 0c2ec94 e17912f 7d8a53d 0c2ec94 e17912f 1bf845b e17912f 0c2ec94 e17912f 85d57e6 7d8a53d a4fc946 85d57e6 495ab87 7d8a53d 85d57e6 0c2ec94 85d57e6 495ab87 7d8a53d 64bc281 495ab87 0c2ec94 7d8a53d 46fc6dc 495ab87 7ecfca4 495ab87 64bc281 7ecfca4 d1fd039 7d8a53d 64bc281 7ecfca4 495ab87 85d57e6 495ab87 85d57e6 64bc281 495ab87 96d90f6 495ab87 427d509 85d57e6 495ab87 85d57e6 495ab87 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
import numpy as np
import wave
from scipy.signal import find_peaks
from scipy.fft import fft, fftfreq
import gradio as gr
import tempfile
from PIL import Image
import io
def log_message(message):
print(message)
def smooth_signal(signal, window_len=11):
"""Apply a smoothing filter to the signal to reduce noise."""
if window_len < 3:
return signal
s = np.r_[signal[window_len-1:0:-1], signal, signal[-2:-window_len-1:-1]]
window = np.hanning(window_len)
smoothed = np.convolve(window/window.sum(), s, mode='valid')
return smoothed
def detect_beeps(audio_data, framerate, freq_zero, freq_one, window_size=2048, step_size=512):
log_message("Starting beep detection with sliding window.")
binary_data = bytearray()
num_windows = len(audio_data) // step_size
previous_bit = None
for i in range(0, len(audio_data) - window_size, step_size):
# Get the window of data
window = audio_data[i:i + window_size]
# Perform FFT to detect the dominant frequency in the window
yf = fft(window)
xf = fftfreq(window_size, 1 / framerate)
magnitude = np.abs(yf[:window_size // 2])
dominant_freq = xf[np.argmax(magnitude)]
# Classify based on the dominant frequency
if np.isclose(dominant_freq, freq_zero, atol=10):
current_bit = 0
elif np.isclose(dominant_freq, freq_one, atol=10):
current_bit = 1
else:
continue # Skip if it doesn't match expected frequencies
# Only record the bit if it differs from the previous bit (avoids repetition)
if current_bit != previous_bit:
binary_data.append(current_bit)
log_message(f"Detected bit: {current_bit} (Frequency: {dominant_freq} Hz)")
previous_bit = current_bit
log_message("Finished beep detection.")
return binary_data
def audio_to_binary(audio_file, freq_zero, freq_one):
log_message("Starting audio_to_binary function.")
# Read the audio file
with wave.open(audio_file.name, 'rb') as wav_file:
framerate = wav_file.getframerate()
n_frames = wav_file.getnframes()
audio_data = wav_file.readframes(n_frames)
audio_data = np.frombuffer(audio_data, dtype=np.int16).astype(np.float32)
audio_data = audio_data / np.max(np.abs(audio_data)) # Normalize to [-1, 1]
# Detect beeps and reconstruct binary data
binary_data = detect_beeps(audio_data, framerate, freq_zero, freq_one)
if not binary_data:
return None, "No binary data detected."
# Convert binary list to bytes
bit_accumulator = 0
bit_count = 0
final_binary_data = bytearray()
for bit in binary_data:
bit_accumulator = (bit_accumulator << 1) | bit
bit_count += 1
if bit_count == 8:
final_binary_data.append(bit_accumulator)
bit_count = 0
bit_accumulator = 0
if bit_count > 0:
final_binary_data.append(bit_accumulator << (8 - bit_count))
log_message(f"Extracted binary data: {final_binary_data[:20]}... (truncated for log)")
return final_binary_data
def binary_to_file(binary_data, file_format):
log_message("Starting binary_to_file function.")
temp_file_path = None
if file_format == 'PNG':
try:
image = Image.open(io.BytesIO(binary_data))
with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as temp_file:
image.save(temp_file, format='PNG')
temp_file_path = temp_file.name
log_message("Successfully reconstructed PNG file.")
except Exception as e:
log_message(f"Failed to reconstruct PNG file: {e}")
elif file_format == 'TXT':
try:
text_data = binary_data.decode('utf-8', errors='replace')
with tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as temp_file:
temp_file.write(text_data.encode('utf-8'))
temp_file_path = temp_file.name
log_message("Successfully reconstructed TXT file.")
except Exception as e:
log_message(f"Failed to reconstruct TXT file: {e}")
else:
log_message("Unsupported file format.")
return temp_file_path
def process_audio(file, freq_zero, freq_one, file_format):
log_message("Starting process_audio function.")
binary_data = audio_to_binary(file, freq_zero, freq_one)
if not binary_data:
log_message("No binary data was extracted from the audio.")
return None, "No data was extracted from the audio file."
original_file_path = binary_to_file(binary_data, file_format)
if original_file_path is None:
return None, "Error in reconstructing the file."
log_message("Processing complete.")
return original_file_path, "File successfully reconstructed."
gr.Interface(
fn=process_audio,
inputs=[
gr.File(label="Upload Binary WAV File"),
gr.Number(label="Frequency for 0 (Hz)", value=1000),
gr.Number(label="Frequency for 1 (Hz)", value=2000),
gr.Dropdown(choices=['PNG', 'TXT'], label="File Format")
],
outputs=[gr.File(label="Download Original File"), gr.Text(label="Status")],
title="Binary WAV to Original File Decoder",
description="Detect beeps with different frequencies in a binary WAV file to reconstruct the original file."
).launch()
|