ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/PDL-Audio/sndlib/sound.c
Revision: 1.1
Committed: Tue Dec 28 01:05:17 2004 UTC (19 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1_1, rel-1_2, HEAD
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /* sound.c */
2    
3     /* TODO: make this thread-safe by wrapping locks around the header/data base references */
4    
5     #if defined(HAVE_CONFIG_H)
6     #include "config.h"
7     #endif
8    
9     #include <math.h>
10     #include <stdio.h>
11     #if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_FCNTL_H))
12     #include <fcntl.h>
13     #endif
14     #include <signal.h>
15     #if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_LIMITS_H))
16     #include <limits.h>
17     #endif
18     #include <errno.h>
19     #include <stdlib.h>
20    
21     #if (defined(NEXT) || (defined(HAVE_LIBC_H) && (!defined(HAVE_UNISTD_H))))
22     #include <libc.h>
23     #else
24     #if (!(defined(_MSC_VER))) && (!(defined(MPW_C)))
25     #include <unistd.h>
26     #endif
27     #if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_STRING_H))
28     #include <string.h>
29     #endif
30     #endif
31    
32     #include <ctype.h>
33     #include <stddef.h>
34    
35     #include "sndlib.h"
36    
37     #if MACOS
38     #if (!defined(MPW_C))
39     #include <time.h>
40     #include <stat.h>
41     #endif
42     #else
43     #include <sys/types.h>
44     #include <sys/stat.h>
45     #endif
46    
47     #include <stdarg.h>
48    
49     static int mus_error_tag = MUS_INITIAL_ERROR_TAG;
50     int mus_make_error_tag(void) {return(mus_error_tag++);}
51     static void (*mus_error_handler)(int err_type, char *err_msg);
52     void mus_set_error_handler(void (*new_error_handler)(int err_type, char *err_msg)) {mus_error_handler = new_error_handler;}
53     static char *mus_error_buffer = NULL;
54    
55     void mus_error(int error, char *format, ...)
56     {
57     va_list ap;
58     va_start(ap,format);
59     vsprintf(mus_error_buffer,format,ap);
60     va_end(ap);
61     if (mus_error_handler)
62     (*mus_error_handler)(error,mus_error_buffer);
63     else fprintf(stderr,mus_error_buffer);
64     }
65    
66     void mus_fwrite(int fd, char *format, ...)
67     {
68     va_list ap;
69     va_start(ap,format);
70     vsprintf(mus_error_buffer,format,ap);
71     va_end(ap);
72     write(fd,mus_error_buffer,strlen(mus_error_buffer));
73     }
74    
75     static char *s_copy_string (char *str)
76     {
77     char *newstr = NULL;
78     if ((str) && (*str))
79     {
80     newstr = (char *)CALLOC(strlen(str)+1,sizeof(char));
81     strcpy(newstr,str);
82     }
83     return(newstr);
84     }
85    
86    
87     #ifndef MPW_C
88     static time_t file_write_date(char *filename)
89     {
90     struct stat statbuf;
91     int err;
92     err = stat(filename,&statbuf);
93     if (err < 0) return(err);
94     return((time_t)(statbuf.st_mtime));
95     }
96     #else
97     #include <Files.h>
98     static int file_write_date(char *filename)
99     {
100     #if 0
101     /* this isn't right... */
102     HParamBlockRec pb;
103     FSSpec fs;
104     FSMakeFSSpec(0,0,(unsigned char *)filename,&fs);
105     pb.fileParam.ioVRefNum = fs.vRefNum;
106     pb.fileParam.ioDirID = fs.parID;
107     pb.fileParam.ioNamePtr = fs.name;
108     PBHGetFInfo(&pb,FALSE);
109     mus_error(0,"%s date: %d ",filename,pb.fileParam.ioFlMdDat);
110     return(pb.fileParam.ioFlMdDat);
111     #else
112     return(1);
113     #endif
114     }
115     #endif
116    
117     static int sndlib_initialized = 0;
118    
119     int initialize_sndlib(void)
120     {
121     int err = 0;
122     if (!sndlib_initialized)
123     {
124     sndlib_initialized = 1;
125     mus_error_buffer = (char *)CALLOC(256,sizeof(char));
126     if (mus_error_buffer == NULL) return(-1);
127     err = mus_create_header_buffer();
128     if (err == 0)
129     {
130     err = mus_create_descriptors();
131     if (err == 0) err = initialize_audio();
132     }
133     if (err == -1) {FREE(mus_error_buffer); return(-1);}
134     }
135     return(0);
136     }
137    
138     typedef struct {
139     char *file_name; /* full path -- everything is keyed to this name */
140     int table_pos;
141     int *aux_comment_start,*aux_comment_end;
142     int *loop_modes,*loop_starts,*loop_ends;
143     int markers;
144     int *marker_ids,*marker_positions;
145     int samples, datum_size, data_location, srate, chans, header_type, data_format, original_sound_format, true_file_length;
146     int comment_start, comment_end, header_distributed, type_specifier, bits_per_sample, fact_samples, block_align;
147     int write_date;
148     int *max_amps;
149     } sound_file;
150    
151     static int sound_table_size = 0;
152     static sound_file **sound_table = NULL;
153    
154     static void free_sound_file(sound_file *sf)
155     {
156     if (sf)
157     {
158     sound_table[sf->table_pos] = NULL;
159     if (sf->aux_comment_start) FREE(sf->aux_comment_start);
160     if (sf->aux_comment_end) FREE(sf->aux_comment_end);
161     if (sf->file_name) FREE(sf->file_name);
162     if (sf->loop_modes) FREE(sf->loop_modes);
163     if (sf->loop_starts) FREE(sf->loop_starts);
164     if (sf->loop_ends) FREE(sf->loop_ends);
165     if (sf->marker_ids) FREE(sf->marker_ids);
166     if (sf->marker_positions) FREE(sf->marker_positions);
167     if (sf->max_amps) FREE(sf->max_amps);
168     FREE(sf);
169     }
170     }
171    
172     static sound_file *add_to_sound_table(void)
173     {
174     int i,pos;
175     #ifdef MACOS
176     sound_file **ptr;
177     #endif
178     pos = -1;
179     for (i=0;i<sound_table_size;i++)
180     if (sound_table[i] == NULL)
181     {
182     pos = i;
183     break;
184     }
185     if (pos == -1)
186     {
187     pos = sound_table_size;
188     sound_table_size += 16;
189     if (sound_table == NULL)
190     sound_table = (sound_file **)CALLOC(sound_table_size,sizeof(sound_file *));
191     else
192     {
193     #ifdef MACOS
194     ptr = (sound_file **)CALLOC(sound_table_size,sizeof(sound_file *));
195     for (i=0;i<pos;i++) ptr[i] = sound_table[i];
196     FREE(sound_table);
197     sound_table = ptr;
198     #else
199     sound_table = (sound_file **)REALLOC(sound_table,sound_table_size * sizeof(sound_file *));
200     #endif
201     for (i=pos;i<sound_table_size;i++) sound_table[i] = NULL;
202     }
203     }
204     sound_table[pos] = (sound_file *)CALLOC(1,sizeof(sound_file));
205     sound_table[pos]->table_pos = pos;
206     return(sound_table[pos]);
207     }
208    
209     static void re_read_raw_header(sound_file *sf)
210     {
211     int chan,data_size;
212     chan = mus_open_read(sf->file_name);
213     data_size = lseek(chan,0L,SEEK_END);
214     sf->true_file_length = data_size;
215     sf->samples = mus_bytes2samples(sf->data_format,data_size);
216     close(chan);
217     }
218    
219     int forget_sound(char *name)
220     {
221     int i;
222     for (i=0;i<sound_table_size;i++)
223     {
224     if (sound_table[i])
225     {
226     if (strcmp(name,sound_table[i]->file_name) == 0)
227     {
228     free_sound_file(sound_table[i]);
229     return(0);
230     }
231     }
232     }
233     return(-1);
234     }
235    
236     static sound_file *find_sound_file(char *name)
237     {
238     int i,date;
239     sound_file *sf;
240     for (i=0;i<sound_table_size;i++)
241     {
242     if (sound_table[i])
243     {
244     if (strcmp(name,sound_table[i]->file_name) == 0)
245     {
246     sf = sound_table[i];
247     date = file_write_date(name);
248     if (date == sf->write_date)
249     return(sf);
250     else
251     {
252     if (sf->header_type == raw_sound_file)
253     {
254     /* sound has changed since we last read it, but it has no header, so
255     * the only sensible thing to check is the new length (i.e. caller
256     * has set other fields by hand)
257     */
258     sf->write_date = date;
259     re_read_raw_header(sf);
260     return(sf);
261     }
262     free_sound_file(sf);
263     return(NULL);
264     }
265     }
266     }
267     }
268     return(NULL);
269     }
270    
271     static void fill_sf_record(sound_file *sf)
272     {
273     sf->data_location = mus_header_data_location();
274     sf->samples = mus_header_samples();
275     sf->data_format = mus_header_format();
276     sf->srate = mus_header_srate();
277     sf->chans = mus_header_chans();
278     sf->datum_size = mus_header_format2bytes();
279     sf->header_type = mus_header_type();
280     sf->original_sound_format = mus_header_original_format();
281     sf->true_file_length = mus_true_file_length();
282     sf->comment_start = mus_header_comment_start();
283     sf->comment_end = mus_header_comment_end();
284     sf->header_distributed = mus_header_distributed();
285     sf->type_specifier = mus_header_type_specifier();
286     sf->bits_per_sample = mus_header_bits_per_sample();
287     sf->fact_samples = mus_header_fact_samples();
288     sf->block_align = mus_header_block_align();
289     sf->write_date = file_write_date(sf->file_name);
290     /* loop points and aux comments */
291     }
292    
293     static sound_file *read_sound_file_header_with_fd(int fd, char *arg)
294     {
295     int err=0;
296     sound_file *sf = NULL;
297     initialize_sndlib();
298     err = mus_read_header_with_fd(fd);
299     if (err == -1) return(NULL);
300     sf = add_to_sound_table();
301     sf->file_name = s_copy_string(arg);
302     fill_sf_record(sf);
303     return(sf);
304     }
305    
306     static sound_file *read_sound_file_header_with_name(char *name)
307     {
308     sound_file *sf = NULL;
309     initialize_sndlib();
310     if (mus_read_header(name) != -1)
311     {
312     sf = add_to_sound_table();
313     sf->file_name = s_copy_string(name);
314     fill_sf_record(sf);
315     }
316     return(sf);
317     }
318    
319     static sound_file *getsf(char *arg)
320     {
321     sound_file *sf = NULL;
322     if ((sf = find_sound_file(arg)) == NULL)
323     {
324     sf = read_sound_file_header_with_name(arg);
325     if (sf == NULL) set_audio_error(SNDLIB_CANT_OPEN);
326     }
327     return(sf);
328     }
329    
330     int sound_samples (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->samples); else return(-1);}
331     int sound_frames (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->samples / sf->chans); else return(-1);}
332     int sound_datum_size (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->datum_size); else return(-1);}
333     int sound_data_location (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->data_location); else return(-1);}
334     int sound_chans (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->chans); else return(-1);}
335     int sound_srate (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->srate); else return(-1);}
336     int sound_header_type (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->header_type); else return(-1);}
337     int sound_data_format (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->data_format); else return(-1);}
338     int sound_original_format (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->original_sound_format); else return(-1);}
339     int sound_comment_start (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->comment_start); else return(-1);}
340     int sound_comment_end (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->comment_end); else return(-1);}
341     int sound_length (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->true_file_length); else return(-1);}
342     int sound_fact_samples (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->fact_samples); else return(-1);}
343     int sound_distributed (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->header_distributed); else return(-1);}
344     int sound_write_date (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->write_date); else return(-1);}
345     int sound_type_specifier (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->type_specifier); else return(-1);}
346     int sound_align (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->block_align); else return(-1);}
347     int sound_bits_per_sample (char *arg) {sound_file *sf; sf = getsf(arg); if (sf) return(sf->bits_per_sample); else return(-1);}
348     float sound_duration(char *arg) {return((float)sound_frames(arg) / (float)sound_srate(arg));}
349    
350     int sound_aiff_p(char *arg)
351     {
352     return(sound_header_type(arg) == AIFF_sound_file);
353     }
354    
355     char *sound_comment(char *name)
356     {
357     int start,end,fd,len;
358     char *sc = NULL;
359     start = sound_comment_start(name);
360     end = sound_comment_end(name);
361     if (end == 0) return(NULL);
362     len = end-start+1;
363     if (len>0)
364     {
365     /* open and get the comment */
366     sc = (char *)CALLOC(len+1,sizeof(char)); /* len+1 calloc'd => we'll always have a trailing null */
367     #if MACOS
368     fd = open(name,O_RDONLY);
369     #else
370     #ifdef WINDOZE
371     fd = open(name,O_RDONLY | O_BINARY);
372     #else
373     fd = open(name,O_RDONLY,0);
374     #endif
375     #endif
376     lseek(fd,start,SEEK_SET);
377     read(fd,sc,len);
378     close(fd);
379     return(sc);
380     }
381     else return(NULL);
382     }
383    
384     char *sound_type_name(int type)
385     {
386     return(mus_header_type2string(type));
387     }
388    
389     char *sound_format_name(int format)
390     {
391     return(mus_header_data_format2string(format));
392     }
393    
394     int sound_bytes_per_sample(int format) {return(mus_format2bytes(format));}
395    
396     typedef struct {
397     int fd;
398     char *name;
399     } output_info;
400    
401     static output_info **header_names = NULL;
402     static int header_names_size = 0;
403    
404     static void save_header_name(int fd, char *arg)
405     {
406     int i,loc;
407     #ifdef MACOS
408     output_info **ptr;
409     #endif
410     loc = -1;
411     for (i=0;i<header_names_size;i++)
412     {
413     if (header_names[i] == NULL)
414     {
415     loc = i;
416     break;
417     }
418     }
419     if (loc == -1)
420     {
421     loc = header_names_size;
422     header_names_size += 4;
423     if (header_names == NULL)
424     header_names = (output_info **)CALLOC(header_names_size,sizeof(output_info *));
425     else
426     {
427     #ifdef MACOS
428     ptr = (output_info **)CALLOC(header_names_size,sizeof(output_info *));
429     for (i=0;i<loc;i++) ptr[i] = header_names[i];
430     FREE(header_names);
431     header_names = ptr;
432     #else
433     header_names = (output_info **)REALLOC(header_names,header_names_size * sizeof(output_info *));
434     #endif
435     for (i=loc;i<header_names_size;i++) header_names[i] = NULL;
436     }
437     }
438     header_names[loc] = (output_info *)CALLOC(1,sizeof(output_info));
439     header_names[loc]->fd = fd;
440     header_names[loc]->name = s_copy_string(arg);
441     }
442    
443     static void flush_header(int fd)
444     {
445     int i,loc,val;
446     sound_file *sf;
447     loc = -1;
448     val = -1;
449     for (i=0;i<header_names_size;i++)
450     {
451     if (header_names[i])
452     {
453     if (header_names[i]->fd == fd)
454     {
455     loc = i;
456     break;
457     }
458     }
459     }
460     if (loc != -1)
461     {
462     if (header_names[loc]->name)
463     {
464     sf = getsf(header_names[loc]->name);
465     if (sf) sf->write_date = 0; /* force subsequent re-read */
466     FREE(header_names[loc]->name);
467     header_names[loc]->name = NULL;
468     }
469     FREE(header_names[loc]);
470     header_names[loc] = NULL;
471     }
472     }
473    
474     int open_sound_input (char *arg)
475     {
476     int fd;
477     sound_file *sf = NULL;
478     set_audio_error(SNDLIB_NO_ERROR);
479     initialize_sndlib();
480     fd = mus_open_read(arg);
481     if (fd != -1)
482     {
483     if ((sf = find_sound_file(arg)) == NULL)
484     {
485     sf = read_sound_file_header_with_fd(fd,arg);
486     }
487     }
488     if (sf)
489     {
490     mus_set_file_descriptors(fd,sf->data_format,sf->datum_size,sf->data_location,sf->chans,sf->header_type);
491     mus_seek(fd,sf->data_location,SEEK_SET);
492     }
493     else set_audio_error(SNDLIB_CANT_OPEN);
494     return(fd);
495     }
496    
497     int open_sound_output (char *arg, int srate, int chans, int data_format, int header_type, char *comment)
498     {
499     int fd = 0,err,comlen = 0;
500     if (comment) comlen = strlen(comment);
501     set_audio_error(SNDLIB_NO_ERROR);
502     initialize_sndlib();
503     err = mus_write_header(arg,header_type,srate,chans,0,0,data_format,comment,comlen);
504     if (err != -1)
505     {
506     fd = mus_open_write(arg);
507     mus_set_file_descriptors(fd,data_format,mus_format2bytes(data_format),mus_header_data_location(),chans,header_type);
508     save_header_name(fd,arg);
509     }
510     else set_audio_error(SNDLIB_CANT_OPEN);
511     return(fd);
512     }
513    
514     int reopen_sound_output(char *arg, int chans, int format, int type, int data_loc)
515     {
516     int fd;
517     set_audio_error(SNDLIB_NO_ERROR);
518     initialize_sndlib();
519     fd = mus_reopen_write(arg);
520     mus_set_file_descriptors(fd,format,mus_format2bytes(format),data_loc,chans,type);
521     save_header_name(fd,arg);
522     return(fd);
523     }
524    
525     int close_sound_input (int fd)
526     {
527     return(mus_close(fd)); /* this closes the clm file descriptors */
528     }
529    
530     int close_sound_output (int fd, int bytes_of_data)
531     {
532     flush_header(fd);
533     mus_update_header_with_fd(fd,mus_get_header_type(fd),bytes_of_data);
534     return(mus_close(fd));
535     }
536    
537     int read_sound (int fd, int beg, int end, int chans, int **bufs)
538     {
539     return(mus_read(fd,beg,end,chans,bufs));
540     }
541    
542     int write_sound (int tfd, int beg, int end, int chans, int **bufs)
543     {
544     return(mus_write(tfd,beg,end,chans,bufs));
545     }
546    
547     int seek_sound (int tfd, long offset, int origin)
548     {
549     return(mus_seek(tfd,offset,origin));
550     }
551    
552     int seek_sound_frame(int tfd, int frame)
553     {
554     return(mus_seek_frame(tfd,frame));
555     }
556    
557     int override_sound_header(char *arg, int srate, int chans, int format, int type, int location, int size)
558     {
559     sound_file *sf;
560     /* perhaps once a header has been over-ridden, we should not reset the relevant fields upon re-read? */
561     sf = getsf(arg);
562     if (sf)
563     {
564     if (location != -1) sf->data_location = location;
565     if (size != -1) sf->samples = size;
566     if (format != -1)
567     {
568     sf->data_format = format;
569     sf->datum_size = mus_format2bytes(format);
570     }
571     if (srate != -1) sf->srate = srate;
572     if (chans != -1) sf->chans = chans;
573     if (type != -1) sf->header_type = type;
574     return(0);
575     }
576     else return(-1);
577     }
578    
579     int sound_max_amp(char *ifile, int *vals)
580     {
581     int ifd,ichans,bufnum,n,curframes,i,frames,chn,fc;
582     int *buffer,*time,*samp;
583     int **ibufs;
584     sound_file *sf;
585     sf = getsf(ifile);
586     if ((sf) && (sf->max_amps))
587     {
588     for (chn=0;chn<sf->chans;chn++)
589     {
590     vals[chn*2] = sf->max_amps[chn*2];
591     vals[chn*2+1] = sf->max_amps[chn*2+1];
592     }
593     return(sf->samples / sf->chans);
594     }
595     ifd = open_sound_input(ifile);
596     sf = getsf(ifile);
597     if (ifd == -1) return(-1);
598     ichans = sound_chans(ifile);
599     frames = sound_frames(ifile);
600     if (frames <= 0) {close_sound_input(ifd); return(0);}
601     seek_sound_frame(ifd,0);
602     ibufs = (int **)CALLOC(ichans,sizeof(int *));
603     bufnum = 8192;
604     for (i=0;i<ichans;i++) ibufs[i] = (int *)CALLOC(bufnum,sizeof(int));
605     time = (int *)CALLOC(ichans,sizeof(int));
606     samp = (int *)CALLOC(ichans,sizeof(int));
607     for (n=0;n<frames;n+=bufnum)
608     {
609     if ((n+bufnum)<frames) curframes = bufnum; else curframes = (frames-n);
610     read_sound(ifd,0,curframes-1,ichans,ibufs);
611     for (chn=0;chn<ichans;chn++)
612     {
613     buffer = (int *)(ibufs[chn]);
614     fc=samp[chn];
615     for (i=0;i<curframes;i++)
616     {
617     if ((buffer[i]>fc) || (fc < -buffer[i]))
618     {
619     time[chn]=i+n;
620     samp[chn]=buffer[i];
621     if (samp[chn]<0) samp[chn] = -samp[chn];
622     fc = samp[chn];
623     }
624     }
625     }
626     }
627     close_sound_input(ifd);
628     if (sf->max_amps == NULL) sf->max_amps = (int *)CALLOC(ichans*2,sizeof(int));
629     for (chn=0,i=0;chn<ichans;chn++,i+=2)
630     {
631     vals[i]=samp[chn];
632     vals[i+1]=time[chn];
633     sf->max_amps[i] = vals[i];
634     sf->max_amps[i+1] = vals[i+1];
635     }
636     FREE(time);
637     FREE(samp);
638     for (i=0;i<ichans;i++) FREE(ibufs[i]);
639     FREE(ibufs);
640     return(frames);
641     }
642    
643    
644     int mus_file2array(char *filename, int chan, int start, int samples, int *array)
645     {
646     int ifd,chans,total_read;
647     int **bufs;
648     ifd = open_sound_input(filename);
649     if (ifd == -1) return(-1);
650     chans = sound_chans(filename);
651     bufs = (int **)CALLOC(chans,sizeof(int *));
652     bufs[chan] = array;
653     seek_sound_frame(ifd,start);
654     total_read = mus_read_any(ifd,0,chans,samples,bufs,(int *)bufs);
655     close_sound_input(ifd);
656     FREE(bufs);
657     return(total_read);
658     }
659    
660     int mus_array2file(char *filename, int *ddata, int len, int srate, int channels)
661     {
662     /* put ddata into a sound file, taking byte order into account */
663     /* assume ddata is interleaved already if more than one channel */
664     int fd;
665     #ifdef SNDLIB_LITTLE_ENDIAN
666     int i;
667     unsigned char *o;
668     unsigned char tmp;
669     #endif
670     fd = mus_create(filename);
671     if (fd == -1) return(-1);
672     mus_write_next_header(fd,srate,channels,28,len*4,SNDLIB_32_LINEAR,NULL,0);
673     #ifdef SNDLIB_LITTLE_ENDIAN
674     o = (unsigned char *)ddata;
675     for (i=0;i<len;i++,o+=4)
676     {
677     tmp = o[0]; o[0]=o[3]; o[3]=tmp; tmp=o[1]; o[1]=o[2]; o[2]=tmp;
678     }
679     #endif
680     #ifndef MACOS
681     write(fd,(unsigned char *)ddata,len*4);
682     #else
683     write(fd,(char *)ddata,len*4);
684     #endif
685     close(fd);
686     return(0);
687     }
688