lol, some bullshit
[sound-tools/hdrec.git] / hdrec.c
1 /*
2  * hdrec -- some sort of multi tracker (not right now, but in the future :p)
3  *
4  * author: hackbard@hackdaworld.dyndns.org
5  *
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <sys/select.h>
15 #include <sys/time.h>
16 #include <sys/soundcard.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <errno.h>
20
21 #include "oss_api.h"
22 #include "hdrec.h"
23
24 int usage(void) {
25         printf("usage:\n\n");
26         printf("-h \t\t print this help\n");
27         printf("-i \t\t use/print file info\n");
28         printf("-R \t\t play reversed :)\n");
29         printf("-d <device> \t sound device (eg: /dev/dsp)\n");
30         printf("-r <file> \t record to <file>\n");
31         printf("-p <file> \t play from <file>\n");
32         printf("-s \t\t stereo\n");
33         printf("-m \t\t mono\n");
34         printf("-f <format> \t 1=8bit - 2=16bit (le)\n");
35         printf("-F <hz> \t frequency\n");
36         printf("-c <src> <dst> \t converts raw to wav (specify f/m,s/F)\n");
37         
38         return 1;
39 }
40
41 int main(int argc,char **argv) {
42         int sfile_fd;
43         int pfile_fd;
44         int audio_fd;
45         char device[MAX_C_DEVICE];
46         int i,j,k;
47         int rw;
48         unsigned char mode=0;
49         int o_mode=0;
50         char record_file[MAX_C_FILE];
51         char play_file[MAX_C_FILE];
52         dsp_set set;
53         unsigned char *buf;
54         unsigned char *buf2=NULL;
55         unsigned char print_info=0;
56         unsigned char info[8];
57         int info_int;
58         int tmp;
59         char is_wav=0;
60         fd_set read_fds,write_fds;
61         struct timeval fds_tv;
62         char c;
63
64         /* defaults */
65         strcpy(device,"");
66         set.format=AFMT_S16_LE;
67         set.freq=44100;
68         set.channel=STEREO;
69
70         /* read argv */
71         for(i=1;i<argc;i++) {
72                 if(argv[i][0]=='-') {
73                         switch(argv[i][1]) {
74                                 case 'h':
75                                         usage();
76                                         return 1;
77                                 case 'i':
78                                         print_info=1;
79                                         break;
80                                 case 'r':
81                                         mode|=RECORD;
82                                         strcpy(record_file,argv[++i]);
83                                         break;
84                                 case 'p':
85                                         mode|=PLAY;
86                                         strcpy(play_file,argv[++i]);
87                                         break;
88                                 case 'R':
89                                         mode|=REVERSED;
90                                         break;
91                                 case 's':
92                                         set.channel=STEREO;
93                                         break;
94                                 case 'm':
95                                         set.channel=MONO;
96                                         break;
97                                 case 'f':
98                                         i++;
99                                         if(atoi(argv[i])==1) set.format=AFMT_U8;
100                                         if(atoi(argv[i])==2) set.format=AFMT_S16_LE;
101                                         break;
102                                 case 'F':
103                                         set.freq=atoi(argv[++i]);
104                                         break;
105                                 case 'd':
106                                         strncpy(device,argv[++i],MAX_C_DEVICE-1);
107                                         break;
108                                 case 'c':
109                                         mode=CONVERT;
110                                         strcpy(play_file,argv[++i]);
111                                         strcpy(record_file,argv[++i]);
112                                         break;
113                                 default:
114                                         usage();
115                                         return -1;
116                         }
117                 } else usage();
118         }
119
120         if(!strcmp("",device)) {
121                 printf("you have to specify a device!\n");
122                 return -1;
123         }
124
125         /* open audio fd */
126         if(mode&RECORD) o_mode=O_RDONLY;
127         if(mode&PLAY) o_mode=O_WRONLY;
128         if(mode&RECORD && mode&PLAY) o_mode=O_RDWR;
129         if((audio_fd=open_sound_dev(device,o_mode))==-1) {
130                 printf("unable to open %s\n",device);
131                 return -1;
132         }
133
134         /* file fd's */
135         if((mode&PLAY) || (mode&CONVERT)) {
136                 if((pfile_fd=open_file(play_file,O_RDONLY))==-1) {
137                         printf("unable to open file %s for reading\n",play_file);
138                         return -1;
139                 }
140         }
141         if((mode&RECORD) || (mode&CONVERT)) {
142                 if((sfile_fd=open_file(record_file,O_CREAT|O_WRONLY))==-1) {
143                         printf("unable to open file %s for writing\n",record_file);
144                         return -1;
145                 }
146         }
147
148         if(print_info) {
149                 if(mode&PLAY) {
150                         printf("file info:\n");
151                         lseek(pfile_fd,4,SEEK_SET);
152                         read(pfile_fd,&info_int,4);
153                         printf("file size: %d\n",info_int);
154                         lseek(pfile_fd,8,SEEK_CUR);
155                         read(pfile_fd,&info_int,4);
156                         printf("fmtsize: %d\n",info_int);
157                         if(info_int==16) set.format=AFMT_S16_LE;
158                         if(info_int==8) set.format=AFMT_U8;
159                         read(pfile_fd,&info_int,4);
160                         printf("format tag: %d\n",info_int&0xffff);
161                         printf("channels: %d\n",(info_int>>16)&0xffff);
162                         set.channel=(info_int>>16)&0xffff;
163                         read(pfile_fd,&info_int,4);
164                         printf("samples/sec: %d\n",info_int);
165                         set.freq=info_int;
166                         read(pfile_fd,&info_int,4);
167                         printf("bytes/sec: %d\n",info_int);
168                         read(pfile_fd,&info_int,4);
169                         printf("block allign: %d\n",info_int&0xffff);
170                         printf("bits/sample: %d\n",(info_int>>16)&0xffff);
171                         lseek(pfile_fd,4,SEEK_CUR);
172                         read(pfile_fd,&info_int,4);
173                         printf("datasize: %d\n\n",info_int);
174                         /* return to start */
175                         lseek(pfile_fd,0,SEEK_SET);
176                 }
177         }
178
179         /* set dsp and get capabilities */
180         if(get_dsp_cap(audio_fd,&set,1)==-1) {
181                 printf("unable to get capabilities :(\n");
182                 return -1;
183         }
184         if(set_dsp(audio_fd,&set)==-1) {
185                 printf("unable to set dsp :(\n");
186                 return -1;
187         }
188
189         /* allocating buffer */
190         if((buf=malloc(set.bufsize*sizeof(unsigned char)))==NULL) {
191                 printf("allocating memory failed :(\n");
192                 perror("malloc");
193                 return -1;
194         }
195         if((mode&RECORD) && (mode&PLAY)) {
196                 if((buf2=malloc(set.bufsize*sizeof(unsigned char)))==NULL) {
197                         printf("allocating 2nd memory failed :(\n");
198                         perror("malloc");
199                         return -1;
200                 }
201         }
202
203         if((mode&PLAY) && (!(mode&RECORD))) {
204                 printf("playing file %s ...\n",play_file);
205                 if(mode&REVERSED) printf("but we do it reversed!\n");
206                 rw=1;
207                 if(!(mode&REVERSED)) {
208                         while(rw) {
209                                 rw=read(pfile_fd,buf,set.bufsize);
210                                 write(audio_fd,buf,set.bufsize);
211                         }
212                 } else {
213                         i=0;
214                         read(pfile_fd,info,4);
215                         if(!strncmp(info,"RIFF",4)) {
216                                 is_wav=1;
217                                 printf("\nassuming wav file according to header ...\n");
218                                 i=44;
219                         }
220                         lseek(pfile_fd,0,SEEK_SET);
221                         tmp=lseek(pfile_fd,0,SEEK_END);
222                         // if(set.format==AFMT_U8) i=set.channel;
223                         // if(set.format==AFMT_S16_LE) i=set.channel*2;
224                         for(j=0;j<(tmp-i);j++) {
225                                 for(k=0;k<set.bufsize;k++) {
226                                         lseek(pfile_fd,tmp-(j+1)*set.bufsize+k,SEEK_SET);
227                                         read(pfile_fd,buf+k,1);
228                                 }
229                                 write(audio_fd,buf,set.bufsize);
230                         }
231                 }
232         }
233
234         if((mode&RECORD) && (!(mode&PLAY))) {
235                 printf("recording to file %s ...\n",record_file);
236                 rw=1;
237                 while(rw) {
238                         rw=read(audio_fd,buf,set.bufsize);
239                         write(sfile_fd,buf,set.bufsize);
240                 }
241         }
242
243         if((mode&RECORD) && (mode&PLAY)) {
244                 FD_ZERO(&read_fds);
245                 FD_ZERO(&write_fds);
246                 /* read_fds */
247                 FD_SET(0,&read_fds);
248                 FD_SET(pfile_fd,&read_fds);
249                 FD_SET(audio_fd,&read_fds);
250                 /* write_fds */
251                 FD_SET(sfile_fd,&write_fds);
252                 FD_SET(audio_fd,&write_fds);
253                 while(c!='q') {
254                         fds_tv.tv_sec=0;
255                         fds_tv.tv_usec=1000;
256                         k=select(sfile_fd+1,&read_fds,&write_fds,NULL,&fds_tv);
257                         if(k==0) printf("itz zZzero :p\n");
258                         if(k) {
259                                 printf("returned after %ld usecs\n",1000-fds_tv.tv_usec);
260                                 if(FD_ISSET(0,&read_fds)) {
261                                         read(0,&c,1);
262                                 }
263                                 if(FD_ISSET(pfile_fd,&read_fds)) {
264                                         read(pfile_fd,buf2,set.bufsize);
265                                 }
266                                 if(FD_ISSET(audio_fd,&read_fds)) {
267                                         read(audio_fd,buf,set.bufsize);
268                                 }
269                                 if(FD_ISSET(sfile_fd,&write_fds)) {
270                                         write(sfile_fd,buf,set.bufsize);
271                                 }
272                                 if(FD_ISSET(audio_fd,&write_fds)) {
273                                         write(audio_fd,buf2,set.bufsize);
274                                 }
275                         }
276                 }
277         }
278
279         if(mode&CONVERT) {
280                 if((tmp=lseek(pfile_fd,0,SEEK_END))==-1) {
281                         printf("cannot determine filesize :(\n");
282                         perror("lseek");
283                         return -1;
284                 }
285                 lseek(pfile_fd,0,SEEK_SET);
286                 strcpy(info,"RIFF");
287                 write(sfile_fd,info,4);
288                 info_int=tmp+36;
289                 write(sfile_fd,&info_int,4);
290                 strcpy(info,"WAVEfmt ");
291                 write(sfile_fd,info,8);
292                 if(set.format==AFMT_S16_LE) info_int=16;
293                 if(set.format==AFMT_U8) info_int=8;
294                 write(sfile_fd,&info_int,4);
295                 info_int=set.channel<<16;
296                 info_int|=1;
297                 write(sfile_fd,&info_int,4);
298                 info_int=set.freq;
299                 write(sfile_fd,&info_int,4);
300                 info_int=set.freq*set.channel;
301                 if(set.format==AFMT_S16_LE) info_int*=2;
302                 write(sfile_fd,&info_int,4);
303                 info_int=(set.channel*8)<<16;
304                 info_int|=set.channel;
305                 write(sfile_fd,&info_int,4);
306                 strcpy(info,"data");
307                 write(sfile_fd,info,4);
308                 info_int=tmp;
309                 write(sfile_fd,&info_int,4);
310                 /* write data now ... */
311                 for(j=0;j<tmp/set.bufsize;j++) {
312                         i=read(pfile_fd,buf,set.bufsize);
313                         k=write(sfile_fd,buf,set.bufsize);
314                         printf("read %d, wrote %d\n",i,k);
315                 }
316                 printf("\ndone ...\n");
317         }
318                         
319         return 1;
320 }