r288: This commit was manufactured by cvs2svn to create tag 'hv_1_2_0'.
[cinelerra_cv/mob.git] / hvirtual / guicast / units.C
blob8d9c21e3b93a3d4dc30e5adb886dcd8fe87ace39
1 #include "units.h"
2 #include <stdlib.h>
4 float* DB::topower = 0;
5 int* Freq::freqtable = 0;
8 DB::DB(float infinitygain)
10         this->infinitygain = infinitygain;
11         if(!topower)
12         {
13                 int i;
14                 float value;
16                 // db to power table
17                 topower = new float[(MAXGAIN - INFINITYGAIN) * 10 + 1];
18                 topower += -INFINITYGAIN * 10;
19                 for(i = INFINITYGAIN * 10; i <= MAXGAIN * 10; i++)
20                 {
21                         topower[i] = pow(10, (float)i / 10 / 20);
22                         
23 //printf("%f %f\n", (float)i/10, topower[i]);
24                 }
25                 topower[INFINITYGAIN * 10] = 0;   // infinity gain
26         }
27         db = 0;
30 float DB::fromdb_table() 
31
32         return db = topower[(int)(db * 10)]; 
35 float DB::fromdb_table(float db) 
36
37         if(db > MAXGAIN) db = MAXGAIN;
38         if(db <= INFINITYGAIN) return 0;
39         return db = topower[(int)(db * 10)]; 
42 float DB::fromdb()
44         return pow(10, db / 20);
47 float DB::fromdb(float db)
49         return pow(10, db / 20);
52 // set db to the power given using a formula
53 float DB::todb(float power)
55         float db;
56         if(power == 0) 
57                 db = -100;
58         else 
59         {
60                 db = (float)(20 * log10(power));
61                 if(db < -100) db = -100;
62         }
63         return db;
67 Freq::Freq()
69         init_table();
70         freq = 0;
73 Freq::Freq(const Freq& oldfreq)
75         this->freq = oldfreq.freq;
78 void Freq::init_table()
80         if(!freqtable)
81         {
82                 freqtable = new int[TOTALFREQS + 1];
83 // starting frequency
84                 double freq1 = 27.5, freq2 = 55;  
85 // Some number divisable by three.  This depends on the value of TOTALFREQS
86                 int scale = 105;   
88                 freqtable[0] = 0;
89                 for(int i = 1, j = 0; i <= TOTALFREQS; i++, j++)
90                 {
91                 freqtable[i] = (int)(freq1 + (freq2 - freq1) / scale * j + 0.5);
92 //printf("Freq::init_table %d\n", freqtable[i]);
93                 if(j >= scale)
94                         {
95                                 freq1 = freq2;
96                                 freq2 *= 2;
97                                 j = 0;
98                         }
99                 }
100         }
103 int Freq::fromfreq() 
105         int i;
107         for(i = 0; i < TOTALFREQS && freqtable[i] < freq; i++)
108         ;
109         return(i);
112 int Freq::fromfreq(int index) 
114         int i;
116         init_table();
117         for(i = 0; i < TOTALFREQS && freqtable[i] < index; i++)
118         ;
119         return(i);
122 int Freq::tofreq(int index)
124         init_table();
125         int freq = freqtable[index]; 
126         return freq; 
129 Freq& Freq::operator++() 
131         if(freq < TOTALFREQS) freq++;
132         return *this;
134         
135 Freq& Freq::operator--()
137         if(freq > 0) freq--;
138         return *this;
140         
141 int Freq::operator>(Freq &newfreq) { return freq > newfreq.freq; }
142 int Freq::operator<(Freq &newfreq) { return freq < newfreq.freq; }
143 Freq& Freq::operator=(const Freq &newfreq) { freq = newfreq.freq; return *this; }
144 int Freq::operator=(const int newfreq) { freq = newfreq; return newfreq; }
145 int Freq::operator!=(Freq &newfreq) { return freq != newfreq.freq; }
146 int Freq::operator==(Freq &newfreq) { return freq == newfreq.freq; }
147 int Freq::operator==(int newfreq) { return freq == newfreq; }
149 char* Units::totext(char *text, 
150                         double seconds, 
151                         int time_format, 
152                         int sample_rate, 
153                         float frame_rate, 
154                         float frames_per_foot)    // give text representation as time
156         int hour, minute, second, thousandths;
157         int64_t frame, feet;
159         switch(time_format)
160         {
161                 case TIME_HMS:
162                 {
163                         seconds = fabs(seconds);
164                         hour = (int)(seconds / 3600);
165                         minute = (int)(seconds / 60 - hour * 60);
166                         second = (int)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
167                         thousandths = (int)(seconds * 1000) % 1000;
168                         sprintf(text, "%d:%02d:%02d.%03d", 
169                                 hour, 
170                                 minute, 
171                                 second, 
172                                 thousandths);
173                         return text;
174                 }
175                   break;
176                 
177                 case TIME_HMS2:
178                 {
179                         float second;
180                         seconds = fabs(seconds);
181                         hour = (int)(seconds / 3600);
182                         minute = (int)(seconds / 60 - hour * 60);
183                         second = (float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
184                         sprintf(text, "%d:%02d:%02d", hour, minute, (int)second);
185                         return text;
186                 }
187                   break;
189                 case TIME_HMS3:
190                 {
191                         float second;
192                         seconds = fabs(seconds);
193                         hour = (int)(seconds / 3600);
194                         minute = (int)(seconds / 60 - hour * 60);
195                         second = (float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
196                         sprintf(text, "%02d:%02d:%02d", hour, minute, (int)second);
197                         return text;
198                 }
199                   break;
201                 case TIME_HMSF:
202                 {
203                         int second;
204                         seconds = fabs(seconds);
205                         hour = (int)(seconds / 3600);
206                         minute = (int)(seconds / 60 - hour * 60);
207                         second = (int)(seconds - hour * 3600 - minute * 60);
208                         frame = (int64_t)round(frame_rate * 
209                                  (float)((float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60 - second));
210                         sprintf(text, "%01d:%02d:%02d:%02ld", hour, minute, second, frame);
211                         return text;
212                 }
213                         break;
214                         
215                 case TIME_SAMPLES:
216                         sprintf(text, "%09ld", to_int64(seconds * sample_rate));
217                         break;
218                 
219                 case TIME_SAMPLES_HEX:
220                         sprintf(text, "%08x", to_int64(seconds * sample_rate));
221                         break;
222                 
223                 case TIME_FRAMES:
224                         frame = to_int64(seconds * frame_rate);
225                         sprintf(text, "%06ld", frame);
226                         return text;
227                         break;
228                 
229                 case TIME_FEET_FRAMES:
230                         frame = to_int64(seconds * frame_rate);
231                         feet = (int64_t)(frame / frames_per_foot);
232                         sprintf(text, "%05ld-%02ld", 
233                                 feet, 
234                                 (int64_t)(frame - feet * frames_per_foot));
235                         return text;
236                         break;
237         }
238         return text;
242 char* Units::totext(char *text, 
243                 int64_t samples, 
244                 int samplerate, 
245                 int time_format, 
246                 float frame_rate,
247                 float frames_per_foot)
249         return totext(text, (double)samples / samplerate, time_format, samplerate, frame_rate, frames_per_foot);
250 }    // give text representation as time
252 int64_t Units::fromtext(char *text, 
253                         int samplerate, 
254                         int time_format, 
255                         float frame_rate,
256                         float frames_per_foot)
258         int64_t hours, minutes, frames, total_samples, i, j;
259         int64_t feet;
260         float seconds;
261         char string[256];
262         
263         switch(time_format)
264         {
265                 case TIME_HMS:
266                 case TIME_HMS2:
267                 case TIME_HMS3:
268 // get hours
269                         i = 0;
270                         j = 0;
271                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
272                         string[j] = 0;
273                         hours = atol(string);
274 // get minutes
275                         j = 0;
276 // skip separator
277                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
278                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
279                         string[j] = 0;
280                         minutes = atol(string);
281                         
282 // get seconds
283                         j = 0;
284 // skip separator
285                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
286                         while((text[i] == '.' || (text[i] >=48 && text[i] <= 57)) && j < 10) string[j++] = text[i++];
287                         string[j] = 0;
288                         seconds = atof(string);
290                         total_samples = (uint64_t)(((double)seconds + minutes * 60 + hours * 3600) * samplerate);
291                         return total_samples;
292                         break;
294                 case TIME_HMSF:
295 // get hours
296                         i = 0;
297                         j = 0;
298                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
299                         string[j] = 0;
300                         hours = atol(string);
301                         
302 // get minutes
303                         j = 0;
304 // skip separator
305                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
306                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
307                         string[j] = 0;
308                         minutes = atol(string);
309                         
310 // get seconds
311                         j = 0;
312 // skip separator
313                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
314                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
315                         string[j] = 0;
316                         seconds = atof(string);
317                         
318 // skip separator
319                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
320 // get frames
321                         j = 0;
322                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
323                         string[j] = 0;
324                         frames = atol(string);
325                         
326                         total_samples = (int64_t)(((float)frames / frame_rate + seconds + minutes*60 + hours*3600) * samplerate);
327                         return total_samples;
328                         break;
330                 case TIME_SAMPLES:
331                         return atol(text);
332                         break;
333                 
334                 case TIME_SAMPLES_HEX:
335                         sscanf(text, "%x", &total_samples);
336                         return total_samples;
337                 
338                 case TIME_FRAMES:
339                         return (int64_t)(atof(text) / frame_rate * samplerate);
340                         break;
341                 
342                 case TIME_FEET_FRAMES:
343 // Get feet
344                         i = 0;
345                         j = 0;
346                         while(text[i] >=48 && text[i] <= 57 && text[i] != 0 && j < 10) string[j++] = text[i++];
347                         string[j] = 0;
348                         feet = atol(string);
350 // skip separator
351                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
353 // Get frames
354                         j = 0;
355                         while(text[i] >=48 && text[i] <= 57 && text[i] != 0 && j < 10) string[j++] = text[i++];
356                         string[j] = 0;
357                         frames = atol(string);
358                         return (int64_t)(((float)feet * frames_per_foot + frames) / frame_rate * samplerate);
359                         break;
360         }
361         return 0;
364 double Units::text_to_seconds(char *text, 
365                                 int samplerate, 
366                                 int time_format, 
367                                 float frame_rate, 
368                                 float frames_per_foot)
370         return (double)fromtext(text, 
371                 samplerate, 
372                 time_format, 
373                 frame_rate, 
374                 frames_per_foot) / samplerate;
382 float Units::toframes(int64_t samples, int sample_rate, float framerate) 
384         return (float)samples / sample_rate * framerate; 
385 } // give position in frames
387 int64_t Units::toframes_round(int64_t samples, int sample_rate, float framerate) 
389 // used in editing
390         float result_f = (float)samples / sample_rate * framerate; 
391         int64_t result_l = (int64_t)(result_f + 0.5);
392         return result_l;
395 double Units::fix_framerate(double value)
397         if(value > 29.5 && value < 30) 
398                 value = (double)30000 / (double)1001;
399         else
400         if(value > 59.5 && value < 60) 
401                 value = (double)60000 / (double)1001;
402         else
403         if(value > 23.5 && value < 24) 
404                 value = (double)24000 / (double)1001;
405         
406         return value;
409 double Units::atoframerate(char *text)
411         double result = atof(text);
412         return fix_framerate(result);
416 int64_t Units::tosamples(float frames, int sample_rate, float framerate) 
418         float result = (frames / framerate * sample_rate);
419         
420         if(result - (int)result) result += 1;
421         return (int64_t)result;
422 } // give position in samples
425 float Units::xy_to_polar(int x, int y)
427         float angle;
428         if(x > 0 && y <= 0)
429         {
430                 angle = atan((float)-y / x) / (2 * M_PI) * 360;
431         }
432         else
433         if(x < 0 && y <= 0)
434         {
435                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
436         }
437         else
438         if(x < 0 && y > 0)
439         {
440                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
441         }
442         else
443         if(x > 0 && y > 0)
444         {
445                 angle = 360 + atan((float)-y / x) / (2 * M_PI) * 360;
446         }
447         else
448         if(x == 0 && y < 0)
449         {
450                 angle = 90;
451         }
452         else
453         if(x == 0 && y > 0)
454         {
455                 angle = 270;
456         }
457         else
458         if(x == 0 && y == 0)
459         {
460                 angle = 0;
461         }
463         return angle;
466 void Units::polar_to_xy(float angle, int radius, int &x, int &y)
468         while(angle < 0) angle += 360;
470         x = (int)(cos(angle / 360 * (2 * M_PI)) * radius);
471         y = (int)(-sin(angle / 360 * (2 * M_PI)) * radius);
474 int64_t Units::round(double result)
476         return (int64_t)(result < 0 ? result - 0.5 : result + 0.5);
479 float Units::quantize10(float value)
481         int64_t temp = (int64_t)(value * 10 + 0.5);
482         value = (float)temp / 10;
483         return value;
486 float Units::quantize(float value, float precision)
488         int64_t temp = (int64_t)(value / precision + 0.5);
489         value = (float)temp * precision;
490         return value;
494 int64_t Units::to_int64(double result)
496 // This must round up if result is one sample within cieling.
497 // Sampling rates below 48000 may cause more problems.
498         return (int64_t)(result < 0 ? (result - 0.005) : (result + 0.005));
501 char* Units::print_time_format(int time_format, char *string)
503         switch(time_format)
504         {
505                 case 0: sprintf(string, "Hours:Minutes:Seconds.xxx"); break;
506                 case 1: sprintf(string, "Hours:Minutes:Seconds:Frames"); break;
507                 case 2: sprintf(string, "Samples"); break;
508                 case 3: sprintf(string, "Hex Samples"); break;
509                 case 4: sprintf(string, "Frames"); break;
510                 case 5: sprintf(string, "Feet-frames"); break;
511         }
512         
513         return string;
516 #undef BYTE_ORDER
517 #define BYTE_ORDER ((*(u_int32_t*)"a   ") & 0x00000001)
519 void* Units::int64_to_ptr(uint64_t value)
521         unsigned char *value_dissected = (unsigned char*)&value;
522         void *result;
523         unsigned char *data = (unsigned char*)&result;
525 // Must be done behind the compiler's back
526         if(sizeof(void*) == 4)
527         {
528                 if(!BYTE_ORDER)
529                 {
530                         data[0] = value_dissected[4];
531                         data[1] = value_dissected[5];
532                         data[2] = value_dissected[6];
533                         data[3] = value_dissected[7];
534                 }
535                 else
536                 {
537                         data[0] = value_dissected[0];
538                         data[1] = value_dissected[1];
539                         data[2] = value_dissected[2];
540                         data[3] = value_dissected[3];
541                 }
542         }
543         else
544         {
545                 data[0] = value_dissected[0];
546                 data[1] = value_dissected[1];
547                 data[2] = value_dissected[2];
548                 data[3] = value_dissected[3];
549                 data[4] = value_dissected[4];
550                 data[5] = value_dissected[5];
551                 data[6] = value_dissected[6];
552                 data[7] = value_dissected[7];
553         }
554         return result;
557 uint64_t Units::ptr_to_int64(void *ptr)
559         unsigned char *ptr_dissected = (unsigned char*)&ptr;
560         int64_t result = 0;
561         unsigned char *data = (unsigned char*)&result;
563 // Don't do this at home.
564         if(sizeof(void*) == 4)
565         {
566                 if(!BYTE_ORDER)
567                 {
568                         data[4] = ptr_dissected[0];
569                         data[5] = ptr_dissected[1];
570                         data[6] = ptr_dissected[2];
571                         data[7] = ptr_dissected[3];
572                 }
573                 else
574                 {
575                         data[0] = ptr_dissected[0];
576                         data[1] = ptr_dissected[1];
577                         data[2] = ptr_dissected[2];
578                         data[3] = ptr_dissected[3];
579                 }
580         }
581         else
582         {
583                 data[0] = ptr_dissected[0];
584                 data[1] = ptr_dissected[1];
585                 data[2] = ptr_dissected[2];
586                 data[3] = ptr_dissected[3];
587                 data[4] = ptr_dissected[4];
588                 data[5] = ptr_dissected[5];
589                 data[6] = ptr_dissected[6];
590                 data[7] = ptr_dissected[7];
591         }
592         return result;
595 char* Units::format_to_separators(int time_format)
597         switch(time_format)
598         {
599                 case TIME_HMS:         return "0:00:00.000";
600                 case TIME_HMS2:        return "0:00:00";
601                 case TIME_HMS3:        return "00:00:00";
602                 case TIME_HMSF:        return "0:00:00:00";
603                 case TIME_SAMPLES:     return 0;
604                 case TIME_SAMPLES_HEX: return 0;
605                 case TIME_FRAMES:      return 0;
606                 case TIME_FEET_FRAMES: return "00000-00";
607         }
608         return 0;