/*
* Copyright (C) 2008-2013 Team XBMC
* http://xbmc.org
*
* 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 2, 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 XBMC; see the file COPYING. If not, see
* .
*
*/
#ifdef _LINUX
#define __declspec(x)
#define __cdecl
#endif
extern "C"
{
#include "mywav.h"
#include "uXboxAdpcmDecoder.h"
#include
#define GETLENGTH(x,SAMPLERATE,NCH) (((x * 10) / ((SAMPLERATE / 100) * NCH * (16 >> 3)) / XBOX_ADPCM_SRCSIZE) * XBOX_ADPCM_DSTSIZE)
struct ADPCMInfo
{
FILE* f;
mywav_fmtchunk fmt;
unsigned int length;
int data_offset;
char* szInputBuffer;
char* szBuf;
char* szStartOfBuf;
int bufLen;
};
int getwavinfo(ADPCMInfo* info) {
int wavsize;
wavsize = mywav_data(info->f, &info->fmt);
if (info->fmt.dwSamplesPerSec == 0 || info->fmt.wChannels == 0)
return -1;
if(wavsize >= 0) {
if(info->fmt.wFormatTag != 0x0069) {
fseek(info->f,0,SEEK_SET);
return(-1);
}
info->data_offset = ftell(info->f);
} else {
fseek(info->f,0,SEEK_END);
wavsize = ftell(info->f);
fseek(info->f,0,SEEK_SET);
}
info->length = GETLENGTH(wavsize,info->fmt.dwSamplesPerSec,info->fmt.wChannels);
return(wavsize);
}
__declspec(dllexport) void* __cdecl DLL_LoadXWAV(const char* szFileName)
{
ADPCMInfo* info = (ADPCMInfo*)malloc(sizeof(ADPCMInfo));
info->f = fopen(szFileName,"rb");
if (!info->f)
{
free(info);
return NULL;
}
int iResult = getwavinfo(info);
if (iResult == -1)
{
fclose(info->f);
free(info);
return NULL;
}
info->szBuf = (char*)malloc(XBOX_ADPCM_DSTSIZE*info->fmt.wChannels*4);
info->szInputBuffer = (char*)malloc(XBOX_ADPCM_SRCSIZE*info->fmt.wChannels*4);
info->szStartOfBuf = info->szBuf+XBOX_ADPCM_DSTSIZE*info->fmt.wChannels*4;
info->bufLen = XBOX_ADPCM_DSTSIZE*info->fmt.wChannels*4;
return (void*)info;
}
void __declspec(dllexport) DLL_FreeXWAV(void* info)
{
ADPCMInfo* pInfo = (ADPCMInfo*)info;
fclose(pInfo->f);
free(pInfo);
}
int __declspec(dllexport) DLL_Seek(void* info, int pos)
{
ADPCMInfo* pInfo = (ADPCMInfo*)info;
int offs = pInfo->data_offset + ((((pos/ 1000) * pInfo->fmt.dwSamplesPerSec) / XBOX_ADPCM_DSTSIZE) * XBOX_ADPCM_SRCSIZE * pInfo->fmt.wChannels * (16 >> 3));
fseek(pInfo->f,offs,SEEK_SET);
// invalidate buffer
pInfo->szStartOfBuf = pInfo->szBuf+XBOX_ADPCM_DSTSIZE*pInfo->fmt.wChannels*4;
return pos;
}
long __declspec(dllexport) DLL_FillBuffer(void* info, char* buffer, int size)
{
ADPCMInfo* pInfo = (ADPCMInfo*)info;
int iCurrSize = size;
while (iCurrSize > 0)
{
if (pInfo->szStartOfBuf >= pInfo->szBuf+pInfo->bufLen)
{
// Read data into input buffer
int read = fread(pInfo->szInputBuffer,XBOX_ADPCM_SRCSIZE*pInfo->fmt.wChannels,4,pInfo->f);
if (!read)
break;
TXboxAdpcmDecoder_Decode_Memory((uint8_t*)pInfo->szInputBuffer, read*XBOX_ADPCM_SRCSIZE*pInfo->fmt.wChannels, (uint8_t*)pInfo->szBuf, pInfo->fmt.wChannels);
pInfo->szStartOfBuf = pInfo->szBuf;
}
int iCopy=0;
if (iCurrSize > pInfo->szBuf+pInfo->bufLen-pInfo->szStartOfBuf)
iCopy = pInfo->szBuf+pInfo->bufLen-pInfo->szStartOfBuf;
else
iCopy = iCurrSize;
memcpy(buffer,pInfo->szStartOfBuf,iCopy);
buffer += iCopy;
iCurrSize -= iCopy;
pInfo->szStartOfBuf += iCopy;
}
return size-iCurrSize;
}
int __declspec(dllexport) DLL_GetPlaybackRate(void* info)
{
ADPCMInfo* pInfo = (ADPCMInfo*)info;
return pInfo->fmt.dwSamplesPerSec;
}
int __declspec(dllexport) DLL_GetNumberOfChannels(void* info)
{
ADPCMInfo* pInfo = (ADPCMInfo*)info;
return pInfo->fmt.wChannels;
}
int __declspec(dllexport) DLL_GetSampleSize(void* info)
{
ADPCMInfo* pInfo = (ADPCMInfo*)info;
return pInfo->fmt.wBitsPerSample;
}
int __declspec(dllexport) DLL_GetLength(void* info)
{
ADPCMInfo* pInfo = (ADPCMInfo*)info;
return pInfo->length;
}
}