• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Bug:
3 	- runs only on little endian machines for WAV files
4         - Not all WAV files are recognized
5  */
6 
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <math.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <memory.h>
14 
15 typedef signed short stereo [2];
16 typedef signed short mono;
17 typedef struct {
18     unsigned long long  n;
19     long double         x;
20     long double         x2;
21     long double         y;
22     long double         y2;
23     long double         xy;
24 } korr_t;
25 
analyze_stereo(const stereo * p,size_t len,korr_t * k)26 void analyze_stereo ( const stereo* p, size_t len, korr_t* k )
27 {
28     long double  _x = 0, _x2 = 0, _y = 0, _y2 = 0, _xy = 0;
29     double       t1;
30     double       t2;
31 
32     k -> n  += len;
33 
34     for ( ; len--; p++ ) {
35         _x  += (t1 = (*p)[0]); _x2 += t1 * t1;
36         _y  += (t2 = (*p)[1]); _y2 += t2 * t2;
37                                _xy += t1 * t2;
38     }
39 
40     k -> x  += _x ;
41     k -> x2 += _x2;
42     k -> y  += _y ;
43     k -> y2 += _y2;
44     k -> xy += _xy;
45 }
46 
analyze_dstereo(const stereo * p,size_t len,korr_t * k)47 void analyze_dstereo ( const stereo* p, size_t len, korr_t* k )
48 {
49     static double l0 = 0;
50     static double l1 = 0;
51     long double   _x = 0, _x2 = 0, _y = 0, _y2 = 0, _xy = 0;
52     double        t1;
53     double        t2;
54 
55     k -> n  += len;
56 
57     for ( ; len--; p++ ) {
58         _x  += (t1 = (*p)[0] - l0);  _x2 += t1 * t1;
59         _y  += (t2 = (*p)[1] - l1);  _y2 += t2 * t2;
60                                      _xy += t1 * t2;
61 	l0   = (*p)[0];
62 	l1   = (*p)[1];
63     }
64 
65     k -> x  += _x ;
66     k -> x2 += _x2;
67     k -> y  += _y ;
68     k -> y2 += _y2;
69     k -> xy += _xy;
70 }
71 
72 
analyze_mono(const mono * p,size_t len,korr_t * k)73 void analyze_mono   ( const mono* p, size_t len, korr_t* k )
74 {
75     long double   _x = 0, _x2 = 0;
76     double        t1;
77 
78     k -> n  += len;
79 
80     for ( ; len--; p++ ) {
81         _x  += (t1 = (*p)); _x2 += t1 * t1;
82     }
83 
84     k -> x  += _x ;
85     k -> x2 += _x2;
86     k -> y  += _x ;
87     k -> y2 += _x2;
88     k -> xy += _x2;
89 }
90 
analyze_dmono(const mono * p,size_t len,korr_t * k)91 void analyze_dmono   ( const mono* p, size_t len, korr_t* k )
92 {
93     static double l0 = 0;
94     long double   _x = 0, _x2 = 0;
95     double        t1;
96 
97     k -> n  += len;
98 
99     for ( ; len--; p++ ) {
100         _x  += (t1 = (*p) - l0); _x2 += t1 * t1;
101 	l0   = *p;
102     }
103 
104     k -> x  += _x ;
105     k -> x2 += _x2;
106     k -> y  += _x ;
107     k -> y2 += _x2;
108     k -> xy += _x2;
109 }
110 
sgn(long double x)111 int sgn ( long double x )
112 {
113     if ( x > 0 ) return +1;
114     if ( x < 0 ) return -1;
115     return 0;
116 }
117 
report(const korr_t * k)118 int report ( const korr_t* k )
119 {
120     long double  scale = sqrt ( 1.e5 / (1<<29) ); // Sine Full Scale is +10 dB, 7327 = 100%
121     long double  r;
122     long double  rd;
123     long double  sx;
124     long double  sy;
125     long double  x;
126     long double  y;
127     long double  b;
128 
129     r  = (k->x2*k->n - k->x*k->x) * (k->y2*k->n - k->y*k->y);
130     r  = r  > 0.l  ?  (k->xy*k->n - k->x*k->y) / sqrt (r)  :  1.l;
131     sx = k->n > 1  ?  sqrt ( (k->x2 - k->x*k->x/k->n) / (k->n - 1) )  :  0.l;
132     sy = k->n > 1  ?  sqrt ( (k->y2 - k->y*k->y/k->n) / (k->n - 1) )  :  0.l;
133     x  = k->n > 0  ?  k->x/k->n  :  0.l;
134     y  = k->n > 0  ?  k->y/k->n  :  0.l;
135 
136     b  = atan2 ( sy, sx * sgn (r) ) * ( 8 / M_PI);
137 
138 //    6       5        4        3        2
139 //      _______________________________
140 //      |\             |             /|
141 //    7 |   \          |          /   |  1
142 //      |      \       |       /      |
143 //      |         \    |    /         |
144 //      |            \ | /            |
145 //    8 |--------------+--------------|  0
146 //      |            / | \            |
147 //      |         /    |    \         |
148 //   -7 |      /       |       \      | -1
149 //      |   /          |          \   |
150 //      |/_____________|_____________\|
151 //
152 //   -6       -5      -4      -3        -2
153 
154     if ( r > 0.98 ) {
155         printf ("-mm");		// disguised mono file
156 	return;
157     }
158     if ( fabs (b-2) > 0.666 ) {
159         printf ("-ms");		// low profit for joint stereo
160 	return;
161     }
162     if ( r < 0.333 ) {
163         printf ("-ms");		// low profit for joint stereo
164 	return;
165     }
166 }
167 
readfile(const char * name,int fd)168 void readfile ( const char* name, int fd )
169 {
170     unsigned short  header [22];
171     stereo          s [4096];
172     mono            m [8192];
173     size_t          samples;
174     korr_t          k0;
175     korr_t          k1;
176 
177     memset ( &k0, 0, sizeof(k0) );
178     memset ( &k1, 0, sizeof(k1) );
179 
180     read ( fd, header, sizeof(header) );
181 
182     switch ( header[11] ) {
183     case 1:
184         printf ("-mm\n");
185         break;
186 
187     case 2:
188         while  ( ( samples = read (fd, s, sizeof(s)) ) > 0 ) {
189             analyze_stereo  ( s, samples / sizeof (*s), &k0 );
190             analyze_dstereo ( s, samples / sizeof (*s), &k1 );
191 	}
192         report (&k0);
193         report (&k1);
194 	break;
195 
196     default:
197         fprintf ( stderr, "%u Channels not supported: %s\n", header[11], name );
198         break;
199     }
200 }
201 
main(int argc,char ** argv)202 int main ( int argc, char** argv )
203 {
204     char*  name;
205     int    fd;
206 
207     if (argc < 2)
208         readfile ( "<stdin>", 0 );
209     else
210         while ( (name = *++argv) != NULL ) {
211 	    if ( (fd = open ( name, O_RDONLY )) >= 0 ) {
212                 readfile ( name, fd );
213 		close ( fd );
214 	    } else {
215 	        fprintf ( stderr, "Can't open: %s\n", name );
216 	    }
217         }
218 
219     return 0;
220 }
221