/********************************************************

         PCM audio decoder
	 Copyright 2000 Eugene Kuznetsov  (divx@euro.ru)

*********************************************************/

#include <stdio.h>
#include <string.h>
#include "pcm.h"
PCM_Decoder::PCM_Decoder(const CodecInfo& info, const WAVEFORMATEX* wf)
    :IAudioDecoder(info, wf)
{
}

int PCM_Decoder::Convert(const void* in_data, size_t in_size,
			 void* out_data, size_t out_size,
			 size_t* size_read, size_t* size_written)
{
    if (!in_data || !out_data)
	return -1;

    size_t csize = (in_size < out_size) ? in_size : out_size;

    memcpy(out_data, in_data, csize);

    if (size_read)
	*size_read = csize;
    if (size_written)
	*size_written = csize;

    return 0;
}
/*

int PCM_Decoder::Init(WAVEFORMATEX* wf, void* extension)
{
    if(wf==0)
	return -1;
    memcpy(&m_wstr, wf, sizeof(WAVEFORMATEX));
    if(m_wstr.nSamplesPerSec==0)
	return -1;
    if((m_wstr.wBitsPerSample!=8) && (m_wstr.wBitsPerSample!=16))
    {
	printf("PCM with %d bits per sample is not supported\n");
	return -1;
    }
    m_resampler=48000*m_wstr.nChannels/m_wstr.nSamplesPerSec;
    if(m_resampler==0)
	return -1;
    m_status=1;
    return 0;
}
int PCM_Decoder::decode_frames(unsigned char* in_data, unsigned char* out_data,
	    unsigned& in_size, unsigned out_size, out_format* format)
{
    int num_samples;

    if(m_status!=1)
	goto fail;
    if(!in_data)
	goto fail;
    if(!out_data)
	goto fail;
	
    num_samples=in_size*8/m_wstr.wBitsPerSample;
    if(out_size<2*m_resampler*num_samples)
	num_samples=out_size/2/m_resampler;
    
    if(m_resampler>1)// need to raise frequency
	if(m_wstr.wBitsPerSample==8)
	    raise_and_resample_8to16((char*)in_data, (short*)out_data, num_samples);
	else
	    resample((short*)in_data, (short*)out_data, num_samples);    
    else
	if(m_wstr.wBitsPerSample==8)
	    raise_8to16((char*)in_data, (short*)out_data, num_samples);
	else
	    copy((short*)in_data, (short*)out_data, num_samples);    
	    
    if(format)
    {
	format->is_stereo=m_wstr.nChannels-1;
	format->freq=m_wstr.nSamplesPerSec/m_wstr.nChannels*m_resampler;
	format->valid=OUT_FORMAT_VALID;
    }		
    in_size=num_samples*m_wstr.wBitsPerSample/8;
    return num_samples*m_resampler*2;
fail:		
    in_size=0;
    return 0;
}

void PCM_Decoder::raise_8to16(const char* src_data, short* dest_data, int samples)
{
    for(int i=0; i<samples; i++)
	*dest_data++=((*src_data++)<<8)^0x8000;
}	
void PCM_Decoder::raise_and_resample_8to16(const char* src_data, short* dest_data, int samples)
{
    int i,j;
    if(m_wstr.nChannels==1)
    {
        for(i=0; i<samples; i++)
	{
	    for(j=1; j<m_resampler; j++)
		*dest_data++=((*src_data)<<8)^0x8000;
	    *dest_data++=((*src_data++)<<8)^0x8000;
	}
    }
    else
    {	    
        for(i=0; i<samples; i++)
	{
	    for(j=0; j<m_resampler; j++)
	    {
		const char* temp=src_data;
		for(int i=0; i<m_wstr.nChannels; i++)
		    *dest_data++=((*src_data++)<<8)^0x8000;
		src_data=temp;	    
	    }
	    src_data+=m_wstr.nChannels;
	}
    }

}
*/
