there is a new event api ...
[sound-tools/hdrec.git] / hdrec.c
diff --git a/hdrec.c b/hdrec.c
index 58cb670..bf36409 100644 (file)
--- a/hdrec.c
+++ b/hdrec.c
@@ -5,30 +5,42 @@
  *
  */
 
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/time.h>
 #include <sys/soundcard.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
 
+/* dfb */
+#include <directfb.h>
+
 #include "oss_api.h"
 #include "hdrec.h"
 
+/* fourier */
+#include "fourier.h"
+
 int usage(void) {
        printf("usage:\n\n");
        printf("-h \t\t print this help\n");
        printf("-i \t\t use/print file info\n");
+       printf("-R \t\t play reversed :)\n");
+       printf("-d <device> \t sound device (eg: /dev/dsp)\n");
        printf("-r <file> \t record to <file>\n");
        printf("-p <file> \t play from <file>\n");
        printf("-s \t\t stereo\n");
        printf("-m \t\t mono\n");
        printf("-f <format> \t 1=8bit - 2=16bit (le)\n");
        printf("-F <hz> \t frequency\n");
+       printf("-c <src> <dst> \t converts raw to wav (specify f/m,s/F)\n");
        
        return 1;
 }
@@ -46,9 +58,27 @@ int main(int argc,char **argv) {
        char play_file[MAX_C_FILE];
        dsp_set set;
        unsigned char *buf;
+       unsigned char *buf2=NULL;
        unsigned char print_info=0;
        unsigned char info[8];
        int info_int;
+       int tmp;
+       char is_wav=0;
+       fd_set read_fds,write_fds;
+       struct timeval fds_tv;
+       char c;
+
+       /* dfb */
+       IDirectFB *dfb;
+       IDirectFBSurface *primary;
+       DFBSurfaceDescription dsc;
+       int width,height;
+
+       /* fourier */
+       t_fourier fourier;
+       int sample;
+       int dx;
+       int a_f;
 
        /* defaults */
        strcpy(device,"");
@@ -67,13 +97,16 @@ int main(int argc,char **argv) {
                                        print_info=1;
                                        break;
                                case 'r':
-                                       mode=RECORD;
+                                       mode|=RECORD;
                                        strcpy(record_file,argv[++i]);
                                        break;
                                case 'p':
-                                       mode=PLAY;
+                                       mode|=PLAY;
                                        strcpy(play_file,argv[++i]);
                                        break;
+                               case 'R':
+                                       mode|=REVERSED;
+                                       break;
                                case 's':
                                        set.channel=STEREO;
                                        break;
@@ -91,6 +124,11 @@ int main(int argc,char **argv) {
                                case 'd':
                                        strncpy(device,argv[++i],MAX_C_DEVICE-1);
                                        break;
+                               case 'c':
+                                       mode=CONVERT;
+                                       strcpy(play_file,argv[++i]);
+                                       strcpy(record_file,argv[++i]);
+                                       break;
                                default:
                                        usage();
                                        return -1;
@@ -113,13 +151,13 @@ int main(int argc,char **argv) {
        }
 
        /* file fd's */
-       if(mode&PLAY) {
+       if((mode&PLAY) || (mode&CONVERT)) {
                if((pfile_fd=open_file(play_file,O_RDONLY))==-1) {
                        printf("unable to open file %s for reading\n",play_file);
                        return -1;
                }
        }
-       if(mode&RECORD) {
+       if((mode&RECORD) || (mode&CONVERT)) {
                if((sfile_fd=open_file(record_file,O_CREAT|O_WRONLY))==-1) {
                        printf("unable to open file %s for writing\n",record_file);
                        return -1;
@@ -135,16 +173,20 @@ int main(int argc,char **argv) {
                        lseek(pfile_fd,8,SEEK_CUR);
                        read(pfile_fd,&info_int,4);
                        printf("fmtsize: %d\n",info_int);
+                       if(info_int==16) set.format=AFMT_S16_LE;
+                       if(info_int==8) set.format=AFMT_U8;
                        read(pfile_fd,&info_int,4);
-                       printf("format tag: %d\n",(info_int>>16)&1<<16);
-                       printf("channels: %d\n",info_int&1<<16);
+                       printf("format tag: %d\n",info_int&0xffff);
+                       printf("channels: %d\n",(info_int>>16)&0xffff);
+                       set.channel=(info_int>>16)&0xffff;
                        read(pfile_fd,&info_int,4);
                        printf("samples/sec: %d\n",info_int);
+                       set.freq=info_int;
                        read(pfile_fd,&info_int,4);
                        printf("bytes/sec: %d\n",info_int);
                        read(pfile_fd,&info_int,4);
-                       printf("block allign: %d\n",(info_int>>16)&1<<16);
-                       printf("bits/sample: %d\n",info_int&1<<16);
+                       printf("block allign: %d\n",info_int&0xffff);
+                       printf("bits/sample: %d\n",(info_int>>16)&0xffff);
                        lseek(pfile_fd,4,SEEK_CUR);
                        read(pfile_fd,&info_int,4);
                        printf("datasize: %d\n\n",info_int);
@@ -170,16 +212,88 @@ int main(int argc,char **argv) {
                return -1;
        }
 
-       if(mode&PLAY) {
+       if((mode&RECORD) && (mode&PLAY)) {
+               if((buf2=malloc(set.bufsize*sizeof(unsigned char)))==NULL) {
+                       printf("allocating 2nd memory failed :(\n");
+                       perror("malloc");
+                       return -1;
+               }
+       }
+
+       if((mode&PLAY) && (!(mode&RECORD))) {
+
+       /* dfb */
+       DirectFBInit(&argc,&argv);
+       DirectFBCreate(&dfb);
+       dfb->SetCooperativeLevel(dfb,DFSCL_FULLSCREEN);
+       dsc.flags=DSDESC_CAPS;
+       dsc.caps=DSCAPS_PRIMARY|DSCAPS_FLIPPING;
+       dfb->CreateSurface(dfb,&dsc,&primary);
+       primary->GetSize(primary,&width,&height);
+       dprintf(1,"graphical equalizer dims: %dx%d\n",width,height);
+       primary->SetColor(primary,0x80,0x80,0xff,0xff);
+       //primary->Flip(primary,NULL,DSFLIP_WAITFORSYNC);
+
+       /* fourier */
+       fourier_init(&fourier,1);
+       fourier.type=FWD|DFT;
+       fourier.dim=1;
+       fourier.data_len[0]=set.bufsize/(set.format&AFMT_S16_LE?4:2);
+       fourier_alloc_data(&fourier);
+       printf("debug: allocated size for %d samples to do dft\n",fourier.data_len[0]);
+       dx=8*width/fourier.data_len[0];
+       printf("debug: dx = %d ???\n",dx);
+
                printf("playing file %s ...\n",play_file);
+               if(mode&REVERSED) printf("but we do it reversed!\n");
                rw=1;
-               while(rw) {
-                       rw=read(pfile_fd,buf,set.bufsize);
-                       write(audio_fd,buf,set.bufsize);
+               if(!(mode&REVERSED)) {
+                       while(rw) {
+                               /* read samples */
+                               rw=read(pfile_fd,buf,set.bufsize);
+                               /* do fourier trafo */
+                               for(sample=0;sample<fourier.data_len[0];sample++) fourier.data[sample].r=*((signed short *)buf+(set.format&AFMT_S16_LE?2:1)*sample);
+                               fourier_dft_1d(&fourier);
+                               /* print graph */
+                               primary->Clear(primary,0,0,0,0xff);
+                               a_f=dx*fourier.data_len[0]*440/set.freq;
+                               primary->DrawLine(primary,a_f,height,a_f,0);
+                               for(sample=0;sample<fourier.data_len[0]/8;sample++) primary->FillRectangle(primary,sample*dx,0,dx,height*sqrt(fourier.ftdata[sample].r*fourier.ftdata[sample].r+fourier.ftdata[sample].i*fourier.ftdata[sample].i)/0x7fff);
+                               primary->Flip(primary,NULL,DSFLIP_WAITFORSYNC);
+                               //fcount=0;
+
+                               //}
+
+                               write(audio_fd,buf,set.bufsize);
+                       }
+               } else {
+                       i=0;
+                       read(pfile_fd,info,4);
+                       if(!strncmp(info,"RIFF",4)) {
+                               is_wav=1;
+                               printf("\nassuming wav file according to header ...\n");
+                               i=44;
+                       }
+                       lseek(pfile_fd,0,SEEK_SET);
+                       tmp=lseek(pfile_fd,0,SEEK_END);
+                       // if(set.format==AFMT_U8) i=set.channel;
+                       // if(set.format==AFMT_S16_LE) i=set.channel*2;
+                       for(j=0;j<(tmp-i);j++) {
+                               for(k=0;k<set.bufsize;k++) {
+                                       lseek(pfile_fd,tmp-(j+1)*set.bufsize+k,SEEK_SET);
+                                       read(pfile_fd,buf+k,1);
+                               }
+                               write(audio_fd,buf,set.bufsize);
+                       }
                }
+
+               /* dfb release */
+               primary->Release(primary);
+               dfb->Release(dfb);
+
        }
 
-       if(mode&RECORD) {
+       if((mode&RECORD) && (!(mode&PLAY))) {
                printf("recording to file %s ...\n",record_file);
                rw=1;
                while(rw) {
@@ -188,5 +302,81 @@ int main(int argc,char **argv) {
                }
        }
 
+       if((mode&RECORD) && (mode&PLAY)) {
+               FD_ZERO(&read_fds);
+               FD_ZERO(&write_fds);
+               /* read_fds */
+               FD_SET(0,&read_fds);
+               FD_SET(pfile_fd,&read_fds);
+               FD_SET(audio_fd,&read_fds);
+               /* write_fds */
+               FD_SET(sfile_fd,&write_fds);
+               FD_SET(audio_fd,&write_fds);
+               while(c!='q') {
+                       fds_tv.tv_sec=0;
+                       fds_tv.tv_usec=1000;
+                       k=select(sfile_fd+1,&read_fds,&write_fds,NULL,&fds_tv);
+                       if(k==0) printf("itz zZzero :p\n");
+                       if(k) {
+                               printf("returned after %ld usecs\n",1000-fds_tv.tv_usec);
+                               if(FD_ISSET(0,&read_fds)) {
+                                       read(0,&c,1);
+                               }
+                               if(FD_ISSET(pfile_fd,&read_fds)) {
+                                       read(pfile_fd,buf2,set.bufsize);
+                               }
+                               if(FD_ISSET(audio_fd,&read_fds)) {
+                                       read(audio_fd,buf,set.bufsize);
+                               }
+                               if(FD_ISSET(sfile_fd,&write_fds)) {
+                                       write(sfile_fd,buf,set.bufsize);
+                               }
+                               if(FD_ISSET(audio_fd,&write_fds)) {
+                                       write(audio_fd,buf2,set.bufsize);
+                               }
+                       }
+               }
+       }
+
+       if(mode&CONVERT) {
+               if((tmp=lseek(pfile_fd,0,SEEK_END))==-1) {
+                       printf("cannot determine filesize :(\n");
+                       perror("lseek");
+                       return -1;
+               }
+               lseek(pfile_fd,0,SEEK_SET);
+               strcpy(info,"RIFF");
+               write(sfile_fd,info,4);
+               info_int=tmp+36;
+               write(sfile_fd,&info_int,4);
+               strcpy(info,"WAVEfmt ");
+               write(sfile_fd,info,8);
+               if(set.format==AFMT_S16_LE) info_int=16;
+               if(set.format==AFMT_U8) info_int=8;
+               write(sfile_fd,&info_int,4);
+               info_int=set.channel<<16;
+               info_int|=1;
+               write(sfile_fd,&info_int,4);
+               info_int=set.freq;
+               write(sfile_fd,&info_int,4);
+               info_int=set.freq*set.channel;
+               if(set.format==AFMT_S16_LE) info_int*=2;
+               write(sfile_fd,&info_int,4);
+               info_int=(set.channel*8)<<16;
+               info_int|=set.channel;
+               write(sfile_fd,&info_int,4);
+               strcpy(info,"data");
+               write(sfile_fd,info,4);
+               info_int=tmp;
+               write(sfile_fd,&info_int,4);
+               /* write data now ... */
+               for(j=0;j<tmp/set.bufsize;j++) {
+                       i=read(pfile_fd,buf,set.bufsize);
+                       k=write(sfile_fd,buf,set.bufsize);
+                       printf("read %d, wrote %d\n",i,k);
+               }
+               printf("\ndone ...\n");
+       }
+                       
        return 1;
 }