/*
   Risc os Digital Signal Processor
   (C) 2014-2019 A.V.Bartram

  THIS SOFTWARE IS PROVIDED  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  IN NO EVENT SHALL A.V.Bartram BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL
  ,SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO
  ),PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS
  ;OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#ifndef SYNTH_H
#define SYNTH_H

extern unsigned int _toneTable[];
extern unsigned int _sampleFreqTable[];

typedef unsigned long DWORD;
typedef unsigned short WORD;


#define ADSR_FLAG_PITCH  0x1
#define ADSR_FLAG_FILTER 0x2
#define ADSR_FLAG_PWM    0x4

#define ASR_FLAG_AMP     0x8
#define ASR_FLAG_PITCH   0x10
#define ASR_FLAG_FILTER  0x20
#define ASR_FLAG_PWM     0x40

#define ASR_FLAG_LOOP    0x80

// Waveforms
#define WAVEFORM_SAW      0x20
#define WAVEFORM_TRIANGLE 0x40
#define WAVEFORM_NOISE    0x80

// Implemented to allow 'target' level to take precdence over step limit
#define MAX_STEPS 99999

// 16 channels
#define MAX_POLY 16
#define MAX_POLY_MASK (MAX_POLY-1)

typedef unsigned char U8;
typedef unsigned int  U32;
typedef signed char   S8;

typedef struct _BUFFER_TYPE
{
	short *m_data;
	size_t m_size;
	size_t m_dataLength;
     unsigned int m_loop;
     unsigned int m_loopBack;
} BUFFER_TYPE;

typedef struct _BUFFER_TYPE32
{
	int *m_data;
	size_t m_size;
	size_t m_dataLength;
} BUFFER_TYPE32;

#define MAX_BUFFER (256*1024)
typedef struct _DCO
{
	BUFFER_TYPE m_sample;
	unsigned int m_osc_lookup;
	// If sample playback m_osc_lookup > 64k then update
	// most significant word.
	// Sample playback position = m_sample_lookup_msw * 64k + m_osc_lookup>>14
    unsigned int m_sample_lookup_msw;

} DCO;


typedef enum
{
	adsr_attack,
	adsr_decay,
	adsr_sustain,
	adsr_release
} ADSR_TYPE;


typedef struct _LPF
{
	int pole1;
	int pole2;
	int cutoff;
	int resonance;
	int resUp; // resonance logarithmic multiplier
} LPF;

typedef struct _ENVELOPE_ADSR
{
	unsigned int m_flags;
	unsigned int m_stage;
	unsigned int m_stageCounter;
	unsigned int m_counterSpeed;
	unsigned int m_speedCounter;
	unsigned int m_endState;    /* The last state with any data i.e. there may be zero step states in between     */
	int          m_stepADSR[4]; /* Amount of change in each phase (Sustain is always 0)*/
                 // 1 = 65536 for ADSR.
	unsigned int m_numADSR[4]; // Number of steps in 1/100ths of a second
    int          m_targetADSR[4]; // If non-zero override num steps
                 // For legacy mode implements wrap around of 3 stage envelope
                 // For ADSR implements target that overrides num steps
                 // TODO : Re-state for legacy mode
    int          m_accumulator[4];
                 // stores fractional values. Add on val / 65536
                 // Only remainder i.e. mod 65536 is saved between
                 // cycles
                 // n.b. Not used by 3 stage envelope
                 // i.e. this is used to calculate what step is added QED
} ENVELOPE_ADSR;

typedef struct _EFFECT_DLINE
{
	signed int m_line[65536]; // TODO check whether 32 bit faster than 16 bit
	U32          m_play;
	U32          m_record;
	int          m_feedback;
} EFFECT_DLINE;

typedef struct _EFFECT_SDLINE
{
	signed int          m_line[4096];
	U32          m_play;
	U32          m_record;
} EFFECT_SDLINE; // Short delay line

typedef struct _EFFECT_CHORUS
{
	EFFECT_SDLINE m_line;
	int          m_lfo;
	int          m_lfoRate;
	int          m_lfoPolarity;
	int          m_lfoSpeed;
	int          m_lfoDepth;
	LPF          m_filter;
} EFFECT_CHORUS;

typedef struct _EFFECT_DRIVE
{
	int m_gain;
	LPF m_lpf;
} EFFECT_DRIVE;

typedef struct _EFFECT_WARM
{
	EFFECT_SDLINE m_line1;
	EFFECT_SDLINE m_line2;
} EFFECT_WARM;

typedef struct _EFFECT_REVERB
{
    EFFECT_DLINE m_line[10];
    U32 m_numLine;
	LPF m_lpf;
} EFFECT_REVERB;


#define EFFECT_MODE_RESER1 0x00000001 // reserved
#define EFFECT_MODE_RESER2 0x00000002
#define EFFECT_MODE_RESET  0x00000004
#define EFFECT_MODE_DELAY  0x00000008
#define EFFECT_MODE_CHORUS 0x00000010
#define EFFECT_MODE_REVERB 0x00000020
#define EFFECT_MODE_DRIVE  0x00000040


typedef struct _EFFECT_PROC
{
	U32          m_mode;

	// Registers and cache
	EFFECT_DLINE  m_delayLine;
	EFFECT_CHORUS m_chorus;
	EFFECT_WARM   m_warm;
	EFFECT_DRIVE  m_drive;
    EFFECT_REVERB m_reverb;

} EFFECTS_PROC;

