initial commit
[goodguy/history.git] / cinelerra-5.0 / cinelerra / filebaseima4.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "asset.h"
23 #include "byteorder.h"
24 #include "file.h"
25 #include "filebase.h"
26 #include "sizes.h"
27
28 int FileBase::ima4_step[89] = 
29 {
30     7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
31     19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
32     50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
33     130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
34     337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
35     876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
36     2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
37     5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
38     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
39 };
40
41 int FileBase::ima4_index[16] = 
42 {
43     -1, -1, -1, -1, 2, 4, 6, 8,
44     -1, -1, -1, -1, 2, 4, 6, 8
45 };
46
47
48
49 int FileBase::init_ima4()
50 {
51         ima4_block_samples = 1024;
52         ima4_block_size = (ima4_block_samples - 1) * asset->channels / 2 + 4;
53         last_ima4_samples = 0;
54         last_ima4_indexes = 0;
55         return 0;
56 }
57
58 int FileBase::delete_ima4()
59 {
60         if(last_ima4_samples) delete last_ima4_samples;
61         if(last_ima4_indexes) delete last_ima4_indexes;
62         last_ima4_samples = 0;
63         last_ima4_indexes = 0;  
64         return 0;
65 }
66
67 int FileBase::ima4_decode_block(int16_t *output, unsigned char *input)
68 {
69 return 0;
70 //      int predictor[asset->channels];
71 //      int index[asset->channels];
72 //      int step[asset->channels];
73 //      int i, j, nibble;
74 //      unsigned char *block_ptr;
75 //      unsigned char *input_end = input + ima4_block_size;
76 //      int buffer_advance = asset->channels;
77 //      int16_t *suboutput;
78 // 
79 // // Get the chunk header
80 //      for(int i = 0; i < asset->channels; i++)
81 //      {
82 //              predictor[i] = *input++;
83 //              predictor[i] |= (int)(*input++) << 8;
84 //              index[i] = *input++;
85 //              if(index[i] > 88) index[i] = 88;
86 //              if(predictor[i] & 0x8000) predictor[i] -= 0x10000;
87 //              step[i] = ima4_step[index[i]];
88 //              *output++ = predictor[i];
89 //              input++;
90 //      }
91 // 
92 // // Read the input buffer sequentially, one nibble at a time
93 //      while(input < input_end)
94 //      {
95 //              for(i = 0; i < asset->channels; i++)
96 //              {
97 //                      suboutput = output + i;
98 // 
99 //                      for(j = 0; j < 4; j++)
100 //                      {
101 //                              ima4_decode_sample(&predictor[i], *input & 0x0f, &index[i], &step[i]);
102 //                              *suboutput = predictor[i];
103 //                              suboutput += buffer_advance;
104 //                              ima4_decode_sample(&predictor[i], (*input++ >> 4) & 0x0f, &index[i], &step[i]);
105 //                              *suboutput = predictor[i];
106 //                              suboutput += buffer_advance;
107 //                      }
108 //              }
109 // 
110 //              output += 8 * asset->channels;
111 //      }
112 }
113
114 int FileBase::ima4_decode_sample(int *predictor, int nibble, int *index, int *step)
115 {
116         int difference, sign;
117
118 // Get new index value
119         *index += ima4_index[nibble];
120
121         if(*index < 0) *index = 0; 
122         else 
123         if(*index > 88) *index = 88;
124
125 // Get sign and magnitude from nibble
126         sign = nibble & 8;
127         nibble = nibble & 7;
128
129 // Get difference
130         difference = *step >> 3;
131         if(nibble & 4) difference += *step;
132         if(nibble & 2) difference += *step >> 1;
133         if(nibble & 1) difference += *step >> 2;
134
135 // Predict value
136         if(sign) 
137         *predictor -= difference;
138         else 
139         *predictor += difference;
140
141         if(*predictor > 32767) *predictor = 32767;
142         else
143         if(*predictor < -32768) *predictor = -32768;
144
145 // Update the step value
146         *step = ima4_step[*index];
147
148         return 0;
149 }
150
151
152 int FileBase::ima4_encode_block(unsigned char *output, int16_t *input, int step, int channel)
153 {
154         int i, j, nibble;
155         int16_t *input_end = input + ima4_block_size;
156         int16_t *subinput;
157         int buffer_advance = asset->channels;
158
159         if(!last_ima4_samples)
160         {
161                 last_ima4_samples = new int[asset->channels];
162                 for(i = 0; i < asset->channels; i++) last_ima4_samples[i] = 0;
163         }
164
165         if(!last_ima4_indexes)
166         {
167                 last_ima4_indexes = new int[asset->channels];
168                 for(i = 0; i < asset->channels; i++) last_ima4_indexes[i] = 0;
169         }
170
171         for(i = 0; i < asset->channels; i++)
172         {
173                 *output++ = last_ima4_samples[i] & 0xff;
174                 *output++ = (last_ima4_samples[i] >> 8) & 0xff;
175                 *output++ = last_ima4_indexes[i];
176                 *output++ = 0;
177         }
178
179         while(input < input_end)
180         {
181                 for(i = 0; i < asset->channels; i++)
182                 {
183                         subinput = input + i;
184                         for(j = 0; j < 4; j++)
185                         {
186                                 ima4_encode_sample(&(last_ima4_samples[i]), 
187                                                                 &(last_ima4_indexes[i]), 
188                                                                 &nibble, 
189                                                                 *subinput);
190
191                                 subinput += buffer_advance;
192                                 *output = nibble;
193                                 
194                                 ima4_encode_sample(&(last_ima4_samples[i]), 
195                                                                 &(last_ima4_indexes[i]), 
196                                                                 &nibble, 
197                                                                 *subinput);
198
199                                 subinput += buffer_advance;
200                                 *output++ |= (nibble << 4);
201                         }
202                 }
203                 input += 8 * asset->channels;
204         }
205
206         return 0;
207 }
208
209 int FileBase::ima4_encode_sample(int *last_sample, int *last_index, int *nibble, int next_sample)
210 {
211         int difference, new_difference, mask, step;
212
213         difference = next_sample - *last_sample;
214         *nibble = 0;
215         step = ima4_step[*last_index];
216         new_difference = step >> 3;
217
218         if(difference < 0)
219         {
220                 *nibble = 8;
221                 difference = -difference;
222         }
223
224         mask = 4;
225         while(mask)
226         {
227                 if(difference >= step)
228                 {
229                         *nibble |= mask;
230                         difference -= step;
231                         new_difference += step;
232                 }
233
234                 step >>= 1;
235                 mask >>= 1;
236         }
237
238         if(*nibble & 8)
239                 *last_sample -= new_difference;
240         else
241                 *last_sample += new_difference;
242
243         if(*last_sample > 32767) *last_sample = 32767;
244         else
245         if(*last_sample < -32767) *last_sample = -32767;
246
247         *last_index += ima4_index[*nibble];
248
249         if(*last_index < 0) *last_index = 0;
250         else
251         if(*last_index > 88) *last_index= 88;
252
253         return 0;
254 }
255
256 // Convert the number of samples in a chunk into the number of bytes in that
257 // chunk.  The number of samples in a chunk should end on a block boundary.
258 int64_t FileBase::ima4_samples_to_bytes(int64_t samples, int channels)
259 {
260         int64_t bytes = (int64_t)(samples / ima4_block_samples) * ima4_block_size * channels;
261         return bytes;
262 }
263
264 int64_t FileBase::ima4_bytes_to_samples(int64_t bytes, int channels)
265 {
266         int64_t samples = (int64_t)(bytes / channels / ima4_block_size) * ima4_block_samples;
267         return samples;
268 }