r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / guicast / units.C
blob042552944e176ee792db61c6074cf77ea4509b16
1 #include "units.h"
2 #include <stdlib.h>
4 float* DB::topower = 0;
5 int* Freq::freqtable = 0;
7 DB::DB(float infinitygain)
9         this->infinitygain = infinitygain;
10         if(!topower)
11         {
12                 int i;
13                 float value;
15                 // db to power table
16                 topower = new float[(MAXGAIN - INFINITYGAIN) * 10 + 1];
17                 topower += -INFINITYGAIN * 10;
18                 for(i = INFINITYGAIN * 10; i <= MAXGAIN * 10; i++)
19                 {
20                         topower[i] = pow(10, (float)i / 10 / 20);
21                         
22 //printf("%f %f\n", (float)i/10, topower[i]);
23                 }
24                 topower[INFINITYGAIN * 10] = 0;   // infinity gain
25         }
26         db = 0;
29 float DB::fromdb_table() 
30
31         return db = topower[(int)(db * 10)]; 
34 float DB::fromdb_table(float db) 
35
36         if(db > MAXGAIN) db = MAXGAIN;
37         if(db <= INFINITYGAIN) return 0;
38         return db = topower[(int)(db * 10)]; 
41 float DB::fromdb()
43         return pow(10, db / 20);
46 float DB::fromdb(float db)
48         return pow(10, db / 20);
51 // set db to the power given using a formula
52 float DB::todb(float power)
54         float db;
55         if(power == 0) 
56                 db = -100;
57         else 
58         {
59                 db = (float)(20 * log10(power));
60                 if(db < -100) db = -100;
61         }
62         return db;
66 Freq::Freq()
68         init_table();
69         freq = 0;
72 Freq::Freq(const Freq& oldfreq)
74         this->freq = oldfreq.freq;
77 void Freq::init_table()
79         if(!freqtable)
80         {
81                 freqtable = new int[TOTALFREQS + 1];
82 // starting frequency
83                 double freq1 = 27.5, freq2 = 55;  
84 // Some number divisable by three.  This depends on the value of TOTALFREQS
85                 int scale = 105;   
87                 freqtable[0] = 0;
88                 for(int i = 1, j = 0; i <= TOTALFREQS; i++, j++)
89                 {
90                 freqtable[i] = (int)(freq1 + (freq2 - freq1) / scale * j + 0.5);
91 //printf("Freq::init_table %d\n", freqtable[i]);
92                 if(j >= scale)
93                         {
94                                 freq1 = freq2;
95                                 freq2 *= 2;
96                                 j = 0;
97                         }
98                 }
99         }
102 int Freq::fromfreq() 
104         int i;
106         for(i = 0; i < TOTALFREQS && freqtable[i] < freq; i++)
107         ;
108         return(i);
111 int Freq::fromfreq(int index) 
113         int i;
115         init_table();
116         for(i = 0; i < TOTALFREQS && freqtable[i] < index; i++)
117         ;
118         return(i);
121 int Freq::tofreq(int index)
123         init_table();
124         int freq = freqtable[index]; 
125         return freq; 
128 Freq& Freq::operator++() 
130         if(freq < TOTALFREQS) freq++;
131         return *this;
133         
134 Freq& Freq::operator--()
136         if(freq > 0) freq--;
137         return *this;
139         
140 int Freq::operator>(Freq &newfreq) { return freq > newfreq.freq; }
141 int Freq::operator<(Freq &newfreq) { return freq < newfreq.freq; }
142 Freq& Freq::operator=(const Freq &newfreq) { freq = newfreq.freq; return *this; }
143 int Freq::operator=(const int newfreq) { freq = newfreq; return newfreq; }
144 int Freq::operator!=(Freq &newfreq) { return freq != newfreq.freq; }
145 int Freq::operator==(Freq &newfreq) { return freq == newfreq.freq; }
146 int Freq::operator==(int newfreq) { return freq == newfreq; }
148 char* Units::totext(char *text, 
149                         double seconds, 
150                         int time_format, 
151                         int sample_rate, 
152                         float frame_rate, 
153                         float frames_per_foot)    // give text representation as time
155         int hour, minute, second, thousandths;
156         int64_t frame, feet;
158         switch(time_format)
159         {
160                 case TIME_HMS:
161                 {
162                         seconds = fabs(seconds);
163                         hour = (int)(seconds / 3600);
164                         minute = (int)(seconds / 60 - hour * 60);
165                         second = (int)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
166                         thousandths = (int)(seconds * 1000) % 1000;
167                         sprintf(text, "%d:%02d:%02d.%03d", 
168                                 hour, 
169                                 minute, 
170                                 second, 
171                                 thousandths);
172                         return text;
173                 }
174                   break;
175                 
176                 case TIME_HMS2:
177                 {
178                         float second;
179                         seconds = fabs(seconds);
180                         hour = (int)(seconds / 3600);
181                         minute = (int)(seconds / 60 - hour * 60);
182                         second = (float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
183                         sprintf(text, "%d:%02d:%02d", hour, minute, (int)second);
184                         return text;
185                 }
186                   break;
188                 case TIME_HMSF:
189                 {
190                         int second;
191                         seconds = fabs(seconds);
192                         hour = (int)(seconds / 3600);
193                         minute = (int)(seconds / 60 - hour * 60);
194                         second = (int)(seconds - hour * 3600 - minute * 60);
195                         frame = (int64_t)(frame_rate * 
196                                  (float)((float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60 - second))
197                                  ;
198                         sprintf(text, "%01d:%02d:%02d:%02ld", hour, minute, second, frame);
199                         return text;
200                 }
201                         break;
202                         
203                 case TIME_SAMPLES:
204                         sprintf(text, "%09ld", to_int64(seconds * sample_rate));
205                         break;
206                 
207                 case TIME_SAMPLES_HEX:
208                         sprintf(text, "%08x", to_int64(seconds * sample_rate));
209                         break;
210                 
211                 case TIME_FRAMES:
212                         frame = to_int64(seconds * frame_rate);
213                         sprintf(text, "%06ld", frame);
214                         return text;
215                         break;
216                 
217                 case TIME_FEET_FRAMES:
218                         frame = to_int64(seconds * frame_rate);
219                         feet = (int64_t)(frame / frames_per_foot);
220                         sprintf(text, "%05ld-%02ld", 
221                                 feet, 
222                                 (int64_t)(frame - feet * frames_per_foot));
223                         return text;
224                         break;
225         }
226         return text;
230 char* Units::totext(char *text, 
231                 int64_t samples, 
232                 int samplerate, 
233                 int time_format, 
234                 float frame_rate,
235                 float frames_per_foot)
237         return totext(text, (double)samples / samplerate, time_format, samplerate, frame_rate, frames_per_foot);
238 }    // give text representation as time
240 int64_t Units::fromtext(char *text, 
241                         int samplerate, 
242                         int time_format, 
243                         float frame_rate,
244                         float frames_per_foot)
246         int64_t hours, minutes, frames, total_samples, i, j;
247         int64_t feet;
248         float seconds;
249         char string[256];
250         
251         switch(time_format)
252         {
253                 case 0:
254 // get hours
255                         i = 0;
256                         j = 0;
257                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
258                         string[j] = 0;
259                         hours = atol(string);
260 // get minutes
261                         j = 0;
262 // skip separator
263                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
264                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
265                         string[j] = 0;
266                         minutes = atol(string);
267                         
268 // get seconds
269                         j = 0;
270 // skip separator
271                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
272                         while((text[i] == '.' || (text[i] >=48 && text[i] <= 57)) && j < 10) string[j++] = text[i++];
273                         string[j] = 0;
274                         seconds = atof(string);
276                         total_samples = (uint64_t)(((double)seconds + minutes * 60 + hours * 3600) * samplerate);
277                         return total_samples;
278                         break;
280                 case 1:
281 // get hours
282                         i = 0;
283                         j = 0;
284                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
285                         string[j] = 0;
286                         hours = atol(string);
287                         
288 // get minutes
289                         j = 0;
290 // skip separator
291                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
292                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
293                         string[j] = 0;
294                         minutes = atol(string);
295                         
296 // get seconds
297                         j = 0;
298 // skip separator
299                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
300                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
301                         string[j] = 0;
302                         seconds = atof(string);
303                         
304 // skip separator
305                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
306 // get frames
307                         j = 0;
308                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
309                         string[j] = 0;
310                         frames = atol(string);
311                         
312                         total_samples = (int64_t)(((float)frames / frame_rate + seconds + minutes*60 + hours*3600) * samplerate);
313                         return total_samples;
314                         break;
316                 case 2:
317                         return atol(text);
318                         break;
319                 
320                 case 3:
321                         sscanf(text, "%x", &total_samples);
322                         return total_samples;
323                 
324                 case 4:
325                         return (int64_t)(atof(text) / frame_rate * samplerate);
326                         break;
327                 
328                 case 5:
329 // Get feet
330                         i = 0;
331                         j = 0;
332                         while(text[i] >=48 && text[i] <= 57 && text[i] != 0 && j < 10) string[j++] = text[i++];
333                         string[j] = 0;
334                         feet = atol(string);
336 // skip separator
337                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
339 // Get frames
340                         j = 0;
341                         while(text[i] >=48 && text[i] <= 57 && text[i] != 0 && j < 10) string[j++] = text[i++];
342                         string[j] = 0;
343                         frames = atol(string);
344                         return (int64_t)(((float)feet * frames_per_foot + frames) / frame_rate * samplerate);
345                         break;
346         }
347         return 0;
350 double Units::text_to_seconds(char *text, 
351                                 int samplerate, 
352                                 int time_format, 
353                                 float frame_rate, 
354                                 float frames_per_foot)
356         return (double)fromtext(text, 
357                 samplerate, 
358                 time_format, 
359                 frame_rate, 
360                 frames_per_foot) / samplerate;
368 float Units::toframes(int64_t samples, int sample_rate, float framerate) 
370         return (float)samples / sample_rate * framerate; 
371 } // give position in frames
373 int64_t Units::toframes_round(int64_t samples, int sample_rate, float framerate) 
375 // used in editing
376         float result_f = (float)samples / sample_rate * framerate; 
377         int64_t result_l = (int64_t)(result_f + 0.5);
378         return result_l;
381 double Units::fix_framerate(double value)
383         if(value > 29.5 && value < 30) 
384                 value = (double)30000 / (double)1001;
385         else
386         if(value > 59.5 && value < 60) 
387                 value = (double)60000 / (double)1001;
388         else
389         if(value > 23.5 && value < 24) 
390                 value = (double)24000 / (double)1001;
391         
392         return value;
395 double Units::atoframerate(char *text)
397         double result = atof(text);
398         return fix_framerate(result);
402 int64_t Units::tosamples(float frames, int sample_rate, float framerate) 
404         float result = (frames / framerate * sample_rate);
405         
406         if(result - (int)result) result += 1;
407         return (int64_t)result;
408 } // give position in samples
411 float Units::xy_to_polar(int x, int y)
413         float angle;
414         if(x > 0 && y <= 0)
415         {
416                 angle = atan((float)-y / x) / (2 * M_PI) * 360;
417         }
418         else
419         if(x < 0 && y <= 0)
420         {
421                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
422         }
423         else
424         if(x < 0 && y > 0)
425         {
426                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
427         }
428         else
429         if(x > 0 && y > 0)
430         {
431                 angle = 360 + atan((float)-y / x) / (2 * M_PI) * 360;
432         }
433         else
434         if(x == 0 && y < 0)
435         {
436                 angle = 90;
437         }
438         else
439         if(x == 0 && y > 0)
440         {
441                 angle = 270;
442         }
443         else
444         if(x == 0 && y == 0)
445         {
446                 angle = 0;
447         }
449         return angle;
452 void Units::polar_to_xy(float angle, int radius, int &x, int &y)
454         while(angle < 0) angle += 360;
456         x = (int)(cos(angle / 360 * (2 * M_PI)) * radius);
457         y = (int)(-sin(angle / 360 * (2 * M_PI)) * radius);
460 int64_t Units::round(double result)
462         return (int64_t)(result < 0 ? result - 0.5 : result + 0.5);
465 float Units::quantize10(float value)
467         int64_t temp = (int64_t)(value * 10 + 0.5);
468         value = (float)temp / 10;
469         return value;
472 float Units::quantize(float value, float precision)
474         int64_t temp = (int64_t)(value / precision + 0.5);
475         value = (float)temp * precision;
476         return value;
480 int64_t Units::to_int64(double result)
482 // This must round up if result is one sample within cieling.
483 // Sampling rates below 48000 may cause more problems.
484         return (int64_t)(result < 0 ? (result - 0.005) : (result + 0.005));
487 char* Units::print_time_format(int time_format, char *string)
489         switch(time_format)
490         {
491                 case 0: sprintf(string, "Hours:Minutes:Seconds.xxx"); break;
492                 case 1: sprintf(string, "Hours:Minutes:Seconds:Frames"); break;
493                 case 2: sprintf(string, "Samples"); break;
494                 case 3: sprintf(string, "Hex Samples"); break;
495                 case 4: sprintf(string, "Frames"); break;
496                 case 5: sprintf(string, "Feet-frames"); break;
497         }
498         
499         return string;
502 #undef BYTE_ORDER
503 #define BYTE_ORDER ((*(u_int32_t*)"a   ") & 0x00000001)
505 void* Units::int64_to_ptr(uint64_t value)
507         unsigned char *value_dissected = (unsigned char*)&value;
508         void *result;
509         unsigned char *data = (unsigned char*)&result;
511 // Must be done behind the compiler's back
512         if(sizeof(void*) == 4)
513         {
514                 if(!BYTE_ORDER)
515                 {
516                         data[0] = value_dissected[4];
517                         data[1] = value_dissected[5];
518                         data[2] = value_dissected[6];
519                         data[3] = value_dissected[7];
520                 }
521                 else
522                 {
523                         data[0] = value_dissected[0];
524                         data[1] = value_dissected[1];
525                         data[2] = value_dissected[2];
526                         data[3] = value_dissected[3];
527                 }
528         }
529         else
530         {
531                 data[0] = value_dissected[0];
532                 data[1] = value_dissected[1];
533                 data[2] = value_dissected[2];
534                 data[3] = value_dissected[3];
535                 data[4] = value_dissected[4];
536                 data[5] = value_dissected[5];
537                 data[6] = value_dissected[6];
538                 data[7] = value_dissected[7];
539         }
540         return result;
543 uint64_t Units::ptr_to_int64(void *ptr)
545         unsigned char *ptr_dissected = (unsigned char*)&ptr;
546         int64_t result = 0;
547         unsigned char *data = (unsigned char*)&result;
549 // Don't do this at home.
550         if(sizeof(void*) == 4)
551         {
552                 if(!BYTE_ORDER)
553                 {
554                         data[4] = ptr_dissected[0];
555                         data[5] = ptr_dissected[1];
556                         data[6] = ptr_dissected[2];
557                         data[7] = ptr_dissected[3];
558                 }
559                 else
560                 {
561                         data[0] = ptr_dissected[0];
562                         data[1] = ptr_dissected[1];
563                         data[2] = ptr_dissected[2];
564                         data[3] = ptr_dissected[3];
565                 }
566         }
567         else
568         {
569                 data[0] = ptr_dissected[0];
570                 data[1] = ptr_dissected[1];
571                 data[2] = ptr_dissected[2];
572                 data[3] = ptr_dissected[3];
573                 data[4] = ptr_dissected[4];
574                 data[5] = ptr_dissected[5];
575                 data[6] = ptr_dissected[6];
576                 data[7] = ptr_dissected[7];
577         }
578         return result;