// AudioDecoderSimple.cpp: Audio decoding using "simple" internal decoders.
// 
//   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
//   Free Software Foundation, Inc.
//
// 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 3 of the License, 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; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//


#include "AudioDecoderSimple.h"
#include "AudioResampler.h"
#include "BitsReader.h"
#include "SoundInfo.h"
#include "MediaParser.h" // for AudioInfo definition..
#include "GnashNumeric.h" // for clamp

#include "log.h"

#include <algorithm> // for std::swap

namespace gnash {
namespace media {

// ----------------------------------------------------------------------------
// ADPCMDecoder class
// ----------------------------------------------------------------------------

/// ADPCM decoder utilities
//
/// Algo from http://www.circuitcellar.com/pastissues/articles/richey110/text.htm
/// And also Jansen.
/// Here's another reference: http://www.geocities.com/SiliconValley/8682/aud3.txt
/// Original IMA spec doesn't seem to be on the web :(
///
/// TODO: move in it's own file
///
class ADPCMDecoder {

private:

	// Data from Alexis' SWF reference
	static int _index_update_table_2bits[2];
	static int _index_update_table_3bits[4];
	static int _index_update_table_4bits[8];
	static int _index_update_table_5bits[16];

	static int* s_index_update_tables[4];

	// Data from Jansen.  http://homepages.cwi.nl/~jack/
	// Check out his Dutch retro punk songs, heh heh :)
	static const int STEPSIZE_CT = 89;
	static int s_stepsize[STEPSIZE_CT];


	static void doSample(int n_bits, int& sample, int& stepsize_index, int raw_code)
	{
		assert(raw_code >= 0 && raw_code < (1 << n_bits));

		static const int	HI_BIT = (1 << (n_bits - 1));
		int*	index_update_table = s_index_update_tables[n_bits - 2];

		/* Core of ADPCM. */

		int	code_mag = raw_code & (HI_BIT - 1);
		bool	code_sign_bit = (raw_code & HI_BIT) ? 1 : 0;
		int	mag = (code_mag << 1) + 1;	/* shift in LSB (they do this so that pos & neg zero are different)*/

		int	stepsize = s_stepsize[stepsize_index];

		/* Compute the new sample.  It's the predicted value			*/
		/* (i.e. the previous value), plus a delta.  The delta			*/
		/* comes from the code times the stepsize.  going for			*/
		/* something like: delta = stepsize * (code * 2 + 1) >> code_bits	*/
		int	delta = (stepsize * mag) >> (n_bits - 1);
		if (code_sign_bit) delta = -delta;

		sample += delta;
		sample = clamp<int>(sample, -32768, 32767);

		/* Update our stepsize index.  Use a lookup table. */
		stepsize_index += index_update_table[code_mag];
		stepsize_index = clamp<int>(stepsize_index, 0, STEPSIZE_CT - 1);
	}

	/* Uncompress 4096 mono samples of ADPCM. */
	static std::uint32_t doMonoBlock(std::int16_t** out_data, int n_bits, BitsReader& in, int sample, int stepsize_index)
	{
		/* First sample doesn't need to be decompressed. */
		std::uint32_t sample_count = 1;
		*(*out_data)++ = (std::int16_t) sample;

		while (sample_count < 4096 && in.gotBits(n_bits))
		{
			int	raw_code = in.read_uint(n_bits);
			doSample(n_bits, sample, stepsize_index, raw_code);	/* sample & stepsize_index are in/out params */
			*(*out_data)++ = (std::int16_t) sample;

			sample_count++;
		}	
		return sample_count;
	}


	/* Uncompress 4096 stereo sample pairs of ADPCM. */
	static int doStereoBlock(
			std::int16_t** out_data,	// in/out param
			int n_bits,
			BitsReader& in,
			int left_sample,
			int left_stepsize_index,
			int right_sample,
			int right_stepsize_index
			)
	{
		/* First samples don't need to be decompressed. */
		std::uint32_t sample_count = 2;
		*(*out_data)++ = (std::int16_t) left_sample;
		*(*out_data)++ = (std::int16_t) right_sample;

		unsigned bitsNeeded = n_bits*2;
		while (sample_count < 4096 && in.gotBits(bitsNeeded))
		{														
			int	left_raw_code = in.read_uint(n_bits);
			doSample(n_bits, left_sample, left_stepsize_index, left_raw_code);
			*(*out_data)++ = (std::int16_t) left_sample;

			int	right_raw_code = in.read_uint(n_bits);
			doSample(n_bits, right_sample, right_stepsize_index, right_raw_code);
			*(*out_data)++ = (std::int16_t) right_sample;

			sample_count++;
		}
		return sample_count;
	}

public:

