Sophie

Sophie

distrib > Fedora > 20 > x86_64 > by-pkgid > 3ba85bf2939f39f5621bfaac4201a3af > files > 1

audio-entropyd-2.0.3-6.fc20.src.rpm

--- audio-entropyd.c	2010-02-28 06:21:33.000000000 -0700
+++ audio-entropyd.c	2014-03-05 10:45:29.688013075 -0700
@@ -17,10 +17,11 @@ 
 #include <getopt.h>
 #include <unistd.h>
 #include <string.h>
 #include <syslog.h>
 #include <signal.h>
+#include <time.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/wait.h>
@@ -36,511 +37,1444 @@ 
 #include "proc.h"
 #include "val.h"
 #include "RNGTEST.h"
 #include "error.h"
 
-#define RANDOM_DEVICE				"/dev/random"
-#define DEFAULT_SAMPLE_RATE			11025
-#define PID_FILE				"/var/run/audio-entropyd.pid"
-#define DEFAULT_CLICK_READ			(1 * DEFAULT_SAMPLE_RATE)
-#define DEFAULT_POOLSIZE_FN                     "/proc/sys/kernel/random/poolsize"
-#define	RNGTEST_PENALTY				(20000 / 8) /* how many bytes to skip when the rng-test fails */
+#define RANDOM_DEVICE                     "/dev/random"
+#define DEFAULT_FRAME_RATE                22050  
+#define DEFAULT_SAMPLE_SIZE               11072
+#define DEFAULT_SKIP_SIZE                 11025
+#define DEFAULT_CONFIGURATION_FILE        "/etc/sysconfig/audio-entropyd"
+#define PID_FILE                          "/var/run/audio-entropyd.pid"
+#define DEFAULT_POOLSIZE_FN               "/proc/sys/kernel/random/poolsize"
+#define RNGTEST_PENALTY                   (20000 / 8) /* how many bytes to skip when the rng-test fails */
 
 void dolog(int level, char *format, ...);
 
+/* Global Variables - they all have a leading capital case, and
+ * they are used throughout the program without passing.  That's why
+ * the case is different, so they can be recognized.  
+ * Not optimal as it can obscure the logic flow, but simple.  */
 extern int loggingstate;
-int treshold = 0;
-char skip_test = 0;
-int error_state = 0;
-char dofork = 1;
-char *file = NULL;
-
-static char *cdevice = "hw:0";				/* capture device */
-const char *id = "capture";
-int err;
-int verbose=0;
-int format = -1;
+int Always_Close = 0;
+unsigned Frame_Rate = (unsigned) DEFAULT_FRAME_RATE;
+unsigned Process_Frames = (unsigned) DEFAULT_SAMPLE_SIZE;
+unsigned Skip_Frames = (unsigned) DEFAULT_SAMPLE_SIZE;
+char Internal_Test = 0;
+int Error_State = 0;
+int Entropy_Filter = 30;
+float Lower_Threshold = .0;
+float Upper_Threshold = .5;
+char Do_Fork = 1;
+char *Capture_File = NULL;
+static char *Capture_Device = "plughw:0";        /* capture device */
+const char *Stream_Mode = "capture";
+int Snd_Pcm_Err;
+int Verbose=0;
+int Snd_Pcm_Format = -1;
 
-#define max(x, y)	((x)>(y)?(x):(y))
+#define max(x, y)  ((x)>(y)?(x):(y))
 
 /* Prototypes */
-void main_loop(const char *cdevice, int sample_rate);
-int setparams(snd_pcm_t *chandle, int sample_rate);
+void main_loop(void);
+int parse_options (int option_count, char **options);
+int read_config_file (FILE * infile, char ***config_options);
+void * Alloc (size_t len);
+char * StrnDup (char *str);
+char * StrMem (size_t slen);
+int setparams(snd_pcm_t *chandle);
 void usage(void);
 void credit_krng(int random_fd, struct rand_pool_info *entropy);
 void daemonise(void);
 void gracefully_exit(int signum);
 void logging_handler(int signum);
-void get_random_data(int sample_rate, int skip_samples, int process_samples, int *n_output_bytes, char **output_buffer);
-int add_to_kernel_entropyspool(int handle, char *buffer, int nbytes);
+void get_random_data (snd_pcm_t *chandle, unsigned char *input_buffer, unsigned char *output_buffer, int *n_output_bytes);
+void add_entropy_bit (char bit, unsigned char *output_buffer, int *n_output_bytes);
+int add_to_kernel_entropyspool(int handle, unsigned char *buffer, int nbytes);
 
 /* Functions */
 
 int main(int argc, char **argv)
 {
-	int sample_rate = DEFAULT_SAMPLE_RATE;
-	int c;
-	static struct option long_options[] =
-	{
-		{"device",	1, NULL, 'd' },
-		{"do-not-fork",	1, NULL, 'n' },
-		{"sample-rate", 1, NULL, 'N' },
-		{"skip-test",	0, NULL, 's' },
-		{"file",	1, NULL, 'f' },
-		{"verbose",	0, NULL, 'v' },
-		{"help",	0, NULL, 'h' },
-		{NULL,		0, NULL, 0   }
-	};
-
-	/* Process commandline options */
-	while(1)
-	{
-		c = getopt_long (argc, argv, "f:nsr:d:N:vh", long_options, NULL);
-		if (c == -1)
-			break;
-
-		switch(c)
-		{
-			case 'f':
-				file = optarg;
-				break;
-
-			case 'n':
-				dofork = 0;
-				break;
-
-			case 'N':
-				sample_rate = atoi(optarg);
-				break;
-
-			case 'v':
-				loggingstate = 1;
-				verbose++;
-				break;
-
-			case 's':
-				skip_test = 1;
-				break;
-
-			case 'd':
-				cdevice = strdup(optarg);
-				break;
-
-			case 'h':
-				usage();
-				exit(0);
-
-			case '?':
-			default:
-				fprintf(stderr, "Invalid commandline options.\n\n");
-				usage();
-				exit(1);
-		}
-	}
-
-	RNGTEST_init();
-
-	signal(SIGPIPE, SIG_IGN);
-	signal(SIGHUP, gracefully_exit);
-	signal(SIGINT, gracefully_exit);
-	signal(SIGTERM, gracefully_exit);
-	signal(SIGUSR1, logging_handler);
-	signal(SIGUSR2, logging_handler);
-
-	openlog("audio-entropyd", LOG_CONS, LOG_DAEMON);
-
-	dolog(LOG_NOTICE, "audio-entropyd starting up");
-
-	if (mlockall(MCL_FUTURE | MCL_CURRENT) == -1)
-		error_exit("mlockall failed");
-
-	if (dofork)
-		daemonise();
-
-	main_loop(cdevice, sample_rate);
+  int option_count = 0, iii;
+  FILE *config_file;
+  char **config_file_options;
+
+  config_file = fopen(DEFAULT_CONFIGURATION_FILE, "rt");
+  if (!config_file)
+    error_exit("Couldn't open configuration file: %s", DEFAULT_CONFIGURATION_FILE);
+  option_count = read_config_file (config_file, &config_file_options);
+  fclose(config_file);
+  parse_options ( option_count, config_file_options);  // Process configuration file
+  for (iii=0; iii < option_count; iii++)
+  { free (config_file_options [iii]);
+  }
+  free (config_file_options);
+  if (argc > 1)
+  { optind = 0;  // start at first option
+    opterr = 0;  // reset any error
+    optopt = 0;  // reset any error
+    optarg = NULL;  // reset any error
+    parse_options (argc, argv);  // Process command line
+  }
+  RNGTEST_init();
+  signal(SIGPIPE, SIG_IGN);
+  signal(SIGHUP, gracefully_exit);
+  signal(SIGINT, gracefully_exit);
+  signal(SIGTERM, gracefully_exit);
+  signal(SIGUSR1, logging_handler);
+  signal(SIGUSR2, logging_handler);
+  openlog("audio-entropyd", LOG_CONS, LOG_DAEMON);
+  dolog(LOG_NOTICE, "audio-entropyd starting up with entropy filter %d", Entropy_Filter);
+  if (mlockall(MCL_FUTURE | MCL_CURRENT) == -1)
+    error_exit("mlockall failed");
+  if (Do_Fork)
+    daemonise();
+  main_loop();
+  exit(0);
+}
 
-	exit(0);
+/*
+   Parse the options passed in the char** array.
+   lines and comments.  Rets: 0 on success.
+*/
+int
+parse_options (int option_count, char **options)
+{ int c;
+  static struct option long_options[] =
+  {
+    {"always_close",  0, NULL, 'a' },
+    {"device",  1, NULL, 'd' },
+    {"do-not-fork",  0, NULL, 'n' },
+    {"entropy-filter",  1, NULL, 'e' },
+    {"sample-rate", 1, NULL, 'r' },
+    {"sample-size", 1, NULL, 'z' },
+    {"skip-size", 1, NULL, 's' },
+    {"internal-test",  0, NULL, 'i' },
+    {"store-in-file",  1, NULL, 'f' },
+    {"lower-threshold",  1, NULL, 'l' },
+    {"upper-threshold",  1, NULL, 'u' },
+    {"verbose",  0, NULL, 'v' },
+    {"help",  0, NULL, 'h' },
+    {NULL,    0, NULL, 0   }
+  };
+
+  while(1)
+  { c = getopt_long (option_count, options, "ad:e:f:hil:nr:s:u:vz:", long_options, NULL);
+    if (c == -1)
+      break;
+    switch(c)
+    { case 'f':
+        Capture_File = StrnDup (optarg);
+        break;
+      case 'a':
+        Always_Close = 1;
+        break;
+      case 'n':
+        Do_Fork = 0;
+        break;
+      case 'r':
+        Frame_Rate = (unsigned) atoi(optarg);
+        break;
+      case 'z':
+        Process_Frames = (unsigned) atoi(optarg);
+        break;
+      case 's':
+        Skip_Frames = (unsigned) atoi(optarg);
+        break;
+      case 'v':
+        loggingstate = 1;
+        Verbose++;
+        break;
+      case 'i':
+        Internal_Test = 1;
+        break;
+      case 'e':
+        Entropy_Filter = atoi(optarg);
+        break;
+      case 'l':
+        Lower_Threshold = (float) atof(optarg);
+        break;
+      case 'u':
+        Upper_Threshold = (float) atof(optarg);
+        break;
+      case 'd':
+        Capture_Device = StrnDup(optarg);
+        break;
+      case 'h':
+        usage();
+        exit(0);
+      case '?':
+      default:
+        fprintf(stderr, "Invalid commandline options.\n\n");
+        usage();
+        exit(1);
+        break;
+    }
+  }
+  return 0;
 }
 
