#!/bin/bash ######################################################################### # # THEMEBUILDER # ######################################################################### # # Programmed by: David Huron Date: 11 Oct. 1999 # Copyright (c) 1999 David Huron # (Re-written with the assistance of Craig Sapp.) # # Modifications: # Date: Programmer: Description: # 12 Oct 1999 Craig Sapp (1) removed rests from pitch-class entry (j) # (2) removed rests from name-class entry (J) # (3) removed tied notes from interval entry (}) # (4) minor key entries made capital (za -> zA) # 13 Oct 1999 Craig Sapp (5) changed temp file names to remove strange # bug in the key entry. # 14 Oct 1999 Craig Sapp (6) made program work on themes with multiple # spines. # (7) adjusted meter entry so that multiple meter # classifications are reported as "mixed" # 9 Jun 2000 Craig Sapp Fixed pitch entry ending by adding a space # to end of pitch string (circa line 181). # # This program generates a "thema" database from a set of **kern input files. # For each input file (theme) a single output record is generated. The format # for this record is given below. # # For more information, see the documentation for "thema". # # THEMA DATABASE ENTRY FORMAT # One line for each theme, with the following entries separated by tabs: # # Field Example Information # 1. beet523 (basename of theme, filename) # 2. ZE-= (Z=major z=minor) E- (E-flat) = (marker) # 3. {m1p1p2m2p0m3 (intervals: m=minus; p=plus; 1=1, etc.) # 4. #duudsUsD (u = unison; d = down-step; # D = down-leap; u = up-step; U = up-leap) # 5. :DUUDS (S = same; D = down; U = up) # 6. %5456554 (scale degree) # 7. }xm2Xm2Xm2xM2P1xM2xm2xM2 (interval: x=down; X=up; m=minor; # M=major; P=perfect; A=aug.; d=dim.) # 8. jA9A0AA875320 (pitch-class:0=C;1=C#/Db;2=D;3=D#/Eb etc) # 9. JBb A Bb C Bb (name-class) # 10a. M4/4 (meter signature) [no space between # 10b. quadruplesimple (meter classification) 10a and 10b] # # Set up some reassignment files for the "recode" command: echo '>2 U' > $TMPDIR/recode.refined.$$ echo '>0 u' >> $TMPDIR/recode.refined.$$ echo '==0 s' >> $TMPDIR/recode.refined.$$ echo '>-3 d' >> $TMPDIR/recode.refined.$$ echo 'else D' >> $TMPDIR/recode.refined.$$ echo '>0 U' >> $TMPDIR/recode.gross.$$ echo '==0 S' >> $TMPDIR/recode.gross.$$ echo 'else D' >> $TMPDIR/recode.gross.$$ # Process each input file independently: for i in $* do # make a temporary file name extension: EXT=$RANDOM$$ ### Process the theme file to handle multiple spines FILENAME=$i TMPTHM=$TMPDIR/kernspines.$$ extract -i '**kern' $i > $TMPTHM # make sure that all **kern spines start at the same time if [ `grep '**kern' $TMPTHM | wc -l` != 1 ]; then echo "Invalid theme structure in file $FILENAME" exit fi SPINECOUNT=`grep '**kern' $TMPTHM | wc -w` # process each **kern spine in the file # There is a hack here limiting the spines to 9 for j in 1 2 3 4 5 6 7 8 9 do FILE=$TMPDIR/kernspine$j.$EXT if [ $[ $j <= $SPINECOUNT ] != "1" ] then break fi extract -f $j $TMPTHM | rid -d > $FILE # # End of setup for multiple spined themes # ################################################### ### Record the filename (without the extension). ######################## echo $FILENAME | sed 's/\.thm$//' >> $TMPDIR/filenames.$EXT ### Key (z or Z entry in thema database) ################################ grep '^\*[a-gA-G][#-]*:' $FILE | tr '*:' 'Z=' | \ awk '{if ($FILE ~/[a-g]/) gsub("Z","z",$1); print $1}' | \ tr 'a-g' 'A-G' >> $TMPDIR/key.$EXT ### Meter (M entry in the thema database ) ############################## # Meter signature METER=`grep '^\*M[0-9]' $FILE | sed 's/^\*//' | sed 's/ .*$//'` # Meter classification METERCLASS=`grep '^\*M[0-9]' $FILE | sed 's/^\*//' | awk '{ if ($1 ~ /M4/ || $1 ~ /M12/) beats = "quadruple" else if ($1 ~ /M3/ || $1 ~ /M9/) beats = "triple" else if ($1 ~ /M2/ || $1 ~ /M6/) beats = "duple" else beats = "irregular" if ($1 ~ /M6/ || $1 ~ /M9/ || $1 ~ /M12/ || $1 ~ /M16/) type = "compound" else if ($1 ~ /M1/ || $1 ~ /M2/ || $1 ~ /M3/ || $1 ~ /M4/ || $1 ~ /M5/ )\ type = "simple" print beats type}'` if [ `echo $METERCLASS | wc -w` = 1 ] then echo $METER$METERCLASS > $TMPDIR/meter.$EXT else echo ${METER}mixed > $TMPDIR/meter.$EXT fi ### Semitone Interval ({ entry in thema database) ####################### semits -tx $FILE | grep -v '[=r]' | xdelta | grep -v '[[]' > $TMPDIR/semits.$EXT rid -GLId $TMPDIR/semits.$EXT | sed 's/^/p/; s/p-/m/' | \ awk 'BEGIN{string="{"}{string = string "" $1}END{print string}' > \ $TMPDIR/semitint.$EXT ### Refined Contour (# entry in thema database) ######################### recode -f $TMPDIR/recode.refined.$$ -i '**Xsemits' $TMPDIR/semits.$EXT | \ rid -GLId | \ awk 'BEGIN{string="\#"}{string = string "" $1}END{print string}' > \ $TMPDIR/refined.out.$EXT ### Gross Contour (: entry in thema database) ########################### recode -f $TMPDIR/recode.gross.$$ -i '**Xsemits' $TMPDIR/semits.$EXT | \ rid -GLId | \ awk 'BEGIN{string=":"}{string = string "" $1}END{print string}' > \ $TMPDIR/gross.out.$EXT ### Scale Degree (% entry in thema database) ############################ deg -at $FILE | rid -GLId | sed 's/[+-]//' | grep -v '[=r]' | \ awk 'BEGIN{string="%"}{string = string "" $1}END{print string}' > \ $TMPDIR/scaledegree.$EXT ### Intervals (} entry in thema database) ############################### sed 's/[^*!].*[]]/r/; s/[^*!].*_/r/' $FILE | \ mint | tr '+-' 'Xx' | rid -GLId | grep -v '[[=r]' | \ awk 'BEGIN{string="\}"}{string = string "" $1}END{print string}' > \ $TMPDIR/intervals.$EXT ### Pitch-class (j entry in thema database) ############################# pc -atx $FILE | rid -GLId | grep -v '=' | \ awk 'BEGIN{string="j"}{string = string "" $1}END{print string}' | \ sed 's/r//g' > $TMPDIR/pitchclass.$EXT ### Pitch-name (J entry in thema database) ############################## pitch -tx $FILE | sed 's/[0-9]//' | rid -GLId | grep -v '=' | \ awk 'BEGIN{string="J"}{string = string " " $1}END{print string}' | \ sed 's/ //' | sed 's/r //g; s/r$//; s/$/ /; s/ / /' > $TMPDIR/pitchname.$EXT # Now paste all of the temporary files into a single output paste $TMPDIR/filenames.$EXT \ $TMPDIR/key.$EXT \ $TMPDIR/semitint.$EXT \ $TMPDIR/refined.out.$EXT \ $TMPDIR/gross.out.$EXT \ $TMPDIR/scaledegree.$EXT \ $TMPDIR/intervals.$EXT \ $TMPDIR/pitchclass.$EXT \ $TMPDIR/pitchname.$EXT \ $TMPDIR/meter.$EXT rm $TMPDIR/*.$EXT done # inner for loop processing multiple spines done # outer for loop processing each theme file. # Remove temporary files. rm $TMPDIR/*.$$