|
Post by TrojanNemo on Jul 7, 2015 0:37:42 GMT
Keep trying, I'm sure you'll figure it out. It took me a while at first. Now I don't think there is a single song I've tested on cPlayer that it doesn't play correctly. So once you get it, you'll have it for all songs.
|
|
|
Post by srylain on Jul 14, 2015 5:50:29 GMT
Been trying to figure it out, but am having no success at all. I'm assuming that Time Signature changes don't do anything as the code I received just ignores them. Another thing I could think of that was messing things up is if a Time Signature Change event happened before a Tempo Change, as that would be giving out wrong Delta Times. In all the notecharts it did desync, that wasn't the case.
I've tried looking through the notecharts and finding things that are common with them, and haven't come up with anything. Afterlife (Avenged Sevenfold) for example, desyncs after a minute. Money For Nothing (Dire Straits) desyncs near the end.
I doubt the notecharts are bad because they seem to work just fine with Phase Shift. Thanks for the help.
EDIT: Also, how would I go about doing sustains? I'm seeing that each note that isn't a sustain has a length, and I assume that in order to get the length of the note in real time I'd need to calculate where each tick lands according to the tempo map?
|
|
|
Post by djlastnight on Jul 14, 2015 6:43:08 GMT
I never used time signatures, all works fine for me without them. However, here is the "missing" part of the code provided. I didn't test it, but I'm sure it works. {Spoiler}
#region Unused content //private List<TimeSignature> timeSignatures;
//private void BuildTimeSignatureList() //{ // timeSignatures = new List<TimeSignature>(); // foreach (var ev in midiFile.Events[0]) // { // if (ev.CommandCode != MidiCommandCode.MetaEvent) continue; // var signature = (MetaEvent)ev; // if (signature.MetaEventType != MetaEventType.TimeSignature) continue; // //Track the time signature change // var index1 = signature.ToString().IndexOf(" ", signature.ToString().IndexOf("TimeSignature", StringComparison.Ordinal), StringComparison.Ordinal) + 1; // var index2 = signature.ToString().IndexOf("/", StringComparison.Ordinal); // var numerator = Convert.ToInt16(signature.ToString().Substring(index1, index2 - index1)); // //Track the time signature change // index1 = signature.ToString().IndexOf("/", StringComparison.Ordinal) + 1; // index2 = signature.ToString().IndexOf(" ", signature.ToString().IndexOf("/", StringComparison.Ordinal), StringComparison.Ordinal); // var denominator = Convert.ToInt16(signature.ToString().Substring(index1, index2 - index1)); // var time_sig = new TimeSignature // { // AbsoluteTime = ev.AbsoluteTime, // Numerator = numerator, // Denominator = denominator // }; // timeSignatures.Add(time_sig); // } //}
//internal class TimeSignature //{ // public long AbsoluteTime { get; set; } // public int Numerator { get; set; } // public int Denominator { get; set; } //} #endregion
|
|
|
Post by srylain on Jul 14, 2015 9:49:40 GMT
Well, it does seem that I found the problem. I was using floats to keep track of time, and on my computer that was running my game at 1000+ FPS it would always desync somewhere in the 4-5 minute area. On my friend's computer (which I just tried playing it on), it stayed synced the whole way through.
I've since changed the floats to doubles, and hopefully that helps so I can stop worrying about this.
But, at least for now, my question is still how to get sustain length from the MIDIs. Another question I have, is I've noticed a few MIDIs (Green Grass and High Tides, My Sharona) seem like all the NoteOn events are doubled. Is there any reasoning to that or is it just something I need to find a workaround for?
|
|
|
Post by TrojanNemo on Jul 14, 2015 13:42:17 GMT
Another question I have, is I've noticed a few MIDIs (Green Grass and High Tides, My Sharona) seem like all the NoteOn events are doubled. Is there any reasoning to that or is it just something I need to find a workaround for? Seems to me like you're not following the advice that was given to you. Second, and I know it's been mentioned before: learn and understand running status. If you intend to use "all" Rock Band / Phase Shift / FoF MIDIs, you'll come across quite a few that use that feature. I was using floats to keep track of time, and on my computer that was running my game at 1000+ FPS it would always desync somewhere in the 4-5 minute area. On my friend's computer (which I just tried playing it on), it stayed synced the whole way through. That makes no sense. First, don't keep track of time yourself, use a timer. There are various code samples for this online. Second, running at 1000FPS is no reason for it to go out of sync, it's just wasting cycles, but should stay synced. So the problem is elsewhere. But, at least for now, my question is still how to get sustain length from the MIDIs. The sustain length, as you call it, is just the note.NoteLength value. How you choose to display that, and how you choose to calculate that length relative to each other note and relative to the spacing between the notes, is entirely up to you. For example, I use the same function to calculate the real time (using note.AbsoluteTime) and that I use to calculate the length (using note.NoteLength). This is accurate and simple.
|
|
|
Post by srylain on Jul 14, 2015 21:48:08 GMT
I just kinda figured that since I was only using the NoteOn events, I didn't really need to do anything with the NoteOff events and that there would only ever be NoteOn events for when there were actually notes to be played. Unless NAudio does something different because of the running status, I didn't think I'd need to do anything about it. But again, apparently I've assumed wrong.
Unity gives me access to a delta time, which is the time between frames. I add that to a double that keeps track of the time since the song started, and use that to determine when the notes should be played. I believe the problem was that adding to the float I had before a thousand times a second just caused precision loss, and it seems that doubles work much better as I've been able to play some Dream Theater just fine.
As for the sustains, will there be times when the tempo will change during them? I'd assume that I'd have to find the ticks during the current tempo, and then when it changes get the remaining ticks and then calculate the rest of the time using that new tempo.
|
|
|
Post by srylain on Jul 14, 2015 22:20:29 GMT
I believe I've figured out the running status problem. Before I add a note, I check to see if its NoteOff event is null. If it is, I ignore the note. It made Green Grass' chart work perfectly, so hopefully that's all I needed.
|
|
|
Post by raynebc on Jul 15, 2015 0:08:57 GMT
In rhythm games, you definitely have to account for tempo changes that occur in the middle of notes. Your approach sounds like it would work, but you can optimize it by building a list of all tempo and time signature changes, and their associated delta and real times. Then each note on/off will be relative to one of the changes in your list and you can minimize the amount of calculations you need to do for each note.
|
|
|
Post by srylain on Jul 15, 2015 21:01:17 GMT
I'm seeing that each note has a length, even if it's a note that wouldn't normally be a sustain in PS or RB. How do I only get the sustains that would show up in PS or RB?
|
|
|
Post by srylain on Jul 17, 2015 22:57:23 GMT
I know you guys said it's up to me to display the notes how I want to, but I really need just a bit more help trying to get the sustains working. Obviously there's some sort of algorithm or something that determines what note is an actual long note (since each note has a length), and that's where I need help. I'm trying to make my game as close to RB/PS/GH as possible for right now.
For the most part I've figured out how to get the real time length of the notes, it's just determining what notes to not count as sustains is the problem.
|
|
|
Post by raynebc on Jul 17, 2015 23:27:29 GMT
I couldn't find information about it, you may have to obtain the original MIDIs for some GH and RB charts and compare them to game footage of the charts being played in order to determine that yourself. Or it's quite likely somebody somewhere knows this already.
|
|
|
Post by srylain on Jul 17, 2015 23:37:01 GMT
Thanks for the response. I've been using the MIDIs I've found off the Frets on Fire forums from the original games, but I believe those had already been converted to work in PS.
As it seems, there's probably just a cutoff or something where if a note's length is less than some number it just gets set to zero. I'm gonna try looking in FoF's source again, maybe I can find something. If I can't, are there other forums with people who may know?
|
|
|
Post by raynebc on Jul 18, 2015 1:43:02 GMT
It's probably going to depend more on how long the note is in terms of measures (ie. 1/16 note) or less might be considered as having no tail. A good place to ask this would be the two ScoreHero forums: The Guitar Hero one (http://www.scorehero.com/forum) and the Rock Band one (http://rockband.scorehero.com/forum/).
|
|
|
Post by David on Jul 18, 2015 7:12:13 GMT
For Phase Shift we define a sustained note when it's longer than a 16th note.
David
|
|
|
Post by srylain on Jul 18, 2015 9:32:12 GMT
Thank you, at least now I have a starting point. Another couple questions I do have are about HOPOs. I know the MIDIs use a way to force a note to be HOPO or not, and is there any way I can use NAudio to retrieve that? Or is there another MIDI library I can use (with C#) that'll expose that data?
Also, I believe I've read that 8th notes are normally treated as HOPOs. Is that correct?
|
|