-int setparams(snd_pcm_t *chandle, int sample_rate)
+/*
+   Read a configuration file, discarding blank
+   lines and comments.  Rets: option count on success.
+   Everything from the file is put into an argv like array.
+*/
+
+int
+read_config_file (FILE * infile, char ***config_options)
 {
-	snd_pcm_hw_params_t *ct_params;		/* templates with rate, format and channels */
-	snd_pcm_hw_params_alloca(&ct_params);
+  char *curr_option, *retptr, *workline, *cmnt, *token;
+  char **all_options;
+  int iii, line_count = 0, configuration_count = 0;
+
+  workline= StrMem (256);
+  curr_option = StrnDup ("audio_entropyd");  // save the program name to simulate argv
+  all_options = (char **) StrMem ((sizeof (char *)) * (configuration_count+1));  // allocate an array for option char pointers, including the new option
+  configuration_count++;  // update the option count
+  *(all_options + configuration_count - 1) = curr_option;  // append the new option pointer
+  *config_options = all_options;  // point to the new option pointer array
+  retptr = fgets (workline, 256, infile);
+  if (retptr == NULL)
+    error_exit ("Unable to read line from configuration file");
+  while (*workline != '\0')
+  { line_count++;
+    token = strtok (workline, " \t\n");    // get first token separated by spaces, tabs, or newline
+    if (token)                  // not an empty line
+    { cmnt = strchr (workline, '#');
+      if (token[0] == '-')      // options line
+      { if (cmnt)
+          strncpy (cmnt, "\0", 1);     // truncate at comment
+        curr_option = StrnDup (workline);  // duplicate the option
+        all_options = (char **) StrMem ((sizeof (char *)) * (configuration_count+1));  // allocate an array for option char pointers, including the new option
+        for (iii = 0; iii < configuration_count; iii++)  // transfer existing pointers to the new array of option pointers
+        { *(all_options + iii) = *((*config_options) + iii);
+        }
+        configuration_count++;  // update the option count
+        *(all_options + configuration_count - 1) = curr_option;  // append the new option pointer
+        free (*config_options);  // free the existing option pointer array
+        *config_options = all_options;  // point to the new option pointer array
+      }
+      else if (token[0] == '#') // line is a comment
+        ;  // do nothing
+      else
+      { if (Verbose > 1)
+          dolog(LOG_DEBUG, "Skipped line %d in configuration file with invalid %s at start of line", line_count, token);
+      }
+    }
+    memset (workline, 0x00, 256);
+    retptr = fgets (workline, 256, infile);
+  }
+  curr_option = NULL;  // terminate like argv is terminated, with a null char*.
+  all_options = (char **) StrMem ((sizeof (char *)) * (configuration_count+1));  // allocate an array for option char pointers, including the new option
+  for (iii = 0; iii < configuration_count; iii++)  // transfer existing pointers to the new array of option pointers
+  { *(all_options + iii) = *((*config_options) + iii);
+  }
+  *(all_options + configuration_count) = curr_option;
+  free (*config_options);  // free the existing option pointer array
+  //config_options = &all_options;  // point to the new option pointer array
+  *config_options = all_options;  // point to the new option pointer array
+  if (*workline == '\0')
+  { if (feof (infile))
+    { free (workline);
+      return configuration_count;
+    }
+    free (workline);
+    error_exit ("Read error on configuration file");
+  }
+  free (workline);
+  return configuration_count;
+}
 
-	err = snd_pcm_hw_params_any(chandle, ct_params);
-	if (err < 0)
-		error_exit("Broken configuration for %s PCM: no configurations available: %s", id, snd_strerror(err));
-
-	/* Disable rate resampling */
-	err = snd_pcm_hw_params_set_rate_resample(chandle, ct_params, 0);
-	if (err < 0)
-		error_exit("Could not disable rate resampling: %s", snd_strerror(err));
-
-	/* Set access to SND_PCM_ACCESS_RW_INTERLEAVED */
-	err = snd_pcm_hw_params_set_access(chandle, ct_params, SND_PCM_ACCESS_RW_INTERLEAVED);
-	if (err < 0)
-		error_exit("Could not set access to SND_PCM_ACCESS_RW_INTERLEAVED: %s", snd_strerror(err));
-
-	/* Restrict a configuration space to have rate nearest to our target rate */
-	err = snd_pcm_hw_params_set_rate_near(chandle, ct_params, &sample_rate, 0);
-	if (err < 0)
-		error_exit("Rate %iHz not available for %s: %s", sample_rate, id, snd_strerror(err));
-
-	/* Set sample format */
-	format = SND_PCM_FORMAT_S16_BE;
-	err = snd_pcm_hw_params_set_format(chandle, ct_params, format);
-	if (err < 0)
-	{
-		format = SND_PCM_FORMAT_S16_LE;
-		err = snd_pcm_hw_params_set_format(chandle, ct_params, format);
-	}
-	if (err < 0)
-		error_exit("Sample format (SND_PCM_FORMAT_S16_BE and _LE) not available for %s: %s", id, snd_strerror(err));
-
-	/* Set stereo */
-	err = snd_pcm_hw_params_set_channels(chandle, ct_params, 2);
-	if (err < 0)
-		error_exit("Channels count (%i) not available for %s: %s", 2, id, snd_strerror(err));
-
-	/* Apply settings to sound device */
-	err = snd_pcm_hw_params(chandle, ct_params);
-	if (err < 0)
-		error_exit("Could not apply settings to sound device!");
+void *
+Alloc (size_t len)
+{ void *p = calloc (1, len);
+  if (!p)
+    error_exit ("Out of memory in request for %u", len);
+  return p;
+}
 
-	return 0;
+char *
+StrnDup (char *str)
+{ size_t len = strlen (str);
+  char *rv = strndup (str, len);
+  if (!rv)
+    error_exit ("Out of memory in StrnDup");
+  return rv;
 }
 
