annotate ext/kissfft/tools/psdpng.c @ 409:1f1999b0f577

Bring in kissfft into this repo (formerly a subrepo, but the remote is not responding)
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 21 Jul 2015 07:34:15 +0100
parents
children
rev   line source
c@409 1 /*
c@409 2 Copyright (c) 2003-2004, Mark Borgerding
c@409 3
c@409 4 All rights reserved.
c@409 5
c@409 6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
c@409 7
c@409 8 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
c@409 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.
c@409 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.
c@409 11
c@409 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.
c@409 13 */
c@409 14
c@409 15 #include <stdlib.h>
c@409 16 #include <math.h>
c@409 17 #include <stdio.h>
c@409 18 #include <string.h>
c@409 19 #include <unistd.h>
c@409 20 #include <png.h>
c@409 21
c@409 22 #include "kiss_fft.h"
c@409 23 #include "kiss_fftr.h"
c@409 24
c@409 25 int nfft=1024;
c@409 26 FILE * fin=NULL;
c@409 27 FILE * fout=NULL;
c@409 28
c@409 29 int navg=20;
c@409 30 int remove_dc=0;
c@409 31 int nrows=0;
c@409 32 float * vals=NULL;
c@409 33 int stereo=0;
c@409 34
c@409 35 static
c@409 36 void config(int argc,char** argv)
c@409 37 {
c@409 38 while (1) {
c@409 39 int c = getopt (argc, argv, "n:r:as");
c@409 40 if (c == -1)
c@409 41 break;
c@409 42 switch (c) {
c@409 43 case 'n': nfft=(int)atoi(optarg);break;
c@409 44 case 'r': navg=(int)atoi(optarg);break;
c@409 45 case 'a': remove_dc=1;break;
c@409 46 case 's': stereo=1;break;
c@409 47 case '?':
c@409 48 fprintf (stderr, "usage options:\n"
c@409 49 "\t-n d: fft dimension(s) [1024]\n"
c@409 50 "\t-r d: number of rows to average [20]\n"
c@409 51 "\t-a : remove average from each fft buffer\n"
c@409 52 "\t-s : input is stereo, channels will be combined before fft\n"
c@409 53 "16 bit machine format real input is assumed\n"
c@409 54 );
c@409 55 default:
c@409 56 fprintf (stderr, "bad %c\n", c);
c@409 57 exit (1);
c@409 58 break;
c@409 59 }
c@409 60 }
c@409 61 if ( optind < argc ) {
c@409 62 if (strcmp("-",argv[optind]) !=0)
c@409 63 fin = fopen(argv[optind],"rb");
c@409 64 ++optind;
c@409 65 }
c@409 66
c@409 67 if ( optind < argc ) {
c@409 68 if ( strcmp("-",argv[optind]) !=0 )
c@409 69 fout = fopen(argv[optind],"wb");
c@409 70 ++optind;
c@409 71 }
c@409 72 if (fin==NULL)
c@409 73 fin=stdin;
c@409 74 if (fout==NULL)
c@409 75 fout=stdout;
c@409 76 }
c@409 77
c@409 78 #define CHECKNULL(p) if ( (p)==NULL ) do { fprintf(stderr,"CHECKNULL failed @ %s(%d): %s\n",__FILE__,__LINE__,#p );exit(1);} while(0)
c@409 79
c@409 80 typedef struct
c@409 81 {
c@409 82 png_byte r;
c@409 83 png_byte g;
c@409 84 png_byte b;
c@409 85 } rgb_t;
c@409 86
c@409 87 static
c@409 88 void val2rgb(float x,rgb_t *p)
c@409 89 {
c@409 90 const double pi = 3.14159265358979;
c@409 91 p->g = (int)(255*sin(x*pi));
c@409 92 p->r = (int)(255*abs(sin(x*pi*3/2)));
c@409 93 p->b = (int)(255*abs(sin(x*pi*5/2)));
c@409 94 //fprintf(stderr,"%.2f : %d,%d,%d\n",x,(int)p->r,(int)p->g,(int)p->b);
c@409 95 }
c@409 96
c@409 97 static
c@409 98 void cpx2pixels(rgb_t * res,const float * fbuf,size_t n)
c@409 99 {
c@409 100 size_t i;
c@409 101 float minval,maxval,valrange;
c@409 102 minval=maxval=fbuf[0];
c@409 103
c@409 104 for (i = 0; i < n; ++i) {
c@409 105 if (fbuf[i] > maxval) maxval = fbuf[i];
c@409 106 if (fbuf[i] < minval) minval = fbuf[i];
c@409 107 }
c@409 108
c@409 109 fprintf(stderr,"min ==%f,max=%f\n",minval,maxval);
c@409 110 valrange = maxval-minval;
c@409 111 if (valrange == 0) {
c@409 112 fprintf(stderr,"min == max == %f\n",minval);
c@409 113 exit (1);
c@409 114 }
c@409 115
c@409 116 for (i = 0; i < n; ++i)
c@409 117 val2rgb( (fbuf[i] - minval)/valrange , res+i );
c@409 118 }
c@409 119
c@409 120 static
c@409 121 void transform_signal(void)
c@409 122 {
c@409 123 short *inbuf;
c@409 124 kiss_fftr_cfg cfg=NULL;
c@409 125 kiss_fft_scalar *tbuf;
c@409 126 kiss_fft_cpx *fbuf;
c@409 127 float *mag2buf;
c@409 128 int i;
c@409 129 int n;
c@409 130 int avgctr=0;
c@409 131
c@409 132 int nfreqs=nfft/2+1;
c@409 133
c@409 134 CHECKNULL( cfg=kiss_fftr_alloc(nfft,0,0,0) );
c@409 135 CHECKNULL( inbuf=(short*)malloc(sizeof(short)*2*nfft ) );
c@409 136 CHECKNULL( tbuf=(kiss_fft_scalar*)malloc(sizeof(kiss_fft_scalar)*nfft ) );
c@409 137 CHECKNULL( fbuf=(kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx)*nfreqs ) );
c@409 138 CHECKNULL( mag2buf=(float*)malloc(sizeof(float)*nfreqs ) );
c@409 139
c@409 140 memset(mag2buf,0,sizeof(mag2buf)*nfreqs);
c@409 141
c@409 142 while (1) {
c@409 143 if (stereo) {
c@409 144 n = fread(inbuf,sizeof(short)*2,nfft,fin);
c@409 145 if (n != nfft )
c@409 146 break;
c@409 147 for (i=0;i<nfft;++i)
c@409 148 tbuf[i] = inbuf[2*i] + inbuf[2*i+1];
c@409 149 }else{
c@409 150 n = fread(inbuf,sizeof(short),nfft,fin);
c@409 151 if (n != nfft )
c@409 152 break;
c@409 153 for (i=0;i<nfft;++i)
c@409 154 tbuf[i] = inbuf[i];
c@409 155 }
c@409 156
c@409 157 if (remove_dc) {
c@409 158 float avg = 0;
c@409 159 for (i=0;i<nfft;++i) avg += tbuf[i];
c@409 160 avg /= nfft;
c@409 161 for (i=0;i<nfft;++i) tbuf[i] -= (kiss_fft_scalar)avg;
c@409 162 }
c@409 163
c@409 164 /* do FFT */
c@409 165 kiss_fftr(cfg,tbuf,fbuf);
c@409 166
c@409 167 for (i=0;i<nfreqs;++i)
c@409 168 mag2buf[i] += fbuf[i].r * fbuf[i].r + fbuf[i].i * fbuf[i].i;
c@409 169
c@409 170 if (++avgctr == navg) {
c@409 171 avgctr=0;
c@409 172 ++nrows;
c@409 173 vals = (float*)realloc(vals,sizeof(float)*nrows*nfreqs);
c@409 174 float eps = 1;
c@409 175 for (i=0;i<nfreqs;++i)
c@409 176 vals[(nrows - 1) * nfreqs + i] = 10 * log10 ( mag2buf[i] / navg + eps );
c@409 177 memset(mag2buf,0,sizeof(mag2buf[0])*nfreqs);
c@409 178 }
c@409 179 }
c@409 180
c@409 181 free(cfg);
c@409 182 free(inbuf);
c@409 183 free(tbuf);
c@409 184 free(fbuf);
c@409 185 free(mag2buf);
c@409 186 }
c@409 187
c@409 188 static
c@409 189 void make_png(void)
c@409 190 {
c@409 191 png_bytepp row_pointers=NULL;
c@409 192 rgb_t * row_data=NULL;
c@409 193 int i;
c@409 194 int nfreqs = nfft/2+1;
c@409 195
c@409 196 png_structp png_ptr=NULL;
c@409 197 png_infop info_ptr=NULL;
c@409 198
c@409 199 CHECKNULL( png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,0,0,0) );
c@409 200 CHECKNULL( info_ptr = png_create_info_struct(png_ptr) );
c@409 201
c@409 202
c@409 203 png_init_io(png_ptr, fout );
c@409 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 );
c@409 205
c@409 206
c@409 207 row_data = (rgb_t*)malloc(sizeof(rgb_t) * nrows * nfreqs) ;
c@409 208 cpx2pixels(row_data, vals, nfreqs*nrows );
c@409 209
c@409 210 row_pointers = realloc(row_pointers, nrows*sizeof(png_bytep));
c@409 211 for (i=0;i<nrows;++i) {
c@409 212 row_pointers[i] = (png_bytep)(row_data + i*nfreqs);
c@409 213 }
c@409 214 png_set_rows(png_ptr, info_ptr, row_pointers);
c@409 215
c@409 216
c@409 217 fprintf(stderr,"creating %dx%d png\n",nfreqs,nrows);
c@409 218 fprintf(stderr,"bitdepth %d \n",png_get_bit_depth(png_ptr,info_ptr ) );
c@409 219
c@409 220 png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY , NULL);
c@409 221
c@409 222 }
c@409 223
c@409 224 int main(int argc,char ** argv)
c@409 225 {
c@409 226 config(argc,argv);
c@409 227
c@409 228 transform_signal();
c@409 229
c@409 230 make_png();
c@409 231
c@409 232 if (fout!=stdout) fclose(fout);
c@409 233 if (fin!=stdin) fclose(fin);
c@409 234 return 0;
c@409 235 }