00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <inttypes.h>
00025 #include <assert.h>
00026
00027 #define FFMIN(a,b) ((a) > (b) ? (b) : (a))
00028 #define F 100
00029 #define SIZE 2048
00030
00031 uint64_t exp16_table[21]={
00032 65537,
00033 65538,
00034 65540,
00035 65544,
00036 65552,
00037 65568,
00038 65600,
00039 65664,
00040 65793,
00041 66050,
00042 66568,
00043 67616,
00044 69763,
00045 74262,
00046 84150,
00047 108051,
00048 178145,
00049 484249,
00050 3578144,
00051 195360063,
00052 582360139072LL,
00053 };
00054
00055 #if 0
00056
00057 static unsigned int exp16(unsigned int a){
00058 int i;
00059 int out= 1<<16;
00060
00061 for(i=19;i>=0;i--){
00062 if(a&(1<<i))
00063 out= (out*exp16_table[i] + (1<<15))>>16;
00064 }
00065
00066 return out;
00067 }
00068 #endif
00069
00070
00071 static int64_t log16(uint64_t a){
00072 int i;
00073 int out=0;
00074
00075 if(a < 1<<16)
00076 return -log16((1LL<<32) / a);
00077 a<<=16;
00078
00079 for(i=20;i>=0;i--){
00080 int64_t b= exp16_table[i];
00081 if(a<(b<<16)) continue;
00082 out |= 1<<i;
00083 a = ((a/b)<<16) + (((a%b)<<16) + b/2)/b;
00084 }
00085 return out;
00086 }
00087
00088 static uint64_t int_sqrt(uint64_t a)
00089 {
00090 uint64_t ret=0;
00091 int s;
00092 uint64_t ret_sq=0;
00093
00094 for(s=31; s>=0; s--){
00095 uint64_t b= ret_sq + (1ULL<<(s*2)) + (ret<<s)*2;
00096 if(b<=a){
00097 ret_sq=b;
00098 ret+= 1ULL<<s;
00099 }
00100 }
00101 return ret;
00102 }
00103
00104 int main(int argc,char* argv[]){
00105 int i, j;
00106 uint64_t sse=0;
00107 uint64_t dev;
00108 FILE *f[2];
00109 uint8_t buf[2][SIZE];
00110 uint64_t psnr;
00111 int len= argc<4 ? 1 : atoi(argv[3]);
00112 int64_t max= (1<<(8*len))-1;
00113 int shift= argc<5 ? 0 : atoi(argv[4]);
00114 int skip_bytes = argc<6 ? 0 : atoi(argv[5]);
00115 int size0=0;
00116 int size1=0;
00117 int maxdist = 0;
00118
00119 if(argc<3){
00120 printf("tiny_psnr <file1> <file2> [<elem size> [<shift> [<skip bytes>]]]\n");
00121 printf("WAV headers are skipped automatically.\n");
00122 return 1;
00123 }
00124
00125 f[0]= fopen(argv[1], "rb");
00126 f[1]= fopen(argv[2], "rb");
00127 if(!f[0] || !f[1]){
00128 fprintf(stderr, "Could not open input files.\n");
00129 return 1;
00130 }
00131
00132 for (i = 0; i < 2; i++) {
00133 uint8_t *p = buf[i];
00134 if (fread(p, 1, 12, f[i]) != 12)
00135 return 1;
00136 if (!memcmp(p, "RIFF", 4) &&
00137 !memcmp(p+8, "WAVE", 4)) {
00138 if (fread(p, 1, 8, f[i]) != 8)
00139 return 1;
00140 while (memcmp(p, "data", 4)) {
00141 int s = p[4] | p[5]<<8 | p[6]<<16 | p[7]<<24;
00142 fseek(f[i], s, SEEK_CUR);
00143 if (fread(p, 1, 8, f[i]) != 8)
00144 return 1;
00145 }
00146 } else {
00147 fseek(f[i], -12, SEEK_CUR);
00148 }
00149 }
00150
00151 fseek(f[shift<0], abs(shift), SEEK_CUR);
00152
00153 fseek(f[0],skip_bytes,SEEK_CUR);
00154 fseek(f[1],skip_bytes,SEEK_CUR);
00155
00156 for(;;){
00157 int s0= fread(buf[0], 1, SIZE, f[0]);
00158 int s1= fread(buf[1], 1, SIZE, f[1]);
00159
00160 for(j=0; j<FFMIN(s0,s1); j++){
00161 int64_t a= buf[0][j];
00162 int64_t b= buf[1][j];
00163 int dist;
00164 if(len==2){
00165 a= (int16_t)(a | (buf[0][++j]<<8));
00166 b= (int16_t)(b | (buf[1][ j]<<8));
00167 }
00168 sse += (a-b) * (a-b);
00169 dist = abs(a-b);
00170 if (dist > maxdist) maxdist = dist;
00171 }
00172 size0 += s0;
00173 size1 += s1;
00174 if(s0+s1<=0)
00175 break;
00176 }
00177
00178 i= FFMIN(size0,size1)/len;
00179 if(!i) i=1;
00180 dev= int_sqrt( ((sse/i)*F*F) + (((sse%i)*F*F) + i/2)/i );
00181 if(sse)
00182 psnr= ((2*log16(max<<16) + log16(i) - log16(sse))*284619LL*F + (1LL<<31)) / (1LL<<32);
00183 else
00184 psnr= 1000*F-1;
00185
00186 printf("stddev:%5d.%02d PSNR:%3d.%02d MAXDIFF:%5d bytes:%9d/%9d\n",
00187 (int)(dev/F), (int)(dev%F),
00188 (int)(psnr/F), (int)(psnr%F),
00189 maxdist,
00190 size0, size1);
00191 return 0;
00192 }
00193
00194