mirror of
https://github.com/MacPaw/XADMaster.git
synced 2025-08-29 03:23:48 +02:00
153 lines
4.3 KiB
C
153 lines
4.3 KiB
C
/*
|
|
* RARAudioDecoder.c
|
|
*
|
|
* Copyright (c) 2017-present, MacPaw Inc. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301 USA
|
|
*/
|
|
#include "RARAudioDecoder.h"
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
static inline int iabs(int x) { return x<0?-x:x; }
|
|
|
|
int DecodeRAR20Audio(RAR20AudioState *state,int *channeldelta,int delta)
|
|
{
|
|
state->count++;
|
|
|
|
state->delta4=state->delta3;
|
|
state->delta3=state->delta2;
|
|
state->delta2=state->lastdelta-state->delta1;
|
|
state->delta1=state->lastdelta;
|
|
|
|
int predbyte=((
|
|
8*state->lastbyte+
|
|
state->weight1*state->delta1+
|
|
state->weight2*state->delta2+
|
|
state->weight3*state->delta3+
|
|
state->weight4*state->delta4+
|
|
state->weight5**channeldelta
|
|
)>>3)&0xff;
|
|
|
|
int byte=predbyte-delta&0xff;
|
|
|
|
int prederror=((int8_t)delta)<<3;
|
|
state->error[0]+=iabs(prederror);
|
|
state->error[1]+=iabs(prederror-state->delta1);
|
|
state->error[2]+=iabs(prederror+state->delta1);
|
|
state->error[3]+=iabs(prederror-state->delta2);
|
|
state->error[4]+=iabs(prederror+state->delta2);
|
|
state->error[5]+=iabs(prederror-state->delta3);
|
|
state->error[6]+=iabs(prederror+state->delta3);
|
|
state->error[7]+=iabs(prederror-state->delta4);
|
|
state->error[8]+=iabs(prederror+state->delta4);
|
|
state->error[9]+=iabs(prederror-*channeldelta);
|
|
state->error[10]+=iabs(prederror+*channeldelta);
|
|
|
|
*channeldelta=state->lastdelta=(int8_t)(byte-state->lastbyte);
|
|
state->lastbyte=byte;
|
|
|
|
if((state->count&0x1f)==0)
|
|
{
|
|
int minerror=state->error[0];
|
|
int minindex=0;
|
|
for(int i=1;i<11;i++)
|
|
{
|
|
if(state->error[i]<minerror)
|
|
{
|
|
minerror=state->error[i];
|
|
minindex=i;
|
|
}
|
|
}
|
|
|
|
memset(state->error,0,sizeof(state->error));
|
|
|
|
switch(minindex)
|
|
{
|
|
case 1: if(state->weight1>=-16) state->weight1--; break;
|
|
case 2: if(state->weight1<16) state->weight1++; break;
|
|
case 3: if(state->weight2>=-16) state->weight2--; break;
|
|
case 4: if(state->weight2<16) state->weight2++; break;
|
|
case 5: if(state->weight3>=-16) state->weight3--; break;
|
|
case 6: if(state->weight3<16) state->weight3++; break;
|
|
case 7: if(state->weight4>=-16) state->weight4--; break;
|
|
case 8: if(state->weight4<16) state->weight4++; break;
|
|
case 9: if(state->weight5>=-16) state->weight5--; break;
|
|
case 10: if(state->weight5<16) state->weight5++; break;
|
|
}
|
|
}
|
|
|
|
return byte;
|
|
}
|
|
|
|
int DecodeRAR30Audio(RAR30AudioState *state,int delta)
|
|
{
|
|
state->delta3=state->delta2;
|
|
state->delta2=state->lastdelta-state->delta1;
|
|
state->delta1=state->lastdelta;
|
|
|
|
int predbyte=((
|
|
8*state->lastbyte+
|
|
state->weight1*state->delta1+
|
|
state->weight2*state->delta2+
|
|
state->weight3*state->delta3
|
|
)>>3)&0xff;
|
|
|
|
int byte=predbyte-delta&0xff;
|
|
|
|
int prederror=((int8_t)delta)<<3;
|
|
state->error[0]+=iabs(prederror);
|
|
state->error[1]+=iabs(prederror-state->delta1);
|
|
state->error[2]+=iabs(prederror+state->delta1);
|
|
state->error[3]+=iabs(prederror-state->delta2);
|
|
state->error[4]+=iabs(prederror+state->delta2);
|
|
state->error[5]+=iabs(prederror-state->delta3);
|
|
state->error[6]+=iabs(prederror+state->delta3);
|
|
|
|
state->lastdelta=(int8_t)(byte-state->lastbyte);
|
|
state->lastbyte=byte;
|
|
|
|
if((state->count&0x1f)==0)
|
|
{
|
|
int minerror=state->error[0];
|
|
int minindex=0;
|
|
for(int i=1;i<7;i++)
|
|
{
|
|
if(state->error[i]<minerror)
|
|
{
|
|
minerror=state->error[i];
|
|
minindex=i;
|
|
}
|
|
}
|
|
|
|
memset(state->error,0,sizeof(state->error));
|
|
|
|
switch(minindex)
|
|
{
|
|
case 1: if(state->weight1>=-16) state->weight1--; break;
|
|
case 2: if(state->weight1<16) state->weight1++; break;
|
|
case 3: if(state->weight2>=-16) state->weight2--; break;
|
|
case 4: if(state->weight2<16) state->weight2++; break;
|
|
case 5: if(state->weight3>=-16) state->weight3--; break;
|
|
case 6: if(state->weight3<16) state->weight3++; break;
|
|
}
|
|
}
|
|
|
|
state->count++;
|
|
|
|
return byte;
|
|
}
|