annotate ext/kissfft/tools/psdpng.c @ 187:5b065087cb7e qm-vamp-plugins-v1.7.1

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