# Writeup: The Devil's Diagram

## Metadata

- **Category:** Forensics / Signal Analysis
- **Difficulty:** Medium
- **Author:** Serrac
- **Files Provided:** `evidence_4b.wav`

## Description (Player Facing)

> **Subject:** Evidence Item #4B - "The St. Jude's Tapes"
> **Background:**
> St. Jude’s Asylum was shuttered in 1988 after the "incident" in the basement ward. Last night, urban explorers found an old medical XY-plotter plugged into a dead outlet. It was moving on its own.
> They recorded the sound of the machine screeching in the dark. It seems to be trying to draw something.
> **Objective:** Decipher the audio to see what the machine drew.

## Solution

### Step 1: Initial Reconnaissance

The player opens `evidence_4b.wav` in an audio editor (e.g., Sonic Visualizer or Audacity).

- **First observation:** It is a **Stereo** file. The left and right ears hear different patterns. This suggests independent data streams for two channels (Likely X and Y coordinates).

![1](imgs/image-1.png)

### Step 2: Spectral Analysis

The player switches to a **Spectrogram View**. (Here we can see the two channels)

![2](imgs/image-2.png)

- **Visual:** We see a continuous stream of varying pitches, but crucially, the signal is **[Frequency Modulated (FM)](https://en.wikipedia.org/wiki/Frequency_modulation)**. The lines move up and down in frequency over time.

![3](imgs/image-3.png)

- **First observation:** The frequencies bounce between a specific range (**600 Hz** to **4000 Hz**). (1)
- **Second observation:** There are occasional vertical gaps (silence) where the signal drops out completely. (2)

![4](imgs/image-4.png)

- **Deduction:** This is an analog vector drawing.
- **Left Channel** = X-Axis Position (mapped to pitch)
- **Right Channel** = Y-Axis Position (mapped to pitch)
- **Pitch:** Low Pitch = 0% Coordinate, High Pitch = 100% Coordinate.
- **Silence:** Pen Up (Stop drawing).

- **Deduction 1:** The machine is clearly writing text, as the movement from left to right matches typical text writing direction.
- **Deduction 2:** The presence of gaps or silence indicates the machine is starting a new letter each time.

### Step 3: Developing the Decoder

The player realizes they cannot decode this manually. They write a script to:

1. **Read the WAV file.**

```python
# 1. Load the file
rate, data = wavfile.read("challenge/evidence_4b.wav")
```

2. **Demodulate the Signal:** Use the **[Hilbert Transform](https://en.wikipedia.org/wiki/Hilbert_transform)** to extract the _Instantaneous Frequency_ (pitch) of both channels.

```python
# 2. Extract Signal (Hilbert Transform)
analytic_x = hilbert(data[:, 0])
analytic_y = hilbert(data[:, 1])

# Calculate frequency: frequency is the rate of change of the phase
freq_x = np.diff(np.unwrap(np.angle(analytic_x)))
freq_y = np.diff(np.unwrap(np.angle(analytic_y)))
```

3. **Detect Pen Lifts (Filter Silence):** If the volume drops below a threshold, stop drawing.

```python
# 3. Filter Silence (Simple "Pen Up" check)
# Only draw when the volume is loud enough (10% of max volume)
amplitude = np.abs(analytic_x[1:])  # Match length with freq array (which is one shorter)
mask = amplitude > (np.max(amplitude) * 0.1)
```

4. **Plot:** Draw the extracted (X, Y) coordinates. _Note: We skip manual normalization here because the Plotter automatically scales the graph._

```python
# 4. Plot (We plot Frequency X vs Frequency Y)
plt.figure(figsize=(10, 10))
plt.scatter(freq_x[mask], freq_y[mask], s=0.1, c='green')  # Apply the mask to ignore silent sections
plt.axis('equal')        # Prevent squashing
plt.gca().invert_yaxis() # Fix SVG coordinate flip (origin is top-left)
plt.show()
```

![5](imgs/image-5.png)
