/// \file
/// \brief Voice compression and transmission interface
///
/// This file is part of RakNet Copyright 2003 Kevin Jenkins.
///
/// Usage of RakNet is subject to the appropriate license agreement.
/// Creative Commons Licensees are subject to the
/// license found at
/// http://creativecommons.org/licenses/by-nc/2.5/
/// Single application licensees are subject to the license found at
/// http://www.rakkarsoft.com/SingleApplicationLicense.html
/// Custom license users are subject to the terms therein.
/// GPL license users are subject to the GNU General Public
/// License as published by the Free
/// Software Foundation; either version 2 of the License, or (at your
/// option) any later version.

#ifndef __RAK_VOICE_H
#define __RAK_VOICE_H

class RakPeerInterface;
#include "NetworkTypes.h"
#include "PluginInterface.h"
#include "DS_OrderedList.h"

// How many frames large to make the circular buffers in the VoiceChannel structure
#define FRAME_OUTGOING_BUFFER_COUNT 100
#define FRAME_INCOMING_BUFFER_COUNT 100

/// \internal
struct VoiceChannel
{
	PlayerID playerId;
	void *enc_state;
	void *dec_state;
	bool remoteIsShortSampleType;
	unsigned short remoteSampleRate;
	
	// Circular buffer of unencoded sound data read from the user.
	char *outgoingBuffer;
	// Each frame sent to speex requires this many samples, of whatever size you are using.
	int speexOutgoingFrameSampleCount;
	// Index in is bytes.
	// Write index points to the next byte to write to, which must be free.
	unsigned outgoingReadIndex, outgoingWriteIndex;
	bool bufferOutput;
	bool copiedOutgoingBufferToBufferedOutput;
	unsigned short outgoingMessageNumber;

	// Circular buffer of unencoded sound data to be passed to the user.  Each element in the buffer is of size bufferSizeBytes bytes.
	char *incomingBuffer;
	int speexIncomingFrameSampleCount;
	unsigned incomingReadIndex, incomingWriteIndex;	// Index in bytes
	unsigned short incomingMessageNumber;  // The ID_VOICE message number we expect to get.  Used to drop out of order and detect how many missing packets in a sequence

	RakNetTime lastSend;
};
int VoiceChannelComp( const PlayerID &key, VoiceChannel * const &data );

/// \brief Encodes, decodes, and transmits voice data.
/// Voice compression and transmission interface
/// \addtogroup Plugins
class RakVoice : public PluginInterface
{
public:
	RakVoice();
	~RakVoice();

	// --------------------------------------------------------------------------------------------
	// User functions
	// --------------------------------------------------------------------------------------------

	/// \brief Starts RakVoice
	/// \param[in] sampleTypeIsShort true if your sample types are unsigned shorts - otherwise they must be floats
	/// \param[in] speexSampleRate 8000, 16000, or 32000
	/// \param[in] bufferSizeBytes How many bytes long inputBuffer and outputBuffer are in SendFrame and ReceiveFrame are.  Should be your sample size * the number of samples to encode at once.
	void Init(bool sampleTypeIsShort, unsigned short speexSampleRate, unsigned bufferSizeBytes);

	/// Shuts down RakVoice
	void Deinit(void);
	
	/// \brief Opens a channel to another connected system
	/// You will get ID_RAKVOICE_OPEN_CHANNEL_REPLY on success
	/// \param[in] recipient Which system to open a channel to
	void RequestVoiceChannel(PlayerID recipient);

	/// \brief Closes an existing voice channel.
	/// Other system will get ID_RAKVOICE_CLOSE_CHANNEL
	/// \param[in] recipient Which system to close a channel with
	void CloseVoiceChannel(PlayerID recipient);

	/// \brief Closes all existing voice channels
	/// Other systems will get ID_RAKVOICE_CLOSE_CHANNEL
	void CloseAllChannels(void);

	/// \brief Sends voice data to a system on an open channel
	/// \pre \a recipient must refer to a system with an open channel via RequestVoiceChannel
	/// \param[in] recipient The system to send voice data to
	/// \param[in] inputBuffer The voice data.  The size of inputBuffer should be what was specified as bufferSizeBytes in Init
	bool SendFrame(PlayerID recipient, void *inputBuffer);

	/// \brief Gets decoded voice data, from one or more remote senders
	/// \param[out] outputBuffer The voice data.  The size of outputBuffer should be what was specified as bufferSizeBytes in Init
	void ReceiveFrame(void *outputBuffer);

	// --------------------------------------------------------------------------------------------
	// Message handling functions
	// --------------------------------------------------------------------------------------------
	virtual void OnAttach(RakPeerInterface *peer);
	virtual void OnDisconnect(RakPeerInterface *peer);
	virtual void Update(RakPeerInterface *peer);
	virtual PluginReceiveResult OnReceive(RakPeerInterface *peer, Packet *packet);
	virtual void OnCloseConnection(RakPeerInterface *peer, PlayerID playerId);
protected:
	void OnOpenChannelRequest(RakPeerInterface *peer, Packet *packet);
	void OnOpenChannelReply(RakPeerInterface *peer, Packet *packet);
	void OnVoiceData(RakPeerInterface *peer, Packet *packet);
	void OpenChannel(RakPeerInterface *peer, Packet *packet);
	void FreeChannelMemory(PlayerID recipient);
	void FreeChannelMemory(unsigned index);
	void WriteOutputToChannel(VoiceChannel *channel, char *dataToWrite);
	
	RakPeerInterface *rakPeer;
	DataStructures::OrderedList<PlayerID, VoiceChannel*, VoiceChannelComp> voiceChannels;
	bool shortSampleType;
	int sampleRate;
	int sampleSize; // Size of each sample - 2 if shortSampleType==true - 4 otherwise
	unsigned bufferSizeBytes;
	float *bufferedOutput;
	unsigned bufferedOutputCount;
	bool zeroBufferedOutput;
};

#endif


syntax highlighted by Code2HTML, v. 0.9.1