	// Utility function: uncompress ADPCM data from in BitReader to
	// out_data[]. Returns the output samplecount.
	static std::uint32_t adpcm_expand(
		unsigned char* &data,
		BitsReader& in,
		unsigned int insize,
		bool stereo)
	{
		// Read header.
		if ( ! in.gotBits(2) )
		{
			IF_VERBOSE_MALFORMED_SWF(
			log_swferror(_("corrupted ADPCM header"));
			);
			return 0;
		}
		unsigned int n_bits = in.read_uint(2) + 2; // 2 to 5 bits 

		// The compression ratio is 4:1, so this should be enough...
		std::int16_t* out_data = new std::int16_t[insize * 5];
		data = reinterpret_cast<unsigned char *>(out_data);

		std::uint32_t sample_count = 0;

		while ( in.gotBits(22) )
		{
			// Read initial sample & index values.

			int	sample = in.read_sint(16);

			int	stepsize_index = in.read_uint(6);
			assert(STEPSIZE_CT >= (1 << 6));	// ensure we don't need to clamp.

			if (stereo == false)
			{

				if (n_bits == 0) {
					abort();
				} else if (n_bits == 2) {
					sample_count += doMonoBlock(&out_data, 2, in, sample, stepsize_index);
				} else if (n_bits == 3) {
					sample_count += doMonoBlock(&out_data, 3, in, sample, stepsize_index);
				} else if (n_bits == 4) {
					sample_count += doMonoBlock(&out_data, 4, in, sample, stepsize_index);
				} else if (n_bits == 5) {
					sample_count += doMonoBlock(&out_data, 5, in, sample, stepsize_index);
				}
			}
			else
			{
				// Stereo.

				// Got values for left channel; now get initial sample
				// & index for right channel.
				int	right_sample = in.read_sint(16);

				int	right_stepsize_index = in.read_uint(6);
				assert(STEPSIZE_CT >= (1 << 6));	// ensure we don't need to clamp.

				if (n_bits == 0) {
					abort();
				} else if (n_bits == 2) {
					sample_count += doStereoBlock(&out_data, 2, in, sample, stepsize_index, right_sample, right_stepsize_index);
				} else if (n_bits == 3) {
					sample_count += doStereoBlock(&out_data, 3, in, sample, stepsize_index, right_sample, right_stepsize_index);
				} else if (n_bits == 4) {
					sample_count += doStereoBlock(&out_data, 4, in, sample, stepsize_index, right_sample, right_stepsize_index);
				} else if (n_bits == 5) {
					sample_count += doStereoBlock(&out_data, 5, in, sample, stepsize_index, right_sample, right_stepsize_index);
				}

			}
		}
		return sample_count;

	}

};

int ADPCMDecoder::_index_update_table_2bits[2] = { -1,  2 };
int ADPCMDecoder::_index_update_table_3bits[4] = { -1, -1,  2,  4 };
int ADPCMDecoder::_index_update_table_4bits[8] = { -1, -1, -1, -1,  2,  4,  6,  8 };
int ADPCMDecoder::_index_update_table_5bits[16] = { -1, -1, -1, -1, -1, -1, -1, -1, 1,  2,  4,  6,  8, 10, 13, 16 };

int* ADPCMDecoder::s_index_update_tables[4] = {
	ADPCMDecoder::_index_update_table_2bits,
	ADPCMDecoder::_index_update_table_3bits,
	ADPCMDecoder::_index_update_table_4bits,
	ADPCMDecoder::_index_update_table_5bits
};

int ADPCMDecoder::s_stepsize[STEPSIZE_CT] = {
	7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
	19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
	50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
	130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
	337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
	876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
	2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
	5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
	15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};

// ----------------------------------------------------------------------------
// END OF ADPCMDecoder class
// ----------------------------------------------------------------------------

//
// Unsigned 8-bit expansion (128 is silence)
//
// u8_expand allocates the memory for its "data" pointer.
//

static void
u8_expand(unsigned char * &data,
	const unsigned char* input,
	std::uint32_t input_size) // This is also the number of u8bit samples
{
	std::int16_t	*out_data = new std::int16_t[input_size];

	// Convert 8-bit to 16
	const std::uint8_t *inp = input;
	std::int16_t *outp = out_data;
	for (unsigned int i = input_size; i>0; i--) {
		*outp++ = ((std::int16_t)(*inp++) - 128) * 256;
	}
	
	data = (unsigned char *)out_data;
}


AudioDecoderSimple::AudioDecoderSimple(const AudioInfo& info)
	:
	_sampleRate(0),
	_sampleCount(0),
	_stereo(false),
	_is16bit(true)
{
    setup(info);

  	log_debug(_("AudioDecoderSimple: initialized flash codec %s (%d)"),
		(int)_codec, _codec);
}

AudioDecoderSimple::AudioDecoderSimple(const SoundInfo& info)
	:
	_sampleRate(0),
	_sampleCount(0),
	_stereo(false),
	_is16bit(true)
{
    setup(info);

  	log_debug(_("AudioDecoderSimple: initialized flash codec %s (%d)"),
		(int)_codec, _codec);
}


AudioDecoderSimple::~AudioDecoderSimple()
{
}

void
AudioDecoderSimple::setup(const SoundInfo& info)
{
	_codec = info.getFormat();
    switch (_codec)
    {
        case AUDIO_CODEC_ADPCM:
        case AUDIO_CODEC_RAW:
        case AUDIO_CODEC_UNCOMPRESSED:
		    _sampleRate = info.getSampleRate();
		    _sampleCount = info.getSampleCount();
		    _stereo = info.isStereo();
		    _is16bit = info.is16bit();
            break;

        default:
            boost::format err = boost::format(
                _("AudioDecoderSimple: unsupported flash codec %d (%s)"))
                % (int)_codec % _codec;
            throw MediaException(err.str());
	}
}

void
AudioDecoderSimple::setup(const AudioInfo& info)
{
    if (info.type != CODEC_TYPE_FLASH) {
        boost::format err = boost::format(
            _("AudioDecoderSimple: unable to intepret custom audio codec id %s"))
            % info.codec;
        throw MediaException(err.str());
    }

    _codec = static_cast<audioCodecType>(info.codec);
    switch (_codec)
    {
        case AUDIO_CODEC_ADPCM:
        case AUDIO_CODEC_RAW:
        case AUDIO_CODEC_UNCOMPRESSED:
            _sampleRate = info.sampleRate;
            _stereo = info.stereo;
            _is16bit = (info.sampleSize==2); // check this!
            if ( info.sampleSize > 2 ) // troubles...
                log_unimpl("Sample size > 2 in %s sound!", _codec);
            break;

        default:
            boost::format err = boost::format(
                _("AudioDecoderSimple: unsupported flash codec %d (%s)"))
                % (int)_codec % _codec;
            throw MediaException(err.str());
	}
}

std::uint8_t*
AudioDecoderSimple::decode(const std::uint8_t* input, std::uint32_t inputSize,
        std::uint32_t& outputSize, std::uint32_t& decodedBytes)
{

	unsigned char* decodedData = nullptr;
	std::uint32_t outsize = 0;

    switch (_codec) {
	case AUDIO_CODEC_ADPCM:
		{
		//std::uint32_t sample_count = inputSize * ( _stereo ? 1 : 2 ); //(_sampleCount == 0 ? inputSize / ( _stereo ? 4 : 2 ) : _sampleCount);
		BitsReader br(input, inputSize);
		std::uint32_t sample_count = ADPCMDecoder::adpcm_expand(decodedData, br, inputSize, _stereo);
		outsize = sample_count * (_stereo ? 4 : 2);
		}
		break;
	case AUDIO_CODEC_RAW:
		if (_is16bit) {
			// FORMAT_RAW 16-bit is exactly what we want!
			decodedData = new unsigned char[inputSize];
			memcpy(decodedData, input, inputSize);
			outsize = inputSize;
		} else {
			// Convert 8-bit unsigned to 16-bit signed range
			// Allocate as many shorts as there are samples
			u8_expand(decodedData, input, inputSize);
			outsize = inputSize * 2;
		}
		break;
	case AUDIO_CODEC_UNCOMPRESSED:
		// 8- or 16-bit mono or stereo little-endian audio
		// Convert to 16-bit host-endian.
		if (!_is16bit)
		{
			// Convert 8-bit unsigned to 16-bit signed range
			// Allocate as many shorts as there are 8-bit samples
			u8_expand(decodedData, input, inputSize);
			outsize = inputSize * 2;

		} else {
			// Allocate a destination buffer
			// Read 16-bit data into buffer
			decodedData = new unsigned char[inputSize];
			outsize = inputSize;
			
			// Convert 16-bit little-endian data to host-endian.

			// Runtime detection of host endianness costs almost
			// nothing and is less of a continual maintenance headache
			// than compile-time detection.
			union u {
				std::uint16_t s;
				struct {
					std::uint8_t c0;
					std::uint8_t c1;
				} c;
			} u = { 0x0001 };

			switch (u.c.c0) {
				default:	// Impossible
					log_error(_("Host endianness not detected in AudioDecoderSimple"));
					// Just carry on anyway...
				case 0x01:	// Little-endian host: sample is already native.
					// If the input data is the output data, then we probably
					// can't move the data faster than memcpy.
					memcpy((char *)decodedData, input, inputSize);
					break;
				case 0x00:  // Big-endian host
					// Swap sample bytes to get big-endian format.
					assert((inputSize & 1) == 0);

					// Cast the buffers to help the compiler understand that we
					// swapping 16-bit words. This should produce a single-instruction
					// swap for each 16-bit word.
					const std::uint16_t* input16 = reinterpret_cast<const std::uint16_t*>(input);
					std::uint16_t* decodedData16 = reinterpret_cast<std::uint16_t*>(decodedData);
					unsigned inputSize16 = inputSize / sizeof(std::uint16_t);
					for ( unsigned i = 0; i < inputSize16; i++ )
					{
						std::uint16_t sample = input16[i];
						decodedData16[i] = ((sample << 8) & 0xFF00) | ((sample >> 8) & 0x00FF);
					}
					break;
			}
		}
		break;
		default:
		break;
		// ???, this should only decode ADPCM, RAW and UNCOMPRESSED
	}

	std::uint8_t* tmp_raw_buffer = decodedData;
	std::uint32_t tmp_raw_buffer_size = 0;

	// If we need to convert samplerate or/and from mono to stereo...
	if (outsize > 0 && (_sampleRate != 44100 || !_stereo)) {

		std::int16_t* adjusted_data = nullptr;
		int	adjusted_size = 0;
		int sample_count = outsize / (_stereo ? 4 : 2); // samples are of size 2

		// Convert to needed samplerate - this converter only support standard flash samplerates
		AudioResampler::convert_raw_data(&adjusted_data, &adjusted_size,
                tmp_raw_buffer,
                sample_count, 2,  // input sample size is 2 !
				_sampleRate, _stereo,
				44100,  true /* stereo */);

		// Hopefully this wont happen
		if (!adjusted_data) {
			log_error(_("Error in sound sample conversion"));
			delete[] tmp_raw_buffer;
			outputSize = 0;
			decodedBytes = 0;
			return nullptr;
		}

		// Move the new data to the sound-struct
		delete[] tmp_raw_buffer;
		tmp_raw_buffer = reinterpret_cast<std::uint8_t*>(adjusted_data);
		tmp_raw_buffer_size = adjusted_size;

	} else {
		tmp_raw_buffer_size = outsize;
	}

	outputSize = tmp_raw_buffer_size;

	decodedBytes = inputSize;
	return tmp_raw_buffer;
}

} // gnash.media namespace 
} // gnash namespace
