C Implementation to generate Pseudo Random Numbers

From LTwiki-Wiki for LTspice

See http://www.teaser.fr/~amajorel/noise/ with premade wav files that can be used as inputs to LTspice and
The Maxim Application Note

/*
 *	lfsr.c
 */

/*
This file is copyright Andre Majorel 2007-2008.

This program is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published by the
Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/


#include <inttypes.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>


static void err (const char *fmt, ...);


int main (int argc, char *argv[])
{
  uint32_t r = 0x12345678;
  uint32_t tapsmask = 0x80000062;
  char output_format = 'h';

  /*
   *	Parse the command line
   */
  if (argc == 2 && strcmp (argv[1], "--help") == 0)
  {
    printf (
"Usage:\n"
"  lfsr --help\n"
"  lfsr [-bh] [-s num] [-t num]\n"
"Options:\n"
"  -b      Binary dump in native endianness of state to stdout\n"
"  -h      Hex dump of state to stdout (this is the default)\n"
"  -s num  Seed value (default 0x%08lx)\n"
"  -t num  Taps mask (default 0x%08lx)\n"
	, (unsigned long) r
	, (unsigned long) tapsmask
      );
    exit (0);
  }
  {
    int g;

    while ((g = getopt (argc, argv, "bhs:t:")) != EOF)
    {
      if (g == 'b')
	output_format = 'b';
      else if (g == 'h')
	output_format = 'h';
      else if (g == 's')
	r = strtoul (optarg, NULL, 0);  /* FIXME catch errors */
      else if (g == 't')
	tapsmask = strtoul (optarg, NULL, 0);  /* FIXME catch errors */
      else if (g == '?')
	exit (1);
      else
      {
	err ("unhandled option -%c, report this bug", g);
	exit (3);
      }
    }
  }
  if (argc > optind)
  {
    err ("too many arguments, try lfsr --help");
    exit (1);
  }

  /*
   *	Crunch
   */
  fprintf (stderr, "lfsr: seed %08lX\n", (unsigned long) r);
  fprintf (stderr, "lfsr: taps mask %08lX\n", (unsigned long) tapsmask);
  for (;;)
  {
    if (output_format == 'h')
    {
      if (printf ("%08lx\n", (unsigned long) r) < 1)
      {
	err ("-: write error");
	exit (2);
      }
    }
    else if (output_format == 'b')
    {
      if (fwrite ((char *) &r, sizeof r, 1, stdout) != 1)
      {
	err ("-: write error");
	exit (2);
      }
    }

    if (r & 1)
      r = (1 << 31) | ((r ^ tapsmask) >> 1);
    else
      r >>= 1;
  }

  return 0;
}


static void err (const char *fmt, ...)
{
  va_list argp;

  fflush (stdout);			/* FIXME catch errors */
  fputs ("lfsr: ", stderr);		/* FIXME catch errors */
  va_start (argp, fmt);
  vfprintf (stderr, fmt, argp);		/* FIXME catch errors */
  va_end (argp);
  fputc ('\n', stderr);			/* FIXME catch errors */
}