r999: maintainers added to README_en.
[cinelerra_cv/mob.git] / cinelerra / filebaseima4.C
blob164b7bc9b300e1a1a9881af2edf8c91f06c440d2
1 #include "asset.h"
2 #include "byteorder.h"
3 #include "file.h"
4 #include "filebase.h"
5 #include "sizes.h"
7 int FileBase::ima4_step[89] = 
9     7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
10     19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
11     50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
12     130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
13     337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
14     876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
15     2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
16     5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
17     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
20 int FileBase::ima4_index[16] = 
22     -1, -1, -1, -1, 2, 4, 6, 8,
23     -1, -1, -1, -1, 2, 4, 6, 8
28 int FileBase::init_ima4()
30         ima4_block_samples = 1024;
31         ima4_block_size = (ima4_block_samples - 1) * asset->channels / 2 + 4;
32         last_ima4_samples = 0;
33         last_ima4_indexes = 0;
36 int FileBase::delete_ima4()
38         if(last_ima4_samples) delete last_ima4_samples;
39         if(last_ima4_indexes) delete last_ima4_indexes;
40         last_ima4_samples = 0;
41         last_ima4_indexes = 0;  
44 int FileBase::ima4_decode_block(int16_t *output, unsigned char *input)
46 return 0;
47 //      int predictor[asset->channels];
48 //      int index[asset->channels];
49 //      int step[asset->channels];
50 //      int i, j, nibble;
51 //      unsigned char *block_ptr;
52 //      unsigned char *input_end = input + ima4_block_size;
53 //      int buffer_advance = asset->channels;
54 //      int16_t *suboutput;
55 // 
56 // // Get the chunk header
57 //      for(int i = 0; i < asset->channels; i++)
58 //      {
59 //              predictor[i] = *input++;
60 //              predictor[i] |= (int)(*input++) << 8;
61 //              index[i] = *input++;
62 //              if(index[i] > 88) index[i] = 88;
63 //              if(predictor[i] & 0x8000) predictor[i] -= 0x10000;
64 //              step[i] = ima4_step[index[i]];
65 //              *output++ = predictor[i];
66 //              input++;
67 //      }
68 // 
69 // // Read the input buffer sequentially, one nibble at a time
70 //      while(input < input_end)
71 //      {
72 //              for(i = 0; i < asset->channels; i++)
73 //              {
74 //                      suboutput = output + i;
75 // 
76 //                      for(j = 0; j < 4; j++)
77 //                      {
78 //                              ima4_decode_sample(&predictor[i], *input & 0x0f, &index[i], &step[i]);
79 //                              *suboutput = predictor[i];
80 //                              suboutput += buffer_advance;
81 //                              ima4_decode_sample(&predictor[i], (*input++ >> 4) & 0x0f, &index[i], &step[i]);
82 //                              *suboutput = predictor[i];
83 //                              suboutput += buffer_advance;
84 //                      }
85 //              }
86 // 
87 //              output += 8 * asset->channels;
88 //      }
91 int FileBase::ima4_decode_sample(int *predictor, int nibble, int *index, int *step)
93         int difference, sign;
95 // Get new index value
96         *index += ima4_index[nibble];
98         if(*index < 0) *index = 0; 
99         else 
100         if(*index > 88) *index = 88;
102 // Get sign and magnitude from nibble
103         sign = nibble & 8;
104         nibble = nibble & 7;
106 // Get difference
107         difference = *step >> 3;
108         if(nibble & 4) difference += *step;
109         if(nibble & 2) difference += *step >> 1;
110         if(nibble & 1) difference += *step >> 2;
112 // Predict value
113         if(sign) 
114         *predictor -= difference;
115         else 
116         *predictor += difference;
118         if(*predictor > 32767) *predictor = 32767;
119         else
120         if(*predictor < -32768) *predictor = -32768;
122 // Update the step value
123         *step = ima4_step[*index];
125         return 0;
129 int FileBase::ima4_encode_block(unsigned char *output, int16_t *input, int step, int channel)
131         int i, j, nibble;
132         int16_t *input_end = input + ima4_block_size;
133         int16_t *subinput;
134         int buffer_advance = asset->channels;
136         if(!last_ima4_samples)
137         {
138                 last_ima4_samples = new int[asset->channels];
139                 for(i = 0; i < asset->channels; i++) last_ima4_samples[i] = 0;
140         }
142         if(!last_ima4_indexes)
143         {
144                 last_ima4_indexes = new int[asset->channels];
145                 for(i = 0; i < asset->channels; i++) last_ima4_indexes[i] = 0;
146         }
148         for(i = 0; i < asset->channels; i++)
149         {
150                 *output++ = last_ima4_samples[i] & 0xff;
151                 *output++ = (last_ima4_samples[i] >> 8) & 0xff;
152                 *output++ = last_ima4_indexes[i];
153                 *output++ = 0;
154         }
156         while(input < input_end)
157         {
158                 for(i = 0; i < asset->channels; i++)
159                 {
160                         subinput = input + i;
161                         for(j = 0; j < 4; j++)
162                         {
163                                 ima4_encode_sample(&(last_ima4_samples[i]), 
164                                                                 &(last_ima4_indexes[i]), 
165                                                                 &nibble, 
166                                                                 *subinput);
168                                 subinput += buffer_advance;
169                                 *output = nibble;
170                                 
171                                 ima4_encode_sample(&(last_ima4_samples[i]), 
172                                                                 &(last_ima4_indexes[i]), 
173                                                                 &nibble, 
174                                                                 *subinput);
176                                 subinput += buffer_advance;
177                                 *output++ |= (nibble << 4);
178                         }
179                 }
180                 input += 8 * asset->channels;
181         }
183         return 0;
186 int FileBase::ima4_encode_sample(int *last_sample, int *last_index, int *nibble, int next_sample)
188         int difference, new_difference, mask, step;
190         difference = next_sample - *last_sample;
191         *nibble = 0;
192         step = ima4_step[*last_index];
193         new_difference = step >> 3;
195         if(difference < 0)
196         {
197                 *nibble = 8;
198                 difference = -difference;
199         }
201         mask = 4;
202         while(mask)
203         {
204                 if(difference >= step)
205                 {
206                         *nibble |= mask;
207                         difference -= step;
208                         new_difference += step;
209                 }
211                 step >>= 1;
212                 mask >>= 1;
213         }
215         if(*nibble & 8)
216                 *last_sample -= new_difference;
217         else
218                 *last_sample += new_difference;
220         if(*last_sample > 32767) *last_sample = 32767;
221         else
222         if(*last_sample < -32767) *last_sample = -32767;
224         *last_index += ima4_index[*nibble];
226         if(*last_index < 0) *last_index = 0;
227         else
228         if(*last_index > 88) *last_index= 88;
230         return 0;
233 // Convert the number of samples in a chunk into the number of bytes in that
234 // chunk.  The number of samples in a chunk should end on a block boundary.
235 int64_t FileBase::ima4_samples_to_bytes(int64_t samples, int channels)
237         int64_t bytes = (int64_t)(samples / ima4_block_samples) * ima4_block_size * channels;
238         return bytes;
241 int64_t FileBase::ima4_bytes_to_samples(int64_t bytes, int channels)
243         int64_t samples = (int64_t)(bytes / channels / ima4_block_size) * ima4_block_samples;
244         return samples;