- Home /
What's a good way to do dynamically-generated music, note-by-note?
So, the game I'm working on is based around building some simple melodies during play. Algorithmically speaking, I've got some interesting ideas as to how to do that, but I'm having some technical trouble -- as far as I can tell, the only way to accomplish this would be to import sound files for each note, attach them all to a container object, and treat each one as an AudioSource. MIDI would make more sense, of course, and I imagine that tracker files would present interesting opportunities as well, but I can't find built-in functionality that would let me play notes "off-the-cuff" using either of those two technologies (and I can't afford Unity Pro to get access to C libraries). Do you guys have any clever ideas as to how I might play notes, one-by-one, in Unity to create dynamic melodies?
doesn't look like there's a proper framework in place to actually generate sounds from within unity at the moment, but there are requests for it (top few results): http://feedback.unity3d.com/forums/15792-unity/category/439-audio
Answer by aldonaletto · Jul 10, 2011 at 10:02 PM
Musical keyboards and even midi devices all use the same trick: they have a limited number of notes stored, and alter the pitch to create the notes in between. These notes usually have also a loop section defined, which can be repeated to extend the note. Unfortunately, this extension can't be done in Unity, but maybe for your purposes it may not be necessary.
The idea is to have one or more long duration notes, set the audio.pitch to the note you want, then play it using audio.Play(). When you need to play another note, change the pitch and play it using audio.Play() again - the previous note will be stopped and replaced by the new one. To stop a note, use audio.Stop().
Just to give you an idea of what can be done, I created a little "piano" in the script below. The keys a s d f g h j k l play the notes C D E F G A B C D. Create an empty object, assign this script to it, add an Audio Source component, and set its audio clip to some long note (if you don't have any, download it from here and import it to the assets):
var transpose = -4; // transpose in semitones
function Update(){
var note = -1; // invalid value to detect when note is pressed
if (Input.GetKeyDown("a")) note = 0; // C
if (Input.GetKeyDown("s")) note = 2; // D
if (Input.GetKeyDown("d")) note = 4; // E
if (Input.GetKeyDown("f")) note = 5; // F
if (Input.GetKeyDown("g")) note = 7; // G
if (Input.GetKeyDown("h")) note = 9; // A
if (Input.GetKeyDown("j")) note = 11; // B
if (Input.GetKeyDown("k")) note = 12; // C
if (Input.GetKeyDown("l")) note = 14; // D
if (note>=0){ // if some key pressed...
audio.pitch = Mathf.Pow(2, (note+transpose)/12.0);
audio.Play();
}
}
You can use the basic audio.pitch idea to produce the notes. Use an array to specify which notes to play, and another one to determine how much time each one will last. Another solution would be to have a single float array, where the integer part of each number is the note, and the fractional part is the duration in seconds.
This is a better answer than I got from all of Google on building a simple mathmatical synthesizer from a single note sample. Thank you so much, @aldonaletto... simply elegant!
$$anonymous$$ore deep realization of the same idea: https://github.com/ukushu/UnityPianoGame
Very useful coding example - clear and simple. Thank you!
Answer by deeredman1991 · Jul 10, 2011 at 09:06 PM
not sure how you would go about doing that but if your worried about the quantity of audio files you could try making one audio file to play whole notes c1-c6 and then when the player triggers a specific note have it jump to that part of the audio file play the note and stop...not sure how you would do this either...but it sounds alot less complicated lol
Not sure why this has been down-voted several times, the idea itself looks pretty good to me especially since there are recordings that have music notes in ascending order.
So maybe it won't be feasible in the end but worth a try in my opinion
This is awesome, is there any chance of having a C# version of this?
I just had a thought that another way might be for each key press to instantiate a prefab that played each note and then destroyed itself after the note was played, this way each key stroke would sustain each note. Not sure if it's the best way but it's an idea. ;)
The reason it has been downvoted is probably because it's pretty useless. The problem with the quantity of audio files is either the total size (in which case gathering them will not fix it) or the complexity, and having to play audio at a specific time and stop after the right time, different for each note, specific times that you may have to keep serialized somewhere anyway. Well, that's definitely not more simple. Also it might affect performance to play a sound not from the beginning (not 100% sure).
i have up voted this answer. Both seem like very relevant ideas.
Your answer
Follow this Question
Related Questions
How to make a MIDI vizualizer? 0 Answers
Why can't I hear my audio? 5 Answers
GetSpectrumData over entire file 1 Answer
How to start/stop/loop different music tracks 0 Answers
audio change object size 1 Answer