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