Music Representation and Transformation in Software: Structure and Algorithms in Python 1st Edition Donald P. Pazel - The complete ebook set is ready for download today
Music Representation and Transformation in Software: Structure and Algorithms in Python 1st Edition Donald P. Pazel - The complete ebook set is ready for download today
com
https://ebookmeta.com/product/music-representation-and-
transformation-in-software-structure-and-algorithms-in-
python-1st-edition-donald-p-pazel/
OR CLICK HERE
DOWLOAD EBOOK
https://ebookmeta.com/product/mousetrap-structure-and-meaning-in-
hamlet-1st-edition-p-j-aldus/
ebookmeta.com
https://ebookmeta.com/product/data-structures-algorithms-in-python-
john-canning/
ebookmeta.com
https://ebookmeta.com/product/the-tell-tale-a-small-town-enduring-
love-a-web-of-secrets-1st-edition-clare-ashton-2/
ebookmeta.com
https://ebookmeta.com/product/birds-of-new-jersey-field-guide-2nd-
edition-stan-tekiela/
ebookmeta.com
Dad Bod Lumberjack Dad Bod Men Built For Comfort 1st
Edition Gia Bailey
https://ebookmeta.com/product/dad-bod-lumberjack-dad-bod-men-built-
for-comfort-1st-edition-gia-bailey/
ebookmeta.com
https://ebookmeta.com/product/snowed-in-with-the-grump-1st-edition-
kat-baxter/
ebookmeta.com
Renewable energy conversion systems: Technologies, Design
and Operation 1st Edition Kamran Muhammad
https://ebookmeta.com/product/renewable-energy-conversion-systems-
technologies-design-and-operation-1st-edition-kamran-muhammad/
ebookmeta.com
Donald P. Pazel
Music
Representation
and Transformation
in Software
Structure and Algorithms
in Python
Music Representation and Transformation in Software
Donald P. Pazel
Music Representation
and Transformation in Software
Structure and Algorithms in Python
Donald P. Pazel
Fishkill, NY, USA
© The Editor(s) (if applicable) and The Author(s), under exclusive license to Springer Nature Switzerland AG 2022
This work is subject to copyright. All rights are solely and exclusively licensed by the Publisher, whether the whole or part of
the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting,
reproduction on microfilms or in any other physical way, and transmission or information sto rage and retrieval, electronic
adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication does not imply, even
in the absence of a specific statement, that such names are exempt from the relevant protective laws and regulations and therefore
free for general use.
The publisher, the authors, and the editors are safe to assume that the advice and information in this book are believed to be true
and accurate at the date of publication. Neither the publisher nor the authors or the editors give a warranty, expressed or implied,
with respect to the material contained herein or for any errors or omissions that may have been made. The publisher remains
neutral with regard to jurisdictional claims in published maps and institutional affiliations.
This Springer imprint is published by the registered company Springer Nature Switzerland AG
The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
Preface
Introduction
Suppose you have an interest in programming computer music and need a starting point. Perhaps you
have tried various music applications or tools, such as mixers, production systems, or notation systems,
but feel a need to dig deeper, to be more hands-on and work with music fundamentals. Perhaps you
have familiarity with concepts of musical notes, keys, chords, scores, and other music elements, but
you don’t know where to begin in designing and programming about them, let alone translating them
to MIDI®1. You want to be able to put all those elements to work through programming, but you need
direction to get to that next killer music app that you have in mind. This book guides you to that sweet
spot of developing and using your programming skills to design and build systems about music.
However, this book does more than provide that kind of instruction. This book takes the reader on a
journey through music concepts in an organized approach that develops music essentials, from the
concepts of tone, pitch, and time, through notes, intervals, chords, and scores while at the same time
interpreting these elements as software artifacts. As these many concepts are covered, we do so with
close attention to the organization of and relationships amongst these concepts and reflect those as
Python classes and objects, and so learn about music from a software design viewpoint. By this process,
we approach this design in a logical and structured way.
The objective for doing this is to make music theory elements programmatically accessible. The result-
ing software should allow you to be able to code in the language of music, letting you to think primarily
in musical concepts about your programming objectives, while leaving various music calculations,
such as key or chord construction, transparent. That is the point behind the software discussion on
music representation in the first part of this book.
The second part of the book is devoted to music transformation algorithms. These transforms comprise
an interesting application of music representation for modifying music through key change, melodic
reflection, and much more. This part of the book is more academic and has more of a research feel.
However, the connection to programming prominently remains with discussions grounded in
1
MIDI is a registered trademark of the Association of Manufacturers of Electronic Instruments
(AMEI).
v
Preface
implementation details and software structure considerations. We hope the reader finds inspiration in
this section for novel applications or advanced interests in the wide area of computer music research.
2
IBM is a registered trademark of International Business Machines.
3
VST is a trademark of Steinberg Media Technologies, GmbH.
vi
Prerequisites and Approach
The problem which with I struggled was that this project was simply too massive for one person to
contain within reasonable time. Although initially I focused on building a proper music representation,
I quickly became absorbed with server architecture details, distributed playback algorithms, client syn-
chronization, web interfaces (JavaScript), and general maintenance. Quickly, the core music represen-
tation became brittle and sketchy with the load of work. What started as a music project, became more
of a “soup to nuts” web application project, a terribly interesting one, but one that left scarce time and
energy for addressing the increasingly insufficient core music representative and transformative issues
on which I wanted and needed to spend much more time and energy.
I took a break from the project for reflection, to reexamine the work that had been done, determine how
to improve upon it, and see to where that circumspection leads. As I realized early on, music represen-
tation is a deep and interesting software modeling exercise in itself. The intuitive concepts of music
require rigorous definition. The closer I looked, it seemed that although we are generally adept with
many music concepts like intervals, scales, chords, and the like, our understanding of these are some-
what superficial and at times not so well structured, if not incomplete, and rough around the edges. It’s
like the many skills we adopt from rote learning. We work with certain skills daily but don’t think
deeply about them nor even understand their foundations with much clarity. Looking at the music
representation I had developed, I found needless complexity that seemed to come more from lack of
foundation (from admittedly a rush to get that component finished as an expense for other needs) than
say sloppy code.
Yet another important aspect surfaced, that music representation comes with a set of algorithms that
are in fact, genuinely interesting. The computation of scales, computing interval end notes, and similar,
are interesting topics, that in a thought-provoking way made me question how as a musician I had done
those things, and if there are better ways to think about those topics, especially, when designing soft-
ware to manipulate them. As an example, the notion of time in music is interesting, that along with the
varied temporal representations comprises an interesting study, including the conversions of one tem-
poral representation to another. It is interesting to think about the properties of a musical note, to ques-
tion why we limit to specific durations, and pitches. These are just a few examples of what came to
light. It speaks to the larger issue of questioning our understanding of music, what restrictions might
be too rigid, and if anything can be done to lessen those restrictions.
I never returned to that initial distributed application. Instead, I decided to focus on music representa-
tion, the related foundational algorithms, and eventually to music transformational issues, from the
perspective of a software engineer and to some degree, a mathematician. This turn of focus resulted in
a sizeable body of study and code that is detailed in this book. The result is a far more fulfilling adven-
ture than I could have imagined.
This experience is what led me to writing this book. After years of working solely on music represen-
tation, and years looking at how to build transformational algorithms with that representation, I thought
I would share that experience here in hopes of motivating others to carry on and perfect that effort and
inspire people towards efforts in computer music.
vii
Preface
The reader should have some loosely defined notions of musical elements. That is, the reader should
have notions about what notes, intervals and chords are. However, the book is built around introducing
all these concepts in a methodical structured way. So, unlike the programming prerequisites, the music
prerequisites are less strict.
Object-Oriented design skills are not required but are a critical part of the book’s teachings. This book
places a heavy emphasis on learning object-oriented (O-O or OO) design and thinking. Designing in
an object-oriented manner forces one to step back from a problem space, and pull apart the concepts
and their dependencies, and make judgments on how to approach a programming task. It forces devel-
opers to:
• code a software model that clearly maps to the problem domain’s conceptual model, and in a sense,
“talks in its terms”.
• reflect relationships and dependencies directly in the software model that are relevant in the do-
main’s conceptual model.
• keep in mind efficiencies and inefficiencies, or limitations of programming artifacts used in the
software model.
• stretch for generality where needed, but within reasonable bounds.
What the reader should realize is that like with so many software endeavors, the software design pro-
cess never ends. This is particularly so with the music domain, with, for example, the introduction of
different instruments, different styles of music, and so forth, each introducing their own conceptual
needs. We do not claim to present in this book the best possible music representation but do believe
this model goes a long way on generality and will change over time to be more inclusive, and to intro-
duce the reader to software design in the object-oriented style.
Since music many times involves calculations, especially involving dynamics over time, some mathe-
matics is involved. The reader should be able to understand simple equations for calculations and sim-
ilar and be capable of translating these into code.
4
Dorico is a registered trademark of Steinberg Media Technologies GMbH.
5
Sibelius is a registered trademark of Avid Technology Europe LTD.
6
Notion is a registered trademark of Presonus Expansion, L.L.C.
7
Finale is a registered trademark of MakeMusic, Inc.
viii
Intended Audience
educational introduction for readers interested in learning about MIDI. However, construction of MIDI
rendering software is a topic unto itself and is outside the scope of this book.
Intended Audience
A wide variety of readership is envisioned for this book. Primarily it is for students to accelerate their
software development capabilities in designing and building music software. With that, we offer the
following thoughts for the varied reader constituency:
Students
Students should take seriously the technical prerequisites. It is important to be able to program proce-
durally in some programming language. If you already know Python, fine. If not and you pick up
programming languages easily, fine. However, knowing the basics of Python is the expectation of this
book. The book also delivers an introduction to object-oriented principles and how to program to them
in Python. The book applies object-oriented principles to varied music elements and accelerates in
depth rapidly. The algorithms, even in the representation section at times can be complex and intricate,
and in some cases are expressed in mathematical formulae which the user should be able to understand
and translate to code.
In a few instances, advanced computer science concepts are discussed, for example, red-black trees
and constraint engines. Students need not understand the implementations of these concepts in detail,
but should concentrate in understanding the features they provide, how to use them, their interfaces,
and chiefly their strengths and limitations. The more intrigued student may want to invest more time
on theory and implementation details in these areas.
While the primary focus for entry-level students should be on the representation part of the book, the
transformation part could be of great interest and well-worth reading. It comprises a combination of
practical applications of music representation and an introduction to constraint management. Students,
if not guided by an instructor, should read through the transformations and at least understand what
they contribute musically, and understand them technically as best can. Reading through the many
examples should help in providing this understanding.
For representation chapters, the end of chapter questions are mostly for provoking thought about the
range in complexity of what is presented. The student is encouraged to read through the questions and
select a few (if not assigned by the instructor) to think through as best can. For the transformation
chapters, each chapter ends with a “final thoughts” section which highlights both positive and less than
positive aspects of the chapter’s topic. It is meant to be thought provoking, and fuel for further efforts.
Instructors
Instructors can consider using this book for a one semester course on computer music programming.
The representation part could easily occupy a semester. For classes comprised of students with lower-
level programming skills, the instructor could augment the course with a robust Python review. That
said, it is recommended to spend a good deal of time on object-oriented concepts and how to code
Python to an object-oriented methodology. After that, the book can be followed chapter to chapter with
the idea of introducing new music concepts in succession, along with representation and coding prin-
ciples.
If the semester has more time to offer, one can consider introducing topics from the transformation
section, with at least a guide through the transformations and examples. The constraint engine itself
can be technically demanding for students, and the instructor can defer on its implementation details,
and instead highlight its interface and usage. The constraint engine is an interesting topic, and advanced
ix
Preface
students may want to consider augmenting or working with it as an advanced project in this or other
domains.
Practitioners
Practitioners may come to this book for a variety of reasons, and in a variety of ways. If you want to
learn how to approach object-oriented programming with computer music as a domain, then a straight-
forward read is recommended. Otherwise, treating it as a reference text, picking and choosing chapters
in the representation section is useful.
As for the transformation section, there are many topics from which to choose. A few of the transforms
make use of the constraint engine, but many don’t. It is a matter of looking through the transform types
to determine which topics might be of interest.
Experienced Researchers
Experienced researchers may generally find the representation section less interesting than the trans-
formation section, except perhaps for the later chapters of the representation section concerning varia-
ble dynamics and harmony representation. We would expect this audience to be more interested in the
transformation section of the book, on which there are a wide range of topics to study and expand upon.
As a bonus this book is associated with an accessible software package that reflects the work of this
text. This software can be found at:
https://github.com/dpazel/music_rep
This software package reflects the class hierarchy and details described throughout this text. It is cov-
ered by MIT license with no guarantees nor warrantees.
x
About the Software
Readers are encouraged to copy the code locally to their computers and use a programming IDE like
Eclipse®8 or PyCharm®9 to review the code while working through related sections of the book. Im-
portantly, please review the “readme” file which instructs which related software packages (Python
packages) are required for the code to build and run. There are ample unit tests as well in the package
that the reader may find useful towards understanding the code and concepts. The code base uses some
interesting external packages which should be educational and useful to software engineering students.
It is emphasized that running examples in debug mode may be the best way for learning and exploring
the ideas in this book.
Bear in mind that the software was developed from a research viewpoint. The conceptual model on
music was developed with two ambitions. One was to develop a music software model that encapsu-
lates in logical development most basic music theoretical elements. Also, the model’s developmental
aim is to provide a foundation capable of enabling transformations, and in doing so prove strong enough
to sort out a transform’s strengths and limitations that a simpler model might not be able to do.
However, the code is less than industrial in strength and robustness! That is, one is likely to find missing
features or outright errors, or even some intentional missing elements meant for exercises. The code
may occasionally be improved upon over time, so it would be in the readers’ interests to periodically
check for updates.
It is my hope that readers find this book more than helpful in their programming or music careers or
general educational endeavors, but also find the book thought-provoking, stimulating, and encouraging
for interests in computer music programming and research.
To all who venture here, Best of Luck!
Donald P Pazel,
Fishkill, NY
January 2022
8
Eclipse is a registered trademark of Eclipse Foundation, Inc. Ref. http://www.eclipse.org
9
PyCharm is a registered trademark of JetBrains s.r.o. Ref. https://www.jetbrains.com/pycharm
xi
Preface
Acknowledgements
Parts of this text were produced using the MusiSync font, © 2001, 2008 by Robert Allgeyer, SIL Open
Font License10. Also, the overwhelming majority of musical examples were constructed in and figures
extracted from personal Dorico projects.
There are many people who introduced me to the study of computer music, and the problems and issues
behind representing music in software. Of course, much of that starts with the Computer Music Center
members at IBM Watson Labs and especially to Danny Oppenheim and Jim Wright who together em-
bodied the spirit and mind of the project, and Robert Fuhrer, as well as the manager David Jameson,
our fearless tester David Speck, and Jim Cate in a production role. However, a special thanks to Steven
Abrams who as the newly minted manager at the time, served as a crucial catalyst and contributor for
ideas and progress that resulted in pulling together the best ideas in the group, including Smart Har-
mony. Many of these ideas provided inspiration for the follow-on work in this text, and a few of those
seed ideas are borrowed and cited appropriately. I offer my thanks and appreciation to Dr. William R.
Pullyblank for sponsoring that effort as part of his Mathematics department.
Many thanks go to Aries Arditi for many directional conversations and for his review and suggested
changes to the document, and similarly to Daniel Spreadbury and Roger Dannenberg for their kind
reviews. Also thanks to Dr. Stephen Andrilli of LaSalle University for his continued encouragement,
and to Brian Hinman for his sage counsel.
Also, I would be completely lost in this endeavor were it not for the strong musical influences in my
life. I studied piano for many years with Ralph Burkhart who taught me the foundations of music
theory, music performance technique, and music appreciation. Also Dr. Ruth Schonthal taught me
foundations and appreciation for music composition. Both Ralph and Dr. Schonthal are now gone and
are very much missed. I hope they understood how totally in awe of them I am. After many years of
absence from piano, in recent years I continued piano study with Jennifer Gallant Lopez who led me
to an awakening of a renewed appreciation of great music and performance. Also, many thanks to Amy
Baglione for introducing me to the rudiments of jazz and beyond.
A special thanks to Ralf Gerstner, executive editor at Springer, for taking on this book and for his
patient shepherding and steady hand through the publication process.
Some influences are long lasting and unforgettable, and come from a different and indeed magical time
of my life. I am deeply indebted to Br. Hugh Albright of LaSalle University, Philadelphia. His ethereal
yet profound way of conveying the beauty of mathematical abstraction left a lasting influence, and a
life-long love and respect for mathematics. As well, Dr. Thomas Kriete of the University of Virginia
taught me the importance of rigor and clarity of presentation for instruction. I am grateful for their
belief in me. I could only hope that some of those influences show through here.
And the best for last, with love for my wife Joan for the time and patience for making this book happen.
My love and best friend forever!
10
The SIL Open Font License is completely free for personal and commercial tasks. And you don’t
need to pay any single penny for utilizing them commercially. Also, if you get some other license like
OFL, Public domain, and 100% free. They are also free for commercial uses.
xii
Contents
PREFACE ................................................................................................................................... V
INTRODUCTION ................................................................................................................................. V
THE ORIGIN OF THIS BOOK .................................................................................................................. VI
PREREQUISITES AND APPROACH .......................................................................................................... VII
WHAT THIS BOOK IS NOT ABOUT ....................................................................................................... VIII
INTENDED AUDIENCE ......................................................................................................................... IX
REGARDING THE MUSICAL EXAMPLES ....................................................................................................X
ABOUT THE SOFTWARE .......................................................................................................................X
ACKNOWLEDGEMENTS ...................................................................................................................... XII
CONTENTS ..............................................................................................................................XIII
xiii
Contents
xiv
Contents
xv
Contents
xvi
Contents
xvii
Contents
xviii
Contents
xix
Contents
xx
Part 1: Representation
The first part of this book focuses on the representation of music in software. We begin with a more
precise definition about the meaning of the phrase “representation in software”. Whenever software
applications are designed, be they music applications, billing systems, or internet chat rooms, etc., they
are broken down at a conceptual level to account for the discrete concepts or entities involved. For
example, invoices, bills, customers in billing systems or participants and discussions in chat rooms,
etc. are discrete concepts that are the subjects of their respective applications. Each of those entities
can be further broken into two key constituents, namely data properties, and algorithmic logic which
we refer to as methods. For example, for a representative entity for a person, data properties might
include name, address, and age. Methods might include accessing or changing these data properties.
What is important is that the data always remains consistent during an application’s execution lifetime.
For example, ensuring the address is correct for the name.
A method is usually referenced by a signature consisting of a method name descriptive of what the
method does, a set of input data, and one or more data that is returned. The set of method signatures
for an entity usually divides into strictly internal, meaning it maintains the data consistency even when
changed, or external, meaning it is meant to be used by other entities or generally by the application
itself.
Discovering the conceptual elements of an application, and further refining each by data property and
methods is what is meant by the term ‘representation in software’ and is further embodied in the process
known as object-oriented (OO) design. The opening chapter of this part of the book describes OO
design and discusses OO programming in the Python programming language.
The topic of this part of the book concerns representation in software for the main elements found in
music theory. Anyone who has attempted to build a music-based software project is aware of how
difficult it is to capture the complex conceptual space of music into software. For example, a note is a
basic entity in music theory that is encapsulated by data properties including pitch frequency, duration,
and volume. One immediately comes across an increasingly complex set of artifacts that add to the
context of a note. Among these are key, time signature, and tempo. Add upon that, chords, measures,
voices, and so forth, of which note is a part, and the complexity multiplies. Following so, we are even-
tually led to score representation, including processes for complex changes such as in time signatures,
tempos, and so forth. There is a hierarchy of music concepts, each layer built upon the lower until we
see the full conceptual space that defines a knowledge base about music, often referred to as music
theory.
Translating these entities into a structured, accurate, and flexible software model is not an easy task.
There are decisions to be made on the conceptual model as structure, the key entities, and their depend-
encies. That is, how does one represent or code all that information using a programming language,
and after that, using that representation, how does one program towards application goals. Each mis-
step, however small, may not necessarily lead to inoperable code, but rather inflexible code, where
Part 1: Representation
doing even the easiest of changes requires, for example, overly complex coding changes. One may also
find suspicious infrequently used procedures that depend on multiple sources of information for per-
haps partial calculations, which overall seem to stick out like a sore thumb in the code base.
The objective of this part of the book is to provide direction to this discussion, to build a music software
model from basic concepts and build towards more complex concepts. Chapter by chapter we introduce
new music concepts and break each apart into data properties and methods. The goal is that by the end
of this book section, we will have developed a relatively complete library of music elements in software
that can be practically useful and for experimentation and provide a foundation for the advanced work
found later in the transformation part of the book.
2
1 Software Modeling and Object-Oriented Design
Software design has been an ever-evolving craft since the beginning of programming. As software
systems became more complex there was more need for discipline in crafting software and organizing
it. It became clear that strict procedural designs and use of data structures, although effective, could
lead to code that easily fractures under the strain of changes, through carelessness or lack of foresight.
Looked at another way, the early programming languages had no implicit capability to assist with
enforcing design principles.
Object-oriented design is a paradigm for programming that evolved primarily through the 1970’s and
into the 1980’s. At a simplistic level, the basic idea behind this paradigm is to think of a software
system as a set of concepts or entities, and for each define a set of data properties that encapsulate the
entity, and as well, a set of procedure-like logic that allow the entity to regulate or maintain consistency
of those data properties, and a set of procedure-like logic that provides public access from other con-
cepts or generally. This approach has been adopted by many programming languages including Small-
talk, C++, and Python, to name a few, and each has inherent support structures and features for object-
oriented design. The design concepts become actualized as classes within which are defined the data
properties and logic methods.
The point of using object-oriented design is to consolidate application data and processes into well-
defined conceptual silos as design. The development becomes more logical as it adheres to the problem
space more precisely at a conceptual level. In using object-oriented design, as we will see, there are
decisions to make about class definition and related class hierarchies, data property and method defi-
nition and so forth. Over time, object-oriented programming has evolved into a rather large topic. How-
ever, many of the basics are easily stated and illustrated. It is beyond this text to develop object-oriented
design theory in detail here. Instead, the basics are described in this chapter, and further aspects are
introduced as needed later.
In this book, we take a journey towards building an object-oriented model for music using the Python
programming language. However, at the same time, we look at music theory very deeply, even to the
point of including some modern music concepts, such as 8 tone scales, and cluster chords. With that,
we transform music theory to software within a broader context, and in doing so, guide ourselves
through a set of decisions and problems in doing the related software design and implementation.
suppose there are two types of checking accounts, basic and enhanced. A diagram depicting the rela-
tionships amongst these entities is shown in Fig. 1.1. Keep in mind that this diagram aims to facilitate
design, indicating what entities are envisioned in our application and how data and code is organized.
The design diagram is abstract in showing the definitions of the application’s entities and relationships,
and not actual instances of the entities. In programming, we instantiate the definitions in that many
Accounts, many Checking accounts, and so forth, based on these definitions are created. Building these
kinds of diagrams is common practice in program design.
The hierarchical diagram shows a box for each entity type discussed above, along with relationship
arrows described below. Let’s look at the element of this application more closely.
Class: Instead of entity we will use the word class, which relates more to its programming embodiment
described later. Classes represent the conceptual elements that comprise our system. It is abstract in
the sense that classes are descriptive or defining elements. For example, there is only one class defini-
tion for ‘Account’, which describes its data and behavior. However, in an actual application, there will
be many account objects or instances based on that definition. Each instance holds real data with be-
haviors based on actual data values and code. This bundling of related data on a common conceptual
entity is called encapsulation.
Properties and Methods: With class being a defining element, at the detail level, a class is composed
of properties and methods. It is easiest to think of properties as data definitions. For example, in the
case of the class Account, one would have a property that names or identities the owner of the account
and name that property ‘owner’. Other properties include the date the account was opened, called
‘opening date’, and the property ‘status’ of the account with values like open, closed, frozen, and so
on. Properties are defined data holders related to what the class conceptually represents.
Methods on the other hand, can be thought of as calculations or actions related to the class that either
other classes can invoke, or that can be invoked external to any class. Returning to the class Account
example, invoking change_owner(), would provide a means to change ownership of the account. More
than simply a name setting action, change_owner() verifies the identity of new owner, as well as checks
if the new owner has permission to ownership and related business role to it, and so on.
Get_Credit_Line() is another method requiring various calculations depending on the type of account,
balances, and so forth. Many methods and properties may be openly accessible, or public, to the appli-
cation. Others may be strictly internal to each class, or in that sense private. These accessibility
4
1.1 Object-Oriented Design by Example
characteristics, public or private, are referred to as data protection values. Methods are specified in the
form of a signature which provides the name of the method, and the names of both input and output
data.
Inheritance: The arrows between classes in the diagram can best be thought of as denoting “is a” rela-
tionships between the source class and the target class. For example, “Checking is a kind of Account”
or “Basic is a kind of Checking (Account)”, the “Z1 credit card is a CreditCard (Account)”, and so
forth, are clearly marked in the diagram by arrows. Each arrow indicates inheritance, that one class
has the same properties and methods of another and may likely include additional properties or meth-
ods. In an inheritance relationship, the class at the base of the arrow is called a subclass in relationship
to the class at the arrowhead called the superclass. What this means is that all the properties and meth-
ods of the superclass, for example Account, are also part of say, a Checking (account), the subclass.
Similarly, Account’s properties and methods are included in CreditCard and Savings. Superclasses like
Account reduce duplication of data definitions and method implementations for its subclasses. This
makes development much easier since changes and enhancements to superclasses automatically bind
to their subclasses.
Interface: An interface, like a class, is a summary of data properties and methods, but unlike a class
are not directly instantiated. Classes implement interfaces, in that when so indicated, the classes further
define the interface’s data properties and methods. Many classes can implement the same interface. In
that way, interface provides a form of multiple inheritance, allowing instances of different implement-
ing classes to be identified by the interface semantics only. An interface should not be confused with a
class definition wherein the semantics or meaning of these characteristics is laid out, described, and
even coded as properties and methods. In fact, interface instances are not created by themselves but
only in as much as an implementing class is created. What is important about interfaces is that they
encapsulate a set of data properties and methods that can be accessed through the implementing class.
The interface mechanism varies across programming languages. Java provides interfaces to be used at
user discretion. Python and C++ do not. In these latter cases, the class definitions themselves are in a
sense, de facto interfaces. The point behind the notion of interface whether by interface semantics or
by class definition, is that in both cases there is an identifiable encapsulation of accessible data and
methods that can be used as a source for coding activity.
Polymorphism: The object-oriented feature of polymorphism has several different meanings. Inher-
itance relates to a kind of polymorphism, in as much as, for example, CreditCard, Checking, and Sav-
ings are subclasses of Account, and wherever an Account instance can be used, usually so can Ac-
count’s subclasses of CreditCard, Checking, and Savings. In that sense, inheritance leverages a kind of
polymorphism. A more commonly held notion of polymorphism is when a class can have several meth-
ods of the same name but with different parameter types or numbers of parameters that serve to distin-
guish which method is invoked by calling arguments. As a simple example, the Checking class may
have several method implementations for the method deduct(). In one, deduct(owner_name, amount),
a deduction for some amount is made by a specific owner of the account. In another, deduct(amount),
a deduction is made anonymously on an account.
As mentioned earlier, object-oriented design is a kind of science to itself. The brief introduction above
hardly scratches the surface. For more information, reference [7], [8]. A visual representation of many
concepts in object-oriented design can be found in the study of Unified Modeling Language or UML.
The inheritance arrow in the above diagram is the UML symbol for inheritance for example. A refer-
ence for UML is [9]. Finally, to see object-oriented design in light of practice for commonly used
programming motifs, refer to the study of programming patterns [10].
5
1 Software Modeling and Object-Oriented Design
• Class Declaration Header: This statement provides the name of the class being defined, along
with a list of class names of other defined classes to serve as superclasses. When no super-
classes are specified, the default is the Python system class “object”. So far, we have only
explored classes with only one superclass, and for this text that will typically be the case.
However, a class can have multiple superclasses, and pick up the properties and methods of
all the superclasses. Such a situation is called multiple inheritance. Multiple inheritance has
some complexity and must be defined with care especially in cases where the subclasses share
similarly name methods or data. Further discussion on multiple inheritance can be found be-
low.
• Class Static Data Definitions: A class can define static data variables proper to the class itself,
and independent of class instances. That is, although we may create many class instances,
there is only one value for each of these class data variables, that is, the static values being
singular to the class itself. Access is made through ClassName.class_data1, for example.
• Class Instance Initializer: When a class is instantiated to an instance, that instance requires
proper initialization, with application dependent default values for instance data, and for pos-
sibly building ancillary data for proper instance behavior. That initialization is implemented
in the class’s __init__() method. In code, the __init__() method is automatically invoked at
instance creation, e.g., a = ClassName(args). The first variable in the signature of __init__(),
self, is a reference to the new instance. Additional parameters may be specified for supple-
mental value input to assist in initialization. While, the __init__() method is invoked to ini-
tialize a class instance, note that the subclasses also require initialization as well, and this is
achieved by the subclass’s __init__() invoking the __init__() methods of each superclass.
• Instance Data Definitions: Instance data refers to the class variables that on an instance-by-
instance basis hold values for that instance. They come into existence usually on first usage,
as opposed to a formal declaration of name and type found in many programming languages.
Instance data access is made through the reference self.instanceData1, for example. While
instance data variables can be defined in any method for an instance, doing so in __init__(),
as a policy, establishes an expectation as to where to find all instance data definitions and their
initial settings.
• Instance Method Definitions: Class methods define class behaviors. Each class definition pro-
vides a set of method definitions. A method definition consists of a method name along with
6
1.2 A Concise Introduction to Python Classes
a set of parameters which together defines the method signature, and an implementation as
code. As for the parameters, the first parameter is “self”, which for the instance access refers
to the class instance itself. Note that, when called, “self” is not explicitly passed, e.g., in-
stance.method1(args). It is worth noting that while method signatures must be unique, meth-
ods can be defined with the same name provided the signatures are unique, e.g., deposit(dol-
lars) verses deposit(dollars, for_account_name).
• Class and Static Methods: Python provide two method variants that have a more global nature,
in that they are called independent of any class instance. In both cases, there is a signature as
described. A class method’s signature has, instead of “self”, a “cls” variable as first parameter
which references the Python class object itself. The other parameters are as before. A class
method is called, e.g., class.method_namer(args). Static methods on the other hand have
neither self nor cls as a first parameter. They are called by object or class as before, but the
again the first argument is neither self nor cls.
Properties
On the topic of instance data definitions, the related topic of Python properties is worth highlighting.
While instance variables are accessible by name both inside or outside the class definition, sometimes
getting and setting an instance variable to some value might require additional processing above and
beyond merely accessing the instance data directly. However, accessing instance variable data along
with the additional processing through new user defined methods would only add to the complexity of
class usage. Python properties is a feature that provides for that extra processing while maintaining
simple user access to instance data. An outline for defining properties is as follows:
@property
def account_name(self):
# Additional processing
return self.name
@account_name.setter
def account_name(self, name):
# Code to determine the name value
self.name = new_name
return
The decorator ‘@property’ is used to declare the getter method, while @name.setter prefixes the setter
method. In usage, for example, one simply calls instance.account_name to get the account name, and
instance.account_name=‘Valerie’ to set the account name.
Multiple Inheritance
In regards to multiple inheritance, it is important during object instantiation to not only initialize the
main object, but each instantiated superclass by calling the __init__() method for each superclass. Con-
sider the following modification on the Account class example. In this case, suppose Account inherits
from both Bank and Client. In that case, Account’s initialization includes initializing data for both Bank
and Client. When an Account is constructed, full data of each is expected in Account’s __init__()
signature, and the Account must then pass the appropriate initialization data to the superclass’ initiali-
zation methods.
7
1 Software Modeling and Object-Oriented Design
Following along to this example, we have Account derive from, or more specifically, inherit from the
classes Bank and Client. This is a case of multiple inheritance. A sketch of how to specify this in Python
is given below.
Bank.__init__(self, bank_record_data)
Client.__init__(self, client_record_data)
We see in this example the two superclasses for Account are Bank and Client and are specified in the
class definition. Also, the __init__() for Account has two additional arguments, one an unspecified
amalgam of data about the bank, and one about the client, which are used to initialize Bank and Client
respectively. Observe that the __init__() methods for both Bank and Client are called with the respec-
tive initialization data within the Account constructor. This is a very important step as it fills in critical
data for the superclass instance for each class.
Python supports many of the characteristics of object-oriented design touched upon earlier, such as
encapsulation, inheritance, and polymorphism. However, there is little to no data protection except by
convention11. Regarding interface, it effectively consists of the data variables and methods defined in
the class and is not a separate abstraction. Nonetheless Python does provide more than adequate object-
oriented support for implementing object-oriented design.
This concise description of Python classes goes a long way toward understanding how to use them,
and to understand how they are used in the context of this book. Further features of Python classes are
discussed as they arise in the text. As always, one can refer to the many excellent textbooks on Python,
such as [4] [5], for further information.
11
One often finds in Python that protected or private data is prefixed with a single underscore, and
methods with two underscores. This is simply a convention for protected data access, and not an out-
right enforcement.
8
1.4 The Meaning of Music Representation
example, is for the class hierarchy to expand from say three layers deep to five layers deep, even though
the initial model sufficed for the application. Some objects that were single inheritance become multi-
ple inheritance, and so forth. Sometimes these kinds of expansive architectures are quite necessary, and
sometimes they only burden the schema and coding effort needlessly, and in the end make an architec-
ture that becomes difficult to navigate with some largely useless design enclaves.
This happens many times on a first encounter with object-oriented design, when novices “see objects
everywhere”, and end-up coding to an ideal instead of a practical application. Perhaps the best practice
is that when deriving class schemas, watch for object types, relationships and inheritances that lack
relevance to the needs of the application and/or do not fill any application needs. At that point, it is
good to reconsider the current and future goals of the project design. As one simple example, if a
system designer feels a need to derive their own integer or real number class, it might be a good time
to retreat and question the true necessity for making that kind of decision and judge the necessity of
that impact across the application, now and in the future.
Correcting a schema after first application release can be a difficult and thankless task, especially when
removing these kinds of design elements.
Concurrency and Side-effects
It is important as well to not confuse the benefits of object-oriented design with general coding practice.
Depending on the application, you still must deal with for example, concurrency issues. You still must
deal with potential side-effects sometimes stemming from processing side-effects, e.g., unexpected
data value changes during transactions. These don’t go away simply because you use object-oriented
design, and sometimes a correct object-oriented design to address these issues can be difficult.
Still Requires Good Practice
This leads to the final consideration, that object-oriented design is not a panacea for treating all the ills
of programming. Many of those remain. We might point out, that even within the confines of object-
oriented design, you should be encouraged to devise meaningful class, variable, and method names,
and avoid cramming too much semantics into one place, for example, a Python file, i.e., putting multi-
ple classes into a single file.
While much has been accomplished in programming and program design over the last few decades,
application/system design and coding remain difficult tasks, and require skill, continual diligence, and
attention.
9
1 Software Modeling and Object-Oriented Design
knowledge gaps, and to acknowledge edge cases that are often overlooked, towards building a complete
and consistent view of the domain.
Music students should find this study interesting in that it necessarily entails rigorous definition of
music theory concepts, even to the point of articulating with precision the most fundamental ideas. For
example, what distinguishes tone from pitch? Many times, terms like these are used loosely and inter-
changeably, perhaps with meaning inferred from usage context. Here however, each concept, like any
of these, is defined with precision and accuracy. It is an essential point in software modeling that con-
cept definitions have well-defined semantics.
Computer science students accustomed to working with class hierarchy definitions will appreciate this
rigorous formalism on music theory.
10
2 The Chromatic Scale and the Diatonic Foundation
Among the most fundamental concepts of music training and music theory education are the sounds of
different tones or pitches12 on one or more instruments. We come to know and identify them and dis-
tinguish similarities and differences among them both within and across instruments. Eventually we
see them in larger coherent organizations, understanding tonal relationships in broader terms, such as
intervals, scales, and chords. Due to certain unvarying and recognizable characteristics about pitches,
these larger concepts have a marked stability that make music possible across the space of instruments.
With the help of educators, we learn the formal and larger organization of these concepts in what we
call music theory, and further apply this theory in music composition, analysis, and performance.
We begin our musical journey similarly with a focus on tones and pitches, and likewise explore their
structure around the chromatic scale as our starting point. From the chromatic scale, we look at seven
tones that become the foundation for naming all tones. As we will see later, these primitives build a
foundation for further music theoretical artifacts such as intervals, scales, chords, etc.
We begin with a brief informal survey of Western music foundations by examining the Pythagorean
scale and its subsequent evolution. Our exploration continues to the 12-tone equal-tempered chromatic
scale which defines the space of tones and pitches that will be used throughout the text. We develop
the diatonic or 7-tone structure that is imposed on the chromatic scale as a larger concept we term “the
diatonic foundation”. This structural relationship between diatonic tones and the chromatic scale is
core to the foundations of scales, intervals, and chords that are discussed in detail later.
We finally pivot to the software modeling viewpoint, developing tone and pitch Python classes as the
foundation of music representation in software. Subsequent music concept representations are built
upon the representations defined here. This co-development of music theory and software representa-
tion returns throughout the remainder of the book.
12
In informal discussion tones and pitches are many times used synonymously. Later these are more
precisely defined.
13
So named as being attributed to the famous Greek mathematician Pythagoras.
The construction of this ancient scale is based on creating pitches with frequencies based on fractions
or ratios one pitch’s frequency relative to another pitch’s frequency. This is sometimes referred to as
an interval, however, intervals have a more precise meaning discussed later. Select a pitch of some
frequency as a root pitch. For the root pitch, intervals relative to the root based on doubling that fre-
quency were considered in some sense related, of having a strongly discernable sameness. Other ratios
to the root pitch were also noted as significant. In particular, the root pitch’s frequency multiplied by
3/2 corresponding to a pitch a perfect fifth interval higher to the root was considered important. Two
pitches a perfect fifth apart were consider in some sense pleasing and were given the characterization
consonant, as were many pitches with intervals expressed as ratios of small integers, e.g., 3/2, 4/3, 6/5.
The root pitch frequency multiplied by 2/3 is the frequency of the perfect fourth to the lower identical
root (1/2 the root frequency). Accordingly, the frequency a perfect fourth above the root is 4/3 (2 * 2/3)
of the root frequency.
The process for generating a Pythagorean scale is based on using the perfect fourth and fifth intervals
just discussed. It involves generating 7 tones successively using each interval, and applying some ap-
propriate powers of 2 or 1/2 to the frequencies to contain the generated pitches within twice the root’s
pitch frequency, that is, making the pitches’ resulting ratios contained in the ratio range [1 .. 2]. This
results in deriving a sequence of notes between the two pitches considered nearly synonymous. In other
words, it derives a scale.
As a demonstration of Pythagorean scale derivation, consider Fig. 2.1 below which outlines the deri-
vation of the Pythagorean 12 tone scale. (We use standard note annotations here for referential purposes
only.)
Fig. 2.1 Pythagorean scale derivation using the factor 3/2 successively to the right, and 2/3 to the left. Each
column shows the doubling or halving necessary to get the ratio to within one octave, i.e., within the interval
[1 ... 2].
Starting at C we derive pitches a perfect fifth higher in succession to the right until F#, making 7 notes.
Then, starting at C, we derive the pitches a perfect fifth lower in succession to the left until Gb, again
making 7 notes. This gives a total of 13 pitches. The frequencies are normalized to C having a ratio 1.
According to construction, all the derived pitch ratios must be in the interval [1 .. 2]. To achieve this,
after applying the appropriate multiplier for the pitch ratio, we then reduce the pitch by applying suffi-
cient factors of 1/2 ( or 2 for fifths lower) so that the resulting ratio per pitch lies in [1 .. 2]. (Shown in
each column) We get our final 13 pitches. Then, sorting the resulting ratio values we have the resulting
scale shown in Fig. 2.2.
In total the construction produces 12 tones, akin to the Western 12 tone chromatic scale. However,
there is an issue. In the derivation of the 7 tones in each direction, there are two tones, F# and Gb, that
are quite close in ratio values but not the same. Ideally, we would like these to match to make a perfect
scale that we could repeat at double or half the root, and so forth. This misalignment causes problems,
12
2.2 Just Intonation and Equal-Tempered Chromatic Scales
which in that time were relieved with various pitch omissions [11]. In any case, despite its consonant
sounds, the Pythagorean scale is a flawed if not problematic scale system for music.
Fig. 2.2 Pythagorean Scale
Ratios,final ratios after reduc-
tion in Fig. 2.1
The eventual solution involves altering the factors to make the pitches in some sense “evenly spaced”,
while preserving the notion of consonant sounds that the ratio approach of the Pythagorean scale
achieved. As we will see, the eventual solution was to have identical ratios for any two consecutive
ascending pitches. This leads us to the discussion of the equal-tempered chromatic scale.
Fig. 2.3 shows ratios used for just intonation. The downside of this approach is that some instruments
so tuned will only sound good in the key to which it is tuned. Using other tones as keys will be out of
tune, and so the instrument needs to be re-tuned for other keys [12] (See exercise 2.4.1.)
Following to just intonation is the notion of well-tempered tuning, in which slight perturbations on
pitch tuning achieve making major and minor keys sound good on a keyboard. There are many such
schemes, with mixed results. Reference Werckmeister temperaments [13] for an example.
A variant of well-tempered tuning that eventually found widespread acceptance is equal-temperament,
resulting in an improved tuning scale over ancient scales in avoiding consonance issues, while provid-
ing pitch consistency across octaves. The idea behind well-tempering is that through 12 tones, any two
consecutive ascending tones have identical ratios, namely 2!/!# , or roughly 1.059, while by necessity
13
2 The Chromatic Scale and the Diatonic Foundation
successive octave pitches have a ratio of 2. The successive multiplication of each pitch’s frequency by
2!/!# for the successor pitch’s frequency results in evenness in the tonal space, while at the same time
approximating reasonably well the ancient ratio-based pitches providing consonant sounds. The scale
ratio uniformity also provides stability of tuning for other keys, i.e., one tuning is good for all keys,
avoiding the problems of just intonation, in addition to those of the Pythagorean approach. This 12-
tone equal-tempered system is sometimes referred to as 12-EDO or 12-TET.
Why 12 notes and not 10 or 15? In part at least, the answer is that 12 solves an optimization problem
that, remarkably, preserves the benefits of the just intonation consonant pitches while avoiding its def-
icits. In reference to Fig. 2.3, it turns out that “the twelve-tone equal-tempered scale is the smallest
equal-tempered scale that contains all seven of the basic consonant intervals to a good approximation
— within one percent — and contains more consonant intervals than dissonant intervals.”14 [14]
Furthermore, a 12-tone pitch set based on a root pitch can be extended to lower or higher pitch ranges
using the same equal-tempered ratio thereby extending to a larger range of pitches. For the purposes of
this book, any range of pitches derived in this manner from the 12-tone equal-tempered scale is called
a chromatic scale and is the foundation for the tonal space referenced throughout the remainder of the
book.
While the above provides a constructive means for computing chromatic pitches, the precise pitch
range of chromaticism must be determined. More precisely:
• What is the frequency range of the chromatic scale that we will consider? That is, what are
the lowest and highest pitch frequencies?
• Is there one frequency that can be selected as a tonal center for the chromatic range, from
which all other pitch frequencies can be derived using the equal-tempered ratio of 2!/!# ?
Knowing the answer to the second question, lower and higher pitches are easily computed. But how
many? Where does it start and end?
The answer to the second question, based on tuning standards, is 440hz15 [15], which is what we know
as the A above middle C, notated as A4. As to the first question, there is no definitive answer as each
musical instrument is constrained to specific natural ranges. However, the range of the modern standard
keyboard is broad, well established and encompasses the pitch ranges of nearly all other commonly
used musical instruments. The keyboard range is from 4 octaves below A4 to 4 octaves above middle
C (C4), for a total of 88 individual pitches based on the equal-tempered scale. Notationally, these refer
to A0 and C8 respectively. We refer to any two successive pitches of these 88 pitches as being a sem-
itone, or half-step apart.
As an exercise for understanding the chromatic scale structure introduced above, we break down a
pitch reference as tone and octave and address how to index each pitch in the chromatic scale. We then
show how to compute between the pitch’s reference structure and its index in the chromatic scale.
As there are 12 sequential chromatic pitches per frequency doubling, the 88 semitones are divided into
adjacent groupings, each comprising 12 consecutive semitones. The convention we use is for each
group to start on a C pitch. Each group is called a chromatic partition or simply partition, or octave.
In this manner, any semitone in the chromatic scale can be designated by a combination of an octave
number and a 0-based16 offset into the partition. We assume octave numbering is also 0-based in such
14
The basic consonant intervals are octave, perfect fourth, and fifth, major and minor third, and
major and minor sixth.
15
Hz or Hertz is a unit of frequency taken to be one vibrational cycle.
16
0-based means the first offset is 0. In 1-based, the first offset is 1.
14
2.2 Just Intonation and Equal-Tempered Chromatic Scales
a way that C4’s octave is the fourth octave. We call this pair of numbers the pitch’s chromatic location,
i.e.,
(octave number, offset in octave)
Expressed as chromatic locations, the chromatic scale then comprises the pitches:
(0, 0), (0, 1), ... (0, 11), (1, 0) ... (1, 11), (2, 0) ...
Using this notation, the standard keyboard range is from (0, 9), the lowest A on the keyboard, to (8, 0),
the highest C on the keyboard. Again, we use 0-based numbering for octave and tonal offset, i.e.,
partition 0 is the first partition, and semitone 0 is the first pitch C. Note that (4, 0) corresponds to middle
C, and (4, 9) to the A above middle C that is usually 440hz, as mentioned earlier.
Looking at this another way, the pitches in the chromatic scale are sequential and so can be counted or
indexed, again 0-based. Going with that scheme, (0, 0) corresponding to index 0, and A0 or (0, 9)
having index 9. Fig. 2.4 shows these relationships.
Conversions between chromatic location and index are based on the formulas:
𝑖𝑛𝑑𝑒𝑥 ( 2.2 )
𝑖𝑛𝑑𝑒𝑥 = ( , 𝑖𝑛𝑑𝑒𝑥 % 12)
12
The division by 12 above is integer division, meaning use the integer part and discard the fractional
part or remainder.
To clarify on terminology, in discussing tones we are talking about any of the 12 semitones of an
octave, regardless of octave. For example, the 3rd tone (D) refers to the 3rd semitone in any partition.
Consequently, there are only 12 tones. Pitch, however, references both the partition number and the
tone’s offset. Recapping, tone references to the offset in any octave location, but pitch is a precise
chromatic location.
15
2 The Chromatic Scale and the Diatonic Foundation
class as a static class meaning that it contains only static methods and constants. There is an argument
that static classes make for a less preferable representation of global characteristics, and that instead,
non-class (i.e., global function) based code would be a qualitatively less complex representation with
equal efficiency. However, for pedagogical purposes, we generally insist on looking at the world in
terms of classes and class instances. Besides, global static data and methods wrapped as a class provide
a consolidation of related global elements under a unified theme or concept. The class provides a global
singular reference point for related activity and data. Furthermore, doing so preserves viewpoint con-
sistency over the entire code base, wherein everything is viewed through an objectified lens.
The ChromaticScale class is of limited use in the code base and exists mainly to summarize the topics
of this chapter as well as easing into case studies of Python classes for musical elements. More expe-
rienced programmers may ask why not used the singleton design pattern (refer to [10]) for the imple-
mentation. The answer is that the topic here does not require that level of complexity. For example,
this class does not rely on more complex superclasses, nor does it require cloning or the like.
A portion of the ChromaticScale class definition is shown below. The class consist of constants that
are static to the class as well as a number of methods which are also static. In the case of the methods,
the Python decorator “@staticmethod” declares that the following method is static for the class. As
with chromatic locations discussed earlier, we represent pitches as Python tuples of numbers (octave,
offset). The methods above replicate the two conversion formulas ( 2.1 ) ( 2.2 ) presented earlier.
class ChromaticScale:
NUMBER_OF_SEMITONES = 12
CHROMATIC_START = (0, 9)
CHROMATIC_END = (8, 0)
CHROMATIC_FORM = r'([0-8]):(10|11|[0-9])'
CHROMATIC_PATTERN = re.compile(CHROMATIC_FORM)
. . .
@staticmethod
def location_to_index(pitch):
return ChromaticScale.NUMBER_OF_SEMITONES * pitch[0] + pitch[1]
@staticmethod
def index_to_location(index):
return index // ChromaticScale.NUMBER_OF_SEMITONES, index %
ChromaticScale.NUMBER_OF_SEMITONES
@staticmethod
def parse_notation(notation):
n = ChromaticScale.CHROMATIC_PATTERN.match(notation)
if not n:
return None
return int(n.group(1)), int(n.group(2))
16
2.3 Tones, Pitches, and the Diatonic Foundation
• SEMITONE_RATIO: denotes the value 2!/!# , which is the multiplier to derive a tone’s fre-
quency from its predecessor tone’s frequency.
This class introduces a powerful Python means for converting strings to binary information that can be
used within representational objects or for calculations. This technique is used frequently in the code
base. In this simple case, we convert a textual pitch location expression into a Python tuple for chro-
matic scale reference. For example, we can parse the text “4:6” (meaning octave 4, offset 6) into the
Python tuplet (4, 6). Python regular expressions are discussed thoroughly in [16]. The pattern for this
case is held by static variable CHROMATIC_FORM as r’([0-8]):(10|11|[0-9])’. The ‘r’ means the text
should be understood as a regular expression. This expression can be read as “start with an integer
between 0 and 8, followed by a ‘:’, followed by an integer between 0 and 11”.
The seemingly odd positions of 10 and 11 in the regular expression simply give parsing precedence to
10 and 11, where if placed after [0-9], the parser would pick up 1 and ! on the second 0 or 1. The
regular expression is then processed or “compiled” into a Python pattern, the result of which is held by
CHROMATIC_PATTERN. The static method parse_notation() takes a string input, matches it against
the pattern, and returns the chromatic location, octave and offset, as a Python tuple (after conversion
from string to integer).
Here is a simple example of these static methods’ usage:
To see further examples of ChromaticScale usage, the reader is encouraged to read, run, and step
through the corresponding test file test_chromatic_scale.py.
17
2 The Chromatic Scale and the Diatonic Foundation
Fig. 2.5 Tonal Positions in the Diatonic Foundation. This figure shows seven
basic diatonic tones (shorter arrows) along with the remaining five tones
(longer arrows being chromatic modifications to the seven.
The position of the basic diatonic tones, i.e., C through B, over a 12-tone octave is given by a list of
distinct semitone offsets {0, 2, 4, 5, 7, 9, 11} from the beginning of the octave, which correspond to
{C, D, E, F, G, A, B}. The remaining five tones arise through augmentations of neighboring basic
tones. The standard augmentations are given by the symbols {bb, b, #, ##} which correspond to { -2, -
1, 1, 2} semitone offsets respectively. These specify deviations on basic tones to derive the augmented
tones.
More precisely, a diatonic tone is specified by a basic diatonic tone label (e.g., C, D, …) in combination
with any one or none of the augmentation symbols (e.g., Ab, C#). For example, F## is a diatonic tone
based on F and the ## augmentation. This tone’s chromatic offset is 5(F) + 2(##) = 7, and Gb is chro-
matic offset 7(G) - 1(b) = 6. For completion, but not shown in the above diagram, for C there is Cb,
Cbb; for B, B# and B##.
Based on the above arguments, diatonic tones are not unique to chromatic offset. In other words, a
chromatic offset may correspond to several tones. To list a few, for offsets 3 and 6 respectively,
D# == Eb == Fbb, F# == Gb == E##
The tones in these equivalences are called enharmonic tones. While the existence of enharmonic tones
may seem problematic, or at worst a flaw to the diatonic system, they provide a solid foundation for
scale construction. Later we will see which enharmonic is used for a tone in a scale is contextually
based and logical and determined by the type of the scale within which one is working.
It is important to point out that the diatonic foundation as described here is a fixed conceptual structure
that provides a map of pitches to sound frequencies, an ordering and structuring of tones within all
octaves and for all pitches, along with tone and pitch naming. It is a foundational artifact for the rest of
music theory as described here. While its layout is observed to be identical to the C major scale, that is
in fact incidental. Major scales are constructed relative to any pitch on the diatonic foundation.
Each octave starts on C and comprises a collection of 12 diatonic tones. Octaves are numbered 0, 1, 2
... The terms chromatic partition, partition, and octave are often used interchangeably and that usage
should be noted particularly in the Python code.
The combination of an octave with a diatonic tone is called a diatonic pitch. A textual representation
for a pitch is “tone:octave”17. For example, middle C is “C:4” and the standard A 440hz pitch is ”A:4”.
An equivalent tuple-based representation more suitable for programming and algorithms is the diatonic
location representation of (octave, diatonic pitch), such as (5, C#), (3, D), (6, Fbb), etc., which will be
seen later.
17
This is synonymous to what is known as Scientific Pitch Notation (ref. ref. https://en.wikipe-
dia.org/wiki/Scientific_pitch_notation).
18
2.3 Tones, Pitches, and the Diatonic Foundation
class DiatonicTone(object):
# Constructor
def __init__(self, diatonic_name):
diatonic_info = DiatonicTone.parse(diatonic_name)
if not diatonic_info:
raise Exception('Illegal diatonic pitch specified {0}'.format(
diatonic_name))
self.__diatonic_letter = …
self.__augmentation_symbol = …
self.__diatonic_symbol = self.diatonic_letter + self.augmentation_symbol
self.__diatonic_index = …
self.__augmentation_offset = self.__tonal_offset = …
self.__placement = …
We begin by looking the data DiatonicTone keeps per instance that defines what a diatonic tone repre-
sents, shown above. The constructor takes the name of the tone as string, parses it, using a parser much
as was introduced in ChromaticScale. Looking inside the constructor code we see seven fields define
the object. With that, we have the following fields:
• __diatonic_letter: the letter part of the tone e.g., the C in C#.
• __augmentation_symbol: The augmentation part if any, e.g., the # in C#.
18
This is surprising given the significance of the A:4 tuning mentioned earlier.
19
2 The Chromatic Scale and the Diatonic Foundation
• __diatonic_symbol: a standardized textual format for the tone, e.g., C#, using upper case for
the diatonic letter, even if specified as “c#” in constructor input.
• __diatonic_index: index of diatonic letter, e.g., C—>0, D—>1, E—>2, etc.
• __augmentation_offset: numerical value of augmentation, e.g., bb—>-2, ##—>2.
• __tonal_offset: chromatic offset of the diatonic letter plus the augmentation_offset.
• __placement: the actual position (offset) for the note on a 12-tone partition. See below.
The distinction between tonal_offset and placement is very important and deserves explanation. Dia-
tonic locations can sometimes ‘spill over’ to neighboring octaves, as we will see with pitches. For
example, Cb:5 is identical to B:4, and B#:5 is identical to C:6. The attribute tonal_offset provides an
offset relative to the start of an octave. In that case, Cb has -1 as the tonal_offset, and 12 for B#.
Placement indicates which of the 12 tones (origin 0) in an octave the tone represents, accounting for
tonal_offsets that are out of the [0, 11] range. In this case Cb is 11 (B), and B# is 0 (C). The attribute
tonal_offset is useful in calculations across the full chromatic scale, especially for determining the
actual octave a pitch is in. The attribute “placement” on the other hand precisely points out the correct
tone regardless of partition.
class DiatonicTone:
# Basic diatonic tone letters.
DIATONIC_LETTERS = list('CDEFGAB')
# Regex used for parsing diatonic pitch.
DIATONIC_PATTERN_STRING = '([A-Ga-g])(bbb|bb|b|###|##|#)?'
DIATONIC_PATTERN = re.compile(DIATONIC_PATTERN_STRING)
# Diatonic C scale indices
DIATONIC_INDEX_MAPPING = {'C': 0, 'D': 1, 'E': 2, 'F': 3, 'G': 4, 'A': 5, 'B': 6}
# Semitone offsets for all diatonic pitch letters
CHROMATIC_OFFSETS = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
# All augmentations in text representation
AUGMENTATIONS = ('bbb', 'bb', 'b', '', '#', '##', '###')
AUGMENTATION_OFFSET_MAPPING={'': 0, 'b': -1, 'bb': -2, 'bbb': -3, '#': 1,
'##': 2, '###': 3}
DIATONIC_OFFSET_ENHARMONIC_MAPPING = {
0: ['C', 'B#', 'Dbb'],
1: ['C#', 'B##', 'Db'], …
Diatonic tone includes several constants that are useful across the code base, such as:
• DIATONIC_LETTERS: the list [C, D, E, F, G, A, B].
• DIATONIC_INDEX_MAPPING: giving the index of a diatonic letter.
• CHROMATIC_OFFSETS: giving diatonic letters to chromatic offset.
• AUGMENTATIONS: listing the valid set of augmentations as string.
• AUGMENTATION_OFFSET_MAPPING: mapping augmentation (string) to a displace-
ment value.
• DIATONIC_OFFSET_ENHARMONIC_MAPPING: For each offset, the set of enhar-
monic diatonic symbols.
20
Other documents randomly have
different content
TALES of an INDIAN CAMP. In 3 vols. post 8vo. 31s. 6d.
1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside
the United States, check the laws of your country in addition to
the terms of this agreement before downloading, copying,
displaying, performing, distributing or creating derivative works
based on this work or any other Project Gutenberg™ work. The
Foundation makes no representations concerning the copyright
status of any work in any country other than the United States.
1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if
you provide access to or distribute copies of a Project
Gutenberg™ work in a format other than “Plain Vanilla ASCII” or
other format used in the official version posted on the official
Project Gutenberg™ website (www.gutenberg.org), you must,
at no additional cost, fee or expense to the user, provide a copy,
a means of exporting a copy, or a means of obtaining a copy
upon request, of the work in its original “Plain Vanilla ASCII” or
other form. Any alternate format must include the full Project
Gutenberg™ License as specified in paragraph 1.E.1.
• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”
• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.
1.F.
Most people start at our website which has the main PG search
facility: www.gutenberg.org.