Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Milo Han #4

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 42 additions & 14 deletions Entry 1 -- April 3.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,61 @@

## Last week's critique

**TODO:** Fill in this part with a summary and reflection on the critque you
received for last week's work. Answer questions such as: How, specifically, did
the feedback help improve the project? Did the feedback point out or offer
something you hadn't considered? Did it help you make a design decision? Was it
helpful in addressing the most pressing issues in your project? How will you
incorporate the feedback into your work? Will you change something about the
design, implementation, or evaluation as a result?
I got some great feedback/suggestions from William and Prof Ben about user experience and adding more language-y features.
William's main concern was that my project seems too backend-heavy. I definitely was a bit worried about this since I started the project, so this served as a confirmation that I'll have to come up with some more language-y features. However, he warned against adding things like complex control-structures simply for the sake of having more language to design. This is something I'll be keeping in mind - user experience comes first.
He also suggested that I eventually implement some sort of "beginner" setting where users don't have to write too much code. I kind of liked the sound of this, but wasn't sure exactly what this would look like.
However, Prof Ben then suggested that I eventually implement an alternate UI/GUI-based form of input. This seems like a great idea that would address both of William's suggestions. It's a language-y feature that should be a lot simpler to use for beginners. I'm not yet sure exactly how it will look/work (I'm thinking it'll involve a bunch of sliders and dropdowns), but it's something I'll be thinking about in the coming weeks.

## Description

**TODO:** Fill in this part with information about your work this week:
important design decisions, changes to previous decisions, open questions,
exciting milestones, preliminary results, etc. Feel free to include images
(e.g., a sketch of the design or a screenshot of a running program), links to
code, and any other resources that you think will help clearly convey your
design process.
I was able to make a decent amount of progress this week. Most excitingly, I've linked up all the various technologies/tools and laid out the architecture of the DSL from input to output. The biggest factor that allowed me to get this all done was the simplicity of PEG.js. I thought the parser was going to be a roadblock (it still might, later down the line), but so far it hasn't been. Check out my parser grammar [here](https://github.com/milohan/sheet-music-gen/blob/master/parserGrammar.js) if you're interested.
You can test out what I have so far in terms of the actual DSL by heading over to my [code repo](https://github.com/milohan/sheet-music-gen). Just open up the index.html file with your browser of choice (more detailed instructions can be found in the [readme](https://github.com/milohan/sheet-music-gen/blob/master/README.md).
Below is a work log outlining the tasks I worked on throughout the week.

Tues
- familiarized myself with PEG.js, abcjs
- implemented logic to generate and render arbitrary number of measures of music
- currently using random pitches, only quarter notes
- started building parser with PEG.js
- now accepts "measures: 12"
- stitched together basic architecture, from input to output
- user input -> parser -> internal logic -> render sheet music

Wed
- (during class) worked on design + implementation writeup

Fri
- parsing + logic for measure ranges ("measures: 12-14")
- parsing + logic for keys ("key: A")
- parser now accepts arbitrary number of lines of parameters

Sunday
- finished design + implementation writeup
- notebook entry
- implemented seeded random generation. should be useful for debuggging later on.
- syntax errors now displayed to users on web page.

## Questions

**What is the most pressing issue for your project? What design decision do
you need to make, what implementation issue are you trying to solve, or how
are you evaluating your design and implementation?**

The next set of parameters I'm hoping to tackle are the ones relating to rhythm. I'd like to, for example, allow users to specify that they want 30% quarter notes, 20% half notes, and 50% eight notes. However, I'm not exactly sure how I'll accomplish this in the back end. If I simply randomly choose note lengths based on the given percentages, the results will be skewed because each measure has to have an exact number of beats. For example, let's say the user asks for 50% half notes and 50% quarter notes in 3/4 time. With the above method, we'd have a 50% chance of choosing a half note as the first note of each measure. However, any time we choose a half note first, we'd then have to automatically stick in a quarter note to complete the measure (since you can't fit two half notes in a measure when you're in 3/4 time). We'd end up with more than 50% quarter notes. There's probably a better way to approach this problem, but I'm having some trouble coming up with it. If there isn't, I may have to scrap the feature of allowing users to enter specific percentages.

My original plan was to have three places for users to enter parameters:
1. Inside a "Stave" (bounded by brackets). Parameters here would describe a specific stave.
2. Inside a "Global Stave" (bounded by brackets). Parameters here would be inherited by all staves (though individual staves can override these global parameters by defining them themselves).
3. Outside any staves (not bounded by any brackets). These parameters are "score parameters." These are parameters that aren't specific to any stave, such as the number of measures or whether or not there should be repeats.

However, now I'm wondering whether there's a need for the "Global Stave" at all. I could instead have users enter "global" stave parameters outside any specific stave, along with the score parameters. This could be clearer/simpler, especially for non-programmers who might have trouble understanding what a "Global Stave" is supposed to do.

**What questions do you have for your critique partners? How can they best help
you?**

My questions are basically if you have any advice for the problems I outlined above. Are there any algorithms or ideas that relate to my note-length issue? Do you think it's even necessary that I allow users to enter specific percentages? Are there any other pros/cons you see to having a "Global Stave"? Should I have it or not?

**How much time did you spend on the project this week? If you're working in a
team, how did you share the labor?**


Including time spent on writeups + design, I spent about 12 hours on the project this week.
76 changes: 63 additions & 13 deletions Entry 2 -- April 10.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,83 @@

## Last week's critique

**TODO:** Fill in this part with a summary and reflection on the critque you
received for last week's work. Answer questions such as: How, specifically, did
the feedback help improve the project? Did the feedback point out or offer
something you hadn't considered? Did it help you make a design decision? Was it
helpful in addressing the most pressing issues in your project? How will you
incorporate the feedback into your work? Will you change something about the
design, implementation, or evaluation as a result?
Aaron warned me about my current error handling, saying that it went against what Prof Ben had told him. He said that my "10-8" case (where I give a parse error since that's not a valid min-max integer range) is "semantic, not syntactic," meaning that I shouldn't return an error while parsing. I don't understand exactly why this is, so it's something I plan to ask prof Ben/my critique group about before acting on it.

For note-lengths, Aaron suggested that I could enable users to specify probabilities for each length to occur (something I originally wanted to do) by using ties. It's something we discussed in class, and would, as Aaron claims, solve the issue that I point out in last week's [notebook](https://github.com/milohan/project-notebook/blob/master/Entry%201%20--%20April%203.md). However, depending on the note lengths the user chose and the time signature, this could cause there to be way more note ties than there would be in normal-looking music. It would could also cause the generation of note lengths that the user didn't specify (something Aaron and I discussed in class). For these reasons, I've decided to scrap the idea of allowing users to specify specific percentages for note-lengths, and instead focus on other parameters. I don't think it'd be an especially useful parameter, and I'm starting to think it may not be possible to impement without annoying side-effects.

Aaron also responded to my question about the "Global Stave" from last week's notebook. He said to scrap it, and I've done exactly that. As he says, there isn't really any need for it since I can just put "global" parameters in the score environment of the program.

## Description

**TODO:** Fill in this part with information about your work this week:
important design decisions, changes to previous decisions, open questions,
exciting milestones, preliminary results, etc. Feel free to include images
(e.g., a sketch of the design or a screenshot of a running program), links to
code, and any other resources that you think will help clearly convey your
design process.
The major things I worked on this week are as follows:
- Pitch: Started creating an internal system for representing pitches that allows me to perform meaningful logic on notes. I decided to base my system on [MIDI pitch values](http://www.electronics.dit.ie/staff/tscarff/Music_technology/midi/midi_note_numbers_for_octaves.htm) (integers from 0 to 127 representing pitches). By using integers, I can perform simple harmonic "math" that is key-agnostic. For example, to create a 5th interval I add 7 to a pitch's MIDI value. This system allowed me to implement the "absRange" parameter that defines the range of allowable pitches. In order to use MIDI in the back-end, I convert [scientific pitch notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation) (input) to MIDI value (internal) to ABC notation (output).
- Polyphony (the number of notes that can be played at the same time): Back-end was straightforward, though I'm sure it will get more complex once I allow for parameters like "relRange" (number of allowable semitones between notes within a chord). [Parsing](https://github.com/milohan/sheet-music-gen/blob/master/parserGrammar.js) for this was interesting. I allow users to specify polyphony in three different ways.
- A single integer: "polyphony: 3" means that only triads will be generated.
- A range of integers: "polyphony: 1-3" means that single notes, diads, or triads will be generated.
- A list of integers: "polyphony: "1, 3" means that only single notes and triads will be generated.
- Multiple staves/voicings: Users can now create an arbitrary number of staves. Followed my critique group's advice and scrapped the "Global stave" idea. Now, parameters defined outside any specific stave are automatically considered "global" and will be used by any stave that doesn't itself specify that parameter.

#### Example input and corresponding output:

![asd](https://raw.githubusercontent.com/milohan/project-notebook/master/images/4-10_input.png)
![output](https://raw.githubusercontent.com/milohan/project-notebook/master/images/4-10_output.png)

#### This week's work log (feel free to ignore):

**Monday**: 3 hours
-wrote critique for William
-users can now specify seed with "seed" parameter.
-"clef" parameter now supported.

**Tuesday**: 1.5 hours
-designed and began implementing pitch system, from input -> internal -> output

**Wednesday**: 2 hours
-parsing for "absRange"

**Thursday**: 2.5 hours
-worked on back end for pitch system
-"absRange" backend working
-started working on polyphony support (chords)

**Friday**: 1.5 hours
-parsing, semantics for polyphony. Allows int (eg "4"), range of ints (eg "1-3"), list of ints (eg "1, 2, 4")

**Saturday**: 1 hr
-planning + parsing for multiple staves

**Sunday**: 2.5 hr
-backend + finished parsing to handle arbitrary number of staves
-"global" variables (defined outside of staves) properly used when not defined inside individual staves

## Questions

**What is the most pressing issue for your project? What design decision do
you need to make, what implementation issue are you trying to solve, or how
are you evaluating your design and implementation?**

- I'm still working out how I'll generate decent rhythms while allowing users to specify any time signature any any set of note lengths. An idea I had was as follows: on a measure-by-measure basis, start out with largest available note (e.g. a whole note in 4/4 time, assuming the user allows it). Based on some probability, either leave it or split it into equal-length children. Recursively apply same algorithm to children. A benefit of this is that it should naturally create rhythms that emphasize downbeats. However, it needs a lot of refinement if I'm to use a version of it since certain problems would arise.
- Some note values would be impossible to generate. How do we get, say dotted half notes in 4/4 time? (Maybe allow a certain chance for two notes to "combine" into one once the measure's been generated?)
- How does this alg work in odd times?
- For user feedback, I need something better than the types of error messages I'm currently giving. I'm contemplating trying to implement feedback where I'd highlight the troublesome pieces of code. I'd have to delve into the parser generator I'm using, but it could be a cool "language-y" aspect to sink some time into.
- Also - There are a huge amount of things I could work on to try to generate harmonically pleasing music, but I'm going to leave that to the side for the time being. The code I'd have to write would be super back-end heavy, and would probably be out of scope considering the amount of time I have for this project. I would like to do some basic things with harmony/consonance before the semester ends, but at least for the next week I'm going to focus on things like user feedback, the UI version of the DSL, rhythms, MIDI output, etc.

**What questions do you have for your critique partners? How can they best help
you?**

- What are your thoughts on my idea for generating rhythms? Any major flaws I haven't noticed? Any other ideas on how I could get accetable rhythms?
- Can you think of a better parameter name than "polyphony"? It describes the number of notes that can be generated in a single chord.
- For parameter names that are more than one word, such as "absRange," what do you think of using camel case? I write a lot of java, so it feels natural for me, but would something else be better?
- Are there any major parameters I should prioritize (other than rhythm)? There are countless I can think of, but there are also a bunch of other things I'd like to work on.
- Besides parameters, what should I prioritize? I feel like there are a lot of directions I could go.
- UI version of DSL
- Better user feedback (e.g. highlighting problematic code)
- MIDI integration (allow users to hear what the music sounds like)
- Something else?

**How much time did you spend on the project this week? If you're working in a
team, how did you share the labor?**

Was able to spend some time coding/planning every day this week (github commits won't necessarily reflect this since I'll often work past midnight and I sometimes forget to push). Splitting up my time into smaller chunks helped keep things moving along. If I got stuck on something, I'd just sleep on it and come back the next day.

Total: ~14 hours. Daily breakdown in work log above.
Loading