-void main_loop(const char *cdevice, int sample_rate)
-{
-	unsigned char *output_buffer = NULL;
-	int n_output_bytes = -1;
-	int random_fd = -1, max_bits;
-	FILE *poolsize_fh;
-
-	/* Open kernel random device */
-	random_fd = open(RANDOM_DEVICE, O_RDWR);
-	if (random_fd == -1)
-		error_exit("Couldn't open random device: %m");
-
-	/* find out poolsize */
-	poolsize_fh = fopen(DEFAULT_POOLSIZE_FN, "rb");
-	if (!poolsize_fh)
-		error_exit("Couldn't open poolsize file: %m");
-	fscanf(poolsize_fh, "%d", &max_bits);
-	fclose(poolsize_fh);
-
-	/* first get some data so that we can immediately submit something when the
-	 * kernel entropy-buffer gets below some limit
-	 */
-	get_random_data(sample_rate, DEFAULT_CLICK_READ, DEFAULT_SAMPLE_RATE, &n_output_bytes, &output_buffer);
-
-	/* Main read loop */
-	for(;;)
-	{	
-		int added = 0, before, loop, after;
-		fd_set write_fd;
-		FD_ZERO(&write_fd);
-		FD_SET(random_fd, &write_fd);
-
-		if (!file)
-		{
-			for(;;) 
-			{ 
-				int rc = select(random_fd+1, NULL, &write_fd, NULL, NULL); /* wait for krng */ 
-				if (rc >= 0) break; 
-				if (errno != EINTR) 
-					error_exit("Select error: %m"); 
-			}
-		}
-
-		/* find out how many bits to add */
-		if (ioctl(random_fd, RNDGETENTCNT, &before) == -1)
-			error_exit("Couldn't query entropy-level from kernel");
-
-		dolog(LOG_DEBUG, "woke up due to low entropy state (%d bits left)", before);
-
-		/* loop until the buffer is (supposed to be) full: we do NOT check the number of bits
-		 * currently in the buffer each iteration, since (on a heavily used random-driver)
-		 * audio-entropyd might run constantly, using a lot of cpu-usage
-		 */
-		if (verbose > 1)
-			printf("max_bits: %d\n", max_bits);
-		for(loop=0; loop < max_bits;)
-		{
-			if (verbose > 1)
-				dolog(LOG_DEBUG, "n_output_bytes: %d", n_output_bytes);
-
-			if (n_output_bytes > 0)
-			{
-				int cur_added;
-
-				if (file)
-				{
-					FILE *fh = fopen(file, "a+");
-					if (!fh)
-						error_exit("error accessing file %s", file);
-
-					if (fwrite(output_buffer, 1, n_output_bytes, fh) != n_output_bytes)
-						error_exit("error writeing to file");
-
-					fclose(fh);
-
-					cur_added = n_output_bytes * 8;
-				}
-				else
-				{
-					cur_added = add_to_kernel_entropyspool(random_fd, output_buffer, n_output_bytes);
-				}
-
-				added += cur_added;
-				loop += cur_added;
-
-				if (verbose > 1)
-					dolog(LOG_DEBUG, "%d bits of data, %d bits usable were added, total %d added", n_output_bytes * 8, cur_added, added);
-			}
-
-			/* Get number of bits in KRNG after credit */
-			if (ioctl(random_fd, RNDGETENTCNT, &after) == -1)
-				error_exit("Coundn't query entropy-level from kernel: %m");
-
-			if (verbose > 1 && after < max_bits)
-				dolog(LOG_DEBUG, "minimum level not reached: %d", after);
-
-			free(output_buffer);
-			output_buffer = NULL;
-			get_random_data(sample_rate, DEFAULT_CLICK_READ, DEFAULT_SAMPLE_RATE, &n_output_bytes, &output_buffer);
-		}
+/* Allocate a string of the passed in size from memory.
+ * Strings allocated with this routine can use the StrCat
+ * routine below safely.  Does *not* allocate an extra
+ * position for the NULL terminator.  Callers responsibility. */
+char *
+StrMem (size_t slen)
+{ char *nstr = NULL;
+  nstr = (char *) Alloc (slen);
+  if (!nstr)
+    error_exit ("Out of memory in StrMem");
+  return nstr;
+}
+
+int setparams(snd_pcm_t *chandle)
+{ 
+  snd_pcm_hw_params_t *ct_params;    /* templates with rate, format and channels */
+  snd_pcm_hw_params_alloca(&ct_params);
+
+  Snd_Pcm_Err = snd_pcm_hw_params_any(chandle, ct_params);
+  if (Snd_Pcm_Err < 0)
+    error_exit("Broken configuration for %s PCM: no configurations available: %s", Stream_Mode, snd_strerror(Snd_Pcm_Err));
+
+  /* Disable rate resampling */
+  // redundant with set_rate_near, as set_rate_near always picks a native rate of the device that would not be resampled.
+  //Snd_Pcm_Err = snd_pcm_hw_params_set_rate_resample(chandle, ct_params, 0);
+  //if (Snd_Pcm_Err < 0)
+  //  error_exit("Could not disable rate resampling: %s", snd_strerror(Snd_Pcm_Err));
+
+  /* Set access to SND_PCM_ACCESS_RW_INTERLEAVED */
+  Snd_Pcm_Err = snd_pcm_hw_params_set_access(chandle, ct_params, SND_PCM_ACCESS_RW_INTERLEAVED);
+  if (Snd_Pcm_Err < 0)
+    error_exit("Could not set access to SND_PCM_ACCESS_RW_INTERLEAVED: %s", snd_strerror(Snd_Pcm_Err));
+
+  /* Restrict a configuration space to have rate nearest to our target rate */
+  Snd_Pcm_Err = snd_pcm_hw_params_set_rate_near(chandle, ct_params, &Frame_Rate, 0);
+  if (Snd_Pcm_Err < 0)
+    error_exit("Rate %iHz not available for %s: %s", Frame_Rate, Stream_Mode, snd_strerror(Snd_Pcm_Err));
+
+  /* Set sample format appropriate for architecture */
+  int test_int = 1;
+  if ((* (char *) &test_int) == 1)
+  { Snd_Pcm_Format = SND_PCM_FORMAT_S32_LE;
+    Snd_Pcm_Err = snd_pcm_hw_params_set_format(chandle, ct_params, Snd_Pcm_Format);
+    if (Snd_Pcm_Err < 0)
+    { error_exit("Sample format SND_PCM_FORMAT_S32_LE not available for %s: %s", Stream_Mode, snd_strerror(Snd_Pcm_Err));
+    }
+  } 
+  else
+  { Snd_Pcm_Format = SND_PCM_FORMAT_S32_BE;
+    Snd_Pcm_Err = snd_pcm_hw_params_set_format(chandle, ct_params, Snd_Pcm_Format);
+    if (Snd_Pcm_Err < 0)
+    { error_exit("Sample format SND_PCM_FORMAT_S32_BE not available for %s: %s", Stream_Mode, snd_strerror(Snd_Pcm_Err));
+    }
+  }
+
+  /* Set stereo */
+  Snd_Pcm_Err = snd_pcm_hw_params_set_channels(chandle, ct_params, 2);
+  if (Snd_Pcm_Err < 0)
+    error_exit("Channels count (%i) not available for %s: %s", 2, Stream_Mode, snd_strerror(Snd_Pcm_Err));
+
+  /* Apply settings to sound device */
+  Snd_Pcm_Err = snd_pcm_hw_params(chandle, ct_params);
+  if (Snd_Pcm_Err < 0)
+    error_exit("Could not apply settings to sound device!");
+
+  int can_pause = snd_pcm_hw_params_can_pause (ct_params);
+  int can_resume = snd_pcm_hw_params_can_resume (ct_params);
+  if (can_pause == 1 && can_resume == 1)
+    return 1;
+  else
+    return 0;
+}
 
-		dolog(LOG_INFO, "Entropy credit of %i bits made (%i bits before, %i bits after)", added, before, after);
-	}
+void main_loop(void)
+{ unsigned input_buffer_size, output_buffer_size;
+  unsigned char *input_buffer = NULL;
+  unsigned char *output_buffer = NULL;
+  int can_pause_resume = 0, pause = 1, resume = 0;
+  int n_output_bytes = -1;
+  int random_fd = -1, max_bits;
+  FILE *poolsize_fh;
+  snd_pcm_t *chandle = NULL;
+
+  if ((Snd_Pcm_Err = snd_pcm_open(&chandle, Capture_Device, SND_PCM_STREAM_CAPTURE, 0)) < 0)
+    error_exit("Record open error: %s", snd_strerror(Snd_Pcm_Err));
+
+  if (Verbose > 1)
+    dolog(LOG_DEBUG, "main loop chandle %p", chandle);
+
+  /* Open and set up ALSA device for reading */
+  can_pause_resume = setparams(chandle);
+
+  input_buffer_size = snd_pcm_frames_to_bytes(chandle, Process_Frames);
+  input_buffer = (unsigned char *)malloc(input_buffer_size);
+  output_buffer_size = (Process_Frames / 8) + (8 - ((Process_Frames / 8) % 8));  // max of 1 bit of entropy per frame
+  output_buffer = (unsigned char *)malloc(output_buffer_size);
+  if (!input_buffer || !output_buffer)
+    error_exit("problem allocating %d bytes of memory", input_buffer_size);
+  if (Verbose > 1)
+    dolog(LOG_DEBUG, "Input buffer size: %d bytes", input_buffer_size);
+
+  /* Discard the first data read */
+  /* it often contains weird looking data - probably a click from */
+  /* driver loading / card initialisation */
+  /* Read a buffer of audio */
+  int total = Skip_Frames;
+  int n_to_do = Process_Frames;
+  if (Skip_Frames < Process_Frames)
+    n_to_do = Skip_Frames;
+  unsigned char *dummy = input_buffer;
+  while (total > 0)
+  { while (n_to_do > 0)
+    { snd_pcm_sframes_t frames_read = snd_pcm_readi(chandle, dummy, Process_Frames);
+      /* Make  sure we  aren't hitting a disconnect/suspend case */
+      if (frames_read < 0)
+        snd_pcm_recover(chandle, frames_read, 0);
+      /* Nope, something else is wrong. Bail.  */
+      if (frames_read < 0)
+      { snd_pcm_close(chandle);
+        free(input_buffer);
+        free(output_buffer);
+         error_exit("Read initial throw away data error: %m");
+      } 
+      else
+      { n_to_do -= frames_read;
+        total -= frames_read;
+        dummy += frames_read;  
+      }
+    }
+    n_to_do = Process_Frames;
+    dummy = input_buffer;
+  }
+  /* Open kernel random device */
+  random_fd = open(RANDOM_DEVICE, O_RDWR);
+  if (random_fd == -1)
+    error_exit("Couldn't open random device: %m");
+
+  /* find out poolsize */
+  poolsize_fh = fopen(DEFAULT_POOLSIZE_FN, "rb");
+  if (!poolsize_fh)
+    error_exit("Couldn't open poolsize file: %m");
+  fscanf(poolsize_fh, "%d", &max_bits);
+  fclose(poolsize_fh);
+  /* first get some data so that we can immediately submit something when the
+   * kernel entropy-buffer gets below some limit
+   */
+  get_random_data(chandle, input_buffer, output_buffer, &n_output_bytes);
+  if (can_pause_resume && Always_Close == 0)
+    snd_pcm_pause (chandle, pause);
+  else
+    snd_pcm_close(chandle);
+  /* Main read loop */
+  for(;;)
+  {  int added = 0, before, loop, after;
+    fd_set write_fd;
+    FD_ZERO(&write_fd);
+    FD_SET(random_fd, &write_fd);
+    if (!Capture_File)
+    { for(;;) 
+      { int rc = select(random_fd+1, NULL, &write_fd, NULL, NULL); /* wait for krng */ 
+        if (Verbose > 1)
+          dolog(LOG_DEBUG, "select return code rc %d", rc);
+        if (rc >= 0)
+          break; 
+        else if (errno != EINTR) 
+          error_exit("Select error: %m"); 
+      }
+    }
+    /* find out how many bits to add */
+    if (ioctl(random_fd, RNDGETENTCNT, &before) == -1)
+      error_exit("Couldn't query entropy-level from kernel");
+    dolog(LOG_DEBUG, "woke up due to low entropy state (%d bits left)", before);
+    /* loop until the buffer is (supposed to be) full: we do NOT check the number of bits
+     * currently in the buffer each iteration, since (on a heavily used random-driver)
+     * audio-entropyd might run constantly, using a lot of cpu-usage
+     */
+    if (Verbose > 1)
+      printf("max_bits: %d\n", max_bits);
+    if (can_pause_resume && Always_Close == 0)
+      snd_pcm_pause (chandle, resume);
+    else  // no pause resume on this device, have to re initialize each time to avoid overrun errors
+    { if ((Snd_Pcm_Err = snd_pcm_open(&chandle, Capture_Device, SND_PCM_STREAM_CAPTURE, 0)) < 0)
+        error_exit("Record open error: %s", snd_strerror(Snd_Pcm_Err));
+      if (Verbose > 1)
+        dolog(LOG_DEBUG, "main loop chandle %p", chandle);
+      /* Open and set up ALSA device for reading */
+      setparams(chandle);
+      /* Discard the first data read */
+      /* it often contains weird looking data - probably a click from */
+      /* driver loading / card initialisation */
+      /* Read a buffer of audio */
+      int total = Skip_Frames;
+      int n_to_do = Process_Frames;
+      if (Skip_Frames < Process_Frames)
+        n_to_do = Skip_Frames;
+      unsigned char *dummy = input_buffer;
+      while (total > 0)
+      { while (n_to_do > 0)
+        { snd_pcm_sframes_t frames_read = snd_pcm_readi(chandle, dummy, Process_Frames);
+          /* Make  sure we  aren't hitting a disconnect/suspend case */
+          if (frames_read < 0)
+            snd_pcm_recover(chandle, frames_read, 0);
+          /* Nope, something else is wrong. Bail.  */
+          if (frames_read < 0)
+          { snd_pcm_close(chandle);
+            free(input_buffer);
+            free(output_buffer);
+            error_exit("Read initial throw away data error: %m");
+          } 
+          else
+          { n_to_do -= frames_read;
+            total -= frames_read;
+            dummy += frames_read;  
+          }
+        }
+        n_to_do = Process_Frames;
+        dummy = input_buffer;
+      }
+    }
+    for(loop=0; loop < max_bits;)
+    { if (Verbose > 1)
+        dolog(LOG_DEBUG, "n_output_bytes: %d", n_output_bytes);
+      if (n_output_bytes > 0)
+      { int cur_added;
+        if (Capture_File)
+        { FILE *fh = fopen(Capture_File, "a+");
+          if (!fh)
+            error_exit("error accessing Capture_File %s", Capture_File);
+          if (fwrite(output_buffer, 1, n_output_bytes, fh) != n_output_bytes)
+            error_exit("error writeing to Capture_File");
+          fclose(fh);
+          cur_added = n_output_bytes * 8;
+        } 
+        else
+          cur_added = add_to_kernel_entropyspool(random_fd, output_buffer, n_output_bytes);
+        added += cur_added;
+        loop += cur_added;
+        if (Verbose > 1)
+          dolog(LOG_DEBUG, "%d bits of data, %d bits usable were added, total %d added", n_output_bytes * 8, cur_added, added);
+      }
+      /* Get number of bits in KRNG after credit */
+      if (ioctl(random_fd, RNDGETENTCNT, &after) == -1)
+        error_exit("Coundn't query entropy-level from kernel: %m");
+      if (Verbose > 1 && after < max_bits)
+        dolog(LOG_DEBUG, "minimum level not reached: %d", after);
+      memset (output_buffer, 0x00, output_buffer_size);
+      get_random_data(chandle, input_buffer, output_buffer, &n_output_bytes);
+    }
+    dolog(LOG_INFO, "Entropy credit of %i bits made (%i bits before, %i bits after)", added, before, after);
+    if (can_pause_resume && Always_Close == 0)
+      snd_pcm_pause (chandle, pause);
+    else
+      snd_pcm_close(chandle);
+  }
+  if (can_pause_resume && Always_Close == 0)
+    snd_pcm_close(chandle);
+  free(input_buffer);
+  free(output_buffer);
 }
 
-int add_to_kernel_entropyspool(int handle, char *buffer, int nbytes)
+int add_to_kernel_entropyspool(int handle, unsigned char *buffer, int nbytes)
 {
-	double nbits;
-	struct rand_pool_info *output;
+  double nbits;
+  struct rand_pool_info *output;
 
-	output = (struct rand_pool_info *)malloc(sizeof(struct rand_pool_info) + nbytes);
-	if (!output)
-		error_exit("malloc failure in add_to_kernel_entropyspool");
-
-	// calculate number of bits in the block of
-	// data. put in structure
-	nbits = calc_nbits_in_data((unsigned char *)buffer, nbytes);
-	if (nbits >= 1.0)
-	{
-		output -> entropy_count = (int)nbits;
-		output -> buf_size      = nbytes;
-		memcpy(output -> buf, buffer, nbytes);
-
-		if (ioctl(handle, RNDADDENTROPY, output) == -1)
-			error_exit("RNDADDENTROPY failed!");
-	}
+  output = (struct rand_pool_info *)malloc(sizeof(struct rand_pool_info) + nbytes);
+  if (!output)
+    error_exit("malloc failure in add_to_kernel_entropyspool");
+
+  // calculate number of bits in the block of
+  // data. put in structure
+  nbits = calc_nbits_in_data((unsigned char *)buffer, nbytes);
+  if (nbits >= 1.0)
+  {
+    output -> entropy_count = (int)nbits;
+    output -> buf_size      = nbytes;
+    memcpy(output -> buf, buffer, nbytes);
+
+    if (ioctl(handle, RNDADDENTROPY, output) == -1)
+      error_exit("RNDADDENTROPY failed!");
+  }
 
-	free(output);
+  free(output);
 
-	return (int)nbits;
+  return (int)nbits;
 }
 
 #define order(a, b)     (((a) == (b)) ? -1 : (((a) > (b)) ? 1 : 0))
 
-void get_random_data(int sample_rate, int skip_samples, int process_samples, int *n_output_bytes, char **output_buffer)
+void get_random_data (snd_pcm_t *chandle, unsigned char *input_buffer, unsigned char *output_buffer, int *n_output_bytes)
 {
-	int n_to_do, bits_out=0, loop;
-	char *dummy;
-	static short psl=0, psr=0; /* previous samples */
+  int n_to_do, loop;
+  unsigned char *dummy;
+	static int psl=0, psr=0; /* previous samples */
 	static char a=1; /* alternater */
-	unsigned char byte_out=0;
-	int input_buffer_size;
-	char *input_buffer;
-	snd_pcm_t *chandle;
-
-	if (verbose > 1)
-		dolog(LOG_DEBUG, "get_random_data(%p, %d, %d, %p, %p)", chandle, skip_samples, process_samples, n_output_bytes, output_buffer);
-
-	if ((err = snd_pcm_open(&chandle, cdevice, SND_PCM_STREAM_CAPTURE, 0)) < 0)
-		error_exit("Record open error: %s", snd_strerror(err));
-
-	/* Open and set up ALSA device for reading */
-	setparams(chandle, sample_rate);
-
-	*n_output_bytes=0;
-
-	input_buffer_size = snd_pcm_frames_to_bytes(chandle, max(skip_samples, process_samples)) * 2; /* *2: stereo! */
-	input_buffer = (char *)malloc(input_buffer_size);
-	*output_buffer = (char *)malloc(input_buffer_size);
-	if (!input_buffer || !output_buffer)
-		error_exit("problem allocating %d bytes of memory", input_buffer_size);
-	if (verbose > 1)
-		dolog(LOG_DEBUG, "Input buffer size: %d bytes", input_buffer_size);
-
-	/* Discard the first data read */
-	/* it often contains weird looking data - probably a click from */
-	/* driver loading / card initialisation */
-	snd_pcm_sframes_t garbage_frames_read = snd_pcm_readi(chandle, input_buffer, skip_samples);
-	/* Make sure we aren't hitting a disconnect/suspend case */
-	if (garbage_frames_read < 0)
-		snd_pcm_recover(chandle, garbage_frames_read, 0);
-	/* Nope, something else is wrong. Bail. */
-	if (garbage_frames_read < 0)
-		error_exit("Get random data: read error: %m");
-
-	/* Read a buffer of audio */
-	n_to_do = process_samples * 2;
-	dummy = input_buffer;
-	while (n_to_do > 0)
-	{
-		snd_pcm_sframes_t frames_read = snd_pcm_readi(chandle, dummy, n_to_do);
-		/* Make	sure we	aren't hitting a disconnect/suspend case */
-		if (frames_read < 0)
-			frames_read = snd_pcm_recover(chandle, frames_read, 0);
-		/* Nope, something else is wrong. Bail.	*/
-		if (frames_read < 0)
-			error_exit("Read error: %m");
-		if (frames_read == -1) 
-		{
-			if (errno != EINTR)
-				error_exit("Read error: %m");
-		}
-		else
-		{
-			n_to_do -= frames_read;
-			dummy += frames_read;	
-		}
-	}
-	snd_pcm_close(chandle);
-
-	/* de-biase the data */
-	for(loop=0; loop<(process_samples * 2/*16bits*/ * 2/*stereo*/ * 2); loop+=8)
-	{
-		int w1, w2, w3, w4, o1, o2;
-
-		if (format == SND_PCM_FORMAT_S16_BE)
-		{
-			w1 = (input_buffer[loop+0]<<8) + input_buffer[loop+1];
-			w2 = (input_buffer[loop+2]<<8) + input_buffer[loop+3];
-			w3 = (input_buffer[loop+4]<<8) + input_buffer[loop+5];
-			w4 = (input_buffer[loop+6]<<8) + input_buffer[loop+7];
-		}
-		else
-		{
-			w1 = (input_buffer[loop+1]<<8) + input_buffer[loop+0];
-			w2 = (input_buffer[loop+3]<<8) + input_buffer[loop+2];
-			w3 = (input_buffer[loop+5]<<8) + input_buffer[loop+4];
-			w4 = (input_buffer[loop+7]<<8) + input_buffer[loop+6];
-		}
-
-		/* Determine order of channels for each sample, subtract previous sample
-		 * to compensate for unbalanced audio devices */
-		o1 = order(w1-psl, w2-psr);
-		o2 = order(w3-psl, w4-psr);
-		if (a > 0)
-		{
-			psl = w3;
-			psr = w4;
-		}
-		else
-		{
-			psl = w1;
-			psr = w2;
-		}
-
-		/* If both samples have the same order, there is bias in the samples, so we
-		 * discard them; if both channels are equal on either sample, we discard
-		 * them too; additionally, alternate the sample we'll use next (even more
-		 * bias removal) */
-		if (o1 == o2 || o1 < 0 || o2 < 0)
-		{
-			a = -a;
-		}
-		else
-		{
-			/* We've got a random bit; the bit is either the order from the first or
-			 * the second sample, determined by the alternator 'a' */
-			char bit = (a > 0) ? o1 : o2;
-
-			byte_out <<= 1;
-			byte_out += bit;
-
-			bits_out++;
-
-			if (bits_out>=8)
-			{
-				if (error_state == 0 || skip_test == 0)
-				{
-					(*output_buffer)[*n_output_bytes]=byte_out;
-					(*n_output_bytes)++;
-				}
-				bits_out=0;
-
-				RNGTEST_add(byte_out);
-				if (skip_test == 0 && RNGTEST() == -1)
-				{
-					if (error_state == 0)
-						dolog(LOG_CRIT, "test of random data failed, skipping %d bytes before re-using data-stream (%d bytes in flush)", RNGTEST_PENALTY, error_state);
-					error_state = RNGTEST_PENALTY;
-					*n_output_bytes = 0;
-				}
-				else
-				{
-					if (error_state > 0)
-					{
-						error_state--;
-
-						if (error_state == 0)
-							dolog(LOG_INFO, "Restarting fetching of entropy data");
-					}
-				}
-			}
-		}
-	}
+  int min_left_val = 0x0fffffff, max_left_val = 0, min_right_val = 0x0fffffff, max_right_val = 0;
+  long left_input_total = 0, right_input_total = 0;
+  float dc_offset_left = 0.0, dc_offset_right = 0.0;
+
+  if (Verbose > 1)
+    dolog(LOG_DEBUG, "get_random_data(%p, %u, %d, %d, %p, %p)", chandle, Frame_Rate, Process_Frames, input_buffer, output_buffer, n_output_bytes);
+  *n_output_bytes=0;
+  /* Read a buffer of audio */
+  n_to_do = Process_Frames;
+  dummy = input_buffer;
+  while (n_to_do > 0)
+  { snd_pcm_sframes_t frames_read = snd_pcm_readi(chandle, dummy, n_to_do);
+    /* Make  sure we  aren't hitting a disconnect/suspend case */
+    if (frames_read < 0)
+      frames_read = snd_pcm_recover(chandle, frames_read, 0);
+    /* Nope, something else is wrong. Bail.  */
+    if (frames_read < 0)
+      error_exit("Read error: %m");
+    if (frames_read == -1) 
+    { if (errno != EINTR)
+        error_exit("Read error: %m");
+    } else
+    { n_to_do -= frames_read;
+      dummy += frames_read;  
+      if (n_to_do > 0)
+      { double time_for_frames = (double) n_to_do / (double) Frame_Rate;  // how long to create that many frames?
+        long nanoseconds = floor ((time_for_frames * 1000000.));  // how many nanoseconds is that?
+        struct timespec time_to_wait, time_left; 
+        time_to_wait.tv_sec = (long) floor (time_for_frames);
+        time_to_wait.tv_nsec = (nanoseconds % 1000000);
+        int wait_retval = nanosleep (&time_to_wait, &time_left);  // wait for that many nanoseconds
+      }
+    }
+  }
+  /* de-bias the data */
+  for (loop = 0; loop < (Process_Frames*2); loop += 2)
+  { int32_t w1, w2;
+    /* because we are using plughw, alsa (or pulse) will have formatted the data
+     * to be signed 32 as requested by shifting, regardless of device internal format.
+     * 32 bits should take care of
+     * sound cards for now as there is really no discernable difference above that 
+     * for human ears, while it allows for extracting maximum entropy from cards
+     * with larger internal formats.  I think the new hda-intel standard defaults to 
+     * 32 bit.  Most systems will have this onboard now.
+     * Note that big endian or little endian doesn't matter as we are reading in native
+     * format we requested, whatever it is for int32_t.
+     */
+    w1 = ((int32_t *) input_buffer) [loop + 0];
+    left_input_total += w1;
+    if (w1 < min_left_val)
+    { min_left_val = w1;
+    } else if (w1 > max_left_val)
+      max_left_val = w1;
+    w2 = ((int32_t *) input_buffer) [loop + 1];
+    right_input_total += w2;
+    if (w2 < min_right_val)
+    { min_right_val = w2;
+    } else if (w2 > max_right_val)
+      max_right_val = w2;
+    if (Verbose > 2)
+      dolog(LOG_DEBUG, "w1 %d  w2 %d", w1, w2);
+    else if (Verbose > 1 && loop % 1024 == 0)
+      dolog(LOG_DEBUG, "w1 %d  w2 %d", w1, w2);
+  }
+  if (Verbose > 1)
+    dolog(LOG_DEBUG, "left_input_total %ld  right_input_total %ld", left_input_total, right_input_total);
+  if (Verbose > 1)
+    dolog(LOG_DEBUG, "min_left_val %d  max_left_val %d", min_left_val, max_left_val);
+  if (Verbose > 1)
+    dolog(LOG_DEBUG, "min_right_val %d  max_right_val %d", min_right_val, max_right_val);
+  dc_offset_left = (float) ((double) left_input_total / (double) (Process_Frames));
+  dc_offset_right = (float) ((double) right_input_total / (double) (Process_Frames));
+  if (Verbose > 1)
+    dolog(LOG_DEBUG, "dc_offset_left %8.3f  dc_offset_right %8.3f", dc_offset_left, dc_offset_right);
+  char bit = 0;
+  int iii = 0;
+  if (Entropy_Filter == 0)  // absolute normalized distance change between channels, more less or less more
+  { for (iii = 0; iii < (Process_Frames*2) - 4; iii += 2)
+    { int32_t w1, w2;
+      float leftval, rightval, delta [3];
+      int jjj;
+      for (jjj = 0; jjj < 3; jjj++)
+      { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0];
+        w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1];
+        leftval = ((float) w1 - dc_offset_left);
+        if (leftval < 0.)
+          leftval = leftval / (dc_offset_left - (float) min_left_val);
+        else
+          leftval = leftval / ((float) max_left_val - dc_offset_left);
+        rightval = ((float) w2 - dc_offset_right);
+        if (rightval < 0.)
+          rightval = rightval / (dc_offset_right - (float) min_right_val);
+        else
+          rightval = rightval / ((float) max_right_val - dc_offset_right);
+        delta [jjj] = fabs (leftval - rightval);
+      }
+      if (delta [1] - delta [0] < Lower_Threshold  &&  delta [2] - delta [1] > Upper_Threshold)  // change less, change more
+      { bit = 0;
+      } else if (delta [1] - delta [0] > Upper_Threshold  &&  delta [2] - delta [1] < Lower_Threshold)  // change more, change less
+      { bit = 1;
+      } else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 1)  // absolute normalized distance change between channels with second difference == 0
+  { for (iii = 0; iii < (Process_Frames*2) - 4; iii += 2)
+    { int32_t w1, w2;
+      float leftval, rightval, delta [3];
+      int jjj;
+      for (jjj = 0; jjj < 3; jjj++)
+      { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0];
+        w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1];
+        leftval = ((float) w1 - dc_offset_left);
+        if (leftval < 0.)
+          leftval = leftval / (dc_offset_left - (float) min_left_val);
+        else
+          leftval = leftval / ((float) max_left_val - dc_offset_left);
+        rightval = ((float) w2 - dc_offset_right);
+        if (rightval < 0.)
+          rightval = rightval / (dc_offset_right - (float) min_right_val);
+        else
+          rightval = rightval / ((float) max_right_val - dc_offset_right);
+        delta [jjj] = fabs (leftval - rightval);
+      }
+      if (delta [1] - delta [0] < Lower_Threshold
+          &&  delta [2] - delta [1] > Upper_Threshold
+          &&  delta [2] - delta [0] == 0.)  // change less, change more, back at beginning value
+      { bit = 0;
+      } else if (delta [1] - delta [0] > Upper_Threshold
+          &&  delta [2] - delta [1] < Lower_Threshold
+          &&  delta [2] - delta [0] == 0.)  // change more, change less, back at beginning value
+      { bit = 1;
+      } else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 2)  // absolute normalized distance change between channels with second difference != 0
+  { for (iii = 0; iii < (Process_Frames*2) - 4; iii += 2)
+    { int32_t w1, w2;
+      float leftval, rightval, delta [3];
+      int jjj;
+      for (jjj = 0; jjj < 3; jjj++)
+      { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0];
+        w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1];
+        leftval = ((float) w1 - dc_offset_left);
+        if (leftval < 0.)
+          leftval = leftval / (dc_offset_left - (float) min_left_val);
+        else
+          leftval = leftval / ((float) max_left_val - dc_offset_left);
+        rightval = ((float) w2 - dc_offset_right);
+        if (rightval < 0.)
+          rightval = rightval / (dc_offset_right - (float) min_right_val);
+        else
+          rightval = rightval / ((float) max_right_val - dc_offset_right);
+        delta [jjj] = fabs (leftval - rightval);
+      }
+      if (delta [1] - delta [0] < Lower_Threshold
+          &&  delta [2] - delta [1] > Upper_Threshold
+          && delta [2] - delta [0] != 0.)  // change less, change more, not at beginning value
+      { bit = 0;
+      } else if (delta [1] - delta [0] > Upper_Threshold
+          &&  delta [2] - delta [1] < Lower_Threshold
+          && delta [2] - delta [0] != 0.)  // change more, change less, not at beginning value
+      { bit = 1;
+      } else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 3)  // absolute normalized distance change between channels using 5 samples, less more less more or more less more less
+  { for (iii = 0; iii < (Process_Frames*2) - 8; iii += 2)
+    { int32_t w1, w2;
+      float leftval, rightval, delta [5];
+      int jjj;
+      for (jjj = 0; jjj < 5; jjj++)
+      { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0];
+        w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1];
+        leftval = ((float) w1 - dc_offset_left);
+        if (leftval < 0.)
+          leftval = leftval / (dc_offset_left - (float) min_left_val);
+        else
+          leftval = leftval / ((float) max_left_val - dc_offset_left);
+        rightval = ((float) w2 - dc_offset_right);
+        if (rightval < 0.)
+          rightval = rightval / (dc_offset_right - (float) min_right_val);
+        else
+          rightval = rightval / ((float) max_right_val - dc_offset_right);
+        delta [jjj] = fabs (leftval - rightval);
+      }
+      if (delta [1] - delta [0] < Lower_Threshold 
+          && delta [2] - delta [1] > Upper_Threshold 
+          && delta [3] - delta [2] < Lower_Threshold 
+          && delta [4] - delta [3] > Upper_Threshold)  // change less, change more, change less, change more
+      { bit = 0;
+      } else if (delta [1] - delta [0] > Upper_Threshold 
+                && delta [2] - delta [1] < Lower_Threshold 
+                && delta [3] - delta [2] > Upper_Threshold 
+                && delta [4] - delta [3] < Lower_Threshold)  // change more, change less, change more, change less
+      { bit = 1;
+      } else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 4)  // absolute normalized distance change between channels using 5 samples, less more more less or more less less more
+  { for (iii = 0; iii < (Process_Frames*2) - 8; iii += 2)
+    { int32_t w1, w2;
+      float leftval, rightval, delta [5];
+      int jjj;
+      for (jjj = 0; jjj < 5; jjj++)
+      { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0];
+        w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1];
+        leftval = ((float) w1 - dc_offset_left);
+        if (leftval < 0.)
+          leftval = leftval / (dc_offset_left - (float) min_left_val);
+        else
+          leftval = leftval / ((float) max_left_val - dc_offset_left);
+        rightval = ((float) w2 - dc_offset_right);
+        if (rightval < 0.)
+          rightval = rightval / (dc_offset_right - (float) min_right_val);
+        else
+          rightval = rightval / ((float) max_right_val - dc_offset_right);
+        delta [jjj] = fabs (leftval - rightval);
+      }
+      if (delta [1] - delta [0] < Lower_Threshold 
+          && delta [2] - delta [1] > Upper_Threshold 
+          && delta [3] - delta [2] > Upper_Threshold 
+          && delta [4] - delta [3] < Lower_Threshold)  // change less, change more, change more, change less
+      { bit = 0;
+      } else if (delta [1] - delta [0] > Upper_Threshold 
+                && delta [2] - delta [1] < Lower_Threshold 
+                && delta [3] - delta [2] < Lower_Threshold 
+                && delta [4] - delta [3] > Upper_Threshold)  // change more, change less, change less, change more
+      { bit = 1;
+      } else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 5)  // absolute normalized distance change between channels using 5 samples, less more same less or more less same more
+  { for (iii = 0; iii < (Process_Frames*2) - 8; iii += 2)
+    { int32_t w1, w2;
+      float leftval, rightval, delta [5];
+      int jjj;
+      for (jjj = 0; jjj < 5; jjj++)
+      { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0];
+        w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1];
+        leftval = ((float) w1 - dc_offset_left);
+        if (leftval < 0.)
+          leftval = leftval / (dc_offset_left - (float) min_left_val);
+        else
+          leftval = leftval / ((float) max_left_val - dc_offset_left);
+        rightval = ((float) w2 - dc_offset_right);
+        if (rightval < 0.)
+          rightval = rightval / (dc_offset_right - (float) min_right_val);
+        else
+          rightval = rightval / ((float) max_right_val - dc_offset_right);
+        delta [jjj] = fabs (leftval - rightval);
+      }
+      if (delta [1] - delta [0] < Lower_Threshold 
+          && delta [2] - delta [1] > Upper_Threshold 
+          && delta [3] - delta [2] == 0. 
+          && delta [4] - delta [3] < Lower_Threshold)  // change less, change more, stay, change less
+      { bit = 0;
+      } else if (delta [1] - delta [0] > Upper_Threshold 
+                && delta [2] - delta [1] < Lower_Threshold 
+                && delta [3] - delta [2] == 0. 
+                && delta [4] - delta [3] > Upper_Threshold)  // change more, change less, stay, change more
+      { bit = 1;
+      } else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 6)  // absolute normalized distance change between channels using 5 samples, same same more same or same same less same
+  { for (iii = 0; iii < (Process_Frames*2) - 8; iii += 2)
+    { int32_t w1, w2;
+      float leftval, rightval, delta [5];
+      int jjj;
+      for (jjj = 0; jjj < 5; jjj++)
+      { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0];
+        w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1];
+        leftval = ((float) w1 - dc_offset_left);
+        if (leftval < 0.)
+          leftval = leftval / (dc_offset_left - (float) min_left_val);
+        else
+          leftval = leftval / ((float) max_left_val - dc_offset_left);
+        rightval = ((float) w2 - dc_offset_right);
+        if (rightval < 0.)
+          rightval = rightval / (dc_offset_right - (float) min_right_val);
+        else
+          rightval = rightval / ((float) max_right_val - dc_offset_right);
+        delta [jjj] = fabs (leftval - rightval);
+      }
+      if (delta [1] - delta [0] == 0. 
+          && delta [2] - delta [1] == 0. 
+          && delta [3] - delta [2] < Lower_Threshold 
+          && delta [4] - delta [3] == 0.)  // step down
+      { bit = 0;
+      } else if (delta [1] - delta [0] == 0. 
+                && delta [2] - delta [1] == 0. 
+                && delta [3] - delta [2] > Upper_Threshold 
+                && delta [4] - delta [3] == 0.)  // step up
+      { bit = 1;
+      } else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 7)  // absolute normalized distance change between channels with pattern same same more or same same less
+  { for (iii = 0; iii < (Process_Frames*2) - 6; iii += 2)
+    { int32_t w1, w2;
+      float leftval, rightval, delta [4];
+      int jjj;
+      for (jjj = 0; jjj < 4; jjj++)
+      { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0];
+        w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1];
+        leftval = ((float) w1 - dc_offset_left);
+        if (leftval < 0.)
+          leftval = leftval / (dc_offset_left - (float) min_left_val);
+        else
+          leftval = leftval / ((float) max_left_val - dc_offset_left);
+        rightval = ((float) w2 - dc_offset_right);
+        if (rightval < 0.)
+          rightval = rightval / (dc_offset_right - (float) min_right_val);
+        else
+          rightval = rightval / ((float) max_right_val - dc_offset_right);
+        delta [jjj] = fabs (leftval - rightval);
+      }
+      if (delta [1] - delta [0] == 0. 
+          && delta [2] - delta [1] == 0. 
+          && delta [3] - delta [2] < 0.)  // same, change less
+      { bit = 0;
+      } else if (delta [1] - delta [0] == 0. 
+                && delta [2] - delta [1] == 0. 
+                && delta [3] - delta [2] > 0.) // same, change more
+      { bit = 1;
+      } else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 8)  // absolute normalized distance change between channels, less more or more less, uses time mod 2 to set entropy bit
+  { for (iii = 0; iii < (Process_Frames*2) - 4; iii += 2)
+    { int32_t w1, w2;
+      float leftval, rightval, delta [3];
+      int jjj;
+      for (jjj = 0; jjj < 3; jjj++)
+      { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0];
+        w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1];
+        leftval = ((float) w1 - dc_offset_left);
+        if (leftval < 0.)
+          leftval = leftval / (dc_offset_left - (float) min_left_val);
+        else
+          leftval = leftval / ((float) max_left_val - dc_offset_left);
+        rightval = ((float) w2 - dc_offset_right);
+        if (rightval < 0.)
+          rightval = rightval / (dc_offset_right - (float) min_right_val);
+        else
+          rightval = rightval / ((float) max_right_val - dc_offset_right);
+        delta [jjj] = fabs (leftval - rightval);
+      }
+      if ((delta [1] - delta [0] < Lower_Threshold  &&  delta [2] - delta [1] > Upper_Threshold)
+          || (delta [1] - delta [0] > Upper_Threshold  &&  delta [2] - delta [1] < Lower_Threshold))  // change less, change more or change more, change less
+      { clock_t used_time = clock ();
+        if (used_time != (clock_t) -1)
+          bit = (char) (used_time % 2);
+        else
+        { struct timespec current_time;
+          clock_gettime(CLOCK_REALTIME, &current_time);
+          bit = (char) current_time.tv_nsec % 2;
+        }
+      } 
+      else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 10)  // original style Entropy_Filter for entropy
+  { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 4)
+    { int32_t w1, w2, w3, w4;
+      char o1, o2;
+      w1 = ((int32_t *) input_buffer) [iii + 0];
+      w2 = ((int32_t *) input_buffer) [iii + 1];
+      w3 = ((int32_t *) input_buffer) [iii + 2];
+      w4 = ((int32_t *) input_buffer) [iii + 3];
+      /* Determine order of channels for each sample, subtract previous sample
+       * to compensate for unbalanced audio devices */
+      if ((w1-psl) > (w2-psr))
+        o1 = 1;
+      else if ((w1-psl) < (w2-psr))
+        o1 = 0;
+      else
+        o1 = -1;
+      if ((w3-psl) > (w4-psr))
+        o2 = 1;
+      else if ((w3-psl) < (w4-psr))
+        o2 = 0;
+      else
+        o2 = -1;
+      if (Verbose > 1)
+        dolog(LOG_DEBUG, "w1-psl %d  w2-psr %d", w1-psl, w2-psr);
+      if (Verbose > 1)
+        dolog(LOG_DEBUG, "w3-psl %d  w4-psr %d", w3-psl, w4-psr);
+      if (Verbose > 1)
+        dolog(LOG_DEBUG, "o1 %d  o2 %d", (int) o1, (int) o2);
+      if (a > 0)
+      { psl = w3;
+        psr = w4;
+      }
+      else
+      { psl = w1;
+        psr = w2;
+      }
+      /* If both samples have the same order, there is bias in the samples, so we
+       * discard them; if both channels are equal on either sample, we discard
+       * them too; additionally, alternate the sample we'll use next (even more
+       * bias removal) */
+      if (o1 == o2 || o1 < 0 || o2 < 0)
+      { a = -a;
+      }
+      else
+      { /* We've got a random bit; the bit is either the order from the first or
+         * the second sample, determined by the alternator 'a' */
+        bit = (a > 0) ? o1 : o2;
+        if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 11)  // original style Entropy_Filter for entropy but using dc_offset values for bias elimination
+  { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 4)
+    { int32_t w1, w2, w3, w4;
+      char o1, o2;
+      w1 = ((int32_t *) input_buffer) [iii + 0];
+      w2 = ((int32_t *) input_buffer) [iii + 1];
+      w3 = ((int32_t *) input_buffer) [iii + 2];
+      w4 = ((int32_t *) input_buffer) [iii + 3];
+      /* Determine order of channels for each sample, subtract previous sample
+       * to compensate for unbalanced audio devices */
+      if ((w1-dc_offset_left) > (w2-dc_offset_right))
+        o1 = 1;
+      else if ((w1-dc_offset_left) < (w2-dc_offset_right))
+        o1 = 0;
+      else
+        o1 = -1;
+      if ((w3-dc_offset_left) > (w4-dc_offset_right))
+        o2 = 1;
+      else if ((w3-dc_offset_left) < (w4-dc_offset_right))
+        o2 = 0;
+      else
+        o2 = -1;
+      if (Verbose > 1)
+        dolog(LOG_DEBUG, "w1-dc_offset_left %d  w2-dc_offset_right %d", w1-dc_offset_left, w2-dc_offset_right);
+      if (Verbose > 1)
+        dolog(LOG_DEBUG, "w3-dc_offset_left %d  w4-dc_offset_right %d", w3-dc_offset_left, w4-dc_offset_right);
+      if (Verbose > 1)
+        dolog(LOG_DEBUG, "o1 %d  o2 %d", (int) o1, (int) o2);
+      /* If both samples have the same order, there is bias in the samples, so we
+       * discard them; if both channels are equal on either sample, we discard
+       * them too; additionally, alternate the sample we'll use next (even more
+       * bias removal) */
+      if (o1 == o2 || o1 < 0 || o2 < 0)
+      { a = -a;
+      }
+      else
+      { /* We've got a random bit; the bit is either the order from the first or
+         * the second sample, determined by the alternator 'a' */
+        bit = (a > 0) ? o1 : o2;
+        if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 12)  // original style Entropy_Filter for entropy, use system time mod 2 for bit
+  { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 4)
+    { int32_t w1, w2, w3, w4;
+      char o1, o2;
+      w1 = ((int32_t *) input_buffer) [iii + 0];
+      w2 = ((int32_t *) input_buffer) [iii + 1];
+      w3 = ((int32_t *) input_buffer) [iii + 2];
+      w4 = ((int32_t *) input_buffer) [iii + 3];
+      /* Determine order of channels for each sample, subtract previous sample
+       * to compensate for unbalanced audio devices */
+      if ((w1-psl) > (w2-psr))
+        o1 = 1;
+      else if ((w1-psl) < (w2-psr))
+        o1 = 0;
+      else
+        o1 = -1;
+      if ((w3-psl) > (w4-psr))
+        o2 = 1;
+      else if ((w3-psl) < (w4-psr))
+        o2 = 0;
+      else
+        o2 = -1;
+      if (Verbose > 1)
+        dolog(LOG_DEBUG, "w1-psl %d  w2-psr %d", w1-psl, w2-psr);
+      if (Verbose > 1)
+        dolog(LOG_DEBUG, "w3-psl %d  w4-psr %d", w3-psl, w4-psr);
+      if (Verbose > 1)
+        dolog(LOG_DEBUG, "o1 %d  o2 %d", (int) o1, (int) o2);
+      if (a > 0)
+      { psl = w3;
+        psr = w4;
+      }
+      else
+      { psl = w1;
+        psr = w2;
+      }
+      /* If both samples have the same order, there is bias in the samples, so we
+       * discard them; if both channels are equal on either sample, we discard
+       * them too; additionally, alternate the sample we'll use next (even more
+       * bias removal) */
+      if (o1 == o2 || o1 < 0 || o2 < 0)
+      { a = -a;
+      }
+      else
+      { // We've matched our pattern, the orders are 0 and 1, and are different, make a bit
+        clock_t used_time = clock ();
+        if (used_time != (clock_t) -1)
+          bit = (char) (used_time % 2);
+        else
+        { struct timespec current_time;
+          clock_gettime(CLOCK_REALTIME, &current_time);
+          bit = (char) current_time.tv_nsec % 2;
+        }
+        if (Verbose > 1)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 20)  // pattern in individual channels, both normalized get less or both get more
+  { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 2)
+    { int32_t w1, w2, w3, w4;
+      float leftval0, leftval1, rightval0, rightval1;
+      w1 = ((int32_t *) input_buffer) [iii + 0];
+      w3 = ((int32_t *) input_buffer) [iii + 2];
+      leftval0 = ((float) w1 - dc_offset_left);
+      if (leftval0 < 0.)
+        leftval0 = leftval0 / (dc_offset_left - (float) min_left_val);
+      else
+        leftval0 = leftval0 / ((float) max_left_val - dc_offset_left);
+      leftval1 = ((float) w3 - dc_offset_left);
+      if (leftval1 < 0.)
+        leftval1 = leftval1 / (dc_offset_left - (float) min_left_val);
+      else
+        leftval1 = leftval1 / ((float) max_left_val - dc_offset_left);
+      if ((leftval1 - leftval0) < Lower_Threshold || (leftval1 - leftval0) > Upper_Threshold)  // finding a bit is feasible
+      { w2 = ((int32_t *) input_buffer) [iii + 1];
+        w4 = ((int32_t *) input_buffer) [iii + 3];
+        rightval0 = ((float) w2 - dc_offset_right);
+        if (rightval0 < 0.)
+          rightval0 = rightval0 / (dc_offset_right - (float) min_right_val);
+        else
+          rightval0 = rightval0 / ((float) max_right_val - dc_offset_right);
+        rightval1 = ((float) w4 - dc_offset_right);
+        if (rightval1 < 0.)
+          rightval1 = rightval1 / (dc_offset_right - (float) min_right_val);
+        else
+          rightval1 = rightval1 / ((float) max_right_val - dc_offset_right);
+        if ((leftval1 - leftval0) < Lower_Threshold  &&  (rightval1 - rightval0) > Upper_Threshold)  // left channel less, right channel more
+        { bit = 0;
+        } 
+        else if ((leftval1 - leftval0) > Upper_Threshold  &&  (rightval1 - rightval0) < Lower_Threshold)  // left channel more, right channel less
+        { bit = 1;
+        } 
+        else
+          bit = -1;
+        if (bit != -1)
+        { if (Verbose > 2)
+            dolog(LOG_DEBUG, "bit %d", (int) bit);
+          add_entropy_bit (bit, output_buffer, n_output_bytes);
+        }
+      }
+    }
+  }
+  else if (Entropy_Filter == 21)  // pattern in individual channels, both normalized, one significantly changes relative to the other
+  { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 2)
+    { int32_t w1, w2, w3, w4;
+      float leftval0, leftval1, rightval0, rightval1;
+      w1 = ((int32_t *) input_buffer) [iii + 0];
+      w3 = ((int32_t *) input_buffer) [iii + 2];
+      leftval0 = ((float) w1 - dc_offset_left);
+      if (leftval0 < 0.)
+        leftval0 = leftval0 / (dc_offset_left - (float) min_left_val);
+      else
+        leftval0 = leftval0 / ((float) max_left_val - dc_offset_left);
+      leftval1 = ((float) w3 - dc_offset_left);
+      if (leftval1 < 0.)
+        leftval1 = leftval1 / (dc_offset_left - (float) min_left_val);
+      else
+        leftval1 = leftval1 / ((float) max_left_val - dc_offset_left);
+      w2 = ((int32_t *) input_buffer) [iii + 1];
+      w4 = ((int32_t *) input_buffer) [iii + 3];
+      rightval0 = ((float) w2 - dc_offset_right);
+      if (rightval0 < 0.)
+        rightval0 = rightval0 / (dc_offset_right - (float) min_right_val);
+      else
+        rightval0 = rightval0 / ((float) max_right_val - dc_offset_right);
+      rightval1 = ((float) w4 - dc_offset_right);
+      if (rightval1 < 0.)
+        rightval1 = rightval1 / (dc_offset_right - (float) min_right_val);
+      else
+        rightval1 = rightval1 / ((float) max_right_val - dc_offset_right);
+      if  (fabs (leftval1 - leftval0) < Lower_Threshold
+          &&  fabs (rightval1 - rightval0) > Upper_Threshold)  // left channel minimal change, right channel significant change more or less
+      { bit = 0;
+      } else if (fabs (leftval1 - leftval0) > Upper_Threshold
+          &&  fabs (rightval1 - rightval0) < Lower_Threshold)  // left channel significant change more or less, right channel minimal change
+      { bit = 1;
+      } else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 2)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 22)  // pattern in individual channels, both normalized get less or both get more, use time mod 2 for bit
+  { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 2)
+    { int32_t w1, w2, w3, w4;
+      float leftval0, leftval1, rightval0, rightval1;
+      w1 = ((int32_t *) input_buffer) [iii + 0];
+      w3 = ((int32_t *) input_buffer) [iii + 2];
+      leftval0 = ((float) w1 - dc_offset_left);
+      if (leftval0 < 0.)
+        leftval0 = leftval0 / (dc_offset_left - (float) min_left_val);
+      else
+        leftval0 = leftval0 / ((float) max_left_val - dc_offset_left);
+      leftval1 = ((float) w3 - dc_offset_left);
+      if (leftval1 < 0.)
+        leftval1 = leftval1 / (dc_offset_left - (float) min_left_val);
+      else
+        leftval1 = leftval1 / ((float) max_left_val - dc_offset_left);
+      if ((leftval1 - leftval0) != 0.)
+      { w2 = ((int32_t *) input_buffer) [iii + 1];
+        w4 = ((int32_t *) input_buffer) [iii + 3];
+        rightval0 = ((float) w2 - dc_offset_right);
+        if (rightval0 < 0.)
+          rightval0 = rightval0 / (dc_offset_right - (float) min_right_val);
+        else
+          rightval0 = rightval0 / ((float) max_right_val - dc_offset_right);
+        rightval1 = ((float) w4 - dc_offset_right);
+        if (rightval1 < 0.)
+          rightval1 = rightval1 / (dc_offset_right - (float) min_right_val);
+        else
+          rightval1 = rightval1 / ((float) max_right_val - dc_offset_right);
+        if (((leftval1 - leftval0) > Upper_Threshold  &&  (rightval1 - rightval0) < Lower_Threshold) 
+            || ((leftval1 - leftval0) < Lower_Threshold  &&  (rightval1 - rightval0) > Upper_Threshold))  // either pattern of filter 20, make a bit
+        { clock_t used_time = clock ();
+          if (used_time != (clock_t) -1)
+            bit = (char) (used_time % 2);
+          else
+          { struct timespec current_time;
+            clock_gettime(CLOCK_REALTIME, &current_time);
+            bit = (char) current_time.tv_nsec % 2;
+          }
+        }
+        else
+          bit = -1;
+        if (bit != -1)
+        { if (Verbose > 2)
+            dolog(LOG_DEBUG, "bit %d", (int) bit);
+          add_entropy_bit (bit, output_buffer, n_output_bytes);
+        }
+      }
+    }
+  }
+  else if (Entropy_Filter == 23)  // pattern in individual channels, both normalized, one significantly changes relative to the other, use time mod 2 for bit
+  { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 2)
+    { int32_t w1, w2, w3, w4;
+      float leftval0, leftval1, rightval0, rightval1;
+      w1 = ((int32_t *) input_buffer) [iii + 0];
+      w3 = ((int32_t *) input_buffer) [iii + 2];
+      leftval0 = ((float) w1 - dc_offset_left);
+      if (leftval0 < 0.)
+        leftval0 = leftval0 / (dc_offset_left - (float) min_left_val);
+      else
+        leftval0 = leftval0 / ((float) max_left_val - dc_offset_left);
+      leftval1 = ((float) w3 - dc_offset_left);
+      if (leftval1 < 0.)
+        leftval1 = leftval1 / (dc_offset_left - (float) min_left_val);
+      else
+        leftval1 = leftval1 / ((float) max_left_val - dc_offset_left);
+      w2 = ((int32_t *) input_buffer) [iii + 1];
+      w4 = ((int32_t *) input_buffer) [iii + 3];
+      rightval0 = ((float) w2 - dc_offset_right);
+      if (rightval0 < 0.)
+        rightval0 = rightval0 / (dc_offset_right - (float) min_right_val);
+      else
+        rightval0 = rightval0 / ((float) max_right_val - dc_offset_right);
+      rightval1 = ((float) w4 - dc_offset_right);
+      if (rightval1 < 0.)
+        rightval1 = rightval1 / (dc_offset_right - (float) min_right_val);
+      else
+        rightval1 = rightval1 / ((float) max_right_val - dc_offset_right);
+      if ((fabs (leftval1 - leftval0) <= Lower_Threshold &&  fabs (rightval1 - rightval0) >= Upper_Threshold)
+           || (fabs (leftval1 - leftval0) >= Upper_Threshold &&  fabs (rightval1 - rightval0) <= Lower_Threshold))  // either pattern of filter 21, make bit
+      { clock_t used_time = clock ();
+        if (used_time != (clock_t) -1)
+          bit = (char) (used_time % 2);
+        else
+        { struct timespec current_time;
+          clock_gettime(CLOCK_REALTIME, &current_time);
+          bit = (char) current_time.tv_nsec % 2;
+        }
+      } 
+      else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 2)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  else if (Entropy_Filter == 30)  // if absolute normalized delta greater or less than threshold, generate a bit using system time mod 2
+  { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 2)
+    { int32_t w1, w2;
+      float leftval, rightval, delta;
+      w1 = ((int32_t *) input_buffer) [iii + 0];
+      w2 = ((int32_t *) input_buffer) [iii + 1];
+      leftval = ((float) w1 - dc_offset_left);
+      if (leftval < 0.)
+        leftval = leftval / (dc_offset_left - (float) min_left_val);
+      else
+        leftval = leftval / ((float) max_left_val - dc_offset_left);
+      rightval = ((float) w2 - dc_offset_right);
+      if (rightval < 0.)
+        rightval = rightval / (dc_offset_right - (float) min_right_val);
+      else
+        rightval = rightval / ((float) max_right_val - dc_offset_right);
+      delta = fabs (leftval - rightval);
+      if (delta  >= Upper_Threshold)  // max delta is 2, min is 0.  How different are channels in normalized terms?  Above threshold, make a bit.
+      { clock_t used_time = clock ();
+        if (used_time != (clock_t) -1)
+          bit = (char) (used_time % 2);
+        else
+        { struct timespec current_time;
+          clock_gettime(CLOCK_REALTIME, &current_time);
+          bit = (char) current_time.tv_nsec % 2;
+        }
+      } 
+      else
+        bit = -1;
+      if (bit != -1)
+      { if (Verbose > 2)
+          dolog(LOG_DEBUG, "bit %d", (int) bit);
+        add_entropy_bit (bit, output_buffer, n_output_bytes);
+      }
+    }
+  }
+  if (Verbose > 1)
+    dolog(LOG_DEBUG, "get_random_data() finished");
+}
 
