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