Crypto / Miscmedium
Notation
by Pavel Knespl (capyplivl)
A melody in notation.wav where each message event is a chord, not a single note. A C-major scale and arpeggio intro declares the 7-tone alphabet C D E F G A B; each message chord is a subset of those tones read as a 7-bit ASCII byte with C as the least significant bit.
Solve
- Segment events on RMS energy. The first 24 events are single pure tones (the scale up and down plus the tonic arpeggio). Any monophonic pitch tracker disagrees with itself on the message events, which signals polyphony.
- FFT a message event: multiple fundamentals sound at once (for example
261.6 + 293.6 + 392.0 + 493.9 Hz= C4 D4 G4 B4), versus a single peak for an intro note. The message events are chords. - The intro fixes the alphabet to the seven naturals
C D E F G A B. For each message chord, run a Goertzel filter at each octave-4 fundamental and threshold presence at 35% of the loudest tone. - Pack the seven booleans into a byte with C = bit 0 and B = bit 6, then read as ASCII (LSB-first; MSB-first is garbage). The first chord
C D G Bgives0b1010011 = 0x53 = 'S', matching the flag prefix.import wave, array, math import numpy as np w = wave.open("notation.wav","rb"); sr = w.getframerate() a = np.array(array.array("h", w.readframes(w.getnframes())), float)/32768 hop = int(sr*0.005) env = np.array([np.sqrt(np.mean(a[i:i+hop]**2)+1e-12) for i in range(0,len(a),hop)]) on = env > env.max()*0.10 runs, i = [], 0 while i < len(on): if on[i]: j = i while j < len(on) and on[j]: j += 1 if (j-i)*5 > 60: runs.append((i*hop, j*hop)) i = j else: i += 1 msg = runs[24:] NOTES = [("C",261.63),("D",293.66),("E",329.63),("F",349.23),("G",392.00),("A",440.00),("B",493.88)] def goertzel(seg, f): coeff = 2*math.cos(2*math.pi*f/sr); s1=s2=0.0 for x in seg: s0 = x + coeff*s1 - s2; s2, s1 = s1, s0 return math.sqrt(s1*s1 + s2*s2 - coeff*s1*s2)/len(seg) out = [] for s,e in msg: seg = a[int(s+(e-s)*0.3):int(s+(e-s)*0.7)] mags = [goertzel(seg,f) for _,f in NOTES] thr = max(mags)*0.35 out.append(chr(sum((1<<b) for b in range(7) if mags[b] > thr))) print("".join(out))$ python3 solve.py SVIUSCG{b1n4ry_mus1c_1s_c00l}
Flag: SVIUSCG{b1n4ry_mus1c_1s_c00l}