1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4     Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20     output.c
21 
22     Audio output (to file / device) functions.
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif /* HAVE_CONFIG_H */
28 #ifdef STDC_HEADERS
29 #include <string.h>
30 #include <ctype.h>
31 #elif HAVE_STRINGS_H
32 #include <strings.h>
33 #endif
34 #include "timidity.h"
35 #include "common.h"
36 #include "output.h"
37 #include "tables.h"
38 #include "controls.h"
39 #include "audio_cnv.h"
40 
41 int audio_buffer_bits = DEFAULT_AUDIO_BUFFER_BITS;
42 
43 /* These are very likely mutually exclusive.. */
44 #if defined(AU_AUDRIV)
45 extern PlayMode audriv_play_mode;
46 #define DEV_PLAY_MODE &audriv_play_mode
47 
48 #elif defined(AU_SUN)
49 extern PlayMode sun_play_mode;
50 #define DEV_PLAY_MODE &sun_play_mode
51 
52 #elif defined(AU_OSS)
53 extern PlayMode oss_play_mode;
54 #define DEV_PLAY_MODE &oss_play_mode
55 
56 #elif defined(AU_HPUX_AUDIO)
57 extern PlayMode hpux_play_mode;
58 #define DEV_PLAY_MODE &hpux_play_mode
59 
60 #elif defined(AU_W32)
61 extern PlayMode w32_play_mode;
62 #define DEV_PLAY_MODE &w32_play_mode
63 
64 #elif defined(AU_BSDI)
65 extern PlayMode bsdi_play_mode;
66 #define DEV_PLAY_MODE &bsdi_play_mode
67 
68 #elif defined(__MACOS__)
69 extern PlayMode mac_play_mode;
70 #define DEV_PLAY_MODE &mac_play_mode
71 
72 #elif defined(AU_DARWIN)
73 extern PlayMode darwin_play_mode;
74 #define DEV_PLAY_MODE &darwin_play_mode
75 #endif
76 
77 #ifdef AU_ALSA
78 extern PlayMode alsa_play_mode;
79 #endif /* AU_ALSA */
80 
81 #ifdef AU_HPUX_ALIB
82 extern PlayMode hpux_nplay_mode;
83 #endif /* AU_HPUX_ALIB */
84 
85 #ifdef AU_ARTS
86 extern PlayMode arts_play_mode;
87 #endif /* AU_ARTS */
88 
89 #ifdef AU_ESD
90 extern PlayMode esd_play_mode;
91 #endif /* AU_ESD */
92 
93 #ifdef AU_PORTAUDIO
94 #ifndef AU_PORTAUDIO_DLL
95 extern PlayMode portaudio_play_mode;
96 #else
97 extern PlayMode portaudio_asio_play_mode;
98 extern PlayMode portaudio_win_ds_play_mode;
99 extern PlayMode portaudio_win_wmme_play_mode;
100 #endif
101 #endif /* AU_PORTAUDIO */
102 
103 #ifdef AU_NPIPE
104 extern PlayMode npipe_play_mode;
105 #endif /* AU_NPIPE */
106 
107 #ifdef AU_JACK
108 extern PlayMode jack_play_mode;
109 #endif /* AU_NAS */
110 
111 #ifdef AU_NAS
112 extern PlayMode nas_play_mode;
113 #endif /* AU_NAS */
114 
115 #ifdef AU_AO
116 extern PlayMode ao_play_mode;
117 #endif /* AU_AO */
118 
119 #ifndef __MACOS__
120 /* These are always compiled in. */
121 extern PlayMode raw_play_mode, wave_play_mode, au_play_mode, aiff_play_mode;
122 extern PlayMode list_play_mode;
123 #ifdef AU_VORBIS
124 extern PlayMode vorbis_play_mode;
125 #endif /* AU_VORBIS */
126 #ifdef AU_FLAC
127 extern PlayMode flac_play_mode;
128 #endif /* AU_FLAC */
129 #ifdef AU_SPEEX
130 extern PlayMode speex_play_mode;
131 #endif /* AU_SPEEX */
132 #ifdef AU_GOGO
133 extern PlayMode gogo_play_mode;
134 #endif /* AU_GOGO */
135 #endif /* !__MACOS__ */
136 
137 extern PlayMode midi_play_mode;
138 extern PlayMode modmidi_play_mode;
139 
140 PlayMode *play_mode_list[] = {
141 #if defined(AU_AO) /* Try libao first as that will give us pulseaudio */
142   &ao_play_mode,
143 #endif /* AU_AO */
144 
145 #if defined(AU_ARTS)
146   &arts_play_mode,
147 #endif /* AU_ARTS */
148 
149 #if defined(AU_ESD)
150   &esd_play_mode,
151 #endif /* AU_ESD */
152 
153 #ifdef AU_ALSA /* Try alsa (aka DEV_PLAY_MODE 2 on Linux) first */
154   &alsa_play_mode,
155 #endif /* AU_ALSA */
156 
157 #ifdef DEV_PLAY_MODE /* OS dependent direct hardware access, OSS on Linux */
158   DEV_PLAY_MODE,
159 #endif
160 
161 #ifdef AU_HPUX_ALIB
162   &hpux_nplay_mode,
163 #endif /* AU_HPUX_ALIB */
164 
165 #if defined(AU_PORTAUDIO)
166 #ifndef AU_PORTAUDIO_DLL
167   &portaudio_play_mode,
168 #else
169   &portaudio_asio_play_mode,
170   &portaudio_win_ds_play_mode,
171   &portaudio_win_wmme_play_mode,
172 #endif
173 #endif /* AU_PORTAUDIO */
174 
175 #if defined(AU_NPIPE)
176   &npipe_play_mode,
177 #endif /*AU_NPIPE*/
178 
179 #if defined(AU_JACK)
180   &jack_play_mode,
181 #endif /* AU_PORTAUDIO */
182 
183 #if defined(AU_NAS)
184   &nas_play_mode,
185 #endif /* AU_NAS */
186 
187 #ifndef __MACOS__
188   &wave_play_mode,
189   &raw_play_mode,
190   &au_play_mode,
191   &aiff_play_mode,
192 #ifdef AU_VORBIS
193   &vorbis_play_mode,
194 #endif /* AU_VORBIS */
195 #ifdef AU_FLAC
196   &flac_play_mode,
197 #endif /* AU_FLAC */
198 #ifdef AU_SPEEX
199   &speex_play_mode,
200 #endif /* AU_SPEEX */
201 #ifdef AU_GOGO
202   &gogo_play_mode,
203 #endif /* AU_GOGO */
204   &list_play_mode,
205 #endif /* __MACOS__ */
206   &midi_play_mode,
207   &modmidi_play_mode,
208   NULL
209 };
210 
211 PlayMode *play_mode = NULL;
212 PlayMode *target_play_mode = NULL;
213 
214 /*****************************************************************/
215 /* Some functions to convert signed 32-bit data to other formats */
216 
s32tos8(int32 * lp,int32 c)217 void s32tos8(int32 *lp, int32 c)
218 {
219     int8 *cp=(int8 *)(lp);
220     int32 l, i;
221 
222     for(i = 0; i < c; i++)
223     {
224 	l=(lp[i])>>(32-8-GUARD_BITS);
225 	if (l>127) l=127;
226 	else if (l<-128) l=-128;
227 	cp[i] = (int8)(l);
228     }
229 }
230 
s32tou8(int32 * lp,int32 c)231 void s32tou8(int32 *lp, int32 c)
232 {
233     uint8 *cp=(uint8 *)(lp);
234     int32 l, i;
235 
236     for(i = 0; i < c; i++)
237     {
238 	l=(lp[i])>>(32-8-GUARD_BITS);
239 	if (l>127) l=127;
240 	else if (l<-128) l=-128;
241 	cp[i] = 0x80 ^ ((uint8) l);
242     }
243 }
244 
s32tos16(int32 * lp,int32 c)245 void s32tos16(int32 *lp, int32 c)
246 {
247   int16 *sp=(int16 *)(lp);
248   int32 l, i;
249 
250   for(i = 0; i < c; i++)
251     {
252       l=(lp[i])>>(32-16-GUARD_BITS);
253       if (l > 32767) l=32767;
254       else if (l<-32768) l=-32768;
255       sp[i] = (int16)(l);
256     }
257 }
258 
s32tou16(int32 * lp,int32 c)259 void s32tou16(int32 *lp, int32 c)
260 {
261   uint16 *sp=(uint16 *)(lp);
262   int32 l, i;
263 
264   for(i = 0; i < c; i++)
265     {
266       l=(lp[i])>>(32-16-GUARD_BITS);
267       if (l > 32767) l=32767;
268       else if (l<-32768) l=-32768;
269       sp[i] = 0x8000 ^ (uint16)(l);
270     }
271 }
272 
s32tos16x(int32 * lp,int32 c)273 void s32tos16x(int32 *lp, int32 c)
274 {
275   int16 *sp=(int16 *)(lp);
276   int32 l, i;
277 
278   for(i = 0; i < c; i++)
279     {
280       l=(lp[i])>>(32-16-GUARD_BITS);
281       if (l > 32767) l=32767;
282       else if (l<-32768) l=-32768;
283       sp[i] = XCHG_SHORT((int16)(l));
284     }
285 }
286 
s32tou16x(int32 * lp,int32 c)287 void s32tou16x(int32 *lp, int32 c)
288 {
289   uint16 *sp=(uint16 *)(lp);
290   int32 l, i;
291 
292   for(i = 0; i < c; i++)
293     {
294       l=(lp[i])>>(32-16-GUARD_BITS);
295       if (l > 32767) l=32767;
296       else if (l<-32768) l=-32768;
297       sp[i] = XCHG_SHORT(0x8000 ^ (uint16)(l));
298     }
299 }
300 
301 #define MAX_24BIT_SIGNED (8388607)
302 #define MIN_24BIT_SIGNED (-8388608)
303 
304 #define STORE_S24_LE(cp, l) *cp++ = l & 0xFF, *cp++ = l >> 8 & 0xFF, *cp++ = l >> 16
305 #define STORE_S24_BE(cp, l) *cp++ = l >> 16, *cp++ = l >> 8 & 0xFF, *cp++ = l & 0xFF
306 #define STORE_U24_LE(cp, l) *cp++ = l & 0xFF, *cp++ = l >> 8 & 0xFF, *cp++ = l >> 16 ^ 0x80
307 #define STORE_U24_BE(cp, l) *cp++ = l >> 16 ^ 0x80, *cp++ = l >> 8 & 0xFF, *cp++ = l & 0xFF
308 
309 #ifdef LITTLE_ENDIAN
310   #define STORE_S24  STORE_S24_LE
311   #define STORE_S24X STORE_S24_BE
312   #define STORE_U24  STORE_U24_LE
313   #define STORE_U24X STORE_U24_BE
314 #else
315   #define STORE_S24  STORE_S24_BE
316   #define STORE_S24X STORE_S24_LE
317   #define STORE_U24  STORE_U24_BE
318   #define STORE_U24X STORE_U24_LE
319 #endif
320 
s32tos24(int32 * lp,int32 c)321 void s32tos24(int32 *lp, int32 c)
322 {
323 	uint8 *cp = (uint8 *)(lp);
324 	int32 l, i;
325 
326 	for(i = 0; i < c; i++)
327 	{
328 		l = (lp[i]) >> (32 - 24 - GUARD_BITS);
329 		l = (l > MAX_24BIT_SIGNED) ? MAX_24BIT_SIGNED
330 				: (l < MIN_24BIT_SIGNED) ? MIN_24BIT_SIGNED : l;
331 		STORE_S24(cp, l);
332 	}
333 }
334 
s32tou24(int32 * lp,int32 c)335 void s32tou24(int32 *lp, int32 c)
336 {
337 	uint8 *cp = (uint8 *)(lp);
338 	int32 l, i;
339 
340 	for(i = 0; i < c; i++)
341 	{
342 		l = (lp[i]) >> (32 - 24 - GUARD_BITS);
343 		l = (l > MAX_24BIT_SIGNED) ? MAX_24BIT_SIGNED
344 				: (l < MIN_24BIT_SIGNED) ? MIN_24BIT_SIGNED : l;
345 		STORE_U24(cp, l);
346 	}
347 }
348 
s32tos24x(int32 * lp,int32 c)349 void s32tos24x(int32 *lp, int32 c)
350 {
351 	uint8 *cp = (uint8 *)(lp);
352 	int32 l, i;
353 
354 	for(i = 0; i < c; i++)
355 	{
356 		l = (lp[i]) >> (32 - 24 - GUARD_BITS);
357 		l = (l > MAX_24BIT_SIGNED) ? MAX_24BIT_SIGNED
358 				: (l < MIN_24BIT_SIGNED) ? MIN_24BIT_SIGNED : l;
359 		STORE_S24X(cp, l);
360 	}
361 }
362 
s32tou24x(int32 * lp,int32 c)363 void s32tou24x(int32 *lp, int32 c)
364 {
365 	uint8 *cp = (uint8 *)(lp);
366 	int32 l, i;
367 
368 	for(i = 0; i < c; i++)
369 	{
370 		l = (lp[i]) >> (32 - 24 - GUARD_BITS);
371 		l = (l > MAX_24BIT_SIGNED) ? MAX_24BIT_SIGNED
372 				: (l < MIN_24BIT_SIGNED) ? MIN_24BIT_SIGNED : l;
373 		STORE_U24X(cp, l);
374 	}
375 }
376 
s32toulaw(int32 * lp,int32 c)377 void s32toulaw(int32 *lp, int32 c)
378 {
379     int8 *up=(int8 *)(lp);
380     int32 l, i;
381 
382     for(i = 0; i < c; i++)
383     {
384 	l=(lp[i])>>(32-16-GUARD_BITS);
385 	if (l > 32767) l=32767;
386 	else if (l<-32768) l=-32768;
387 	up[i] = AUDIO_S2U(l);
388     }
389 }
390 
s32toalaw(int32 * lp,int32 c)391 void s32toalaw(int32 *lp, int32 c)
392 {
393     int8 *up=(int8 *)(lp);
394     int32 l, i;
395 
396     for(i = 0; i < c; i++)
397     {
398 	l=(lp[i])>>(32-16-GUARD_BITS);
399 	if (l > 32767) l=32767;
400 	else if (l<-32768) l=-32768;
401 	up[i] = AUDIO_S2A(l);
402     }
403 }
404 
405 /* return: number of bytes */
general_output_convert(int32 * buf,int32 count)406 int32 general_output_convert(int32 *buf, int32 count)
407 {
408     int32 bytes;
409 
410     if(!(play_mode->encoding & PE_MONO))
411 	count *= 2; /* Stereo samples */
412     bytes = count;
413     if(play_mode->encoding & PE_16BIT)
414     {
415 	bytes *= 2;
416 	if(play_mode->encoding & PE_BYTESWAP)
417 	{
418 	    if(play_mode->encoding & PE_SIGNED)
419 		s32tos16x(buf, count);
420 	    else
421 		s32tou16x(buf, count);
422 	}
423 	else if(play_mode->encoding & PE_SIGNED)
424 	    s32tos16(buf, count);
425 	else
426 	    s32tou16(buf, count);
427     }
428 	else if(play_mode->encoding & PE_24BIT) {
429 		bytes *= 3;
430 		if(play_mode->encoding & PE_BYTESWAP)
431 		{
432 			if(play_mode->encoding & PE_SIGNED)
433 			s32tos24x(buf, count);
434 			else
435 			s32tou24x(buf, count);
436 		} else if(play_mode->encoding & PE_SIGNED)
437 			s32tos24(buf, count);
438 		else
439 			s32tou24(buf, count);
440     }
441 	else if(play_mode->encoding & PE_ULAW)
442 	s32toulaw(buf, count);
443     else if(play_mode->encoding & PE_ALAW)
444 	s32toalaw(buf, count);
445     else if(play_mode->encoding & PE_SIGNED)
446 	s32tos8(buf, count);
447     else
448 	s32tou8(buf, count);
449     return bytes;
450 }
451 
validate_encoding(int enc,int include_enc,int exclude_enc)452 int validate_encoding(int enc, int include_enc, int exclude_enc)
453 {
454     const char *orig_enc_name, *enc_name;
455 
456     orig_enc_name = output_encoding_string(enc);
457     enc |= include_enc;
458     enc &= ~exclude_enc;
459     if(enc & (PE_ULAW|PE_ALAW))
460 	enc &= ~(PE_24BIT|PE_16BIT|PE_SIGNED|PE_BYTESWAP);
461     if(!(enc & PE_16BIT || enc & PE_24BIT))
462 	enc &= ~PE_BYTESWAP;
463 	if(enc & PE_24BIT)
464 	enc &= ~PE_16BIT;	/* 24bit overrides 16bit */
465     enc_name = output_encoding_string(enc);
466     if(strcmp(orig_enc_name, enc_name) != 0)
467 	ctl->cmsg(CMSG_WARNING, VERB_NOISY,
468 		  "Notice: Audio encoding is changed `%s' to `%s'",
469 		  orig_enc_name, enc_name);
470     return enc;
471 }
472 
apply_encoding(int32 old_enc,int32 new_enc)473 int32 apply_encoding(int32 old_enc, int32 new_enc)
474 {
475 	const int32 mutex_flags[] = {
476 		PE_16BIT | PE_24BIT | PE_ULAW | PE_ALAW,
477 		PE_BYTESWAP | PE_ULAW | PE_ALAW,
478 		PE_SIGNED | PE_ULAW | PE_ALAW,
479 	};
480 	int i;
481 
482 	for (i = 0; i < sizeof mutex_flags / sizeof mutex_flags[0]; i++) {
483 		if (new_enc & mutex_flags[i])
484 			old_enc &= ~mutex_flags[i];
485 	}
486 	return old_enc | new_enc;
487 }
488 
output_encoding_string(int enc)489 const char *output_encoding_string(int enc)
490 {
491     if(enc & PE_MONO)
492     {
493 	if(enc & PE_16BIT)
494 	{
495 	    if(enc & PE_SIGNED)
496 		return "16bit (mono)";
497 	    else
498 		return "unsigned 16bit (mono)";
499 	}
500 	else if(enc & PE_24BIT)
501 	{
502 	    if(enc & PE_SIGNED)
503 		return "24bit (mono)";
504 	    else
505 		return "unsigned 24bit (mono)";
506 	}
507 	else
508 	{
509 	    if(enc & PE_ULAW)
510 		return "U-law (mono)";
511 	    else if(enc & PE_ALAW)
512 		return "A-law (mono)";
513 	    else if(enc & PE_SIGNED)
514 		return "8bit (mono)";
515 	    else
516 		return "unsigned 8bit (mono)";
517 	}
518     }
519     else if(enc & PE_16BIT)
520     {
521 	if(enc & PE_BYTESWAP)
522 	{
523 	    if(enc & PE_SIGNED)
524 		return "16bit (swap)";
525 	    else
526 		return "unsigned 16bit (swap)";
527 	}
528 	else if(enc & PE_SIGNED)
529 	    return "16bit";
530 	else
531 	    return "unsigned 16bit";
532     }
533     else if(enc & PE_24BIT)
534     {
535 	if(enc & PE_SIGNED)
536 	    return "24bit";
537 	else
538 	    return "unsigned 24bit";
539     }
540     else
541 	if(enc & PE_ULAW)
542 	    return "U-law";
543 	else if(enc & PE_ALAW)
544 	    return "A-law";
545 	else if(enc & PE_SIGNED)
546 	    return "8bit";
547 	else
548 	    return "unsigned 8bit";
549     /*NOTREACHED*/
550 }
551 
get_encoding_sample_size(int32 enc)552 int get_encoding_sample_size(int32 enc)
553 {
554 	int size = (enc & PE_MONO) ? 1 : 2;
555 
556 	if (enc & PE_24BIT)
557 		size *= 3;
558 	else if (enc & PE_16BIT)
559 		size *= 2;
560 	return size;
561 }
562 
563 /* mode
564   0,1: Default mode.
565   2: Remove the directory path of input_filename, then add output_dir.
566   3: Replace directory separator characters ('/','\',':') with '_', then add output_dir.
567  */
create_auto_output_name(const char * input_filename,char * ext_str,char * output_dir,int mode)568 char *create_auto_output_name(const char *input_filename, char *ext_str, char *output_dir, int mode)
569 {
570   char *output_filename;
571   char *ext, *p;
572   int32 dir_len = 0;
573   char ext_str_tmp[65];
574 
575   output_filename = (char *)safe_malloc((output_dir!=NULL?strlen(output_dir):0) + strlen(input_filename) + 6);
576   if(output_filename==NULL)
577     return NULL;
578   output_filename[0] = '\0';
579   if(output_dir!=NULL && (mode==2 || mode==3)) {
580     strcat(output_filename,output_dir);
581     dir_len = strlen(output_filename);
582 #ifndef __W32__
583     if(dir_len>0 && output_filename[dir_len-1]!=PATH_SEP){
584 #else
585       if(dir_len>0 && output_filename[dir_len-1]!='/' && output_filename[dir_len-1]!='\\' && output_filename[dir_len-1]!=':'){
586 #endif
587 	strcat(output_filename,PATH_STRING);
588 	dir_len++;
589       }
590     }
591     strcat(output_filename, input_filename);
592 
593     if((ext = strrchr(output_filename, '.')) == NULL)
594       ext = output_filename + strlen(output_filename);
595     else {
596       /* strip ".gz" */
597       if(strcasecmp(ext, ".gz") == 0) {
598 	*ext = '\0';
599 	if((ext = strrchr(output_filename, '.')) == NULL)
600 	  ext = output_filename + strlen(output_filename);
601       }
602     }
603 
604     /* replace '\' , '/' or PATH_SEP between '#' and ext */
605     p = strrchr(output_filename,'#');
606     if(p!=NULL){
607       char *p1;
608 #ifdef _mbsrchr
609 #define STRCHR(a,b) _mbschr(a,b)
610 #else
611 #define STRCHR(a,b) strchr(a,b)
612 #endif
613 #ifndef __W32__
614       p1 = p + 1;
615       while((p1 = STRCHR(p1,PATH_SEP))!=NULL && p1<ext){
616         *p1 = '_';
617 	p1++;
618       }
619 #else
620       p1 = p + 1;
621       while((p1 = STRCHR(p1,'\\'))!=NULL && p1<ext){
622       	*p1 = '_';
623 	p1++;
624       }
625       p1 = p;
626       while((p1 = STRCHR(p1,'/'))!=NULL && p1<ext){
627 	*p1 = '_';
628 	p1++;
629       }
630 #endif
631 #undef STRCHR
632     }
633 
634     /* replace '.' and '#' before ext */
635     for(p = output_filename; p < ext; p++)
636 #ifndef __W32__
637       if(*p == '.' || *p == '#')
638 #else
639 	if(*p == '#')
640 #endif
641 	  *p = '_';
642 
643     if(mode==2){
644       char *p1,*p2,*p3;
645 #ifndef __W32__
646       p = strrchr(output_filename+dir_len,PATH_SEP);
647 #else
648 #ifdef _mbsrchr
649 #define STRRCHR _mbsrchr
650 #else
651 #define STRRCHR strrchr
652 #endif
653       p1 = STRRCHR(output_filename+dir_len,'/');
654       p2 = STRRCHR(output_filename+dir_len,'\\');
655       p3 = STRRCHR(output_filename+dir_len,':');
656 #undef STRRCHR
657       p1>p2 ? (p1>p3 ? (p = p1) : (p = p3)) : (p2>p3 ? (p = p2) : (p = p3));
658 #endif
659       if(p!=NULL){
660 	for(p1=output_filename+dir_len,p2=p+1; *p2; p1++,p2++)
661 	  *p1 = *p2;
662 	*p1 = '\0';
663       }
664     }
665 
666     if(mode==3){
667       for(p=output_filename+dir_len; *p; p++)
668 #ifndef __W32__
669 	if(*p==PATH_SEP)
670 #else
671 	  if(*p=='/' || *p=='\\' || *p==':')
672 #endif
673 	    *p = '_';
674     }
675 
676     if((ext = strrchr(output_filename, '.')) == NULL)
677       ext = output_filename + strlen(output_filename);
678     if(*ext){
679       strncpy(ext_str_tmp,ext_str,64);
680       ext_str_tmp[64]=0;
681       if(isupper(*(ext + 1))){
682 	for(p=ext_str_tmp;*p;p++)
683 	  *p = toupper(*p);
684 	*p = '\0';
685       } else {
686 	for(p=ext_str_tmp;*p;p++)
687 	  *p = tolower(*p);
688 	*p = '\0';
689       }
690       strcpy(ext+1,ext_str_tmp);
691     }
692     return output_filename;
693 }
694