FinalRelease

History Key

  • New content
  • Removed content

Recent Versions

Choose two versions to compare, or click the link to view it.

  1. 16. almost 3 years by mrsoviet
  2. 15. almost 3 years by uniquesnowflake8
  3. 14. almost 3 years by uniquesnowflake8
  4. 13. almost 3 years by mrsoviet
  5. 12. almost 3 years by uniquesnowflake8
  6. 11. almost 3 years by uniquesnowflake8
  7. 10. almost 3 years by veraltb
  8. 9. almost 3 years by uniquesnowflake8
  9. 8. almost 3 years by veraltb
  10. 7. almost 3 years by uniquesnowflake8
  11. 6. almost 3 years by veraltb
  12. 5. almost 3 years by mrsoviet
  13. 4. almost 3 years by tjac0
  14. 3. almost 3 years by uniquesnowflake8
  15. 2. almost 3 years by beenen34
  16. 1. almost 3 years by uniquesnowflake8
 

What went right

Our greatest strength as a group is our drive to accomplish the ambitious goals we set at our first group meeting. It's the reason we met several times a week for every week of the quarter, which helped with risk management and mitigation, which helped us deliver in our key goals.

From the beginning, we were focused on a simple and easy interface, which we accomplished. We also achieved musical output, and demonstrated that it was possible to generate tones which were not cacophonous. Our code design and architecture benefited from the added time we spent on it, resulting in a clean, easily broken apart system. The result is that it is exceedingly simple to add new musicians, and it is not painful to splice in a new UI or audio parsing back end.

Cross-platform compatibility was achieved early on and maintained throughout the project, by necessity since there were three different development platforms involved.

Lastly, everyone on the team was heavily engaged in every stage of the project, and motivated by the challenge presented by its ambitious nature. This, above all else, is why Robot Rock is a success.

Individual Achievements

Alan

  • Abstraction: Score data structure preserved a pure model of the sheet music in a way that did not rely on the underlying audio implementation.
  • Simplicity: The Score was relatively simple, making it easy to customize and extend with views and aiding with testability.
  • Delegation: The conductor removed a lot of complexity and responsibility from the musicians by handing off current measures with up-to-date meta data at each point of the song.

Michael

  • Integration: Due to a well designed architecture, integration between the corecontroller module and the gui modules was very seamless
  • Refactor: With the help of a code review, musiciandirectory.py was vastly improved in modularity and readability
  • Plugability? : Musiciandirectory was implemented in such a way so that no changes need to made to existing source code to add new musicians, just the necessary materials need to be placed into a folder in the musicians directory

Tim

  • Modularity: The beta GUI was very intertwined, and after a major refactoring the logic was more compartmentalized and simpler to understand
  • Resource locating: The GUI includes functions to search for program resources such as image files, both when installed in a standard location and when running locally.
  • Raw painting: The stage and all musician widgets paint themselves using the raw Qt interface. They paint quickly and look fairly good, for items using no built in painting.

Travis

  • Early experiments: Creating and digesting the results of experiments set our design off toward the right direction
  • Library support: Fluidsynth and Soundfonts were a pleasure to use; without a solid audio base this project would have been unachievable in the short life cycle.

Rich

  • Learning Python: I learned python in 2-4 hours. It was really really easy to pick up.There are probably some subtleties that I do not know about, but thats neither here nor there.
  • Group Dynamics: With the exception of figuring out the score, everything went really smoothly. Everyone did their work, did it mostly on time, and did it well. Integration: In general, integration worked really well. We have a fairly complex pipeline in the end, and it all works pretty smoothly.
  • Musician Support: With our system, it is really really easy to add musicians, remove them, change their sound, etc. Awesome! This really helped me crank some musicians out (we have 13!).

What could have gone better

Not everything in the project went as planned. Communication was weaker at the start, and resulted in the pain of refactoring or wheel-spinning that could have been avoided.

It may have been worthwhile to create a sandbox for testing different musical ideas early on, since listening is a prerequisite for ensuring music quality.

We used an atomic model for checking for notes of given lengths, when it may have been more efficient and flexible to use an event-based model. Luckily, this could be re-implemented without affecting musicians, the UI, etc.

We designed for responsiveness, but confused users by allowing differing levels of responsiveness. For example, a key change is not immediately applied to the sound. This is something we could fix without too much trouble, although it would affect the internal model for composition.

There was a huge opportunity to employ animations, which we missed, and could require extensive 2-way communication with the UI in order to achieve.

We spent excessive amounts of time working through release and path issues. We feel like this is a weakness of python, since everything else seems so natural by comparison, and working with path resources requires lots of developer support.

Our daily build is another opportunity for improvement: the script needs to run the musician tests as well, and use python 2.6 in order to show all tests as passing.

Individual Opportunities for Improvement

Alan

  • Design: Note values were cumbersome to use, it may be worthwhile to refactor their use to match the Tone style implementation.
  • Utilities/Developer Support: There is not much support for musicians who wish to examine the score, since they are only provided a current score slice. Some analysis tools are probably necessary to make things simpler for musicians which listen to one another.
  • Communication: The Score required several revisions, which were probably not necessary if there was more communication and fewer assumptions made. It held back our progress as it was revised, since it's a core class and other team members waited on it being ready.

Michael

  • Tests: Many more system tests could be written, especially for successfully loading in musicians, which caused a number of bugs throughout the development process
  • Planning: The final structure of the musicians directory in the source code was not established until a day or two before the FC release, which caused a bit of a rushed and unsuccessful attempt to get it ready for the FC release. Planning ahead for this directory structure would have likely created a more effective and understandable musiciandirectory earlier in the project.
  • Installation: I didn't figure out how the installation really worked on Windows until the last couple weeks or so, understanding this may have helped me avoid some issues with the musiciandirectory installation

Tim

  • Planning: Before the beta, very little of the GUI internals were designed ahead of time.
  • Centralized actions: Planned but scrapped due to time constraints, I had wanted to put in another component which would centralize all major actions that the user could do. This component could be used in testing, building menus, and general consolidation of logic.
  • Group Meetings: I missed a lot of group meeting time due to later working hours on Tuesdays, which was our primary meeting day. Not too much I could have done beyond meeting on a different day (which we could not do consistently), but it certainly affected my understanding of the program as a whole.

Travis

  • Performance and scalability: the atomic note model we use to run the system has limitations. We cannot have very short or odd divisions of beats. We have a solution for this but it is not a small feat. Fortunately, our modularity makes this task reachable despite not being trivial.
  • Python wave support: All indications are that the Python library has less than perfect support for wave files at the moment. Experiments showed that under certain conditions wave files would not be produced correctly.

Rich

  • Early team dynamics: It took us a while to get the score and it's interface nailed down. This slowed me down considerably. To try to counter this, I put all adding of notes to the score in a single place. I would have done this anyways, but I had to do it sooner. Where it really slowed me down was writing tests for the musicians.
  • Long wait to hear results: I was unable to 'hear' the musicians I was creating for a long time, so I had no idea if they sounded good. As a result, it took longer to find problems in the code, and thus fix them.
  • Isolated Running: Even when we had releases I was unable to run the releases. I think this was due to people making changes to structure and not letting me know about them. As a result, I had some .pyc files left around which would muck everything up. It was frustrating to go thorough, but once the problem was found I knew where to go to fix the problem.

Extensibility

The high-level procedure for adding code to our data base is listed below each desired feature.

Record performance's audio

  • The ScoreParser within RobotRock may have an arbitrary number of Receiver objects associated with it. Each Receiver is given the opportunity to handle note events in a particular way. Furthermore, besides being able to handle note events, Receiver objects are also given the opportunity to respond at the end of each frame. These end-of-frame opportunity offers the means to perform batch operations that would otherwise be too expensive to handle at the note event level, such as disk accesses.
  • Capturing the performance as MIDI data is straight forward. When note events are handled they may be simply converted to appropriate MIDI codes. Our current audio outputting receiver is based upon Fluidsynth, and because it is modelled after MIDI, functions to convert note events into MIDI codes already exist within our project. Our implementation converts to MIDI codes on the fly, rather than using this model throughout our design. In order to implement this, we would create a new Receiver type which stores the converted event MIDI data. When instantiated, the header for a MIDI file may be created and at the end of each frame the MIDI data would be appended.
  • Capturing the performance as an audio file may be handled in a similar fashion to the MIDI data. Fluidsynth makes available the option to obtain sample data rather than output it via the audio driver. These two operations, however, are mutually exclusive. Two Fluidsynth Synth objects must exist--one for the audio driver and one for tangible samples. A new Receiver type would be needed to perform this task. Python makes available a Wave class that will nearly effortlessly create a wave file. At the end of every frame, samples may be collected and fed to an instantiation of this object.
  • Lastly, the GUI would need to make available these capabilities to the user. In theory, the GUI could just instantiate the desired receiver and attach it to the parser. The parser, at the moment, doesn't officially support the addition of other receivers and all receivers must be specified in the parser's constructor. Adding this support, however, is trivial.

Record performance's user actions

  • The most minimal way to do this is to log the user actions, and then play them back from within the application so that the recorded actions are indistinguishable from the live user actions from the application's perspective.
  • We need to add a record button, and a file dialog to the UI through the guimain.py file. Both of these are simple UI widgets and fairly trivial to add.
  • Add logging to every CoreController methods, which records the relative timestamp and method name and parameters to the specified file while recording is enabled.
  • Add a file menu option to guimain.py to load the log file back in for playback.
  • After the file is loaded and we are playing back from it, there is another class, with its own thread and a built-in timer, which performs the same method calls at the same relative times as originally recorded to the log.

Set parameters to change over time

  • Currently musician positions on screen are only manipulated by direct UI calls, and we would like to reflect any changes to their energy or complexity in the UI, even if there was no direct user action. We will need to add a callback method for any changes to a musician's energy and complexity, which will handle redrawing.
  • Alternatively, we can periodically redraw every musician based on their energy and complexity. This is essentially picking one side in the common dichotomy of polling vs. event driven models.
  • A musician will need to provide a gui python module for the UI to load as its custom control window (displayed when it is selected in the upper right corner).
  • As an aside, the musician directory currently does not load any specific UI classes, but it is intended to eventually, and this functionality is not difficult to add. It requires a naming standard for this UI class, a tests for sanity and an import in MusicianDirectory, and one extra field in the MusicianMetadata class.
  • This custom musician control window is where the user can set the musician to change over time.
  • The musician class itself can provide a timer to implement the user-specified changes over time, or the GUI control can call the core controller method directly using its own QtTimer. The internal based implementation is preferred since it requires less coupling.
  • Either way, the musician will receive a change to its energy and complexity at regular intervals, and the application will redraw it on screen.