/*
 * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
 * Copyright (C) 2016 Furrtek
 * 
 * This file is part of PortaPack.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#include "proc_audiotx.hpp"
#include "portapack_shared_memory.hpp"
#include "sine_table.hpp"
#include "audio_output.hpp"
#include "lfsr_random.hpp"

#include <cstdint>

uint32_t lfsr(uint32_t v) {

	enum {
		length         = 31,
		tap_0          = 31,
		tap_1          = 18,
		shift_amount_0 = 12,
		shift_amount_1 = 12,
		shift_amount_2 =  8
	};

	const lfsr_word_t zero = 0;
	v = (
		(
			v << shift_amount_0
		) | (
			(
				(v >> (tap_0 - shift_amount_0)) ^
				(v >> (tap_1 - shift_amount_0))
			) & (
				~(~zero << shift_amount_0)
			)
		)
	);
	v = (
		(
			v << shift_amount_1
		) | (
			(
				(v >> (tap_0 - shift_amount_1)) ^
				(v >> (tap_1 - shift_amount_1))
			) & (
				~(~zero << shift_amount_1)
			)
		)
	);
	v = (
		(
			v << shift_amount_2
		) | (
			(
				(v >> (tap_0 - shift_amount_2)) ^
				(v >> (tap_1 - shift_amount_2))
			) & (
				~(~zero << shift_amount_2)
			)
		)
	);
	
	return v;
}

void AudioTXProcessor::execute(const buffer_c8_t& buffer){
	
	for (size_t i = 0; i<buffer.count; i++) {
		sample = (sine_table_f32[(aphase & 0x03FF0000)>>18]*127);	//(int8_t)lfsr(sample + i);

		if (bc & 0x40)
			aphase += 60000;
		else
			aphase += 90000;
			
		//FM
		frq = sample * 2500;
		
		phase = (phase + frq);
		sphase = phase + (256<<16);

		re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*127);
		im = (sine_table_f32[(phase & 0x03FF0000)>>18]*127);
		
		buffer.p[i] = {(int8_t)re,(int8_t)im};
	}
	
	bc++;
}