-	if (verbose > 1)
-		dolog(LOG_DEBUG, "get_random_data() finished");
+void add_entropy_bit (char bit, unsigned char *output_buffer, int *n_output_bytes)
+{
+  static int bits_out=0;
+  static unsigned char byte_out=0;
 
-	free(input_buffer);
+  byte_out <<= 1;
+  byte_out += bit;
+  bits_out++;
+  if (bits_out>=8)
+  { if (Error_State == 0 || Internal_Test == 1)
+    { (output_buffer)[*n_output_bytes]=byte_out;
+      (*n_output_bytes)++;
+    }
+    bits_out=0;
+    RNGTEST_add(byte_out);
+    if (Internal_Test == 1 && RNGTEST() == -1)
+    { if (Error_State == 0)
+        dolog(LOG_CRIT, "test of random data failed, skipping %d bytes before re-using data-stream (%d bytes in flush)", RNGTEST_PENALTY, Error_State);
+      Error_State = RNGTEST_PENALTY;
+      *n_output_bytes = 0;
+    } else
+    { if (Error_State > 0)
+      { Error_State--;
+        if (Error_State == 0)
+          dolog(LOG_INFO, "Restarting fetching of entropy data");
+      }
+    }
+  }
 }
 
 void usage(void)
 {
-	fprintf(stderr, "Usage: audio-entropyd [options]\n\n");
-	fprintf(stderr, "Collect entropy from a soundcard and feed it into the kernel random pool.\n");
-	fprintf(stderr, "\n");
-	fprintf(stderr, "Options:\n");
-	fprintf(stderr, "--device,       -d []  Specify sound device to use. (Default %s)\n", cdevice);
-	fprintf(stderr, "--sample-rate,  -N []  Audio sampling rate. (default %i)\n", DEFAULT_SAMPLE_RATE);
-	fprintf(stderr, "--skip-test,    -s     Do not check if data is random enough.\n");
-	fprintf(stderr, "--do-not-fork   -n     Do not fork.\n");
-	fprintf(stderr, "--verbose,      -v     Be verbose.\n");
-	fprintf(stderr, "--help,         -h     This help.\n");
-	fprintf(stderr, "\n");
+  fprintf(stderr, "Usage: audio-entropyd [options]\n\n");
+  fprintf(stderr, "Collect entropy from a soundcard and feed it into the kernel random pool.\n");
+  fprintf(stderr, "\n");
+  fprintf(stderr, "Options:\n");
+  fprintf(stderr, "--always_close,    -a     Always close sound device after use, even if pause-resume available. (Default no)\n");
+  fprintf(stderr, "--device,          -d []  Specify sound device to use. (Default %s)\n", Capture_Device);
+  fprintf(stderr, "--entropy_filter,  -e []  Filter to use for extracting entropy from the capture data. (Default %i)\n", Entropy_Filter);
+  fprintf(stderr, "--lower_threshodd, -l []  When an entropy filter needs thresholds, this is the lower. (Default %5.3f)\n", Lower_Threshold);
+  fprintf(stderr, "--upper_threshodd, -u []  When an entropy filter needs thresholds, this is the upper. (Default %5.3f)\n", Upper_Threshold);
+  fprintf(stderr, "--sample-rate,     -r []  Audio sampling rate. (Default %i)\n", Frame_Rate);
+  fprintf(stderr, "--sample-size,     -z []  Size of sample to get for analysis each time. (Default %i)\n", Process_Frames);
+  fprintf(stderr, "--skip-size,       -s []  Size of sample to skip each time device opened. No skip for pause-resume. (Default %i)\n", Skip_Frames);
+  fprintf(stderr, "--internal_test,   -i []  Test the gathered entropy internally. (Default no)\n");
+  fprintf(stderr, "--do-not-fork      -n     Do not fork. (Default fork)\n");
+  fprintf(stderr, "--store_in_file,   -f []  Path to save file. (Default no)\n");
+  fprintf(stderr, "--verbose,         -v     Be Verbose, up to 3 times. (Default no)\n");
+  fprintf(stderr, "--help,            -h     This help. (Default no)\n");
+  fprintf(stderr, "Configuration file at /etc/sysconfig/audio-entropyd has more detail and sample values.\n");
+  fprintf(stderr, "\n");
 }
 
 void daemonise(void)
 {
-	if (become_daemon() == -1)
-		error_exit("cannot fork into the background");
+  if (become_daemon() == -1)
+    error_exit("cannot fork into the background");
 
-	if (write_pidfile(PID_FILE) == -1)
-		error_exit("Couldn't open PID file \"%s\" for writing: %m.", PID_FILE);
+  if (write_pidfile(PID_FILE) == -1)
+    error_exit("Couldn't open PID file \"%s\" for writing: %m.", PID_FILE);
 }
 
 void gracefully_exit(int signum)
 {
-	if (munlockall() == -1)
-		error_exit("problem unlocking pages");
-	unlink(PID_FILE);
-	dolog(LOG_NOTICE, "audio-entropyd stopping due to signal %d", signum);
-	exit(0);
+  if (munlockall() == -1)
+    error_exit("problem unlocking pages");
+  unlink(PID_FILE);
+  dolog(LOG_NOTICE, "audio-entropyd stopping due to signal %d", signum);
+  exit(0);
 }
 
 void logging_handler(int signum)
 {
-	if (signum == SIGUSR1) 
-	{
-		loggingstate = 1; 
-		dolog(LOG_WARNING, "Currently in flush state: entropy data is not random enough");
-	}
+  if (signum == SIGUSR1) 
+  {
+    loggingstate = 1; 
+    dolog(LOG_WARNING, "Currently in flush state: entropy data is not random enough");
+  }
 
-	if (signum == SIGUSR2) 
-		loggingstate = 0; 
+  if (signum == SIGUSR2) 
+    loggingstate = 0; 
 }