]> git.sesse.net Git - kdenlive/blob - src/kiss_fft/tools/psdpng.c
Reorganize and cleanup build structure
[kdenlive] / src / kiss_fft / tools / psdpng.c
1 /*
2 Copyright (c) 2003-2004, Mark Borgerding
3
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7
8     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10     * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11
12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13 */
14
15 #include <stdlib.h>
16 #include <math.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <png.h>
21
22 #include "../kiss_fft.h"
23 #include "kiss_fftr.h"
24
25 int nfft=1024;
26 FILE * fin=NULL;
27 FILE * fout=NULL;
28
29 int navg=20;
30 int remove_dc=0;
31 int nrows=0;
32 float * vals=NULL;
33 int stereo=0;
34
35 static
36 void config(int argc,char** argv)
37 {
38     while (1) {
39         int c = getopt (argc, argv, "n:r:as");
40         if (c == -1)
41             break;
42         switch (c) {
43         case 'n': nfft=(int)atoi(optarg);break;
44         case 'r': navg=(int)atoi(optarg);break;
45         case 'a': remove_dc=1;break;
46         case 's': stereo=1;break;
47         case '?':
48             fprintf (stderr, "usage options:\n"
49                      "\t-n d: fft dimension(s) [1024]\n"
50                      "\t-r d: number of rows to average [20]\n"
51                      "\t-a : remove average from each fft buffer\n"
52                      "\t-s : input is stereo, channels will be combined before fft\n"
53                      "16 bit machine format real input is assumed\n"
54                      );
55         default:
56             fprintf (stderr, "bad %c\n", c);
57             exit (1);
58             break;
59         }
60     }
61     if ( optind < argc ) {
62         if (strcmp("-",argv[optind]) !=0)
63             fin = fopen(argv[optind],"rb");
64         ++optind;
65     }
66
67     if ( optind < argc ) {
68         if ( strcmp("-",argv[optind]) !=0 ) 
69             fout = fopen(argv[optind],"wb");
70         ++optind;
71     }
72     if (fin==NULL)
73         fin=stdin;
74     if (fout==NULL)
75         fout=stdout;
76 }
77
78 #define CHECKNULL(p) if ( (p)==NULL ) do { fprintf(stderr,"CHECKNULL failed @ %s(%d): %s\n",__FILE__,__LINE__,#p );exit(1);} while(0)
79
80 typedef struct
81 {
82     png_byte r;
83     png_byte g;
84     png_byte b;
85 } rgb_t;
86
87 static 
88 void val2rgb(float x,rgb_t *p)
89 {
90     const double pi = 3.14159265358979;
91     p->g = (int)(255*sin(x*pi));
92     p->r = (int)(255*abs(sin(x*pi*3/2)));
93     p->b = (int)(255*abs(sin(x*pi*5/2)));
94     //fprintf(stderr,"%.2f : %d,%d,%d\n",x,(int)p->r,(int)p->g,(int)p->b);
95 }
96
97 static
98 void cpx2pixels(rgb_t * res,const float * fbuf,size_t n)
99 {
100     size_t i;
101     float minval,maxval,valrange;
102     minval=maxval=fbuf[0];
103
104     for (i = 0; i < n; ++i) {
105         if (fbuf[i] > maxval) maxval = fbuf[i];
106         if (fbuf[i] < minval) minval = fbuf[i];
107     }
108
109     fprintf(stderr,"min ==%f,max=%f\n",minval,maxval);
110     valrange = maxval-minval;
111     if (valrange == 0) {
112         fprintf(stderr,"min == max == %f\n",minval);
113         exit (1);
114     }
115
116     for (i = 0; i < n; ++i)
117         val2rgb( (fbuf[i] - minval)/valrange , res+i );
118 }
119
120 static
121 void transform_signal(void)
122 {
123     short *inbuf;
124     kiss_fftr_cfg cfg=NULL;
125     kiss_fft_scalar *tbuf;
126     kiss_fft_cpx *fbuf;
127     float *mag2buf;
128     int i;
129     int n;
130     int avgctr=0;
131
132     int nfreqs=nfft/2+1;
133
134     CHECKNULL( cfg=kiss_fftr_alloc(nfft,0,0,0) );
135     CHECKNULL( inbuf=(short*)malloc(sizeof(short)*2*nfft ) );
136     CHECKNULL( tbuf=(kiss_fft_scalar*)malloc(sizeof(kiss_fft_scalar)*nfft ) );
137     CHECKNULL( fbuf=(kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx)*nfreqs ) );
138     CHECKNULL( mag2buf=(float*)malloc(sizeof(float)*nfreqs ) );
139
140     memset(mag2buf,0,sizeof(mag2buf)*nfreqs);
141
142     while (1) {
143         if (stereo) {
144             n = fread(inbuf,sizeof(short)*2,nfft,fin);
145             if (n != nfft ) 
146                 break;
147             for (i=0;i<nfft;++i) 
148                 tbuf[i] = inbuf[2*i] + inbuf[2*i+1];
149         }else{
150             n = fread(inbuf,sizeof(short),nfft,fin);
151             if (n != nfft ) 
152                 break;
153             for (i=0;i<nfft;++i) 
154                 tbuf[i] = inbuf[i];
155         }
156
157         if (remove_dc) {
158             float avg = 0;
159             for (i=0;i<nfft;++i)  avg += tbuf[i];
160             avg /= nfft;
161             for (i=0;i<nfft;++i)  tbuf[i] -= (kiss_fft_scalar)avg;
162         }
163
164         /* do FFT */
165         kiss_fftr(cfg,tbuf,fbuf);
166
167         for (i=0;i<nfreqs;++i)
168             mag2buf[i] += fbuf[i].r * fbuf[i].r + fbuf[i].i * fbuf[i].i;
169
170         if (++avgctr == navg) {
171             avgctr=0;
172             ++nrows;
173             vals = (float*)realloc(vals,sizeof(float)*nrows*nfreqs);
174             float eps = 1;
175             for (i=0;i<nfreqs;++i)
176                 vals[(nrows - 1) * nfreqs + i] = 10 * log10 ( mag2buf[i] / navg + eps );
177             memset(mag2buf,0,sizeof(mag2buf[0])*nfreqs);
178         }
179     }
180
181     free(cfg);
182     free(inbuf);
183     free(tbuf);
184     free(fbuf);
185     free(mag2buf);
186 }
187
188 static
189 void make_png(void)
190 {
191     png_bytepp row_pointers=NULL;
192     rgb_t * row_data=NULL;
193     int i;
194     int nfreqs = nfft/2+1;
195
196     png_structp png_ptr=NULL;
197     png_infop info_ptr=NULL;
198     
199     CHECKNULL( png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,0,0,0) );
200     CHECKNULL( info_ptr = png_create_info_struct(png_ptr) );
201
202
203     png_init_io(png_ptr, fout );
204     png_set_IHDR(png_ptr, info_ptr ,nfreqs,nrows,8,PNG_COLOR_TYPE_RGB,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT );
205     
206
207     row_data = (rgb_t*)malloc(sizeof(rgb_t) * nrows * nfreqs) ;
208     cpx2pixels(row_data, vals, nfreqs*nrows );
209
210     row_pointers = realloc(row_pointers, nrows*sizeof(png_bytep));
211     for (i=0;i<nrows;++i) {
212         row_pointers[i] = (png_bytep)(row_data + i*nfreqs);
213     }
214     png_set_rows(png_ptr, info_ptr, row_pointers);
215
216
217     fprintf(stderr,"creating %dx%d png\n",nfreqs,nrows);
218     fprintf(stderr,"bitdepth %d \n",png_get_bit_depth(png_ptr,info_ptr ) );
219
220     png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY , NULL);
221
222 }
223
224 int main(int argc,char ** argv)
225 {
226     config(argc,argv);
227
228     transform_signal();
229
230     make_png();
231
232     if (fout!=stdout) fclose(fout);
233     if (fin!=stdin) fclose(fin);
234     return 0;
235 }