代写Project 1 - Note Player代做Java程序

2024-12-14 代写Project 1 - Note Player代做Java程序

Project 1 - Note Player

Introduction

The objective of this assignment is to play music entered by the user as a list of notes.  Your user will type a song (a list of notes), and then your Note Player will play that song, ready to accept a new song.  The user can repeatedly enter song after song, with your Note Player playing each one in turn.  The user exits the program by entering the command “quit" instead of a song.

We will guide you through the project using a series of checkpoints.  Each checkpoint will add a little more functionality, until your project is complete.

I don’t know anything about music!

Perfect.  This project doesn’t require any knowledge of music, and this document tells you all you need to know.  What we do expect you to know are String methods (indexOf and substring), Scanner, and later on, if/else and while loops.

Code Organization

Your code will start executing in your main method, as usual.  Beyond that, it’s up to you how to organize your code.  We’d recommend factoring your code: breaking up tasks into small methods and avoiding duplicating code by using helper methods.  This will be easier for you to manage than stuffing all your code into main.

Comments

· The topics we have been learning in class are designed to allow you to complete this assignment. Remember to review your notes and the textbook.

o Scanner, indexOf, substring, etc.

· You are not allowed to use any Java features that we have not yet covered in our class.  For example, you may NOT use arrays (or anything that involves arrays), you may not define any new classes and objects (use only the NotePlayer class we give you in your starter project), you may not use exception handling, or anything else not yet covered in our class.

· Use the unit tests!  There is no penalty for running tests and failing a lot.  We only grade the test results for the version that you choose to turn in for each checkpoint.  See the Student GitHub Instructions document for details on how to do this.

· You can assume we will never give you input that would exceed the range of MIDI Note numbers (e.g., we will never give you Cb-5, as that would be -1, which would be outside the range).

Getting Started

Import the NotePlayer Starter Project

These are the same instructions as those for importing your Classwork project, except the project name is different:

1. Find the github URL for your starter project.  The easiest way to do this is the following:

a. Go to https://buildci318.com/

b. Click on the “Projects” tab along the top

c. You should see a tile for NotePlayer, with a “Copy Project Link” button.  Press it!

d. The URL for your starter project is now in your clipboard, ready to paste into Eclipse

2. IF the above doesn’t work for some reason, you can grab the URL from github instead.  Do this ONLY if the above doesn’t work for you.

a. In Chrome, go to https://github.com/BHS-APCS

b. You should see the list of your projects.

c. Click on the NotePlayer result (should look like NotePlayer_<LastName><FirstName>), and then copy the URL to your clipboard.  It will be something like: https://github.com/BHS-APCS/NotePlayer_<LastName><FirstName>.

3. Start Eclipse.

4. Go to “File” -> “Import”, and select “Git” -> “Projects from Git.” NOT with “smart import”

5. Click “Clone URI” and click next.

6. Fill out the form.

a. In the URI box, paste the URL you copied to your clipboard (often, Eclipse will paste this for you automatically)

b. In the User box, enter your GitHub username.

c. In the Password box, enter your GitHub password.

d. Check “Store in Secure Store,” so you don’t have to keep typing your password.

Here is an example:

Type this line in as you see it here, but use the link you found in step 1 or 2 

Leave these, they get populated automatically 

Type in your github username and password, and ensure the ‘store in secure store’ is checked

7. Click next. Make sure “master” is the only branch checked. (Uncheck any other branches that may be checked.) Click next/next/next/finish.

Working from Home and School

You should always use this pattern, or else you will cause Eclipse errors making it impossible to work on your project:

1. Whenever you sit down to work—either at home or school—always PULL first.  (See Student GitHub Instructions document in your OneNote.)

a. This refreshes your computer with the latest version stored on github.

b. Note: The plug-in initiates this for you automatically when you launch Eclipse.  If you left Eclipse open when you last took a break (not recommended!) you’ll need to pull manually.

2. Whenever you are ready to take a break, always COMMIT AND PUSH.  (See Student GitHub Instructions document)

a. This uploads the changes you just made up to github.

b. Note: The plug-in initiates this for you automatically when you close Eclipse.  Don’t just put your computer to sleep—always close Eclipse first so it forces the Commit + Push.

