Hi Andraž!

I am now working on BlueDot theme and I think I had the same issue.
I made a small fix in units.C file, which I haven't spoke about yet,
because my work has not finished yet.
The point is that BlueDot needs 11 digits when displaying time
in order to look nice (it's because the clock's graphic and the digits
have graded background.

I am attaching the units.C file.
I hope we can work this things out without makeing conflicting changes
on each other.
Please tell me your oppinion on how to solve this!

Miha

On sre, 2006-10-25 at 01:10 +0200, Andraž Tori wrote:
> when entering timecodes that had more than one digit number of hours, 
> timecodes got messed up.
> 
> This directly hindered one user when working on his film project.
> 
> bye
> andraz        
#include "bcwindowbase.inc"
#include "units.h"


#include <stdlib.h>
#include <string.h>

// NOTE: DB::allocated is the original allocation, to which we keep a
// pointer so that in theory we could have a destructor. DB::topower
// is a pointer into the middle of DB::allocated, which allows us to
// do lookups using negative array coefficients.
float* DB::topower = 0;
float* DB::allocated = NULL;

int* Freq::freqtable = 0;


DB::DB(float infinitygain)
{
	this->infinitygain = infinitygain;
	if(allocated == NULL)
	{
		int i;
		float value;

		// db to power table
		allocated = new float[(MAXGAIN - INFINITYGAIN) * 10 + 1];
		topower = allocated + (-INFINITYGAIN * 10);
		for(i = INFINITYGAIN * 10; i <= MAXGAIN * 10; i++)
		{
			topower[i] = pow(10, (float)i / 10 / 20);
			
//printf("%f %f\n", (float)i/10, topower[i]);
		}
		topower[INFINITYGAIN * 10] = 0;   // infinity gain
	}
	db = 0;
}

// FUTURE: would bounds checking be possible here?  Or at least make private?
float DB::fromdb_table() 
{ 
	return db = topower[(int)(db * 10)]; 
}

float DB::fromdb_table(float db) 
{ 
	if(db > MAXGAIN) db = MAXGAIN;
	if(db <= INFINITYGAIN) return 0;
	return db = topower[(int)(db * 10)]; 
}

float DB::fromdb()
{
	return pow(10, db / 20);
}

float DB::fromdb(float db)
{
	return pow(10, db / 20);
}

// set db to the power given using a formula
float DB::todb(float power)
{
	float db;
	if(power == 0) 
		db = -100;
	else 
	{
		db = (float)(20 * log10(power));
		if(db < -100) db = -100;
	}
	return db;
}


Freq::Freq()
{
	init_table();
	freq = 0;
}

Freq::Freq(const Freq& oldfreq)
{
	this->freq = oldfreq.freq;
}

void Freq::init_table()
{
	if(!freqtable)
	{
		freqtable = new int[TOTALFREQS + 1];
// starting frequency
  		double freq1 = 27.5, freq2 = 55;  
// Some number divisable by three.  This depends on the value of TOTALFREQS
  		int scale = 105;   

  		freqtable[0] = 0;
  		for(int i = 1, j = 0; i <= TOTALFREQS; i++, j++)
  		{
    		freqtable[i] = (int)(freq1 + (freq2 - freq1) / scale * j + 0.5);
//printf("Freq::init_table %d\n", freqtable[i]);
    		if(j >= scale)
			{
				freq1 = freq2;
				freq2 *= 2;
				j = 0;
			}
  		}
	}
}

int Freq::fromfreq() 
{
	int i;

  	for(i = 0; i < TOTALFREQS && freqtable[i] < freq; i++)
    	;
  	return(i);
};

int Freq::fromfreq(int index) 
{
	int i;

 	init_table();
 	for(i = 0; i < TOTALFREQS && freqtable[i] < index; i++)
    	;
  	return(i);
};

int Freq::tofreq(int index)
{ 
	init_table();
	int freq = freqtable[index]; 
	return freq; 
}

Freq& Freq::operator++() 
{
	if(freq < TOTALFREQS) freq++;
	return *this;
}
	
Freq& Freq::operator--()
{
	if(freq > 0) freq--;
	return *this;
}
	
int Freq::operator>(Freq &newfreq) { return freq > newfreq.freq; }
int Freq::operator<(Freq &newfreq) { return freq < newfreq.freq; }
Freq& Freq::operator=(const Freq &newfreq) { freq = newfreq.freq; return *this; }
int Freq::operator=(const int newfreq) { freq = newfreq; return newfreq; }
int Freq::operator!=(Freq &newfreq) { return freq != newfreq.freq; }
int Freq::operator==(Freq &newfreq) { return freq == newfreq.freq; }
int Freq::operator==(int newfreq) { return freq == newfreq; }

char* Units::totext(char *text, 
			double seconds, 
			int time_format, 
			int sample_rate, 
			float frame_rate, 
			float frames_per_foot)    // give text representation as time
{
	int hour, minute, second, thousandths;
	int64_t frame, feet;

	switch(time_format)
	{
		case TIME_SECONDS:
			seconds = fabs(seconds);
			sprintf(text, "%7d.%03d", (int)seconds, (int)(seconds * 1000) % 1000);
// sprintf(text, "%04d.%03d", (int)seconds, (int)(seconds * 1000) % 1000);
			return text;
			break;

		case TIME_HMS:
			seconds = fabs(seconds);
  			hour = (int)(seconds / 3600);
  			minute = (int)(seconds / 60 - hour * 60);
  			second = (int)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
			thousandths = (int)(seconds * 1000) % 1000;
  			sprintf(text, "%d:%02d:%02d.%03d", 
				hour, 
				minute, 
				second, 
				thousandths);
			return text;
		  break;
		
		case TIME_HMS2:
		{
			float second;
			seconds = fabs(seconds);
  			hour = (int)(seconds / 3600);
  			minute = (int)(seconds / 60 - hour * 60);
  			second = (float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
  			sprintf(text, "%d:%02d:%02d", hour, minute, (int)second);
			return text;
		}
		  break;

		case TIME_HMS3:
		{
			float second;
			seconds = fabs(seconds);
  			hour = (int)(seconds / 3600);
  			minute = (int)(seconds / 60 - hour * 60);
  			second = (float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60;
  			sprintf(text, "%02d:%02d:%02d", hour, minute, (int)second);
			return text;
		}
		  break;

		case TIME_HMSF:
		{
			int second;
			seconds = fabs(seconds);
  			hour = (int)(seconds / 3600);
  			minute = (int)(seconds / 60 - hour * 60);
  			second = (int)(seconds - hour * 3600 - minute * 60);
//   			frame = (int64_t)round(frame_rate * 
//   	 			 (float)((float)seconds - (int64_t)hour * 3600 - (int64_t)minute * 60 - second));
//   			sprintf(text, "%01d:%02d:%02d:%02ld", hour, minute, second, frame);
			frame = (int64_t)((double)frame_rate * 
					seconds + 
					0.0000001) - 
				(int64_t)((double)frame_rate * 
					(hour * 
					3600 + 
					minute * 
					60 + 
					second) + 
				0.0000001);   
			sprintf(text, "%2d:%02d:%02d:%02ld", hour, minute, second, frame);
//Original was sprintf(text, "%01d:%02d:%02d:%02ld", hour, minute, second, frame);
			return text;
		}
			break;
			
		case TIME_SAMPLES:
  			sprintf(text, "%11ld", to_int64(seconds * sample_rate));
// Originally sprintf(text, "%09ld", to_int64(seconds * sample_rate));
			break;
		
		case TIME_SAMPLES_HEX:
  			sprintf(text, "%11x", to_int64(seconds * sample_rate));
// Originally sprintf(text, "%08x", to_int64(seconds * sample_rate));
			break;
		
		case TIME_FRAMES:
			frame = to_int64(seconds * frame_rate);
			sprintf(text, "%11ld", frame);
// Original sprintf(text, "%06ld", frame);
			return text;
			break;
		
		case TIME_FEET_FRAMES:
			frame = to_int64(seconds * frame_rate);
			feet = (int64_t)(frame / frames_per_foot);
			sprintf(text, "%8ld-%02ld", 
				feet, 
				(int64_t)(frame - feet * frames_per_foot));
// Original 			sprintf(text, "%05ld-%02ld", 
//				feet, 
//				(int64_t)(frame - feet * frames_per_foot));
			return text;
			break;
	}
	return text;
}


// give text representation as time
char* Units::totext(char *text, 
		int64_t samples, 
		int samplerate, 
		int time_format, 
		float frame_rate,
		float frames_per_foot)
{
	return totext(text, (double)samples / samplerate, time_format, samplerate, frame_rate, frames_per_foot);
}    

int64_t Units::fromtext(char *text, 
			int samplerate, 
			int time_format, 
			float frame_rate,
			float frames_per_foot)
{
	int64_t hours, minutes, frames, total_samples, i, j;
	int64_t feet;
	double seconds;
	char string[BCTEXTLEN];
	
	switch(time_format)
	{
		case TIME_SECONDS:
			seconds = atof(text);
			return (int64_t)(seconds * samplerate);
			break;

		case TIME_HMS:
		case TIME_HMS2:
		case TIME_HMS3:
// get hours
			i = 0;
			j = 0;
			while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
			string[j] = 0;
			hours = atol(string);
// get minutes
			j = 0;
// skip separator
			while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
			while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
			string[j] = 0;
			minutes = atol(string);
			
// get seconds
			j = 0;
// skip separator
			while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
			while((text[i] == '.' || (text[i] >=48 && text[i] <= 57)) && j < 10) string[j++] = text[i++];
			string[j] = 0;
			seconds = atof(string);

			total_samples = (uint64_t)(((double)seconds + minutes * 60 + hours * 3600) * samplerate);
			return total_samples;
			break;

		case TIME_HMSF:
// get hours
			i = 0;
			j = 0;
			while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
			string[j] = 0;
			hours = atol(string);
			
// get minutes
			j = 0;
// skip separator
			while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
			while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
			string[j] = 0;
			minutes = atol(string);
			
// get seconds
			j = 0;
// skip separator
			while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
			while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
			string[j] = 0;
			seconds = atof(string);
			
// skip separator
			while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;
// get frames
			j = 0;
			while(text[i] >=48 && text[i] <= 57 && j < 10) string[j++] = text[i++];
			string[j] = 0;
			frames = atol(string);
			
			total_samples = (int64_t)(((float)frames / frame_rate + seconds + minutes*60 + hours*3600) * samplerate);
			return total_samples;
			break;

		case TIME_SAMPLES:
			return atol(text);
			break;
		
		case TIME_SAMPLES_HEX:
			sscanf(text, "%x", &total_samples);
			return total_samples;
		
		case TIME_FRAMES:
			return (int64_t)(atof(text) / frame_rate * samplerate);
			break;
		
		case TIME_FEET_FRAMES:
// Get feet
			i = 0;
			j = 0;
			while(text[i] >=48 && text[i] <= 57 && text[i] != 0 && j < 10) string[j++] = text[i++];
			string[j] = 0;
			feet = atol(string);

// skip separator
			while((text[i] < 48 || text[i] > 57) && text[i] != 0) i++;

// Get frames
			j = 0;
			while(text[i] >=48 && text[i] <= 57 && text[i] != 0 && j < 10) string[j++] = text[i++];
			string[j] = 0;
			frames = atol(string);
			return (int64_t)(((float)feet * frames_per_foot + frames) / frame_rate * samplerate);
			break;
	}
	return 0;
}

double Units::text_to_seconds(char *text, 
				int samplerate, 
				int time_format, 
				float frame_rate, 
				float frames_per_foot)
{
	return (double)fromtext(text, 
		samplerate, 
		time_format, 
		frame_rate, 
		frames_per_foot) / samplerate;
}




int Units::timeformat_totype(char *tcf) {
	if (!strcmp(tcf,TIME_SECONDS__STR)) return(TIME_SECONDS);
	if (!strcmp(tcf,TIME_HMS__STR)) return(TIME_HMS);
	if (!strcmp(tcf,TIME_HMS2__STR)) return(TIME_HMS2);
	if (!strcmp(tcf,TIME_HMS3__STR)) return(TIME_HMS3);
	if (!strcmp(tcf,TIME_HMSF__STR)) return(TIME_HMSF);
	if (!strcmp(tcf,TIME_SAMPLES__STR)) return(TIME_SAMPLES);
	if (!strcmp(tcf,TIME_SAMPLES_HEX__STR)) return(TIME_SAMPLES_HEX);
	if (!strcmp(tcf,TIME_FRAMES__STR)) return(TIME_FRAMES);
	if (!strcmp(tcf,TIME_FEET_FRAMES__STR)) return(TIME_FEET_FRAMES);
	return(-1);
}


float Units::toframes(int64_t samples, int sample_rate, float framerate) 
{ 
	return (float)samples / sample_rate * framerate; 
} // give position in frames

int64_t Units::toframes_round(int64_t samples, int sample_rate, float framerate) 
{
// used in editing
	float result_f = (float)samples / sample_rate * framerate; 
	int64_t result_l = (int64_t)(result_f + 0.5);
	return result_l;
}

double Units::fix_framerate(double value)
{
	if(value > 29.5 && value < 30) 
		value = (double)30000 / (double)1001;
	else
	if(value > 59.5 && value < 60) 
		value = (double)60000 / (double)1001;
	else
	if(value > 23.5 && value < 24) 
		value = (double)24000 / (double)1001;
	
	return value;
}

double Units::atoframerate(char *text)
{
	double result = atof(text);
	return fix_framerate(result);
}


int64_t Units::tosamples(float frames, int sample_rate, float framerate) 
{ 
	float result = (frames / framerate * sample_rate);
	
	if(result - (int)result) result += 1;
	return (int64_t)result;
} // give position in samples


float Units::xy_to_polar(int x, int y)
{
	float angle;
	if(x > 0 && y <= 0)
	{
		angle = atan((float)-y / x) / (2 * M_PI) * 360;
	}
	else
	if(x < 0 && y <= 0)
	{
		angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
	}
	else
	if(x < 0 && y > 0)
	{
		angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
	}
	else
	if(x > 0 && y > 0)
	{
		angle = 360 + atan((float)-y / x) / (2 * M_PI) * 360;
	}
	else
	if(x == 0 && y < 0)
	{
		angle = 90;
	}
	else
	if(x == 0 && y > 0)
	{
		angle = 270;
	}
	else
	if(x == 0 && y == 0)
	{
		angle = 0;
	}

	return angle;
}

void Units::polar_to_xy(float angle, int radius, int &x, int &y)
{
	while(angle < 0) angle += 360;

	x = (int)(cos(angle / 360 * (2 * M_PI)) * radius);
	y = (int)(-sin(angle / 360 * (2 * M_PI)) * radius);
}

int64_t Units::round(double result)
{
	return (int64_t)(result < 0 ? result - 0.5 : result + 0.5);
}

float Units::quantize10(float value)
{
	int64_t temp = (int64_t)(value * 10 + 0.5);
	value = (float)temp / 10;
	return value;
}

float Units::quantize(float value, float precision)
{
	int64_t temp = (int64_t)(value / precision + 0.5);
	value = (float)temp * precision;
	return value;
}

int64_t Units::to_int64(double result)
{
// This must round up if result is one sample within cieling.
// Sampling rates below 48000 may cause more problems.
	return (int64_t)(result < 0 ? (result - 0.005) : (result + 0.005));
}

char* Units::print_time_format(int time_format, char *string)
{
	switch(time_format)
	{
		case 0: sprintf(string, "Hours:Minutes:Seconds.xxx"); break;
		case 1: sprintf(string, "Hours:Minutes:Seconds:Frames"); break;
		case 2: sprintf(string, "Samples"); break;
		case 3: sprintf(string, "Hex Samples"); break;
		case 4: sprintf(string, "Frames"); break;
		case 5: sprintf(string, "Feet-frames"); break;
		case 8: sprintf(string, "Seconds"); break;
	}
	
	return string;
}

#undef BYTE_ORDER
#define BYTE_ORDER ((*(u_int32_t*)"a   ") & 0x00000001)

void* Units::int64_to_ptr(uint64_t value)
{
	unsigned char *value_dissected = (unsigned char*)&value;
	void *result;
	unsigned char *data = (unsigned char*)&result;

// Must be done behind the compiler's back
	if(sizeof(void*) == 4)
	{
		if(!BYTE_ORDER)
		{
			data[0] = value_dissected[4];
			data[1] = value_dissected[5];
			data[2] = value_dissected[6];
			data[3] = value_dissected[7];
		}
		else
		{
			data[0] = value_dissected[0];
			data[1] = value_dissected[1];
			data[2] = value_dissected[2];
			data[3] = value_dissected[3];
		}
	}
	else
	{
		data[0] = value_dissected[0];
		data[1] = value_dissected[1];
		data[2] = value_dissected[2];
		data[3] = value_dissected[3];
		data[4] = value_dissected[4];
		data[5] = value_dissected[5];
		data[6] = value_dissected[6];
		data[7] = value_dissected[7];
	}
	return result;
}

uint64_t Units::ptr_to_int64(void *ptr)
{
	unsigned char *ptr_dissected = (unsigned char*)&ptr;
	int64_t result = 0;
	unsigned char *data = (unsigned char*)&result;
// Don't do this at home.
	if(sizeof(void*) == 4)
	{
		if(!BYTE_ORDER)
		{
			data[4] = ptr_dissected[0];
			data[5] = ptr_dissected[1];
			data[6] = ptr_dissected[2];
			data[7] = ptr_dissected[3];
		}
		else
		{
			data[0] = ptr_dissected[0];
			data[1] = ptr_dissected[1];
			data[2] = ptr_dissected[2];
			data[3] = ptr_dissected[3];
		}
	}
	else
	{
		data[0] = ptr_dissected[0];
		data[1] = ptr_dissected[1];
		data[2] = ptr_dissected[2];
		data[3] = ptr_dissected[3];
		data[4] = ptr_dissected[4];
		data[5] = ptr_dissected[5];
		data[6] = ptr_dissected[6];
		data[7] = ptr_dissected[7];
	}
	return result;
}

char* Units::format_to_separators(int time_format)
{
	switch(time_format)
	{
		case TIME_SECONDS:     return "0000.000";
		case TIME_HMS:         return "0:00:00.000";
		case TIME_HMS2:        return "0:00:00";
		case TIME_HMS3:        return "00:00:00";
		case TIME_HMSF:        return "00:00:00:00";	// Originally 0:00:00:00, but I added one for bluedot
		case TIME_SAMPLES:     return 0;
		case TIME_SAMPLES_HEX: return 0;
		case TIME_FRAMES:      return 0;
		case TIME_FEET_FRAMES: return "00000-00";
	}
	return 0;
}

void Units::punctuate(char *string)
{
	int len = strlen(string);
	int commas = (len - 1) / 3;
	for(int i = len + commas, j = len, k; j >= 0 && i >= 0; i--, j--)
	{
		k = (len - j - 1) / 3;
		if(k * 3 == len - j - 1 && j != len - 1 && string[j] != 0)
		{
			string[i--] = ',';
		}

		string[i] = string[j];
	}
}

void Units::fix_double(double *x)
{
	*x = *x;
}



Reply via email to