/*************************************************************************** * Copyright (C) 1994 Charles P. Peterson * * 4007 Enchanted Sun, San Antonio, Texas 78244-1254 * * Email: Charles_P_Peterson@fcircus.sat.tx.us * * * * This is free software with NO WARRANTY. * * See gfft.c, or run program itself, for details. * * Support is available for a fee. * *************************************************************************** * * Program: gfft--General FFT analysis * File: ok.c * Purpose: OK! Do it! (Whatever it is to be done) * Author: Charles Peterson (CPP) * History: 23-August-1993 CPP; Created. * 5-Aug-94 CPP (1.05); Fix nameless append mode * 1-Oct-94 CPP (1.14); Fix 'not enough frames' off-by-1 error * 10-Feb-95 CPP (1.38); Cleanup if output stopped * 13-Feb-95 CPP (1.40); Header on spectrum files * Comment: */ #include #include "gfft.h" #include "settings.h" /* Power, Amplitude, ReadPtr */ #include "format.h" /* ID_8SVX */ static void check_output_parameters (BOOLEAN do_it_for_real); static void check_plot_parameters (void); static void spectrum_file_cleanup (void ); static BOOLEAN temporary_name_used = FALSE; /* * First, the interface(s) */ char *ok (char *arguments) { if (InputFormat.zero != 0) { int sample_width = (InputFormat.bits > 8) ? 16 : 8; InputFormat.zero = ((unsigned long) 0xffffffff >> (33 - sample_width)) + (unsigned long) 1; } CATCH_ERROR { do_ok (TRUE); } ON_ERROR { spectrum_file_cleanup (); } END_CATCH_ERROR; return arguments; } char *re_plot (char *arguments) { check_plot_parameters (); if (WriteName && strlen(WriteName)) { OkWriteName = WriteName; /* Probably used Append to load pre-ex */ } if (!OkWriteName || !strlen(OkWriteName)) { error_message (NO_WRITE_FILE); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } do_re_plot (); return arguments; } char *re_output (char *arguments) { CATCH_ERROR { check_output_parameters (TRUE); do_re_output (); if (WritePtr != stdout) { FILE *write_ptr = WritePtr; WritePtr = NULL; fclose (write_ptr); } if (Plot) { ok_plot (); } if (temporary_name_used) WriteName = NULL; } ON_ERROR { spectrum_file_cleanup (); } END_CATCH_ERROR; return arguments; } static void spectrum_file_cleanup (void) { if (WritePtr != stdout && WritePtr != NULL) { FILE *write_ptr = WritePtr; WritePtr = NULL; fclose (write_ptr); } if (temporary_name_used) WriteName = NULL; } /* * Now, the 'main routine' used by OK */ ULONG do_ok (BOOLEAN do_it_for_real) { ULONG bins_used = 0; if (!ReadPtr) { error_message (NO_READ_FILE); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } if (NumberBins == INVALID_BINS) { error_message (INVALID_BINS_SPEC); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } if (Interleave == INVALID_INTERLEAVE) { error_message (INVALID_INTERLEAVE_SPEC); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } check_output_parameters (do_it_for_real); if (FileFormat) { if (!FileFormatOK) { error_message (FORMAT_NOT_OK); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } if ((OneShotOnly || RepeatOnly) && FileFormat != ID_8SVX) { error_message (ONESHOT_BUT_NOT_8SVX); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } OkRate = (Rate == AUTO_RATE) ? FileRate : Rate;/* user may ovride */ OkOffset = FileDataOffset; OkChannels = FileChannels; OkOctaveOffset = ok_octave_offset (TRUE); if (OkOctaveOffset == 0) { ULONG available_frames = FileFrames; OkStartFrame = StartFrame; OkStartFrame += (RepeatOnly) ? FileOneShotHiFrames : 0; available_frames -= (RepeatOnly) ? FileOneShotHiFrames : 0; available_frames -= (OneShotOnly) ? FileRepeatHiFrames : 0; OkFrames = available_frames - StartFrame; if (OkFrames < 1) { error_message (NOT_ENOUGH_FRAMES); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } } else { /* * Deal with multi-octave stuff (and, OneShot/Repeat stuff here too) * since user asked for higher octave * We use indirection inherent in OkFrames and OkStartFrame. * (Otherwise, format reader defaults FileFrames to first octave.) * * NOTE! Currently multi-octaves are only supported for 8SVX. * Also, I ought to move this stuff back into the format module for * better modularity. Someday. */ ULONG octave_and_oneshot_offset = 0; int power2 = 1; int i; for (i = 0; i < OkOctaveOffset; i++) { octave_and_oneshot_offset += power2 * FileFrames; power2 *= 2; } OkFrames = power2 * FileFrames; if (RepeatOnly) { OkFrames -= power2 * FileOneShotHiFrames; octave_and_oneshot_offset += power2 * FileOneShotHiFrames; } if (OneShotOnly) { OkFrames -= power2 * FileRepeatHiFrames; } OkStartFrame = StartFrame + octave_and_oneshot_offset; OkFrames -= StartFrame; if (OkFrames < 1) { error_message (NOT_ENOUGH_FRAMES); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } } /* * Now, see if we have enough frames for user's specification */ if (Frames <= OkFrames) { OkFrames = Frames; } else { if (Frames != ULONG_MAX) { error_message (NOT_ENOUGH_FRAMES); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } } } else /* Unformatted file */ { if (Rate == AUTO_RATE) { error_message (NO_RATE_SPECIFIED); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } OkRate = Rate; OkOffset = StartByte; if (FileFrames == 0) /* If file length unknown */ { OkFrames = ULONG_MAX; OkStartFrame = StartFrame; } else { if (FileFrames <= StartFrame) /* StartFrame is 0 based */ { error_message (NOT_ENOUGH_FRAMES); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } OkFrames = FileFrames - StartFrame; OkStartFrame = StartFrame; } OkChannels = 1; /* unformatted files must have 1 channel now */ } if (Channel > OkChannels || Channel < 1) { error_message (SPEC_CHANNEL_UNAVAIL); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } /* * To permit multiple analyses without redundantly entering filename * it is reset to beginning here */ ok_rewind (); if (Power || Amplitude) { if (Header && do_it_for_real) { fprintf (WritePtr, "#FFT\n"); write_settings (WritePtr, "#", TRUE, FALSE); } if (Time3D) { bins_used = ok_time3d_spectrum (do_it_for_real); } else { bins_used = ok_spectrum (do_it_for_real); } } else { bins_used = ok_fft (do_it_for_real); } if (do_it_for_real) { if (WritePtr != stdout) { FILE *write_ptr = WritePtr; WritePtr = NULL; fclose (write_ptr); } if (Plot) { ok_plot (); } if (temporary_name_used) WriteName = NULL; } return bins_used; } /* * Now, the checking and utilty routines */ /* * User selects 1 for lowest octave, 2 for second, etc. * (Special case...0 for highest) * however, 8SVX octaves are stored in order highest first * so, we compute OkOctaveOffset to match storage order */ int ok_octave_offset (BOOLEAN report_error) { int octave_offset = 0; if (Octave != 0) { octave_offset = FileOctaves - Octave; if (octave_offset < 0) { if (report_error) error_message (OCTAVE_NOT_PRESENT); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } } return octave_offset; } static void check_output_parameters (BOOLEAN do_it_for_real) { temporary_name_used = FALSE; if (Rate == INVALID_RATE) /* Last rate command was invalid */ { error_message (NO_RATE_SPECIFIED); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } if (SmoothingSegments == INVALID_SMOOTHING) { error_message (INVALID_SMOOTHING_SPEC); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } check_plot_parameters (); if (do_it_for_real) { if (WriteName && strlen (WriteName) && !WritePtr) { char temp_filename[MAX_PATH+1]; strcpy (temp_filename, WriteName); if (Appending) { set_append (temp_filename); } else { set_write (temp_filename); } } if (Plot && !WritePtr) { extern int Old_File_Count; int file_number = (CombinePlots) ? Old_File_Count+1 : 1; char *read_name = (ReadName) ? ReadName : NullString; char temp_filename[MAX_PATH+1]; char temp_name[MAX_PATH+1]; temporary_name_used = TRUE; stcgfn (temp_filename, read_name); /* SAS/C SYSTEM DEPENDENT */ sprintf (temp_name, TEMP_DATAFILE_NAME, temp_filename, file_number); /* * (1.05) */ if (Appending) { set_append (temp_name); } else { set_write (temp_name); } } if (!WritePtr) { error_message (NO_WRITE_FILE); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } OkWriteName = WriteName; } /* end if (do_it_for_real) */ } static void check_plot_parameters (void) { if (WritePtr == stdout && Plot) { error_message (CANT_PLOT_FROM_STDOUT); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } if (RotX == INVALID_ROTATION) { error_message (INVALID_ROTATION_SPEC); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } if (RotZ == INVALID_ROTATION) { error_message (INVALID_ROTATION_SPEC); RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */ } }