In lieu of an abstract, here is a brief excerpt of the content:

187 Chapter 14 Hierarchical and Recursive Musical Structure Most programs are hierarchical. We have already seen many examples of nested expressions and function calls. Complex programming problems should always be decomposed hierarchically into understandable units that can be implemented as functions. Music is often hierarchical. We can decompose traditional music into movements, sections, voices, phrases, chords, and notes. Musical structures can be reflected in software structures of algorithmic compositions. In this chapter, we look at some of the issues of moving from “flat” musical structures to hierarchical and recursive ones. 14.1 Structure from Nested Patterns Pattern generators can be nested hierarchically to create interesting musical structure. In this section, we present a very simple rhythm generator based on nested patterns. Rhythmic patterns can be perceived only if there is repetition involved. Interestingly, almost any rhythmic pattern becomes interesting (or at least salient) when it is repeated. Thus, to make a rhythmic pattern, we only need to create a sequence of rhythmic intervals and then repeat them. An interesting way to generate a rhythmic pattern is to divide a time span into equal intervals and flip a coin to decide whether each interval will contain a sound or not. We can model this as a simple random pattern: make-random({#t #f}). Example 14.1.1 uses make-random with a for: to keyword parameter to make a rhythmic pattern of length 12. Example 14.1.1: Rhythmic pattern generation SAL> set rp = make-random({#t #f}, for: 12) SAL> print next(rp, #t) {#f #t #t #f #f #f #t #f #f #t #t #f} If we were to play this pattern once, it would not really sound like a pattern since every element is random. However, if we use makecopier to repeat periods, they become recognizable and suddenly 188 Chapter 14 ⋅ Hierarchical and Recursive Musical Structure sound very rhythmic. Example 14.1.2 uses make-copier to repeat each pattern twice, and a loop prints 6 periods of patterns. Example 14.1.2: make-copier repeats patterns SAL> set cp = make-copier(rp, repeat: 2) SAL> loop repeat 6 print next(cp, t) end {#t #f #f #f #f #t #f #f #t #t #f #t} {#t #f #f #f #f #t #f #f #t #t #f #t} {#t #t #t #t #t #f #f #t #f #f #f #t} {#t #t #t #t #t #f #f #t #f #f #f #t} {#f #t #t #t #f #t #f #t #t #f #f #t} {#f #t #t #t #f #t #f #t #t #f #f #t} In this example, a blank line was inserted manually between groups to illustrate that that the pattern changes every two periods of length 12. Using these ideas, we can make a random, rhythmic drum machine. We will use bass drum, snare, and cymbal samples (included in Nyquist), each with a different pattern. The patterns will be 8 time intervals each and the patterns will change every 4 repetitions. In Example 14.1.3, one-drum generates a score for one of the drum sounds, using copies of periods as described above. The drummer function calls one-drum three times for the bass drum, snare, and cymbal scores, and merges them. The drum sounds themselves are loaded from files, e.g. kit/snare-1.wav contains a stereo snare drum sound. The drumsound function appends the file name to a path obtained from the global variable *plight-drumpath * and loads the file using s-read. The *plight-drum-path* is set by loading "../demos/plight/drum.lsp", which is part of the Nyquist software distribution. Experiment with this program. There is no need to make all of the patterns the same length. Other sounds can be used. Try latin percussion sounds or record your voice. The patterns generated here tend to have “anchor points” where the listener feels a downbeat, but since all choices are random, these “anchor points” might not be at the beginning of the cycle. Think about what cues indicate the beginning of a repeating pattern. Modify the program to either generate patterns that seem to begin on the first beat, or rotate patterns generated by make-random so that a good candidate for the first beat is in the first beat position. [18.222.67.251] Project MUSE (2024-04-23 09:07 GMT) 14.2 Hierarchy in Scores 189 Example 14.1.3: drummer.sal load "../demos/plight/drum.lsp" define function one-drum( name, beats, copies, phrases...

Share