aboutsummaryrefslogtreecommitdiff
path: root/lib/xbadpcm/uXboxAdpcmDecoder.c
diff options
context:
space:
mode:
authortheuni <theuni-nospam-@xbmc.org>2011-01-24 16:05:21 -0500
committertheuni <theuni-nospam-@xbmc.org>2011-01-24 16:05:21 -0500
commitc51b1189e3d5353e842991f5859ddcea0f73e426 (patch)
treeef2cb8a6184699aa614f3655dca4ce661cdc108e /lib/xbadpcm/uXboxAdpcmDecoder.c
parentbe61ebdc9e897fe40c6f371111724de79ddee8d5 (diff)
Merged cptspiff's code-reshuffle branch.
Squashed commit due to build breakage during code-reshuffle history. Conflicts: xbmc/Util.cpp xbmc/cdrip/CDDARipper.cpp xbmc/filesystem/Directory.cpp xbmc/filesystem/File.cpp
Diffstat (limited to 'lib/xbadpcm/uXboxAdpcmDecoder.c')
-rw-r--r--lib/xbadpcm/uXboxAdpcmDecoder.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/lib/xbadpcm/uXboxAdpcmDecoder.c b/lib/xbadpcm/uXboxAdpcmDecoder.c
new file mode 100644
index 0000000000..f405c42212
--- /dev/null
+++ b/lib/xbadpcm/uXboxAdpcmDecoder.c
@@ -0,0 +1,164 @@
+/*
+ TXboxAdpcmDecoder class
+ (c) 2005 Benjamin Haisch
+
+ Revision 2 with stereo support
+
+###
+ C conversion 0.1.3
+ by Luigi Auriemma
+ e-mail: aluigi@autistici.org
+ web: aluigi.org
+
+ Copyright 2005,2006 Luigi Auriemma
+
+ 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ http://www.gnu.org/licenses/gpl.txt
+*/
+
+#include "uXboxAdpcmDecoder.h"
+
+#define TXboxAdpcmDecoder_delimit(x,h,l) \
+ if(x > h) { \
+ x = h; \
+ } else if(x < l) { \
+ x = l; \
+ }
+
+
+
+typedef struct {
+ int8_t Index;
+ int16_t StepSize;
+ int16_t Predictor;
+} TAdpcmState;
+
+
+
+const static int16_t StepTable[89] = {
+ 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
+};
+
+
+
+const static int8_t IndexTable[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+};
+
+
+
+int TXboxAdpcmDecoder_DecodeSample(int Code, TAdpcmState *State) {
+ int Delta,
+ Result;
+
+ Delta = State->StepSize >> 3;
+ if(Code & 4) Delta += State->StepSize;
+ if(Code & 2) Delta += State->StepSize >> 1;
+ if(Code & 1) Delta += State->StepSize >> 2;
+ if(Code & 8) Delta = -Delta;
+ Result = State->Predictor + Delta;
+ TXboxAdpcmDecoder_delimit(Result, 32767, -32768);
+ State->Index += IndexTable[Code];
+ TXboxAdpcmDecoder_delimit(State->Index, 88, 0);
+ State->StepSize = StepTable[State->Index];
+ State->Predictor = Result;
+ return(Result);
+}
+
+
+
+int TXboxAdpcmDecoder_Decode_Memory(uint8_t *in, int inlen, uint8_t *out, int FChannels) {
+ TAdpcmState FAdpcmState[6];
+ int16_t Buffers[6][8];
+ uint32_t CodeBuf;
+ int i,
+ j,
+ c,
+ outlen;
+
+ inlen = (inlen / XBOX_ADPCM_SRCSIZE) / FChannels;
+
+ for(outlen = 0; inlen--; outlen++) {
+ for(c = 0; c < FChannels; c++) {
+ *out++ = in[0];
+ *out++ = in[1];
+ FAdpcmState[c].Predictor = in[0] | (in[1] << 8); in += 2;
+ FAdpcmState[c].Index = in[0] | (in[1] << 8); in += 2;
+ TXboxAdpcmDecoder_delimit(FAdpcmState[c].Index, 88, 0);
+ FAdpcmState[c].StepSize = StepTable[FAdpcmState[c].Index];
+ }
+ for(i = 0; i < 8; i++) {
+ for(c = 0; c < FChannels; c++) {
+ CodeBuf = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24);
+ in += 4;
+ for(j = 0; j < 8; j++) {
+ Buffers[c][j] = TXboxAdpcmDecoder_DecodeSample(CodeBuf & 15, &FAdpcmState[c]);
+ CodeBuf >>= 4;
+ }
+ }
+ for(j = 0; j < 8; j++) {
+ for(c = 0; c < FChannels; c++) {
+ *out++ = (Buffers[c][j] ) & 0xff;
+ *out++ = (Buffers[c][j] >> 8) & 0xff;
+ }
+ }
+ }
+ }
+
+ return(outlen * XBOX_ADPCM_DSTSIZE * FChannels);
+}
+
+
+
+int TXboxAdpcmDecoder_Decode(FILE *ASource, FILE *ADest, int SourcePos, int SourceSize, int FChannels) {
+ int DestSize;
+ uint8_t in[XBOX_ADPCM_SRCSIZE * 6],
+ out[XBOX_ADPCM_DSTSIZE * 6];
+
+ if(FChannels <= 0) return(0);
+
+ if(SourcePos >= 0) {
+ if(fseek(ASource, SourcePos, SEEK_SET) < 0) return(0);
+ }
+ if(SourceSize > 0) {
+ SourceSize -= (SourceSize % XBOX_ADPCM_SRCSIZE);
+ SourceSize = (SourceSize / XBOX_ADPCM_SRCSIZE) / FChannels;
+ }
+
+ for(DestSize = 0; SourceSize; SourceSize--) {
+ if(!fread(in, sizeof(in), 1, ASource)) break;
+ DestSize += TXboxAdpcmDecoder_Decode_Memory(in, sizeof(in), out, FChannels);
+ if(!fwrite(out, sizeof(out), 1, ADest)) break;
+ }
+
+ return(DestSize);
+}
+
+
+
+int TXboxAdpcmDecoder_guess_output_size(int SourceSize) {
+ return((SourceSize / XBOX_ADPCM_SRCSIZE) * XBOX_ADPCM_DSTSIZE);
+}
+