diff options
Diffstat (limited to 'spectro/conv.c')
-rw-r--r-- | spectro/conv.c | 659 |
1 files changed, 71 insertions, 588 deletions
diff --git a/spectro/conv.c b/spectro/conv.c index 94023db..284a30c 100644 --- a/spectro/conv.c +++ b/spectro/conv.c @@ -64,7 +64,7 @@ #include "conv.h" #include "icoms.h" -#ifdef __APPLE__ +#ifdef UNIX_APPLE //#include <stdbool.h> #include <sys/sysctl.h> #include <sys/param.h> @@ -81,7 +81,7 @@ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 # include <objc/objc-auto.h> #endif -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ #undef DEBUG @@ -131,6 +131,8 @@ int next_con_char(void) { return c; } +#ifdef NEVER // Don't need this now. + /* Horrible hack to poll stdin when we're not interactive. */ /* This has the drawback that the char and returm must be */ /* written in one operation for the character to be recognised - */ @@ -143,9 +145,12 @@ static int th_read_char(void *pp) { DWORD bread; if ((stdinh = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { + *rp = 0; /* We've started */ return 0; } + *rp = 0; /* We've started */ + if (ReadFile(stdinh, buf, 1, &bread, NULL) && bread == 1 && buf[0] != '\r' && buf[0] != '\n') { @@ -154,32 +159,65 @@ static int th_read_char(void *pp) { return 0; } +#endif /* NEVER */ /* If there is one, return the next character from the keyboard, else return 0 */ /* (If not_interactive, always returns 0) */ int poll_con_char(void) { if (not_interactive) { /* Can't assume that it's the console */ + +#ifdef NEVER // Use better approach below. athread *getch_thread = NULL; - char c = 0; + volatile char c = 0xff; /* This is pretty horrible. The problem is that we can't use */ /* any of MSWin's async file read functions, because we */ /* have no way of ensuring that the STD_INPUT_HANDLE has been */ /* opened with FILE_FLAG_OVERLAPPED. Used a thread instead... */ - /* ReOpenFile() would fix this, but it's not available in WinXP, only Visa+ :-( */ - if ((getch_thread = new_athread(th_read_char, &c)) != NULL) { + /* ReOpenFile() would in theory fix this, but it's not available in WinXP, only Visa+, */ + /* and aparently doesn't work on stdin anyway! :-( */ + if ((getch_thread = new_athread(th_read_char, (char *)&c)) != NULL) { HANDLE stdinh; if ((stdinh = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { return 0; } - Sleep(100); /* We just hope 1 msec is enough for the thread to start */ - CancelIo(stdinh); + /* Wait for the thread to start */ + while (c == 0xff) { + Sleep(10); /* We just hope 1 msec is enough for the thread to start */ + } + Sleep(10); /* Give it time to read */ + CancelIo(stdinh); /* May not work since ReadFile() is on a different thread ? */ getch_thread->del(getch_thread); return c; } +#else /* ! NEVER */ + /* This approach is very flakey from the console, but seems */ + /* to work reliably when operated progromatically. */ + HANDLE stdinh; + char buf[10] = { 0 }, c; + DWORD bread; + + if ((stdinh = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { + return 0; + } +// printf("Waiting\n"); + if (WaitForSingleObject(stdinh, 1) == WAIT_OBJECT_0) { +// printf("stdin signalled\n"); + +// FlushFileBuffers(stdinh); +// FlushConsoleInputBuffer(stdinh); + if (ReadFile(stdinh, buf, 1, &bread, NULL)) { + int i; +// fprintf(stderr,"Read %d chars 0x%x 0x%x 0x%x\n",bread,buf[0],buf[1], buf[2]); + if (buf[0] != '\r' && buf[0] != '\n') + return buf[0]; + return 0; + } + } +#endif /* !NEVER */ return 0; } @@ -192,10 +230,23 @@ int poll_con_char(void) { } /* Suck all characters from the keyboard */ -/* (If not_interactive, does nothing) */ +/* (If not_interactive, does nothing ?) */ void empty_con_chars(void) { if (not_interactive) { + HANDLE stdinh; + char buf[100] = { 0 }, c; + DWORD bread; + + if ((stdinh = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) + return; + for (;;) { + if (WaitForSingleObject(stdinh, 1) == WAIT_OBJECT_0) { + ReadFile(stdinh, buf, 100, &bread, NULL); + } else { + break; + } + } return; } @@ -211,51 +262,6 @@ void sleep(unsigned int secs) { Sleep(secs * 1000); } -/* Sleep for the given number of msec */ -void msec_sleep(unsigned int msec) { - Sleep(msec); -} - -/* Return the current time in msec since */ -/* the first invokation of msec_time() */ -/* (Is this based on timeGetTime() ? ) */ -unsigned int msec_time() { - unsigned int rv; - static unsigned int startup = 0; - - rv = GetTickCount(); - if (startup == 0) - startup = rv; - - return rv - startup; -} - -/* Return the current time in usec */ -/* since the first invokation of usec_time() */ -/* Return -1.0 if not available */ -double usec_time() { - double rv; - LARGE_INTEGER val; - static double scale = 0.0; - static LARGE_INTEGER startup; - - if (scale == 0.0) { - if (QueryPerformanceFrequency(&val) == 0) - return -1.0; - scale = 1000000.0/val.QuadPart; - QueryPerformanceCounter(&val); - startup.QuadPart = val.QuadPart; - - } else { - QueryPerformanceCounter(&val); - } - val.QuadPart -= startup.QuadPart; - - rv = val.QuadPart * scale; - - return rv; -} - static athread *beep_thread = NULL; static int beep_delay; static int beep_freq; @@ -552,126 +558,6 @@ void empty_con_chars(void) { tcflush(STDIN_FILENO, TCIFLUSH); } -/* Sleep for the given number of msec */ -/* (Note that OS X 10.9+ App Nap can wreck this, unless */ -/* it is turned off.) */ -void msec_sleep(unsigned int msec) { -#ifdef NEVER - if (msec > 1000) { - unsigned int secs; - secs = msec / 1000; - msec = msec % 1000; - sleep(secs); - } - usleep(msec * 1000); -#else - struct timespec ts; - - ts.tv_sec = msec / 1000; - ts.tv_nsec = (msec % 1000) * 1000000; - nanosleep(&ts, NULL); -#endif -} - - -#if defined(__APPLE__) && !defined(CLOCK_MONOTONIC) - -#include <mach/mach_time.h> - -unsigned int msec_time() { - mach_timebase_info_data_t timebase; - static uint64_t startup = 0; - uint64_t time; - double msec; - - time = mach_absolute_time(); - if (startup == 0) - startup = time; - - mach_timebase_info(&timebase); - time -= startup; - msec = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e6); - - return (unsigned int)floor(msec + 0.5); -} - -/* Return the current time in usec */ -/* since the first invokation of usec_time() */ -double usec_time() { - mach_timebase_info_data_t timebase; - static uint64_t startup = 0; - uint64_t time; - double usec; - - time = mach_absolute_time(); - if (startup == 0) - startup = time; - - mach_timebase_info(&timebase); - time -= startup; - usec = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e3); - - return usec; -} - -#else - -/* Return the current time in msec */ -/* since the first invokation of msec_time() */ -unsigned int msec_time() { - unsigned int rv; - static struct timespec startup = { 0, 0 }; - struct timespec cv; - - clock_gettime(CLOCK_MONOTONIC, &cv); - - /* Set time to 0 on first invocation */ - if (startup.tv_sec == 0 && startup.tv_nsec == 0) - startup = cv; - - /* Subtract, taking care of carry */ - cv.tv_sec -= startup.tv_sec; - if (startup.tv_nsec > cv.tv_nsec) { - cv.tv_sec--; - cv.tv_nsec += 1000000000; - } - cv.tv_nsec -= startup.tv_nsec; - - /* Convert nsec to msec */ - rv = cv.tv_sec * 1000 + cv.tv_nsec / 1000000; - - return rv; -} - -/* Return the current time in usec */ -/* since the first invokation of usec_time() */ -double usec_time() { - double rv; - static struct timespec startup = { 0, 0 }; - struct timespec cv; - - clock_gettime(CLOCK_MONOTONIC, &cv); - - /* Set time to 0 on first invocation */ - if (startup.tv_sec == 0 && startup.tv_nsec == 0) - startup = cv; - - /* Subtract, taking care of carry */ - cv.tv_sec -= startup.tv_sec; - if (startup.tv_nsec > cv.tv_nsec) { - cv.tv_sec--; - cv.tv_nsec += 1000000000; - } - cv.tv_nsec -= startup.tv_nsec; - - /* Convert to usec */ - rv = cv.tv_sec * 1000000.0 + cv.tv_nsec/1000; - - return rv; -} - -#endif - /* - - - - - - - - - - - - - - - - - - - - - - - - */ int acond_timedwait_imp(pthread_cond_t *cond, pthread_mutex_t *lock, int msec) { @@ -699,7 +585,7 @@ int acond_timedwait_imp(pthread_cond_t *cond, pthread_mutex_t *lock, int msec) { /* Set the current threads priority */ int set_interactive_priority() { -#ifdef __APPLE__ +#ifdef UNIX_APPLE #ifdef NEVER int rv = 0; struct task_category_policy tcatpolicy; @@ -725,7 +611,7 @@ int set_interactive_priority() { // a1logd(g_log, 8, "set_interactive_priority: set to important got %d\n",rv); return rv; #endif /* NEVER */ -#else /* !APPLE */ +#else /* !UNIX_APPLE */ int rv; struct sched_param param; param.sched_priority = 32; @@ -734,11 +620,11 @@ int set_interactive_priority() { rv = pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m); // a1logd(g_log, 8, "set_interactive_priority: set got %d\n",rv); return rv; -#endif /* !APPLE */ +#endif /* !UNIX_APPLE */ } int set_normal_priority() { -#ifdef __APPLE__ +#ifdef UNIX_APPLE #ifdef NEVER int rv = 0; struct task_category_policy tcatpolicy; @@ -763,7 +649,7 @@ int set_normal_priority() { // a1logd(g_log, 8, "set_normal_priority: set to standard got %d\n",rv); return rv; #endif /* NEVER */ -#else /* !APPLE */ +#else /* !UNIX_APPLE */ struct sched_param param; param.sched_priority = 0; int rv; @@ -771,7 +657,7 @@ int set_normal_priority() { rv = pthread_setschedparam(pthread_self(), SCHED_OTHER, ¶m); // a1logd(g_log, 8, "set_normal_priority: reset got %d\n",rv); return rv; -#endif /* !APPLE */ +#endif /* !UNIX_APPLE */ } #endif /* NEVER */ @@ -786,7 +672,7 @@ static int beep_msec; static int delayed_beep(void *pp) { msec_sleep(beep_delay); a1logd(g_log,8, "msec_beep activate\n"); -#ifdef __APPLE__ +#ifdef UNIX_APPLE # if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 AudioServicesPlayAlertSound(kUserPreferredAlert); # else @@ -812,7 +698,7 @@ void msec_beep(int delay, int freq, int msec) { a1logw(g_log, "msec_beep: Delayed beep failed to create thread\n"); } else { a1logd(g_log,8, "msec_beep activate\n"); -#ifdef __APPLE__ +#ifdef UNIX_APPLE # if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 AudioServicesPlayAlertSound(kUserPreferredAlert); # else @@ -980,7 +866,7 @@ int create_parent_directories(char *path) { #endif /* defined(UNIX) */ /* - - - - - - - - - - - - - - - - - - - - - - - - */ -#if defined(__APPLE__) || defined(NT) +#if defined(UNIX_APPLE) || defined(NT) /* Thread to monitor and kill the named processes */ static int th_kkill_nprocess(void *pp) { @@ -1109,7 +995,7 @@ int kill_nprocess(char **pname, a1log *log) { #endif /* NT */ -#if defined(__APPLE__) +#if defined(UNIX_APPLE) /* Kill a list of named process. */ /* Kill the first process found, then return */ @@ -1188,411 +1074,8 @@ int kill_nprocess(char **pname, a1log *log) { return rv; } -#endif /* __APPLE__ */ - -#endif /* __APPLE__ || NT */ - -/* ============================================================= */ - -/* A very small subset of icclib, copied to here. */ -/* This is just enough to support the standalone instruments */ -#ifdef SALONEINSTLIB - -sa_XYZNumber sa_D50 = { - 0.9642, 1.0000, 0.8249 -}; - -sa_XYZNumber sa_D65 = { - 0.9505, 1.0000, 1.0890 -}; - -void sa_SetUnity3x3(double mat[3][3]) { - int i, j; - for (j = 0; j < 3; j++) { - for (i = 0; i < 3; i++) { - if (i == j) - mat[j][i] = 1.0; - else - mat[j][i] = 0.0; - } - } - -} - -void sa_Cpy3x3(double dst[3][3], double src[3][3]) { - int i, j; - - for (j = 0; j < 3; j++) { - for (i = 0; i < 3; i++) - dst[j][i] = src[j][i]; - } -} - -void sa_MulBy3x3(double out[3], double mat[3][3], double in[3]) { - double tt[3]; - - tt[0] = mat[0][0] * in[0] + mat[0][1] * in[1] + mat[0][2] * in[2]; - tt[1] = mat[1][0] * in[0] + mat[1][1] * in[1] + mat[1][2] * in[2]; - tt[2] = mat[2][0] * in[0] + mat[2][1] * in[1] + mat[2][2] * in[2]; +#endif /* UNIX_APPLE */ - out[0] = tt[0]; - out[1] = tt[1]; - out[2] = tt[2]; -} - -void sa_Mul3x3_2(double dst[3][3], double src1[3][3], double src2[3][3]) { - int i, j, k; - double td[3][3]; /* Temporary dest */ - - for (j = 0; j < 3; j++) { - for (i = 0; i < 3; i++) { - double tt = 0.0; - for (k = 0; k < 3; k++) - tt += src1[j][k] * src2[k][i]; - td[j][i] = tt; - } - } - - /* Copy result out */ - for (j = 0; j < 3; j++) - for (i = 0; i < 3; i++) - dst[j][i] = td[j][i]; -} - - -/* Matrix Inversion by Richard Carling from "Graphics Gems", Academic Press, 1990 */ -#define det2x2(a, b, c, d) (a * d - b * c) - -static void adjoint( -double out[3][3], -double in[3][3] -) { - double a1, a2, a3, b1, b2, b3, c1, c2, c3; - - /* assign to individual variable names to aid */ - /* selecting correct values */ - - a1 = in[0][0]; b1 = in[0][1]; c1 = in[0][2]; - a2 = in[1][0]; b2 = in[1][1]; c2 = in[1][2]; - a3 = in[2][0]; b3 = in[2][1]; c3 = in[2][2]; - - /* row column labeling reversed since we transpose rows & columns */ - - out[0][0] = det2x2(b2, b3, c2, c3); - out[1][0] = - det2x2(a2, a3, c2, c3); - out[2][0] = det2x2(a2, a3, b2, b3); - - out[0][1] = - det2x2(b1, b3, c1, c3); - out[1][1] = det2x2(a1, a3, c1, c3); - out[2][1] = - det2x2(a1, a3, b1, b3); - - out[0][2] = det2x2(b1, b2, c1, c2); - out[1][2] = - det2x2(a1, a2, c1, c2); - out[2][2] = det2x2(a1, a2, b1, b2); -} - -static double sa_Det3x3(double in[3][3]) { - double a1, a2, a3, b1, b2, b3, c1, c2, c3; - double ans; - - a1 = in[0][0]; b1 = in[0][1]; c1 = in[0][2]; - a2 = in[1][0]; b2 = in[1][1]; c2 = in[1][2]; - a3 = in[2][0]; b3 = in[2][1]; c3 = in[2][2]; - - ans = a1 * det2x2(b2, b3, c2, c3) - - b1 * det2x2(a2, a3, c2, c3) - + c1 * det2x2(a2, a3, b2, b3); - return ans; -} - -#define SA__SMALL_NUMBER 1.e-8 - -int sa_Inverse3x3(double out[3][3], double in[3][3]) { - int i, j; - double det; - - /* calculate the 3x3 determinant - * if the determinant is zero, - * then the inverse matrix is not unique. - */ - det = sa_Det3x3(in); - - if ( fabs(det) < SA__SMALL_NUMBER) - return 1; - - /* calculate the adjoint matrix */ - adjoint(out, in); - - /* scale the adjoint matrix to get the inverse */ - for (i = 0; i < 3; i++) - for(j = 0; j < 3; j++) - out[i][j] /= det; - return 0; -} - -#undef SA__SMALL_NUMBER -#undef det2x2 - -/* - - - - - - - - - - - - - - - - - - - - - - - - */ -/* Transpose a 3x3 matrix */ -void sa_Transpose3x3(double out[3][3], double in[3][3]) { - int i, j; - if (out != in) { - for (i = 0; i < 3; i++) - for (j = 0; j < 3; j++) - out[i][j] = in[j][i]; - } else { - double tt[3][3]; - for (i = 0; i < 3; i++) - for (j = 0; j < 3; j++) - tt[i][j] = in[j][i]; - for (i = 0; i < 3; i++) - for (j = 0; j < 3; j++) - out[i][j] = tt[i][j]; - } -} - -/* Scale a 3 vector by the given ratio */ -void sa_Scale3(double out[3], double in[3], double rat) { - out[0] = in[0] * rat; - out[1] = in[1] * rat; - out[2] = in[2] * rat; -} - -/* Clamp a 3 vector to be +ve */ -void sa_Clamp3(double out[3], double in[3]) { - int i; - for (i = 0; i < 3; i++) - out[i] = in[i] < 0.0 ? 0.0 : in[i]; -} - -/* Return the normal Delta E given two Lab values */ -double sa_LabDE(double *Lab0, double *Lab1) { - double rv = 0.0, tt; - - tt = Lab0[0] - Lab1[0]; - rv += tt * tt; - tt = Lab0[1] - Lab1[1]; - rv += tt * tt; - tt = Lab0[2] - Lab1[2]; - rv += tt * tt; - - return sqrt(rv); -} - -/* CIE XYZ to perceptual CIE 1976 L*a*b* */ -void -sa_XYZ2Lab(icmXYZNumber *w, double *out, double *in) { - double X = in[0], Y = in[1], Z = in[2]; - double x,y,z,fx,fy,fz; - - x = X/w->X; - y = Y/w->Y; - z = Z/w->Z; - - if (x > 0.008856451586) - fx = pow(x,1.0/3.0); - else - fx = 7.787036979 * x + 16.0/116.0; - - if (y > 0.008856451586) - fy = pow(y,1.0/3.0); - else - fy = 7.787036979 * y + 16.0/116.0; - - if (z > 0.008856451586) - fz = pow(z,1.0/3.0); - else - fz = 7.787036979 * z + 16.0/116.0; - - out[0] = 116.0 * fy - 16.0; - out[1] = 500.0 * (fx - fy); - out[2] = 200.0 * (fy - fz); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - */ -/* A sub-set of ludecomp code from numlib */ - -int sa_lu_decomp(double **a, int n, int *pivx, double *rip) { - int i, j; - double *rscale, RSCALE[10]; - - if (n <= 10) - rscale = RSCALE; - else - rscale = dvector(0, n-1); - - for (i = 0; i < n; i++) { - double big; - for (big = 0.0, j=0; j < n; j++) { - double temp; - temp = fabs(a[i][j]); - if (temp > big) - big = temp; - } - if (fabs(big) <= DBL_MIN) { - if (rscale != RSCALE) - free_dvector(rscale, 0, n-1); - return 1; - } - rscale[i] = 1.0/big; - } - - for (*rip = 1.0, j = 0; j < n; j++) { - double big; - int k, bigi = 0; - - for (i = 0; i < j; i++) { - double sum; - sum = a[i][j]; - for (k = 0; k < i; k++) - sum -= a[i][k] * a[k][j]; - a[i][j] = sum; - } - - for (big = 0.0, i = j; i < n; i++) { - double sum, temp; - sum = a[i][j]; - for (k = 0; k < j; k++) - sum -= a[i][k] * a[k][j]; - a[i][j] = sum; - temp = rscale[i] * fabs(sum); - if (temp >= big) { - big = temp; - bigi = i; - } - } - - if (j != bigi) { - { - double *temp; - temp = a[bigi]; - a[bigi] = a[j]; - a[j] = temp; - } - *rip = -(*rip); - rscale[bigi] = rscale[j]; - } - - pivx[j] = bigi; - if (fabs(a[j][j]) <= DBL_MIN) { - if (rscale != RSCALE) - free_dvector(rscale, 0, n-1); - return 1; - } - - if (j != (n-1)) { - double temp; - temp = 1.0/a[j][j]; - for (i = j+1; i < n; i++) - a[i][j] *= temp; - } - } - if (rscale != RSCALE) - free_dvector(rscale, 0, n-1); - return 0; -} - -void sa_lu_backsub(double **a, int n, int *pivx, double *b) { - int i, j; - int nvi; - - for (nvi = -1, i = 0; i < n; i++) { - int px; - double sum; - - px = pivx[i]; - sum = b[px]; - b[px] = b[i]; - if (nvi >= 0) { - for (j = nvi; j < i; j++) - sum -= a[i][j] * b[j]; - } else { - if (sum != 0.0) - nvi = i; - } - b[i] = sum; - } - - for (i = (n-1); i >= 0; i--) { - double sum; - sum = b[i]; - for (j = i+1; j < n; j++) - sum -= a[i][j] * b[j]; - b[i] = sum/a[i][i]; - } -} - -int sa_lu_invert(double **a, int n) { - int i, j; - double rip; - int *pivx, PIVX[10]; - double **y; - - if (n <= 10) - pivx = PIVX; - else - pivx = ivector(0, n-1); - - if (sa_lu_decomp(a, n, pivx, &rip)) { - if (pivx != PIVX) - free_ivector(pivx, 0, n-1); - return 1; - } - - y = dmatrix(0, n-1, 0, n-1); - for (i = 0; i < n; i++) { - for (j = 0; j < n; j++) { - y[i][j] = a[i][j]; - } - } - - for (i = 0; i < n; i++) { - for (j = 0; j < n; j++) - a[i][j] = 0.0; - a[i][i] = 1.0; - sa_lu_backsub(y, n, pivx, a[i]); - } - - free_dmatrix(y, 0, n-1, 0, n-1); - if (pivx != PIVX) - free_ivector(pivx, 0, n-1); - - return 0; -} - -int sa_lu_psinvert(double **out, double **in, int m, int n) { - int rv = 0; - double **tr; - double **sq; - - tr = dmatrix(0, n-1, 0, m-1); - matrix_trans(tr, in, m, n); - - if (m > n) { - sq = dmatrix(0, n-1, 0, n-1); - if ((rv = matrix_mult(sq, n, n, tr, n, m, in, m, n)) == 0) { - if ((rv = sa_lu_invert(sq, n)) == 0) { - rv = matrix_mult(out, n, m, sq, n, n, tr, n, m); - } - } - free_dmatrix(sq, 0, n-1, 0, n-1); - } else { - sq = dmatrix(0, m-1, 0, m-1); - if ((rv = matrix_mult(sq, m, m, in, m, n, tr, n, m)) == 0) { - if ((rv = sa_lu_invert(sq, m)) == 0) { - rv = matrix_mult(out, n, m, tr, n, m, sq, m, m); - } - } - free_dmatrix(sq, 0, m-1, 0, m-1); - } - - free_dmatrix(tr, 0, n-1, 0, m-1); - return rv; -} - - -#endif /* SALONEINSTLIB */ -/* ============================================================= */ +#endif /* UNIX_APPLE || NT */ |