Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / guicast / units.C
blobe7f0fcdd6e7dc349d046477128af2f4370afaf49
1 #include "bcwindowbase.inc"
2 #include "units.h"
5 #include <stdlib.h>
6 #include <string.h>
8 // NOTE: DB::allocated is the original allocation, to which we keep a
9 // pointer so that in theory we could have a destructor. DB::topower
10 // is a pointer into the middle of DB::allocated, which allows us to
11 // do lookups using negative array coefficients.
12 float* DB::topower = 0;
13 float* DB::allocated = NULL;
15 int* Freq::freqtable = 0;
18 DB::DB(float infinitygain)
20         this->infinitygain = infinitygain;
21         if(allocated == NULL)
22         {
23                 int i;
24                 float value;
26                 // db to power table
27                 allocated = new float[(MAXGAIN - INFINITYGAIN) * 10 + 1];
28                 topower = allocated + (-INFINITYGAIN * 10);
29                 for(i = INFINITYGAIN * 10; i <= MAXGAIN * 10; i++)
30                 {
31                         topower[i] = pow(10, (float)i / 10 / 20);
32                         
33 //printf("%f %f\n", (float)i/10, topower[i]);
34                 }
35                 topower[INFINITYGAIN * 10] = 0;   // infinity gain
36         }
37         db = 0;
40 // FUTURE: would bounds checking be possible here?  Or at least make private?
41 float DB::fromdb_table() 
42
43         return db = topower[(int)(db * 10)]; 
46 float DB::fromdb_table(float db) 
47
48         if(db > MAXGAIN) db = MAXGAIN;
49         if(db <= INFINITYGAIN) return 0;
50         return db = topower[(int)(db * 10)]; 
53 float DB::fromdb()
55         return pow(10, db / 20);
58 float DB::fromdb(float db)
60         return pow(10, db / 20);
63 // set db to the power given using a formula
64 float DB::todb(float power)
66         float db;
67         if(power == 0) 
68                 db = -100;
69         else 
70         {
71                 db = (float)(20 * log10(power));
72                 if(db < -100) db = -100;
73         }
74         return db;
78 Freq::Freq()
80         init_table();
81         freq = 0;
84 Freq::Freq(const Freq& oldfreq)
86         this->freq = oldfreq.freq;
89 void Freq::init_table()
91         if(!freqtable)
92         {
93                 freqtable = new int[TOTALFREQS + 1];
94 // starting frequency
95                 double freq1 = 27.5, freq2 = 55;  
96 // Some number divisable by three.  This depends on the value of TOTALFREQS
97                 int scale = 105;   
99                 freqtable[0] = 0;
100                 for(int i = 1, j = 0; i <= TOTALFREQS; i++, j++)
101                 {
102                 freqtable[i] = (int)(freq1 + (freq2 - freq1) / scale * j + 0.5);
103 //printf("Freq::init_table %d\n", freqtable[i]);
104                 if(j >= scale)
105                         {
106                                 freq1 = freq2;
107                                 freq2 *= 2;
108                                 j = 0;
109                         }
110                 }
111         }
114 int Freq::fromfreq() 
116         int i;
118         for(i = 0; i < TOTALFREQS && freqtable[i] < freq; i++)
119         ;
120         return(i);
123 int Freq::fromfreq(int index) 
125         int i;
127         init_table();
128         for(i = 0; i < TOTALFREQS && freqtable[i] < index; i++)
129         ;
130         return(i);
133 int Freq::tofreq(int index)
135         init_table();
136         int freq = freqtable[index]; 
137         return freq; 
140 Freq& Freq::operator++() 
142         if(freq < TOTALFREQS) freq++;
143         return *this;
145         
146 Freq& Freq::operator--()
148         if(freq > 0) freq--;
149         return *this;
151         
152 int Freq::operator>(Freq &newfreq) { return freq > newfreq.freq; }
153 int Freq::operator<(Freq &newfreq) { return freq < newfreq.freq; }
154 Freq& Freq::operator=(const Freq &newfreq) { freq = newfreq.freq; return *this; }
155 int Freq::operator=(const int newfreq) { freq = newfreq; return newfreq; }
156 int Freq::operator!=(Freq &newfreq) { return freq != newfreq.freq; }
157 int Freq::operator==(Freq &newfreq) { return freq == newfreq.freq; }
158 int Freq::operator==(int newfreq) { return freq == newfreq; }
160 char* Units::totext(char *text, 
161                         double seconds, 
162                         int time_format, 
163                         int sample_rate, 
164                         float frame_rate, 
165                         float frames_per_foot)    // give text representation as time
167         int hour, minute, second, thousandths;
168         int64_t frame, feet;
170         switch(time_format)
171         {
172                 case TIME_SECONDS:
173                         seconds = fabs(seconds);
174                         sprintf(text, "%04d.%03d", (int)seconds, (int)(seconds * 1000) % 1000);
175                         return text;
176                         break;
178                 case TIME_HMS:
179                         seconds = fabs(seconds);
180                         hour = (int)(seconds / 3600);
181                         minute = (int)(seconds / 60 - hour * 60);
182                         second = (int)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
183                         thousandths = (int)(seconds * 1000) % 1000;
184                         sprintf(text, "%d:%02d:%02d.%03d", 
185                                 hour, 
186                                 minute, 
187                                 second, 
188                                 thousandths);
189                         return text;
190                   break;
191                 
192                 case TIME_HMS2:
193                 {
194                         float second;
195                         seconds = fabs(seconds);
196                         hour = (int)(seconds / 3600);
197                         minute = (int)(seconds / 60 - hour * 60);
198                         second = (float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
199                         sprintf(text, "%d:%02d:%02d", hour, minute, (int)second);
200                         return text;
201                 }
202                   break;
204                 case TIME_HMS3:
205                 {
206                         float second;
207                         seconds = fabs(seconds);
208                         hour = (int)(seconds / 3600);
209                         minute = (int)(seconds / 60 - hour * 60);
210                         second = (float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
211                         sprintf(text, "%02d:%02d:%02d", hour, minute, (int)second);
212                         return text;
213                 }
214                   break;
216                 case TIME_HMSF:
217                 {
218                         int second;
219                         seconds = fabs(seconds);
220                         hour = (int)(seconds / 3600);
221                         minute = (int)(seconds / 60 - hour * 60);
222                         second = (int)(seconds - hour * 3600 - minute * 60);
223 //                      frame = (int64_t)round(frame_rate * 
224 //                               (float)((float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60 - second));
225 //                      sprintf(text, "%01d:%02d:%02d:%02ld", hour, minute, second, frame);
226                         frame = (int64_t)((double)frame_rate * 
227                                         seconds + 
228                                         0.0000001) - 
229                                 (int64_t)((double)frame_rate * 
230                                         (hour * 
231                                         3600 + 
232                                         minute * 
233                                         60 + 
234                                         second) + 
235                                 0.0000001);   
236                         sprintf(text, "%01d:%02d:%02d:%02ld", hour, minute, second, frame);
237                         return text;
238                 }
239                         break;
240                         
241                 case TIME_SAMPLES:
242                         sprintf(text, "%09ld", to_int64(seconds * sample_rate));
243                         break;
244                 
245                 case TIME_SAMPLES_HEX:
246                         sprintf(text, "%08x", to_int64(seconds * sample_rate));
247                         break;
248                 
249                 case TIME_FRAMES:
250                         frame = to_int64(seconds * frame_rate);
251                         sprintf(text, "%06ld", frame);
252                         return text;
253                         break;
254                 
255                 case TIME_FEET_FRAMES:
256                         frame = to_int64(seconds * frame_rate);
257                         feet = (int64_t)(frame / frames_per_foot);
258                         sprintf(text, "%05ld-%02ld", 
259                                 feet, 
260                                 (int64_t)(frame - feet * frames_per_foot));
261                         return text;
262                         break;
263         }
264         return text;
268 // give text representation as time
269 char* Units::totext(char *text, 
270                 int64_t samples, 
271                 int samplerate, 
272                 int time_format, 
273                 float frame_rate,
274                 float frames_per_foot)
276         return totext(text, (double)samples / samplerate, time_format, samplerate, frame_rate, frames_per_foot);
277 }    
279 int64_t Units::fromtext(char *text, 
280                         int samplerate, 
281                         int time_format, 
282                         float frame_rate,
283                         float frames_per_foot)
285         int64_t hours, minutes, frames, total_samples, i, j;
286         int64_t feet;
287         double seconds;
288         char string[BCTEXTLEN];
289         
290         switch(time_format)
291         {
292                 case TIME_SECONDS:
293                         seconds = atof(text);
294                         return (int64_t)(seconds * samplerate);
295                         break;
297                 case TIME_HMS:
298                 case TIME_HMS2:
299                 case TIME_HMS3:
300 // get hours
301                         i = 0;
302                         j = 0;
303                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
304                         string[j] = 0;
305                         hours = atol(string);
306 // get minutes
307                         j = 0;
308 // skip separator
309                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
310                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
311                         string[j] = 0;
312                         minutes = atol(string);
313                         
314 // get seconds
315                         j = 0;
316 // skip separator
317                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
318                         while((text[i] == '.' || (text[i] >=48 && text[i] <= 57)) && j < 10) string[j++] = text[i++];
319                         string[j] = 0;
320                         seconds = atof(string);
322                         total_samples = (uint64_t)(((double)seconds + minutes * 60 + hours * 3600) * samplerate);
323                         return total_samples;
324                         break;
326                 case TIME_HMSF:
327 // get hours
328                         i = 0;
329                         j = 0;
330                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
331                         string[j] = 0;
332                         hours = atol(string);
333                         
334 // get minutes
335                         j = 0;
336 // skip separator
337                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
338                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
339                         string[j] = 0;
340                         minutes = atol(string);
341                         
342 // get seconds
343                         j = 0;
344 // skip separator
345                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
346                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
347                         string[j] = 0;
348                         seconds = atof(string);
349                         
350 // skip separator
351                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
352 // get frames
353                         j = 0;
354                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
355                         string[j] = 0;
356                         frames = atol(string);
357                         
358                         total_samples = (int64_t)(((float)frames / frame_rate + seconds + minutes*60 + hours*3600) * samplerate);
359                         return total_samples;
360                         break;
362                 case TIME_SAMPLES:
363                         return atol(text);
364                         break;
365                 
366                 case TIME_SAMPLES_HEX:
367                         sscanf(text, "%x", &total_samples);
368                         return total_samples;
369                 
370                 case TIME_FRAMES:
371                         return (int64_t)(atof(text) / frame_rate * samplerate);
372                         break;
373                 
374                 case TIME_FEET_FRAMES:
375 // Get feet
376                         i = 0;
377                         j = 0;
378                         while(text[i] >=48 && text[i] <= 57 && text[i] != 0 && j < 10) string[j++] = text[i++];
379                         string[j] = 0;
380                         feet = atol(string);
382 // skip separator
383                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
385 // Get frames
386                         j = 0;
387                         while(text[i] >=48 && text[i] <= 57 && text[i] != 0 && j < 10) string[j++] = text[i++];
388                         string[j] = 0;
389                         frames = atol(string);
390                         return (int64_t)(((float)feet * frames_per_foot + frames) / frame_rate * samplerate);
391                         break;
392         }
393         return 0;
396 double Units::text_to_seconds(char *text, 
397                                 int samplerate, 
398                                 int time_format, 
399                                 float frame_rate, 
400                                 float frames_per_foot)
402         return (double)fromtext(text, 
403                 samplerate, 
404                 time_format, 
405                 frame_rate, 
406                 frames_per_foot) / samplerate;
412 int Units::timeformat_totype(char *tcf) {
413         if (!strcmp(tcf,TIME_SECONDS__STR)) return(TIME_SECONDS);
414         if (!strcmp(tcf,TIME_HMS__STR)) return(TIME_HMS);
415         if (!strcmp(tcf,TIME_HMS2__STR)) return(TIME_HMS2);
416         if (!strcmp(tcf,TIME_HMS3__STR)) return(TIME_HMS3);
417         if (!strcmp(tcf,TIME_HMSF__STR)) return(TIME_HMSF);
418         if (!strcmp(tcf,TIME_SAMPLES__STR)) return(TIME_SAMPLES);
419         if (!strcmp(tcf,TIME_SAMPLES_HEX__STR)) return(TIME_SAMPLES_HEX);
420         if (!strcmp(tcf,TIME_FRAMES__STR)) return(TIME_FRAMES);
421         if (!strcmp(tcf,TIME_FEET_FRAMES__STR)) return(TIME_FEET_FRAMES);
422         return(-1);
426 float Units::toframes(int64_t samples, int sample_rate, float framerate) 
428         return (float)samples / sample_rate * framerate; 
429 } // give position in frames
431 int64_t Units::toframes_round(int64_t samples, int sample_rate, float framerate) 
433 // used in editing
434         float result_f = (float)samples / sample_rate * framerate; 
435         int64_t result_l = (int64_t)(result_f + 0.5);
436         return result_l;
439 double Units::fix_framerate(double value)
441         if(value > 29.5 && value < 30) 
442                 value = (double)30000 / (double)1001;
443         else
444         if(value > 59.5 && value < 60) 
445                 value = (double)60000 / (double)1001;
446         else
447         if(value > 23.5 && value < 24) 
448                 value = (double)24000 / (double)1001;
449         
450         return value;
453 double Units::atoframerate(char *text)
455         double result = atof(text);
456         return fix_framerate(result);
460 int64_t Units::tosamples(float frames, int sample_rate, float framerate) 
462         float result = (frames / framerate * sample_rate);
463         
464         if(result - (int)result) result += 1;
465         return (int64_t)result;
466 } // give position in samples
469 float Units::xy_to_polar(int x, int y)
471         float angle;
472         if(x > 0 && y <= 0)
473         {
474                 angle = atan((float)-y / x) / (2 * M_PI) * 360;
475         }
476         else
477         if(x < 0 && y <= 0)
478         {
479                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
480         }
481         else
482         if(x < 0 && y > 0)
483         {
484                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
485         }
486         else
487         if(x > 0 && y > 0)
488         {
489                 angle = 360 + atan((float)-y / x) / (2 * M_PI) * 360;
490         }
491         else
492         if(x == 0 && y < 0)
493         {
494                 angle = 90;
495         }
496         else
497         if(x == 0 && y > 0)
498         {
499                 angle = 270;
500         }
501         else
502         if(x == 0 && y == 0)
503         {
504                 angle = 0;
505         }
507         return angle;
510 void Units::polar_to_xy(float angle, int radius, int &x, int &y)
512         while(angle < 0) angle += 360;
514         x = (int)(cos(angle / 360 * (2 * M_PI)) * radius);
515         y = (int)(-sin(angle / 360 * (2 * M_PI)) * radius);
518 int64_t Units::round(double result)
520         return (int64_t)(result < 0 ? result - 0.5 : result + 0.5);
523 float Units::quantize10(float value)
525         int64_t temp = (int64_t)(value * 10 + 0.5);
526         value = (float)temp / 10;
527         return value;
530 float Units::quantize(float value, float precision)
532         int64_t temp = (int64_t)(value / precision + 0.5);
533         value = (float)temp * precision;
534         return value;
537 int64_t Units::to_int64(double result)
539 // This must round up if result is one sample within cieling.
540 // Sampling rates below 48000 may cause more problems.
541         return (int64_t)(result < 0 ? (result - 0.005) : (result + 0.005));
544 char* Units::print_time_format(int time_format, char *string)
546         switch(time_format)
547         {
548                 case 0: sprintf(string, "Hours:Minutes:Seconds.xxx"); break;
549                 case 1: sprintf(string, "Hours:Minutes:Seconds:Frames"); break;
550                 case 2: sprintf(string, "Samples"); break;
551                 case 3: sprintf(string, "Hex Samples"); break;
552                 case 4: sprintf(string, "Frames"); break;
553                 case 5: sprintf(string, "Feet-frames"); break;
554                 case 8: sprintf(string, "Seconds"); break;
555         }
556         
557         return string;
560 #undef BYTE_ORDER
561 #define BYTE_ORDER ((*(u_int32_t*)"a   ") & 0x00000001)
563 void* Units::int64_to_ptr(uint64_t value)
565         unsigned char *value_dissected = (unsigned char*)&value;
566         void *result;
567         unsigned char *data = (unsigned char*)&result;
569 // Must be done behind the compiler's back
570         if(sizeof(void*) == 4)
571         {
572                 if(!BYTE_ORDER)
573                 {
574                         data[0] = value_dissected[4];
575                         data[1] = value_dissected[5];
576                         data[2] = value_dissected[6];
577                         data[3] = value_dissected[7];
578                 }
579                 else
580                 {
581                         data[0] = value_dissected[0];
582                         data[1] = value_dissected[1];
583                         data[2] = value_dissected[2];
584                         data[3] = value_dissected[3];
585                 }
586         }
587         else
588         {
589                 data[0] = value_dissected[0];
590                 data[1] = value_dissected[1];
591                 data[2] = value_dissected[2];
592                 data[3] = value_dissected[3];
593                 data[4] = value_dissected[4];
594                 data[5] = value_dissected[5];
595                 data[6] = value_dissected[6];
596                 data[7] = value_dissected[7];
597         }
598         return result;
601 uint64_t Units::ptr_to_int64(void *ptr)
603         unsigned char *ptr_dissected = (unsigned char*)&ptr;
604         int64_t result = 0;
605         unsigned char *data = (unsigned char*)&result;
606 // Don't do this at home.
607         if(sizeof(void*) == 4)
608         {
609                 if(!BYTE_ORDER)
610                 {
611                         data[4] = ptr_dissected[0];
612                         data[5] = ptr_dissected[1];
613                         data[6] = ptr_dissected[2];
614                         data[7] = ptr_dissected[3];
615                 }
616                 else
617                 {
618                         data[0] = ptr_dissected[0];
619                         data[1] = ptr_dissected[1];
620                         data[2] = ptr_dissected[2];
621                         data[3] = ptr_dissected[3];
622                 }
623         }
624         else
625         {
626                 data[0] = ptr_dissected[0];
627                 data[1] = ptr_dissected[1];
628                 data[2] = ptr_dissected[2];
629                 data[3] = ptr_dissected[3];
630                 data[4] = ptr_dissected[4];
631                 data[5] = ptr_dissected[5];
632                 data[6] = ptr_dissected[6];
633                 data[7] = ptr_dissected[7];
634         }
635         return result;
638 char* Units::format_to_separators(int time_format)
640         switch(time_format)
641         {
642                 case TIME_SECONDS:     return "0000.000";
643                 case TIME_HMS:         return "0:00:00.000";
644                 case TIME_HMS2:        return "0:00:00";
645                 case TIME_HMS3:        return "00:00:00";
646                 case TIME_HMSF:        return "0:00:00:00";
647                 case TIME_SAMPLES:     return 0;
648                 case TIME_SAMPLES_HEX: return 0;
649                 case TIME_FRAMES:      return 0;
650                 case TIME_FEET_FRAMES: return "00000-00";
651         }
652         return 0;
655 void Units::punctuate(char *string)
657         int len = strlen(string);
658         int commas = (len - 1) / 3;
659         for(int i = len + commas, j = len, k; j >= 0 && i >= 0; i--, j--)
660         {
661                 k = (len - j - 1) / 3;
662                 if(k * 3 == len - j - 1 && j != len - 1 && string[j] != 0)
663                 {
664                         string[i--] = ',';
665                 }
667                 string[i] = string[j];
668         }
671 void Units::fix_double(double *x)
673         *x = *x;
679 //      Local Variables:
680 //      mode: C++
681 //      c-file-style: "linux"
682 //      End: