cannam@85: /* cannam@85: ** Copyright (C) 2005-2011 Erik de Castro Lopo cannam@85: ** cannam@85: ** This program is free software; you can redistribute it and/or modify cannam@85: ** it under the terms of the GNU General Public License as published by cannam@85: ** the Free Software Foundation; either version 2 of the License, or cannam@85: ** (at your option) any later version. cannam@85: ** cannam@85: ** This program is distributed in the hope that it will be useful, cannam@85: ** but WITHOUT ANY WARRANTY; without even the implied warranty of cannam@85: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the cannam@85: ** GNU General Public License for more details. cannam@85: ** cannam@85: ** You should have received a copy of the GNU General Public License cannam@85: ** along with this program; if not, write to the Free Software cannam@85: ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. cannam@85: */ cannam@85: cannam@85: /* cannam@85: ** A simple checksum for short, int and float data. cannam@85: */ cannam@85: cannam@85: #include "sfconfig.h" cannam@85: cannam@85: #include cannam@85: #include cannam@85: #include cannam@85: #include cannam@85: cannam@85: #include cannam@85: cannam@85: #include "regtest.h" cannam@85: cannam@85: #define BIG_PRIME 999983 cannam@85: cannam@85: #define ARRAY_LEN(x) ((int) (sizeof (x)) / (sizeof ((x) [0]))) cannam@85: cannam@85: static int short_checksum (SNDFILE * file, int start) ; cannam@85: static int int_checksum (SNDFILE * file, int start) ; cannam@85: static int float_checksum (SNDFILE * file, int start) ; cannam@85: cannam@85: int cannam@85: calc_checksum (SNDFILE * file, const SF_INFO * info) cannam@85: { int start ; cannam@85: cannam@85: /* Seed the checksum with data from the SF_INFO struct. */ cannam@85: start = info->samplerate ; cannam@85: start = start * BIG_PRIME + info->channels ; cannam@85: start = start * BIG_PRIME + info->format ; cannam@85: cannam@85: switch (info->format & SF_FORMAT_SUBMASK) cannam@85: { case SF_FORMAT_FLOAT : cannam@85: case SF_FORMAT_DOUBLE : cannam@85: return float_checksum (file, start) ; cannam@85: cannam@85: case SF_FORMAT_PCM_24 : cannam@85: case SF_FORMAT_PCM_32 : cannam@85: return int_checksum (file, start) ; cannam@85: cannam@85: default : cannam@85: return short_checksum (file, start) ; cannam@85: } ; cannam@85: cannam@85: return 0 ; cannam@85: } /* calc_checksum */ cannam@85: cannam@85: /*------------------------------------------------------------------------------ cannam@85: */ cannam@85: cannam@85: static union cannam@85: { short s [1 << 16] ; cannam@85: int i [1 << 15] ; cannam@85: float f [1 << 15] ; cannam@85: } data ; cannam@85: cannam@85: static int cannam@85: short_checksum (SNDFILE * file, int start) cannam@85: { int k, count ; cannam@85: cannam@85: do cannam@85: { count = (int) sf_read_short (file, data.s, ARRAY_LEN (data.s)) ; cannam@85: for (k = 0 ; k < count ; k++) cannam@85: start = start * BIG_PRIME + data.s [k] ; cannam@85: } cannam@85: while (count > 0) ; cannam@85: cannam@85: return start ; cannam@85: } /* short_checksum */ cannam@85: cannam@85: static int cannam@85: int_checksum (SNDFILE * file, int start) cannam@85: { int k, count ; cannam@85: cannam@85: do cannam@85: { count = (int) sf_read_int (file, data.i, ARRAY_LEN (data.i)) ; cannam@85: for (k = 0 ; k < count ; k++) cannam@85: start = start * BIG_PRIME + data.i [k] ; cannam@85: } cannam@85: while (count > 0) ; cannam@85: cannam@85: return start ; cannam@85: } /* int_checksum */ cannam@85: cannam@85: static int cannam@85: float_checksum (SNDFILE * file, int start) cannam@85: { int k, count ; cannam@85: cannam@85: do cannam@85: { count = (int) sf_read_float (file, data.f, ARRAY_LEN (data.f)) ; cannam@85: for (k = 0 ; k < count ; k++) cannam@85: start = start * BIG_PRIME + lrintf (0x7FFFFFFF * data.f [k]) ; cannam@85: } cannam@85: while (count > 0) ; cannam@85: cannam@85: return start ; cannam@85: } /* float_checksum */ cannam@85: