summaryrefslogtreecommitdiff
path: root/regtest/checksum.c
diff options
context:
space:
mode:
Diffstat (limited to 'regtest/checksum.c')
-rw-r--r--regtest/checksum.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/regtest/checksum.c b/regtest/checksum.c
new file mode 100644
index 0000000..033a156
--- /dev/null
+++ b/regtest/checksum.c
@@ -0,0 +1,125 @@
+/*
+** Copyright (C) 2005 Erik de Castro Lopo
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+** A simple checksum for short, int and float data.
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sndfile.h>
+
+#include "float_cast.h"
+
+#include "regtest.h"
+
+#define BIG_PRIME 999983
+
+#define ARRAY_LEN(x) ((int) (sizeof (x)) / (sizeof ((x) [0])))
+
+static int short_checksum (SNDFILE * file, int start) ;
+static int int_checksum (SNDFILE * file, int start) ;
+static int float_checksum (SNDFILE * file, int start) ;
+
+int
+calc_checksum (SNDFILE * file, const SF_INFO * info)
+{ int start ;
+
+ /* Seed the checksum with data from the SF_INFO struct. */
+ start = info->samplerate ;
+ start = start * BIG_PRIME + info->channels ;
+ start = start * BIG_PRIME + info->format ;
+
+ switch (info->format & SF_FORMAT_SUBMASK)
+ { case SF_FORMAT_FLOAT :
+ case SF_FORMAT_DOUBLE :
+ return float_checksum (file, start) ;
+
+ case SF_FORMAT_PCM_24 :
+ case SF_FORMAT_PCM_32 :
+ return int_checksum (file, start) ;
+
+ default :
+ return short_checksum (file, start) ;
+ } ;
+
+ return 0 ;
+} /* calc_checksum */
+
+/*------------------------------------------------------------------------------
+*/
+
+static union
+{ short s [1 << 16] ;
+ int i [1 << 15] ;
+ float f [1 << 15] ;
+} data ;
+
+static int
+short_checksum (SNDFILE * file, int start)
+{ int k, count ;
+
+ do
+ { count = (int) sf_read_short (file, data.s, ARRAY_LEN (data.s)) ;
+ for (k = 0 ; k < count ; k++)
+ start = start * BIG_PRIME + data.s [k] ;
+ }
+ while (count > 0) ;
+
+ return start ;
+} /* short_checksum */
+
+static int
+int_checksum (SNDFILE * file, int start)
+{ int k, count ;
+
+ do
+ { count = (int) sf_read_int (file, data.i, ARRAY_LEN (data.i)) ;
+ for (k = 0 ; k < count ; k++)
+ start = start * BIG_PRIME + data.i [k] ;
+ }
+ while (count > 0) ;
+
+ return start ;
+} /* int_checksum */
+
+static int
+float_checksum (SNDFILE * file, int start)
+{ int k, count ;
+
+ do
+ { count = (int) sf_read_float (file, data.f, ARRAY_LEN (data.f)) ;
+ for (k = 0 ; k < count ; k++)
+ start = start * BIG_PRIME + lrintf (0x7FFFFFFF * data.f [k]) ;
+ }
+ while (count > 0) ;
+
+ return start ;
+} /* float_checksum */
+
+/*
+** Do not edit or modify anything in this comment block.
+** The following line is a file identity tag for the GNU Arch
+** revision control system.
+**
+** arch-tag: 6ae999d1-dd5a-4306-9e11-d4cfc9e8ae27
+*/