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 |
|