fd85529078f93ca4d1bdcc2c7040fec1ba5465e2
[lcr.git] / tones.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** PBX4Linux                                                                 **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** opening and reading tone                                                  **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14 /* 
15 notes about codecs:
16
17 CODEC_OFF is a none accepted value
18 CODEC_LAW is 8 bit (1 byte) data 8khz
19 other codecs are 16 bit (2 bytes) data 8khz
20 the read_tone() will return law or 16bit mono. the read_tone will convert all other formats to 16bit mono.
21
22 */ 
23
24
25 /*
26  * open the tone (don't increase fhuse, since it is done after calling this function)
27  * NOTE: length and left will be set to the number of samples, NOT bytes
28  */
29 struct fmt {
30         unsigned short  stereo; /* 1 = pcm, 2 = adpcm */
31         unsigned short  channels; /* number of channels */
32         unsigned int   sample_rate; /* sample rate */
33         unsigned int   data_rate; /* data rate */
34         unsigned short  bytes_sample; /* bytes per sample (all channels) */
35         unsigned short  bits_sample; /* bits per sample (one channel) */
36 };
37 int open_tone(char *file, int *codec, signed int *length, signed int *left)
38 {
39         int fh;
40         char filename[256];        
41         char linkname[256];        
42         unsigned char buffer[256];
43         struct fmt *fmt;
44         int channels, bytes;
45         unsigned int size, chunk;
46         int gotfmt = 0;
47         struct stat _stat;
48         int linksize;
49         int l;
50         char *p;
51
52
53         /* try to open the law file */
54         SPRINT(filename, "%s.isdn", file);
55         if ((fh = open(filename, O_RDONLY)) >= 0)
56         {
57                 /* stat tone */
58                 l = 0;
59                 while(42)
60                 {
61                         if (l >= 10)
62                         {
63                                 close(fh);
64                                 PERROR("Link chain too deep: '%s'\n", filename);
65                                 return(-1);
66                         }
67                         if (lstat(filename, &_stat) == -1)
68                         {
69                                 close(fh);
70                                 PERROR("Cannot stat file: '%s'\n", filename);
71                                 return(-1);
72                         }
73                         if (!S_ISLNK(_stat.st_mode))
74                         {
75                                 break;
76                         }
77                         if ((linksize=readlink(filename, linkname, sizeof(linkname))) > 0)
78                         {
79                                 linkname[linksize] = '\0';
80                         } else
81                         {
82                                 close(fh);
83                                 PERROR("Cannot read link information: '%s'\n", filename);
84                                 return(-1);
85                         }
86                         if (linkname[0] == '/') /* absolute link */
87                         {
88                                 SCPY(filename, linkname);
89                         } else /* relative link */
90                         {
91                                 /* remove filename */
92                                 p = filename;
93                                 while(strchr(p, '/'))
94                                 {
95                                         p = strchr(p, '/')+1;
96                                 }
97                                 *p = 0;
98                                 /* concat the link */
99                                 SCAT(filename, linkname);
100                         }
101 //printf("follow link: %s\n", filename);
102                         l++;
103                 }
104                 if (length)
105                         *length = _stat.st_size;
106                 if (left)
107                         *left = _stat.st_size;
108                 if (codec)
109                         *codec = CODEC_LAW;
110                 return(fh);
111         }
112
113         /* try to open the wave file */
114         SPRINT(filename, "%s.wav", file);
115         if ((fh = open(filename, O_RDONLY)) >= 0)
116         {
117                 /* get wave header */
118                 read(fh, buffer, 8);
119                 size=(buffer[4]) + (buffer[5]<<8) + (buffer[6]<<16) + (buffer[7]<<24);
120                 if (!!strncmp((char *)buffer, "RIFF", 4))
121                 {
122                         close(fh);
123                         errno = 0;
124                         PERROR("%s is no riff file!\n", filename);
125                         return(-1);
126                 }
127 //              printf("%c%c%c%c size=%ld\n",buffer[0],buffer[1],buffer[2],buffer[3],size);
128                 read(fh, buffer, 4);
129                 size -= 4;
130                 if (!!strncmp((char *)buffer, "WAVE", 4))
131                 {
132                         close(fh);
133                         errno = 0;
134                         PERROR("%s is no wave file!\n", filename);
135                         return(-1);
136                 }
137                 while(size)
138                 {
139                         if (size>0 && size<8)
140                         {
141                                 close(fh);
142                                 errno = 0;
143                                 PERROR("Remaining file size %ld not large enough for next chunk.\n",size);
144                                 return(-1);
145                         }
146                         read(fh, buffer, 8);
147                         chunk=(buffer[4]) + (buffer[5]<<8) + (buffer[6]<<16) + (buffer[7]<<24);
148                         size -= (8+chunk);
149 //                      printf("%c%c%c%c length=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],chunk);
150                         if (size < 0)
151                         {
152                                 close(fh);
153                                 errno = 0;
154                                 PERROR("Chunk '%c%c%c%c' is larger than remainig file size (length=%ld)\n",buffer[0],buffer[1],buffer[2],buffer[3], chunk);
155                                 return(-1);
156                         }
157                         if (!strncmp((char *)buffer, "fmt ", 4))
158                         {
159                                 if (chunk < 16)
160                                 {
161                                         close(fh);
162                                         errno = 0;
163                                         PERROR("File %s Fmt chunk illegal size.\n", filename);
164                                         return(-1);
165                                 }
166                                 read(fh, buffer, chunk);
167                                 fmt = (struct fmt *)buffer;
168                                 if (fmt->channels<1 || fmt->channels>2)
169                                 {
170                                         close(fh);
171                                         errno = 0;
172                                         PERROR("File %s Only support one or two channels file.\n", filename);
173                                         return(-1);
174                                 }
175                                 channels = fmt->channels;
176 //                              printf("Channels: %d\n", channels);
177                                 if (fmt->sample_rate != 8000)
178                                 {
179                                         PERROR("Warning: File %s has sample rate of %ld.\n", filename, fmt->sample_rate);
180                                 }
181 //                              printf("Sample Rate: %ld\n", fmt->sample_rate);
182                                 if (fmt->bits_sample!=8 && fmt->bits_sample!=16)
183                                 {
184                                         close(fh);
185                                         errno = 0;
186                                         PERROR("File %s has neigher 8 nor 16 bit samples.\n", filename);
187                                         return(-1);
188                                 }
189                                 bytes = (fmt->bits_sample==16)?2:1;
190 //                              printf("Bit-Resolution: %d\n", bytes*16-16);
191                                 gotfmt = 1;
192                         } else
193                         if (!strncmp((char *)buffer, "data", 4))
194                         {
195                                 if (!gotfmt)
196                                 {
197                                         close(fh);
198                                         errno = 0;
199                                         PERROR("File %s No fmt chunk found before data chunk.\n", filename);
200                                         return(-1);
201                                 }
202 //                              printf("Length: %ld samples (%ld.%03ld seconds)\n", chunk/bytes/channels, chunk/bytes/channels/8000, ((chunk/bytes/channels)%8000)*1000/8000);
203                                 if (bytes==2 && channels==1)
204                                 {
205                                         if (codec)
206                                                 *codec = CODEC_MONO;
207                                         if (length)
208                                                 *length = ((signed int)chunk)>>1;
209                                         if (left)
210                                                 *left = ((signed int)chunk)>>1;
211 //                                      printf("left=%d\n",*left);
212                                 } else
213                                 if (bytes==2 && channels==2)
214                                 {
215                                         if (codec)
216                                                 *codec = CODEC_STEREO;
217                                         if (length)
218                                                 *length = ((signed int)chunk)>>2;
219                                         if (left)
220                                                 *left = ((signed int)chunk)>>2;
221                                 } else
222                                 if (bytes==1 && channels==1)
223                                 {
224                                         if (codec)
225                                                 *codec = CODEC_8BIT;
226                                         if (length)
227                                                 *length = (signed int)chunk;
228                                         if (left)
229                                                 *left = (signed int)chunk;
230                                 } else
231                                 {
232                                         close(fh);
233                                         errno = 0;
234                                         PERROR("File %s Is not MONO8, MONO16 nor STEREO16.\n", filename);
235                                         return(-1);
236                                 }
237                                 return(fh);
238                         } else
239                         {
240 //                              PDEBUG(DEBUG_PORT, "Unknown chunk '%c%c%c%c'\n",buffer[0],buffer[1],buffer[2],buffer[3]);
241                                 while(chunk > sizeof(buffer))
242                                 {
243                                         read(fh, buffer, sizeof(buffer));
244                                         chunk -=  sizeof(buffer);
245                                 }
246                                 if (chunk)
247                                         read(fh, buffer, chunk);
248                         }
249                         
250                 }
251                 if (!gotfmt)
252                 {
253                         close(fh);
254                         errno = 0;
255                         PERROR("File %s No fmt chunk found in file.\n", filename);
256                         return(-1);
257                 }
258                 close(fh);
259                 errno = 0;
260                 PERROR("File %s No data chunk found in file.\n", filename);
261                 return(-1);
262         }
263
264         return(-1);
265 }
266
267
268 /*
269  * read from tone, check size
270  * the len must be the number of samples, NOT for the bytes to read!!
271  * the data returned is law-code
272  */
273 int read_tone(int fh, unsigned char *buffer, int codec, int len, signed int size, signed int *left, int speed)
274 {
275         int l;
276         int offset;
277         signed short buffer16[len], *buf16 = buffer16;
278         signed short buffer32[len<<1], *buf32 = buffer32;
279         unsigned char buffer8[len], *buf8 = buffer8;
280         signed int sample;
281         int i = 0;
282 //printf("left=%ld\n",*left);
283
284         /* if no *left is given (law has unknown length) */
285         if (!left)
286                 goto unknown_length;
287
288         if (speed!=1)
289         {
290                 offset = ((len&(~4)) * (speed-1));
291                 lseek(fh, offset, SEEK_CUR); /* step fowards, backwards (len must be round to 4 bytes, to be sure, that 16bit stereo will not drift out of sync)*/
292                 *left -= offset; /* correct the current bytes left */
293                 if (*left < 0)
294                 {
295                         /* eof */
296                         *left = 0;
297                         return(0);
298                 }
299                 if (*left >= size)
300                 {
301                         /* eof */
302                         *left = size;
303                         return(0);
304                 }
305         }
306
307         if (*left == 0)
308                 return(0);
309
310         if (*left < len)
311                 len = *left;
312         unknown_length:
313         switch(codec)
314         {
315                 case CODEC_LAW:
316                 l = read(fh, buffer, len); /* as is */
317                 break;
318
319                 case CODEC_MONO:
320                         l = read(fh, buf16, len<<1);
321                         if (l>0)
322                         {
323                                 l = l>>1;
324                                 while(i < l)
325                                 {
326                                         sample = *buf16++;
327                                         if (sample < -32767)
328                                                 sample = -32767;
329                                         if (sample > 32767)
330                                                 sample = 32767;
331                                         *buffer++ = audio_s16_to_law[sample & 0xffff];
332                                         i++;
333                                 }
334                         }
335                 break;
336
337                 case CODEC_STEREO:
338                 {
339                         l = read(fh, buf32, len<<2);
340                         if (l>0)
341                         {
342                                 l = l>>2;
343                                 while(i < l)
344                                 {
345                                         sample = (*buf32++) + (*buf32++);
346                                         if (sample < -32767)
347                                                 sample = -32767;
348                                         if (sample > 32767)
349                                                 sample = 32767;
350                                         *buffer++ = audio_s16_to_law[sample & 0xffff];
351                                         i++;
352                                 }
353                         }
354                 }
355                 break;
356
357                 case CODEC_8BIT:
358                 {
359                         l = read(fh, buf8, len);
360                         if (l>0)
361                         {
362                                 while(i < l)
363                                 {
364                                         *buffer++ = audio_s16_to_law[(((*buf8++)<<8)-0x8000) & 0xffff];
365                                         i++;
366                                 }
367                         }
368                 }
369                 break;
370
371                 default:
372                 FATAL("codec %d is not supported.\n", codec);
373         }
374
375         if (l>0 && left)
376                 *left -= l;
377         return(l);
378 }
379
380
381 struct toneset *toneset_first = NULL;
382
383 /*
384  * free fetched tones
385  */
386 void free_tones(void)
387 {
388         struct toneset *toneset_temp;
389         struct tonesettone *tonesettone_temp;
390         void *temp;
391
392         toneset_temp = toneset_first;
393         while(toneset_temp)
394         {
395                 tonesettone_temp = toneset_temp->first;
396                 while(tonesettone_temp)
397                 {
398                         temp = tonesettone_temp;
399                         tonesettone_temp = tonesettone_temp->next;
400                         FREE(temp, sizeof(struct tonesettone));
401                         memuse--;
402                 }
403                 temp = toneset_temp;
404                 toneset_temp = toneset_temp->next;
405                 FREE(temp, sizeof(struct toneset));
406                 memuse--;
407         }
408         toneset_first = NULL;
409 }
410
411 /*
412  * fetch tones as specified in options.conf
413  */
414 int fetch_tones(void)
415 {
416         DIR *dir;
417         struct dirent *dirent;
418         struct toneset **toneset_nextpointer;
419         struct tonesettone **tonesettone_nextpointer;
420         char *p, *p_next;
421         char path[256];
422         char filename[256], name[256];
423         int fh;
424         int tone_codec;
425         signed int tone_size, tone_left;
426         unsigned int memory = 0;
427         int samples = 0;
428
429         /* if disabled */
430         if (!options.fetch_tones)
431                 return(1);
432
433         toneset_nextpointer = &toneset_first;
434         p = options.fetch_tones;
435         if (*p == '\0')
436                 return(1);
437
438         while (*p)
439         {
440                 p_next = p;
441                 while(*p_next)
442                 {
443                         if (*p_next == ',')
444                         {
445                                 *p_next = '\0';
446                                 p_next++;
447                                 break;
448                         }
449                         p_next++;
450                 }
451
452                 /* remove trailing / */
453                 if (*p) if (p[strlen(p)-1] == '/')
454                         p[strlen(p)-1] = '\0';
455
456                 printf("PBX: Fetching tones '%s'\n", p);
457                 PDEBUG(DEBUG_PORT, "fetching tones directory '%s'\n", p);
458
459                 *toneset_nextpointer = (struct toneset *)MALLOC(sizeof(struct toneset));
460                 memuse++;
461                 memory += sizeof(struct toneset);
462                 SCPY((*toneset_nextpointer)->directory, p);
463                 tonesettone_nextpointer = &(*toneset_nextpointer)->first;
464
465                 SPRINT(path, "%s/%s", INSTALL_DATA, p);
466                 dir = opendir(path);
467                 if (dir == NULL)
468                 {
469                         PERROR("Tone set not found: '%s'\n", path);
470                         return(0);
471                 }
472
473                 while((dirent=readdir(dir)))
474                 {
475                         SPRINT(name, "%s", dirent->d_name);
476
477                         /* remove .isdn and .wave */
478                         if (strlen(name) >= 4)
479                         {
480                                 if (!strcmp(name+strlen(name)-4, ".wav"))
481                                         name[strlen(name)-4] = '\0';
482                         }
483                         if (strlen(name) >= 5)
484                         {
485                                 if (!strcmp(name+strlen(name)-5, ".isdn"))
486                                         name[strlen(name)-5] = '\0';
487                         }
488
489                         SPRINT(filename, "%s/%s", path, name);
490
491                         /* skip . / .. */
492                         if (!strcmp(dirent->d_name, "."))
493                                 continue;
494                         if (!strcmp(dirent->d_name, ".."))
495                                 continue;
496
497                         /* open file */
498                         fh = open_tone(filename, &tone_codec, &tone_size, &tone_left);
499                         if (fh < 0)
500                         {
501                                 PERROR("Cannot open file: '%s'\n", filename);
502                                 continue;
503                         }
504                         fduse++;
505
506                         if (tone_size < 0)
507                         {
508                                 PERROR("File has 0-length: '%s'\n", filename);
509                                 close(fh);
510                                 fduse--;
511                                 continue;
512                         }
513
514                         /* Allocate tone */
515                         *tonesettone_nextpointer = (struct tonesettone *)MALLOC(sizeof(struct tonesettone)+tone_size);
516                         memuse++;
517 //printf("tone:%s, %ld bytes\n", name, tone_size);
518                         memory += sizeof(struct tonesettone)+tone_size;
519                         samples ++;
520
521                         /* load tone */
522                         read_tone(fh, (*tonesettone_nextpointer)->data, tone_codec, tone_size, tone_size, &tone_left, 1);
523                         (*tonesettone_nextpointer)->size = tone_size;
524                         (*tonesettone_nextpointer)->codec = (tone_codec==CODEC_LAW)?CODEC_LAW:CODEC_MONO;
525                         SCPY((*tonesettone_nextpointer)->name, name);
526
527                         close(fh);
528                         fduse--;
529                                  
530                         tonesettone_nextpointer = &((*tonesettone_nextpointer)->next);
531                 }
532
533                 toneset_nextpointer = &((*toneset_nextpointer)->next);
534                 p = p_next;
535         }
536
537         printf("PBX: Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
538         PDEBUG(DEBUG_PORT, "Memory used for tones: %ld bytes (%d samples)\n", memory, samples);
539
540         return(1);
541
542
543
544 /*
545  * opens the fetched tone (if available)
546  */
547 void *open_tone_fetched(char *dir, char *file, int *codec, signed int *length, signed int *left)
548 {
549         struct toneset *toneset;
550         struct tonesettone *tonesettone;
551
552         /* if anything fetched */
553         if (!toneset_first)
554                 return(NULL);
555
556         /* find set */
557         toneset = toneset_first;
558         while(toneset)
559         {
560 //printf("1. comparing '%s' with '%s'\n", toneset->directory, dir);
561                 if (!strcmp(toneset->directory, dir))
562                         break;
563                 toneset = toneset->next;
564         }
565         if (!toneset)
566                 return(NULL);
567
568         /* find tone */
569         tonesettone = toneset->first;
570         while(tonesettone)
571         {
572 //printf("2. comparing '%s' with '%s'\n", tonesettone->name, file);
573                 if (!strcmp(tonesettone->name, file))
574                         break;
575                 tonesettone = tonesettone->next;
576         }
577         if (!tonesettone)
578                 return(NULL);
579
580         /* return information */
581         if (length)
582                 *length = tonesettone->size;
583         if (left)
584                 *left = tonesettone->size;
585         if (codec)
586                 *codec = tonesettone->codec;
587 //printf("size=%ld, data=%08x\n", tonesettone->size, tonesettone->data);
588         return(tonesettone->data);
589 }
590
591
592 /*
593  * read from fetched tone, check size
594  * the len must be the number of samples, NOT for the bytes to read!!
595  */
596 int read_tone_fetched(void **fetched, void *buffer, int len, signed int size, signed int *left, int speed)
597 {
598         int l;
599 //printf("left=%ld\n",*left);
600
601         /* if no *left is given (law has unknown length) */
602         if (!left)
603                 return(0);
604
605         if (*left == 0)
606                 return(0);
607
608         if (*left < len)
609                 len = *left;
610
611         memcpy(buffer, *fetched, len);
612         *((char **)fetched) += len;
613         l = len;
614
615         if (l>0 && left)
616                 *left -= l;
617         return(l);
618 }
619