CS 3005: Programming in C++
Score Editor
Introduction
We are beginning the score editor program that will allow the user to create, edit, save, load, and render scores. Rendering a score is converting it into a WAV file. Saving and loading are using a custom text format. Editing will allow changing instruments, notes, and mixers.
Assignment
The score editor is a new program, similar in structure to the instrument designer program. It will reuse some commands from the menu test and instrument designer programs, and create many new commands. Here are the commands that are required for this assignment.
Command | Prefixable? | Function | Description |
help |
no | menuUI |
Display help message. |
menu |
no | menuUI |
Display help message. |
# |
yes | commentUI |
Skip to end of line (comment). |
comment |
no | commentUI |
Skip to end of line (comment). |
echo |
no | echoUI |
Echo back the arguments given. |
quit |
no | quitUI |
Terminate the program. |
score-list-waveforms |
no | listScoreWaveformsUI |
List waveforms in the score. |
score-add-waveform |
no | addScoreWaveformUI |
Add waveform to the score. |
score-edit-waveform |
no | editScoreWaveformUI |
Edit waveform in the score. |
Example Session
$ ./program-score-editor/score_editor
Choice? menu
Options are:
# - Skip to end of line (comment).
comment - Skip to end of line (comment).
echo - Echo back the arguments given.
help - Display help message.
menu - Display help message.
quit - Terminate the program.
score-add-waveform - Add waveform to the score.
score-edit-waveform - Edit waveform in the score.
score-list-waveforms - List waveforms in the score.
Choice? score-add-waveform
Waveform name: sin1
Waveform type: sine
Amplitude: 0.80
Choice? score-add-waveform
Waveform name: squ1
Waveform type: rectangle
Unable to create a waveform of type 'rectangle'.
Choice? score-edit-waveform
Waveform name: sin1
Amplitude(0.8): 0.90
Choice? score-edit-waveform
Waveform name: squ1
Unable to find a waveform with name 'squ1'.
Choice? score-list-waveforms
sin1 : sin1 sine 0.9
Choice? quit
Programming Requirements
Update library-waveform/Waveform.h
- Add
const std::string AMPLITUDE = "AMPLITUDE";
as a global constant. This can be used by theScoreReader
to reduce the number of “magic” strings.
Create library-score/MusicalScore.{h,cpp}
We will start the MusicalScore
class by adding the Waveforms
collection. Future assignments will add more to the class.
MusicalScore
Class
This class will store all of the information for a piece of music.
Data Members:
- A
Waveforms
collection object for storing all waveforms that may be used in the music.
public
Methods:
MusicalScore();
Allow theWaveforms
object to be default constructed. Nothing else to initialize.Waveforms& getWaveforms();
Return the data member.const Waveforms& getWaveforms() const;
Return the data member.
Create library-score/Makefile
This file is responsible for making a library named libscore.a
, and installing it and its header files.
Create library-score-io/ScoreReader.{h,cpp}
We will start the ScoreReader
class by adding the ability to read Waveform
objects. Future assignments will add more to the class.
ScoreReader
Class
This class will eventually read all of the information for a piece of music from the .score
file format.
Data Members:
No data members are required.
public
Methods:
ScoreReader();
Nothing to initialize.virtual ~ScoreReader();
Nothing to clean up, but required.void readScore(std::istream& input_stream, MusicalScore& score) const;
Reads a score from the input stream. At this time, this method recoginizes onlySCORE
,SCORE-END
andWAVEFORM
keywords. If it finds any other words, it will ignore them. If the input doesn’t start with aSCORE
keyword, it will fail by returning immediately. If the stream ends before encountering aSCORE-END
keyword, it will fail by returning immediately. If the input stream contains aWAVEFORM
keyword, it will read the waveform from the stream by calling thereadWaveform
method.std::shared_ptr<Waveform> readWaveform(std::istream& input_stream, MusicalScore& score) const;
Reads Waveform from the input stream. When this method is called theWAVEFORM
keyword will have already been read from the stream. Read the rest of the information. Notes: 1) if the waveform name already exists in the waveforms of the score, just read the information from the stream, but do not change the existing waveform or create a new one. 2) If the waveform name does not already exist in the waveforms of the score, create a new waveform with the factory and configure the waveform based on the information in the stream; then add the waveform to the score’s waveforms. 3) Must stop and return if theWAVEFORM-END
keyword is encountered, or the stream ends. 4) Must also recognize theAMPLITUDE
keyword and read the amplitude value. 5) Any other keyword will cause the function to immediately return. 6) The return value is either the waveform that was created or already exists, or a null pointer if a bad keyword was found or the stream ended without encountering aWAVEFORM-END
keyword.
Create library-score-io/Makefile
This file is responsible for making a library named libscore-io.a
, and installing it and its header files.
Update library-application/ApplicationData.{h,cpp}
We will update the ApplicationData
class to have a MusicalScore
member.
ApplicationData
Class
Note there is no need to change the constructor, as the MusicalScore
default constructor will create an empty MusicalScore
object, just fine.
Data Members:
- A
MusicalScore
object.
public
Methods:
const MusicalScore& getScore() const;
Return the data memberMusicalScore& getScore();
Return the data member
Create library-commands/score_editor_aux.{h,cpp}
Commands created for the score editor program will go here. We’ll make a few in this assignment, and add more in future assignments.
Functions:
void listScoreWaveformsUI(ApplicationData& app);
Lists all of the waveforms in theApplicationData
object’sMusicalScore
object. Uses the format shown in the example.void addScoreWaveformUI(ApplicationData& app);
Prompts the user for the information for a newWaveform
. Uses the format shown in the example. Uses the factory to create a new object, configures the object, and stores in the waveform collection of the score. If the factory fails, then gives an error message.void editScoreWaveformUI(ApplicationData& app);
Prompts the user for the name of a waveform. If it exists, prompts for the information to change. Uses the format shown in the example. If the waveform does not exist, gives an error message.int register_score_editor_commands(ApplicationData& app_data);
Usesregister_menu_test_commands(app_data);
to pick up some of the required commands for this task. Also uses theaddAction
method to add the other commands to the menu.int score_editor(ApplicationData& app_data);
Registers the score editor commands, then usesmainLoop()
. Returns 0.
Create program-score-editor/score_editor.cpp
Functions:
int main();
Entry point to the instrument designer program. Should create anApplicationData
and pass it to thescore_editor
function and return the result of that function call.
Create program-score-editor/Makefile
This file must contain rules such that any of the following commands will build the score_editor
program:
make
make all
make score_editor
Create program-score-editor/.gitignore
The file needs to store one line of text:
score_editor
This will prevent the executable program from being committed to the repository. It is a derived file.
Update Makefile
- Update the project-level Makefile so that
make
andmake all
in the project directory will callmake
in theprogram-score-editor
directory. - If necessary, make sure the order of make commands is correct to build prerequisite libraries in the correct order.
Additional Documentation
- None
Grading Instructions
To receive credit for this assignment:
- your code must be pushed to your repository for this class on GitHub
- all unit tests must pass
- all acceptance tests must pass
- all programs must build, run, and execute as described in the assignment descriptions.
Extra Challenges (Not Required)
TBA
Last Updated 03/27/2025