In short, it takes any audio file (the longer the better) and a message you want to encode. It turns the message into binary and produces high-pitched beeps (over 20 kHz, outside normal human hearing range) to combine with the base audio file. The output would sound just like the original to a human, but has inaudible beeping that can be picked up by a decoder to extract the original binary.
DEMO - https://www.youtube.com/watch?v=FybIR58LiDw
Key Features:
- Encode messages into WAV files using frequency-shift encoding
- Decode messages by analyzing the high-frequency spectrum
- Live spectrogram visualization showing up to 24 kHz frequency range
- Interactive web UI with drag-and-drop file upload
- Real-time audio playback with waveform and spectrogram display
- Steganography: Hide messages in plain sight within audio files
- Audio forensics: Analyze spectrograms for hidden data
- Learning tool: Understand digital signal processing and frequency encoding
- Data hiding: Embed metadata or messages in audio streams without degrading quality
- Backend: Python 3.8+, pip
- Frontend: Node.js 16+, npm
- Both the backend and frontend must be running simultaneously
- Install Python dependencies:
cd hoya_backend
pip install -r requirements.txt- Create a
.envfile inhoya_backendwith API keys (optional for full features):
ELEVENLABS_API_KEY=your_key_here
GOOGLE_API_KEY=your_key_here- Start the Flask server:
cd src
python app.pyThe server runs on http://localhost:5000
- Install dependencies:
cd hoya_frontend
npm install- Start the development server:
npm run devOpen http://localhost:5173 (or the URL shown in terminal)
- Navigate to the Encode tab
- Select or drag a
.wavaudio file - Enter the message you want to hide
- Click Encode
- Download the encoded audio file (sounds identical to the original)
- Navigate to the Decode tab
- Select or drag an encoded
.wavfile - Click Decode
- The hidden message appears in the output area
- The file also loads into the player for inspection
The spectrogram below the player shows the frequency content of the audio in real-time:
- X-axis: Time
- Y-axis: Frequency (up to 24 kHz)
- Color intensity: Signal strength
- You can see the encoding pattern at 22-23 kHz as a distinct horizontal band
Encoding Process (encode.py):
- Read input WAV file
- Apply bandstop filter to clear the 22-23 kHz frequency range
- Convert message text to binary (8 bits per character)
- Generate a carrier wave at 22.5 kHz with amplitude modulated by the binary message
- Mix the modulated signal with the filtered audio
- Write output as WAV file
Key parameters:
- Message frequency band: 22-23 kHz
- Control signal: 21-22 kHz (marks message boundaries)
- Bitrate: 64 bits/second
- Sample rate: 44.1 kHz or 48 kHz
Decoding Process (decode.py):
- Read encoded WAV file
- Extract 22-23 kHz band with bandpass filter
- Calculate signal envelope using Hilbert transform
- Divide signal into 64 chunks per second
- Measure each chunk's amplitude (threshold-based binary detection)
- Convert binary back to ASCII characters
Key Components:
- AudioController: Centralized audio state management and playback control
- PlayerBar: Play/pause controls, seek slider, time display
- EncodeForm: File upload and message input for encoding
- DecodeForm: File upload for decoding with message output
- Spectrogram: Real-time frequency visualization using WaveSurfer.js
- AudioColorBackground: Dynamic background that responds to audio playback
Tech Stack:
- React 19 with TypeScript
- Tailwind CSS for styling
- Vite for bundling
- WaveSurfer.js for audio visualization
- Framer Motion for animations
hoya26/
├── hoya_backend/
│ ├── src/
│ │ ├── app.py # Flask server with API endpoints
│ │ ├── encode.py # Audio encoding logic
│ │ └── decode.py # Audio decoding logic
│ ├── files/ # Temporary audio files storage
│ └── requirements.txt # Python dependencies
├── hoya_frontend/
│ ├── src/
│ │ ├── audio/
│ │ │ └── AudioController.tsx # Audio state management
│ │ ├── components/
│ │ │ ├── PlayerBar.tsx # Playback controls
│ │ │ ├── EncodeForm.tsx # Encoding UI
│ │ │ ├── DecodeForm.tsx # Decoding UI
│ │ │ ├── Spectrogram.tsx # Frequency visualization
│ │ │ └── ...other components
│ │ ├── App.tsx # Main app component
│ │ └── index.css # Global styles
│ ├── package.json # Node dependencies
│ └── vite.config.ts # Vite configuration
└── README.md # This file
Encodes a message into a WAV file.
Request:
curl -X POST http://localhost:5000/encode \
-F "file=@audio.wav" \
-F "message=Hello World"Response: WAV file (binary)
Decodes a message from a WAV file.
Request:
curl -X POST http://localhost:5000/decode \
-F "file=@encoded.wav"Response:
{
"message": "Hello World"
}Generates random audio using text-to-speech (requires API keys).
Response: WAV file (binary)
The encoding uses amplitude modulation of a high-frequency carrier:
- Message binary: "A" →
01000001in binary - Carrier: 22.5 kHz sine wave
- Modulation: For each bit:
1→ Full amplitude sine wave0→ Silence (zero amplitude)
- Frequency: 22-23 kHz is chosen because:
- Beyond typical human hearing range (cuts off ~20 kHz)
- Below Nyquist frequency for standard 44.1 kHz audio
- Doesn't interfere with the original audio content
Example: 8 bits at 64 bits/second = 8/64 = 0.125 seconds per character
Backend won't start:
- Ensure Python 3.8+ is installed:
python --version - Check Flask is installed:
pip list | grep Flask - Verify port 5000 is available
Frontend won't connect to backend:
- Confirm backend is running on
localhost:5000 - Check browser console for CORS errors
- Ensure both are on the same machine or adjust CORS settings in
app.py
Decoded message is garbled:
- The input audio may be too low quality or compressed
- Try with a longer audio file for better signal-to-noise ratio
- Ensure the file was encoded with the same version of this tool
Spectrogram is blank:
- Wait a moment for WaveSurfer.js to load the audio
- Check browser console for JavaScript errors
- Ensure the WAV file is valid
npm run buildnpm run lintThe Flask server runs in debug mode by default, auto-reloading on file changes.
See hoya_backend/requirements.txt and hoya_frontend/package.json for complete lists.
Key backend packages:
- Flask: Web framework
- librosa: Audio processing
- scipy: Signal filtering
- soundfile: WAV file I/O
Key frontend packages:
- React: UI framework
- WaveSurfer.js: Audio visualization
- Tailwind CSS: Styling
Current limitations:
- Message length limited by audio file duration
- Only supports WAV files
- No error correction (bit errors = message corruption)
- Single message per file
Potential improvements:
- Error correction codes (Hamming, Reed-Solomon)
- Support for MP3, FLAC, and other formats
- Multiple independent messages in different frequency bands
- Adaptive bitrate based on SNR
- Message encryption before encoding
- Least Significant Bit encoding for higher efficiency and harder detection
See LICENSE file for details.
Built at HoyaHacks 2026 by Ruslan Akmyradov, Yafee Khan, Daniel Yi, and Eric Zou.
For issues, questions, or feature requests, please open an issue on the project repository or check the documentation in this README.



