This line import all of the names and functions in the os library,
including the functions walk() and path.join() used below.
To refer to these names and functions, we must prefix the library name
os; thus, os.walk() and os.path.join().
import osThis line imports only the name Counter, which is a function in the
collections library. Since we are importing the name Counter
directly, we do not need to prefix collections. (In fact, we are not
importing the entire library, so using the name collections would
produce an error.)
from collections import CounterThis line is similar to that immediately above except for the use of "*".
The asterisk is a wildcard character indicating that we are directly importing
all names and functions associated with the music21 library. Thus, we
use (for example) note.Note() rather than music21.note.Note().
from music21 import *A Counter is a container that keeps track of how many times equivalent
items are added. (Thus it is essentially a multiset.) Counter is much more
convenient than using a dictionary to count frequencies of items. For a
tutorial on Counter see https://pymotw.com/2/collections/counter.html or
see https://docs.python.org/2/library/collections.html#collections.Counter
for the reference document.
Here we create two seperate lists.
list1 = ['a', 'b', 'c', 'a', 'b', 'b']
list2 = ['b', 'c', 'd', 'd', 'b', 'b']Create a Counter of list1 and assign to count.
count += Counter(list1)Output: Counter({'b': 3, 'a': 2, 'c': 1})
print(count)Create a Counter of list2, add to count, and then assign the result
to count.
count += Counter(list2)Output: Counter({'b': 6, 'd': 2, 'a': 2, 'c': 2})
print(count)My code uses two functions:
dir_name is a string corresonding to a directory name
returns a list of streams for all files in dir_name and its subdirectories
that can be parsed by music21
def all_streams(dir_name):    my_streams = []
    for root, dirs, files in os.walk(dir_name):
        for file_name in files:
            path = os.path.join(root, file_name)try to execute the following block of code.
If an error is encountered, a try block code execution is
stopped and transferred down to the except block.
If not error is encountered, the try block code is successfully
executed.
            try:
                my_streams.append(converter.parse(path))
                number_completed += 1the except block code is executed if an error occurs in the
try block
            except:here we use the reserve word pass to indicate that there
are no statements to execute. (We simply want to ignore files
that can't be parsed by music21.)
                pass
    return my_streamsdef melody_to_intervals(my_stream, directed=False):my_stream is a music21 stream assumed to be a single-line melody
returns a list of intervals between successive pitches
If directed=True, the intervals are directed. Otherwise, the intervals
are undirected. If melody_to_intervals is called with a single parameter,
then directed is set to False by default.
    intervals = []
    flat_stream = my_stream.flat.notes
    for i in range(len(flat_stream) - 1):interval.Interval is a music21 class for handling intervals.
See http://web.mit.edu/music21/doc/moduleReference/
moduleInterval.html#interval.
        interval_type = interval.Interval(flat_stream[i], flat_stream[i+1]).semitones is a property of the interval.Interval class that
yields the interval in directed semitones
        current_interval = interval_type.semitonesIf directed is False (meaning you want undirected intervals),
then take the absolute (abs) value.
        if not directed:
            current_interval = abs(current_interval)
        intervals.append(current_interval)
    return intervalsdir_name = '/Users/ccallender/Desktop/europa/deutschl/altdeu2/'Convert all songs in the altdeu1 dir to music21 streams.
my_streams = all_streams(dir_name)Create an empty Counter.
count = Counter()Update counts of intervals for every stream in myStreams.
for s in my_streams:
    count += Counter(melody_to_intervals(s))print('Absolute counts of intervals')
for key in count:
    print(key, 'semitone(s):', count[key])Print a blank line.
print().values returns a list of the values in a Counter or dictionary.
sum returns the sum of all values in a list, tuple, or set.
total_count = sum(count.values())
for interval in count:round is a built-in Python function.
round(value, decimals) will round value to the specified number
of decimals.
    percent = round(100 * count[interval] / total_count, 2)
    print(interval, 'semitone(s):', percent)