Skip to content

Instantly share code, notes, and snippets.

@r618
Created March 3, 2025 23:54
Show Gist options
  • Select an option

  • Save r618/c62b9a6d84896e1303ccbd6d01c89b27 to your computer and use it in GitHub Desktop.

Select an option

Save r618/c62b9a6d84896e1303ccbd6d01c89b27 to your computer and use it in GitHub Desktop.

Revisions

  1. r618 created this gist Mar 3, 2025.
    410 changes: 410 additions & 0 deletions notes2MIDI.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,410 @@
    class Program
    {
    static void Main(string[] args)
    {

    string outputFile = args[0];
    GenerateMidiFile(outputFile);
    Console.WriteLine($"MIDI file saved as {outputFile}");
    }

    const int NOTE_C4 = 60; // C4
    const int NOTE_D4 = 62; // D4
    const int NOTE_E4 = 64; // E4
    const int NOTE_F4 = 65; // F4
    const int NOTE_G4 = 67; // G4
    const int NOTE_A4 = 69; // A4
    const int NOTE_H4_FLAT = 70;
    const int NOTE_H4 = 71; // B4 (H in Czech notation)
    const int NOTE_C5 = 72; // C5

    // Define note durations (in MIDI ticks)
    const int EIGHTH_NOTE = QUARTER_NOTE / 2;
    const int QUARTER_NOTE = 480; // Standard MIDI resolution
    const int HALF_NOTE = QUARTER_NOTE * 2;
    const int HALF_AND_QUARTER_NOTE = QUARTER_NOTE * 3;
    const int WHOLE_NOTE = HALF_NOTE * 2;
    const int REST = -1; // Using -1 as a sentinel value to indicate a rest

    // Define the notes according to the sheet music for Běžela Ovečka
    // Format: [note, duration]
    static readonly object[] bezela_ovecka_notes = new[]
    {
    // First line
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_H4, Duration = HALF_NOTE },
    new { Note = NOTE_C5, Duration = HALF_NOTE },
    new { Note = NOTE_C5, Duration = QUARTER_NOTE },
    new { Note = NOTE_C5, Duration = QUARTER_NOTE },
    new { Note = NOTE_C5, Duration = QUARTER_NOTE },
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = HALF_NOTE },
    new { Note = NOTE_H4, Duration = HALF_NOTE },
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },

    // Second line
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = HALF_NOTE },
    new { Note = NOTE_A4, Duration = HALF_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = HALF_NOTE },
    new { Note = NOTE_G4, Duration = HALF_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE }
    };

    // The notes for "Kočka leze dírou" song
    static readonly object[] kocka_leze_notes = new[]
    {
    // First measure - four eighth notes
    new { Note = NOTE_C4, Duration = QUARTER_NOTE },
    new { Note = NOTE_D4, Duration = QUARTER_NOTE},
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },

    // Second measure - two quarter notes
    new { Note = NOTE_G4, Duration = HALF_NOTE },
    new { Note = NOTE_G4, Duration = HALF_NOTE},

    // Third measure - two quarter notes
    new { Note = NOTE_A4, Duration = HALF_NOTE},
    new { Note = NOTE_A4, Duration = HALF_NOTE},

    // Fourth measure - half note
    new { Note = NOTE_G4, Duration = WHOLE_NOTE },

    // Fifth measure - two quarter notes
    new { Note = NOTE_A4, Duration = HALF_NOTE},
    new { Note = NOTE_A4, Duration = HALF_NOTE},

    // Sixth measure - half note
    new { Note = NOTE_G4, Duration = WHOLE_NOTE },

    // Seventh measure - four quarter notes
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE},
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },

    // Eighth measure - two quarter notes
    new { Note = NOTE_E4, Duration = HALF_NOTE },
    new { Note = NOTE_E4, Duration = HALF_NOTE},

    // Ninth measure - two quarter notes
    new { Note = NOTE_D4, Duration = HALF_NOTE},
    new { Note = NOTE_D4, Duration = HALF_NOTE},

    // Tenth measure - half note (with repeat sign)
    new { Note = NOTE_G4, Duration = WHOLE_NOTE },

    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE},
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },

    // Eighth measure - two quarter notes
    new { Note = NOTE_E4, Duration = HALF_NOTE },
    new { Note = NOTE_E4, Duration = HALF_NOTE},

    // Ninth measure - two quarter notes
    new { Note = NOTE_D4, Duration = HALF_NOTE},
    new { Note = NOTE_D4, Duration = HALF_NOTE},

    // Final measure after repeat - half note
    new { Note = NOTE_C4, Duration = WHOLE_NOTE }
    };

    static readonly object[] prsi_prsi_notes = new[]
    {
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },

    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },

    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },

    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },

    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },

    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = HALF_NOTE },


    new { Note = NOTE_D4, Duration = QUARTER_NOTE },
    new { Note = NOTE_D4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },

    new { Note = NOTE_C4, Duration = QUARTER_NOTE },
    new { Note = NOTE_C4, Duration = QUARTER_NOTE },
    new { Note = NOTE_C4, Duration = HALF_NOTE },
    };

    static readonly object[] pec_nam_spadla_notes = new[]
    {
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },

    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },

    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },


    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = HALF_NOTE },

    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_D4, Duration = QUARTER_NOTE },
    new { Note = NOTE_D4, Duration = QUARTER_NOTE },
    new { Note = NOTE_D4, Duration = QUARTER_NOTE },

    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_D4, Duration = QUARTER_NOTE },
    new { Note = NOTE_D4, Duration = QUARTER_NOTE },
    new { Note = NOTE_D4, Duration = QUARTER_NOTE },

    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },

    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = HALF_NOTE },
    };

    static readonly object[] tluce_bubenicek_notes = new[]
    {
    new { Note = NOTE_F4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_F4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_F4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_F4, Duration = EIGHTH_NOTE },

    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_C4, Duration = QUARTER_NOTE },

    new { Note = NOTE_D4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_D4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_E4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_E4, Duration = EIGHTH_NOTE },

    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = REST, Duration = QUARTER_NOTE },

    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_C5, Duration = EIGHTH_NOTE },

    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },

    new { Note = NOTE_E4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_E4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_D4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_D4, Duration = EIGHTH_NOTE },

    new { Note = NOTE_C4, Duration = QUARTER_NOTE },
    new { Note = REST, Duration = QUARTER_NOTE },

    new { Note = NOTE_H4_FLAT, Duration = EIGHTH_NOTE },
    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },

    new { Note = NOTE_A4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_F4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_F4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_F4, Duration = EIGHTH_NOTE },

    new { Note = NOTE_H4_FLAT, Duration = EIGHTH_NOTE },
    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },

    new { Note = NOTE_A4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_F4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_F4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_F4, Duration = EIGHTH_NOTE },

    new { Note = NOTE_C4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_C4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_D4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_E4, Duration = EIGHTH_NOTE },

    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = REST, Duration = QUARTER_NOTE },

    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_G4, Duration = EIGHTH_NOTE },
    new { Note = NOTE_C5, Duration = EIGHTH_NOTE },
    new { Note = NOTE_E4, Duration = EIGHTH_NOTE },

    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = REST, Duration = QUARTER_NOTE },
    };

    static readonly object[] komari_se_zenili_notes = new[]
    {
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },

    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = HALF_NOTE },

    new { Note = NOTE_D4, Duration = HALF_NOTE },
    new { Note = NOTE_F4, Duration = HALF_NOTE },

    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = HALF_NOTE },

    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },

    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = HALF_NOTE },

    new { Note = NOTE_D4, Duration = HALF_NOTE },
    new { Note = NOTE_F4, Duration = HALF_NOTE },

    new { Note = NOTE_E4, Duration = QUARTER_NOTE },
    new { Note = NOTE_D4, Duration = QUARTER_NOTE },
    new { Note = NOTE_C4, Duration = HALF_NOTE },

    new { Note = NOTE_C4, Duration = HALF_NOTE },
    new { Note = NOTE_C5, Duration = HALF_NOTE },

    new { Note = NOTE_A4, Duration = HALF_AND_QUARTER_NOTE },
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },

    new { Note = NOTE_C5, Duration = QUARTER_NOTE },
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = HALF_NOTE },

    new { Note = NOTE_C5, Duration = QUARTER_NOTE },
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = HALF_NOTE },

    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },

    new { Note = NOTE_E4, Duration = HALF_NOTE },
    new { Note = NOTE_F4, Duration = HALF_NOTE },

    new { Note = NOTE_G4, Duration = WHOLE_NOTE },

    new { Note = NOTE_C4, Duration = HALF_NOTE },
    new { Note = NOTE_C5, Duration = HALF_NOTE },

    new { Note = NOTE_A4, Duration = HALF_AND_QUARTER_NOTE },
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },

    new { Note = NOTE_C5, Duration = QUARTER_NOTE },
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = HALF_NOTE },

    new { Note = NOTE_C5, Duration = QUARTER_NOTE },
    new { Note = NOTE_H4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = HALF_NOTE },

    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_A4, Duration = QUARTER_NOTE },
    new { Note = NOTE_G4, Duration = QUARTER_NOTE },
    new { Note = NOTE_F4, Duration = QUARTER_NOTE },

    new { Note = NOTE_E4, Duration = HALF_NOTE },
    new { Note = NOTE_D4, Duration = HALF_NOTE },

    new { Note = NOTE_C4, Duration = WHOLE_NOTE },
    };

    static void GenerateMidiFile(string outputPath)
    {
    // Create a new MIDI file with one track
    MidiEventCollection midiEvents = new MidiEventCollection(1, QUARTER_NOTE);
    midiEvents.AddTrack();
    midiEvents.AddTrack();

    // Add tempo and time signature info
    long absoluteTime = 0;

    // Set tempo to 120 BPM
    var tempoEvent = new TempoEvent(500000, absoluteTime); // 500000 microseconds = 120 BPM
    midiEvents[0].Add(tempoEvent);

    // Set time signature to 4/4
    var timeSignature = new TimeSignatureEvent(absoluteTime, 4, 4, 24, 8);
    midiEvents[0].Add(timeSignature);

    // Set instrument to Acoustic Grand Piano (General MIDI program 0)
    var patchEvent = new PatchChangeEvent(absoluteTime, 1, 0);
    midiEvents[1].Add(patchEvent);

    // Add notes to the MIDI file
    absoluteTime = 0;

    foreach (dynamic note in komari_se_zenili_notes)
    {
    if (note.Note != REST)
    {
    // Note On event
    var noteOnEvent = new NoteOnEvent(absoluteTime, 1, note.Note, 100, note.Duration);
    midiEvents[1].Add(noteOnEvent);

    // Note Off event (immediately after the note duration)
    var noteOffEvent = new NoteEvent(absoluteTime + note.Duration, 1, MidiCommandCode.NoteOff, note.Note, 0);
    midiEvents[1].Add(noteOffEvent);
    }

    // Move absolute time forward by the note duration
    absoluteTime += note.Duration;
    }

    // Add end of track event
    var endOfTrackEvent = new MetaEvent(MetaEventType.EndTrack, 0, absoluteTime);
    midiEvents[1].Add(endOfTrackEvent);

    // Save MIDI file
    MidiFile.Export(outputPath, midiEvents);
    }
    }