1 #include "mrilib.h"
2
3 static byte mulaw( float x ) ; /* prototype for mu-law conversion */
4
5 #undef DEFAULT_SRATE
6 #define DEFAULT_SRATE 16000
7
8 /* get specific sound recordings */
9 #include "cs_sounds.h" /* stored in Audio subdirectory */
10
11 /*--------------------------------------------------------------------------*/
12 /*---------- find a sound playing program ----------*/
13
14 static int found_pprog = -1 ;
15 static char *pprog = NULL ;
16 static char *pprog_name = NULL ;
17
18 static const int DEBUG = 0 ;
19
get_sound_player(void)20 char * get_sound_player(void)
21 {
22 if( found_pprog < 0 ){
23 char *eee ;
24 eee = getenv("AFNI_SOUND_PLAYER") ;
25 if( eee != NULL || THD_is_executable(eee) ){
26 pprog = strdup(eee) ;
27 } else {
28 pprog = THD_find_executable("play") ; /* sox */
29 if( pprog == NULL )
30 pprog = THD_find_executable("afplay") ; /* OS X */
31 if( pprog == NULL )
32 pprog = THD_find_executable("mplayer") ; /* Linux or Mac */
33 if( pprog == NULL )
34 pprog = THD_find_executable("aplay") ; /* Linux */
35 }
36
37 found_pprog = (pprog != NULL) ;
38 if( found_pprog ) pprog_name = THD_trailname(pprog,0) ;
39
40 if( DEBUG )
41 INFO_message("get_sound_player: %s",(found_pprog)?pprog:"NULL") ;
42 }
43
44 return pprog ;
45 }
46
47 /*--------------------------------------------------------------------------*/
48 static char note_type[32] = "pluck" ;
49 static int gain_value = -27 ;
50 static int two_tone = 0 ;
51
set_sound_note_type(char * typ)52 void set_sound_note_type( char *typ )
53 {
54 if( typ == NULL || typ[0] == '\0' ){ strcpy(note_type,"pluck"); return; }
55
56 if( strncmp(typ,"sine",3) == 0 ||
57 strncmp(typ,"square",3) == 0 ||
58 strncmp(typ,"triangle",3) == 0 ||
59 strncmp(typ,"sawtooth",3) == 0 ||
60 strncmp(typ,"trapezium",3) == 0 ||
61 strncmp(typ,"pluck",3) == 0 ){
62
63 strcpy( note_type , typ ) ;
64 } else {
65 WARNING_message("unknown sox note type '%s'",typ) ;
66 }
67
68 return ;
69 }
70
71 /*-----*/
72
set_sound_gain_value(int ggg)73 void set_sound_gain_value( int ggg )
74 {
75 if( ggg < 0 ) gain_value = ggg ;
76 return ;
77 }
78
79 /*-----*/
80
set_sound_twotone(int ggg)81 void set_sound_twotone( int ggg )
82 {
83 two_tone = ggg ; return ;
84 }
85
86 /*-----*/
87
88 static int psk_set = 0 ;
89
90 /*-----*/
91
92 #if 0
93 #define NFORKLIST 4
94 static int nfork_pg = 0 ;
95 static int forklist_pg[NFORKLIST] ;
96
97 void play_sound_killpg(void){
98 int ii ;
99 for( ii=0 ; ii < NFORKLIST ; ii++ ){
100 if( forklist_pg[ii] > 0 ){
101 killpg(forklist_pg[ii],SIGKILL) ;
102 }
103 }
104 return ;
105 }
106 #endif
107
108 /*-----*/
109
110 #if 0
111 static int nfork_id = 0 ;
112 static int forklist_id[NFORKLIST] ;
113
114 void play_sound_killid(void)
115 {
116 int ii ;
117 INFO_message("play_sound_killid()") ;
118 for( ii=0 ; ii < NFORKLIST ; ii++ ){
119 if( forklist_id[ii] > 0 ){
120 ININFO_message("try to kill pid %d",forklist_id[ii]) ;
121 kill(forklist_id[ii],SIGKILL) ;
122 forklist_id[ii] = 0 ;
123 }
124 }
125 nfork_id = 0 ;
126 return ;
127 }
128 #endif
129
130 /*-----*/
131
kill_sound_players(void)132 void kill_sound_players(void)
133 {
134 char cmd[1024] ;
135 if( pprog_name != NULL ){
136 sprintf(cmd,"tcsh -c 'killall %s >& /dev/null'",pprog_name) ;
137 system(cmd) ;
138 }
139 return ;
140 }
141
142 /*---------------------------------------------------------------------------*/
143
144 static char *play_append = NULL ;
mri_sound_play_append(char * app)145 void mri_sound_play_append( char *app ) /* 09 Aug 2019 */
146 {
147 if( play_append != NULL ){ free(play_append) ; play_append = NULL ; }
148 if( app != NULL && *app != '\0' ) play_append = strdup(app) ;
149 return ;
150 }
151
152 static int play_notify = 0 ;
mri_play_sound_notify(int nn)153 void mri_play_sound_notify(int nn){ play_notify = nn ; return ; }
154
155 static float play_rate_fac = 1.0f ;
mri_play_sound_rate_fac(float fff)156 void mri_play_sound_rate_fac( float fff ){
157 if( fff > 0.1f && fff <= 10.0f ) play_rate_fac = fff ;
158 }
159
160 /*---------------------------------------------------------------------------*/
161 /* Play sound from a 1D image (up to 4 columns) */
162
mri_play_sound(MRI_IMAGE * imin,int ignore)163 void mri_play_sound( MRI_IMAGE *imin , int ignore )
164 {
165 MRI_IMAGE *qim ;
166 char *pre , fname[256] , cmd[2048] , extras[1024] ;
167 int ii , nsper ; float dt ;
168
169 (void)get_sound_player() ;
170 if( imin == NULL || imin->nx < 2 || pprog == NULL ) return ;
171
172 kill_sound_players() ;
173
174 if( !psk_set ){ atexit(kill_sound_players) ; psk_set = 1 ; }
175
176 ii = (int)fork() ;
177 if( ii != 0 ){ /*-- return to parent process --*/
178 #if 0
179 int jj = getpgid(ii) ;
180 if( nfork_pg == 0 || (nfork_pg > 0 && jj != forklist_pg[nfork_pg-1]) ){
181 forklist_pg[nfork_pg] = getpgid(ii) ;
182 nfork_pg = (nfork_pg+1)%NFORKLIST ;
183 }
184 #endif
185 #if 0
186 jj = ii ;
187 if( nfork_id == 0 || (nfork_id > 0 && jj != forklist_id[nfork_id-1]) ){
188 forklist_id[nfork_id] = jj ;
189 nfork_id = (nfork_id+1)%NFORKLIST ;
190 }
191 #endif
192 return ;
193 }
194
195 dt = (imin->nx <= 100) ? 0.20f : 0.14f + 6.0f/(float)imin->nx ;
196 dt *= play_rate_fac ;
197 nsper = (int)rintf(DEFAULT_SRATE*dt) ;
198
199 qim = mri_sound_1D_to_notes( imin , DEFAULT_SRATE , nsper , 4 , ignore , 0 ) ;
200 if( qim == NULL ) _exit(0) ;
201
202 pre = UNIQ_idcode_11() ; /* make up name for sound file */
203 sprintf(fname,"AFNI_SOUND_TEMP.%s.au",pre) ;
204 unlink(fname) ; /* remove sound file, in case it already exists */
205 if( DEBUG ) ININFO_message(" temp sound filename = %s",fname) ;
206 if( play_notify )
207 ININFO_message(" writing temp sound file: %s",fname) ;
208 sound_write_au_16PCM( fname, qim->nx, MRI_FLOAT_PTR(qim), DEFAULT_SRATE, 0.1f ) ;
209 extras[0] = '\0' ;
210 if( strcmp(pprog_name,"play") == 0 ){
211 strcat(extras," reverb 44 ") ;
212 if( play_append != NULL ) strcat(extras,play_append) ;
213 }
214 sprintf(cmd,"tcsh -c '%s %s %s >& /dev/null'",pprog,fname,extras) ;
215 if( DEBUG ) ININFO_message("%s",cmd) ;
216 if( play_notify )
217 ININFO_message(" starting sound player: %s",cmd) ;
218 system(cmd) ;
219 sleep(1);
220 unlink(fname) ;
221 _exit(0) ;
222 }
223
224 /*---------------------------------------------------------------------------*/
225 /*-------- convert value in range -1..1 into 8 bit code via 'mu-law' --------*/
226
mulaw(float x)227 static INLINE byte mulaw( float x )
228 {
229 short sx ; byte bx ;
230 int sr , im ;
231 short is , imag, iesp, ofst, ofst1 , sp ;
232
233 if( x < -1.0f ) x = -1.0f ;
234 else if( x > 1.0f ) x = 1.0f ;
235
236 sx = (short)rintf(8158.0f * x) ;
237
238 is = sx >> 15 ;
239 sr = (sx & 65535) ;
240 im = (is==0) ? sr : (65536-sr)&32767 ;
241
242 imag = im ; if( imag > 8158 ) imag = 8158 ;
243 ++imag;
244 iesp = 0;
245 ofst = 31;
246
247 if( imag > ofst ){
248 for( iesp = 1 ; iesp <= 8 ; ++iesp){
249 ofst1 = ofst ;
250 ofst += (1 << (iesp + 5)) ;
251 if (imag <= ofst) break ;
252 }
253 imag -= ofst1 + 1 ;
254 }
255
256 imag /= (1 << (iesp + 1)) ;
257
258 sp = (is == 0) ? (imag + (iesp << 4)) : (imag + (iesp << 4) + 128) ;
259
260 sp ^= 128 ; sp ^= 127 ;
261
262 bx = (byte)sp ; return bx ;
263 }
264
265 /*---------------------------------------------------------------------------*/
266
267 static int little_endian = -66 ;
268
set_little_endian(void)269 static INLINE void set_little_endian(void)
270 {
271 union { unsigned char bb[2] ;
272 short ss ; } fred ;
273
274 if( little_endian < 0 ){
275 fred.bb[0] = 1 ; fred.bb[1] = 0 ;
276 little_endian = (fred.ss == 1) ;
277 }
278 return ;
279 }
280
281 /*---------------------------------------------------------------------------*/
282
283 typedef struct { unsigned char a,b,c,d ; } fourby ;
284
swap_fourby(uint32_t ii)285 static uint32_t INLINE swap_fourby( uint32_t ii )
286 {
287 union { uint32_t qq ; fourby ff ; } qf ;
288 unsigned char tt ;
289
290 qf.qq = ii ;
291 tt = qf.ff.a ;
292 qf.ff.a = qf.ff.d ;
293 qf.ff.d = tt ;
294 tt = qf.ff.b ;
295 qf.ff.b = qf.ff.c ;
296 qf.ff.c = tt ;
297 return qf.qq ;
298 }
299
300 typedef struct { unsigned char a,b ; } twoby ;
301
swap_twobyar(int n,void * ar)302 static void swap_twobyar( int n , void *ar )
303 {
304 int ii ;
305 twoby *tb = (twoby *)ar ;
306 unsigned char tt ;
307
308 for( ii=0 ; ii < n ; ii++ ){
309 tt = tb[ii].a ;
310 tb[ii].a = tb[ii].b ;
311 tb[ii].b = tt ;
312 }
313 return ;
314 }
315
316 /*---------------------------------------------------------------------------*/
317
sound_write_au_header(FILE * fp,int nn,int srate,int code)318 void sound_write_au_header( FILE *fp , int nn , int srate , int code )
319 {
320 uint32_t ival ;
321
322 set_little_endian() ; /* do we need to swap bytes in header output? */
323
324 fwrite( ".snd" , 1 , 4, fp ) ; /*----- magic 'number' -----*/
325
326 ival = 32 ; if( little_endian ) ival = swap_fourby(ival) ;
327 fwrite( &ival , 1 , 4 , fp ) ; /*----- offset to data -----*/
328
329 ival = nn ; if( little_endian ) ival = swap_fourby(ival) ;
330 fwrite( &ival , 1 , 4 , fp ) ; /*----- number of data bytes -----*/
331
332 ival = code ; if( little_endian ) ival = swap_fourby(ival) ;
333 fwrite( &ival , 1 , 4 , fp ) ; /*----- encoding -----*/
334
335 ival = srate ; if( little_endian ) ival = swap_fourby(ival) ;
336 fwrite( &ival , 1 , 4 , fp ) ; /*----- samples per second -----*/
337
338 ival = 1 ; if( little_endian ) ival = swap_fourby(ival) ;
339 fwrite( &ival , 1 , 4 , fp ) ; /*----- number of channels -----*/
340
341 fwrite( "AFNI.au" , 1 , 8 , fp ) ; /*----- 8 bytes of annotation -----*/
342
343 return ;
344 }
345
346 /*---------------------------------------------------------------------------*/
347 /* samples in aa[] are between -1 and 1.
348 sample rate (per second) is in srate.
349 scl is a scale down factor (0 < scl <= 1).
350 *//*-------------------------------------------------------------------------*/
351
sound_write_au_ulaw(char * fname,int nn,float * aa,int srate,float scl)352 void sound_write_au_ulaw( char *fname, int nn, float *aa, int srate, float scl )
353 {
354 FILE *fp ;
355 uint32_t ival , jval ;
356 byte *bb ;
357 int ii ;
358
359 /* check inputs */
360
361 if( fname == NULL || nn < 2 || aa == NULL ){
362 ERROR_message("Illegal inputs to sound_write_au :(") ;
363 return ;
364 }
365
366 if( srate < 8000 ) srate = DEFAULT_SRATE ;
367 if( scl < 0.0f || scl > 1.0f ) scl = 1.0f ;
368
369 /* open output file */
370
371 fp = fopen( fname , "w" ) ;
372 if( fp == NULL ){
373 ERROR_message("Can't open audio output file '%s'",fname) ;
374 return ;
375 }
376
377 /* write .au file header */
378
379 sound_write_au_header( fp , nn , srate , 1 ) ;
380
381 /* convert and write data */
382
383 bb = (byte *)malloc(sizeof(byte)*nn) ;
384 for( ii=0 ; ii < nn ; ii++ ) bb[ii] = mulaw(scl*aa[ii]) ;
385 fwrite( bb , 1 , nn , fp ) ;
386
387 /* done done done */
388
389 fclose(fp) ;
390 free(bb) ;
391 return ;
392 }
393
394 /*---------------------------------------------------------------------------*/
395 /* samples in aa[] are between -1 and 1.
396 sample rate (per second) is in srate.
397 scl is a scale down factor (0 < scl <= 1).
398 *//*-------------------------------------------------------------------------*/
399
sound_write_au_8PCM(char * fname,int nn,float * aa,int srate,float scl)400 void sound_write_au_8PCM( char *fname, int nn, float *aa, int srate, float scl )
401 {
402 FILE *fp ;
403 uint32_t ival , jval ;
404 int8_t *bb ;
405 int ii ; float fac , val ;
406
407 /* check inputs */
408
409 if( fname == NULL || nn < 2 || aa == NULL ){
410 ERROR_message("Illegal inputs to sound_write_au :(") ;
411 return ;
412 }
413
414 if( srate < 8000 ) srate = DEFAULT_SRATE ;
415 if( scl < 0.0f || scl > 1.0f ) scl = 1.0f ;
416
417 /* open output file */
418
419 fp = fopen( fname , "w" ) ;
420 if( fp == NULL ){
421 ERROR_message("Can't open audio output file '%s'",fname) ;
422 return ;
423 }
424
425 /* write .au file header */
426
427 sound_write_au_header( fp , nn , srate , 2 ) ;
428
429 /* convert and write data */
430
431 bb = (int8_t *)malloc(sizeof(int8_t)*nn) ;
432 fac = 127.444f * scl ;
433 for( ii=0 ; ii < nn ; ii++ ){
434 val = fac*aa[ii] ;
435 bb[ii] = ( val < -127.0f ) ? -127 :
436 ( val > 127.0f ) ? 127 : (int8_t)rintf(val) ;
437 }
438 fwrite( bb , 1 , nn , fp ) ;
439
440 /* done done done */
441
442 fclose(fp) ;
443 free(bb) ;
444 return ;
445 }
446
447 /*---------------------------------------------------------------------------*/
448 /* samples in aa[] are between -1 and 1.
449 sample rate (per second) is in srate.
450 scl is a scale down factor (0 < scl <= 1).
451 *//*-------------------------------------------------------------------------*/
452
sound_write_au_16PCM(char * fname,int nn,float * aa,int srate,float scl)453 void sound_write_au_16PCM( char *fname, int nn, float *aa, int srate, float scl )
454 {
455 FILE *fp ;
456 uint32_t ival , jval ;
457 int16_t *bb ;
458 int ii ; float fac , val ;
459
460 /* check inputs */
461
462 if( fname == NULL || nn < 2 || aa == NULL ){
463 ERROR_message("Illegal inputs to sound_write_au :(") ;
464 return ;
465 }
466
467 if( srate < 8000 ) srate = DEFAULT_SRATE ;
468 if( scl < 0.0f || scl > 1.0f ) scl = 1.0f ;
469
470 /* open output file */
471
472 fp = fopen( fname , "w" ) ;
473 if( fp == NULL ){
474 ERROR_message("Can't open audio output file '%s'",fname) ;
475 return ;
476 }
477
478 /* write .au file header */
479
480 sound_write_au_header( fp , 2*nn , srate , 3 ) ;
481
482 /* convert and write data */
483
484 bb = (int16_t *)malloc(sizeof(int16_t)*nn) ;
485 fac = 32767.444f * scl ;
486 for( ii=0 ; ii < nn ; ii++ ){
487 val = fac*aa[ii] ;
488 bb[ii] = ( val < -32767.0f ) ? -32767 :
489 ( val > 32767.0f ) ? 32767 : (int16_t)rintf(val) ;
490 }
491 if( little_endian ) swap_twobyar( nn , bb ) ;
492
493 fwrite( bb , 2 , nn , fp ) ;
494
495 /* done done done */
496
497 fclose(fp) ;
498 free(bb) ;
499 return ;
500 }
501
502 /*---------------------------------------------------------------------------*/
503
504 #undef A4
505 #define A4 440.0 /* Hz */
506
mri_sound_1D_to_FM(MRI_IMAGE * imin,float fbot,float ftop,int srate,int nsper)507 MRI_IMAGE * mri_sound_1D_to_FM( MRI_IMAGE *imin ,
508 float fbot , float ftop ,
509 int srate , int nsper )
510 {
511 float *aa,*bb ;
512 float abot,atop , lfbot,lftop,dlf,dfac,ai,ap,di,dp ;
513 float afac,dph,ph , val ;
514 int nout , ii,jj,kk,ip , nn ;
515 MRI_IMAGE *imout , *qim ;
516
517 if( imin == NULL ) return NULL ;
518
519 nn = imin->nx ;
520 if( nn < 2 ){
521 ERROR_message("mri_sound_1D_to_FM: nn = %d",nn) ;
522 return NULL ;
523 }
524
525 if( imin->kind != MRI_float ){
526 qim = mri_to_float(imin) ;
527 } else {
528 qim = imin ;
529 }
530 aa = MRI_FLOAT_PTR(qim) ;
531
532 if( fbot <= 0.0f || fbot >= ftop ){
533 fbot = 0.25f * A4 ; ftop = 4.0f * A4 ;
534 }
535 if( ftop > 10000.0f ) ftop = 10000.0f ;
536 if( fbot < 30.0f ) fbot = 30.0f ;
537
538 if( srate < 8000 ) srate = DEFAULT_SRATE ;
539 if( nsper <= 0 ) nsper = 1 ;
540
541 /* will scale so abot..atop = log(fbot)..log(ftop) */
542
543 abot = atop = aa[0] ;
544 for( ii=1 ; ii < nn ; ii++ ){
545 if( aa[ii] < abot ) abot = aa[ii] ;
546 else if( aa[ii] > atop ) atop = aa[ii] ;
547 }
548
549 nout = nsper * nn ;
550 imout = mri_new( nout , 1 , MRI_float ) ;
551 bb = MRI_FLOAT_PTR(imout) ;
552
553 if( abot >= atop ){
554 float fmid = sqrtf(fbot*ftop) ;
555 INFO_message("mri_sound_1D_to_FM: only 1 value == sine wave output f=%.1g",fmid) ;
556 ph = 0.0f ;
557 dph = 2.0f * PI * fmid / srate ;
558 for( ii=0 ; ii < nout ; ii++ ){
559 bb[ii] = sin(ph) ; ph += dph ;
560 }
561 if( qim != imin ) mri_free(qim) ;
562 return imout ;
563 }
564
565 lfbot = log2(fbot) ; lftop = log2(ftop) ; dlf = lftop-lfbot ;
566
567 dfac = 1.0f / nsper ;
568 afac = dlf / (atop-abot) ;
569
570 #undef FRMOD
571 #define FRMOD(x) exp2f( lfbot + afac*((x)-abot) )
572
573 ph = 0.0f ;
574 dph = 2.0f * PI / srate ;
575 for( jj=ii=0 ; ii < nn ; ii++ ){
576 ph += FRMOD(aa[ii]) * dph ; bb[jj++] = sin(ph) ;
577 #if 0
578 val = FRMOD(aa[ii]) ;
579 ININFO_message(" %g %g",val,bb[jj-1]) ;
580 #endif
581 if( nsper > 1 ){
582 ip = ii+1 ; if( ip >= nn ) ip = nn-1 ;
583 ai = aa[ii] ; ap = aa[ip] ;
584 di = 1.0f ; dp = 0.0f ;
585 for( kk=1 ; kk < nsper ; kk++ ){
586 di -= dfac ; dp += dfac ;
587 ph += FRMOD( di*ai+dp*ap ) * dph ; bb[jj++] = sin(ph) ;
588 #if 0
589 val = FRMOD( di*ai+dp*ap ) ;
590 ININFO_message(" %g %g",val,bb[jj-1]) ;
591 #endif
592 }
593 }
594 }
595
596 #undef FRMOD
597
598 if( qim != imin ) mri_free(qim) ;
599 return imout ;
600 }
601
602 #undef A4
603
604 /*---------------------------------------------------------------------------*/
605
606 #define PA 54.0f /* 5 base notes (Hz) */
607 #define PC 64.0f
608 #define PD 72.0f
609 #define PE 81.0f
610 #define PG 96.0f
611
612 #define POCTA 4 /* number of octaves */
613
614 static int npenta = 0 ; /* will be 5*POCTA+1 */
615 static float *penta = NULL ; /* will hold all the notes */
616
sound_setup_penta(int octstart)617 void sound_setup_penta( int octstart )
618 {
619 int ii , jj ; float fac ;
620
621 if( npenta > 0 ) return ;
622 if( octstart < 0 || octstart >= POCTA ) octstart = 0 ;
623
624 npenta = 5*POCTA+1 ;
625 penta = (float *)malloc(sizeof(float)*npenta) ;
626 fac = 1.0f ;
627
628 for( jj=ii=0 ; ii < POCTA ; ii++ ){
629 if( ii >= octstart ){
630 penta[jj++] = fac * PA ;
631 penta[jj++] = fac * PC ;
632 penta[jj++] = fac * PD ;
633 penta[jj++] = fac * PE ;
634 penta[jj++] = fac * PG ;
635 }
636 fac *= 2.0f ;
637 }
638 penta[jj++] = fac * PA ; /* complete last octave */
639 npenta = jj ;
640
641 return ;
642 }
643
644 /*---------------------------------------------------------------------------*/
645
646 static int note_waveform = SOUND_WAVEFORM_TRIANGLE ;
647
sound_set_note_waveform(int nn)648 void sound_set_note_waveform( int nn ){ note_waveform = nn; }
649
650 #undef twoPI
651 #define twoPI 6.283185f
652 #undef fourPI
653 #define fourPI 12.566371f
654 #undef sixPI
655 #define sixPI 18.849556f
656
657 /* wav_xxx functions have period 1, amplitude 1, and assume t > 0 */
658
wav_sine(float t)659 static INLINE float wav_sine(float t){ return ( 0.999f*sinf(twoPI*t) ) ; }
660
wav_h2sine(float t)661 static INLINE float wav_h2sine(float t){
662 return ( 0.953f*sinf(twoPI*t)+0.3f*cosf(fourPI*t) ) ;
663 }
664
wav_sqsine(float t)665 static INLINE float wav_sqsine(float t){
666 float val = sinf(twoPI*t) , aval ;
667 #if 1
668 aval = sqrtf(fabsf(val)) ;
669 #else
670 aval = powf( fabsf(val) , 0.6f ) ;
671 #endif
672 return ( (val >= 0.0f ) ? aval : -aval ) ;
673 }
674
wav_square(float t)675 static INLINE float wav_square(float t){
676 float dt = fmodf(t,1.0f) ;
677 return ( (dt < 0.45f) ? 0.999f
678 :(dt < 0.55f) ? 0.999f-19.98f*(dt-0.45f)
679 : -0.999f ) ;
680 }
681
682 #undef TW
683 #define TW(x) (0.999f-3.996f*fabsf(x))
684
wav_triangle(float t)685 static INLINE float wav_triangle(float t){
686 float dt = fmodf(t,1.0f) ;
687 return ( (dt < 0.5f) ? TW(dt-0.25f) : -TW(dt-0.75f) ) ;
688 }
689
690 #undef envA
691 #undef envD
692 #undef envS
693 #define envA 0.0666f
694 #define envD 0.1666f
695 #define envS 0.9333f
696
697 /* Envelope for note, with 0 <= t <= 1 */
698
ADSR_env(float t)699 static INLINE float ADSR_env(float t){
700 if( t <= envA ) return (0.07f+0.93f*t/envA) ;
701 else if( t <= envD ) return (1.0f-0.1f*(t-envD)/(envD-envA)) ;
702 else if( t <= envS ) return (0.9f) ;
703 return (0.9f-0.83f*(t-envS)/(1.0f-envS)) ;
704 }
705
706 static int use_ADSR = 1 ;
707
sound_set_note_ADSR(int qq)708 void sound_set_note_ADSR(int qq){ use_ADSR = qq ; }
709
710 /*---------------------------------------------------------------------------*/
711 /* Note that if frq >= 0.5*srate, bad things will happen due to Mr Nyquist!! */
712 /*---------------------------------------------------------------------------*/
713
714 static float ttn = 0.0f ; /* continuous time between notes */
715
reset_note_ttn(void)716 static void reset_note_ttn(void){ ttn = 0.0f ; }
717
sound_make_note(float frq,int waveform,int srate,int nsam,float * sam)718 void sound_make_note( float frq, int waveform, int srate, int nsam, float *sam )
719 {
720 int ii ; float dt,tt ;
721
722 if( frq <= 0.0f || nsam < 9 || sam == NULL ) return ;
723
724 if( srate < 8000 ) srate = DEFAULT_SRATE ;
725
726 dt = frq / srate ; tt = ttn ;
727
728 /* form periodic waveform */
729
730 switch( waveform ){
731
732 default:
733 case SOUND_WAVEFORM_SINE:
734 for( ii=0 ; ii < nsam ; ii++ ){ sam[ii] = wav_sine(tt); tt += dt; }
735 break ;
736
737 case SOUND_WAVEFORM_SQUARE:
738 for( ii=0 ; ii < nsam ; ii++ ){ sam[ii] = wav_square(tt); tt += dt; }
739 break ;
740
741 case SOUND_WAVEFORM_TRIANGLE:
742 for( ii=0 ; ii < nsam ; ii++ ){ sam[ii] = wav_triangle(tt); tt += dt; }
743 break ;
744
745 case SOUND_WAVEFORM_H2SINE:
746 for( ii=0 ; ii < nsam ; ii++ ){ sam[ii] = wav_h2sine(tt); tt += dt; }
747 break ;
748
749 case SOUND_WAVEFORM_SQSINE:
750 for( ii=0 ; ii < nsam ; ii++ ){ sam[ii] = wav_sqsine(tt); tt += dt; }
751 break ;
752
753 }
754
755 ttn = tt ; /* continuous time between notes */
756
757 /* apply envelope (if note has enough samples) */
758
759 if( nsam > 127 && use_ADSR ){
760 dt = 1.0f/nsam ; tt= 0.0f ;
761 for( ii=0 ; ii < nsam ; ii++ ){ sam[ii] *= ADSR_env(tt); tt += dt; }
762 } else if( nsam > 24 ){
763 #if 0
764 float fac ;
765 for( ii=0 ; ii < 9 ; ii++ ){
766 fac = (ii+1)*0.1f ; sam[ii] *= fac ; sam[nsam-1-ii] *= fac ;
767 }
768 #endif
769 }
770
771 return ;
772 }
773
774 /*---------------------------------------------------------------------------*/
775
776 #define VAL_TO_CODE(v) ((int)rintf((v)-SOUND_WAVECODE_BASE))
777
mri_sound_1D_to_notes(MRI_IMAGE * imin,int srate,int nsper,int ny,int ignore,int use_wavecodes)778 MRI_IMAGE * mri_sound_1D_to_notes( MRI_IMAGE *imin, int srate, int nsper,
779 int ny, int ignore, int use_wavecodes )
780 {
781 float *aa,*bb,*qa ;
782 float abot,atop , fac , *valn ;
783 int nout , ii,jj , nn , qq ;
784 MRI_IMAGE *imout , *qim ;
785 int max_wavecode=0 ;
786 int ncode=0 , nsamcode=0 ;
787
788 /*--- deal with inputs ---*/
789
790 if( imin == NULL ) return NULL ;
791
792 nn = imin->nx ;
793 if( nn < 2 ){
794 ERROR_message("mri_sound_1D_to_notes: nn = %d",nn) ;
795 return NULL ;
796 }
797
798 if( ignore < 0 || nn-ignore < 2 ) ignore = 0 ;
799
800 if( imin->kind != MRI_float ){
801 qim = mri_to_float(imin) ;
802 } else {
803 qim = imin ;
804 }
805 aa = MRI_FLOAT_PTR(qim) ;
806
807 if( ny <= 0 ) ny = 1 ;
808 else if( ny > qim->ny ) ny = qim->ny ;
809
810 if( srate < 8000 ) srate = DEFAULT_SRATE ;
811 if( nsper <= 9 ) nsper = srate/2 ;
812
813 /*-- check for wavecodes embedded in the data --*/
814
815 if( use_wavecodes ){
816 max_wavecode = get_num_sound_waveforms() ;
817 use_wavecodes = max_wavecode > 0 ;
818 }
819
820 if( use_wavecodes ){
821 }
822
823 /*-- create output ---*/
824
825 nout = nsper * (nn-ignore) ;
826 imout = mri_new( nout , 1 , MRI_float ) ;
827 bb = MRI_FLOAT_PTR(imout) ; /* is full of zeros */
828
829 sound_setup_penta(1) ; /* skip octave 0 -- it's too low */
830
831 valn = (float *)malloc(sizeof(float)*nsper) ; /* notes */
832
833 for( qq=0 ; qq < ny ; qq++ ){ /* process first ny columns */
834 qa = aa + (nn*qq) ; /* add their sounds all up */
835 abot = atop = qa[ignore] ;
836 reset_note_ttn() ; /* re-start time at 0 */
837 for( ii=ignore+1 ; ii < nn ; ii++ ){
838 if( qa[ii] < abot ) abot = qa[ii] ;
839 else if( qa[ii] > atop ) atop = qa[ii] ;
840 }
841
842 if( abot < atop ){ /* some range to the numbers */
843 fac = (npenta-1.0f) / (atop-abot) ;
844 for( ii=ignore ; ii < nn ; ii++ ){
845 jj = rintf( fac*(qa[ii]-abot) ) ;
846 sound_make_note( penta[jj], note_waveform, srate, nsper, valn ) ;
847 for( jj=0 ; jj < nsper ; jj++ ) bb[((ii-ignore)*nsper)+jj] += valn[jj];
848 }
849 }
850 }
851
852 abot = mri_maxabs(imout) ;
853 if( abot == 0.0f ){ /* nothing computed? do something random! */
854 for( ii=ignore ; ii < nn ; ii++ ){
855 jj = lrand48() % npenta ;
856 sound_make_note( penta[jj], note_waveform,
857 srate, nsper, bb+((ii-ignore)*nsper) ) ;
858 }
859 }
860
861 THD_normmax( nout , bb ) ; /* max abs value = 1 */
862
863 free(valn) ;
864 if( qim != imin ) mri_free(qim) ;
865
866 return imout ;
867 }
868