*
*/
+#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;
}
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,"");
case 'h':
usage();
return 1;
+ case 'i':
+ 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;
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;
}
/* 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;
}
}
+ if(print_info) {
+ if(mode&PLAY) {
+ printf("file info:\n");
+ lseek(pfile_fd,4,SEEK_SET);
+ read(pfile_fd,&info_int,4);
+ printf("file size: %d\n",info_int);
+ 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&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&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);
+ /* return to start */
+ lseek(pfile_fd,0,SEEK_SET);
+ }
+ }
+
/* set dsp and get capabilities */
if(get_dsp_cap(audio_fd,&set,1)==-1) {
printf("unable to get capabilities :(\n");
perror("malloc");
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) {
}
}
+ 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;
}