00001 #include "asset.h"
00002 #include "byteorder.h"
00003 #include "file.h"
00004 #include "filebase.h"
00005 #include "sizes.h"
00006
00007 int FileBase::ima4_step[89] =
00008 {
00009 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
00010 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
00011 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
00012 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
00013 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
00014 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
00015 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
00016 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
00017 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
00018 };
00019
00020 int FileBase::ima4_index[16] =
00021 {
00022 -1, -1, -1, -1, 2, 4, 6, 8,
00023 -1, -1, -1, -1, 2, 4, 6, 8
00024 };
00025
00026
00027
00028 int FileBase::init_ima4()
00029 {
00030 ima4_block_samples = 1024;
00031 ima4_block_size = (ima4_block_samples - 1) * asset->channels / 2 + 4;
00032 last_ima4_samples = 0;
00033 last_ima4_indexes = 0;
00034 }
00035
00036 int FileBase::delete_ima4()
00037 {
00038 if(last_ima4_samples) delete last_ima4_samples;
00039 if(last_ima4_indexes) delete last_ima4_indexes;
00040 last_ima4_samples = 0;
00041 last_ima4_indexes = 0;
00042 }
00043
00044 int FileBase::ima4_decode_block(int16_t *output, unsigned char *input)
00045 {
00046 return 0;
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 }
00090
00091 int FileBase::ima4_decode_sample(int *predictor, int nibble, int *index, int *step)
00092 {
00093 int difference, sign;
00094
00095
00096 *index += ima4_index[nibble];
00097
00098 if(*index < 0) *index = 0;
00099 else
00100 if(*index > 88) *index = 88;
00101
00102
00103 sign = nibble & 8;
00104 nibble = nibble & 7;
00105
00106
00107 difference = *step >> 3;
00108 if(nibble & 4) difference += *step;
00109 if(nibble & 2) difference += *step >> 1;
00110 if(nibble & 1) difference += *step >> 2;
00111
00112
00113 if(sign)
00114 *predictor -= difference;
00115 else
00116 *predictor += difference;
00117
00118 if(*predictor > 32767) *predictor = 32767;
00119 else
00120 if(*predictor < -32768) *predictor = -32768;
00121
00122
00123 *step = ima4_step[*index];
00124
00125 return 0;
00126 }
00127
00128
00129 int FileBase::ima4_encode_block(unsigned char *output, int16_t *input, int step, int channel)
00130 {
00131 int i, j, nibble;
00132 int16_t *input_end = input + ima4_block_size;
00133 int16_t *subinput;
00134 int buffer_advance = asset->channels;
00135
00136 if(!last_ima4_samples)
00137 {
00138 last_ima4_samples = new int[asset->channels];
00139 for(i = 0; i < asset->channels; i++) last_ima4_samples[i] = 0;
00140 }
00141
00142 if(!last_ima4_indexes)
00143 {
00144 last_ima4_indexes = new int[asset->channels];
00145 for(i = 0; i < asset->channels; i++) last_ima4_indexes[i] = 0;
00146 }
00147
00148 for(i = 0; i < asset->channels; i++)
00149 {
00150 *output++ = last_ima4_samples[i] & 0xff;
00151 *output++ = (last_ima4_samples[i] >> 8) & 0xff;
00152 *output++ = last_ima4_indexes[i];
00153 *output++ = 0;
00154 }
00155
00156 while(input < input_end)
00157 {
00158 for(i = 0; i < asset->channels; i++)
00159 {
00160 subinput = input + i;
00161 for(j = 0; j < 4; j++)
00162 {
00163 ima4_encode_sample(&(last_ima4_samples[i]),
00164 &(last_ima4_indexes[i]),
00165 &nibble,
00166 *subinput);
00167
00168 subinput += buffer_advance;
00169 *output = nibble;
00170
00171 ima4_encode_sample(&(last_ima4_samples[i]),
00172 &(last_ima4_indexes[i]),
00173 &nibble,
00174 *subinput);
00175
00176 subinput += buffer_advance;
00177 *output++ |= (nibble << 4);
00178 }
00179 }
00180 input += 8 * asset->channels;
00181 }
00182
00183 return 0;
00184 }
00185
00186 int FileBase::ima4_encode_sample(int *last_sample, int *last_index, int *nibble, int next_sample)
00187 {
00188 int difference, new_difference, mask, step;
00189
00190 difference = next_sample - *last_sample;
00191 *nibble = 0;
00192 step = ima4_step[*last_index];
00193 new_difference = step >> 3;
00194
00195 if(difference < 0)
00196 {
00197 *nibble = 8;
00198 difference = -difference;
00199 }
00200
00201 mask = 4;
00202 while(mask)
00203 {
00204 if(difference >= step)
00205 {
00206 *nibble |= mask;
00207 difference -= step;
00208 new_difference += step;
00209 }
00210
00211 step >>= 1;
00212 mask >>= 1;
00213 }
00214
00215 if(*nibble & 8)
00216 *last_sample -= new_difference;
00217 else
00218 *last_sample += new_difference;
00219
00220 if(*last_sample > 32767) *last_sample = 32767;
00221 else
00222 if(*last_sample < -32767) *last_sample = -32767;
00223
00224 *last_index += ima4_index[*nibble];
00225
00226 if(*last_index < 0) *last_index = 0;
00227 else
00228 if(*last_index > 88) *last_index= 88;
00229
00230 return 0;
00231 }
00232
00233
00234
00235 int64_t FileBase::ima4_samples_to_bytes(int64_t samples, int channels)
00236 {
00237 int64_t bytes = (int64_t)(samples / ima4_block_samples) * ima4_block_size * channels;
00238 return bytes;
00239 }
00240
00241 int64_t FileBase::ima4_bytes_to_samples(int64_t bytes, int channels)
00242 {
00243 int64_t samples = (int64_t)(bytes / channels / ima4_block_size) * ima4_block_samples;
00244 return samples;
00245 }