Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

units.C

Go to the documentation of this file.
00001 #include "bcwindowbase.inc"
00002 #include "units.h"
00003 
00004 
00005 #include <stdlib.h>
00006 #include <string.h>
00007 
00008 // NOTE: DB::allocated is the original allocation, to which we keep a
00009 // pointer so that in theory we could have a destructor. DB::topower
00010 // is a pointer into the middle of DB::allocated, which allows us to
00011 // do lookups using negative array coefficients.
00012 float* DB::topower = 0;
00013 float* DB::allocated = NULL;
00014 
00015 int* Freq::freqtable = 0;
00016 
00017 
00018 DB::DB(float infinitygain)
00019 {
00020         this->infinitygain = infinitygain;
00021         if(allocated == NULL)
00022         {
00023                 int i;
00024                 float value;
00025 
00026                 // db to power table
00027                 allocated = new float[(MAXGAIN - INFINITYGAIN) * 10 + 1];
00028                 topower = allocated + (-INFINITYGAIN * 10);
00029                 for(i = INFINITYGAIN * 10; i <= MAXGAIN * 10; i++)
00030                 {
00031                         topower[i] = pow(10, (float)i / 10 / 20);
00032                         
00033 //printf("%f %f\n", (float)i/10, topower[i]);
00034                 }
00035                 topower[INFINITYGAIN * 10] = 0;   // infinity gain
00036         }
00037         db = 0;
00038 }
00039 
00040 // FUTURE: would bounds checking be possible here?  Or at least make private?
00041 float DB::fromdb_table() 
00042 { 
00043         return db = topower[(int)(db * 10)]; 
00044 }
00045 
00046 float DB::fromdb_table(float db) 
00047 { 
00048         if(db > MAXGAIN) db = MAXGAIN;
00049         if(db <= INFINITYGAIN) return 0;
00050         return db = topower[(int)(db * 10)]; 
00051 }
00052 
00053 float DB::fromdb()
00054 {
00055         return pow(10, db / 20);
00056 }
00057 
00058 float DB::fromdb(float db)
00059 {
00060         return pow(10, db / 20);
00061 }
00062 
00063 // set db to the power given using a formula
00064 float DB::todb(float power)
00065 {
00066         float db;
00067         if(power == 0) 
00068                 db = -100;
00069         else 
00070         {
00071                 db = (float)(20 * log10(power));
00072                 if(db < -100) db = -100;
00073         }
00074         return db;
00075 }
00076 
00077 
00078 Freq::Freq()
00079 {
00080         init_table();
00081         freq = 0;
00082 }
00083 
00084 Freq::Freq(const Freq& oldfreq)
00085 {
00086         this->freq = oldfreq.freq;
00087 }
00088 
00089 void Freq::init_table()
00090 {
00091         if(!freqtable)
00092         {
00093                 freqtable = new int[TOTALFREQS + 1];
00094 // starting frequency
00095                 double freq1 = 27.5, freq2 = 55;  
00096 // Some number divisable by three.  This depends on the value of TOTALFREQS
00097                 int scale = 105;   
00098 
00099                 freqtable[0] = 0;
00100                 for(int i = 1, j = 0; i <= TOTALFREQS; i++, j++)
00101                 {
00102                 freqtable[i] = (int)(freq1 + (freq2 - freq1) / scale * j + 0.5);
00103 //printf("Freq::init_table %d\n", freqtable[i]);
00104                 if(j >= scale)
00105                         {
00106                                 freq1 = freq2;
00107                                 freq2 *= 2;
00108                                 j = 0;
00109                         }
00110                 }
00111         }
00112 }
00113 
00114 int Freq::fromfreq() 
00115 {
00116         int i;
00117 
00118         for(i = 0; i < TOTALFREQS && freqtable[i] < freq; i++)
00119         ;
00120         return(i);
00121 };
00122 
00123 int Freq::fromfreq(int index) 
00124 {
00125         int i;
00126 
00127         init_table();
00128         for(i = 0; i < TOTALFREQS && freqtable[i] < index; i++)
00129         ;
00130         return(i);
00131 };
00132 
00133 int Freq::tofreq(int index)
00134 { 
00135         init_table();
00136         int freq = freqtable[index]; 
00137         return freq; 
00138 }
00139 
00140 Freq& Freq::operator++() 
00141 {
00142         if(freq < TOTALFREQS) freq++;
00143         return *this;
00144 }
00145         
00146 Freq& Freq::operator--()
00147 {
00148         if(freq > 0) freq--;
00149         return *this;
00150 }
00151         
00152 int Freq::operator>(Freq &newfreq) { return freq > newfreq.freq; }
00153 int Freq::operator<(Freq &newfreq) { return freq < newfreq.freq; }
00154 Freq& Freq::operator=(const Freq &newfreq) { freq = newfreq.freq; return *this; }
00155 int Freq::operator=(const int newfreq) { freq = newfreq; return newfreq; }
00156 int Freq::operator!=(Freq &newfreq) { return freq != newfreq.freq; }
00157 int Freq::operator==(Freq &newfreq) { return freq == newfreq.freq; }
00158 int Freq::operator==(int newfreq) { return freq == newfreq; }
00159 
00160 char* Units::totext(char *text, 
00161                         double seconds, 
00162                         int time_format, 
00163                         int sample_rate, 
00164                         float frame_rate, 
00165                         float frames_per_foot)    // give text representation as time
00166 {
00167         int hour, minute, second, thousandths;
00168         int64_t frame, feet;
00169 
00170         switch(time_format)
00171         {
00172                 case TIME_SECONDS:
00173                         seconds = fabs(seconds);
00174                         sprintf(text, "%04d.%03d", (int)seconds, (int)(seconds * 1000) % 1000);
00175                         return text;
00176                         break;
00177 
00178                 case TIME_HMS:
00179                         seconds = fabs(seconds);
00180                         hour = (int)(seconds / 3600);
00181                         minute = (int)(seconds / 60 - hour * 60);
00182                         second = (int)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
00183                         thousandths = (int)(seconds * 1000) % 1000;
00184                         sprintf(text, "%d:%02d:%02d.%03d", 
00185                                 hour, 
00186                                 minute, 
00187                                 second, 
00188                                 thousandths);
00189                         return text;
00190                   break;
00191                 
00192                 case TIME_HMS2:
00193                 {
00194                         float second;
00195                         seconds = fabs(seconds);
00196                         hour = (int)(seconds / 3600);
00197                         minute = (int)(seconds / 60 - hour * 60);
00198                         second = (float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
00199                         sprintf(text, "%d:%02d:%02d", hour, minute, (int)second);
00200                         return text;
00201                 }
00202                   break;
00203 
00204                 case TIME_HMS3:
00205                 {
00206                         float second;
00207                         seconds = fabs(seconds);
00208                         hour = (int)(seconds / 3600);
00209                         minute = (int)(seconds / 60 - hour * 60);
00210                         second = (float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
00211                         sprintf(text, "%02d:%02d:%02d", hour, minute, (int)second);
00212                         return text;
00213                 }
00214                   break;
00215 
00216                 case TIME_HMSF:
00217                 {
00218                         int second;
00219                         seconds = fabs(seconds);
00220                         hour = (int)(seconds / 3600);
00221                         minute = (int)(seconds / 60 - hour * 60);
00222                         second = (int)(seconds - hour * 3600 - minute * 60);
00223 //                      frame = (int64_t)round(frame_rate * 
00224 //                               (float)((float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60 - second));
00225 //                      sprintf(text, "%01d:%02d:%02d:%02ld", hour, minute, second, frame);
00226                         frame = (int64_t)((double)frame_rate * 
00227                                         seconds + 
00228                                         0.0000001) - 
00229                                 (int64_t)((double)frame_rate * 
00230                                         (hour * 
00231                                         3600 + 
00232                                         minute * 
00233                                         60 + 
00234                                         second) + 
00235                                 0.0000001);   
00236                         sprintf(text, "%01d:%02d:%02d:%02ld", hour, minute, second, frame);
00237                         return text;
00238                 }
00239                         break;
00240                         
00241                 case TIME_SAMPLES:
00242                         sprintf(text, "%09ld", to_int64(seconds * sample_rate));
00243                         break;
00244                 
00245                 case TIME_SAMPLES_HEX:
00246                         sprintf(text, "%08x", to_int64(seconds * sample_rate));
00247                         break;
00248                 
00249                 case TIME_FRAMES:
00250                         frame = to_int64(seconds * frame_rate);
00251                         sprintf(text, "%06ld", frame);
00252                         return text;
00253                         break;
00254                 
00255                 case TIME_FEET_FRAMES:
00256                         frame = to_int64(seconds * frame_rate);
00257                         feet = (int64_t)(frame / frames_per_foot);
00258                         sprintf(text, "%05ld-%02ld", 
00259                                 feet, 
00260                                 (int64_t)(frame - feet * frames_per_foot));
00261                         return text;
00262                         break;
00263         }
00264         return text;
00265 }
00266 
00267 
00268 // give text representation as time
00269 char* Units::totext(char *text, 
00270                 int64_t samples, 
00271                 int samplerate, 
00272                 int time_format, 
00273                 float frame_rate,
00274                 float frames_per_foot)
00275 {
00276         return totext(text, (double)samples / samplerate, time_format, samplerate, frame_rate, frames_per_foot);
00277 }    
00278 
00279 int64_t Units::fromtext(char *text, 
00280                         int samplerate, 
00281                         int time_format, 
00282                         float frame_rate,
00283                         float frames_per_foot)
00284 {
00285         int64_t hours, minutes, frames, total_samples, i, j;
00286         int64_t feet;
00287         double seconds;
00288         char string[BCTEXTLEN];
00289         
00290         switch(time_format)
00291         {
00292                 case TIME_SECONDS:
00293                         seconds = atof(text);
00294                         return (int64_t)(seconds * samplerate);
00295                         break;
00296 
00297                 case TIME_HMS:
00298                 case TIME_HMS2:
00299                 case TIME_HMS3:
00300 // get hours
00301                         i = 0;
00302                         j = 0;
00303                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
00304                         string[j] = 0;
00305                         hours = atol(string);
00306 // get minutes
00307                         j = 0;
00308 // skip separator
00309                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
00310                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
00311                         string[j] = 0;
00312                         minutes = atol(string);
00313                         
00314 // get seconds
00315                         j = 0;
00316 // skip separator
00317                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
00318                         while((text[i] == '.' || (text[i] >=48 && text[i] <= 57)) && j < 10) string[j++] = text[i++];
00319                         string[j] = 0;
00320                         seconds = atof(string);
00321 
00322                         total_samples = (uint64_t)(((double)seconds + minutes * 60 + hours * 3600) * samplerate);
00323                         return total_samples;
00324                         break;
00325 
00326                 case TIME_HMSF:
00327 // get hours
00328                         i = 0;
00329                         j = 0;
00330                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
00331                         string[j] = 0;
00332                         hours = atol(string);
00333                         
00334 // get minutes
00335                         j = 0;
00336 // skip separator
00337                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
00338                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
00339                         string[j] = 0;
00340                         minutes = atol(string);
00341                         
00342 // get seconds
00343                         j = 0;
00344 // skip separator
00345                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
00346                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
00347                         string[j] = 0;
00348                         seconds = atof(string);
00349                         
00350 // skip separator
00351                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
00352 // get frames
00353                         j = 0;
00354                         while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
00355                         string[j] = 0;
00356                         frames = atol(string);
00357                         
00358                         total_samples = (int64_t)(((float)frames / frame_rate + seconds + minutes*60 + hours*3600) * samplerate);
00359                         return total_samples;
00360                         break;
00361 
00362                 case TIME_SAMPLES:
00363                         return atol(text);
00364                         break;
00365                 
00366                 case TIME_SAMPLES_HEX:
00367                         sscanf(text, "%x", &total_samples);
00368                         return total_samples;
00369                 
00370                 case TIME_FRAMES:
00371                         return (int64_t)(atof(text) / frame_rate * samplerate);
00372                         break;
00373                 
00374                 case TIME_FEET_FRAMES:
00375 // Get feet
00376                         i = 0;
00377                         j = 0;
00378                         while(text[i] >=48 && text[i] <= 57 && text[i] != 0 && j < 10) string[j++] = text[i++];
00379                         string[j] = 0;
00380                         feet = atol(string);
00381 
00382 // skip separator
00383                         while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
00384 
00385 // Get frames
00386                         j = 0;
00387                         while(text[i] >=48 && text[i] <= 57 && text[i] != 0 && j < 10) string[j++] = text[i++];
00388                         string[j] = 0;
00389                         frames = atol(string);
00390                         return (int64_t)(((float)feet * frames_per_foot + frames) / frame_rate * samplerate);
00391                         break;
00392         }
00393         return 0;
00394 }
00395 
00396 double Units::text_to_seconds(char *text, 
00397                                 int samplerate, 
00398                                 int time_format, 
00399                                 float frame_rate, 
00400                                 float frames_per_foot)
00401 {
00402         return (double)fromtext(text, 
00403                 samplerate, 
00404                 time_format, 
00405                 frame_rate, 
00406                 frames_per_foot) / samplerate;
00407 }
00408 
00409 
00410 
00411 
00412 
00413 
00414 float Units::toframes(int64_t samples, int sample_rate, float framerate) 
00415 { 
00416         return (float)samples / sample_rate * framerate; 
00417 } // give position in frames
00418 
00419 int64_t Units::toframes_round(int64_t samples, int sample_rate, float framerate) 
00420 {
00421 // used in editing
00422         float result_f = (float)samples / sample_rate * framerate; 
00423         int64_t result_l = (int64_t)(result_f + 0.5);
00424         return result_l;
00425 }
00426 
00427 double Units::fix_framerate(double value)
00428 {
00429         if(value > 29.5 && value < 30) 
00430                 value = (double)30000 / (double)1001;
00431         else
00432         if(value > 59.5 && value < 60) 
00433                 value = (double)60000 / (double)1001;
00434         else
00435         if(value > 23.5 && value < 24) 
00436                 value = (double)24000 / (double)1001;
00437         
00438         return value;
00439 }
00440 
00441 double Units::atoframerate(char *text)
00442 {
00443         double result = atof(text);
00444         return fix_framerate(result);
00445 }
00446 
00447 
00448 int64_t Units::tosamples(float frames, int sample_rate, float framerate) 
00449 { 
00450         float result = (frames / framerate * sample_rate);
00451         
00452         if(result - (int)result) result += 1;
00453         return (int64_t)result;
00454 } // give position in samples
00455 
00456 
00457 float Units::xy_to_polar(int x, int y)
00458 {
00459         float angle;
00460         if(x > 0 && y <= 0)
00461         {
00462                 angle = atan((float)-y / x) / (2 * M_PI) * 360;
00463         }
00464         else
00465         if(x < 0 && y <= 0)
00466         {
00467                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
00468         }
00469         else
00470         if(x < 0 && y > 0)
00471         {
00472                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
00473         }
00474         else
00475         if(x > 0 && y > 0)
00476         {
00477                 angle = 360 + atan((float)-y / x) / (2 * M_PI) * 360;
00478         }
00479         else
00480         if(x == 0 && y < 0)
00481         {
00482                 angle = 90;
00483         }
00484         else
00485         if(x == 0 && y > 0)
00486         {
00487                 angle = 270;
00488         }
00489         else
00490         if(x == 0 && y == 0)
00491         {
00492                 angle = 0;
00493         }
00494 
00495         return angle;
00496 }
00497 
00498 void Units::polar_to_xy(float angle, int radius, int &x, int &y)
00499 {
00500         while(angle < 0) angle += 360;
00501 
00502         x = (int)(cos(angle / 360 * (2 * M_PI)) * radius);
00503         y = (int)(-sin(angle / 360 * (2 * M_PI)) * radius);
00504 }
00505 
00506 int64_t Units::round(double result)
00507 {
00508         return (int64_t)(result < 0 ? result - 0.5 : result + 0.5);
00509 }
00510 
00511 float Units::quantize10(float value)
00512 {
00513         int64_t temp = (int64_t)(value * 10 + 0.5);
00514         value = (float)temp / 10;
00515         return value;
00516 }
00517 
00518 float Units::quantize(float value, float precision)
00519 {
00520         int64_t temp = (int64_t)(value / precision + 0.5);
00521         value = (float)temp * precision;
00522         return value;
00523 }
00524 
00525 
00526 int64_t Units::to_int64(double result)
00527 {
00528 // This must round up if result is one sample within cieling.
00529 // Sampling rates below 48000 may cause more problems.
00530         return (int64_t)(result < 0 ? (result - 0.005) : (result + 0.005));
00531 }
00532 
00533 char* Units::print_time_format(int time_format, char *string)
00534 {
00535         switch(time_format)
00536         {
00537                 case 0: sprintf(string, "Hours:Minutes:Seconds.xxx"); break;
00538                 case 1: sprintf(string, "Hours:Minutes:Seconds:Frames"); break;
00539                 case 2: sprintf(string, "Samples"); break;
00540                 case 3: sprintf(string, "Hex Samples"); break;
00541                 case 4: sprintf(string, "Frames"); break;
00542                 case 5: sprintf(string, "Feet-frames"); break;
00543                 case 8: sprintf(string, "Seconds"); break;
00544         }
00545         
00546         return string;
00547 }
00548 
00549 #undef BYTE_ORDER
00550 #define BYTE_ORDER ((*(u_int32_t*)"a   ") & 0x00000001)
00551 
00552 void* Units::int64_to_ptr(uint64_t value)
00553 {
00554         unsigned char *value_dissected = (unsigned char*)&value;
00555         void *result;
00556         unsigned char *data = (unsigned char*)&result;
00557 
00558 // Must be done behind the compiler's back
00559         if(sizeof(void*) == 4)
00560         {
00561                 if(!BYTE_ORDER)
00562                 {
00563                         data[0] = value_dissected[4];
00564                         data[1] = value_dissected[5];
00565                         data[2] = value_dissected[6];
00566                         data[3] = value_dissected[7];
00567                 }
00568                 else
00569                 {
00570                         data[0] = value_dissected[0];
00571                         data[1] = value_dissected[1];
00572                         data[2] = value_dissected[2];
00573                         data[3] = value_dissected[3];
00574                 }
00575         }
00576         else
00577         {
00578                 data[0] = value_dissected[0];
00579                 data[1] = value_dissected[1];
00580                 data[2] = value_dissected[2];
00581                 data[3] = value_dissected[3];
00582                 data[4] = value_dissected[4];
00583                 data[5] = value_dissected[5];
00584                 data[6] = value_dissected[6];
00585                 data[7] = value_dissected[7];
00586         }
00587         return result;
00588 }
00589 
00590 uint64_t Units::ptr_to_int64(void *ptr)
00591 {
00592         unsigned char *ptr_dissected = (unsigned char*)&ptr;
00593         int64_t result = 0;
00594         unsigned char *data = (unsigned char*)&result;
00595 // Don't do this at home.
00596         if(sizeof(void*) == 4)
00597         {
00598                 if(!BYTE_ORDER)
00599                 {
00600                         data[4] = ptr_dissected[0];
00601                         data[5] = ptr_dissected[1];
00602                         data[6] = ptr_dissected[2];
00603                         data[7] = ptr_dissected[3];
00604                 }
00605                 else
00606                 {
00607                         data[0] = ptr_dissected[0];
00608                         data[1] = ptr_dissected[1];
00609                         data[2] = ptr_dissected[2];
00610                         data[3] = ptr_dissected[3];
00611                 }
00612         }
00613         else
00614         {
00615                 data[0] = ptr_dissected[0];
00616                 data[1] = ptr_dissected[1];
00617                 data[2] = ptr_dissected[2];
00618                 data[3] = ptr_dissected[3];
00619                 data[4] = ptr_dissected[4];
00620                 data[5] = ptr_dissected[5];
00621                 data[6] = ptr_dissected[6];
00622                 data[7] = ptr_dissected[7];
00623         }
00624         return result;
00625 }
00626 
00627 char* Units::format_to_separators(int time_format)
00628 {
00629         switch(time_format)
00630         {
00631                 case TIME_SECONDS:     return "0000.000";
00632                 case TIME_HMS:         return "0:00:00.000";
00633                 case TIME_HMS2:        return "0:00:00";
00634                 case TIME_HMS3:        return "00:00:00";
00635                 case TIME_HMSF:        return "0:00:00:00";
00636                 case TIME_SAMPLES:     return 0;
00637                 case TIME_SAMPLES_HEX: return 0;
00638                 case TIME_FRAMES:      return 0;
00639                 case TIME_FEET_FRAMES: return "00000-00";
00640         }
00641         return 0;
00642 }
00643 
00644 void Units::punctuate(char *string)
00645 {
00646         int len = strlen(string);
00647         int commas = (len - 1) / 3;
00648         for(int i = len + commas, j = len, k; j >= 0 && i >= 0; i--, j--)
00649         {
00650                 k = (len - j - 1) / 3;
00651                 if(k * 3 == len - j - 1 && j != len - 1 && string[j] != 0)
00652                 {
00653                         string[i--] = ',';
00654                 }
00655 
00656                 string[i] = string[j];
00657         }
00658 }
00659 
00660 
00661 
00662 

Generated on Sun Jan 8 13:26:35 2006 for Guicast-svn by  doxygen 1.4.4