#/usr/bin/env python3
import numpy as np


from scipy.io import wavfile
from scipy.misc import imread
from matplotlib import pyplot as plt


WIDTH = 640
HEIGHT = 496

OUTPUT_RATE = 48000

VIS_START_FREQ = 1900
VIS_START_DUR = 300
VIS_PAUSE = 10
VIS_ONE_FREQ = 1100
VIS_ZERO_FREQ = 1300
VIS_BIT_DUR = 30
# Code 97 + even parity, lsb first
VIS_BITS = [True, False, False, False, False, True, True, True]

SYNC_FREQ = 1200
SYNC_DUR = 20

PORCH_DUR = 2.080

PIXEL_DUR = 0.382

COLOR_LOW_FREQ = 1500
COLOR_HIGH_FREG = 2300

phase_acc = 0


def sine_gen(freq):
    global phase_acc
    phase_inc = (2 * np.pi / OUTPUT_RATE) * freq
    phase_acc += phase_inc
    if phase_acc > 2 * np.pi:
        phase_acc = phase_acc - 2 * np.pi

    return np.sin(phase_acc)


samples_left = 0
def make_tone(freq, duration, data):
    global samples_left
    samples = duration / 1000 * OUTPUT_RATE + samples_left
    sample_count = int(samples)
    samples_left = samples - sample_count

    for i in range(0, sample_count):
        data += [sine_gen(freq)]




def make_vis(samples):
    make_tone(VIS_START_FREQ, VIS_START_DUR, samples)
    make_tone(SYNC_FREQ, VIS_PAUSE, samples)
    make_tone(VIS_START_FREQ, VIS_START_DUR, samples)

    make_tone(SYNC_FREQ, VIS_BIT_DUR, samples)
    for bit in VIS_BITS:
        if bit:
            make_tone(VIS_ONE_FREQ, VIS_BIT_DUR, samples)
        else:
            make_tone(VIS_ZERO_FREQ, VIS_BIT_DUR, samples)

    make_tone(SYNC_FREQ, VIS_BIT_DUR, samples)


def main():

    image = imread('testcard.png', mode='YCbCr')

    samples = []

    make_vis(samples)

    for y in range(0, int(HEIGHT/2)):
        make_tone(SYNC_FREQ, SYNC_DUR, samples)
        make_tone(COLOR_LOW_FREQ, PORCH_DUR, samples)

        for x in range(0, WIDTH):
            lum = image[y*2, x, 0] / 255.0
            freq = COLOR_LOW_FREQ + lum * (COLOR_HIGH_FREG - COLOR_LOW_FREQ)
            make_tone(freq, PIXEL_DUR, samples)

        for x in range(0, WIDTH):
            cr0 = image[y*2, x, 2] / 255.0
            cr1 = image[y*2 + 1, x, 2] / 255.0
            cr = (cr0 + cr1) / 2
            freq = COLOR_LOW_FREQ + cr * (COLOR_HIGH_FREG - COLOR_LOW_FREQ)
            make_tone(freq, PIXEL_DUR, samples)

        for x in range(0, WIDTH):
            cb0 = image[y*2, x, 1] / 255.0
            cb1 = image[y*2 + 1, x, 1] / 255.0
            cb = (cb0 + cb1) / 2
            freq = COLOR_LOW_FREQ + cb * (COLOR_HIGH_FREG - COLOR_LOW_FREQ)
            make_tone(freq, PIXEL_DUR, samples)

        for x in range(0, WIDTH):
            lum = image[y*2 + 1, x, 0] / 255.0
            freq = COLOR_LOW_FREQ + lum * (COLOR_HIGH_FREG - COLOR_LOW_FREQ)
            make_tone(freq, PIXEL_DUR, samples)


    samples = np.array(samples)

    samples = samples * 0.75 * 32767
    samples = np.int16(samples)

    wavfile.write("output.wav", OUTPUT_RATE, samples)

if __name__ == '__main__':
    main()
