-
Notifications
You must be signed in to change notification settings - Fork 7
/
Mix_speech_and_noise.txt
906 lines (770 loc) · 31.9 KB
/
Mix_speech_and_noise.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
####################################################
# #
# MIX SPEECH WITH NOISE #
# #
####################################################
# version 6
#
# written by Matthew Winn
####################################################
# with help on the SSN sub-procedure
# by Theo Veenker, Lisette van Delft, Hugo Quené
#
# See Quené & Van Delft (2010).
# Speech Commun, 52, 911-918.
# doi:10.1016/j.specom.2010.03.005
#
#
####################################################
# Features of this script:
#
# Allows different noise/speech adjustment methods
# (e.g. adjust speech fix noise, or vice versa)
#
# You can generate speech-shaped noise on the fly
# and you can make it speech-modulated noise
# It automatically adjusts for the duration
# of noise that you need for each speech sound
#
# It attempts to account for leading and trailing silence
# in your sounds by excluding those silences
# before calculating speech intensity
# (this can guard against silences messing up
# your effective SNR)
#
# It gracefully handles non-integer SNRs in object naming
# and allows you to override its suggestion.
#
# It prevents you from overwrting your own files
# It interrupts you if you're at risk for slowing down praat
# by loading and maintaining a large number of new objects
# as you loop through a whole folder of sounds.
#
# It produces some documentation
# and saves it, if you are saving the sound output
# also saves the noise you mixed with the speech.
#
# Limitation notes:
# This script currently cannot process sounds
# that have special characters like - in the filename
# example: "Sound1-talkerA"
# because it interprets the - as part of a mathematical formula
# Also, if your files have any other non-basic characters,
# Praat will convert them to underscores upon loading and saving
# e.g. Sound(copy) becomes Sound_copy_
#
# version 7: update to correct an error in variable names,
# and corrected for the situation of different sample rates
# in the target and the noise
# also added check to make sure speech and noise have the same sampling frequency
#
#
# Maybe other features can be added in the future
#
####################################################
#
# Start-up form
form Mix speech and noise
comment signal to noise ratio
real snr 0
comment How do you want to set the SNR?
optionmenu snr_method: 1
option maintain speech, change noise
option maintain noise, change speech
option change both half
comment noise before and after the speech:
real lead_silence_duration 0.4
real trail_silence_duration 0.4
comment circle shift noise?
boolean circle_shift_noise 1
comment =========================================
comment How do you want the new sounds to be named?
optionmenu sound_newnames: 1
option ~sound_name~_snr_`snr`
option maintain exact same name
option custom sound suffix: (below)
option custom sound prefix: (below)
sentence optional_name_add _noise
comment =========================================
comment Which sounds should be mixed with noise?
optionmenu which_sounds: 1
option run objects in the list that I will select
option run all the sounds in this folder
sentence optional_folder L:/PraatScripts/Mix_speech_and_noise/audio2
comment (write choose_folder if you want to navigate through a window)
comment if you're running a whole folder, do you want to save the ouput?
boolean save_files 0
boolean cleanup_loaded_objects_at_runtime 1
sentence new_sub_folder_name _with_noise
comment You will select the noise from the object list
comment (put it in the list before you run this script)
endform
#----------------------------------------------------#
# Preparation
call convert_names_from_form
call check_snr_label
#----------------------------------------------------#
# Using sounds already in the object list
if mode$ == "run_objects_in_praat_list"
# this is for Matt to debug easily
nocheck selectObject: "Sound s0"
nocheck plusObject: "Sound s1"
nocheck plusObject: "Sound s3"
nocheck plusObject: "Sound s4"
nocheck plusObject: "Sound s5"
# Ask the user to select the sounds they want to use
pause select all sounds to be mixed with noise
number_of_selected_sounds = numberOfSelected ("Sound")
# Assign an object number to each of those sounds
for index to number_of_selected_sounds
sound'index' = selected("Sound",index)
endfor
# Select the NOISE to be mixed with the sounds
call select_the_noise
# some documentation
clearinfo
print Processing 'number_of_selected_sounds' sounds in the object list 'newline$'
print mixing with noise at 'snr:3' dB SNR 'newline$'
print mixed by 'snr_method_label$'
print using the noise 'noise$' 'newline$'
if replicated_noise == 1
print ... which was replicated to cover the necessary duration 'newline$'
endif
# Loop through the sounds
# for each selected sound...
for current_sound_index from 1 to number_of_selected_sounds
select sound'current_sound_index'
speech$ = selected$("Sound")
call establish_sound_output_name
@mix_speech_and_noise: speech$, noise$, snr, snr_method$, lead_silence_duration, trail_silence_duration, newname$, circle_shift_noise
# End loop through sounds selected from the list
endfor
elsif mode$ == "run_sounds_in_folder"
# Using sounds in a folder
# First check to make sure the folder names are specified accurately
# and that there are sounds to process
call check_folder_info
# warn the user if they're about to keep loads of obejcts into the window
call check_for_large_list
# Establish an output path if you are saving files
if save_files == 1
save_path$ = "'audio_path$'/'new_sub_folder_name$'"
createFolder: save_path$
endif
# Select the NOISE to be mixed with the sounds
call select_the_noise
# some documentation
clearinfo
print Processing 'num_files' files in 'audio_path$' 'newline$'
print mixing with noise at 'snr:3' dB SNR 'newline$'
print mixed by 'snr_method_label$''newline$'
print using the noise 'noise$' 'newline$'
if replicated_noise == 1
print ... which was replicated to cover the necessary duration 'newline$'
endif
# Loop through the folder
for file_index from 1 to num_files
select Strings fileList
filename$ = Get string: file_index
Read from file: "'audio_path$'/'filename$'"
speech$ = selected$("Sound")
call establish_sound_output_name
@mix_speech_and_noise: speech$, noise$, snr, snr_method$, lead_silence_duration, trail_silence_duration, newname$, circle_shift_noise
if save_files == 1
select Sound 'newname$'
Save as WAV file: "'audio_path$'/'new_sub_folder_name$'/'newname$'.wav"
endif
if cleanup_loaded_objects_at_runtime == 1
select Sound 'newname$'
Remove
endif
# end loop through sounds
endfor
# save the documentation
if save_files == 1
call save_info_window
call save_noise_file
endif
# End conditional on if you are running sounds in a folder
endif
#
#
##
###
#####
########
#############
#####################
##################################
#######################################################
#
# MAIN PROCEDURE
#
procedure mix_speech_and_noise .speech$ .noise$ .snr .snr_method$ .lead_silence_duration .trail_silence_duration .newname$ .circle_shift_noise
# Check input params
call mix_speech_and_noise_check_params
#----------------------------------------------------#
# Basic info about the speech input
select Sound '.speech$'
.original_speech_dB = Get intensity (dB)
.original_full_duration = Get total duration
# Get the intensity of the parts other than the leading & trailing silence
call get_dB_exclude_leading_trailing_silence '.speech$' 0
.speech_content_dB = get_dB_exclude_leading_trailing_silence.dB
#----------------------------------------------------#
# Extract the speech, excluding the leading & trailing silence
select Sound '.speech$'
Extract part: get_dB_exclude_leading_trailing_silence.content_start_time, get_dB_exclude_leading_trailing_silence.content_end_time, "rectangular", 1, "no"
Rename... '.speech$'_center
.speech_content_duration = Get total duration
#----------------------------------------------------#
# Extract part of noise to use
duration_noise_needed = .speech_content_duration + .lead_silence_duration+ .trail_silence_duration
select Sound '.noise$'
noise_duration = Get total duration
# If it's not long enough,
# replicate until it's the duration you need
# but first, copy it in its original form
if noise_duration < duration_noise_needed
select Sound 'noise$'
Copy... '.noise$'_extended
noise$ = selected$("Sound")
while noise_duration < duration_noise_needed
call replicate_in_place 'noise$'
select Sound 'noise$'
noise_duration = Get total duration
endwhile
endif
# Circle shift the noise to randomize its starting point
if .circle_shift_noise == 1
# circle shift the noise
select Sound '.noise$'
num_noise_samples = Get number of samples
samples_to_shift = randomInteger (1, (num_noise_samples - 50))
call circle_shift '.noise$' samples_to_shift '.noise$'_shifted
select Sound '.noise$'_shifted
endif
# Extract the amount of noise needed to mask the speech
# (plus lead & trail time)
Extract part: 0, duration_noise_needed, "rectangular", 1, "no"
Rename... noise_extracted
# Get intensity of that extracted part
# (not the whole noise, because the extract part might be different)
.extracted_noise_dB = Get intensity (dB)
# Cleanup
if circle_shift_noise == 1
# Remove the latest temporary noise
select Sound '.noise$'_shifted
Remove
endif
#----------------------------------------------------#
# Set target intensity for speech and noise
if snr_method$ == "change_noise"
.target_intensity_speech = .speech_content_dB
.target_intensity_noise = .target_intensity_speech - .snr
elsif snr_method$ == "change_speech"
.target_intensity_noise = .extracted_noise_dB
.target_intensity_speech = .target_intensity_noise + .snr
elsif snr_method$ == "change_both_half"
.target_intensity_noise = .speech_content_dB - (.snr/2)
.target_intensity_speech = .speech_content_dB + (.snr/2)
endif
# Scale the two components
select Sound noise_extracted
Scale intensity... .target_intensity_noise
select Sound '.speech$'_center
Scale intensity... .target_intensity_speech
# add leading and trailing silence to speech
# after its intensity has been set
call add_silence_buffer '.speech$'_center .lead_silence_duration .trail_silence_duration
#----------------------------------------------------#
# Blend the speech and noise
if inspect_speech_and_noise_components == 1
pause inspect noise_extracted and '.speech$'_center_silence_buffered
endif
select Sound noise_extracted
Copy... '.newname$'
object_name_to_add$ = "Sound_'.speech$'_center_silence_buffered"
#Formula... self[col] + 'object_name_to_add$'[col]
Formula: "self[col] + 'object_name_to_add$'[col]"
#----------------------------------------------------#
# Cleanup
selectObject: "Sound '.speech$'_center"
plusObject: "Sound '.speech$'_center_silence_buffered"
plusObject: "Sound noise_extracted"
Remove
# Return with the new sound selected
select Sound '.newname$'
endproc
#
#
##
###
#####
########
#############
#####################
##################################
#######################################################
#
# sub-procedures
#
#######################################################
##################################
#####################
#############
########
#####
###
##
#
#
procedure add_silence_buffer .name$ .lead_silence_duration .trail_silence_duration
select Sound '.name$'
.samplerate = Get sampling frequency
# Leading silence
if .lead_silence_duration > 0
Create Sound from formula: "silence_onset", 1, 0, .lead_silence_duration, .samplerate, "0"
endif
selectObject: "Sound '.name$'"
# Position the target speech next in the object list
Copy: "temp_speech"
# Trailing silence
if .trail_silence_duration > 0
Create Sound from formula: "silence_offset", 1, 0, .trail_silence_duration, .samplerate, "0"
endif
# Sequence together
nocheck selectObject: null
if .lead_silence_duration > 0
plusObject: "Sound silence_onset"
endif
plusObject: "Sound temp_speech"
if .trail_silence_duration > 0
plusObject: "Sound silence_offset"
endif
Concatenate
Rename... '.name$'_silence_buffered
# cleanup
selectObject: "Sound temp_speech"
if .lead_silence_duration > 0
plusObject: "Sound silence_onset"
endif
if .trail_silence_duration > 0
plusObject: "Sound silence_offset"
endif
Remove
endproc
procedure replicate_in_place .name$
select Sound '.name$'
Rename... temp1
Copy... temp2
select Sound temp1
plus Sound temp2
# 1 ms cross-fade time to avoid transients
Concatenate with overlap... 0.001
# Restore original name
# (pseudo "in-place" modification)
Rename... '.name$'
# Cleanup
select Sound temp1
plus Sound temp2
Remove
# Have sound selected upon return
select Sound '.name$'
endproc
procedure check_for_large_list
if cleanup_loaded_objects_at_runtime == 0
if num_files > max_loaded_files_in_list
beginPause: "Lots of files to load"
comment: "Your folder has 'num_files' files."
comment: "And you have chosen to keep them all in the list"
comment: "(startup window `cleanup_loaded_objects_at_runtime` box was unhecked)"
comment: "This might slow down Praat"
comment: "Do you want to proceed, "
comment: "Or remove the new sounds form the list as you process the folder?"
choice: "cleanup_objects", 1
option: "proceed, leaving all the sounds in the list"
option: "remove the sounds as they are processed"
endPause: "stop","continue",2
if cleanup_objects == 1
cleanup_loaded_objects_at_runtime = 0
elsif cleanup_objects == 2
cleanup_loaded_objects_at_runtime = 1
endif
endif
endif
endproc
procedure get_dB_exclude_leading_trailing_silence .name$ .criterion
select Sound '.name$'
num_samples = Get number of samples
# Work forward from the beginning,
# advancing until you find signal that isn't silence
#
# initialize level
level_abs = 0
sample = 0
while level_abs <= .criterion
sample = sample + 1
level = Get value at sample number: 0, sample
level_abs = abs(level)
endwhile
.first_content_sample = sample
# Now work backwards from the end
sample = num_samples + 1
# initialize level again
level = 0
while level_abs <= .criterion
sample = sample - 1
level = Get value at sample number: 0, sample
level_abs = abs(level)
endwhile
.last_content_sample = sample
# Extract the part excluding leading & trailing silence
.content_start_time = Get time from sample number: .first_content_sample
.content_end_time = Get time from sample number: .last_content_sample
select Sound '.name$'
Extract part: .content_start_time, .content_end_time, "rectangular", 1, "no"
# get the intensity of that part
.dB = Get intensity (dB)
Remove
endproc
procedure circle_shift .sound$ .num_samples .newname$
select Sound '.sound$'
.start_time1 = Get time from sample number: .num_samples
.end_time1 = Get total duration
.start_time2 = 0
.end_time2 = Get time from sample number: .num_samples - 1
select Sound '.sound$'
Extract part: .start_time1, .end_time1, "rectangular", 1, "no"
Rename... part_1
select Sound '.sound$'
Extract part: .start_time2, .end_time2, "rectangular", 1, "no"
Rename... part_2
select Sound part_1
plus Sound part_2
Concatenate
Rename... '.newname$'
select Sound part_1
plus Sound part_2
Remove
endproc
procedure select_the_noise
beginPause: "Choose the noise to mix"
comment: "Choose the noise you want to mix:"
choice: "noise_selection", 1
option: "pick a noise from the object list"
option: "create speech-shaped noise now"
option: "create speech-shaped modulated noise now"
comment: "if you want to create noise now,"
comment: "you will select a bunch of sounds in the list"
comment: "and the script will generate it"
clicked = endPause: "stop","continue",2
if noise_selection == 1
pause choose the noise you want to use
noise$ = selected$("Sound")
elsif noise_selection == 2
# make 15-second speech-shaped noise
call make_SSN new_noise_duration 0
elsif noise_selection == 3
# make 15-second modulated speech-shaped noise
call make_SSN new_noise_duration 1
endif
endproc
procedure mix_speech_and_noise_check_params
# Check to see if sound exists
nocheck selectObject: "Sound 'mix_speech_and_noise.speech$'"
if numberOfSelected("Sound") == 0
exit PROBLEM: intended speech 'mix_speech_and_noise.speech$' is not in the object list
endif
# Check to see if noise exists
nocheck selectObject: "Sound 'mix_speech_and_noise.noise$'"
if numberOfSelected("Sound") == 0
exit PROBLEM: intended noise 'mix_speech_and_noise.noise$' is not in the object list
endif
# Check to make sure snr is defined
temp = mix_speech_and_noise.snr
if temp == undefined
exit PROBLEM: SNR not defined on call to mix speech and noise
endif
# Check to make sure snr method is a legit choice
if mix_speech_and_noise.snr_method$ != "change_noise"
if mix_speech_and_noise.snr_method$ != "change_speech"
if mix_speech_and_noise.snr_method$ != "change_both_half"
exit PROBLEM: SNR method 'mix_speech_and_noise.snr_method$' not available; must use change_speech, change_noise, or change_both_half
endif
endif
endif
# Check to make sure lead & trail silence is not less than 0
temp = mix_speech_and_noise.lead_silence_duration
if temp < 0
exit PROBLEM: lead_silence_duration 'lead_silence_duration' cannot be less than zero
endif
temp = mix_speech_and_noise.trail_silence_duration
if temp < 0
exit PROBLEM: trail_silence_duration 'trail_silence_duration' cannot be less than zero
endif
# check to make sure speech and noise have the same sampling frequency
selectObject: "Sound 'mix_speech_and_noise.speech$'"
.speech_samplerate = Get sampling frequency
selectObject: "Sound 'mix_speech_and_noise.noise$'"
.noise_samplerate = Get sampling frequency
# if they are not equal, resample the noise
if .noise_samplerate != .speech_samplerate
selectObject: "Sound 'mix_speech_and_noise.noise$'"
Copy... 'mix_speech_and_noise.noise$'_original
Resample... '.speech_samplerate' 30
# re-establish the name that will be called later
Rename... 'mix_speech_and_noise.noise$'
print NOTE: Noise 'mix_speech_and_noise.noise$' was resampled to match the samplerate of the target sound
endif
endproc
procedure check_folder_info
# Folder where the current sounds are
if optional_folder$ == "choose_folder" or optional_folder$ == "choose folder"
# If the user wrote "choose_folder" in the window,
# then let them click around to select the folder
audio_path$ = chooseFolder$: "Choose a folder with all of your sounds"
else
# use user input
audio_path$ = optional_folder$
endif
# List the wav files in that folder
Create Strings as file list: "fileList", "'audio_path$'\*.wav"
num_files = Get number of strings
# If it seems like this folder doesn't have enough sounds...
if num_files < 2
beginPause: "Small number of files"
if num_files == 0
comment: "There are no files in the folder you named."
elsif num_files == 1
comment: "There is only ONE file in the folder you named."
else
comment: "There are only 'num_files' files in the folder you named."
endif
comment: "'audio_path$'"
comment: "Are you sure this is the correct folder?"
if optional_folder$ != "choose_folder"
comment: "(was it typed correctly?)"
endif
clicked = endPause: "Stop","Continue with this folder", 1
if clicked == 1
exit
endif
endif
# If no sub-folder name (blank)
if new_sub_folder_name$ == ""
beginPause: "No sub-folder named"
comment: "Your sub-folder name is blank"
comment: "This means that your new files with noise"
comment: "will be in the SAME folder as your current sounds."
comment: "'audio_path$'"
comment: "Are you sure you want to do this?"
# If the user chose to leave the name unchanged
# AND save the new sounds in the same folder as the originals,
# then the priginals will be irretrievably lost.
# Stop them from doing this.
if sound_newnames == 2
comment: "- - - - - - - - - - - - - - - - - - - - "
comment: "You have chosen to save the sounds"
comment: "with the SAME name as the original filename"
comment: "This means that your new files"
comment: "will OVERWRITE your current files"
comment: "This is a bad idea. Don't do it"
comment: "- - - - - - - - - - - - - - - - - - - - "
comment: ""
comment: "Please go back to the startup window and either:"
comment: "1) Name a sub-folder to save the sounds"
comment: "2) choose a new filename style to distinguish the new output sounds"
clicked = endPause: "oops","OOPS", 2
exit
endif
# It's a valid folder to work with
# this will complete the pause window
clicked = endPause: "Stop","Continue with this folder", 1
# Let the user exit if they want
if clicked == 1
exit
endif
endif
endproc
procedure check_snr_label
# warning against SNR in object/filename
# when SNR is not an integer
if floor(snr) == ceiling(snr)
snr_is_integer = 1
else
snr_is_integer = 0
# SNR is not an integer
# construct a new name for it
# that is amenable for object naming and file saving
if snr > 0
snr_main = floor(snr)
elsif snr < 0
snr_main = ceiling(snr)
endif
snr_decimal = snr - snr_main
snr_decimal2 = round(100*abs(snr_decimal))
snr_converted_label$ = "_snr_'snr_main'_'snr_decimal2'"
endif
# if the SNR is not an integer...
if snr_is_integer != 1
# but you wanted to use the SNR in the output name...
if sound_newnames == 1
# then verify what you want to do here:
beginPause: "SNR not an integer"
comment: "WARNING:"
comment: "your SNR is not an integer,"
comment: "so including it in the filename might get messy."
comment: "The soudn name suffix will be changed to this:"
comment: "(you can override it by typing over it)"
sentence: "optional_suffix", snr_converted_label$
clicked = endPause: "stop","continue",2
# re-establish the naming scheme
# for output sounds
sound_newnames = 5
.sound_suffix$ = snr_converted_label$
endif
endif
endproc
procedure make_SSN .target_duration .modulated
# For Matt to easily debug:
nocheck selectObject: "Sound s0"
nocheck plusObject: "Sound s1"
nocheck plusObject: "Sound s3"
nocheck plusObject: "Sound s4"
nocheck plusObject: "Sound s5"
pause select all sounds to combine into speech-shaped noise
Concatenate
samplerate = Get sampling frequency
int = Get intensity (dB)
To Ltas... 50
# Create some white noise and convert to a spectrum
Create Sound from formula... noise 1 0 '.target_duration' samplerate randomGauss(0,0.1)
To Spectrum... no
select Sound noise
Remove
# Apply LTAS envelope to white noise spectrum
select Spectrum noise
Formula... self * 10 ^ (Ltas_chain(x)/20)
# convert back to sound
To Sound
Scale intensity... 'int'
Rename... speech_shaped_noise
noise$ = selected$("Sound")
# apply modulation envelope if desired
if .modulated == 1
# get intensity envelope from the concatenated sounds
selectObject: "Sound chain"
.modulated_duration = Get total duration
To Intensity: 100, 0, "yes"
Down to IntensityTier
selectObject: "Sound speech_shaped_noise"
plusObject: "IntensityTier chain"
Multiply: "yes"
Rename: "temp"
# only extract as much duration as the intensity envelope
# that was fed into it
# (otherwise you get a big silent gap at the end)
if .target_duration < .modulated_duration
mod_extract_duration = .target_duration
else
mod_extract_duration = .modulated_duration
endif
Extract part: 0, mod_extract_duration, "rectangular", 1, "no"
Rename: "speech_shaped_modulated_noise"
Scale intensity: int
noise$ = selected$("Sound")
# cleanup
select Intensity chain
plus IntensityTier chain
plus Sound temp
Remove
endif
# evaluate noise duration
select Sound 'noise$'
.noise_duration = Get total duration
# if it's not long enough,
# replicate until it's the duration you need
# but first, copy it in its original form
if .noise_duration < .target_duration
select Sound 'noise$'
Copy... 'noise$'_orig_duration
while .noise_duration < .target_duration
call replicate_in_place 'noise$'
select Sound 'noise$'
.noise_duration = Get total duration
endwhile
endif
# Cleanup
select Ltas chain
plus Spectrum noise
plus Sound chain
Remove
endproc
procedure save_noise_file
noise_save_path$ = "'audio_path$'/'new_sub_folder_name$'/noise_used_in_mix"
createFolder: noise_save_path$
select Sound 'noise$'
Save as WAV file: "'noise_save_path$'/'noise$'.wav"
endproc
procedure save_info_window
info_filename$ = "'audio_path$'/'new_sub_folder_name$'/script_info.txt"
# delete the file if it's already there
deleteFile: info_filename$
# create the file
appendFile (info_filename$, info$ ())
endproc
procedure establish_sound_output_name
# Create a sound output name according to user input
if sound_newnames == 1
newname$ = "'speech$'_snr_'snr'"
elsif sound_newnames == 2
newname$ = "'speech$'"
elsif sound_newnames == 3
newname$ = "'speech$''optional_name_add$'"
elsif sound_newnames == 4
newname$ = "'optional_name_add$''speech$'"
elsif sound_newnames == 5
# created at runtime to accommodate SNR non-integers
newname$ = "'speech$''check_snr_label.sound_suffix$'"
endif
endproc
procedure convert_names_from_form
# Read the output from the start-up form,
# establish some variable levels
if snr_method == 1
# descriptive label for documentation
snr_method_label$ = "maintain speech, change noise"
# shorter label for evaluating in the script
snr_method$ = "change_noise"
elsif snr_method == 2
snr_method_label$ = "maintain noise, change speech"
snr_method$ = "change_speech"
elsif snr_method == 3
snr_method_label$ = "change both half"
snr_method$ = "change_both_half"
endif
if which_sounds == 1
mode$ = "run_objects_in_praat_list"
elsif which_sounds == 2
mode$ = "run_sounds_in_folder"
else
exit choose which sounds you want to run (in list / in folder)
endif
# initialize
replicated_noise = 0
# upper limit to the number of files allowed in the list
# before the user is offered the chance to revise their choice
# to clean up the list as it loops through the folder of sounds
max_loaded_files_in_list = 50
# if you want to intercept the speech and noise before they are added
# (for debugging)
inspect_speech_and_noise_components = 0
# a default duration of noise, if you are creating it at runtime
# this just needs to be sufficiently longer than the longest speech stimulus
# that you want to mix with noise,
# and longer still, if you want it to have variability in starting point
# since test sentences are rarely more than 5 seconds long,
# this should be sufficient for *most* cases
new_noise_duration = 15
endproc