//
typedef struct
{
    char           m_name[16];
    unsigned short m_wave;
    unsigned char  m_options;
    unsigned char  m_steptime;
    unsigned char  m_cutoff;
    unsigned char  m_res;
    unsigned char  m_asrStepsAttack;
    unsigned char  m_asrStepsSustain;
    unsigned char  m_asrStepsRelease;
    signed char    m_asrAttackDelta;
    signed char    m_asrSustainDelta;
    signed char    m_asrReleaseDelta;
    int            m_attack;
    int            m_decay;
    int            m_sustain;
    int            m_release;
} INSTRUMENT_TABLE;

typedef struct
{
    signed short *m_data;
    unsigned int m_length;
    unsigned int m_loop;
    unsigned int m_loopBack;
} SAMPLE_TABLE;


#define CHANNEL_MODE_SYNC            0x10
#define CHANNEL_MODE_MUTE            0x20
#define CHANNEL_MODE_XOR             0x40
#define CHANNEL_MODE_QUEUE           0x80

typedef struct _SYNTH_CHANNEL
{
	U8  m_mode;
	DCO m_dco;
	int m_tone;
	U8  m_wave; // 0 indicates sample playback
	int m_amp;
	int m_pulse_width; // TODO move to DCO
	LPF m_lpf;
	ENVELOPE_ADSR m_adr; // TODO fix typo - should be 3 Stage envelope
	ENVELOPE_ADSR m_adsr;
	unsigned int m_prng;
	unsigned int m_noise_throttle;
	int centisecond;
    int m_volumeLeft; // Cheap implementation of pan
    int m_volumeRight; // e.g. SOUND P field = 9,A,B,C,D,E,F = left
                       //                      1,2,3,4,5,6,7 = right
                       // *RPAN = 8 bit value

} SYNTH_CHANNEL;

// Implements a simple ring buffer
// The CModule API atomically increments the m_writer after a channel
// entry has been added.
// Once the current sound has finished playing, the queue will be read
// and m_reader will advance.
// So when the channel is idle, then the channel queue is checked
// As only the reader is read by the interrupt and the writer is modified
// by the API and both operations are commited after the data is written
// there is no race condition.
// If m_writer is 2 behind m_reader the queue is viewed as full.
// Because m_reader may be reading the last entry and if writer = reader
// the queue is empty.
#define MAX_QUEUE_BUFFER 365
typedef struct _CHANNEL_QUEUE
{
  int m_writer;
  int m_reader;
  SYNTH_CHANNEL m_ringBuffer[MAX_QUEUE_BUFFER];
} CHANNEL_QUEUE;

typedef struct _AUDIO_RECORDER
{
  int m_size;
  int m_position;
  int m_on;
  signed short *m_left;
  signed short *m_right;
} AUDIO_RECORDER;

typedef struct _RISC_SYNTH
{
  SYNTH_CHANNEL m_channel[MAX_POLY];
  // This is over allocated - it is always a much smaller number.
  // which the interrupt requests. RISC OS has very low audio latency.
  signed int  m_fillBufferLeft[44100]; // To allow compressor to limit volume
  signed int  m_fillBufferRight[44100];
  unsigned char m_effectChannel[MAX_POLY];
  signed int  m_effectBuffer[44100];

  signed short  m_lastChannel[2][44100];

  unsigned int* tonetable;
  unsigned int* sampleFreqTable;
  INSTRUMENT_TABLE m_instrument[256];
  SAMPLE_TABLE     m_sample[256];

  EFFECTS_PROC m_effects;

  CHANNEL_QUEUE m_queue[MAX_POLY];

  AUDIO_RECORDER m_recorder;

  int m_compressor; // If level goes over 80% of volume
                    // Reduces level to ensure its less than 80%
                    // compressor is by default very fast
  int m_compressorSpeed;
  int m_compressorCounter;

  int m_masterVolume;


     int debug;
} RISC_SYNTH;

extern unsigned int toneTable[];

extern int sampleFreqTable[];

#define OSC_SIZE 722534400 // i.e. 44100 * 16384 (2 ^ 14  ... the fixed point offset in base 2) - I could go to 2^16 without overflow
#define MAX_TONE        365
#define MAX_AMP         100
#define MAX_FILTER      64 // Consider widening to 256 (128 may be max in practice)
#define MAX_PULSE       361267200
#define SWITCH_TOP_AMP  32000
#define SWITCH_BASE_AMP -32000
// frequency modulation. Axiom = step is proportional to frequency. So if frequency increases by 2. So does step.
// Time is constant. 44100 = 1 second. Envelopes describe time in 100ths of a second.
// So every 441 iterations we can trigger the envelope, thus reducing its footprint by 100 times.
// The envelope may change the pulse width. That's fine too.

#define CENTISECOND 441

#define FIFTH_OF_A_SECOND (CENTISECOND * 20)

// For efficiency - writing whole synth in very small function with 1 loop

// This would be a cool SID like VST actually....

// I think allowing the option for more than 1 modulation source is better..
// e.g. 3 stage env and 4 stage env could modulate pitch.
// The ring mod on the sound channel is processed after this function.
// It is an MS-20 XOR effect. Nice and cheap to run.
// So in effect there are at least 256 possible waves (more in practice due to modulation via tone and XOR).
// multiplied by cutoff & resonance and via envelope modulation. So in practice this should be millions or billions
// of tones.

#define HALF_SAMPLE_RATE    22050
#define SAMPLE_RATE         44100
#define QUARTER_SAMPLE_RATE 11025

#define FILTER_LIMITER 0xff
#define PWM_LIMITER    22050

DWORD buffer_fill(void* param, signed short* buffer_base, signed short* buffer_end,
                 DWORD flags);


#endif
