home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga ACS 1997 #2
/
amigaacscoverdisc
/
utilities
/
shareware
/
music
/
gfft-2.03
/
source
/
gfft-2.03-source.lha
/
ok.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-02
|
10KB
|
415 lines
/***************************************************************************
* 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 <string.h>
#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! */
}
}