checksum.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. ** Copyright (C) 2005-2011 Erik de Castro Lopo
  3. **
  4. ** This program is free software; you can redistribute it and/or modify
  5. ** it under the terms of the GNU General Public License as published by
  6. ** the Free Software Foundation; either version 2 of the License, or
  7. ** (at your option) any later version.
  8. **
  9. ** This program is distributed in the hope that it will be useful,
  10. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ** GNU General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU General Public License
  15. ** along with this program; if not, write to the Free Software
  16. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. /*
  19. ** A simple checksum for short, int and float data.
  20. */
  21. #include "sfconfig.h"
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <math.h>
  26. #include <sndfile.h>
  27. #include "regtest.h"
  28. #define BIG_PRIME 999983
  29. #define ARRAY_LEN(x) ((int) (sizeof (x)) / (sizeof ((x) [0])))
  30. static int short_checksum (SNDFILE * file, int start) ;
  31. static int int_checksum (SNDFILE * file, int start) ;
  32. static int float_checksum (SNDFILE * file, int start) ;
  33. int
  34. calc_checksum (SNDFILE * file, const SF_INFO * info)
  35. { int start ;
  36. /* Seed the checksum with data from the SF_INFO struct. */
  37. start = info->samplerate ;
  38. start = start * BIG_PRIME + info->channels ;
  39. start = start * BIG_PRIME + info->format ;
  40. switch (info->format & SF_FORMAT_SUBMASK)
  41. { case SF_FORMAT_FLOAT :
  42. case SF_FORMAT_DOUBLE :
  43. return float_checksum (file, start) ;
  44. case SF_FORMAT_PCM_24 :
  45. case SF_FORMAT_PCM_32 :
  46. return int_checksum (file, start) ;
  47. default :
  48. return short_checksum (file, start) ;
  49. } ;
  50. return 0 ;
  51. } /* calc_checksum */
  52. /*------------------------------------------------------------------------------
  53. */
  54. static union
  55. { short s [1 << 16] ;
  56. int i [1 << 15] ;
  57. float f [1 << 15] ;
  58. } data ;
  59. static int
  60. short_checksum (SNDFILE * file, int start)
  61. { int k, count ;
  62. do
  63. { count = (int) sf_read_short (file, data.s, ARRAY_LEN (data.s)) ;
  64. for (k = 0 ; k < count ; k++)
  65. start = start * BIG_PRIME + data.s [k] ;
  66. }
  67. while (count > 0) ;
  68. return start ;
  69. } /* short_checksum */
  70. static int
  71. int_checksum (SNDFILE * file, int start)
  72. { int k, count ;
  73. do
  74. { count = (int) sf_read_int (file, data.i, ARRAY_LEN (data.i)) ;
  75. for (k = 0 ; k < count ; k++)
  76. start = start * BIG_PRIME + data.i [k] ;
  77. }
  78. while (count > 0) ;
  79. return start ;
  80. } /* int_checksum */
  81. static int
  82. float_checksum (SNDFILE * file, int start)
  83. { int k, count ;
  84. do
  85. { count = (int) sf_read_float (file, data.f, ARRAY_LEN (data.f)) ;
  86. for (k = 0 ; k < count ; k++)
  87. start = start * BIG_PRIME + lrintf (2147483648.0f * data.f [k]) ;
  88. }
  89. while (count > 0) ;
  90. return start ;
  91. } /* float_checksum */