import hashlib
import json
import math
from pathlib import Path
import struct
import wave

root = Path(__file__).resolve().parents[1]
out = root / 'samples'
out.mkdir(exist_ok=True)
sample_rate = 44100
tone_samples = 18522
gap_samples = 7056
notes = [60, 62, 64, 67, 69, 67, 64, 60]
expected = []
mono = []
for i, note in enumerate(notes):
    frequency = 440 * 2 ** ((note - 69) / 12)
    expected.append({'midi': note, 'start_seconds': len(mono) / sample_rate,
                     'duration_seconds': tone_samples / sample_rate})
    for n in range(tone_samples):
        envelope = min(1, n / 441, (tone_samples - 1 - n) / 441)
        mono.append(round(0.55 * envelope * math.sin(2 * math.pi * frequency * n / sample_rate) * 32767))
    mono.extend([0] * gap_samples)

def write_wav(name, samples):
    path = out / name
    with wave.open(str(path), 'wb') as wav:
        wav.setnchannels(1)
        wav.setsampwidth(2)
        wav.setframerate(sample_rate)
        wav.writeframes(struct.pack('<' + 'h' * len(samples), *samples))
    return {'path': "/samples/" + path.name, 'bytes': path.stat().st_size,
            'sha256': hashlib.sha256(path.read_bytes()).hexdigest(),
            'samples': len(samples), 'duration_seconds': len(samples) / sample_rate}

melody = write_wav('known-eight-note-melody.wav', mono)
chord_samples = []
for n in range(len(mono)):
    within_tone = n % (tone_samples + gap_samples)
    if within_tone >= tone_samples:
        chord_samples.append(0)
        continue
    envelope = min(1, within_tone / 441, (tone_samples - 1 - within_tone) / 441)
    chord = sum(math.sin(2 * math.pi * 440 * 2 ** ((note - 69) / 12) * within_tone / sample_rate)
                for note in [60, 64, 67]) / 3
    chord_samples.append(round(0.55 * envelope * chord * 32767))
chords = write_wav('simultaneous-c-major-chords.wav', chord_samples)
record = {'created_for': 'Midilot WAV-to-MIDI independent controlled test',
          'source': 'Locally synthesized sine waves; not a human recording',
          'sample_rate': sample_rate, 'channels': 1, 'bits_per_sample': 16,
          'melody': melody, 'expected_melody': expected,
          'chords': chords, 'expected_simultaneous_midi_pitches': [60, 64, 67],
          'observed_conversion': None}
(out / 'wav-reference.json').write_text(json.dumps(record, indent=2) + '\n')
print(json.dumps({'melody': melody, 'chords': chords}, indent=2))