c. You can & should Commit + Push even more often than when you take a break.  Great way to back up your changes, and the only way to force the tests to rerun when you make fixes.

3. If you forget either of the above steps, you will encounter a merge conflict, and pushing / pulling will start failing.  See the Student GitHub Instructions doc for how to deal with this situation.

Checkpoint 1: Parse and print first note symbol

Example input: A_600 B_450 C_1

The goal of this checkpoint is to read a line of input from the user, find the first note symbol, and break it up into its letter and duration, which you will print to the screen.  Here is an example of what the line of input from the user might look like:

A_600 B_450 C_1

First, you’ll notice a capital letter (the note letter, such as A), an underscore (_), and then an integer (the duration, like 600):

A_600

The sequence of characters “A_600” is called a note symbol.  After this note symbol will be a single space, and then another note symbol and space, and then another, etc.  The line might contain 2 note symbols, or 10, or 100.  All you can be sure of is that, for checkpoint 1, there will be at least 2 note symbols (separated by a space).

This checkpoint is a small step toward your final project and can be done in about six lines or so.  Read carefully!

· All Checkpoint1 Tests must pass

· You will create a Scanner and read one line of input (this is the “note list”)

· You will find the very first note symbol in the note list (the letter, underscore, and duration integer), break it up into the note letter and the duration, and then print them using the following format shown below

· All other note symbols on the line may be ignored.

· For now, you can assume there will be at least two note symbols, so you can rely on a space appearing after the first note symbol

When printing the first note symbol, you must use the following format exactly:

note letter: <letter>, duration: <duration>

For example, an input of A_600 B_450 C_1 should cause you to print:

note letter: A, duration: 600

There must be a single space after each colon (:) and comma (,).  Do not print the angle brackets <>.  Also, ensure that you print the above message on its own line.  For example, if you wish to print a prompt when your program begins (such as “Enter note symbols:”), that’s ok, but be sure that the prompt is printed with a println so that Java moves to the next line when it’s done.  This way when you print the note letter and duration, it will start on its own line.

Hint:

· Study the Java substring and indexOf String methods

Checkpoint 2: Play entire note list, ignore accidentals

The goal of this checkpoint is to start playing some music!  You will find every note on the line and play them all.  Read carefully!

For this checkpoint we’re adding a concept called an “accidental” that may appear after the note letter.  You may ignore the accidental for now, but don’t let it interfere with your code that parses the note symbol.  You will need to interpret the note letter to come up with the correct tone to play. 

Note Symbol Part 1: Note Letter (Checkpoint 2)

The note letter is any capital letter from A through G.  Your job is to convert this letter into a “MIDI Note Number” that the sound card uses to produce a sound.  The following table shows this relationship.

Note Letter

MIDI Note Number in octave 0

C

60

D

62

E

64

F

65

G

67

A

69

B

71

You’ll notice that table begins with C as the lowest MIDI Note Number instead of A.  You’ll also notice the numbers sometimes go up by 1, and sometimes by 2.  Yeah, music is weird.  Just go with it.

For now, you may ignore the words “in octave 0” in the table above.

Note Symbol Part 2: Note Accidental (Checkpoint 2)

The note accidental is sometimes present, but not always.  It can either be a sharp “#” (hashtag symbol) or a flat “b” (lower-case letter b).   For checkpoint 2, you may ignore the accidental.  But make sure your code doesn’t get confused by the presence of an accidental when trying to find the note letter and duration number.

Note: Each note is followed by either no accidental, or one accidental, but never both accidentals.

Note Duration

The note duration is the length of time (in milliseconds) to play the note.  It always appears after the note symbol’s underscore (_).

This part is easy.  You’ll just take the note duration number and pass it directly to the playNote method as its second parameter (see Output section below).

Output

When your Note Player has determined the MIDI Note Number and the Note Duration for a note in the song, it passes those two numbers to the playNote method, which is already included in your starter project:

public static void playNote(int noteNumber, int durationMs)

playNote will print its parameters to the console window (to help you with your testing), and then send the note to your sound card so you can hear it through your speakers or headphones.  You must not modify the playNote method in any way.  It is there for you to call, not for you to change.  (Note: There is another method (setInstrument) just underneath playNote.  For now, leave setInstrument alone.  You will be calling it later on in the project.)

