Sampling at 35hz (35 samples per second) yields 5x35 = 175 samples
during a 5-second window. For purposes of illustration I will assume
that you are obtaining a single integer sample each time, but of
course the algorithm generalizes to other cases.
Literally speaking, the "least CPU intensive" solution would store
every sample for the entire run of the process into a very large buffer,
since this then allows the last 5 seconds to be played back trivially;
however you specify that "whenever the process stops, I only have the
last 5 seconds of data stored," so I suspect that you want to avoid
using enormous amounts of memory during the process as well, although
you did not mention memory as a constraint.
The solution is to use a "ring buffer." This simple data structure
allows an array with the capacity for exactly 5 seconds of samples
to always contain the last 5 seconds of activity, while maintaining
excellent performance and using minimum memory. This is a traditional
strategy, employed in many I/O buffering applications that must
keep up with hardware and cope with limited resources.
Here is C code to do the deed. Naturally I have had
to make reference to a few functions that would be
provided by your specific application, namely:
1. process_continues() should return 'true' immediately
if the process is still taking place, 'false' if it is not.
(This is a good place to put your 1/35th second delay.)
2. get_sample() should, of course, fetch a sample. If you
are not using integer samples, just change the type of
the 'data' array.
3. display_sample() is a stand-in for whatever operation you
wish to perform with each sample at the end.
If you have any questions or concerns, please feel very free
to request clarification!
Thanks for the opportunity to answer your question.
* * * * * * CUT HERE * * * * * *
/* Determine the total samples needed to represent 5 seconds */
#define SECONDS 5
#define HERTZ 35
#define SAMPLES ((SECONDS) * (HERTZ))
/* Declare the sample data array */
int data[SAMPLES];
/* Position of the next sample to be read back from the buffer */
int readPos;
/* Position of the next sample to be written to the buffer */
int writePos = 0;
/* Total samples written; primarily here to keep an eye out for
the possibility that the buffer has not been filled completely once
(a very short process!) */
int total = 0;
/* Now carry out the process and obtain samples */
while (process_continues()) {
data[writePos++] = get_sample();
total++;
/* Divide by SAMPLES and take the remainder to determine the next
writing position. The ring buffer is filled from 0 to SAMPLES - 1,
and writing then begins again at 0 */
writePos %= SAMPLES;
}
/* Now the process is done. Time to read the information. */
/* If at least 5 seconds have elapsed, then the entire buffer
is full, and the oldest sample will be found where the next
sample would have been written. Otherwise, the oldest sample
is sample 0, because we have not overwritten any existing
samples yet */
if (total >= SAMPLES) {
readPos = writePos;
} else {
readPos = 0;
}
/* Special case: no samples (zero-length process).
Exit program (you may prefer to return from a function,
etc) */
if (total == 0) {
exit(0);
}
/* "Display" the samples from the ring buffer,
in correct chronological order. The display_sample function
is a stand-in for whatever operation you wish to perform with them. */
do {
display_sample(data[readPos++]);
/* As before we divide by SAMPLES and take the remainder.
This allows reading to "wrap around" to the beginning of
the buffer */
readPos %= SAMPLES;
} while (readPos != writePos);
/* END OF PROGRAM */ |