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

Not Exact an issue- Get note time near to song time #5

Closed
FabioZumbi12 opened this issue Jan 28, 2018 · 8 comments
Closed

Not Exact an issue- Get note time near to song time #5

FabioZumbi12 opened this issue Jan 28, 2018 · 8 comments
Labels
question Just question about the library
Projects

Comments

@FabioZumbi12
Copy link

FabioZumbi12 commented Jan 28, 2018

Hi,

Me again and now with my game come to be ready soon using your source <3
Take a look: https://www.youtube.com/watch?v=fqLiBD0p2cI

But i am not here only to show you the game, but to ask about notes.

As you can see on some notes in this video, some notes next to other one have different distances, where on midi the distance is equals.

I think the way i using to get notes is not the best, but the song time is not the exat time of note, then, i cant get the note form midi only quering the song time, i need to get next nearest note based on last note time and new time in a interval.

Is there a best way to get the exat note using the song time?

I have created a Dictionary to cache the notes for difficulties based on note time. The way i get the note is:

tempNotes.Where(pairs => pairs.Key == actualTime || pairs.Key > lastTime && pairs.Key < position).ToList().ForEach(pairs =>
{
  ...
  lastTime = actualTime;
}

Where the key is the note time.
And i run this loop on every frame.

If you know a better way to get and put the note time on my Disctionay or a better way to get the next note, ill glad if you can help.

Thank you!

Edit: This is only with too near notes, with other notes theres no problems.

@FabioZumbi12 FabioZumbi12 changed the title Not Exact an issue Not Exact an issue- Get note time near to song time Jan 28, 2018
@melanchall
Copy link
Owner

Hi,

Welcome back! Watched the video, looks really nice! Great job :)

As for you problem, can you say what are actualTime and position variables? Please clarify your issue. As far as I understand the problem is you can miss some notes because their times don't equal times of notes in audio file, and so you should remember what note was played last and take next one. Is it correct?

Max

@melanchall
Copy link
Owner

@FabioZumbi12 Is your question still actual?

@FabioZumbi12
Copy link
Author

FabioZumbi12 commented Jan 31, 2018

Oh sorry,
Because a lot of notifications on my github i didnt have seen this :x

Still... but only for too near notes.

The position and actual time is in TotalMicroseconds.
I not exact missing notes but some notes is near to next mutch than other, where on midi is the same time.

Edit.: A print to show what i mean: http://prntscr.com/i83jk4

@melanchall
Copy link
Owner

So your task is to get nearest note to the current position in audio file, yes?

For example:

Audio file |    1  2      3  4
MIDI file  |    a    b    c    d

When current song pointer stays on note 1 in audio file the a note in MIDI file should be played and b for 2, c for 3 and d for 4? The problem is how to find nearest note to the specified time?

@FabioZumbi12
Copy link
Author

FabioZumbi12 commented Feb 1, 2018

The initial task its to get the exact time from song to note.

But i have a music playing in runtime, then i need to get the note using the song time. On my trys, using something like track.GetNotes().Where(note => note.TimeAs<MetricTimeSpan>(tempo).TotalMicroseconds == position) but never is equals, then, i need to find the next or previous note near and too short than position, whitout repeat this note again.

The task need to get the nearest, if is not equals.
U know what i mean with this explanation?

Thanks for your time and sorry for the delayed aswers.

@melanchall
Copy link
Owner

Now I got it, thanks! :)

What about this code:

var notes = midiFile.GetNotes().ToArray();
var usedNotes = new List<Note>();

// ...

// Find the note nearest to the current position (this should be done every frame)

Note nearestNote = null;
var distance = long.MaxValue;

foreach (var note in notes.Where(n => !usedNotes.Contains(n)))
{
    var newDistance = Math.Abs(position - note.TimeAs<MetricTimeSpan>(tempo).TotalMicroseconds);
    
    // Notes are returned by GetNotes in order of ascending times so we can stop the loop
    // when current distance between position and note's time is not decreased
    if (newDistance >= distance)
        break;

    distance = newDistance;
    nearestNote = note;
}

if (nearestNote != null)
    usedNotes.Add(nearestNote);

Can you test it and say whether it is faster than your solution or not?

@melanchall
Copy link
Owner

@FabioZumbi12 Is your problem solved?

@FabioZumbi12
Copy link
Author

Sorry for the delay. I think yes changing the music speed. Thanks for help <3

@melanchall melanchall added the question Just question about the library label Feb 2, 2020
@melanchall melanchall added this to Done in DryWetMIDI Mar 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Just question about the library
Projects
DryWetMIDI
  
Done
Development

No branches or pull requests

2 participants