#ifndef SEEN_NOISE_H
#define SEEN_NOISE_H

#include <allegro.h>
#include "heap.h"

/* Define the size of a sample (must be unsigned short or unsigned char) */
typedef unsigned short sample_t;

/* Single note to be played */
struct note_t {
	int val;		/* Value of note (value 0 = A, 220 Hz) */
	double dur;		/* Duration value (i.e. quarter note = 0.25) */
};

/* Instrument capable of playing pitched notes */
struct voice_t;
struct instrument_t {
	double (*func)(struct voice_t*);
	double sustain;		/* Staccato/legato factor */
};

/* Currently playing sound */
struct voice_t {
	double freq;		/* Frequency of voice */
	double period;		/* Period of the waveform */
	int step;		/* Number of current sample */
	int dur;		/* Total number of samples in voice */
	double vol;		/* 0-1 volume */
	double pan;		/* 0-1 panning value */
	struct instrument_t* instrument;
};

/* Sequence of notes */
struct channel_t {
	struct note_t* notes;	/* Array of notes */
	int num_notes;		/* Total number of notes in song */

	int note_idx;		/* Index of currently playing note */
	int remain;		/* Time remaining until the next note */
	int repeat;		/* Number of times to repeat (-1 = infinity) */

	double vol;		/* 0-1 volume */
	double pan;		/* 0-1 panning value */
	struct instrument_t* instrument;
	int tempo;		/* Number of beats per second */
	double beat_note;	/* Duration value of note with the beat */
	int transpose;		/* Number of half steps to transpose */
};

/* Collection of channels and sounds */
struct player_t {
	struct heap_t* channels;/* Heap of channels in song */
	struct heap_t* voices;	/* Heap of currently playing voices */

	AUDIOSTREAM* stream;	/* Allegro audio stream */
	int max_voices;		/* Maximum number of simultaneous voices */
	int buf_length;		/* Number of samples in buffer */
	int bits;		/* Number of bits per sample */
	int stereo;		/* Stereo? */
	int rate;		/* Number of samples per second */
	int vol;		/* 0-255 volume for audio stream */
	int pan;		/* 0-255 panning value for audio stream */
	sample_t max_sample;	/* The highest possible value for a sample */

	void** exp_buf;		/* Hack for expiring channels and voices */
	int num_exp;		/* The number of expirations to perform */
};

/* Player functions */
extern struct player_t* create_player(int length, int bits, int stereo,
		int rate, int vol, int pan, int max_voices);
extern void destroy_player(struct player_t* player);
extern void add_channel(struct player_t* player, struct note_t* notes,
		int num_notes, int repeat, double vol, double pan,
		struct instrument_t* instrument, int tempo, double beat_note,
		int transpose);
extern void add_channel_struct(struct player_t* player,
		struct channel_t* channel);
extern int fill_buffer(struct player_t* player);

/* The only globals! */
extern struct channel_t channels[];
extern int num_channels;

#endif