Your Note Player will scan the note list in order, from left to right:

· Looking at each note symbol in the list,

· Breaking the note symbol into the components described above to determine the MIDI Note Number and Note Duration for the note,

· Calling the playNote method for that note, and then

· Continuing with the next note symbol in the list.

Checkpoint 2 Requirements Summary

Allowable Input: Note list with one or more note symbols, SINGLE line, NO playback adjustment, SOMETIMES accidentals, NO octaves.
Example: A_600 Bb_450 C#_1

· All Checkpoint1 and Checkpoint2 Tests must pass.

· Note!  Remove your print statements from checkpoint 1, and your checkpoint 1 tests will continue to pass, so long as you call playNote correctly.

· Your code now needs to find every note symbol in the note list, and call the playNote method on each one

· This means you will now need to convert each note letter into its corresponding MIDI note number (using the table above)

· Some note symbols will contain accidentals (# and b) and some won’t.  This will make parsing a little harder, but you may ignore the accidental when calling playNote.  For example, if you see a note symbol like C#_100, you can actually play that note as if it were just C_100.

· A note list might contain only one note symbol, or possibly many

Hints:

· You will probably need a statement with several IF / ELSE IF clauses to convert the note letter into its MIDI note number.  Remember to use the equals method, not ==, when comparing Strings

· You will find Integer.parseInt useful for the duration.  Look it up!

Checkpoint 3: Accidentals and octaves

For this checkpoint we’re adding a new concept called an “octave”, and you will now need to interpret the accidentals you ignored in checkpoint 2.

Each note symbol now consists of up to four parts.  An example of a complete note symbol looks like this:

 

You will convert the portion before the underscore (_) into a special number, using this plan:

 

Details are in the following sections.

Note Symbol Part 1: Note Letter (Checkpoint 3)

Do as you did in checkpoint 2.  But be aware that the table from Note Symbol Part 1: Note Letter (Checkpoint 2) assumes octave 0, so if the user specifies a different octave, you will need to adjust the number.  (See Note Symbol Part 3: Note Octave below.)

Note Symbol Part 2: Accidental (Checkpoint 3)

Think of the accidental as a slight adjustment to the MIDI Note Number, where you add or subtract 1 from the note number you already calculated:

Note Accidental

What it does

# (pronounced “sharp”)

+ 1

b (pronounced “flat”)

- 1

(no accidental specified)

Nothing (use the note number as is)

Note Symbol Part 3: Note Octave

The note octave is a number which appears after the note letter (or its accidental when present).  This tells your Note Player how low or high the note should be played.  An octave is sometimes present, but not always.  If no octave number is present, use octave 0.

This table describes how an octave changes the MIDI Note Number.  Always start with the Note Letter table we gave you above, then apply the accidental as described above, and then use the octave to change the value as follows

Octave Number

What it does

0

Nothing (use the note number from above)

1

Add 12 to the note number (12 * 1)

-1

Subtract 12 from the note number (12 * -1)

2

Add 24 to the note number (12 * 2)

-2

Subtract 24 from the note number (12 * -2)

3

Add 36 to the note number (12 * 3)

-3

Subtract 36 from the note number (12 * -3)

4

Add 48 to the note number (12 * 4)

-4

Subtract 48 from the note number (12 * -4)

5

Add 60 to the note number (12 * 5)

-5

Subtract 60 from the note number (12 * -5)

Here’s the pattern: Multiply the octave number by 12, and then add that product to the MIDI Note Number you’ve calculated in the sections above.  For example:
D#-2 = 63 + (12 * -2) = 39
D#-1 = 63 + (12 * -1) = 51
D#0 = 63
D#1 = 63 + (12 * 1) = 75
D#2 = 63 + (12 * 2) = 87

Checkpoint 3 Requirements Summary

Allowable Input: Note list with one or more note symbols, SINGLE line, NO playback adjustment, SOMETIMES accidentals, SOMETIMES octaves.
Example: Ab_600 B3_450 C#-2_150

· All Checkpoint1, Checkpoint2, and Checkpoint3 Tests must pass.

· Accidentals will be present on some note symbols, and they must be played properly

· Octaves will be present on some note symbols, and they must be played properly

Hints:

· Each note symbol will be a little harder to parse now.  It may or may not contain a sharp (#), flat (b), or octave number.  All possible combinations need to be handled properly.  Reread the Input section above!  Possible examples for each note symbol (this is not exhaustive!):

o D_10

o D#_1

o Db_150

o D2_11

o D#-3_2000

o Db3_4

· Don’t have six (or more!) IF / ELSE IF clauses to check each possible combination.  Instead, check for each component separately:

o What is the index of “_”?

§ This tells you where the note letter/accidental/octave portion ends

o What is the index of “#” and “b”?

§ This tells you if an accidental appears after the note letter.  This helps you figure out where the octave might start (while the index of “_” above tells you where the octave would end).

Remember, some of those indices will be -1 (meaning that String is not present).

Final Submission: Multiple lines, instruments, playback adjustment

For your final submission, you will add the ability for the user to set the instrument to play, list the available instruments, and enter multiple lines (that is, multiple instrument commands and note lists).  After each line is entered, you will process that line (either executing the instrument command or playing the note list entered on that line) and be ready to accept the next line.  You will continue in this manner until the user types quit, at which point your program will return from main.

You will also add the ability to accept and process a playback adjustment that might appear at the beginning of each note list.

set instrument

You will allow your user to switch the instrument to use by typing the “set instrument” command in the console window.  Any line your user types that begins with set instrument will then contain a space and an integer between 0 and 127 (inclusive) that indicates which instrument to use.  For example:

set instrument 26

would set the jazz guitar to be the currently used instrument.  And

set instrument 125

would set a helicopter sound to be the currently used instrument.  You will process this command by passing the instrument number specified by your user to the setInstrument method, which has been present (unused) in your starter project all this time:

    public static void setInstrument(int instrumentNumber)

list instruments

Since your user probably has not memorized your instrument list, you will allow your user to type

list instruments

from the console to cause you to print the following text exactly.  You may copy and paste this into your project (adding any appropriate Java punctuation and / or escape sequences) to ensure you have it exactly right.  (The tests will require you have this perfectly correct!)

0: Piano 1        1: Piano 2        2: Piano 3        3: Honky-tonk     4: E.Piano 1

5: E.Piano 2      6: Harpsichord    7: Clav.          8: Celesta        9: Glockenspiel

10: Music Box     11: Vibraphone    12: Marimba       13: Xylophone     14: Tubular-bell

15: Santur        16: Organ 1       17: Organ 2       18: Organ 3       19: Church Org.1

20: Reed Organ    21: Accordion Fr  22: Harmonica     23: Bandoneon     24: Nylon-str.Gt

25: Steel-str.Gt  26: Jazz Gt.      27: Clean Gt.     28: Muted Gt.     29: Overdrive Gt

30: DistortionGt  31: Gt.Harmonics  32: Acoustic Bs.  33: Fingered Bs.  34: Picked Bs.

35: Fretless Bs.  36: Slap Bass 1   37: Slap Bass 2   38: Synth Bass 1  39: Synth Bass 2

40: Violin        41: Viola         42: Cello         43: Contrabass    44: Tremolo Str

45: PizzicatoStr  46: Harp          47: Timpani       48: Strings       49: Slow Strings

50: Syn.Strings1  51: Syn.Strings2  52: Choir Aahs    53: Voice Oohs    54: SynVox

55: OrchestraHit  56: Trumpet       57: Trombone      58: Tuba          59: MutedTrumpet

60: French Horns  61: Brass 1       62: Synth Brass1  63: Synth Brass2  64: Soprano Sax

65: Alto Sax      66: Tenor Sax     67: Baritone Sax  68: Oboe          69: English Horn

70: Bassoon       71: Clarinet      72: Piccolo       73: Flute         74: Recorder

75: Pan Flute     76: Bottle Blow   77: Shakuhachi    78: Whistle       79: Ocarina

80: Square Wave   81: Saw Wave      82: Syn.Calliope  83: Chiffer Lead  84: Charang

85: Solo Vox      86: 5th Saw Wave  87: Bass & Lead   88: Fantasia      89: Warm Pad

90: Polysynth     91: Space Voice   92: Bowed Glass   93: Metal Pad     94: Halo Pad

95: Sweep Pad     96: Ice Rain      97: Soundtrack    98: Crystal       99: Atmosphere

100: Brightness   101: Goblin       102: Echo Drops   103: Star Theme   104: Sitar

105: Banjo        106: Shamisen     107: Koto         108: Kalimba      109: Bagpipe

110: Fiddle       111: Shanai       112: Tinkle Bell  113: Agogo        114: Steel Drums

115: Woodblock    116: Taiko        117: Melo. Tom 1  118: Synth Drum   119: Reverse Cym.

120: Gt.FretNoise 121: Breath Noise 122: Seashore     123: Bird         124: Telephone 1

125: Helicopter   126: Applause     127: Gun Shot

Note: there are no tab characters above—only text, spaces, and newlines (\n).

Playback Adjustment

Each song is entered as a single line containing:

· an optional “playback adjustment” followed by a comma (“,”), and then

· a list of note symbols with a space (“ “) between them

The following is an example, with the playback adjustment in italics and the list of note symbols shown in bold:

4_2.3,Ab3_600 B-2_450 Db5_150 G#_5 E_300 D#-1_10

The playback adjustment contains two parts:

1. A transpose adjustment integer, and

2. A tempo adjustment double

For example, here is a playback adjustment with the transpose (4) in bold, and the tempo (2.3) in italics:

4_2.3

The “transpose” adjustment is a number that is added to every note present in that song’s note list.  This can be used to raise or lower the pitch of the entire song.  For example, if you calculated that the MIDI Note Numbers for a song are 12, 14, 16, and the transpose adjustment is 4, then you’d add 4 to each MIDI Note Number, before passing it to the playNote method.  In this case, you’d pass 16 as the MIDI Note Number in your first call to playNote, 18 as the MIDI Note Number in your second call to playNote, and 20 as the MIDI Note Number in your third call to playNote.  The transpose adjustment can be any integer (negative, zero, or positive).

The “tempo” adjustment is a number that is multiplied with every note duration present in the song’s note list.  For example, if the note durations in the note list were 100, 200, 149, and the tempo adjustment is 2.3, then you’d multiply 2.3 with each note duration, before passing it to the playNote method.  In this case, then, you’d pass 230 as the Note Duration in your first call to playNote, 460 as the Note Duration in your second call to playNote, and 342 as the Note Duration in your third call to playNote.  Notice how the product is cast back into an integer (truncating everything after the decimal point) before passing it to playNote, as 149 * 2.3 is actually 342.7, but your Note Player will pass 342.

For example, you can speed up the song by using a tempo adjustment of 0.5 (to play in half the time), or slow down the song by using a tempo adjustment of 2 (to double the length).  The tempo adjustment can be any positive double (less than 1 would speed up the song, greater than 1 would slow it down).

The entire playback adjustment is sometimes present, but not always.  You are guaranteed to see either both parts or neither (i.e., you will never see a transpose without a tempo, or a tempo without a transpose).

A playback adjustment applies only to the line (note list) that it appears on.  It affects every note played from that list, but has no effect on any future lines entered by the user.

Command order

Your user may issue commands in any order she likes.  She may choose to play some songs, then list instruments and then set instrument 12 and then play more songs.  Your user might even choose to just do list instruments over and over again and then quit.  Or do set instrument 4 without first doing list instruments.  The key point is that you may make no assumptions about which commands your user will type or in what order those commands will be typed.

Final Submission Requirements Summary

· All Checkpoint1, Checkpoint2, Checkpoint3, and Final Tests must pass.

· You will now accept multiple lines from the user (until the user types “quit”)

· You will accept and process set instrument and list instruments commands

· The beginning of each note list MAY have a playback adjustment (transpose and tempo).  If so, it must be applied to each note on that line.

· Note that either both the transpose and tempo adjustments will be present on a line, or neither will be present on a line.  You will never have one without the other.

Hints:

· You will find Double.parseDouble useful for the tempo adjustment.  Look it up!

· When a tempo adjustment is present, you will need to cast the resulting duration to an int before calling playNote.