-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathdocs_v1.79.html
More file actions
1258 lines (737 loc) · 121 KB
/
Copy pathdocs_v1.79.html
File metadata and controls
1258 lines (737 loc) · 121 KB
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
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<meta name="distribution" content="GLOBAL" />
<meta name="description" content="Ben Hackbarth, composer of electro-acoustic, computer and chamber music. Scores and recordings of compositions" />
<meta name="author" content="Ben Hackbarth" />
<meta charset="utf-8" />
<meta http-equiv="content-language" content="en" />
<title>AudioGuide - Documentation</title>
<link rel="stylesheet" href="prism/prism.css">
<script src="prism/prism.js"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.2.js"></script>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css">
<style type="text/css">
body { padding-top: 70px; } /* for navbar */
code[class*="language-"],
pre[class*="language-"] {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
figure {
width: 60%;
text-align: center;
font-size: smaller;
text-indent: 0;
border: thin silver solid;
margin: 0.5em;
padding: 0.5em;
}
h2 {
margin: 2.5em 0em 0.5em 0em;
}
h3 {
margin: 2em 0em 0.5em 0em;
}
h4 {
margin: 2.5em 0em 1.5em 0em;
}
.group {
}
.group .subgroup {
}
.group .subsubgroup {
}
.fixed {
position: fixed;
}
/* sidebar */
.bs-docs-mainbar {
padding-left: 20px;
margin-bottom: 100px;
}
/* sidebar */
.bs-docs-sidebar {
padding-left: 20px;
margin-top: 0px;
margin-bottom: 20px;
}
/* all links */
.bs-docs-sidebar .nav>li>a {
color: #999;
border-left: 2px solid transparent;
padding: 4px 20px;
font-size: 13px;
font-weight: 400;
}
/* nested links */
.bs-docs-sidebar .nav .nav>li>a {
padding-top: 1px;
padding-bottom: 1px;
padding-left: 30px;
font-size: 12px;
}
/* active & hover links */
.bs-docs-sidebar .nav>.active>a,
.bs-docs-sidebar .nav>li>a:hover,
.bs-docs-sidebar .nav>li>a:focus {
color: #563d7c;
text-decoration: none;
background-color: transparent;
border-left-color: #563d7c;
}
/* all active links */
.bs-docs-sidebar .nav>.active>a,
.bs-docs-sidebar .nav>.active:hover>a,
.bs-docs-sidebar .nav>.active:focus>a {
font-weight: 500;
}
/* nested active links */
.bs-docs-sidebar .nav .nav>.active>a,
.bs-docs-sidebar .nav .nav>.active:hover>a,
.bs-docs-sidebar .nav .nav>.active:focus>a {
font-weight: 500;
}
</style>
<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
$('body').scrollspy({
target: '.bs-docs-sidebar',
offset: 40
});
});//]]>
</script>
</head>
<body>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">AudioGuide</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li ><a href="index.html">Home</a></li>
<li ><a href="release.html">Download</a></li>
<li class="active"><a href="docs.html">Documentation</a></li>
<li ><a href="tutorial.html">Video Tutorials</a></li>
<li ><a href="examples.html">Sound Examples</a></li>
<li ><a href="resources.html">Other Resources</a></li>
<li ><a href="music.html">Music Made with AudioGuide</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<div class="row">
<!--Main Content -->
<div class="col-xs-9 bs-docs-mainbar">
<p align="center"><h1>AudioGuide1.79 Manual</h1>
By Ben Hackbarth, Norbert Schnell, Philippe Esling, Diemo Schwarz, Gilbert Nouno.<br>
Copyright Ben Hackbarth, 2011-2020.</p><br>
<section id="Installation" class="group"><h2>Installation</h2>
For the moment AudioGuide1.79 only works on OS X. On more current versions of OS X it should run out of the box with python2 or python3. Here is a complete list of the resources that AudioGuide1.79 requires on your computer:
<ul>
<li><b>numpy (python >= 2.7 has numpy pre-installed I think)</b> - Numpy is a numerical computation plugin for Python. Upgrading to the latest python2.7 should automatically install numpy. If you don’t have it, you can download the source code or a binary installer <a href="http://sourceforge.net/projects/numpy/files/NumPy/">here</a>. Or run "sudo easy_install pip" then "python -m pip install numpy"<li><b>csound6</b> - Needed if you would like AudioGuide to automatically render concatenations (which you probably do). Download an installer from <a href="http://csound.github.io/download.html">here</a>.</ul>
</section>
<section id="QuickStart" class="group"><h2>Quick Start</h2>
We are going to do concatenative synthesis with an excerpt of speech as the target and some music by Helmut Lachenmann as the corpus. First we need to break the lachenmann soundfile into small chunks, called segments, which will populate our corpus. Do this by using the agSegmentSf.py script and running the following command in the terminal:
<pre class="language-none"><code class="language-none">python agSegmentSf.py examples/lachenmann.aiff
</code></pre>
Next we run the agConcatenate.py script with an options file. The options file specifies the target soundfile's path along with a lot of other information which parameterized the concatenative process.
<pre class="language-none"><code class="language-none">python agConcatenate.py examples/01-simplest.py
</code></pre>
The agConcatenate.py script creates several output files with segment selection information. By default the selected sound segments are also rendered as a soundfile with csound6 and played back at the command line. Thus, if everything is working you should hear the concatenated soundfile played back after the process is complete.
<br><br>
The reason that segmentation and concatenation are separated into discrete steps that I find is useful to fine-tune the segmentation of corpus sounds <i>before</i> using them in a concatenation. Soundfile segmentation is a difficult technical problem and should remain conceptually and aesthetically open-ended. I have yet to find an algorithm that does not require adjustments based on the nature of the sound in question and the intention of the user as to what a segment should be.
</section>
<section id="CorpusSegmentation" class="group"><h2>Corpus Segmentation</h2>
There are several tools in AudioGuide1.79 to segment long soundfiles into smaller chucks for use in concatenation. The sections below detail two such scripts, agSegmentSf.py and agGranulateSf.py. agSegmentSf.py segments soundfiles into chunks based on the rise and fall of the file's amplitude; agGranulateSf.py makes overlapping grains suitabile for traditional granular synthesis. Keep in mind that you do not <i>need</i> to use AudioGuide scripts if you do not want to -- alternatively you can:
<ul>
<li> Use whole soundfiles as corpus segments. If you only want to use folders of sounds that have been pre-segmented into individual files, you can skip this section and proceed to the <a href="#Concatenating">concatenation</a> section (However make sure tell AudioGuide not to search for segmentation textfiles by setting the corpus attribute wholeFile=True. See <a href="#ManipulatingHowDirectoriesAreRead">Manipulating How Directories Are Read</a> for more info.).
<li> Create segmentation files by hand. You can do this in Audacity with its 'Labels' feature. Create a label track and indicate the start and end times of desired sound segments. Then "Export Labels..." and give the outputfile the same name as the soundfile + '.txt'. So, 'examples/lachenmann.aiff' would need a label file named 'examples/lachenmann.aiff.txt'.
<li> Create segmentation files with other software as long the textfile is written in the same format as AudioGuide’s.
</ul>
<section id="CorpusSegmentationwithagSegmentSfpy" class="group"><h2>Corpus Segmentation with agSegmentSf.py</h2>
The script you use to segment your corpus files according to it's acoustic features is called ‘agSegmentSf.py’. AgSegmentSf.py creates textfiles which denote the start and stop times of sound segments in a multi-segment audiofile.
</ul>
To segment a corpus file, ‘cd’ into the AudioGuide1.79 folder and run the following command:
<pre class="language-none"><code class="language-none">python agSegmentSf.py examples/lachenmann.aiff
</code></pre>
AudioGuide will think for a second, and then output the following data detailing the segmentation of this audiofile:
<pre class="language-none"><code class="language-none">---------------------- AUDIOGUIDE SEGMENT SOUNDFILE ----------------------
Evaluating /Users/ben/Documents/AudioGuide1.79/examples/lachenmann.aiff from 0.00-64.65
AN ONSET HAPPENS when
The amplitude crosses the Relative Onset Trigger Threshold: -40.00 (-t option)
AN OFFSET HAPPENS when
1. Offset Rise Ratio: when next-frame’s-amplitude/this-frame’s-amplitude >= 1.30 (-r option)
...or...
2. Offset dB above minimum: when this frame’s absolute amplitude <= -80.00 (minimum found amplitude of -260.00 plus the offset dB boost of 12.00 (-d option))
Found 144 segments
Wrote file /Users/ben/Documents/AudioGuide1.79/examples/lachenmann.aiff.txt
</code></pre>
As a result of running this python script, AudioGuide1.79 automatically writes a textfile with the exact same name and path as the soundfile, but adding the extension '.txt' -- in this case: examples/lachenmann.aiff.txt.
<div id="FinessingCorpusSegmentation" class="subgroup"><h3>Finessing Corpus Segmentation</h3>
The script ‘agSegmentSf.py’ gives several options in the form of command line flags for setting different parameters that affect how soundfiles are segmented. You can read about them by typing ‘python agSegmentSf.py -h’. Segment onsets are determined by the -t flag. Offsets are determined by a combination of the -d, -a, and -r flags. Segmenation multirise can be turned on with the addition of the -m flag. These flags are detailed below.
<ul> <li id="flag--t"><b>-t <value></b> (<span style="color:green">between -200 and -0</span>; the default is <span style="color:green">-40</span>) - This flag gives the onset trigger threshold value in dB. When the soundfile's amplitude rises above the threshold, a segment onset is created. Higher values closer to 0 will lead to fewer onsets.</li><li id="flag--d"><b>-d <value></b> (<span style="color:green">between 0 and 100</span>; the default is <span style="color:green">+12</span>) - This flag sets the relative offset trigger threshold. This value is added to the soundfile’s minimum amplitude. During segmentation, if a frame’s amplitude is below this threshold, it causes a segment offset. FOr instance, if the lowest amplitude in the soundfile is -82 and -d is set to +12, a dB value of -70 dB will cause a segment offset. Also see -a.</li><li id="flag--a"><b>-a <value></b> (<span style="color:green">between -200 and -0</span>; the default is <span style="color:green">-80</span>) - This flag changes the segmentation offset absolute threshold. When segmenting the target, if a frame's amplitude is below this value it will cause an offset. This variable is an absolute value whereas -d specifies a value relative to the soundfile’s minimum amplitude. Effectively, whichever of these two variables is higher will be the offset threshold. Also seer -d.</li><li id="flag--r"><b>-r <value></b> (<span style="color:green">greater than 1</span>; the default is <span style="color:green">1.1</span>) - This flag gives the offset rise ratio. It causes an offset when the ampltiude of the soundfile in the next frame divded by the amplitude of the current frame is greater than or equal to this ratio. Therefore if you are in a current sound segment, but the soundfile suddenly gets much louder, the current segment ends.</li><li id="flag--m"><b>-m</b> - When this flag is present it turns on the segmentation multirise feature. Essentially this creates a larger number of corpus segments which can overlap each other. When this flag is present the segmentation algorithm will loop over the corpus soundfile several times, varying the user supplied riseRatio (-r) +/- 20%. This leads to certain segments will start at the same time, but last different durations. Try 'agSegmentSf.py examples/lachenmann.aiff' with and without the -m flag and look at the difference when importing examples/lachenmann.aiff.txt in Audacity.</li></ul>
<pre class="language-none"><code class="language-none">python agSegmentSf.py -t -30 -d 4 soundfilename.wav # sets the threshold to -30. it will produce less onsets then -40 (the default). also changes the drop dB value to 4 dB above the minimum amplitude found in the entire soundfile, likely leading to longer segments.
python agSegmentSf.py -r 4 soundfilename.wav # changes the rise ratio from the default (1.1) to 4. This means that a frame's amplitude must be four times louder than the previous one to start a new segment
</code></pre>
Note that to segment a whole directory of soundfiles, you may use wildcard characters in the bash shell, as in:
<pre class="language-none"><code class="language-none">python agSegmentSf.py mydir/*.aiff # create a segmentation file for each aiff file located in mydir/
</code></pre>
The textfiles created by agSegmentSf.py use a segmentation labeling format identical to that of the soundfile editor Audacity. So, to examine your segments, open lachenmann.aiff in Audacity, then import labels and select ‘examples/lachenmann.aiff.txt’.
<figure class="figure">
<img src="http://www.benhackbarth.com/audioGuide/docimg/segmentationSf.png" class="figure-img img-fluid rounded" alt="A generic square placeholder image with rounded corners in a figure." width="75%">
<figcaption class="figure-caption">Segmenation produced by running the command 'python agSegmentSf.py examples/lachenmann.aiff'</figcaption>
</figure>
<figure class="figure">
<img src="http://www.benhackbarth.com/audioGuide/docimg/segmentationSfMinusM.png" class="figure-img img-fluid rounded" alt="A generic square placeholder image with rounded corners in a figure." width="75%">
<figcaption class="figure-caption">Segmenation produced by running the command 'python agSegmentSf.py -m examples/lachenmann.aiff'</figcaption>
</figure>
</div>
</section>
<section id="CorpusSegmentationwithagGranulateSfpy" class="group"><h2>Corpus Segmentation with agGranulateSf.py</h2>
A script you can use to segment your corpus files for use with granular synthesis is called ‘agGranulateSf.py’. Like agSegmentSf.py, agGranulateSf.py creates textfiles which denote the start and stop times of sound segments in a multi-segment audiofile. Unlike agSegmentSf.py, this script chops up a soundfile into evenly size grains and provides a mechanism for adjusting grain overlap.
</ul>
To segment a corpus file, ‘cd’ into the AudioGuide1.79 folder and run the following command:
<pre class="language-none"><code class="language-none">python agGranulateSf.py examples/lachenmann.aiff
</code></pre>
There are similar flags to the agSegment script, as we only want to use grains where there is audio present. Thus the -t, -a, and -d remain. Grain length in second is specified with the -g flag and grain overlap is specified with -o.
<ul> <li id="flag--g"><b>-g <value></b> (<span style="color:green">greater than zero</span>; the default is <span style="color:green">0.1</span>) - This flag sets the length of generated grains in seconds. Target and Corpus generated with agGranulate will be this length.</li><li id="flag--o"><b>-o <value></b> (<span style="color:green">greater than zero, less than -g</span>; the default is <span style="color:green">0.05</span>) - This flag sets the distance between sucessive grain overlaps in seconds. If this value is 0.05 a new grain will begin every 0.05 seconds. If -g is 0.3, the overlap of grains will be 6.</li><li id="flag--t"><b>-t <value></b> (<span style="color:green">between -200 and -0</span>; the default is <span style="color:green">-40</span>) - This flag gives the onset trigger threshold value in dB. When the soundfile's amplitude rises above the threshold, grains start being generated. Higher values closer to 0 will lead to fewer grains.</li><li id="flag--d"><b>-d <value></b> (<span style="color:green">between 0 and 100</span>; the default is <span style="color:green">+12</span>) - This flag sets the relative offset trigger threshold. This value is added to the soundfile’s minimum amplitude. During segmentation, if a frame’s amplitude is below this threshold, it causes grains to stop being generated. For instance, if the lowest amplitude in the soundfile is -82 and -d is set to +12, a dB value of -70 dB will cause grains to cease. Also see -a.</li><li id="flag--a"><b>-a <value></b> (<span style="color:green">between -200 and -0</span>; the default is <span style="color:green">-80</span>) - This flag changes the segmentation offset absolute threshold. When segmenting the target, if a frame's amplitude is below this value it will cause grains to stop being generated. This variable is an absolute value whereas -d specifies a value relative to the soundfile’s minimum amplitude. Effectively, whichever of these two variables is higher will be the offset threshold. Also see -d.</li></ul>
As a result of running this python script, AudioGuide1.79 automatically writes a textfile with the exact same name and path as the soundfile, but adding the extension '.txt' -- in this case: examples/lachenmann.aiff.txt.
<figure class="figure">
<img src="http://www.benhackbarth.com/audioGuide/docimg/segmentationGranulate.png" class="figure-img img-fluid rounded" alt="A generic square placeholder image with rounded corners in a figure." width="75%">
<figcaption class="figure-caption">Segmenation produced by running the command 'python agGranulateSf.py -g 0.3 -o 0.15 examples/lachenmann.aiff'</figcaption>
</figure>
It is important to note that, if you wish to window each grain with a fade in and fade out when concatenating, you will need to use the csf() onsetLen and offsetLen keyword arguments.
<pre class="language-none"><code class="language-none">csf('lachenmann.aiff', onsetLen='50%', offsetLen='50%')
</code></pre>
See examples/06-granular.py for usage and details.
<section id="ConcatenatingwithagConcatenatepy" class="group"><h2>Concatenating with agConcatenate.py</h2>
Once you have segmented corpus soundfiles to your satisfaction, you are ready to call the concatenation script agConcatenate.py with a special AudioGuide1.79 options file as the first (and only) argument.
<br><br>
To run one of the examples in the examples directory, run the following command inside the AudioGuide1.79 directory:
<pre><code>python agConcatenate.py examples/01-simplest.py
</code></pre>
...which will use the options contained in ‘examples/01-simplest.py’ to parameterize the concatenative algorithm. In this options file you specify a target sound, the corpus sounds, and (if you like) lots of other options that parameterize the concatenative process. When run, the ‘agConcatenate.py’ script will perform the following operations:
<ul>
<li> Run an ircamdescriptor analysis of the soundfile in the TARGET variable (note: the analysis is only done once -- subsequent usages of this soundfile simply read data from disk. Analysis files are stored in a directory called ‘AudioGuide1.79/audioguide/data/’ in the AudioGuide1.79 folder. This directory can become quite large since these files are quite substantial in size. Removing this folder will cause all analysis files to be recomputed).
<li> Segment the target sound according to your options file. An Audacity-style label file is created in a file called ‘output/tgtlabels.txt’ in the output directory.
<li> Run an ircamdescriptor analysis of the soundfiles in the CORPUS variable (only the first time each of these files are used).
<li> (If you’ve specified them) Remove corpus segments according to descriptor limitations (Nothing above a certain pitch, nothing below a certain dynamic, etc.).
<li> Normalize target and corpus descriptor data according to your options file (see <a href="#Normalization">this discussion</a> and the "norm" and "normmethod" in the section <a href="#Descriptorsandthedobject">Descriptors and the d() object</a>).
<li> Go through each target segment one by one. Select corpus segment(s) to match each target segment according to the normalized descriptors and search passes in the SEARCH variable (see the section <a href="#SEARCHvariable">SEARCH variable and spass() object</a>) of your options file. Control over the layering and superimposition of corpus sounds is specified in the SUPERIMPOSE variable (see the section <a href="#TheSUPERIMPOSEvariabls">The SUPERIMPOSE variable and si() object</a>).
<li> Write selected segments to a csound score called ‘output/output.csd’. (In addition to the csd file there are many other types of outputs (see the section <a href="#ConcatenationOutputFiles">Concatenation Output Files</a>).
<li> If you have csound, ‘output/output.csd’ is rendered with csound to create an audiofile called ‘output/output.aiff’.
<li> If you have csound, automatic playback of ‘output/output.aiff’ at the command line.
</ul>
The options file used by the concatenate script is a python file that defines a bunch of variables. Most variables are simply floats and strings. For instance, to change the path of the csound output sound file, add the following line to your options file:
<pre class="language-python"><code class="language-python">CSOUND_RENDER_FILEPATH = '/path/to/the/file/i/want.aiff' # sets the path of the csound output aiff file
DESCRIPTOR_HOP_SIZE_SEC = 0.02049 # change the analysis hop size
</code></pre>
However, there are five custom objects that are written into the options file as well -- tsf(), csf(), spass(), d() and si(). These objects take required parameters and also take keyword arguments. The following sections describe the object-style variables; Section <a href="#OtherOptions">Other Options</a> details simple variables assigned with the ‘=’ symbol.
<section id="InteractiveagConcatenatepy" class="group"><h2>Running agConcatenate.py in Interactive Mode</h2>
<p>-> <a href="https://www.youtube.com/watch?v=UYElwMFF6Ug&t=0s">Watch a related discussion from the AudioGuide Tutorial</a>.</p>
<p>As of version 1.6, agConcatenate.py can be run in "interactive mode" by adding the -i flag at runtime. The interactive mode runs agConcatenate.py as normal except that, after rendering and playing the concatenated output, the program stays open and monitors the loaded options file for changes. When the options file is modified and saved, agConcatenate.py will examine the changes and only rerun the parts of the program needed to create a new output. This makes auditioning->tweaking->auditioning the same options file much faster, especially when working with large corpi.</p>
To run agConcatenate.py in interactive mode, add the -i flag:
<pre><code>python agConcatenate.py examples/01-simplest.py -i
</code></pre>
<p>To exit interactive mode, type control-C.</p>
<div id="TheTARGETVariable" class="group"><h3>The TARGET Variable and tsf() object</h3>
The TARGET variable is written as a tsf() object which requires a path to a soundfile and also takes the following optional keyword arguments:
<pre class="language-python"><code class="language-python">tsf('pathtosoundfile', start=0, end=file-length, thresh=-40, offsetRise=1.5, offsetThreshAdd=+12, offsetThreshAbs=-80, scaleDb=0, minSegLen=0.05, maxSegLen=1000, midiPitchMethod='composite', stretch=1, segmentationFilepath=None)
</code></pre>
<ul>
<li><b>start</b> - The time in seconds to start reading the soundfile.<li><b>end</b> - The time in seconds to stop reading the soundfile. <li><b>thresh</b> - Segmentation onset threshold: a value from -100 to 0. This is equilavent to the function of the <a href="#flag--t">-t flag</a>. <li><b>offsetRise</b> - Segmentation offset ratio: a number greater than 1. This is equilavent to the function of the <a href="#flag--r">-r flag</a>.<li><b>offsetThreshAdd</b> - Segmentation offset relative threshold: a positive value in dB. This is equilavent to the function of the <a href="#flag--a">-a flag</a>.<li><b>offsetThreshAbs</b> - Segmentation offset absolute threshold: a negative value in dB. This is equilavent to the function of the <a href="#flag--d">-d flag</a>.<li><b>minSegLen</b> - Segmentation: the minimum duration in seconds of a target segment.<li><b>maxSegLen</b> - Segmentation: the maximum duration in seconds of a target segment.<li><b>scaleDb</b> - Applies an amplitude change to the whole target sound. By default, it is 0, yielding no change. -6 = twice as soft. The target’s amplitude will usually affect concatenation: the louder the target, the more corpus sounds can be composited to approximate it’s energy profile.<li><b>midiPitchMethod</b> - same as corpus method documented <a href="#midiPitchMethod">here</a>.<li><b>segmentationFilepath</b> - by default the Target sound is segmented at runtime. However, if you’d like to specify a user-defined segmentation, you may give a file path to this variable. Note that this file must be a textfile with the same format as corpus segmentation files.</ul>
<pre class="language-python"><code class="language-python">TARGET = tsf('cage.aiff') # uses the whole soundfile at its given amplitude
TARGET = tsf('cage.aiff', start=5, end=7, scaleDb=6) # only use seconds 5-7 of cage.aiff at double the amplitude.
<!--
TARGET = tsf('cage.aiff', start=2, end=3, stretch=2) # only uses seconds 2-3, but stretches the sound with supervp to twice its duration before concatenation
-->
</code></pre>
</div>
<div id="TheCORPUSVariable" class="group"><h3>The CORPUS Variable and csf() object</h3>
<p>-> <a href="https://www.youtube.com/watch?v=OqZzxfXEbc8&t=0s">Watch a related discussion from the AudioGuide Tutorial</a>.</p>
The CORPUS variable is defined as a list of csf() objects which require a path to a soundfile OR a directory. File paths and/or directory paths may be full paths or relative paths to the location of the options file you’re using or a path found in the SEARCH_PATHS variable. A csf() object required the soundfile/directory name, then takes the following optional keyword arguments:
<pre class="language-python"><code class="language-python">csf('pathToFileOrDirectoryOfFiles', start=None, end=None, includeTimes=[], excludeTimes=[], pitchfilter={}, limit=[], wholeFile=False, <a href="#ben">recursive</a>=True, includeStr=None, excludeStr=None, scaleDb=0.0, limitDur=None, clipDurationToTarget=False, onsetLen=0.01, offsetLen='30%', midiPitchMethod='composite', transMethod=None, transQuantize=0, concatFileName=None, allowRepetition=True, restrictRepetition=0.5, restrictOverlaps=None, restrictInTime=0, maxPercentTargetSegments=None, scaleDistance=1, superimposeRule=None, segmentationFile=None, segmentationExtension='.txt', instrTag=None, instrParams={})
</code></pre>
The simplest way to include a soundfile in your corpus is to use its path as the first argument of the csf() object:
<pre class="language-python"><code class="language-python">CORPUS = [csf("lachenmann.aiff")]# will search for a segmentation file called lachenmann.aiff.txt and add all of its segments to the corpus
</code></pre>
The simplest way to include a directory of soundfiles in your corpus is to use its path as the first argument of the csf() object:
<pre class="language-python"><code class="language-python">CORPUS = [csf("lachenmann.aiff"), csf('piano')]# will use segments from lachenmann.aiff as well as all sounds in the directory called piano
</code></pre>
Note that csf segments may also be specified as a list of lists. Each segment should be given as ['path', starttime, endtime]. If endtime = None, the duration of the soundfile is used. See example below:
<pre class="language-python"><code class="language-python">CORPUS = [csf([['myfile1.wav', 14.5, 15.3], ['myfile1.wav', 103.7, 104.1], ['myfile2.wav', 0, None]])] # will use two segments from myfile1.wav and then entire file myfile2.wav as the corpus
</code></pre>
However, as you can see above, each csf() object has <i>a lot</i> of optional arguments to give you better control over what segments are used, how directories are read and how segments are treated during concatenation.
<br><br>
<i>Note: Each of these keyword arguments <i>only</i> apply to the csf() object within which they are written. If you’d like to specify these parameters for the entire corpus, see <a href="#Specifyingcsfkeywordsglobally">Specifying csf() keywords globally</a>.</i>
<div id="Whichsegmentsareaddedtothecorpus" class="subgroup"><h4>Which Segments are Added to the Corpus</h4>
Below are csf() keywords which influence which sound segments make it into the corpus.
<ul>
<li><b>start</b> - Any segments which start before this time will be ignored.<li><b>end</b> - Any segments which start after this time will be ignored.<pre class="language-python"><code class="language-python">csf('lachenmann.aiff', start=20) # only use segments that start later than 20s.
csf('lachenmann.aiff', start=20, end=50) # only use segments that start between 20-50s.
</code></pre>
<li><b>includeTimes</b> - A list of two-number lists which specify regions of segments to include from this file’s list of segment times. See example below.<li><b>excludeTimes</b> - Same as includeTimes but excludes segments in the identified regions.
<pre class="language-python"><code class="language-python">csf('lachenmann.aiff', includeTimes=[(1, 4), (10, 12)]) # only use segments falling between 1-4 seconds and 10-12 seconds.
csf('lachenmann.aiff', excludeTimes=[(30, 55)]) # use Target and Corpus except those falling between 30-55s.
</code></pre>
<li><b>limit</b> - A list of equation-like strings where segmented descriptor names are used to include/exclude segments from this file / directory.<pre class="language-python"><code class="language-python">csf('lachenmann.aiff', limit=['centroid-seg >= 1000']) # segments whose centroid-seg is equal to or above 1000.
csf('lachenmann.aiff', limit=['centroid-seg < 50%']) # only use 50% of segments with the lowest centroid-seg.
csf('lachenmann.aiff', limit=['power-seg < 50%', 'power-seg > 10%']) # only use segments whose power-seg falls between 10%-50% of the total range of power-seg's in this file/directory.
</code></pre>
<li><b><a id="pitchfilter"></a>pitchfilter</b> - removes segments from a csf() entry based on whether or not each segment matches midipitches specified by the user. The user supplies a dictionary with a list of pitches. pitches less than 12 will be treated as pitch classes, i.e. if 0 is given, all pitches modulo 12 which equal 0 will be included. Corpus segments' pitches may be transposed to fit the given pitches -- the 'tolerance' key specifies a semitone tranposition tolerance. For instance, pitchfilter={'pitches': [60], 'tolerance': 3} will include Target and Corpus whose pitch is +-3 semitones from 60, and audioguide will transpose these pitches to be played back at the neaest pitch found in pitches, in this case 60. Note that this feature will override any other transposition given in csf(transMethod=). Also note that a corpus segment's pitch is determined with the segment's MIDIPitch-seg, which can be controled according to csf(midiPitchMethod=)<pre class="language-python"><code class="language-python">csf('pianosamples', pitchfilter={'pitches': [60, 68, 73]}), # discard any segments that do not match any of the given midipitches
csf('pianosamples', pitchfilter={'pitches': [60, 68, 73], 'tolerance': 3}), # discard any segments that do not match any of the given pitches +-3 semitones
csf('pianosamples', pitchfilter={'pitches': ['C4', 'Gs4', 'Db5'], 'tolerance': 3}), # you can also use strings with pitchnames!
csf('pianosamples', pitchfilter={'pitches': [1, 'E4'], 'tolerance': 3}), # C sharp in any octave and E4 will make it through!</code></pre>
<li><b>segmentationFile</b> - Manually specify the segmentation text file. By default, AudioGuide automatically looks for a file with the same name as the soundfile plus the extension ‘.txt’. You may specify a path file (as a string), or a list of strings to include multiple segmentation files which all use the same soundfile.<li><b>segmentationExtension</b> - Manually specify the segmentation text file extension. See above.</ul>
<pre class="language-python"><code class="language-python">csf('lachenmann.aiff', segmentationFile='marmotTent.txt') # will use a segmentation file called marmotTent.txt, not the default lachenmann.aiff.txt.
csf('lachenmann.aiff', segmentationExtension='-gran.txt') # will use a segmentation file called lachenmann.aiff-gran.txt, not the default lachenmann.aiff.txt.
</code></pre>
</div>
<div id="HowDirectoriesAreRead" class="subgroup"><h4>How Directories Are Read</h4>
The following csf() keyword arguments are useful when dealing with directories of files.
<ul>
<li><b>wholeFile</b> - if True AudioGuide will use this soundfile as one single segment. If False, AudioGuide will search for a segmnetation file made with agSegmentSf.py.<pre class="language-python"><code class="language-python">csf('sliced/my-directory', wholeFile=True) # will not search for a segmentation txt file, but use whole soundfiles as single segments.
</code></pre>
<li><b>recursive</b> - if True AudioGuide will include sounds in all subfolders of a given directory.<pre class="language-python"><code class="language-python">csf('/Users/ben/gravillons', wholeFile=True, recursive=False) # will only use soundfiles in the named folder, ignoring its subdirectories.
</code></pre>
<li><b>includeStr</b> - A string which is matched against the filename (not full path) of each soundfile in a given directory. If part of the soundfile name matches this string, it is included. If not it is excluded. This is case sensitive. See example below.<li><b>excludeStr</b> - Opposite of includeStr.<pre class="language-python"><code class="language-python"># includeStr/excludeStr have lots of uses. One to highlight here: working with sample databases which are normalized. Rather than having each corpus segment be at 0dbs, we apply a scaleDb value based on the presence of a ‘dynamic' written into the filename.
csf('Vienna-harpNotes/', includeStr=['_f_', '_ff_'], scaleDb=-6),
csf('Vienna-harpNotes/', includeStr='_mf_', scaleDb=-18),
csf('Vienna-harpNotes/', includeStr='_p_', scaleDb=-30),
# this will use all sounds from this folder which match one of the three dynamics; also see scaleDb='filenamedyn', below.
</code></pre>
</ul>
</div>
<div id="HowSegmentsWillBeConcatenated" class="subgroup"><h4>How Segments Will Be Concatenated</h4>
Below are csf() keywords which influence how sound segments are treated during concatenation.
<ul>
<li><b>scaleDb</b> - applies an amplitude change to each segment of this collection. by default, it is 0, yielding no change. -6 = twice as soft. Note that amplitude scaling affects both the concatenative algorithm and the csound rendering. Also note that scaleDb='filenamedyn' will attempt to scale all sounds in this corpus by finding a dynamic written in the filenames according to DYNAMIC_TO_DECIBEL and FILENAMESTRING_TO_DYNAMICS.<li><b>limitDur</b> - limits the duration of each segment from this csf() entry. The duration of Target and Corpus over this value (in seconds) will be truncated. This happens before concatenation.<li><b>clipDurationToTarget</b> - If True, the duration of any selected sounds from this csf() will be truncated by the duration of the target. This happens after concatenation takes place.<li><b>onsetLen</b> - if onsetLen is a float or integer, it is the fade-in time in seconds. If it is a string formed as ’10%’, it is interpreted as a percent of each segment’s duration. So, onsetLen=0.1 yields a 100 ms. attack envelope while onsetLen=’50%’ yields a fade in over 50% of the segment’s duration.<li><b>offsetLen</b> - Same as onsetLen, but for the envelope fade out.<pre class="language-python"><code class="language-python">csf('lachenmann.aiff', onsetLen=0.1, offsetLen='50%') # will apply a 100ms fade in time and a fade out time lasting 50% of each segments' duration.
</code></pre>
<li><b><a id="midiPitchMethod"></a>midiPitchMethod</b> - this tells AudioGuide how to calculate the descriptor d('MIDIPitch-seg') for each segment in a tsf() or csf() object. Note that this value is important for writing the bach output files, as it determines the displayed pitch of each target and corpus event. It is also important for csf(limit) and csf(pitchfilter). Note that if any of the methods, detailed below, do not find a result, -1 is returned.<ul><li><b>‘f0-seg’</b> - returns the averaged f0 array as the midipitch. Note that it is not power weighted - it is actually the median of f0.<li><b>‘centroid-seg’</b> - returns the power averaged centroid converted into a midipitch.<li><b>‘filename’</b> - looks at the filename of the corpus segment to see if there is a midipitch indicated. Names like A1ShortSeq.wav, Fs1ShortSeq.wav and BP-flatter-f-A\#3.wav work.<li><b>‘composite’</b> - first tries to look for a midipitch in the filename. If not found, then tries ‘f0-seg’.<li><b>float/int</b> - a float or int will set all pitches in this csf() to the midipitch written.<li><b>{'type': 'remap', 'low': 60, 'high': 72, 'method': 'centroid-seg'}</b> - will first determine the pitches in this csf() based on centroid, then remap these values to be between 60 and 70.<li><b>{'type': 'clip', 'low': 60, 'method': 'centroid-seg'}</b> - will first determine the pitches in this csf() based on centroid, then force any pitch below 60 to be 60.<li><b>{'type': 'file_match', 'II': 60, 'IV': 72}</b> - will set the midipitch of any filenames that match 'II' to 60; any that match 'IV' are 72, and all other are determined with the midiPitchMethod composite.</ul><li><b>transMethod</b> - A string indicating how to transpose segments chosen from this corpus entry. You may chose from:<ul><li><b>None</b> - yields no transposition.<li><b>‘random n m’</b> - transposes this segment randomally between midipitch n and m.<li><b>‘f0’</b> - transposes a selected corpus segment to match the f0-seg of the corresponding target segment.<li><b>‘f0-chroma’</b> - transposes a selected corpus segment to match the f0-seg of the corresponding target segment modulo 12 (i.e., matching its chroma).</ul><li><b>transQuantize</b> - Quantization interval for transposition of corpus sounds. 1 will quantize to semitones, 0.5 to quarter tones, 2 to whole tones, etc.<pre class="language-python"><code class="language-python">csf('piano/', transMethod='f0') # transpose corpus segments to match the target's f0.
csf('piano/', transMethod='f0-chroma', transQuantize=0.5) # transpose corpus segments to match the target's f0 mod 12. Then quantize each resulting pitch to the newest quarter of tone.
</code></pre>
<li><b>concatFileName</b> - A string indicating a different soundfile path to use when rending with csound. This means that the first argument of the cps() object is used for soundfile descirptor analysis, but the path found in concatFileName if the soundfile used in the concatenated result. By default, concatFileName is set to the same filename as the first argument of the cps().
<pre class="language-python"><code class="language-python">csf('lachenmann-mono.aiff', concatFileName='lachenmann.stereo.aiff'), # runs the descriptor analysis on lachenmann-mono.aiff, but then uses the audio from lachenmann.stereo.aiff when rendering the csound output.
</code></pre>
<li><b>allowRepetition</b> - If False, any of the segments from this corpus entry may only be picked one time. If True there is no restriction.<li><b>restrictRepetition</b> - A delay time in seconds where, once chosen, a segment from this corpus entry is invalid to be picked again. The default is 0.5, which the same corpus segment from being selected in quick succession.<pre class="language-python"><code class="language-python">csf('piano/', allowRepetition=False) # each individual segment found in this directory of files may only be deleted one time during concatenation.
csf('piano/', restrictRepetition=2.5) # Each segment is invalid to be picked if it has already been selected in the last 2.5 seconds.
</code></pre>
<li><b>restrictOverlaps</b> - An integer specifying how many overlapping samples from this collection may be chosen by the concatenative algorithm at any given moment. So, restrictOverlaps=2 only permits 2 overlapping voices at a time.<li><b>restrictInTime</b> - a time in seconds specifying how often a sample from this entry may be selected. -- for example restrictInTime=0.5 would permit segments from this collection to be select a maximum of once every 0.5 seconds.<li><b>maxPercentTargetSegments</b> - a float as a percentage value from 0-100. This number limits the number of target segments that this corpus entry may be selected. For example, a value of 50 means that this corpus entry is only valid for up to 50% of target segments; after this threshold has been crossed, further selections are not possible. None is the default, which has no effect.<li><b>scaleDistance</b> - Scale the resulting distance when executing a multidimensional search using on segments. scaleDistance=2 will make these sounds twice as ‘far’, and thus less likely to be selected by the search algorithm. scaleDistance=0.25 makes 4 times more likely to be picked.<li><b>superimposeRule</b> - This one is a little crazy. Basically, you can specify when this corpus’s segments can be chosen based on the number of simultaneously selected samples. You do this by writing a little equation as a 2-item list. superimposeRule=(‘==’, 0) says that this set of corpus segments may only be chosen is this is the first selection for this target segment (sim selection ‘0’). superimposeRule=(‘$>$’, 2) say this corpus’s segments are only valid to by picked if there are already more than 2 selections for this target segment. I know, right?<li><b>instrTag</b> - By default, None. If set to a string, this csf() will be linked to an instrument in the score(). E.g. instrTag='tumpet' will permit instr('tumpet') use the segments in this csf(). You may link this csf() to multiple instr()s by using a list: instrTag=['tumpet', 'tombone']<li><b>instrParams</b> - By default, an empty dictionary {}. Use this dictionary to specify notation and behavior of this csf() in the context of writing for instruments with instr(). See a list of all keywords in the <a href="#TheINSTRUMENTSVariable">Instruments</a> section.</ul>
</div>
<div id="Specifyingcsfkeywordsglobally" class="subgroup"><h4>Specifying csf() Keywords Globally</h4>
csf() keywords may be specified globally using the variable CORPUS_GLOBAL_ATTRIBUTES. Note that they are specified in dictionary format rather than object/keyword format.
<pre class="language-python"><code class="language-python">CORPUS = [csf('lachenmann.aiff', scaleDb=-6), csf('piano/', scaleDb=-6, wholeFile=True)]
# is equivalent to
CORPUS_GLOBAL_ATTRIBUTES = {'scaleDb': -6}
CORPUS = [csf('lachenmann.aiff'), csf('piano/', wholeFile=True)]
</code></pre>
</div>
</div>
<h2 id="Normalization">Normalization</h2>
<p>-> <a href="https://www.youtube.com/watch?v=UYElwMFF6Ug&t=18m34s">Watch a related discussion from the AudioGuide Tutorial</a>.</p>
<p>Target segments and corpus segments in AudioGuide are normalized with d() object keywords, documented in the section below.</p>
Normalization is important when measuring the similarity between two different data sets (target sound segments and corpus sound segments) - it is essentially a way of mapping the two data sets onto each other. It is often the case that the target soundfile is less "expressive" than the corpus - i.e. that the variation in the target sound's descriptors are less robust that the variation of the descriptors found across the corpus. </p>
<p>This is the case in examples/01-simplest.py: Cage's voice is fairly monolithic with regard to timbre, amplitude, pitch, etc., which the Lachenmann contains a great deal more nuance in timbre and dynamics. Under these circumstances, what do we want AudioGuide to do? Should Cage's relatively small variation in descriptor space be matched to a relatively small subset of the corpus? Or should Cage's variation in descriptor space be streched to fit the total variation of the corpus? My default answer to this question (aesthetically, compositionally, musically) is the latter. And it is for that reason that AudioGuide's default mode of operating is to normalize target and corpus descirptor spaces separately so that the variability of the target is stretched to fit the variabley of the corpus. </p>
<p>This is done with the norm=2 flag in the d() object (norm=2 is the default value for the d() object); norm=1 normalizes the target and corpus descirptor spaces together so that descriptor values are better preserved. The two charts below show target and corpus segments from examples/01-simplest.py normalized together and separately to show the difference. Normalized descriptor values affect how similarity is measured and therefore which corpus segments will be picked to "match" target segments.</p>
<figure class="figure">
<img src="http://www.benhackbarth.com/audioGuide/docimg/stddev.png" class="figure-img img-fluid rounded" alt="A generic square placeholder image with rounded corners in a figure." width="75%">
<figcaption class="figure-caption">spass('closest', d('centroid-seg'), d('power-seg'))</figcaption>
</figure><figure class="figure">
<img src="http://www.benhackbarth.com/audioGuide/docimg/norm1.png" class="figure-img img-fluid rounded" alt="A generic square placeholder image with rounded corners in a figure." width="75%">
<figcaption class="figure-caption">spass('closest', d('centroid-seg', norm=1), d('power-seg', norm=1))</figcaption>
</figure>
In addition to specifying whether or not target and corpus values are normalized together or separately, you can change the algorithm for normalization. By default, normmethod='stddev', but graphs below show two other possibilities.
<figure class="figure">
<img src="http://www.benhackbarth.com/audioGuide/docimg/minmax.png" class="figure-img img-fluid rounded" alt="A generic square placeholder image with rounded corners in a figure." width="75%">
<figcaption class="figure-caption">spass('closest', d('centroid-seg', normmethod='minmax'), d('power-seg', normmethod='minmax'))</figcaption>
</figure>
<figure class="figure">
<img src="http://www.benhackbarth.com/audioGuide/docimg/sigmoid.png" class="figure-img img-fluid rounded" alt="A generic square placeholder image with rounded corners in a figure." width="75%">
<figcaption class="figure-caption">spass('closest', d('centroid-seg', normmethod='sigmoid'), d('power-seg', normmethod='sigmoid'))</figcaption>
</figure>
However, there are certainly moments when you would want to opt for norm=1. Take the descriptor f0-seg for instance. Given d('f0-seg', norm=1), AudioGuide will attempt to match f0s between the target and corpus as closely as possible. Given d('f0-seg', norm=2), AudioGuide will stretch the target's f0s to match the variablelity of f0s in the corpus, effectively matching the target's contour of pitch but not its exact pitches.
<div id="Descriptorsandthedobject" class="group"><h3>Descriptors and the d() object</h3>
<p>-> <a href="https://www.youtube.com/watch?v=UYElwMFF6Ug&t=3s">Watch a related discussion from the AudioGuide Tutorial</a>.</p>
Use the d() object to specify a descriptor, how it is weighted, and how it is normalized. The d() object takes 1 argument -- the name of the desired descriptor -- and then several optional keywords arguments, detailed below.
<pre class="language-python"><code class="language-python">d('descriptor name', weight=1, norm=2, normmethod='stddev', distance='euclidean', energyWeight=False)
</code></pre>
<ul>
<li><b>descriptor name</b> - a string of the name of the desired descriptor. Note that most (but not all) descriptors have both a time varying version as well as a power-weighted averaged version (‘-seg’). All possible descriptors are listed in <a href="#Appendix1Descriptors">Appendix 1</a>.<li><b>weight</b> - How to weight this descriptor in relation to other descriptors.<pre class="language-python"><code class="language-python">SEARCH= [spass('closest', d('centroid', weight=1), d('noisiness', weight=0.5))]# centroid is twice as important as noisiness.
</code></pre>
<li><b>norm</b> - A value of 2 normalizes the target and corpus data separately. A value of 1 normalizes the target and corpus data together. 2 will yield a better rendering of the target’s morphological contour. 1 will remain more faithful to concrete descriptor values. I recommend using 2 by default, only using 1 when dealing with very ‘descriptive’ descriptors like duration or pitch.
<pre class="language-python"><code class="language-python">SEARCH = [spass('closest', d('centroid'), d('effDur-seg', norm=1))]
</code></pre>
<li><b>normmethod</b> - How to normalize data -- either ‘stddev’ or ‘minmax’. minmax is more precise, stddev is more forgiving of ‘outliers.’<li><b>distance</b> - Only valid for time-varying descriptors. How to arithmetically measure distance between target and corpus arrays.<ul>
<li><b>‘euclidean’</b> - does a simple least squares distance.<li><b>‘pearson’</b> - a pearson correlation measurement.<li><b>‘dtw’</b> - distance measurement according to dynamic time warping.</ul>
<pre class="language-python"><code class="language-python">SEARCH = [spass('closest', d('centroid', distance='pearson'))] # uses a pearson correlation formula for determining distance between target and corpus centroid arrays.
</code></pre>
<li><b>energyWeight</b> - Only valid for time-varying descriptors. Weight distance calculations with the corpus segments’ energy values. The means that softer frames will not affect distance as much as louder frames. Only works if distance=‘euclidean’.</ul>
</div>
<div id="SEARCHvariable" class="group"><h3>SEARCH variable and spass() object</h3>
<p>-> <a href="https://www.youtube.com/watch?v=UYElwMFF6Ug&t=653s">Watch a related discussion from the AudioGuide Tutorial</a>.</p>
<p>The SEARCH variable tells AudioGuide how to pick corpus segments to match target segments. The SEARCH variable is a list of spass() objects which is evaluated in order for each segment in the target soundfile. Multiple search operations are chained together -- the output of each spass() becomes the input of the following spass().</p>
<pre class="language-python"><code class="language-python">SEARCH = [
spass(...), # first spass. the input is all valid corpus samples
spass(...), # second spass. the input is the output from the previous spass
]
</code></pre>
<p>The idea here is make a very flexible searching method where the user can create multiple search passes based on different descriptor criteria. The first argument of spass(), its 'method', is a string which denotes the type of search - i.e. how target and corpus segments are compared. A summary of different methods are listed below:</p>
<ul><li><b>closest</b> - picks the best matching corpus sound according to one of more descriptors.<li><b>farthest</b> - picks the worst matching corpus sound according to one of more descriptors.<li><b>closest_percent</b> - returns a percentage of the best matching corpus sounds according to one of more descriptors.<li><b>farthest_percent</b> - returns a percentage of the worst matching corpus sounds according to one of more descriptors.<li><b>ratio_limit</b> - returns any corpus sounds if, for a given descriptor, the ratio of the target segment/corpus segment falls within certain user specified limits.<li><b>parser</b> - Structured as an if-then-else, this method toggles between two different actions depending on a whether a taget segment's descriptor passes a test. </ul>
<p>spass() objects with the method <b>closest</b> return the single best matching corpus sound according to a list descriptor objects. This spass() objects should only be used as the last (or only) item of the SEARCH list.</p>
<pre class="language-python"><code class="language-python">spass('closest', d('centroid')) # pick the best matching corpus sound according to time-varying centroids
spass('closest', d('centroid'), d('mfccs-seg'), d('zeroCross-delta')) # pick the best matching corpus sound according to the equally weighted distances of centroid, segments mffcs, and first order zeroCross.
</code></pre>
<p>spass() objects with the method <b>closest_percent</b> return a percentage of the best matching corpus samples based on a list of descriptors. The keyword 'percent' is required.</p>
<pre class="language-python"><code class="language-python">spass('closest_percent', d('power-seg'), d('effDur-seg', norm=1), percent=10) # let the best matching 10 percent of courpus sounds through this pass according to averaged power and effective duration.
</code></pre>
<p>Note that if 'closest_percent' is the last (or only) entry in the SEARCH list, the final segment is randomly chosen among remaining corpus sounds.</p>
<p>spass() objects with the method <b>ratio_limit</b> use a single segmented descriptor and divide the targe value by each corpus value. Only corpus samples whose ratio is within the specified limits (keywords minratio and maxratio) are allowed to pass. If either the upper or lower limit is omitted, is has no effect.</p>
<pre class="language-python"><code class="language-python">spass('ratio_limit', d('effDur-seg'), minratio=0.9, maxratio=1.1) # let through corpus sounds if the ratio of target duration/corpus duration is between 0.9 to 1.1.
</code></pre>
<p>Note that ratio_limit only works with one segmented descriptor. It uses unnormalized descriptor values so that, in the case of the above example, the ratio is obtained by dividing the target segment's effDur by the corpus segment's effDur.</p>
<p>The <b>parser</b> spass() method toggles between two different actions depending on a whether each taget segment passes a test.
Each spass() has the following parameters:</p>
<pre class="language-python"><code class="language-python">spass('parser', test, submethod, ifTrue, ifFalse)
</code></pre>
<ul><li><b>test</b> - a string which is a boolean test of a target segment's segmented descriptor. e.g. 'power-seg > 0.1'<li><b>submethod</b> - a string denoting the type of operation to perform - possibilities are <b>closest</b>, <b>closest_percent</b>, and <b>corpus_select</b><li><b>ifTrue</b> - a list of items to perform if ‘test’ is True.<li><b>ifFalse</b> - a list of items to perform if ‘test’ is False. </ul>
<p>The first two submethods behave exactly like those outlined above. For instance:</p>
<pre class="language-python"><code class="language-python">spass('parser', 'closest', 'effDur-seg > 0.4', [d('zeroCross')], [d('zeroCross-delta')]) # if a target segment is less than 0.4 second long, pick the best corpus sound according to zeroCrossings; otherwise pick the best sound according to the first order difference of zeroCrossings
spass('parser', 'f0-seg == 0', 'closest_percent', [d('f0')], [d('mfccs-seg')], percent=10) # if f0-seg equals 0, return the closest 10 percent of matches to f0; otherwise return the 10 percent best matches according to mfccs-seg
spass('parser', 'closest', 'noisiness-seg >= 50%', [d('mfccs-seg')], [d('f0')]) # if this target segment's noisiness is in the upper 50 percentile among all target segments, return the best matching corpus sound according to mfccs; other use f0.
</code></pre>
<p>The third method, <b>corpus_select</b>, uses the target descriptor test to determine which items of the CORPUS list are valid:</p>
<pre class="language-python"><code class="language-python">spass('parser', 'effDur-seg > 0.4', 'corpus_select', [0], [1, 2]) # if the effective duration is less that 0.4 seconds, use corpus samples from arguemnt 1 of the corpus list; otherwise used samples from argument 2 and 3.
</code></pre>
<div id="SEARCHvariable_examples"><h4>Contextual Examples</h4>
<p>Here is the most simple case of a SEARCH variable:</p>
<pre class="language-python"><code class="language-python">SEARCH = [spass('closest', d('centroid'))] # will search all corpus segments and select the one with the ‘closest' time varying centroid to the target segment.
</code></pre>
<p>You may list as many descriptors are you want. The selected sample will be an average of all descriptors listed.</p>
<pre class="language-python"><code class="language-python">SEARCH = [spass('closest', d('centroid'), d('effDur-seg'))] # will search all corpus segments and select the one with the ‘closest' centroid and effective duration compared to the target segment.
</code></pre>
<p>If you use ‘closest_percent’ as the one and only spass object in the SEARCH variable, AudioGuide will select a corpus segment randomly among the final candidates.</p>
<pre class="language-python"><code class="language-python">SEARCH = [spass('closest_percent', d('centroid'), percent=20)] # pick randomally between the top 20 percent best matches.
</code></pre>
<p>However, you can also 'chain' spass objects together, essentially constructing a hierarchical search algorithm. So, for example, take the following SEARCH variable with two separate phases:</p>
<pre class="language-python"><code class="language-python">SEARCH = [
spass('closest_percent', d('effDur-seg'), percent=20), # take the best 20% of matches from the corpus
spass('closest', d('mfccs')), # now find the best matching segment from the 20 percent that remains.
]
</code></pre>
<p>I use the above example a lot when using AudioGuide. It first matches effDur-seg, the effective duration of the target measured agains’t the effective duration of each corpus segment. It retains the 20% closest matches, and throws away the worst 80%. Then, with the remaining 20%, the timbre of the sounds are matched according to mfccs.</p>
<pre class="language-python"><code class="language-python">SEARCH = [
spass('ratio_limit', d('f0-seg'), minratio=0.943, maxratio=1.059),# only let through corpus samples that are within +/-1 semitone of the target segment's f0
spass('closest', d('mfccs')), # now find the best matching segment according to timbre
]
</code></pre>
<p>To help the user understand how different spasses are functioning, the log.html file, created by default, contains a table in the concatenation section which shows information about the size of the corpus through each spass for each target segement search. The following is the table created for examples/09-parseSearch.py. For each pass, the size of the corpus is shown before and after the spass() operation. When a 'parser' spass() is used, the result of the boolean test is shown as well.</p>
<table border="1"><tr><th>time x overlap</th><th>spass #1: closest_percent</th><th>spass #2: parser</th><th>spass #3: closest</th></tr><tr><td>1.46x1</td><td>252 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>4.74x1</td><td>252 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>7.82x1</td><td>252 -> 50</td><td>True 50 -> 10</td><td>10 -> 1</td></tr><tr><td>0.26x1</td><td>252 -> 50</td><td>True 50 -> 10</td><td>10 -> 1</td></tr><tr><td>1.10x1</td><td>251 -> 50</td><td>True 50 -> 10</td><td>10 -> 1</td></tr><tr><td>5.17x1</td><td>251 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>6.83x1</td><td>252 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>9.47x1</td><td>252 -> 50</td><td>True 50 -> 10</td><td>10 -> 1</td></tr><tr><td>4.34x1</td><td>251 -> 50</td><td>True 50 -> 10</td><td>10 -> 1</td></tr><tr><td>4.49x1</td><td>250 -> 50</td><td>True 50 -> 10</td><td>10 -> 1</td></tr><tr><td>8.53x1</td><td>252 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>0.68x1</td><td>250 -> 50</td><td>True 50 -> 10</td><td>10 -> 1</td></tr><tr><td>6.42x1</td><td>251 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>10.28x1</td><td>252 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>7.28x1</td><td>251 -> 50</td><td>True 50 -> 10</td><td>10 -> 1</td></tr><tr><td>6.13x1</td><td>251 -> 50</td><td>True 50 -> 10</td><td>10 -> 1</td></tr><tr><td>7.08x1</td><td>250 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>8.93x1</td><td>251 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>10.53x1</td><td>251 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>8.34x1</td><td>251 -> 50</td><td>False 50 -> 10</td><td>10 -> 1</td></tr><tr><td>7.62x1</td><td>250 -> 50</td><td>True 50 -> 10</td><td>10 -> 1</td></tr></table>
</div>
</div>
<div id="TheSUPERIMPOSEvariabls" class="group"><h3>The SUPERIMPOSE variable and si() object</h3>
<p>-> <a href="https://www.youtube.com/watch?v=V3MgfbaDi9I&t=288s">Watch a related discussion from the AudioGuide Tutorial</a>.</p>
Use the si() object for specifying how corpus segments may be superimposed during concatenation.
<script src="https://gist.github.com/benhackbarth/55094b21330b6cb11e8203a8bb152a95.js"></script>
<ul>
<li><b>minSegment</b> - The minimum number of corpus segments that must be chosen to match a target segment.<li><b>maxSegment</b> - The maximum number of corpus segments that must be chosen to match a target segment.<li><b>minFrame</b> - The minimum number of corpus segments that must be chosen to begin at any single moment in time.<li><b>maxFrame</b> - The maximum number of corpus segments that must be chosen to begin at any single moment in time.<li><b>minOverlap</b> - The minimum number of overlapping corpus segments at any single moment in time. Note that an ‘overlap’ is determined according to an amplitude threshold -- see overlapAmpThresh.<li><b>maxOverlap</b> - The maximum number of overlapping corpus segments at any single moment in time. Note that an ‘overlap’ is determined according to an amplitude threshold -- see overlapAmpThresh.<li><b>searchOrder</b> - (‘power’ or ‘time’) The default is ‘time’, which indicated to match corpus segments to target segments in the temporal order of the target (i.e., first searched segment is the first segment in time). ‘power’ indicates to first sort the target segments from loudest to softest, then search for corpus matches.<li><b>calcMethod</b> - A None/string which denotes how to audioguide should account for selected corpus sounds that overlap. By default, it is 'mixture'. Note that not all descriptors can be algorithnmically mixed, e.g. f0, zeroCross. More information in <a href='https://www.youtube.com/watch?v=V3MgfbaDi9I&t=1026s'>this tutorial video clip</a>.<ul><li><b>None</b> - No accounting for previously selected corpus sounds. Each selected sound is unaware of previous selections.<li><b>‘subtract’</b> - subtracts a selected corpus sound's amplitude from the target segment's amplitude.<li><b>‘mixture’</b> - performs 'subtract', then attempts to mix descriptors of previously selected corpus sound together inform the next corpus selection.</ul><li><b>subtractScale</b> - A float/int/string which denotes how much of a corpus sound's amplitude to subtract from the target. By default it is 1; a value of 0.5 will scale corpus semgment amplitudes by 0,5 before subtracting them from the target. This variable is only meaningful if si(calcMethod='subtract') or si(calcMethod='mixture'). More information in <a href='https://www.youtube.com/watch?v=V3MgfbaDi9I&t=1026s'>this tutorial video clip</a>.<ul><li><b>float/int</b> - Scale the amplitude of corpus sounds by this number when subtracting them from the target.<li><b>‘automedian’</b> - use the median of target and corpus segment amplitudes to determine the amount to scale subtraction.<li><b>‘automax’</b> - use the maximum of target and corpus segment amplitudes to determine the amount to scale subtraction.</ul></ul>
</div>
<div id="ConcatenationOutputFiles" class="subgroup"><h4>Concatenation Output Files</h4>
<p>For each of the following _FILEPATH variables, a value of None tells the agConcatenate.py NOT to create an output file. Otherwise a string tells agConcatenate.py to create this output file and also indicates the path of the file to create. Strings may be absolute paths. If a relative path is given, AudioGuide will create the file relative to the location of the agConcatenate.py script.</p>
<p>Pro tip: You can also use the special string '$TIME' in any output file path to automatically insert the current time stamp into output filenames. This keeps audioguide from overwriting files from previous agConcatenate.py runs. See examples/07-outputfiles.py for details.</p>
<pre class="language-python"><code class="language-python">CSOUND_RENDER_FILEPATH = 'output/$TIME-output.wav' # will create the file output/YYYY-MM-DD_hh-mm-ss-output.wav with the current time
</code></pre>
<p><b>CSOUND_CSD_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/output.csd’</span>) creates an output csd file for rendering the resulting concatenation with csound. See additional csound options <a href="#CsoundOutput">here</a>.</p><p><b>CSOUND_RENDER_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/output.aiff’</span>) sets the sound output file in the CSOUND_CSD_FILEPATH file. This is the name of csound’s output soundfile and will be created at the end of concatenation. See additional csound options <a href="#CsoundOutput">here</a>.</p><p><b>CSOUND_SCORE_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) writes a simple textfile in the csound score format.</p><p><b>BACH_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/bach_roll.txt’</span>) Gathered syntax for concatenation selections that you can load into a bach.roll. See maxmsp/bach/main.maxpat for usage. See additional bach options <a href="#BachOutput">here</a>.</p><p><b>AAF_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) Create an Advanced Authoring Format file for loading into Logic/Pro Tools. See additional aaf options <a href="#AafOutput">here</a>.</p><p><b>RPP_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) Create a .rpp file for loading into Reaper. See additional Reaper options <a href="#RppOutput">here</a>.</p><p><b>HTML_LOG_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/log.html’</span>) a log file with lots of information from the concatenation algorithm.</p><p><b>COPY_OPTIONS_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) Makes a copy of the options file that you're using so that you can remember how to recreate this output.</p><p><b>OUTPUT_LABEL_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/outputlabels.txt’</span>) Audacity-style labels showing the selected corpus sounds and how they overlap.</p><p><b>LISP_OUTPUT_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/output.lisp.txt’</span>) a textfile containing selected corpus events as a lisp-style list.</p><p><b>DICT_OUTPUT_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/output.json’</span>) a textfile containing selected corpus events in json format.</p><p><b>MAXMSP_OUTPUT_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/output.maxmsp.json’</span>) a textfile containing a list of selected corpus events. Data includes starttime in MS, duration in MS, filename, transposition, amplitude, etc.</p><p><b>TARGET_SEGMENT_LABELS_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/targetlabels.txt’</span>) Audacity-style labels showing how the target sound was segmented.</p><p><b>TARGET_SEGMENTATION_GRAPH_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) like TARGET_SEGMENT_LABELS_FILEPATH, this variable creates a file to show information about target segmentation. Here however, the output is a jpg graph of the onset and offset times and the target’s power. This output requires you to install python’s module matplotlib.</p><p><b>TARGET_DESCRIPTORS_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) saves the loaded target descriptors to a json dictionary.</p><p><b>TARGET_PLOT_DESCRIPTORS_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) creates a plot of each target descriptor used in concatenation. Doesn’t create plots for averaged descriptors (“-seg”), only time varying descriptors.</p><p><b>DATA_FROM_SEGMENTATION_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) This file lists all of the extra data of selected events during concatenation. This data is taken from corpus segmentation files, and includes everything after the startTime and endTime of each segment. This is useful if you want to tag each corpus segment with text based information for use later.</p>
</div>
<div id="CsoundOutput" class="subgroup"><h3>Csound Output</h3>
<p>-> <a href="https://www.youtube.com/watch?v=WoLNX2XWemQ&t=251s">Watch a related discussion from the AudioGuide Tutorial</a>.</p>
<p>AudioGuide concatenations are rendered with csound by default. The resulting audiofile is also played back at the command line by default.</p>
<p><b>CSOUND_CSD_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/output.csd’</span>) creates an output csd file for rendering the resulting concatenation with csound.</p><p><b>CSOUND_RENDER_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/output.aiff’</span>) sets the sound output file in the CSOUND_CSD_FILEPATH file. This is the name of csound’s output soundfile and will be created at the end of concatenation.</p><p><b>CSOUND_SCORE_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) writes a simple textfile in the csound score format.</p><p><b>CSOUND_SR</b> (type=<span style="color:red">int</span>, default=<span style="color:green">48000</span>) The sample rate used for csound rendering. Csound will interpolate the sample rates of all corpus files to this rate. It will be the sr of csound’s output soundfile.</p><p><b>CSOUND_BITS</b> (type=<span style="color:red">int</span>, default=<span style="color:green">16</span>) The bitrate of the csound output soundfile. Valid values are 16, 24, and 32.</p><p><b>CSOUND_KSMPS</b> (type=<span style="color:red">int</span>, default=<span style="color:green">128</span>) The ksmps value used for csound rendering. See csound’s documentation for more information.</p><p><b>CSOUND_NORMALIZE</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">False</span>) If True normalize csound's output soundfile after rendering.</p><p><b>CSOUND_NORMALIZE_PEAK_DB</b> (type=<span style="color:red">float</span>, default=<span style="color:green">-3</span>) If CSOUND_NORMALIZE is True, normalization of this peak dB will take place.</p><p><b>CSOUND_PLAY_RENDERED_FILE</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">True</span>) if True, AudioGuide will play the rendered csound file at the command line at the end of the concatenative algorithm.</p><p><b>CSOUND_STRETCH_CORPUS_TO_TARGET_DUR</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) Affects the durations of concatenated sound events rendered by csound.</p><ul><li><b>None</b> - Playback speed unchanged.<li><b>pv</b> - Uses a phase vocoder to stretch corpus sounds to match the duration of the corresponding target segments.<li><b>transpose</b> - Uses the speed of playback to change duration to match corresponding target segments. Note that, in this case, any other transposition information generated by the selection algorithm is overwritten (e.g. csf(pitchfilter=), csf(transmethod=).</ul><p><b>CSOUND_CHANNEL_RENDER_METHOD</b> (type=<span style="color:red">string</span>, default=<span style="color:green">corpusmax</span>) Tells AudioGuide how assign the channel of corpus segments in the csound output soundfile. The default is “corpusmax”.</p><ul><li><b>corpusmax</b> - Creates an output soundfile with the same number of channels as the maxmimum of all corpus files (corpus files may have different channel counts).<li><b>stereo</b> - Mixes all corpus sounds into a 2-channel soundfile.<li><b>targetoutputmix</b> - Makes a simple stereo output where the target is in channel 1 and the corpus sounds are in channel 2.<li><b>oneChannelPerVoice</b> - Tells AudioGuide to put selected sounds from each item of the CORPUS list into a separate channel. The number of output channels will therefore equal the length of the CORPUS list variable.<li><b>oneChannelPerOverlap</b> - Tells AudioGuide to put overlapping selected sounds into different channels so that only one sound is happening in a given channel at any one time. The number of channels will be equal the maximum number of overlapping sounds in the concatenation.<li><b>oneChannelPerInstrument</b> - Tells AudioGuide to put selected sounds from each instrument into a separate channel. This only works when using INSTRUMENTS.</ul></div>
<div id="AafOutput" class="subgroup"><h3>Logic/Pro Tools Output</h3>
<p>-> <a href="https://www.youtube.com/watch?v=rHQI-jXd6iU&t=0s">Watch a related discussion from the AudioGuide Tutorial</a>.</p>
<p>As of version 1.7, AudioGuide concatenations can be written to .aaf files and opened in Logic/Pro Tools. See examples/11-dawOutput.py</p>
<p><b>AAF_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) Create an Advanced Authoring Format file for loading into Logic/Pro Tools.</p><p><b>AAF_INCLUDE_TARGET</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">False</span>) If True, adds the target soundfile to the Advanced Authoring Format output.</p><p><b>AAF_CPSTRACK_METHOD</b> (type=<span style="color:red">string</span>, default=<span style="color:green">'cpsidx'</span>) A string specifying how to write selected corpus sounds into Advanced Authoring Format tracks. By default it is 'cpsidx'</p><ul><li><b>cpsidx</b> - Puts corpus sounds into AAF tracks according to their idx in the CORPUS list and their channel count.<li><b>minimum</b> - Mixes all corpus sounds into a minimal number of AAF tracks.</ul><p><b>AAF_AUTOLAUNCH</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">False</span>) If True, AudioGuide will automatically try to open the AAF file after it has been written. This is equivalent to double clicking the file in OSX.</p></div>
<div id="RppOutput" class="subgroup"><h3>Reaper Output</h3>
<p>As of version 1.71, AudioGuide concatenations can be written to .rpp files and opened in reaper. Unlike the aaf output, reaper files capture csf() sound envelopes, csf(scaleDb), and corpus sound transpositions. See examples/11-dawOutput.py.</p>
<p><b>RPP_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) Create a Reaper output file.</p><p><b>RPP_INCLUDE_TARGET</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">False</span>) If True, adds the target soundfile to the rpp file.</p><p><b>RPP_CPSTRACK_METHOD</b> (type=<span style="color:red">string</span>, default=<span style="color:green">'cpsidx'</span>) A string specifying how to write selected corpus sounds to reaper tracks. By default it is 'cpsidx'</p><ul><li><b>cpsidx</b> - Puts corpus sounds into RPP tracks according to their idx in the CORPUS list and their channel count.<li><b>minimum</b> - Mixes all corpus sounds into a minimal number of RPP tracks.</ul><p><b>RPP_TRANS_AFFECTS_SPEED</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">True</span>) If True, AudioGuide will tell Reaper to render corpus sound transposition with a speed change. If False, Reaper will preserve the original speed of the corpus sound.</p><p><b>RPP_AUTOLAUNCH</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">False</span>) If True, AudioGuide will automatically try to open the RPP file after it has been written. This is equivalent to double clicking the file in OSX.</p></div>
<div id="BachOutput" class="group"><h3>Bach Output</h3>
<p>-> <a href="https://www.youtube.com/watch?v=WoLNX2XWemQ&t=1006s">Watch a related discussion from the AudioGuide Tutorial</a>.</p>
<p>Audioguide automatically creates an output file for every concatenation that may be loaded into a bach.roll in Max/MSP. The path for the bach output file, which is output/bach_roll.txt by default, is controlable by the BACH_FILEPATH variable. You may visualize, explore, and playback concatenated sounds with the patch maxmsp/bach/bach_playback.maxpat. You may also add descriptor data to Bach slots; see BACH_SLOTS_MAPPING below for details.</p>
<p>The options below give a few controls over how the output of a concatenation can be translated into a bach.roll input:</p>
<p><b>BACH_FILEPATH</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">‘output/bach_roll.txt’</span>) Gathered syntax for concatenation selections that you can load into a bach.roll. See maxmsp/bach/main.maxpat for usage.</p><p><b>BACH_INCLUDE_TARGET</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">True</span>) if True, the target soundfile will be included as the first voice in bach_roll.txt.</p><p><b>BACH_DB_TO_VELOCITY_BREAKPOINTS</b> (type=<span style="color:red">list of ints or floats</span>, default=<span style="color:green">[-80, 0, -0, 127]</span>) Breakpoint-style mapping of each target and corpus segment's loudness in dB into a velocity for the bach score. The default list will map linearly from -80 to 0dB onto 0 to 127 in midi velocity (sounds below -80dB will be clipped to velocity 0). Loudness in dB takes csf(scaleDb) into account. However you can specify additional breakpoints in pairs: e.g. [-80, 0, -60, 100, -0, 127].</p><p><b>BACH_TARGET_STAFF</b> (type=<span style="color:red">string</span>, default=<span style="color:green">F</span>) The clef used for the target sound.</p><p><b>BACH_CORPUS_STAFF</b> (type=<span style="color:red">string</span>, default=<span style="color:green">FG</span>) The clef used for corpus sounds.</p></div>
<div id="TheINSTRUMENTSVariable" class="group"><h3>Using Bach to Create Notated Scores</h3>
<p>-> <a href="https://www.youtube.com/watch?v=AyD_ZYjff2c&t=0s">Watch a related discussion from the AudioGuide Tutorial</a>.</p>
<p>AudioGuide's INSTRUMENTS infrastructure lets you restrict the way that elements of corpus can be used during concatenation to create playable instrument parts. These parts may be viewed, edited, and then quantized with Bach in Max/MSP. INSTRUMENTS and its associated objects, score() and instr(), permit corpus resources to be translated into symbolic notation with a high degree of precision and customization through the addition of text, articulation, noteneads. INSTRUMENTS provides a variety of controls for creating idiomatic, playable parts through restricting CORPUS selection according to pitch, playing techniques, and polyphony.</p>
<div id="scoreVariable" class="subgroup"><h4>score() and instr()</h4>
The score() object is assigned to 'INSTRUMENTS' in the options file. score() consists of a list of instru() objects, each of which represents an instrument in the output score. instr()s are linked to cps() entries through their first argument, the instrTag string.</p>
<script src="https://gist.github.com/benhackbarth/313c1c04553c28fef427c72c49a45606.js"></script>
<p>score() may have multiple instr()s with the same instrTag; this indicates that there are more than one of a certain type of instrument in the ensemble that can use the same corpus resources.</p>
<script src="https://gist.github.com/benhackbarth/6936266f5db3da8a1b3f5174a6b994a4.js"></script>
<p>As seen above with 'clef', the instr() object has keywords that affect the instrument's behavoir and how the instrument is translated into musical notation.</p>
<pre class="language-python"><code class="language-python">instr('instrTag', temporal_mode='sus', minspeed=0.075, minpitch=None, maxpitch=None, interval_limit_breakpoints=[], interval_limit_range_per_sec=None, pitched=True, polyphony_max_voices=1, polyphony_max_range=None, polyphony_min_range=None, polyphony_permit_unison=False, polyphony_include_intervals=[], polyphony_exclude_intervals=[], polyphony_max_db_difference=4, technique_switch_delay_map=[], clef='G', key='CM'))
</code></pre>
<ul>
<li><b>instrTag*</b> - This instrument's instrTag. Any corpus entries with the same string will be associated with this instrument.<li><b>temporal_mode*</b> - 'sus' by default, which indicates a sustained event.<li><b>minspeed</b> - The minimum distance between adjecent note onsets for this instrument in seconds.<li><b>minpitch</b> - None of a float. None does nothing; a float sets the minimum midi pitch this instrument can play.<li><b>maxpitch</b> - None of a float. None does nothing; a float sets the maximum midi pitch this instrument can play.<li><b>interval_limit_breakpoints</b> - A list. Described in the Handling Pitch section below.<li><b>interval_limit_range_per_sec</b> - None or a number. Described in the Handling Pitch section, below.<li><b>pitched</b> - True of False. True by default, which does nothing. When False, this csf() will ignore any limitations from pitchfilters, interval_limit_breakpoints, and interval_limit_range_per_sec.<li><b>polyphony_max_voices</b> - Maximum voices that may be picked at the same time for this instrument.<li><b>polyphony_max_range</b> - If a number, the maximum interval from the lowest to highest note in a chord in semitones. If None, there is no limit.<li><b>polyphony_min_range</b> - If a number, the minimum interval from the lowest to highest note in a chord in semitones. If None, there is no limit.<li><b>polyphony_permit_unison</b> - If True, unisons may be selected as part of a chord.<li><b>polyphony_include_intervals</b> - By default, an empty list, which does nothing. However, if you add one or more intervals in semitones, polyphonic selections will be limited to the intervals specified. I.e. polyphony_include_intervals=[7] will only permit perfect 5th polyphony.<li><b>polyphony_exclude_intervals</b> - By default, an empty list, which does nothing. However, if you add one or more intervals in semitones, polyphonic selections will not include the intervals specified. I.e. polyphony_exclude_intervals=[7] will not permit perfect 5ths in the polyphony.<li><b>polyphony_minspeed</b> - The minimum allowable time between polyphonic chord onsets in seconds. This works the same way as minspeed, but only applies to polyphonic selections.<li><b>technique_switch_delay_map*</b> - technique_switch_delay_map let's you specify a list of minimum delay times needed to switich form one csf() technique to another. ['tech1', 'tech2', 0.5] = to go from tech1 to tech2, there must be a delay of at least 0.5 seconds. Techniques must be assigned to csf() objects using the instrParams dictionary. See the example in Handling Time below.<li><b>clef*</b> - The clef for this instrument in the bach.roll. Valid values include, 'F', 'G', 'Alto', and 'FG' for a grand staff. See bach's documentation on clefs for more information.<li><b>key*</b> - The key for this instrument in the bach.roll. See bach's documentation on keys for more information.</ul>
<p>Note that almost all instr() keyword arguments may be overridden in individual csf()s through the csf(instrParams={}) dictionary (those which may not be are denoted with an asterisk). In the example below, the arco violin notes have a 0.05 second minspeed and may have 2 voice polyphony. However the pizzicato sounds have a minspeed of 0.2 second and will always be monophonic:</p>
<script src="https://gist.github.com/benhackbarth/9d844dd092a0415e0b12e753aa0d869b.js"></script>
<p>The csf(instrParams={}) dictionary also permits providing information about articulation, noteheads, and text annotation in the output score for individual csf() entries. The list below details the possible keys you can use in csf(instrParams={}):</p>
<li><b>annotation</b> - Adds text into the Bach score for any segment selected from this csf().<li><b>articulation</b> - Adds articuation marks into the Bach score for any segment selected from this csf(). E.g. csf(instrParams={'articulation': 'accent'} will add an accent. The string you write here must one that Bach understands -- see Bach's documentation for a complete list of articulation strings.<li><b>notehead</b> - Uses a custom notehead in Bach score for any segment selected from this csf(). E.g. csf(instrParams={'notehead': 'x'} will use a cross notehead. The string you write here must one that Bach understands -- see Bach's documentation for a complete list of notehead strings.<li><b>technique</b> - Tags all of the segments in this csf() with a user-specified technique for use with instr(technique_switch_delay_map). See more information below.<li><b>dynamics</b> - A list of dynamic indications to use all segments of the csf(). csf() segments will be ordered from softest to loudest, then assigned a dynamic from the list you specify. By default, it is ['pp', 'p', 'mp', 'mf', 'f', 'ff']. Note that, if AudioGuide finds dynamics written into the filenames of your csf segments, it will use those instead.
<script src="https://gist.github.com/benhackbarth/9485c548cf21b6f860120836a4968338.js"></script>
<div id="INSTRUMENTSPitch" class="subgroup"><h4>Handling Pitch</h4>
<p>The pitches that make it into the bach.roll come from selected corpus segment's MIDIPitch. You can change how midi pitch is evalutated with the csf(midiPitchMethod) keyword. By default, it is 'composite', which first searches for a midi pitch written into the filename of each corpus sound. If no pitch is found, midi pitch is taken from f0-seg. Generally, it is best to use sample databases with pitches in the filenames, as f0-seg is not very reliable. For unpitched sounds, or databases without pitches written into the filenames, you can customize the pitch data by picking a different csf(midiPitchMethod).</p>
<script src="https://gist.github.com/benhackbarth/ef3ce9cc10ac4ccba655117b491006a8.js"></script>
<p>There are several nuanced controls for specifying how pitch may move over time. Consider, first, the unrestricted pitch selection of a solo violin concatenation:</p>
<script src="https://gist.github.com/benhackbarth/8f96600914a35a8967114a29d2a2e144.js"></script>
<figure class="figure">
<img src="http://www.benhackbarth.com/audioGuide/docimg/violin_1.png" class="figure-img img-fluid rounded" alt="A generic square placeholder image with rounded corners in a figure." width="75%">
<figcaption class="figure-caption"></figcaption>
</figure>
<p>interval_limit_breakpoints lets the user specify a list of breakpoints for how intervals are restricted over time. In the example below, the breakpoints are given as [(0,7), (1, 24)], which translates to: if the distance between this selection and the end of the last note is 0 second, restrict this intervals choice to 7 semitones. if the distance is 1 second, restrict it to 24 semitones. The algorithm interpolates these breakpoints, so if the distance in seconds is 0.5, the restriction interval will be 15.5 semitones. You must have at least 2 breakpoints, and the first time difference must be zero, but you have have additional breakpoints if you want. Any note distances greater than the biggest time difference found in interval_limit_breakpoints (in this example, 1 second), any interval is possible. This also works for polyphony.</p>
<script src="https://gist.github.com/benhackbarth/b868f9394330923eeee38c11d31003b6.js"></script>
<figure class="figure">
<img src="http://www.benhackbarth.com/audioGuide/docimg/violin_2.png" class="figure-img img-fluid rounded" alt="A generic square placeholder image with rounded corners in a figure." width="75%">
<figcaption class="figure-caption"></figcaption>
</figure>
<p>interval_limit_range_per_sec restricts what pitches may be selected for an instrument by limiting the total range of pitch for any given second to a number of semitones. Below, the violin is restricted to a 3 semitones total range for any one second slice of it's part. This also works for polyphony.</p>
<script src="https://gist.github.com/benhackbarth/309dd5fec357a8949ae0f103674298c7.js"></script>
<figure class="figure">
<img src="http://www.benhackbarth.com/audioGuide/docimg/violin_3.png" class="figure-img img-fluid rounded" alt="A generic square placeholder image with rounded corners in a figure." width="75%">
<figcaption class="figure-caption"></figcaption>
</figure>
</div>
<div id="INSTRUMENTSDynamics" class="subgroup"><h4>Handling Dynamics/Volume</h4>
<p>Audioguide puts two different kinds of dynamic information into the bachroll.</p>
<p>The first is in each note's midi velocity. Here, audioguide gives a note's playback volume such so that soundfiles in the bach score can be played back at the same volume heard in audioguide's soundfile output. This value comes from each csf(scaleDb). This means that if you use scaleDb='filenamedyn', you will get the same amplitude scalars in bach's velocity as you audioguide uses internally. This value is dB is also included in slot 13 (see below).</p>
<p>The second set of information is found in the written dynamic values (e.g. f, mp), put into bach's dynamic slot (ag uses the default slot, 20). These strings are obtained, by default, through any dynamics found in the filenames of the samples that are used. For instance, if audioguide picks the sound 'HA_ES_mu_mf_C4.wav', it will automatically be assigned a written dynamic of mf in slot 20. However, if you're using soundfiles in a csf() that do not have dynamics written into the filenames, audioguide will automatically extrapolate a dynamic according to the relative loudness of each sf in the entire csf(). These loudnesses get mapped onto a list of dynamics which, by default, are ['pp', 'p', 'mp', 'mf', 'f', 'ff']. However this can be changed for individual csf()s:</p>
<script src="https://gist.github.com/benhackbarth/fa65c40f1a4867f271dfd058ea473868.js"></script>
</div>
<div id="INSTRUMENTSTime" class="subgroup"><h4>Handling Time</h4>
<p>Audioguide provides methods in the instruments interface for controlling how instr()s behave in time.</p>
<p>minspeed and polyphony_minspeed are the most basic, brute-force controls, dictating the minimum time in seconds between sucessive onsets for an instrument.</p>
<p>instr(temporal_mode) is very important to telling audioguide how to treat selected events for an instrument with regard to minspeed and polyphony_minspeed. If instr(temporal_mode='sus'), all selected corpus sounds will be treated as sustained events, and minspeed will be restricted by the start time and stop time of a selected note. If instr(temporal_mode='artic'), all selected corpus sounds will be treated as duration-less, and minspeed will only use a note's start time to restrict density.</p>
<p>instr(technique_switch_delay_map) let's you specify a minimum delay time for AudioGuide1.79 to enforce when switching from one type of playing technique to another. This is specified in 3-item lists in the format of ('technique 1, 'technique 2', delay time in seconds). This takes effect on csf() segments which are tagged with techniques in the instrParams dict; csf()s which are not tagged will not be affected. A CORPUS can have as many techniques as desired, and technique_switch_delay_map can contain as many three item lists as needed.</p>
<script src="https://gist.github.com/benhackbarth/f90f00bd101d6e45eef973287ae4b73e.js"></script>
</div>
<div id="INSTRUMENTSSlots" class="subgroup"><h4>Slot Data</h4>
Data from the concatenative process is automatically added to the BACH_FILEPATH textfile and can be accessed via Bach's slots infrastructure. The table below summarizes the data that AudioGuide puts into different Bach slots by default.
<table class="table-striped table-condensed">
<tr><th>Keyword</th><th>Default Bach Slot Number</th><th>Description</th><th>Valid For</th></tr>
<tr><td>fullpath</td><td>1</td><td>This note's full path.</td><td>Target and Corpus</td></tr>
<tr><td>sfskiptime</td><td>2</td><td>This note's filename's skip time in the file in milliseconds.</td><td>Target and Corpus</td></tr>
<tr><td>sfchannels</td><td>3</td><td>This note's filename's number of channels</td><td>Target and Corpus</td></tr>
<tr><td>env</td><td>4</td><td>This note's amplitude envelope as a bach function. Combines csf(scaleDb), csf(onsetLen), and csf(offsetLen)</td><td>Target and Corpus</td></tr>
<tr><td>transposition</td><td>5</td><td>This note's corresponding transposition from the concatenative process in semitones.</td><td>Target and Corpus</td></tr>
<tr><td>selectionnumber</td><td>6</td><td>For the corpus: this note's selection number in the concatenative process. If 0, it was the first sound picked for the target segment in question. For a target segment: the total number of sounds selected.</td><td>Target and Corpus</td></tr>
<tr><td>instr_dynamic</td><td>20</td><td>This chord/note's dynamics. By default, these are taken from the filename of the selected sounds (C4-mf-IV.wav will have a dynamic of mf)</td><td>Corpus with InstrTag</td></tr>
<tr><td>instr_articulation</td><td>22</td><td>This note/chord's articulation taken from the csf(instrParams) dictionary, e.g. csf(instrParams={'articulation': 'staccato'})</td><td>Corpus with InstrTag</td></tr>
<tr><td>instr_notehead</td><td>23</td><td>This note/chord's notehead taken from the csf(instrParams) dictionary, e.g. csf(instrParams={'notehead': 'cross'})</td><td>Corpus with InstrTag</td></tr>
<tr><td>instr_annotation</td><td>24</td><td>this note/chord's annotation text taken from the csf(instrParams) dictionary, e.g. csf(instrParams={'annotation': 'strike_with_hand'})</td><td>Corpus with InstrTag</td></tr>
<tr><td>instr_technique</td><td>25</td><td>This csf()'s technique string from the csf(instrParams) dictionary, e.g. csf(instrParams={'technique': 'pizz'})</td><td>Corpus with InstrTag</td></tr>
<tr><td>instr_temporal_mode</td><td>26</td><td>This csf()'s temporal_mode from the csf(instrParams) dictionary, e.g' csf(instrParams={'temporal_mode': 'artic'})</td><td>Corpus with InstrTag</td></tr>
</table>
However, you can control what data is assigned to which slot and also add descriptor information to Bach's slots. To do this, overwrite the BACH_SLOTS_MAPPING dictionary with your custom settings. You can use and of the Data Keyword's above to access concatenation parameters. Addtionally, you can specify a segmented descriptor name to get descriptor data for the chosen sound. A time-varying descriptor will place a descriptor time series into the slot.
<pre class="language-python"><code class="language-python"># custom slot assignment:
BACH_SLOTS_MAPPING = {1: 'instr_technique', 2: 'fullpath', 3: 'sfskiptime', 10: 'noisiness-seg', 11: 'centroid'}
# this will put each selected sound with an instr's technique, fullpath, and skip time into slots 1-3. Each selected sound's averaged noisiness will be put into slot 10 (as a float) and its time-varying centroid in slot 11 (as a floatlist).
</code></pre>
</div>
</div>
<div id="OtherOptions" class="group"><h3>Other Options</h3>
<div id="DescriptorComputationParameters" class="subgroup"><h4>Descriptor Computation Parameters</h4>
<p><b>DESCRIPTOR_FORCE_ANALYSIS</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">False</span>) if True, AudioGuide is forced to remake all analysis file, even if previously made.</p><p><b>DESCRIPTOR_WIN_SIZE_SEC</b> (type=<span style="color:red">float</span>, default=<span style="color:green">0.04096</span>) the FFT window size of descriptor analysis in seconds. Note that this value gets automatically rounded to the nearest power-of-two size based on IRCAMDESCRIPTOR_RESAMPLE_RATE. 0.04096 seconds = 512 @ 12.5kHz (the default resample rate).</p><p><b>DESCRIPTOR_HOP_SIZE_SEC</b> (type=<span style="color:red">float</span>, default=<span style="color:green">0.01024</span>) the FFT window overlaps of descriptor analysis in seconds. Note that this value gets automatically rounded to the nearest power-of-two size based on IRCAMDESCRIPTOR_RESAMPLE_RATE. Important, as it effectively sets of temporal resolution of AudioGuide. Performance is best when DESCRIPTOR_HOP_SIZE_SEC/DESCRIPTOR_WIN_SIZE_SEC is a whole number.</p><p><b>IRCAMDESCRIPTOR_RESAMPLE_RATE</b> (type=<span style="color:red">int</span>, default=<span style="color:green">12500</span>) The internal resample rate of the IRCAM analysis binary. Important, as it sets the frequency resolution of spectral sound descriptors.</p><p><b>IRCAMDESCRIPTOR_WINDOW_TYPE</b> (type=<span style="color:red">string</span>, default=<span style="color:green">‘blackman’</span>) see ircamdescriptor documentation for details.</p><p><b>IRCAMDESCRIPTOR_NUMB_MFCCS</b> (type=<span style="color:red">int</span>, default=<span style="color:green">13</span>) sets the number of MFCCs to make. When you use the descriptor 'mfccs' if will automatcially be expanded into mfccs1-N where N is IRCAMDESCRIPTOR_NUMB_MFCCS.</p><p><b>IRCAMDESCRIPTOR_F0_MAX_ANALYSIS_FREQ</b> (type=<span style="color:red">float</span>, default=<span style="color:green">5000</span>) see ircamdescriptor documentation for details.</p><p><b>IRCAMDESCRIPTOR_F0_MIN_FREQUENCY</b> (type=<span style="color:red">float</span>, default=<span style="color:green">20</span>) minimum possible f0 frequency.</p><p><b>IRCAMDESCRIPTOR_F0_MAX_FREQUENCY</b> (type=<span style="color:red">float</span>, default=<span style="color:green">5000</span>) maximum possible f0 frequency.</p><p><b>IRCAMDESCRIPTOR_F0_AMP_THRESHOLD</b> (type=<span style="color:red">float</span>, default=<span style="color:green">1</span>) Thresholding of the spectrum in F0 detection.</p><p><b>DESCRIPTOR_DATABASE_SIZE_LIMIT</b> (type=<span style="color:red">float</span>, default=<span style="color:green">1</span>) The maximum size of the analysis database in gigabytes (audioguide/data) that will trigger AudioGuide to delete the oldest analysis files.</p><p><b>DESCRIPTOR_DATABASE_AGE_LIMIT</b> (type=<span style="color:red">float</span>, default=<span style="color:green">7</span>) The minimum age in days of analysis files in the analysis database (audioguide/data) that AudioGuide will delete if the size of the database is over DESCRIPTOR_DATABASE_SIZE_LIMIT gb.</p>
</div>
<div id="Concatenation" class="subgroup"><h4>Concatenation</h4>
<p><b>ROTATE_VOICES</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">False]</span>) if True, AudioGuide will rotate through the list of corpus entries during concatenation. This means that, when selecting corpus segment one, AudioGuide will only search sound segments from the first item of the CORPUS variable. Selection 2 will only search the second, and so on. Corpus rotation is modular around the length of the CORPUS variable. If the corpus only has one item, True will have no effect.</p><p><b>VOICE_PATTERN</b> (type=<span style="color:red">list</span>, default=<span style="color:green">[]</span>) if an empty list, this does nothing. However, if the user gives a list of strings, AudioGuide will rotate through this list of each concatenative selection and only use corpus segments who’s filepath match this string. Matching can use parts of the filename, not necessarily the whole path and it is not case sensitive.</p><p><b>DYNAMIC_TO_DECIBEL</b> (type=<span style="color:red">dict</span>, default=<span style="color:green">{'pp': -50, 'p': -40, 'mp': -34, 'mf': -24, 'f': -20, 'ff': -10}</span>) This variable specifies the default decebel values for dynamic strings used by csf(scaleDb='filenamedyn').</p><p><b>FILENAMESTRING_TO_DYNAMICS</b> (type=<span style="color:red">dict</span>, default=<span style="color:green">{}</span>) User-defined strings for matching soundfile names with dynamics as in DYNAMIC_TO_DECIBEL. E.g. {'really loud': 'ff', 'loudish': 'f'}. Any filenames which match one these partial strings will be assigned the given dynamic, and then the decebel scalar found in DYNAMIC_TO_DECIBEL will be used if scaleDb='filenamedyn'.</p><p><b>OUTPUT_GAIN_DB</b> (type=<span style="color:red">int/None</span>, default=<span style="color:green">None</span>) adds a uniform gain in dB to all selected corpus units. Affects the subtractive envelope calculations and descriptor mixtures as well as csound rendering.</p><p><b>RANDOM_SEED</b> (type=<span style="color:red">int/None</span>, default=<span style="color:green">None</span>) sets the pseudo-random seed for random unit selection. By default a value of None will use the system’s timestamp. Setting an integer will create repeatable random results.</p></div>
<div id="Post-ConcatenationEventManipulation" class="subgroup"><h4>Post-Concatenation Event Manipulation</h4>
<p>These options change selected corpus events <i>after</i> concatenative selection, meaning that they do not affect similarity calculations, but are applied afterwards. At the moment, all of these parameters affect the temporality of the corpus sounds. These parameters affect all output files - csound, midi, json, etc.</p>
<p><b>OUTPUTEVENT_ALIGN_PEAKS</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">False</span>) If True aligns the peak times of corpus segments to match those of the target segments. Thus, every corpus segment selected to represent a target segment will be moved in time such that corpus segment's peak amplitude is aligned with the target segment's.</p><p><b>OUTPUTEVENT_QUANTIZE_TIME_METHOD</b> (type=<span style="color:red">string/None</span>, default=<span style="color:green">None</span>) controls the quantisation of the start times of events selected during concatenation. Note that any quantisation takes place after the application of OUTPUTEVENT_TIME_STRETCH and OUTPUTEVENT_TIME_ADD, as detailed below. This variable has the following possible settings:</p><ul><li><b>None</b> - no quantisation takes place (the default).<li><b>‘snapToGrid’</b> - conform the start times of events to a grid spaced in OUTPUTEVENT_QUANTIZE_TIME_INTERVAL second slices.<li><b>‘medianAggregate’</b> - change each event’s start time to the median start time of events in slices of OUTPUTEVENT_QUANTIZE_TIME_INTERVAL seconds.</ul><p><b>OUTPUTEVENT_QUANTIZE_TIME_INTERVAL</b> (type=<span style="color:red">float</span>, default=<span style="color:green">0.25</span>) defines the temporal interval in seconds for quantisation. If OUTPUTEVENT_QUANTIZE_TIME_METHOD = None, this doesn’t do anything.</p><p><b>OUTPUTEVENT_TIME_STRETCH</b> (type=<span style="color:red">float</span>, default=<span style="color:green">1.</span>) stretch the temporality of selected units. A value of 2 will stretch all events offsets by a factor of 2. Does not affect corpus segment durations.</p><p><b>OUTPUTEVENT_TIME_ADD</b> (type=<span style="color:red">float</span>, default=<span style="color:green">0.</span>) offset the start time of selected events by a value in seconds.</p><p><b>OUTPUTEVENT_DURATION_SELECT</b> (type=<span style="color:red">string</span>, default=<span style="color:green">cps</span>) if 'cps', AudioGuide will play each selected corpus sample according to its duration. if 'tgt', AudioGuide will use the duration of the target segment a corpus segment was matched to to determine its playback duration. 'tgt' may result in clipped corpus sounds.</p><p><b>OUTPUTEVENT_DURATION_MIN</b> (type=<span style="color:red">float/None</span>, default=<span style="color:green">None</span>) Sets a minimum duration for all selected corpus segments. When this variable is a float, the length of each segment's playback will be at least OUTPUTEVENT_DURATION_MIN seconds (unless the soundfile is too short, in which case the duration will be the soundfile's duration). If None is given (the default), no minimum duration is enforced.</p><p><b>OUTPUTEVENT_DURATION_MAX</b> (type=<span style="color:red">float/None</span>, default=<span style="color:green">None</span>) Sets a maximum duration for all selected corpus segments. When this variable is a float, the length of each segment's playback cannot be more than OUTPUTEVENT_DURATION_MAX seconds. If None is given (the default), no maximum duration is enforced.</p></div>
<div id="PrintingInteraction" class="subgroup"><h4>Printing/Interaction</h4>
<p><b>SEARCH_PATHS</b> (type=<span style="color:red">list</span>, default=<span style="color:green">[]</span>) a list of strings, each of which is a path to a directory where soundfile are located. These paths extend the list of search paths that AudioGuide examines when searching for target and corpus soundfiles. The default is an empty list, which doesn’t do anything.</p><p><b>VERBOSITY</b> (type=<span style="color:red">int</span>, default=<span style="color:green">2</span>) affects the amount of information AudioGuide prints to the terminal. A value of 0 yields nothing. A value of 1 prints a minimal amount of information. A value of 2 (the default) prints refreshing progress bars to indicate the progress of the algorithms.</p><p><b>PRINT_SELECTION_HISTO</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">False</span>) if True will print robust information about corpus selection after concatenation. If false (the default) will add this information to the log file, if used.</p><p><b>PRINT_SIM_SELECTION_HISTO</b> (type=<span style="color:red">bool</span>, default=<span style="color:green">False</span>) if True will print robust information about corpus overlapping selection after concatenation. If false (the default) will add this information to the log file, if used.</p>
</div>