Clapping music: Difference between revisions
No edit summary |
No edit summary |
||
Line 80: | Line 80: | ||
# ... | # ... | ||
done | done | ||
</source> | |||
A final script: | |||
<source lang="bash"> | |||
pat="xxx_xx_x_xx_" | |||
cat << end | |||
@head { | |||
\$tempo 120 | |||
\$time_sig 4/4 | |||
} | |||
@body { | |||
@channel 1 { | |||
\$patch 1 | |||
\$length 16 | |||
\$octave 4 | |||
\$pan 0 | |||
end | |||
for ((bar=0; bar<13; bar++)) | |||
do | |||
for ((repeat=0; repeat<12; repeat++)) | |||
do | |||
echo $pat | sed 's/x/c /g; s/_/r /g' | |||
done | |||
done | |||
cat << end | |||
} | |||
@channel 2 { | |||
\$patch 1 | |||
\$length 16 | |||
\$octave 5 | |||
\$pan 127 | |||
end | |||
for ((bar=0; bar<13; bar++)) | |||
do | |||
for ((repeat=0; repeat<12; repeat++)) | |||
do | |||
echo $pat | sed 's/x/c /g; s/_/r /g' | |||
done | |||
pat=${pat:1}${pat:0:1} | |||
done | |||
cat << end | |||
} | |||
} | |||
end | |||
</source> | </source> |
Revision as of 14:39, 13 October 2010
... continuing from the sedsongs exercise
See the page on Bash for help with using loops & variables
This is an exercise to create a Bash version of Steve Reich's Clapping Music using Bash and a pipeline using midge and timidity.
If you look at a copy of the musical notation for the piece, you can start to see that in fact it's based on a pattern, and could be easily (better?) expressed as an algorithm, namely a loop in which a pattern slowly shifts.
To start, create the first two bars "by hand" as a midge file:
@head {
$tempo 120
$time_sig 4/4
}
@body {
@channel 1 {
$patch 1
$length 16
$octave 4
$pan 0
# the main pattern (3, 2, 1, 2 claps with rests in between)
c c c r c c r c r c c r
# the first performer simply repeats the pattern...
c c c r c c r c r c c r
}
@channel 2 {
$patch 1
$length 16
$octave 5
$pan 127
# the 2nd performer starts with the main pattern
c c c r c c r c r c c r
# .. and (eventually) shifts the pattern
c c r c c r c r c c r c
}
}
Now, we convert the midge file to a minimal bash script that does nothing but outputting the text (using a heredoc and cat). Note the need to backslash the $'s.
cat << END
@head {
\$tempo 120
\$time_sig 4/4
}
@body {
@channel 1 {
\$patch 1
\$length 16
\$octave 4
\$pan 0
c c c r c c r c r c c r
c c c r c c r c r c c r
}
@channel 2 {
\$patch 1
\$length 16
\$octave 5
\$pan 127
c c c r c c r c r c c r
c c r c c r c r c c r c
}
}
END
We will make use of a simple counting loop (see Bash#Loops) ...
for ((i=0; i<13;i++))
do
# ...
done
A final script:
pat="xxx_xx_x_xx_"
cat << end
@head {
\$tempo 120
\$time_sig 4/4
}
@body {
@channel 1 {
\$patch 1
\$length 16
\$octave 4
\$pan 0
end
for ((bar=0; bar<13; bar++))
do
for ((repeat=0; repeat<12; repeat++))
do
echo $pat | sed 's/x/c /g; s/_/r /g'
done
done
cat << end
}
@channel 2 {
\$patch 1
\$length 16
\$octave 5
\$pan 127
end
for ((bar=0; bar<13; bar++))
do
for ((repeat=0; repeat<12; repeat++))
do
echo $pat | sed 's/x/c /g; s/_/r /g'
done
pat=${pat:1}${pat:0:1}
done
cat << end
}
}
end