melanchall / drywetmidi

.NET library to read, write, process MIDI files and to work with MIDI devices
https://melanchall.github.io/drywetmidi
MIT License
523 stars 73 forks source link

How do I know when i have added sufficient notes for a bar using the Pattern Builder Class #239

Closed seunyboyxu closed 1 year ago

melanchall commented 1 year ago

Hi,

Please read this first – https://melanchall.github.io/drywetmidi/articles/dev/Support.html – and correct the issue. Make short title and provide as many details as possible in the issue description.

Thanks, Max

seunyboyxu commented 1 year ago

hi max, it is more of a question than an issue, I just wasn't really sure how to ask

melanchall commented 1 year ago

You didn't provide any details. Show some code and what do you want somewhere in that code.

seunyboyxu commented 1 year ago

So i have this class called FinalNote, image NoteName ranges from "A" to "G" including sharps NoteDuration is in a double where for example 0.25 would represent a quarter note (1/4), like this dictionary i made

image

It is in a 2d List where each list represents a bar. And each bar has a list of FinalNote objects. Here is a test example of what this 2d List will look like with a time signature as 4/4 image where you should see the Final Note objects generated

I want to put my note data into a midi file bar by bar, but I am unsure how to do that since I can't find many guides about how PatternBuilder works.

I currently have this, ignore the ChordSequence parameter, since i want to do the exact same thing with chords but i want to deal with the notes first

image

Thank you, let me know if you need any more information

melanchall commented 1 year ago

Thank you very much for explanation, that's what I wanted :) Please answer following questions:

  1. You have collection (bars) where each item is a collection of notes, right?
  2. Each bar is complete, right? Or is it possible that, for example, bar with signature of 4/4 will have 3 quarter notes?
  3. Each note has length as a fraction of the whole note, right?
  4. Notes should be written in a file without gaps between them, right?
seunyboyxu commented 1 year ago
  1. Yes,
  2. Each bar is complete
  3. yes
  4. yes
melanchall commented 1 year ago

Well, in this case your task is supereasy, we even don't need to know where bars borders are. I'll provide you a solution a bit later. Right now I have one more question: what is the octave of notes? Every note in MIDI is a number which represents letter+octave. We can't write just note's name in a MIDI file.

seunyboyxu commented 1 year ago

I want it to default to octave number 4. I am looking into making my program intelligently switch between octaves.

seunyboyxu commented 1 year ago

do you need to see any other parts of the program to help you?

melanchall commented 1 year ago

No, I have all required info now, thanks.

melanchall commented 1 year ago

I suppose something like that should work:

public MidiFile MidiMaker100(
    List<List<FinalNote>> notesByBars,
    int octave,
    int bpm,
    string timeSignatureString)
{
    var patternBuilder = new PatternBuilder();

    foreach (var barNotes in notesByBars)
    {
        foreach (var note in barNotes)
        {
            patternBuilder.Note(
                Melanchall.DryWetMidi.MusicTheory.Note.Parse($"{note.GetNoteName()}{octave}"),
                NoteDurationConversion[note.GetNoteDuration()]);
        }
    }

    var tempo = Tempo.FromBeatsPerMinute(bpm);

    var numer = ...
    var denom = ...
    var timeSignature = new TimeSignature(numer, denom);

    var tempoMap = TempoMap.Create(tempo, timeSignature);

    return patternBuilder.Build().ToFile(tempoMap);
}

Calculate numer and denom by yourself please. But your way is obviously wrong. Please read official documentation how Substring with single argument works.

I've also added octave parameter so just pass what you want there.

Also please always paste you code as text with triple backticks syntax, not as screenshots. It forces me to write your code instead of just copying and pasting. Please learn GitHub Markdown syntax.

seunyboyxu commented 1 year ago

Hi, sorry I will learn this. This all works but how do I add the pattern to a new MidiFile object as a track chunk because I also want to add chords to the same MidiFile object?

melanchall commented 1 year ago

DryWetMIDI has complete documentation, use it please – https://melanchall.github.io/drywetmidi.

So, if you start from PatternBuilder, you'll find its Build method, which returns Pattern object which has ToTrackChunk method. And thus you need to use following code:

var notesTrackChunk = notesPatternBuilder.Build().ToTrackChunk(tempoMap);
var chordsTrackChunk = chordsPatternBuilder.Build().ToTrackChunk(tempoMap);

var midiFile = new MidiFile(notesTrackChunk, chordsTrackChunk);
midiFile.ReplaceTempoMap(tempoMap);

return midiFile;
seunyboyxu commented 1 year ago

Thank you, I think this has solved my problem. I may need help for something else soon, if I end up struggling with it. Hopefully by then I'll be able to ask questions properly on github