CSC 161 Module 5: Music Composition with Dynamic Data Structures
Summary and Main Topics
The purpose of this module is to cover pointers, and their use in common self referential data structures, such as linked lists, in detail. The main topics covered are:
- pointers
- linked lists
Day-by-day Details
| Day | Topic | Preparation | In-class | Due Date | Availability for Extra Credit |
|---|---|---|---|---|---|
| Wednesday, November 2 | Pointers | Review:
| list-example.c | ||
| Monday, November 7 | Pointers | Read:
| Pointers Lab | ||
| Tuesday, November 8 | Linked Lists |
Review:
| Scheme-like Linked Lists Lab | Friday, November 11 | |
| Wednesday, November 9 | Linked Lists | Linked Lists and Robots Lab | Wednesday, November 23 | ||
| Friday, November 11 | Project: Myro Maestro |
Reading: Doubly-Linked Lists
Understand: myro-maestro.c Experiment: myro-maestro (compiled code) | Project: Myro Maestro | Friday, November 18 | |
| Monday, November 14 | Project: Myro Maestro | Project: Myro Maestro | Friday, November 18 |
Project: Music Composition Myro Maestro
Introduction
When developing a song, a composer may have an initial idea for a melody, including pitches (frequencies) and durations (length of the pitch). After writing down some first ideas, the composer likely will want to edit the melody: altering some notes, adding new notes, removing others, reordering notes, etc. Also, since composing may take place over several sessions, the composer may want to save work from one session and then load it later on to continue.
This project is designed to support this melody composition process through the development of a program, myro-maestro.c.
Picking Data Structures
In considering how to store a single note, the natural choice is a struct with fields for pitch and frequency. The choice for an entire melody requires some analysis.
- A melody may contain any number of pitches.
- The composer may want to insert, delete, or modify notes anywhere within the melody.
- In working with a melody, the composer may want to move forward or backward from one note to another as part of the editing process.
The need for flexibility suggests a linked structure be used. To use an array, we would need to determine how long the array should be. Further, insertion within the array would likely require moving many existing notes down to make room for the new addition. Deletion of a note would likely require moving many existing notes toward the start to take up the place of the deleted note. Linked lists do not have size or ordering constraints, so linked lists seem better suited to the storage of note information than arrays.
Unfortunately, all pointers in singly-linked lists move from the beginnning to the end. If a composer wants to move backward in editing a melody, then work with a singly-linked list would require constant searching from the start of the melody to find a desired note.
Thus, to provide flexibilty, we consider the use of a doubly-linked list. From each node, one pointer indicates the previous node and another pointer indicates the next.
To enable work on the melody, the program will keep track of a specific note in the song; this is the current editing point for the composer. Also, we include an ID for each note, so the composer can easily moved the editing point to any desired note. To clarify this ID further, collaborator David Cowden adds this comment:
The id field is used to uniquely identify an individual node in the case where your list may include duplicate data. To understand why this is necessary, consider the case where you have 7 G's and 2 B's in your song. If you want to remove one of those G's, you need to refer to that G by a unique name. This is where the id field comes in. If the 7 G's all have a different id (say 2, 3, 4, 5, 6, 7, 8 respectively), you can remove the 3rd G by removing the node with id=4.
Putting these pieces together, the first 5 notes of Spirit Song (from the Getting Started Module) might be represented as follows:
In reviewing this figure, the five frequences (pitches) and times (durations of notes) are from Spirit Song. Also, the figure suggests that the composer first entered the third and fourth notes (with IDs 1 and 2), then decided to go back to the beginning to add the first two notes (with IDs 3 and 4), and then added a fifth note at the end (with ID 5). The song variable points to a node within the song (in this case, the second node in the melody).
Refer to the reading on doubly-linked lists for more details related to these doubly-linked structures. Note, however, that this application does not require a first or last pointer for the doubly-linked lists. Only one pointer song is maintained, and the composer moves that pointer forward and backward as a melody is developed.
Organization of Program
Since writing a full melody-editing program requires substantial work, development of this application involves two main steps:
- Implementation of a doubly-linked list, based on a carefully-defined collection of operations.
- Use of the doubly-linked list operations in an application program.
Current Status of the Work
As this project begins, collaborator, David Cowden, has already written the application program, called myro-maestro.c. Thus, you do not have to write this program, although you are welcome to review the code, if you wish.
Further, a header file, dnode.h, has already been started to identify procedures and implement the doubly-linked list framework. Specifically, the doubly-linked list for this project involves these declarations:
typedef struct Note {
int freq;
double time;
} Note;
struct dnode {
Note data;
int id;
struct dnode * next;
struct dnode * prev;
};
typedef struct dnode * dnode_t;
In reviewing this framework, a Note is a struct with two fields (for frequency and time), and a node on the doubly-linked list (a dnode) contains a Note, the node's ID, and pointers to the previous and next nodes in the melody.
At present, dnode.h contains stubbs for each procedure, so that application myro-maestro.c compiles. However, myro-maestro.c does not work, because many details are missing in the implementation of the procedures for dnode.h. This leads to your work for this project.
Draft Compiled Program
To gain experience with the myro-maestro.c, a compiled draft program may be downloaded and run. Feel free to try out this program to get a sense of how the overall program is expected to work.
Doubly-Linked List Music Management
Working in pairs, students should implement dnode.h — the backend for the myro-maestro.c application. Once the header is correctly implemented to an object file, myro-maestro will function correctly.
Although the myro-maestro.c application provides some testing for dnode.h, this is not sufficient testing to prove your library functions are working correctly. You will need to develop a "driver" program that tests all the limits of your library. This driver should comprehensively test all cases that may arise when creating and editing doubly-linked lists such as:
- What happens when you try to insert something into a null list?
- What about at the beginning and the end of a list?
- What happens when you delete a null node?
- etc...
* As a bonus: the myro-maestro program will also facilitate saving and loading the linked list data to a specified binary file. This will come in handy if students end up writing lengthy songs (..because the program is so cool)!
Grading
This project will be worth 25 points, based on the following rubric:
- 12 points: Complete, working, correct, implementation of the dnode.h header.
- 10 points: Tests that show the functions listed in dnode.h (implemented in dnode.c) work correctly, and work properly even for boundary conditions. No segfaults!
- 3 points: A performance of your new smashing hit single as developed in Myro Maestro and performed by your Scribbler itself!
Extra Credit:
- 8 points: The myro-maestro.c contains a range of
interesting techniques. The following groups of procedures have common
approaches. Write an explanation of how each group works (2 points
each):
- editor, main, promptINT, promptUINT, and promptDBL
- advance, nAdvance, retreat, and nRetreat
- printNode, printSong, playNote, playSong, goStart, goEnd, findID
- addNoteBefore, addNoteAfter, changeNote, and removeNote
- 8 points: Add up to four new operations to the myro-maestro.c editor functions. An example might be an option that adds N number of the same note in a row. (Grading: up to 2 points possible per operation)