1/* 2** Copyright (C) 2008-2016 Erik de Castro Lopo <erikd@mega-nerd.com> 3** Copyright (C) 2008 Conrad Parker <conrad@metadecks.org> 4** 5** All rights reserved. 6** 7** Redistribution and use in source and binary forms, with or without 8** modification, are permitted provided that the following conditions are 9** met: 10** 11** * Redistributions of source code must retain the above copyright 12** notice, this list of conditions and the following disclaimer. 13** * Redistributions in binary form must reproduce the above copyright 14** notice, this list of conditions and the following disclaimer in 15** the documentation and/or other materials provided with the 16** distribution. 17** * Neither the author nor the names of any contributors may be used 18** to endorse or promote products derived from this software without 19** specific prior written permission. 20** 21** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 25** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32*/ 33 34#include "sfconfig.h" 35 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <inttypes.h> 40 41#include <sndfile.h> 42 43#include "common.h" 44 45/* Length of comparison data buffers in units of items */ 46#define BUFLEN 65536 47 48static const char * progname = NULL ; 49static char * filename1 = NULL, * filename2 = NULL ; 50 51static int 52comparison_error (const char * what, sf_count_t frame_offset) 53{ char buffer [128] ; 54 55 if (frame_offset >= 0) 56 snprintf (buffer, sizeof (buffer), " (at frame offset %" PRId64 ")", frame_offset) ; 57 else 58 buffer [0] = 0 ; 59 60 printf ("%s: %s of files %s and %s differ%s.\n", progname, what, filename1, filename2, buffer) ; 61 return 1 ; 62} /* comparison_error */ 63 64static int 65compare (void) 66{ 67 double buf1 [BUFLEN], buf2 [BUFLEN] ; 68 SF_INFO sfinfo1, sfinfo2 ; 69 SNDFILE * sf1 = NULL, * sf2 = NULL ; 70 sf_count_t items, i, nread1, nread2, offset = 0 ; 71 int retval = 0 ; 72 73 memset (&sfinfo1, 0, sizeof (SF_INFO)) ; 74 sf1 = sf_open (filename1, SFM_READ, &sfinfo1) ; 75 if (sf1 == NULL) 76 { printf ("Error opening %s.\n", filename1) ; 77 retval = 1 ; 78 goto out ; 79 } ; 80 81 memset (&sfinfo2, 0, sizeof (SF_INFO)) ; 82 sf2 = sf_open (filename2, SFM_READ, &sfinfo2) ; 83 if (sf2 == NULL) 84 { printf ("Error opening %s.\n", filename2) ; 85 retval = 1 ; 86 goto out ; 87 } ; 88 89 if (sfinfo1.samplerate != sfinfo2.samplerate) 90 { retval = comparison_error ("Samplerates", -1) ; 91 goto out ; 92 } ; 93 94 if (sfinfo1.channels != sfinfo2.channels) 95 { retval = comparison_error ("Number of channels", -1) ; 96 goto out ; 97 } ; 98 99 /* Calculate the framecount that will fit in our data buffers */ 100 items = BUFLEN / sfinfo1.channels ; 101 102 while ((nread1 = sf_readf_double (sf1, buf1, items)) > 0) 103 { nread2 = sf_readf_double (sf2, buf2, nread1) ; 104 if (nread2 != nread1) 105 { retval = comparison_error ("PCM data lengths", -1) ; 106 goto out ; 107 } ; 108 for (i = 0 ; i < nread1 * sfinfo1.channels ; i++) 109 { if (buf1 [i] != buf2 [i]) 110 { retval = comparison_error ("PCM data", offset + i / sfinfo1.channels) ; 111 goto out ; 112 } ; 113 } ; 114 offset += nread1 ; 115 } ; 116 117 if ((nread2 = sf_readf_double (sf2, buf2, items)) != 0) 118 { retval = comparison_error ("PCM data lengths", -1) ; 119 goto out ; 120 } ; 121 122out : 123 sf_close (sf1) ; 124 sf_close (sf2) ; 125 126 return retval ; 127} /* compare */ 128 129static void 130usage_exit (void) 131{ 132 printf ("Usage : %s <filename> <filename>\n", progname) ; 133 printf (" Compare the PCM data of two sound files.\n\n") ; 134 printf ("Using %s.\n\n", sf_version_string ()) ; 135 exit (1) ; 136} /* usage_exit */ 137 138int 139main (int argc, char *argv []) 140{ 141 progname = program_name (argv [0]) ; 142 143 if (argc != 3) 144 usage_exit () ; 145 146 filename1 = argv [argc - 2] ; 147 filename2 = argv [argc - 1] ; 148 149 if (strcmp (filename1, filename2) == 0) 150 { printf ("Error : Input filenames are the same.\n\n") ; 151 usage_exit () ; 152 } ; 153 154 return compare () ; 155} /* main */ 156