SonarcAudioSample.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2005 The Pentagram team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 #include "pent_include.h"
00019 #include "SonarcAudioSample.h"
00020 #include "IDataSource.h"
00021 
00022 namespace Pentagram {
00023 
00024 bool SonarcAudioSample::GeneratedOneTable = false;
00025 int SonarcAudioSample::OneTable[256];
00026 
00027 SonarcAudioSample::SonarcAudioSample(uint8 *buffer_, uint32 size_) : 
00028         AudioSample(buffer_, size_),
00029         src_offset(0x20)
00030 
00031 {
00032         if (!GeneratedOneTable) GenerateOneTable();
00033 
00034         length = *buffer;
00035         length |= *(buffer+1) << 8;
00036         length |= *(buffer+2) << 16;
00037         length |= *(buffer+3) << 24;
00038 
00039         sample_rate  = *(buffer+4);
00040         sample_rate |= *(buffer+5) << 8;
00041         bits = 8;
00042         stereo = false;
00043 
00044         // Get frame bytes... we need to compensate for 'large' files
00045         uint32 frame_bytes = *(buffer+src_offset);
00046         frame_bytes |= (*(buffer+src_offset+1)) << 8;
00047 
00048         if (frame_bytes == 0x20 && length > 32767) {
00049                 src_offset += 0x100;
00050         }
00051 
00052         // Get Num Frame Samples
00053         frame_size = *(buffer+src_offset+2);
00054         frame_size |= (*(buffer+src_offset+3)) << 8;
00055 
00056 
00057         decompressor_size = sizeof(SonarcDecompData);
00058 }
00059 
00060 SonarcAudioSample::~SonarcAudioSample(void)
00061 {
00062 }
00063 
00064 //
00065 // Sonarc Audio Decompressor
00066 //
00067 
00068 void SonarcAudioSample::GenerateOneTable()
00069 {
00070         // OneTable[x] gives the number of consecutive 1's on the low side of x
00071         for (int i = 0; i < 256; ++i)
00072                 OneTable[i] = 0;
00073 
00074         for (int power = 2; power < 32; power *= 2)
00075                 for (int col = power-1; col < 16; col += power)
00076                         for (int row = 0; row < 16; ++row)
00077                                 OneTable[row*16+col]++;
00078 
00079         for (int i = 0; i < 16; ++i)
00080                 OneTable[i*16+15] += OneTable[i];
00081 }
00082 
00083 void SonarcAudioSample::decode_EC(int mode, int samplecount,
00084                                                 const uint8* source, int sourcesize,
00085                                                 uint8* dest)
00086 {
00087         bool zerospecial = false;
00088         uint32 data = 0;
00089         int inputbits = 0; // current 'fill rate' of data window
00090 
00091         if (mode >= 7) {
00092                 mode -= 7;
00093                 zerospecial = true;
00094         }
00095 
00096         while (samplecount) {
00097                 // fill data window
00098                 while (sourcesize && inputbits <= 24) {
00099                         data |= (*source++) << inputbits;
00100                         sourcesize--;
00101                         inputbits += 8;
00102                 }
00103 
00104                 if (zerospecial && !(data & 0x1)) {
00105                         *dest++ = 0x80; // output zero
00106                         data >>= 1;
00107                         inputbits--;
00108                 } else {
00109                         if (zerospecial) {
00110                                 data >>= 1; // strip one
00111                                 inputbits--;
00112                         }
00113 
00114                         uint8 lowByte = data & 0xFF;
00115                         int ones = OneTable[lowByte];
00116 
00117                         if (ones == 0) {
00118                                 data >>= 1; // strip zero
00119                                 // low byte contains (mode+1) bits of the sample
00120                                 sint8 sample = data & 0xFF;
00121                                 sample <<= (7 - mode);
00122                                 sample >>= (7 - mode); // sign extend
00123                                 *dest++ = (uint8)(sample+0x80);
00124                                 data >>= mode+1;
00125                                 inputbits -= mode+2;
00126                         } else if (ones < 7-mode) {
00127                                 data >>= ones+1; // strip ones and zero
00128                                 // low byte contains (mode+ones) bits of the sample
00129                                 sint8 sample = data & 0xFF;
00130                                 sample <<= (7-mode-ones);
00131                                 sample &= 0x7F;
00132                                 if (!(sample & 0x40))
00133                                         sample |= 0x80; // reconstruct sign bit
00134                                 sample >>= (7-mode-ones); // sign extend
00135                                 *dest++ = (uint8)(sample+0x80);
00136                                 data >>= (mode+ones);
00137                                 inputbits -= mode+2*ones+1;
00138                         } else {
00139                                 data >>= (7 - mode); // strip ones
00140                                 // low byte contains 7 bits of the sample
00141                                 sint8 sample = data & 0xFF;
00142                                 sample &= 0x7F;
00143                                 if (!(sample & 0x40))
00144                                         sample |= 0x80; // reconstruct sign bit
00145                                 *dest++ = (uint8)(sample+0x80);
00146                                 data >>= 7;
00147                                 inputbits -= 2*7-mode;
00148                         }               
00149                 }
00150                 samplecount--;
00151         }
00152 }
00153 
00154 void SonarcAudioSample::decode_LPC(int order, int nsamples,
00155                                                 uint8* dest, const uint8* factors)
00156 {
00157         uint8 *startdest = dest;
00158         dest -= order;
00159 
00160         // basic linear predictive (de)coding
00161         // the errors this produces are fixed by pass1
00162 
00163         for (int i = 0; i < nsamples; ++i) {
00164                 uint8* loopdest = dest++;
00165                 int accum = 0;
00166                 for (int j = order-1; j >= 0; --j) {
00167                         sint8 val1 = (loopdest<startdest)? 0: (*loopdest);
00168                         loopdest++;
00169                         val1 ^= 0x80;
00170                         sint16 val2 = factors[j*2] + (factors[j*2+1]<<8);
00171                         accum += (int)val1 * val2;
00172                 }
00173 
00174                 accum += 0x00000800;
00175                 *loopdest -= (sint8)((accum >> 12) & 0xFF);
00176         }
00177 }
00178 
00179 
00180 int SonarcAudioSample::audio_decode(const uint8* source, uint8* dest)
00181 {
00182         int size = source[0] + (source[1] << 8);
00183         uint16 checksum = 0;
00184         for (int i = 0; i < size/2; ++i) {
00185                 uint16 val = source[2*i] + (source[2*i+1] << 8);
00186                 checksum ^= val;
00187         }
00188                    
00189         if (checksum != 0xACED) return -1;
00190 
00191         int order = source[7];
00192         int mode = source[6]-8;
00193         int samplecount = source[2] + (source[3] << 8);
00194 
00195         decode_EC(mode, samplecount,
00196                                 source+8+2*order, size-8-2*order,
00197                                 dest);
00198         decode_LPC(order, samplecount, dest, source+8);
00199 
00200 
00201         return 0;
00202 }
00203 
00204 //
00205 // AudioSample Interface
00206 //
00207 
00208 void SonarcAudioSample::initDecompressor(void *DecompData) const
00209 {
00210         SonarcDecompData *decomp = reinterpret_cast<SonarcDecompData *>(DecompData);
00211         decomp->pos = src_offset;
00212         decomp->sample_pos = 0;
00213 }
00214 
00215 uint32 SonarcAudioSample::decompressFrame(void *DecompData, void *samples) const
00216 {
00217         SonarcDecompData *decomp = reinterpret_cast<SonarcDecompData *>(DecompData);
00218 
00219         if (decomp->pos == buffer_size) return 0;
00220         if (decomp->sample_pos == length) return 0;
00221 
00222         // Get Frame size
00223         uint32 frame_bytes  = *(buffer+decomp->pos);
00224         frame_bytes |= (*(buffer+decomp->pos+1)) << 8;
00225 
00226         // Get Num Frame Samples
00227         uint32 frame_samples  = *(buffer+decomp->pos+2);
00228         frame_samples |= (*(buffer+decomp->pos+3)) << 8;
00229 
00230         audio_decode(buffer+decomp->pos, reinterpret_cast<uint8*>(samples));
00231 
00232         decomp->pos += frame_bytes;
00233         decomp->sample_pos += frame_samples;
00234 
00235         return frame_samples;
00236 }
00237 
00238 void SonarcAudioSample::rewind(void *DecompData) const
00239 {
00240         SonarcDecompData *decomp = reinterpret_cast<SonarcDecompData *>(DecompData);
00241         decomp->pos = src_offset;
00242         decomp->sample_pos = 0;
00243 }
00244 
00245 };

Generated on Fri Jul 27 22:27:40 2007 for pentagram by  doxygen 1.4.7