00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
00066
00067
00068 void SonarcAudioSample::GenerateOneTable()
00069 {
00070
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;
00090
00091 if (mode >= 7) {
00092 mode -= 7;
00093 zerospecial = true;
00094 }
00095
00096 while (samplecount) {
00097
00098 while (sourcesize && inputbits <= 24) {
00099 data |= (*source++) << inputbits;
00100 sourcesize--;
00101 inputbits += 8;
00102 }
00103
00104 if (zerospecial && !(data & 0x1)) {
00105 *dest++ = 0x80;
00106 data >>= 1;
00107 inputbits--;
00108 } else {
00109 if (zerospecial) {
00110 data >>= 1;
00111 inputbits--;
00112 }
00113
00114 uint8 lowByte = data & 0xFF;
00115 int ones = OneTable[lowByte];
00116
00117 if (ones == 0) {
00118 data >>= 1;
00119
00120 sint8 sample = data & 0xFF;
00121 sample <<= (7 - mode);
00122 sample >>= (7 - mode);
00123 *dest++ = (uint8)(sample+0x80);
00124 data >>= mode+1;
00125 inputbits -= mode+2;
00126 } else if (ones < 7-mode) {
00127 data >>= ones+1;
00128
00129 sint8 sample = data & 0xFF;
00130 sample <<= (7-mode-ones);
00131 sample &= 0x7F;
00132 if (!(sample & 0x40))
00133 sample |= 0x80;
00134 sample >>= (7-mode-ones);
00135 *dest++ = (uint8)(sample+0x80);
00136 data >>= (mode+ones);
00137 inputbits -= mode+2*ones+1;
00138 } else {
00139 data >>= (7 - mode);
00140
00141 sint8 sample = data & 0xFF;
00142 sample &= 0x7F;
00143 if (!(sample & 0x40))
00144 sample |= 0x80;
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
00161
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
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
00223 uint32 frame_bytes = *(buffer+decomp->pos);
00224 frame_bytes |= (*(buffer+decomp->pos+1)) << 8;
00225
00226
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 };