예제 #1
0
파일: Form1.cs 프로젝트: aquavit/MoEToiro
 public void openFile(string fileName)
 {
     try
     {
         currentMidiFile = new MidiSequence(fileName);
         titleText.Text = Path.GetFileNameWithoutExtension(fileName);
         doRebuild();
     }
     catch (Exception)
     {
         filesize.ForeColor = Color.Red;
         filesize.Text = fileName + ": これはMIDIじゃないよ";
     }
 }
예제 #2
0
        private void SaveAsButton_Click(object sender, EventArgs e)
        {
            var res = SaveMidiFile.ShowDialog(this);

            if (DialogResult.OK == res)
            {
                var f = _file;
                if (ResampleUpDown.Value != _file.TimeBase)
                {
                    f = f.Resample(unchecked ((short)ResampleUpDown.Value));
                }
                var trks = new List <MidiSequence>(f.Tracks.Count);
                for (int ic = TrackList.Items.Count, i = 0; i < ic; ++i)
                {
                    if (TrackList.CheckedItems.Contains(TrackList.Items[i]))
                    {
                        trks.Add(f.Tracks[i]);
                    }
                }

                var mf = new MidiFile(1, f.TimeBase);
                if (!MergeTracksCheckBox.Checked)
                {
                    foreach (var tr in trks)
                    {
                        mf.Tracks.Add(_ProcessTrack(tr));
                    }
                }
                else
                {
                    mf.Tracks.Add(_ProcessTrack(MidiSequence.Merge(trks)));
                }
                using (var stm = File.OpenWrite(SaveMidiFile.FileName))
                {
                    mf.WriteTo(stm);
                }
            }
        }
예제 #3
0
        public void LoadMIDI(string path)
        {
            try
            {
                using (System.IO.Stream inputStream = System.IO.File.OpenRead(path))
                {
                    sequence = MidiSequence.Open(inputStream);
                }

                var lbl = (Label)GetNode("SC/Label");
                lbl.Text = (string)sequence.ToString();

                Stop(); //Stop the player and clear the channels.

                //Set the MIDI sequence for the player.
                player.sequence = sequence;
                Clock.Reset(sequence.Tracks.Count); //RESET THE CLOCK.  This properly sets the number of tracks for the clock to check.

                AudioStreamGenerator streamGenerator = (AudioStreamGenerator)player.Stream;
                player.parser.ParseSequence(sequence, streamGenerator.MixRate);
            } catch (MidiParser.MidiParserException e) {
                GD.Print("WARNING:  Encountered a problem parsing MIDI.\n", e.ToString());
            }
        }
예제 #4
0
        public static void WriteMidiFile(MidiSequence sequence, string filename)
        {
            MidiFileFormatWriter mffw = new MidiFileFormatWriter(filename);

            using (mffw)
            {
                // Write magic number
                mffw.WriteString(MidiFileFormat.midiFileMarker, false);

                // Write header size
                mffw.WriteUInt32(MidiFileFormat.midiFileHeaderLength);

                // Write header
                mffw.WriteUInt16(MidiFileFormat.midiFileVersion);
                mffw.WriteUInt16((ushort)sequence.Tracks.Count);
                mffw.WriteUInt16((ushort)((sequence.PPQN > 0) ? sequence.PPQN : (sequence.SMPTETempo | 0x8000)));

                // Write out the tracks
                for (int t = 0; t < sequence.Tracks.Count; t++)
                {
                    WriteMidiTrack(mffw, sequence.Tracks[t]);
                }
            }
        }
예제 #5
0
        public void TotalTime()
        {
            var sequence = MidiSequence.Import(MIDI_for_whom_the_bell_tolls);

            //MediaPlayer: 4m54s = 294s
            //totalTime/120 = number of music beats
            var musicTime = (4 * 60) + 54;

            long maxTotalTime = 0;

            foreach (var track in sequence.GetTracks())
            {
                long totalTime = 0;
                foreach (MidiEvent midiEvent in track.Events)
                {
                    totalTime += midiEvent.DeltaTime;
                }

                if (totalTime > maxTotalTime)
                {
                    maxTotalTime = totalTime;
                }

                //(60.0/120.0) = time of one beat (120bpm)
                var trackTime = (totalTime / sequence.Division) * (60.0 / sequence.Division);
                Assert.LessOrEqual(trackTime, musicTime);

                //Trace.TraceInformation(string.Format("Track {0}: {1} seconds",
                //    ((SequenceTrackName)track.Events[0]).Text,
                //    (totalTime / sequence.Division) * (60.0 / sequence.Division)));
            }

            var maxTrackTime = (maxTotalTime / sequence.Division) * (60.0 / sequence.Division);

            Assert.AreEqual(musicTime, maxTrackTime);
        }
예제 #6
0
 static bool EventsRemain(MidiSequence sequence, int ch)
 {
     return(eventPos[ch] <= sequence.Tracks[ch].Events.Count - 1);
 }
예제 #7
0
        public void ParseSequence(MidiSequence s, double sample_rate = 44100.0)
        {
            //First MIDI track should always contain the relevant tempo data.  We need to process this data to build a tempo map between ticks,
            //Translate each tick to a frame position, and push an event to a stack located at the given frame of our lookup dictionary.
            if (s.Tracks.Count == 0)
            {
                return;
            }

            eventsAtPosition.Clear();
            ActionSet.Clear();

            //Initial tempo is == 120bpm
            int beatLen = 480000;                                                 //beat length, in microseconds.  Set by tempo events.
            int divider = s.TicksPerBeatOrFrame > 0?  s.TicksPerBeatOrFrame : 48; //Beat divider.  Use this with beatLen to calculate a tick length.

            //Tick length in sample frames. Calculated based on sample_rate * beatLen/ticksPerBeat/1000000.
            //Useful to determine how many frames we can get away with skipping without worrying about an event miss.
            double tickLen = 441;

            TempoMap tempoMap    = new TempoMap(); //List of frame positions for every tick. Use to stuff events into position by looking for closest index
            int      frameOffset = 0;              //Update this every new tempo event found to account for shifts in deltas. The max value is ~12h at 48000hz.


            //Build the tempo map.
            foreach (MidiSharp.Events.MidiEvent m_event in s.Tracks[0])
            {
                if (!(m_event is TempoMetaMidiEvent))
                {
                    continue;
                }
                var ev = (TempoMetaMidiEvent)m_event;

                //Calculate the frames for each tick leading up to this next tempo event. Events on tick 0 will skip this and immediately update tempo.
                //Once the tempo map is built,  each tick index will return a corresponding frame until the end of track 0.  Any tick indices beyond
                //the list size should be calculated based on the last known tempo.
                //TODO:  When going through all track events and their deltas, should we extend the list further? Or will precalculating the
                //      event map, while slower initially, make keeping the tempo map completely unnecessary?

                for (int i = 0; i < ev.DeltaTime; i++)
                {
                    //Round to the nearest frame.
                    tempoMap.Add((int)Math.Round(frameOffset + i * tickLen));
                }

                //Update the frame offset to the frame where this event should exist.
                frameOffset = frameOffset + (int)Math.Round(ev.DeltaTime * tickLen);

                //Now update the actual tempo for the next operation.
                beatLen = ev.Value;
                tickLen = (sample_rate * beatLen) / (double)divider / 1000000.0; //Tick length in frames
            }

            // Now that all events on track 0 are processed, update the tempo map with the last known tempo value so we can calculate frames
            // for the rest of the events on the other tracks should their delta offset exceed the last tempo event.
            tempoMap.tickLen     = tickLen;
            tempoMap.frameOffset = frameOffset;


            //Now, iterate through all tracks and events and push them to the event map.
            // foreach (MidiTrack track in s.Tracks) //Assume enumerator moves in order...
            for (int t = 1; t < s.Tracks.Count; t++) //Assume enumerator moves in order...
            {
                MidiTrack track  = s.Tracks[t];
                int       offset = 0;
                for (int i = 0; i < track.Events.Count; i++)
                {
                    var ev    = track.Events[i];
                    var frame = tempoMap.CalcFrame((int)(ev.DeltaTime + offset));

                    List <MidiSharp.Events.MidiEvent> list;
                    if (eventsAtPosition.ContainsKey(frame)) //Make a new list if this key needs it.
                    {
                        list = eventsAtPosition[frame];
                    }
                    else
                    {
                        list = new List <MidiSharp.Events.MidiEvent>();
                        eventsAtPosition.Add(frame, list);
                    }

                    //Add the event to the list at this frame position.  TODO:  organize by MIDI channel?
                    list.Add(ev);

                    offset += (int)ev.DeltaTime;   //Move up the delta timer.
                }
            }
        }
예제 #8
0
        MidiFile _ProcessFile()
        {
            // first we clone the file to be safe
            // that way in case there's no modifications
            // specified in the UI we'll still return
            // a copy.
            var result = _file.Clone();

            // transpose it if specified
            if (0 != TransposeUpDown.Value)
            {
                result = result.Transpose((sbyte)TransposeUpDown.Value, WrapCheckBox.Checked, !DrumsCheckBox.Checked);
            }
            // resample if specified
            if (ResampleUpDown.Value != _file.TimeBase)
            {
                result = result.Resample(unchecked ((short)ResampleUpDown.Value));
            }
            // compute our offset and length in ticks or beats/quarter-notes
            var ofs = OffsetUpDown.Value;
            var len = LengthUpDown.Value;

            if (0 == UnitsCombo.SelectedIndex)             // beats
            {
                len = Math.Min(len * _file.TimeBase, _file.Length);
                ofs = Math.Min(ofs * _file.TimeBase, _file.Length);
            }
            switch (StartCombo.SelectedIndex)
            {
            case 1:
                ofs += result.FirstDownBeat;
                break;

            case 2:
                ofs += result.FirstNoteOn;
                break;
            }
            // nseq holds our patch and timing info
            var nseq = new MidiSequence();

            if (0 != ofs && CopyTimingPatchCheckBox.Checked)
            {
                // we only want to scan until the
                // first note on
                // we need to check all tracks so
                // we merge them into mtrk and scan
                // that
                var mtrk = MidiSequence.Merge(result.Tracks);
                var end  = mtrk.FirstNoteOn;
                if (0 == end)                 // break later:
                {
                    end = mtrk.Length;
                }
                var ins = 0;
                for (int ic = mtrk.Events.Count, i = 0; i < ic; ++i)
                {
                    var ev = mtrk.Events[i];
                    if (ev.Position >= end)
                    {
                        break;
                    }
                    var m = ev.Message;
                    switch (m.Status)
                    {
                    // the reason we don't check for MidiMessageMetaTempo
                    // is a user might have specified MidiMessageMeta for
                    // it instead. we want to handle both
                    case 0xFF:
                        var mm = m as MidiMessageMeta;
                        switch (mm.Data1)
                        {
                        case 0x51:                                         // tempo
                        case 0x54:                                         // smpte
                            if (0 == nseq.Events.Count)
                            {
                                nseq.Events.Add(new MidiEvent(0, ev.Message.Clone()));
                            }
                            else
                            {
                                nseq.Events.Insert(ins, new MidiEvent(0, ev.Message.Clone()));
                            }
                            ++ins;
                            break;
                        }
                        break;

                    default:
                        // check if it's a patch change
                        if (0xC0 == (ev.Message.Status & 0xF0))
                        {
                            if (0 == nseq.Events.Count)
                            {
                                nseq.Events.Add(new MidiEvent(0, ev.Message.Clone()));
                            }
                            else
                            {
                                nseq.Events.Insert(ins, new MidiEvent(0, ev.Message.Clone()));
                            }
                            // increment the insert count
                            ++ins;
                        }
                        break;
                    }
                }
                // set the track to the loop length
                nseq.Events.Add(new MidiEvent((int)len, new MidiMessageMetaEndOfTrack()));
            }
            // see if track 0 is checked
            var hasTrack0 = TrackList.GetItemChecked(0);

            // slice our loop out of it
            if (0 != ofs || result.Length != len)
            {
                result = result.GetRange((int)ofs, (int)len, CopyTimingPatchCheckBox.Checked, false);
            }
            // normalize it!
            if (NormalizeCheckBox.Checked)
            {
                result = result.NormalizeVelocities();
            }
            // scale levels
            if (1m != LevelsUpDown.Value)
            {
                result = result.ScaleVelocities((double)LevelsUpDown.Value);
            }

            // create a temporary copy of our
            // track list
            var l = new List <MidiSequence>(result.Tracks);

            // now clear the result
            result.Tracks.Clear();
            for (int ic = l.Count, i = 0; i < ic; ++i)
            {
                // if the track is checked in the list
                // add it back to result
                if (TrackList.GetItemChecked(i))
                {
                    result.Tracks.Add(l[i]);
                }
            }
            if (0 < nseq.Events.Count)
            {
                // if we don't have track zero we insert
                // one.
                if (!hasTrack0)
                {
                    result.Tracks.Insert(0, nseq);
                }
                else
                {
                    // otherwise we merge with track 0
                    result.Tracks[0] = MidiSequence.Merge(nseq, result.Tracks[0]);
                }
            }
            // next adjust the tempo
            if (_file.Tempo != (double)TempoUpDown.Value)
            {
                result = result.AdjustTempo((double)TempoUpDown.Value);
            }
            // stretch the result. we do this
            // here so the track lengths are
            // correct and we don't need ofs
            // or len anymore
            if (1m != StretchUpDown.Value)
            {
                result = result.Stretch((double)StretchUpDown.Value, AdjustTempoCheckBox.Checked);
            }

            // if merge is checked merge the
            // tracks
            if (MergeTracksCheckBox.Checked)
            {
                var trk = MidiSequence.Merge(result.Tracks);
                result.Tracks.Clear();
                result.Tracks.Add(trk);
            }
            _dirty       = false;
            _reseekDirty = false;
            return(result);
        }
예제 #9
0
        public void CheckTheFirstChord()
        {
            var sequence     = MidiSequence.Import(MIDI_for_whom_the_bell_tolls);
            var guitar1Track = sequence.GetTracks()[2];

            var           listOfChords = new List <List <NoteOn> >();
            List <NoteOn> chordNotes   = null;
            bool          isPause      = false;

            foreach (MidiEvent midiEvent in guitar1Track.Events)
            {
                if (midiEvent is NoteOn)
                {
                    var note = (NoteOn)midiEvent;
                    if (note.DeltaTime > 0)
                    {
                        if ((chordNotes != null) && (chordNotes.Count > 0))
                        {
                            listOfChords.Add(chordNotes);
                        }

                        chordNotes = new List <NoteOn>();

                        isPause = (note.Velocity == 0); //used for the next notes of the acord (same time)
                    }

                    if ((note.Velocity > 0) && (!isPause))
                    {
                        chordNotes.Add(note);
                    }
                }
            }

            //start on 1680 from the beggining
            {
                var chord = listOfChords[0];

                Assert.AreEqual(3, chord.Count);

                Assert.AreEqual(1680, chord[0].DeltaTime);
                Assert.AreEqual(100, chord[0].Velocity);

                Assert.AreEqual("C#4", MidiEvent.GetNoteName(chord[0].Note));
                Assert.AreEqual("F#4", MidiEvent.GetNoteName(chord[1].Note));
                Assert.AreEqual("F#3", MidiEvent.GetNoteName(chord[2].Note));
            }

            //start on 40 after the last event
            {
                var chord = listOfChords[1];

                Assert.AreEqual(3, chord.Count);

                Assert.AreEqual(40, chord[0].DeltaTime);
                Assert.AreEqual(100, chord[0].Velocity);

                Assert.AreEqual("C#4", MidiEvent.GetNoteName(chord[0].Note));
                Assert.AreEqual("F#4", MidiEvent.GetNoteName(chord[1].Note));
                Assert.AreEqual("F#3", MidiEvent.GetNoteName(chord[2].Note));
            }

            //and so on...

            /*
             *      track.Events.Add(new NoteOn(1680, 1, "C#4", 100));
             *      track.Events.Add(new NoteOn(0, 1, "F#4", 100));
             *      track.Events.Add(new NoteOn(0, 1, "F#3", 100));
             *      track.Events.Add(new NoteOn(40, 1, "F#3", 0));
             *      track.Events.Add(new NoteOn(0, 1, "F#4", 0));
             *      track.Events.Add(new NoteOn(0, 1, "C#4", 0));
             *      track.Events.Add(new NoteOn(0, 1, "C#4", 100));
             *      track.Events.Add(new NoteOn(0, 1, "F#4", 100));
             *      track.Events.Add(new NoteOn(0, 1, "F#3", 100));
             *      track.Events.Add(new NoteOn(40, 1, "F#3", 0));
             *      track.Events.Add(new NoteOn(0, 1, "F#4", 0));
             *      track.Events.Add(new NoteOn(0, 1, "C#4", 0));
             *      track.Events.Add(new NoteOn(40, 1, "C#4", 100));
             *      track.Events.Add(new NoteOn(0, 1, "F#4", 100));
             *      track.Events.Add(new NoteOn(0, 1, "F#3", 100));
             */
        }
예제 #10
0
        public void LoadFile_Check10Tracks()
        {
            var sequence = MidiSequence.Import(MIDI_for_whom_the_bell_tolls);

            Assert.AreEqual(10, sequence.NumberOfTracks);
        }
예제 #11
0
        /// <summary>
        /// Creates a notechart from the specified midi path and the actual charttype
        /// (i.e. ExpertSingle from notes.mid).  Due to the overhead necessary to
        /// parse a midi file.  I am going to cram all midi->chart operations into
        /// one function call.
        /// This function uses the Toub midi parser which is much faster than Sanford,
        /// but will throw an exception on certian midi files.
        /// </summary>
        /// <param name="chartSelection">
        /// The information on which particular notechart to use.
        /// </param>
        /// <param name="chartInfo">The metadata on the chart.</param>
        /// <param name="BPMChanges">The list of BPM changes for this chart.</param>
        /// <returns>
        /// A filled out Notechart containing the needed information from the *.mid file.
        /// </returns>
        public static Notes ParseMidiInformationToub(ChartSelection chartSelection,
                                                     Info chartInfo,
                                                     List <BPMChange> BPMChanges)
        {
            Notes notechartToReturn = new Notes();

            notechartToReturn.instrument = chartSelection.instrument;
            notechartToReturn.difficulty = chartSelection.difficulty;

            // The following two switch's are used to get the proper midi terminology for
            // the selected track and difficulty.
            string instrumentPart = null;
            string greenKey       = null;
            string redKey         = null;
            string yellowKey      = null;
            string blueKey        = null;
            string orangeKey      = null;

            switch (chartSelection.instrument)
            {
            case "Single":
                instrumentPart = "PART GUITAR";
                break;

            case "DoubleGuitar":
                instrumentPart = "PART GUITAR COOP";
                break;

            case "DoubleBass":
                instrumentPart = "PART BASS";
                break;

            case "Drums":
                instrumentPart = "PART DRUMS";
                break;

            default:
                instrumentPart = "PART GUITAR";
                break;
            }

            switch (chartSelection.difficulty)
            {
            case "Expert":
                greenKey  = "C8";
                redKey    = "C#8";
                yellowKey = "D8";
                blueKey   = "D#8";
                orangeKey = "E8";
                break;

            case "Hard":
                greenKey  = "C7";
                redKey    = "C#7";
                yellowKey = "D7";
                blueKey   = "D#7";
                orangeKey = "E7";
                break;

            case "Medium":
                greenKey  = "C6";
                redKey    = "C#6";
                yellowKey = "D6";
                blueKey   = "D#6";
                orangeKey = "E6";
                break;

            case "Easy":
                greenKey  = "C5";
                redKey    = "C#5";
                yellowKey = "D5";
                blueKey   = "D#5";
                orangeKey = "E5";
                break;

            default:
                greenKey  = "C8";
                redKey    = "C#8";
                yellowKey = "D8";
                blueKey   = "D#8";
                orangeKey = "E8";
                break;
            }

            MidiSequence mySequence = MidiSequence.Import(chartSelection.directory + "\\notes.mid");

            MidiTrack[] myTracks = mySequence.GetTracks();
            chartInfo.resolution = mySequence.Division;

            MidiTrack trackToUse     = new MidiTrack();
            uint      totalTickValue = 0;

            // Go through each event in the first track (which contains the BPM changes)
            // and parse the resulting string.
            for (int i = 0; i < myTracks[0].Events.Count; i++)
            {
                Toub.Sound.Midi.MidiEvent currEvent = myTracks[0].Events[i];
                string   eventString      = currEvent.ToString();
                string[] splitEventString = eventString.Split('\t');

                // Since ticks are stored relative to each other (e.g. 300 ticks
                // until next note), we must maintain the total tick amout.
                totalTickValue += Convert.ToUInt32(splitEventString[1]);
                if (splitEventString[0] == "Tempo")
                {
                    // In midi files, bpm chages are stored as "microseconds per quarter note"
                    // and must be converted to BPM, and then into the non decimal format the game
                    // uses.
                    double currBPMDouble = 60000000 / Convert.ToDouble(splitEventString[3]);
                    uint   BPMToAdd      = (uint)(currBPMDouble * 1000);
                    BPMChanges.Add(new BPMChange(totalTickValue, BPMToAdd));
                }
            }

            trackToUse = new MidiTrack();
            // Find the specified instrument's track
            foreach (MidiTrack currTrack in myTracks)
            {
                string   trackHeader = currTrack.Events[0].ToString();
                string[] splitHeader = trackHeader.Split('\t');

                // -If we come across a "T1 GEMS" track, we're in GH1 territory.
                // -GH2/FoF has both PART BASS and PART RHYTHM (one or the other depending
                //  on the chart).
                if (((splitHeader[3] == instrumentPart) || (splitHeader[3] == "T1 GEMS")) ||
                    ((splitHeader[3] == "PART RHYTHM") && (instrumentPart == "PART BASS")))
                {
                    trackToUse = currTrack;
                }
            }

            totalTickValue = 0;
            uint currTickValue = 0;
            Note currNote      = new Note();
            bool blankNote     = true;

            // Scan through and record every note specific to the selected difficulty
            for (int i = 0; i < trackToUse.Events.Count; i++)
            {
                string   currEvent  = trackToUse.Events[i].ToString();
                string[] splitEvent = currEvent.Split('\t');
                currTickValue   = Convert.ToUInt32(splitEvent[1]);
                totalTickValue += currTickValue;

                // We need to specify wether a note is blank or not so we don't add
                // blank notes from other difficulties into the chart, but if we have
                // a filled out note, any nonzero tick value means we are moving to a
                // new note, so we must cut our ties and add this note to the chart.
                if ((currTickValue != 0) && !blankNote)
                {
                    notechartToReturn.notes.Add(currNote);
                    currNote  = new Note();
                    blankNote = true;
                }

                // The "0x64" I think means "not was hit."  There is another
                // set of notes that use "0x00" that all appear slightly after
                // the "0x64" notes.
                if ((splitEvent[0] == "NoteOn") && (splitEvent[4] != "0x00"))
                {
                    // Only consider notes within the octave our difficulty is in.
                    if ((splitEvent[3] == greenKey) || (splitEvent[3] == redKey) ||
                        (splitEvent[3] == yellowKey) || (splitEvent[3] == blueKey) ||
                        (splitEvent[3] == orangeKey))
                    {
                        // If it's a new note, we need to setup the tick value of it.
                        if (blankNote)
                        {
                            currNote.tickValue = totalTickValue;
                            blankNote          = false;
                        }
                        if (splitEvent[3] == greenKey)
                        {
                            currNote.addNote(0);
                        }
                        else if (splitEvent[3] == redKey)
                        {
                            currNote.addNote(1);
                        }
                        else if (splitEvent[3] == yellowKey)
                        {
                            currNote.addNote(2);
                        }
                        else if (splitEvent[3] == blueKey)
                        {
                            currNote.addNote(3);
                        }
                        else if (splitEvent[3] == orangeKey)
                        {
                            currNote.addNote(4);
                        }
                    }
                }
            }

            return(notechartToReturn);
        }
예제 #12
0
        static void ComplexRecordingDemo()
        {
            using (var idev = MidiDevice.Inputs[0])
            {
                // TODO: currently this doesn't let you
                // change the tempo in the middle of recording

                // match these two variables to your input rate
                short timeBase   = 480;
                var   microTempo = MidiUtility.TempoToMicroTempo(120);

                // track 0 - meta track for tempo info
                var tr0 = new MidiSequence();
                // our seq for recording
                var seq = new MidiSequence();
                // compute our timing based on current microTempo and timeBase
                var ticksusec    = microTempo / (double)timeBase;
                var tickspertick = ticksusec / (TimeSpan.TicksPerMillisecond / 1000) * 100;
                var pos          = 0;
                // set this to _PreciseUtcNowTicks in order
                // to start recording now. Otherwise it will
                // not record until the first message is
                // recieved:
                var startTicks = 0L;

                using (var odev = MidiDevice.Outputs[0])
                {
                    // hook up the delegate
                    idev.Input += delegate(object s, MidiInputEventArgs ea)
                    {
                        // initialize start ticks with the current time in ticks
                        if (0 == startTicks)
                        {
                            startTicks = _PreciseUtcNowTicks;
                        }
                        // compute our current MIDI ticks
                        var midiTicks = (int)Math.Round((_PreciseUtcNowTicks - startTicks) / tickspertick);
                        // pass through to play
                        odev.Send(ea.Message);
                        // HACK: technically the sequence isn't threadsafe but as long as this event
                        // is not reentrant and the MidiSequence isn't touched outside this it should
                        // be fine
                        seq.Events.Add(new MidiEvent(midiTicks - pos, ea.Message));
                        // this is to track our old position
                        // so we can compute deltas
                        pos = midiTicks;
                    };
                    // open the input device
                    idev.Open();
                    // open the output device
                    odev.Open();
                    // add our tempo to the beginning of track 0
                    tr0.Events.Add(new MidiEvent(0, new MidiMessageMetaTempo(microTempo)));
                    // start listening
                    idev.Start();
                    Console.Error.WriteLine("Recording started.");
                    // wait
                    Console.Error.WriteLine("Press any key to stop recording...");
                    Console.ReadKey();
                    // stop the buffer and flush any pending events
                    idev.Stop();
                    idev.Reset();
                }

                // create termination track
                var endTrack = new MidiSequence();
                var len      = seq.Length;
                // comment the following to terminate
                // without the trailing empty score:
                len = unchecked ((int)((_PreciseUtcNowTicks - startTicks) / tickspertick));
                endTrack.Events.Add(new MidiEvent(len, new MidiMessageMetaEndOfTrack()));

                // terminate the tracks
                tr0 = MidiSequence.Merge(tr0, endTrack);
                seq = MidiSequence.Merge(seq, endTrack);

                // build a type 1 midi file
                var mf = new MidiFile(1, timeBase);
                // add both tracks
                mf.Tracks.Add(tr0);
                mf.Tracks.Add(seq);

                // now stream the file to the output
                // just grab the first output stream
                using (var stm = MidiDevice.Streams[0])
                {
                    // open it
                    stm.Open();
                    // merge the tracks for playback
                    seq = MidiSequence.Merge(mf.Tracks);
                    // set the stream timebase
                    stm.TimeBase = mf.TimeBase;
                    // start the playback
                    stm.Start();
                    Console.Error.WriteLine("Press any key to exit...");
                    // if we weren't looping
                    // we wouldn't need to
                    // hook this:
                    stm.SendComplete += delegate(object s, EventArgs e)
                    {
                        // loop
                        stm.Send(seq.Events);
                    };
                    // kick things off
                    stm.Send(seq.Events);
                    // wait for exit
                    Console.ReadKey();
                }
            }
        }
예제 #13
0
파일: Form1.cs 프로젝트: aquavit/MoEToiro
        private string makeTitle(MidiSequence.MidiTrack track)
        {
            string inst = track.InstrumentName;
            if (inst == null || inst.Length == 0)
            {
                inst = "_パート #" + track.TrackNumber;
            }
            else
            {
                inst += "_" + track.TrackNumber;
            }

            return this.titleText.Text + "_" + inst;
        }
예제 #14
0
파일: Form1.cs 프로젝트: aquavit/MoEToiro
        private void addTrack(MidiSequence.MidiTrack track)
        {
            string title = makeTitle(track);

            TabPage p = addTabPage(title, track.toMoEAbc());
            p.Tag = track;
        }
예제 #15
0
        MidiSequence _ProcessTrack(MidiSequence trk)
        {
            var ofs = (int)OffsetUpDown.Value;
            var len = (int)LengthUpDown.Value;

            if (0 == UnitsCombo.SelectedIndex)             // beats
            {
                len = (int)Math.Min(Math.Ceiling(len * (decimal)_file.TimeBase), _file.Length);
                ofs = (int)Math.Min(Math.Ceiling(ofs * (decimal)_file.TimeBase), _file.Length);
            }
            switch (StartCombo.SelectedIndex)
            {
            case 1:
                ofs += _file.FirstDownBeat;
                break;

            case 2:
                ofs += _file.FirstNoteOn;
                break;
            }
            switch (StartCombo.SelectedIndex)
            {
            case 1:
                ofs += _file.FirstDownBeat;
                break;

            case 2:
                ofs += _file.FirstNoteOn;
                break;
            }
            if (0 != ofs && CopyTimingPatchCheckBox.Checked)
            {
                var end = trk.FirstNoteOn;
                if (0 == end)
                {
                    end = trk.Length;
                }
                var trk2 = trk.GetRange(ofs, len);
                var ins  = 0;
                for (int ic = trk.Events.Count, i = 0; i < ic; ++i)
                {
                    var ev = trk.Events[i];
                    if (ev.Position >= end)
                    {
                        break;
                    }
                    var m = ev.Message;
                    switch (m.Status)
                    {
                    case 0xFF:
                        var mm = m as MidiMessageMeta;
                        switch (mm.Data1)
                        {
                        case 0x51:
                        case 0x54:
                            trk2.Events.Insert(ins, ev.Clone());
                            ++ins;
                            break;
                        }
                        break;

                    default:
                        if (0xC0 == (ev.Message.Status & 0xF0))
                        {
                            trk2.Events.Insert(ins, ev.Clone());
                            ++ins;
                        }
                        break;
                    }
                }
                trk = trk2;
            }
            else
            {
                if (trk.Length != len || 0 != ofs)
                {
                    trk = trk.GetRange(ofs, len);
                }
            }
            if (1m != StretchUpDown.Value)
            {
                trk = trk.Stretch((double)StretchUpDown.Value, AdjustTempoCheckBox.Checked);
            }
            return(trk);
        }
예제 #16
0
        static void Main(string[] args)
        {
            double        toneDistance = 1;
            double        beatDistance = 1;
            double        n;
            List <string> lines = new List <string>();

            lines.Add("INSERT PUNCHHOLE");
            string path;
            double note;
            double ticks;
            double time;

            if (args.Length == 0)
            {
                Console.WriteLine("Usage: WintergatanLaserMIDI <filename.mid> [Tone Distance (mm)] [Beat Distance (mm)]");
                Console.WriteLine("\tfilename.mid = MIDI file for which to generate code");
                Console.WriteLine("\tTone Distance = Defines the distance between every note-pitch.");
                Console.WriteLine("\tBeat Distance = Defines how far away the beats are from each other.");
                Console.WriteLine();
                return;
            }

            if (!File.Exists(args[0]))
            {
                Console.WriteLine("Error: file {0} not found", args[0]);
                return;
            }

            path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\" + args[0] + ".scr";
            path = new Uri(path).LocalPath;

            if (File.Exists(path))
            {
                File.Delete(path);
            }

            if (args.Length == 2 && !string.IsNullOrEmpty(args[1]))
            {
                if (double.TryParse(args[1], out n))
                {
                    toneDistance = n;
                }
                else
                {
                    Console.WriteLine("Tone Distance must be a number!");
                    return;
                }
            }

            if (args.Length == 3 && !string.IsNullOrEmpty(args[2]))
            {
                if (double.TryParse(args[2], out n))
                {
                    beatDistance = n;
                }
                else
                {
                    Console.WriteLine("Beat Distance must be a number!");
                    return;
                }
            }

            try
            {
                MidiSequence sequence = MidiSequence.Open(File.OpenRead(args[0]));
                ticks = (double)sequence.Division;

                foreach (MidiTrack track in sequence)
                {
                    track.Events.ConvertDeltasToTotals();
                    foreach (MidiEvent ev in track.Events)
                    {
                        if (ev.GetType().ToString() == "MidiSharp.Events.Voice.Note.OnNoteVoiceMidiEvent")
                        {
                            NoteVoiceMidiEvent nvme = ev as NoteVoiceMidiEvent;
                            note = (double)nvme.Note;
                            time = (double)ev.DeltaTime;

                            Console.WriteLine(((time / ticks) * beatDistance) + "," + ((note - 60.0d) * toneDistance));
                            if (lines.Count >= 2)
                            {
                                lines.Add("  " + ((time / ticks) * beatDistance) + "," + ((note - 60.0d) * toneDistance) + ",0 1 1 0");
                            }
                            else
                            {
                                lines.Add(((time / ticks) * beatDistance) + "," + ((note - 60.0d) * toneDistance) + ",0 1 1 0");
                            }
                        }
                    }
                }

                System.IO.File.WriteAllLines(path, lines);
            }
            catch (Exception exc)
            {
                Console.Error.WriteLine("Error: {0}", exc.Message);
            }
        }
예제 #17
0
        private void PreviewButton_Click(object sender, EventArgs e)
        {
            if ("Stop" == PreviewButton.Text)
            {
                if (null != _previewThread)
                {
                    _previewThread.Abort();
                    _previewThread.Join();
                    _previewThread = null;
                }
                PreviewButton.Text = "Preview";
                return;
            }
            var f = _file;

            if (ResampleUpDown.Value != _file.TimeBase)
            {
                f = _file.Resample(unchecked ((short)ResampleUpDown.Value));
            }
            var trks = new List <MidiSequence>(f.Tracks.Count);

            for (int ic = TrackList.Items.Count, i = 0; i < ic; ++i)
            {
                if (TrackList.CheckedItems.Contains(TrackList.Items[i]))
                {
                    trks.Add(f.Tracks[i]);
                }
            }
            var trk = MidiSequence.Merge(trks);
            var ofs = (int)OffsetUpDown.Value;
            var len = (int)LengthUpDown.Value;

            if (0 == UnitsCombo.SelectedIndex)             // beats
            {
                len = (int)Math.Min(Math.Ceiling(len * (decimal)f.TimeBase), f.Length);
                ofs = (int)Math.Min(Math.Ceiling(ofs * (decimal)f.TimeBase), f.Length);
            }
            switch (StartCombo.SelectedIndex)
            {
            case 1:
                ofs += f.FirstDownBeat;
                break;

            case 2:
                ofs += f.FirstNoteOn;
                break;
            }
            if (0 != ofs && CopyTimingPatchCheckBox.Checked)
            {
                var end = trk.FirstNoteOn;
                if (0 == end)
                {
                    end = trk.Length;
                }
                var trk2 = trk.GetRange(ofs, len);
                var ins  = 0;
                for (int ic = trk.Events.Count, i = 0; i < ic; ++i)
                {
                    var ev = trk.Events[i];
                    if (ev.Position >= end)
                    {
                        break;
                    }
                    var m = ev.Message;
                    switch (m.Status)
                    {
                    case 0xFF:
                        var mm = m as MidiMessageMeta;
                        switch (mm.Data1)
                        {
                        case 0x51:
                        case 0x54:
                            trk2.Events.Insert(ins, ev.Clone());
                            ++ins;
                            break;
                        }
                        break;

                    default:
                        if (0xC0 == (ev.Message.Status & 0xF0))
                        {
                            trk2.Events.Insert(ins, ev.Clone());
                            ++ins;
                        }
                        break;
                    }
                }
                trk = trk2;
            }
            else
            {
                if (trk.Length != len || 0 != ofs)
                {
                    trk = trk.GetRange(ofs, len);
                }
            }
            if (1m != StretchUpDown.Value)
            {
                trk = trk.Stretch((double)StretchUpDown.Value, AdjustTempoCheckBox.Checked);
            }

            if (null != _previewThread)
            {
                _previewThread.Abort();
                _previewThread.Join();
                _previewThread = null;
            }
            PreviewButton.Text = "Stop";
            _previewThread     = new Thread(() => { trk.Preview(f.TimeBase, 0, true); });
            _previewThread.Start();
        }
예제 #18
0
        public static MidiSequence ParseMidiFile(string filename)
        {
            MidiFileFormatReader mffr = new MidiFileFormatReader(filename);

            using (mffr)
            {
                //
                // Verify magic number
                //
                string marker = mffr.ReadString(4);
                if (marker != MidiFileFormat.midiFileMarker)
                {
                    throw new FormatException(string.Format("Invalid marker for file {0}, expected {1} found {2}", filename, MidiFileFormat.midiFileMarker, marker));
                }

                // Verify header size
                uint headerLength = mffr.ReadUInt32();
                if (headerLength != MidiFileFormat.midiFileHeaderLength)
                {
                    throw new FormatException(string.Format("Invalid header length for file {0}, expected {1} found {2}", filename, MidiFileFormat.midiFileHeaderLength, headerLength));
                }

                //
                // Parse header
                //

                //
                // The 6 next bytes are 16-bits values, defining
                // the format, #tracks, and ppqn
                //
                uint midiVersion    = mffr.ReadUInt16(); // Midi version (0, 1, 2)
                uint numberOfTracks = mffr.ReadUInt16(); // Number of tracks
                uint resolution     = mffr.ReadUInt16(); // PPQN
                uint ppqn           = 0;
                uint smpteTempo     = 0;

                //
                // ppqn: Pulse per quarter note: The number of tics
                // per quarter notes. The length of a tic is the
                // tempo (length of a quarter note) divided by ppqn.
                //
                //
                // if ppqn is < 0, then it is NOT a ppqn, it is a
                // tempo in SMTPE format (??)
                //
                if (0 != (resolution & 0x8000))
                {
                    ppqn       = 0;
                    smpteTempo = resolution & 0x7FFF;
                }
                else
                {
                    ppqn       = resolution;
                    smpteTempo = 0;
                }

                //
                // Create the midi sequence
                //
                MidiSequence result = new MidiSequence(midiVersion, ppqn, smpteTempo, filename);

                //
                // Create and parse the tracks
                //
                for (uint t = 0; t < numberOfTracks; t++)
                {
                    result.Tracks.Add(ParseMidiTrack(mffr, t));
                }

                // Return the sequence
                return(result);
            }
        }
예제 #19
0
        static void ComplexStreamingDemo()
        {
            // demonstrate streaming a midi file 100 events at a time
            // this allows you to handle files with more than 64kb
            // of in-memory events (not the same as "on disk" size)
            // this replays the events in a loop
            var midiFile = MidiFile
                           //.ReadFrom(@"..\..\Bohemian-Rhapsody-1.mid"); // > 64kb!
                           .ReadFrom(@"..\..\A-Warm-Place.mid");

            //.ReadFrom(@"..\..\GORILLAZ_-_Feel_Good_Inc.mid");
            //.ReadFrom(@"..\..\Feel_good_4beatsBass.mid");
            //.ReadFrom(@"..\..\THE BEASTIE BOYS.Sabotage.mid");
            //.ReadFrom(@"..\..\Peter-Gunn-1.mid");
            Console.WriteLine(Path.GetFileName(midiFile.FilePath) + " @ " + midiFile.TimeBase + " PQN");
            var tsig = midiFile.TimeSignature;

            Console.WriteLine("Tempo: " + midiFile.Tempo + " BPM @ " + tsig.Numerator + "/" + tsig.Denominator + " time");
            Console.WriteLine("Tracks:");
            for (var i = 0; i < midiFile.Tracks.Count; ++i)
            {
                var track = midiFile.Tracks[i];
                Console.Write("\t");
                var name = track.Name;
                if (string.IsNullOrEmpty(name))
                {
                    name = "Track " + i;
                }
                Console.WriteLine(name + " \tEvents: " + track.Events.Count);
            }
            Console.WriteLine();
            // we use 100 events, which should be safe and allow
            // for some measure of SYSEX messages in the stream
            // without bypassing the 64kb limit
            const int EVENT_COUNT = 100;
            // our current cursor pos
            int pos = 0;
            // merge our file for playback
            var seq = MidiSequence.Merge(midiFile.Tracks);
            // the number of events in the seq
            int len = seq.Events.Count;
            // stores the next set of events
            var eventList = new List <MidiEvent>(EVENT_COUNT);

            // just grab the first output stream
            // should be the wavetable synth
            using (var stm = MidiDevice.Streams[0])
            {
                // open the stream
                stm.Open();
                // start it
                stm.Start();
                // first set the timebase
                stm.TimeBase = midiFile.TimeBase;

                // set up our send complete handler
                stm.SendComplete += delegate(object sender, EventArgs eargs)
                {
                    // clear the list
                    eventList.Clear();
                    // iterate through the next events
                    var next = pos + EVENT_COUNT;
                    for (; pos < next; ++pos)
                    {
                        // if it's past the end, loop it
                        if (len <= pos)
                        {
                            pos = 0;
                            break;
                        }
                        // otherwise add the next event
                        eventList.Add(seq.Events[pos]);
                    }
                    // send the list of events
                    stm.SendDirect(eventList);
                };
                // add the first events
                for (pos = 0; pos < EVENT_COUNT; ++pos)
                {
                    // if it's past the end, loop it
                    if (len <= pos)
                    {
                        pos = 0;
                        break;
                    }
                    // otherwise add the next event
                    eventList.Add(seq.Events[pos]);
                }
                // send the list of events
                stm.SendDirect(eventList);

                // loop until a key is pressed
                Console.Error.WriteLine("Press any key to exit...");
                Console.ReadKey();
                // close the stream
                stm.Close();
            }
        }
예제 #20
0
        static void SimpleRecordingDemo()
        {
            MidiFile mf;

            using (var idev = MidiDevice.Inputs[0])
            {
                using (var odev = MidiDevice.Outputs[0])
                {
                    idev.Input += delegate(object s, MidiInputEventArgs e)
                    {
                        // this is so we can pass through and hear
                        // our input while recording
                        odev.Send(e.Message);
                    };
                    idev.TempoChanged += delegate(object s, EventArgs e)
                    {
                        Console.WriteLine("New Tempo: " + idev.Tempo);
                    };
                    // open the input
                    // and output
                    idev.Open();
                    // set our timebase
                    idev.TimeBase = 384;
                    odev.Open();
                    idev.Start();
                    // start recording, waiting for input
                    idev.StartRecording(true);
                    // wait to end it
                    Console.Error.WriteLine("Press any key to stop recording...");
                    Console.ReadKey();
                    // get our MidiFile from this
                    mf = idev.EndRecording();
                    // the MIDI file is always two
                    // tracks, with the first track
                    // being the tempo map
                }
            }
            if (null == mf)
            {
                return;
            }
            // merge for playback
            var seq = MidiSequence.Merge(mf.Tracks);

            // now stream the file to the output
            // just grab the first output stream
            using (var stm = MidiDevice.Streams[0])
            {
                // open it
                stm.Open();
                // merge the tracks for playback
                seq = MidiSequence.Merge(mf.Tracks);
                // set the stream timebase
                stm.TimeBase = mf.TimeBase;
                // start the playback
                stm.Start();
                Console.Error.WriteLine("Press any key to exit...");
                // if we weren't looping
                // we wouldn't need to
                // hook this:
                stm.SendComplete += delegate(object s, EventArgs e)
                {
                    // loop
                    stm.Send(seq.Events);
                };
                // kick things off
                stm.Send(seq.Events);
                // wait for exit
                Console.ReadKey();
            }
        }
예제 #21
0
        public Stream Flip(Stream midiFile, int octaveChangeOption)
        {
            //Load midi file
            MidiSequence midi = MidiSequence.Open(midiFile);

            //The anchor note to flip everything else around
            float anchorNote = midi.Tracks
                               .Where(t => t.Events.OfType <NoteVoiceMidiEvent>().Any() && t.Events.OfType <NoteVoiceMidiEvent>().Any(n => n.Channel != 9 && n.Channel != 10))
                               .Select(t => t.Events.OfType <NoteVoiceMidiEvent>().First())
                               .OrderBy(e => e.DeltaTime).GroupBy(e => e.DeltaTime).First() //Find the first note
                               .Min(e => e.Note);                                           //Order by note number if there are notes playing at the same time

            int highestNote = midi.Tracks
                              .Where(t => t.Events.OfType <NoteVoiceMidiEvent>().Any(n => n.Channel != 9 && n.Channel != 10))
                              .SelectMany(t => t.Events.OfType <NoteVoiceMidiEvent>())
                              .Max(e => e.Note);
            int lowestNote = midi.Tracks
                             .Where(t => t.Events.OfType <NoteVoiceMidiEvent>().Any(n => n.Channel != 9 && n.Channel != 10))
                             .SelectMany(t => t.Events.OfType <NoteVoiceMidiEvent>())
                             .Min(e => e.Note);

            int octaveChange = 0; //Global octave change required for this sequence

            octaveChangeOption *= Constants.Octave;

            bool flipFromMiddle = false; //If octave changes aren't possible, sequence needs to be flipped around the middle

            //Check if flipping won't make the notes go out of range (0-127) TODO: Test all cases
            if (anchorNote - lowestNote > highestNote - anchorNote)
            {
                //Flipping might make notes go past 127, if so, try to decrease octave
                float outOfRange = anchorNote + (anchorNote - lowestNote);

                if (outOfRange > Constants.MaxMidiNote)
                {
                    while (outOfRange + octaveChange > Constants.MaxMidiNote)
                    {
                        octaveChange -= Constants.Octave;
                    }

                    if (lowestNote + octaveChange < Constants.MinMidiNote)
                    {
                        //Out of range on the other side now, flip everything around the middle note instead and don't change octave
                        flipFromMiddle = true;
                        octaveChange   = 0;
                    }
                }
            }
            else
            {
                //Flipping might make notes go below 0, if so, try to increase octave
                float outOfRange = anchorNote - (highestNote - anchorNote);

                if (outOfRange < Constants.MinMidiNote)
                {
                    while (outOfRange + octaveChange < Constants.MinMidiNote)
                    {
                        octaveChange += Constants.Octave;
                    }

                    if (highestNote + octaveChange > Constants.MaxMidiNote)
                    {
                        //Out of range on the other side now, flip everything around the middle note instead and don't change octave
                        flipFromMiddle = true;
                        octaveChange   = 0;
                    }
                }
            }

            if (flipFromMiddle) //Changing octaves is not possible, flip everything around the middle
            {
                anchorNote = (float)(highestNote - lowestNote) / 2;
            }

            //Flip all notes
            foreach (MidiTrack track in midi.Tracks)
            {
                IEnumerable <NoteVoiceMidiEvent> noteEvents = track.OfType <NoteVoiceMidiEvent>().Where(n => n.Channel != 9 && n.Channel != 10);

                if (!noteEvents.Any())
                {
                    continue;                    //Nothing to flip
                }
                foreach (NoteVoiceMidiEvent onNoteEvent in noteEvents)
                {
                    onNoteEvent.Note = (byte)(anchorNote + anchorNote - onNoteEvent.Note + octaveChange + octaveChangeOption);
                }
            }

            //Create flipped MIDI-file
            Stream flippedMidiStream = new MemoryStream();

            midi.Save(flippedMidiStream);
            flippedMidiStream.Position = 0;

            return(flippedMidiStream);
        }
예제 #22
0
        public EasyLedShowLauncher(string filePath = null)
        {
            //filePath = @"C:\Users\2425\Desktop\newyear.els";
            workingSettings = new SavedSettings();
            if (filePath != null)
            {
                workingSettings = loadSettings(filePath);
            }

            InitializeComponent();

            InitializeComports(workingSettings);

            InitializeMidiDevices(workingSettings);

            InitializeLaunchDelay(workingSettings);

            InitializeJINXFile(workingSettings);

            InitializeJINXProgram(workingSettings);

            dmxDataPort = new SerialPort();

            dmxSubEffects = new int[NR_MAIN_PROGRAMS];
            for (int i = 0; i < dmxSubEffects.Length; i++)
            {
                if (i == 0)
                {
                    dmxSubEffects[i] = 4;
                }
                else if (i == 1)
                {
                    dmxSubEffects[i] = 4;
                }
                else
                {
                    dmxSubEffects[i] = 0;
                }
            }


            thresEnabled      = new bool[NR_SLIDERS];
            thresActive       = new bool[NR_SLIDERS];
            thresFreeValue    = new byte[NR_SLIDERS];
            thresOKTime       = new long[NR_SLIDERS];
            thresActivateTime = new int[NR_SLIDERS];
            thresPreValue     = new byte[NR_SLIDERS];

            thresEnabled[0] = false;
            thresEnabled[1] = false;
            thresEnabled[2] = true;
            thresEnabled[3] = false;
            thresEnabled[4] = false;
            thresEnabled[5] = false;
            thresEnabled[6] = true;
            thresEnabled[7] = false;
            for (int i = 0; i < NR_SLIDERS; i++)
            {
                if (thresEnabled[i])
                {
                    thresFreeValue[i]    = 12;
                    thresActivateTime[i] = 2000;
                    thresActive[i]       = false;
                }
            }

            timer          = new System.Timers.Timer(1000);
            timer.Elapsed += OnTimedEvent;


            this.FormClosing += EasyLedShowLauncher_FormClosing;

            //Auto Launch
            if (filePath != null)
            {
                StartLaunch();
            }

            midiSequence = new MidiSequence(0, 100);
        }
예제 #23
0
        private ulong t0Tick; // tick time used as reference

        #endregion

        #region Constructor

        public MidiSequencer(MidiSequence sequence)
            : this(GetEventArrayFromMidiSequence(sequence), sequence.PPQN)
        {
        }
예제 #24
0
        public MidiInterpretation(Stream midiStream, INoteSegmentProvider noteSegmentProvider)
        {
            MidiFile = MidiSequence.Open(midiStream);

            TempoCollection = new TempoCollection(MidiFile.TicksPerBeatOrFrame);

            NoteSegments = new List <NoteSegment>();

            // Calculate the absolute times for all events in each track
            // Also pair note on events with note off events
            for (int track = 0; track < MidiFile.Tracks.Count; track++)
            {
                // Key is a tuple of Channel and Note
                var onEvents = new Dictionary <(byte Channel, int Note), Queue <MidiEventWithTime <OnNoteVoiceMidiEvent> > >();

                // Time in ticks
                long time = 0;
                foreach (var midiEvent in MidiFile.Tracks[track].Events)
                {
                    if (midiEvent.DeltaTime > 0)
                    {
                        time += midiEvent.DeltaTime;
                    }

                    if (midiEvent is TempoMetaMidiEvent tempoEvent)
                    {
                        TempoCollection.AddTempoEvent(time, tempoEvent);
                    }
                    else if (midiEvent is OnNoteVoiceMidiEvent onNote)
                    {
                        var onNoteIdentifier = (onNote.Channel, onNote.Note);

                        if (!onEvents.ContainsKey(onNoteIdentifier))
                        {
                            onEvents[onNoteIdentifier] = new Queue <MidiEventWithTime <OnNoteVoiceMidiEvent> >();
                        }

                        // If the Velocity is 0, we are turning off a note using another OnNote (see https://stackoverflow.com/a/43322203/1984712)
                        // Basically, if a NoteOn event is received with a velocity of 0, we effectively have a NoteOff event.
                        if (onNote.Velocity == 0)
                        {
                            if (onEvents.TryGetValue(onNoteIdentifier, out var midiEventQueue))
                            {
                                NoteSegments.Add(noteSegmentProvider.CreateNoteSegment(
                                                     TempoCollection,
                                                     track,
                                                     midiEventQueue.Dequeue(), // Get the first matching On Event that matches this identifier
                                                     new MidiEventWithTime <OffNoteVoiceMidiEvent>(time, CreateOffNoteFromOnNote(onNote))
                                                     ));
                            }
                            else
                            {
                                System.Diagnostics.Debug.WriteLine(string.Format("OnNote event with Velocity = 0 at [ Channel: {0}; Note: {1} ] is missing a corresponding OnNote event with Velocity > 0.", onNoteIdentifier.Channel, onNoteIdentifier.Note));
                            }
                        }
                        // Otherwise, queue the note so that an OffNote can match to it
                        else
                        {
                            onEvents[onNoteIdentifier].Enqueue(new MidiEventWithTime <OnNoteVoiceMidiEvent>(time, onNote));
                        }
                    }
                    else if (midiEvent is OffNoteVoiceMidiEvent offNote)
                    {
                        var offNoteIdentifer = (offNote.Channel, offNote.Note);

                        if (onEvents.TryGetValue(offNoteIdentifer, out var midiEventQueue))
                        {
                            NoteSegments.Add(noteSegmentProvider.CreateNoteSegment(
                                                 TempoCollection,
                                                 track,
                                                 midiEventQueue.Dequeue(), // Get the first matching On Event
                                                 new MidiEventWithTime <OffNoteVoiceMidiEvent>(time, offNote))
                                             );
                        }
                        else
                        {
                            System.Diagnostics.Debug.WriteLine(string.Format("OffNote event at [ Channel: {0}; Note: {1} ] is missing a corresponding OnNote event.", offNoteIdentifer.Channel, offNoteIdentifer.Note));
                        }
                    }
                }

                if (onEvents.Any(e => e.Value.Count > 0))
                {
                    System.Diagnostics.Debug.WriteLine("One or more OnNote events weren't paired with an OffNote event.");
                }
            }

            TotalDurationSamples = NoteSegments.Max(segment => segment.StartSample + segment.DurationSamples);
        }
예제 #25
0
파일: Main.cs 프로젝트: dawsonf/MidiSlicer
        MidiFile _CreateMidiFile()
        {
            var file = new MidiFile();
            // we'll need a track 0 for our tempo map
            var track0 = new MidiSequence();

            // set the tempo at the first position
            track0.Events.Add(new MidiEvent(0, new MidiMessageMetaTempo((double)TempoUpDown.Value)));
            // compute the length of our loop
            var len = ((int)BarsUpDown.Value) * 4 * file.TimeBase;

            // add an end of track marker just so all
            // of our tracks will be the loop length
            track0.Events.Add(new MidiEvent(len, new MidiMessageMetaEndOfTrack()));

            // here we need a track end with an
            // absolute position for the MIDI end
            // of track meta message. We'll use this
            // later to set the length of the track
            var trackEnd = new MidiSequence();

            trackEnd.Events.Add(new MidiEvent(len, new MidiMessageMetaEndOfTrack()));

            // add track 0 (our tempo map)
            file.Tracks.Add(track0);

            // create track 1 (our drum track)
            var track1 = new MidiSequence();

            // we're going to create a new sequence for
            // each one of the drum sequencer tracks in
            // the UI
            var trks = new List <MidiSequence>(BeatsPanel.Controls.Count);

            foreach (var ctl in BeatsPanel.Controls)
            {
                var beat = ctl as BeatControl;
                // get the note for the drum
                var note = beat.NoteId;
                // it's easier to use a note map
                // to build the drum sequence
                var noteMap = new List <MidiNote>();
                for (int ic = beat.Steps.Count, i = 0; i < ic; ++i)
                {
                    // if the step is pressed create
                    // a note for it
                    if (beat.Steps[i])
                    {
                        noteMap.Add(new MidiNote(i * (file.TimeBase / 4), 9, note, 127, file.TimeBase / 4 - 1));
                    }
                }
                // convert the note map to a sequence
                // and add it to our working tracks
                trks.Add(MidiSequence.FromNoteMap(noteMap));
            }
            // now we merge the sequences into one
            var t = MidiSequence.Merge(trks);

            // we merge everything down to track 1
            track1 = MidiSequence.Merge(track1, t, trackEnd);
            // .. and add it to the file
            file.Tracks.Add(track1);
            return(file);
        }
예제 #26
0
파일: Main.cs 프로젝트: dawsonf/MidiSlicer
        private void PlayButton_Click(object sender, EventArgs e)
        {
            // we use 100 events, which should be safe and allow
            // for some measure of SYSEX messages in the stream
            // without bypassing the 64kb limit
            const int MAX_EVENT_COUNT = 100;
            const int RATE_TICKS      = 500;

            if ("Stop" == PlayButton.Text)
            {
                if (null != _play)              // sanity check
                {
                    _play.Close();
                }
                PlayButton.Text         = "Play";
                PatternComboBox.Enabled = true;
                BarsUpDown.Enabled      = true;
                OutputComboBox.Enabled  = true;
                return;
            }
            PatternComboBox.Enabled = false;
            BarsUpDown.Enabled      = false;
            OutputComboBox.Enabled  = false;
            PlayButton.Text         = "Stop";

            _play = (OutputComboBox.SelectedItem as MidiOutputDevice).Stream;
            var mf  = _CreateMidiFile();
            var stm = _play;

            // our current cursor pos
            int pos = 0;
            // for tracking deltas
            var ofs = 0;
            // merge our file for playback
            var seq = MidiSequence.Merge(mf.Tracks);
            // the number of events in the seq
            int len = seq.Events.Count;
            // stores the next set of events
            var eventList = new List <MidiEvent>(MAX_EVENT_COUNT);

            // open the stream
            stm.Open();
            // start it
            stm.Start();

            // first set the timebase
            stm.TimeBase = mf.TimeBase;

            // set up our send complete handler
            stm.SendComplete += delegate(object s, EventArgs ea)
            {
                try
                {
                    BeginInvoke(new Action(delegate()
                    {
                        // clear the list
                        eventList.Clear();
                        mf  = _CreateMidiFile();
                        seq = MidiSequence.Merge(mf.Tracks);
                        ofs = 0;
                        len = seq.Events.Count;
                        // iterate through the next events
                        var next = pos + MAX_EVENT_COUNT;
                        for (; pos < next && ofs <= RATE_TICKS; ++pos)

                        {
                            // if it's past the end, loop it
                            if (len <= pos)
                            {
                                pos = 0;
                                break;
                            }
                            var ev = seq.Events[pos];
                            ofs   += ev.Position;
                            if (ev.Position < RATE_TICKS && RATE_TICKS < ofs)
                            {
                                break;
                            }
                            // otherwise add the next event
                            eventList.Add(ev);
                        }
                        // send the list of events
                        if (MidiStreamState.Closed != stm.State)
                        {
                            stm.SendDirect(eventList);
                        }
                    }));
                }
                catch
                {
                }
            };
            // add the first events
            for (pos = 0; pos < MAX_EVENT_COUNT && ofs <= RATE_TICKS; ++pos)
            {
                // if it's past the end, loop it
                if (len <= pos)
                {
                    pos = 0;
                    break;
                }
                var ev = seq.Events[pos];
                ofs += ev.Position;
                if (ev.Position < RATE_TICKS && RATE_TICKS < ofs)
                {
                    break;
                }
                // otherwise add the next event
                eventList.Add(ev);
            }
            // send the list of events
            stm.SendDirect(eventList);
        }
예제 #27
0
        public static void doToBMS(MidiSequence wtf, string filename)
        {
            var largest_delta = 0;

            JaiTrackFinal = new MemoryStream();                // Buffer for JaiSeq track
            var JaiWriter = new BeBinaryWriter(JaiTrackFinal); // Writer into JaiSeq buffer

            DeltaEnds        = new int[wtf.Tracks.Count];      // The deltas that will be smashed onto the end of every track.
            TotalTrackDeltas = new int[wtf.Tracks.Count];      // The total delta sizes for each track
            TrackAddresses   = new int[wtf.Tracks.Count];      // The addresses that each track is at.
            TrackLoops       = new int[wtf.Tracks.Count];


            var rootTrack_OpenTrackPos = JaiWriter.BaseStream.Position; // Store the position where our Open track commands are.

            for (int i = 0; i < wtf.Tracks.Count; i++)
            {
                JaiWriter.Write((byte)JaiSeqEvent.OPEN_TRACK); // Write dummy open track commands
                JaiWriter.Write((byte)i);                      // Index
                writeInt24BE(JaiWriter, 0);                    // 0-size pointer.
            }

            JaiWriter.Write((byte)JaiSeqEvent.TIME_BASE);    // Tell JAI to set the timebase
            JaiWriter.Write((short)wtf.TicksPerBeatOrFrame); // Write timebase value
            JaiWriter.Write((byte)JaiSeqEvent.TEMPO);        // Tell JAI to write the tempo
            JaiWriter.Write((ushort)Root.Tempo);             // Write the tempo value.

            writePrint(JaiWriter, @"Generated by Xayrga's JAIMaker.\n");
            writePrint(JaiWriter, @"JAIMakerInitTrack: ");

            JaiWriter.Write((byte)JaiSeqEvent.WAIT_8); // Wait
            JaiWriter.Write((byte)2);                  // for 0xFFFA ticks
            writePrint(JaiWriter, @" || DONE. \n");



            for (int tridx = 0; tridx < wtf.Tracks.Count; tridx++)
            {
                var total_trk_delta = 0;                                   // Total delta for current track
                var CTrk            = wtf.Tracks[tridx];                   // Current track object
                for (int evntid = 0; evntid < CTrk.Events.Count; evntid++) // Iterate through events
                {
                    var CEvent = CTrk.Events[evntid];                      // Current event object
                    total_trk_delta += (int)CEvent.DeltaTime;              // Add the event to the total delta for our track
                    if (CTrk.Events[evntid] is MidiSharp.Events.Meta.Text.CuePointTextMetaMidiEvent)
                    {
                        var mevent = (MidiSharp.Events.Meta.Text.CuePointTextMetaMidiEvent)CTrk.Events[evntid];

                        if (mevent.Text == "JLOOP")
                        {
                            at_least_one_loop = true; // check for loop -- hack
                        }
                    }
                }
                TotalTrackDeltas[tridx] = total_trk_delta; // Once we've iterated through all events we store the total track delta.
                if (total_trk_delta > largest_delta)       // We want to know what our highest delta is so we can make all the tracks end at the same time.
                {
                    largest_delta = total_trk_delta;       // So we should store it if it's greater than the last
                }
            }
            for (int trk = 0; trk < wtf.Tracks.Count; trk++)
            {
                DeltaEnds[trk] = largest_delta - TotalTrackDeltas[trk]; // Now we know when all the tracks will end at the same time, so we want to sandwhich that onto the end of the track.
            }

            var rootTrack_JumpPos = JaiWriter.BaseStream.Position; // Store the position where we want to jump back to

            writeDelta(JaiWriter, largest_delta);

            if (at_least_one_loop)
            {
                JaiWriter.Write((byte)JaiSeqEvent.JUMP_COND);    // Jump to position if
                JaiWriter.Write((byte)0);                        // (always)
                writeInt24BE(JaiWriter, (int)rootTrack_JumpPos); // int24 position.
            }

            JaiWriter.Write((byte)JaiSeqEvent.FIN); // Write the finisher for the track, not because it's required but just becase it's standard.


            for (int TrackID = 0; TrackID < wtf.Tracks.Count; TrackID++)
            {
                var MidTrack = wtf.Tracks[TrackID];
                TrackAddresses[TrackID] = (int)JaiWriter.BaseStream.Position; // Store track position

                JaiWriter.Write((byte)0xA4);
                JaiWriter.Write((byte)0x20);
                JaiWriter.Write((byte)Root.instrumentBanks[TrackID]);

                JaiWriter.Write((byte)0xA4);
                JaiWriter.Write((byte)0x21);
                JaiWriter.Write((byte)Root.programs[TrackID]);

                writePrint(JaiWriter, @", T" + TrackID);

                Stack <byte> voiceStack  = new Stack <byte>(8); // JAISeq has 8 voices per track.
                Queue <byte> notehistory = new Queue <byte>(8);
                for (byte v = 7; v > 0; v--)                    // Push all of them to be ready.
                {
                    Console.WriteLine("PushVoice {0}", v);
                    voiceStack.Push(v);           // Push to stack.
                }
                byte[] voiceMap = new byte[1024]; // Keeps track of what MIDI notes are currently playing on what voices.

                for (int ev = 0; ev < MidTrack.Events.Count; ev++)
                {
                    var cevent = MidTrack.Events[ev];

                    if (cevent.DeltaTime > 0) // Does the event have any delta?
                    {
                        writeDelta(JaiWriter, (int)cevent.DeltaTime);
                    }
                    if (cevent is MidiSharp.Events.Meta.Text.CuePointTextMetaMidiEvent)
                    {
                        var mevent = (MidiSharp.Events.Meta.Text.CuePointTextMetaMidiEvent)cevent;
                        Console.WriteLine("YEET {0} - {1} ", TrackID, mevent.Text);
                        if (mevent.Text == "JLOOP")
                        {
                            TrackLoops[TrackID] = (int)JaiWriter.BaseStream.Position;
                            at_least_one_loop   = true;
                        }
                    }
                    else if (cevent is MidiSharp.Events.Voice.Note.OnNoteVoiceMidiEvent)
                    {
                        var mevent = (MidiSharp.Events.Voice.Note.OnNoteVoiceMidiEvent)cevent;
                        if (voiceMap[mevent.Note] != 0)            // This voice is already in use and hasnt been told to stop?
                        {
                            var stopVoice = voiceMap[mevent.Note]; // grab the voice id
                            {
                                voiceStack.Push(stopVoice);
                                JaiWriter.Write((byte)(0x80 + stopVoice));
                            }
                        }
                        if (voiceStack.Count < 1)                     // if theres no voice available
                        {
                            for (int i = 0; i < voiceMap.Length; i++) // Iterate through voices table
                            {
                                if (voiceMap[i] > 0)                  // if a voice is greater than 0 (used)
                                {
                                    voiceStack.Push(voiceMap[i]);     // Dealloc it (push to voice table)
                                    voiceMap[i] = 0;                  // Set it to 0, it has no pitch,  it's been deallocd
                                }
                            }
                        }
                        if (voiceStack.Count > 0)
                        {
                            JaiWriter.Write(mevent.Note);     // JAI Note on events are literally just midi notes.
                            var useVoice = voiceStack.Pop();  // Grab next available voice.
                            voiceMap[mevent.Note] = useVoice; // Map it to the pitch
                            JaiWriter.Write(useVoice);        // write which JAIVoice it will be using
                            JaiWriter.Write(mevent.Velocity); // Write its velocity.
                        }
                        else
                        {
                            Console.WriteLine("Too many voices {0}", TrackID);
                        }
                    }
                    else if (cevent is MidiSharp.Events.Voice.Note.OffNoteVoiceMidiEvent)
                    {
                        var mevent    = (MidiSharp.Events.Voice.Note.OffNoteVoiceMidiEvent)cevent;
                        var stopVoice = voiceMap[mevent.Note];
                        if (stopVoice == 0)
                        {
                            Console.WriteLine("VOICE LEAK {0}", TrackID);
                        }
                        else
                        {
                            voiceMap[mevent.Note] = 0;
                            voiceStack.Push(stopVoice);
                            //Console.WriteLine("Stop voice {0}",stopVoice);
                            JaiWriter.Write((byte)(0x80 + stopVoice));
                        }
                    }
                }
                // Done with parsting track events.
                if (DeltaEnds[TrackID] > 0)
                {
                    writeDelta(JaiWriter, DeltaEnds[TrackID]);   // Write finishing delta to make sure all tracks end at the same point.
                }
                for (int i = 0; i < voiceMap.Length; i++)
                {
                    if (voiceMap[i] > 0)
                    {
                        JaiWriter.Write((byte)(0x80 + voiceMap[i])); // stop all notes before song end.
                        Console.WriteLine("=== STOP VOICE END SONG {0}", voiceMap[i]);
                    }
                }
                if (TrackLoops[TrackID] > 0)
                {
                    JaiWriter.Write((byte)JaiSeqEvent.JUMP_COND); // Jump to position if
                    JaiWriter.Write((byte)0);                     // (always)
                    writeInt24BE(JaiWriter, TrackLoops[TrackID]); // int24 position.
                }
                JaiWriter.Write((byte)JaiSeqEvent.FIN);
                while (JaiWriter.BaseStream.Position % 32 > 0)
                {
                    JaiWriter.Write((byte)0);
                }
            }
            // Done with parsing tracks.
            JaiWriter.BaseStream.Position = rootTrack_OpenTrackPos; // We have to update the track opening points that we had before.
            for (int i = 0; i < wtf.Tracks.Count; i++)
            {
                JaiWriter.Write((byte)JaiSeqEvent.OPEN_TRACK); // Write open track command
                JaiWriter.Write((byte)i);                      // Index
                writeInt24BE(JaiWriter, TrackAddresses[i]);
            }

            JaiWriter.Flush();
            File.WriteAllBytes(filename, ReadToEnd(JaiTrackFinal));
        }
예제 #28
0
        private void PreviewButton_Click(object sender, EventArgs e)
        {
            if ("Stop" == PreviewButton.Text)
            {
                if (null != _play)
                {
                    _play.Close();
                }
                MidiFileBox.Enabled    = true;
                BrowseButton.Enabled   = true;
                OutputComboBox.Enabled = true;
                PreviewButton.Text     = "Preview";
                return;
            }

            if (null != _play)
            {
                _play.Close();
            }
            MidiFileBox.Enabled    = false;
            BrowseButton.Enabled   = false;
            OutputComboBox.Enabled = false;
            PreviewButton.Text     = "Stop";
            if (_dirty)
            {
                _processedFile = _ProcessFile();
            }
            var mf = _processedFile;

            _play = (OutputComboBox.SelectedItem as MidiOutputDevice).Stream;
            var stm = _play;
            // we use 100 events, which should be safe and allow
            // for some measure of SYSEX messages in the stream
            // without bypassing the 64kb limit
            const int MAX_EVENT_COUNT = 100;
            const int RATE_TICKS      = 500;
            // our current cursor pos
            var pos = 0;
            // for tracking deltas
            var ofs = 0;
            // for tracking the song position
            var songPos = 0;
            // merge our file for playback
            var seq    = MidiSequence.Merge(mf.Tracks);
            var events = seq.Events;
            // the number of events in the seq
            var len = events.Count;
            // stores the next set of events
            var eventList = new List <MidiEvent>(MAX_EVENT_COUNT);

            // open the stream
            stm.Open();
            // start it
            stm.Start();

            // first set the timebase
            stm.TimeBase = mf.TimeBase;
            // set up our send complete handler
            stm.SendComplete += delegate(object s, EventArgs ea)
            {
                try
                {
                    BeginInvoke(new Action(delegate()
                    {
                        // clear the list
                        eventList.Clear();
                        mf = _processedFile;
                        if (_dirty)
                        {
                            if (_reseekDirty)
                            {
                                var time       = _processedFile.Tracks[0].GetContext(songPos, _processedFile.TimeBase).Time;
                                _processedFile = _ProcessFile();
                                songPos        = _processedFile.Tracks[0].GetPositionAtTime(time, _processedFile.TimeBase);
                                mf             = _processedFile;
                                seq            = MidiSequence.Merge(mf.Tracks);
                                events         = new List <MidiEvent>(seq.GetNextEventsAtPosition(songPos, true));
                                len            = events.Count;
                                pos            = 0;
                            }
                            else
                            {
                                _processedFile = _ProcessFile();
                                mf             = _processedFile;
                                seq            = MidiSequence.Merge(mf.Tracks);
                                events         = seq.Events;
                            }
                            Visualizer.Sequence = seq;
                            Visualizer.Width    = Math.Max(VisualizerPanel.Width, Visualizer.Sequence.Length / 4);
                        }


                        ofs = 0;
                        len = events.Count;
                        // iterate through the next events
                        var next = pos + MAX_EVENT_COUNT;
                        for (; pos < next && ofs <= RATE_TICKS; ++pos)

                        {
                            // if it's past the end, loop it
                            if (len <= pos)
                            {
                                pos     = 0;
                                songPos = 0;
                                events  = seq.Events;
                                break;
                            }
                            var ev   = events[pos];
                            ofs     += ev.Position;
                            songPos += pos;
                            if (ev.Position < RATE_TICKS && RATE_TICKS < ofs)
                            {
                                break;
                            }
                            // otherwise add the next event
                            eventList.Add(ev);
                        }
                        // send the list of events
                        if (MidiStreamState.Closed != stm.State && 0 != eventList.Count)
                        {
                            stm.SendDirect(eventList);
                        }
                    }));
                }
                catch { }
            };
            // add the first events
            for (pos = 0; pos < MAX_EVENT_COUNT && ofs <= RATE_TICKS; ++pos)
            {
                // if it's past the end, loop it
                if (len <= pos)
                {
                    pos     = 0;
                    songPos = 0;
                    events  = seq.Events;
                    break;
                }
                var ev = events[pos];
                ofs += ev.Position;
                if (ev.Position < RATE_TICKS && RATE_TICKS < ofs)
                {
                    break;
                }
                // otherwise add the next event
                eventList.Add(ev);
            }
            // send the list of events
            if (0 != eventList.Count)
            {
                stm.SendDirect(eventList);
            }
        }
예제 #29
0
        /// <summary>Create the demo sequence.</summary>
        /// <returns>The created midi sequence.</returns>
        public MidiSequence CreateSequence()
        {
            MidiSequence sequence = new MidiSequence(0, 120);
            MidiTrack    track    = sequence.AddTrack();

            track.Events.Add(new TimeSignature(0, 4, 2, 24, 8));
            track.Events.Add(new KeySignature(0, Key.NoFlatsOrSharps, Tonality.Major));
            track.Events.Add(new Tempo(0, 416667));
            track.Events.Add(new ProgramChange(0, 0, GeneralMidiInstruments.AcousticGrand));
            track.Events.Add(new Controller(0, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new Controller(0, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new NoteOn(11, 0, "E6", 60));
            track.Events.Add(new Controller(56, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(24, 0, "D#6", 66));
            track.Events.Add(new Controller(0, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new NoteOn(2, 0, "E6", 0));
            track.Events.Add(new NoteOn(75, 0, "E6", 60));
            track.Events.Add(new NoteOn(16, 0, "D#6", 0));
            track.Events.Add(new NoteOn(72, 0, "D#6", 62));
            track.Events.Add(new NoteOn(8, 0, "E6", 0));
            track.Events.Add(new NoteOn(77, 0, "E6", 72));
            track.Events.Add(new NoteOn(16, 0, "D#6", 0));
            track.Events.Add(new NoteOn(64, 0, "B5", 71));
            track.Events.Add(new NoteOn(12, 0, "E6", 0));
            track.Events.Add(new NoteOn(64, 0, "D6", 85));
            track.Events.Add(new NoteOn(19, 0, "B5", 0));
            track.Events.Add(new NoteOn(60, 0, "C6", 80));
            track.Events.Add(new NoteOn(24, 0, "D6", 0));
            track.Events.Add(new NoteOn(51, 0, "A3", 66));
            track.Events.Add(new NoteOn(5, 0, "A5", 73));
            track.Events.Add(new NoteOn(13, 0, "C6", 0));
            track.Events.Add(new Controller(24, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(35, 0, "E4", 70));
            track.Events.Add(new NoteOn(51, 0, "A5", 0));
            track.Events.Add(new NoteOn(23, 0, "A4", 75));
            track.Events.Add(new NoteOn(72, 0, "A4", 0));
            track.Events.Add(new NoteOn(0, 0, "C5", 78));
            track.Events.Add(new NoteOn(73, 0, "E5", 86));
            track.Events.Add(new NoteOn(13, 0, "A3", 0));
            track.Events.Add(new NoteOn(42, 0, "E4", 0));
            track.Events.Add(new NoteOn(17, 0, "A5", 87));
            track.Events.Add(new NoteOn(19, 0, "C5", 0));
            track.Events.Add(new NoteOn(14, 0, "E5", 0));
            track.Events.Add(new NoteOn(40, 0, "E3", 72));
            track.Events.Add(new NoteOn(1, 0, "B5", 84));
            track.Events.Add(new Controller(4, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new NoteOn(10, 0, "A5", 0));
            track.Events.Add(new Controller(36, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(19, 0, "E3", 0));
            track.Events.Add(new NoteOn(5, 0, "E4", 70));
            track.Events.Add(new NoteOn(47, 0, "E4", 0));
            track.Events.Add(new NoteOn(0, 0, "B5", 0));
            track.Events.Add(new NoteOn(9, 0, "G#4", 85));
            track.Events.Add(new NoteOn(62, 0, "E5", 82));
            track.Events.Add(new NoteOn(66, 0, "G#4", 0));
            track.Events.Add(new NoteOn(5, 0, "G#5", 85));
            track.Events.Add(new NoteOn(72, 0, "B5", 93));
            track.Events.Add(new NoteOn(3, 0, "E5", 0));
            track.Events.Add(new NoteOn(29, 0, "G#5", 0));
            track.Events.Add(new NoteOn(38, 0, "C6", 78));
            track.Events.Add(new NoteOn(4, 0, "A3", 66));
            track.Events.Add(new Controller(0, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new NoteOn(3, 0, "B5", 0));
            track.Events.Add(new Controller(38, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(27, 0, "E4", 72));
            track.Events.Add(new NoteOn(76, 0, "A4", 70));
            track.Events.Add(new NoteOn(68, 0, "E5", 75));
            track.Events.Add(new NoteOn(5, 0, "C6", 0));
            track.Events.Add(new NoteOn(46, 0, "A4", 0));
            track.Events.Add(new NoteOn(20, 0, "A3", 0));
            track.Events.Add(new NoteOn(5, 0, "E4", 0));
            track.Events.Add(new NoteOn(3, 0, "E5", 0));
            track.Events.Add(new NoteOn(1, 0, "E6", 74));
            track.Events.Add(new NoteOn(70, 0, "E6", 0));
            track.Events.Add(new NoteOn(2, 0, "D#6", 82));
            track.Events.Add(new NoteOn(76, 0, "E6", 90));
            track.Events.Add(new NoteOn(6, 0, "D#6", 0));
            track.Events.Add(new Controller(4, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new NoteOn(59, 0, "D#6", 86));
            track.Events.Add(new NoteOn(14, 0, "E6", 0));
            track.Events.Add(new NoteOn(57, 0, "E6", 103));
            track.Events.Add(new NoteOn(20, 0, "D#6", 0));
            track.Events.Add(new NoteOn(56, 0, "B5", 90));
            track.Events.Add(new NoteOn(11, 0, "E6", 0));
            track.Events.Add(new NoteOn(66, 0, "D6", 86));
            track.Events.Add(new NoteOn(11, 0, "B5", 0));
            track.Events.Add(new NoteOn(62, 0, "C6", 85));
            track.Events.Add(new NoteOn(8, 0, "D6", 0));
            track.Events.Add(new NoteOn(72, 0, "A5", 77));
            track.Events.Add(new NoteOn(3, 0, "C6", 0));
            track.Events.Add(new NoteOn(1, 0, "A3", 55));
            track.Events.Add(new Controller(16, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(52, 0, "E4", 60));
            track.Events.Add(new NoteOn(28, 0, "A5", 0));
            track.Events.Add(new NoteOn(50, 0, "A4", 77));
            track.Events.Add(new NoteOn(63, 0, "C5", 90));
            track.Events.Add(new NoteOn(3, 0, "A4", 0));
            track.Events.Add(new NoteOn(57, 0, "A3", 0));
            track.Events.Add(new NoteOn(14, 0, "E5", 86));
            track.Events.Add(new NoteOn(66, 0, "E4", 0));
            track.Events.Add(new NoteOn(3, 0, "A5", 82));
            track.Events.Add(new NoteOn(3, 0, "C5", 0));
            track.Events.Add(new NoteOn(12, 0, "E5", 0));
            track.Events.Add(new NoteOn(54, 0, "B5", 89));
            track.Events.Add(new NoteOn(3, 0, "E3", 79));
            track.Events.Add(new NoteOn(7, 0, "A5", 0));
            track.Events.Add(new Controller(2, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new Controller(45, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(14, 0, "E3", 0));
            track.Events.Add(new NoteOn(7, 0, "E4", 68));
            track.Events.Add(new NoteOn(66, 0, "E4", 0));
            track.Events.Add(new NoteOn(11, 0, "G#4", 84));
            track.Events.Add(new NoteOn(67, 0, "D5", 82));
            track.Events.Add(new NoteOn(11, 0, "B5", 0));
            track.Events.Add(new NoteOn(4, 0, "G#4", 0));
            track.Events.Add(new NoteOn(68, 0, "C6", 73));
            track.Events.Add(new NoteOn(37, 0, "D5", 0));
            track.Events.Add(new NoteOn(35, 0, "B5", 69));
            track.Events.Add(new NoteOn(69, 0, "B5", 0));
            track.Events.Add(new NoteOn(3, 0, "C6", 0));
            track.Events.Add(new NoteOn(6, 0, "A3", 60));
            track.Events.Add(new NoteOn(2, 0, "A5", 68));
            track.Events.Add(new Controller(0, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new Controller(49, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(29, 0, "E4", 66));
            track.Events.Add(new NoteOn(90, 0, "A4", 71));
            track.Events.Add(new NoteOn(23, 0, "A5", 0));
            track.Events.Add(new NoteOn(5, 0, "A3", 0));
            track.Events.Add(new NoteOn(16, 0, "E4", 0));
            track.Events.Add(new NoteOn(0, 0, "A4", 0));
            track.Events.Add(new NoteOn(130, 0, "E6", 80));
            track.Events.Add(new EndOfTrack(130));
            return(sequence);
        }
예제 #30
0
        void _UpdateMidiFile()
        {
            var exists = false;

            try
            {
                if (File.Exists(MidiFileBox.Text))
                {
                    exists = true;
                }
            }
            catch { }
            TrackList.Items.Clear();
            if (!exists)
            {
                TracksLabel.Text      = "";
                MidiFileBox.ForeColor = Color.Red;
                _file                           = null;
                TrackList.Enabled               = false;
                PreviewButton.Enabled           = false;
                UnitsCombo.Enabled              = false;
                StartCombo.Enabled              = false;
                OffsetUpDown.Enabled            = false;
                LengthUpDown.Enabled            = false;
                StretchUpDown.Enabled           = false;
                MergeTracksCheckBox.Enabled     = false;
                CopyTimingPatchCheckBox.Enabled = false;
                AdjustTempoCheckBox.Enabled     = false;
                ResampleUpDown.Enabled          = false;
                NormalizeCheckBox.Enabled       = false;
                LevelsUpDown.Enabled            = false;
                TransposeUpDown.Enabled         = false;
                WrapCheckBox.Enabled            = false;
                DrumsCheckBox.Enabled           = false;
                SaveAsButton.Enabled            = false;
                TempoUpDown.Enabled             = false;
                Visualizer.Sequence             = null;
                Visualizer.Size                 = VisualizerPanel.Size;
            }
            else
            {
                MidiFileBox.ForeColor = SystemColors.WindowText;
                using (Stream stm = File.OpenRead(MidiFileBox.Text))
                    _file = MidiFile.ReadFrom(stm);
                var i = 0;
                foreach (var trk in _file.Tracks)
                {
                    var s = trk.Name;
                    if (string.IsNullOrEmpty(s))
                    {
                        s = "Track #" + i.ToString();
                    }
                    TrackList.Items.Add(s, true);
                    ++i;
                }
                var sig = _file.TimeSignature;
                var key = _file.KeySignature;
                TracksLabel.Text                = string.Format(_tracksLabelFormat, sig.Numerator, sig.Denominator, key);
                TrackList.Enabled               = true;
                PreviewButton.Enabled           = true;
                UnitsCombo.Enabled              = true;
                StartCombo.Enabled              = true;
                OffsetUpDown.Enabled            = true;
                LengthUpDown.Enabled            = true;
                StretchUpDown.Enabled           = true;
                MergeTracksCheckBox.Enabled     = true;
                CopyTimingPatchCheckBox.Enabled = true;
                AdjustTempoCheckBox.Enabled     = true;
                ResampleUpDown.Enabled          = true;
                NormalizeCheckBox.Enabled       = true;
                LevelsUpDown.Enabled            = true;
                TransposeUpDown.Enabled         = true;
                WrapCheckBox.Enabled            = true;
                DrumsCheckBox.Enabled           = true;
                SaveAsButton.Enabled            = true;
                TempoUpDown.Enabled             = true;

                StretchUpDown.Value             = 1;
                UnitsCombo.SelectedIndex        = 0;
                StartCombo.SelectedIndex        = 0;
                ResampleUpDown.Value            = _file.TimeBase;
                UnitsCombo.SelectedIndex        = 0;
                LengthUpDown.Maximum            = _file.Length / (decimal)_file.TimeBase;
                OffsetUpDown.Maximum            = LengthUpDown.Maximum - 1;
                LengthUpDown.Value              = LengthUpDown.Maximum;
                OffsetUpDown.Value              = 0;
                AdjustTempoCheckBox.Checked     = false;
                MergeTracksCheckBox.Checked     = false;
                NormalizeCheckBox.Checked       = false;
                CopyTimingPatchCheckBox.Checked = true;
                LevelsUpDown.Value              = 1;
                TransposeUpDown.Value           = 0;
                WrapCheckBox.Checked            = false;
                DrumsCheckBox.Checked           = false;
                TempoUpDown.Value   = (decimal)_file.Tempo;
                _dirty              = true;
                _processedFile      = null;
                Visualizer.Sequence = MidiSequence.Merge(_file.Tracks);
                Visualizer.Width    = Math.Max(VisualizerPanel.Width, Visualizer.Sequence.Length / 4);
            }
        }
예제 #31
0
        void Output(OutputType type)
        {
            switch (type)
            {
            case OutputType.Midi:

                /*List<MidiEvent> midiEvents = new List<MidiEvent> ();
                 *
                 * double max = 0;
                 * for (int i = 0; i < notes.Count; i++) {
                 *      double d = notes[i].duration * 4;
                 *      double t1 = notes[i].time * 4;
                 *      double t2 = t1 + d;
                 *      max = t2 > max ? t2 : max;
                 *
                 *      NoteOnEvent note = new NoteOnEvent (Convert.ToInt64 (t1), 1, notes[i].noteNumber + 40, 127, Convert.ToInt32(d));
                 *      midiEvents.Add (note);
                 * }
                 * MidiEvent endMarker = new NoteEvent (Convert.ToInt64(max), 1, MidiCommandCode.StopSequence, 0, 0);
                 * midiEvents.Add (endMarker);
                 *
                 * MidiEventCollection collection = new MidiEventCollection (0, 1);
                 * collection.AddTrack (midiEvents);
                 *
                 * MidiFile.Export ("C:/Users/Jonas/OneDrive/GIP/Proef/Output/midi.mid", collection);*/

                MidiTrack track   = new MidiTrack();
                long      maxTime = 0;
                //string path = "C:/Users/Jonas/Desktop/result.txt";
                double previousTime = 0;
                for (int i = 0; i < notes.Count; i++)
                {
                    string path = "C:/Users/Jonas/Desktop/result.txt";
                    File.AppendAllText(path, string.Format("{0} at {1}\n", DecodeNote(notes[i].noteNumber + 44, NoteNotation.Short), notes[i].time));

                    double d  = 1;
                    double t1 = notes[i].time * 20 - previousTime;
                    double t2 = t1 + d;
                    if (t1 < 0)
                    {
                        continue;
                    }
                    previousTime = t2;



                    MidiEvent onEvent  = new OnNoteVoiceMidiEvent(Convert.ToInt64(t1), 1, (byte)(44 + notes[i].noteNumber), 63);
                    MidiEvent offEvent = new OffNoteVoiceMidiEvent(Convert.ToInt64(t2), 1, (byte)(44 + notes[i].noteNumber), 0);
                    long      t2long   = (long)t2;
                    maxTime = (t2long > maxTime) ? t2long : maxTime;

                    track.Events.Add(onEvent);
                    track.Events.Add(offEvent);
                }
                MidiEvent endMarker = new EndOfTrackMetaMidiEvent(maxTime);
                track.Events.Add(endMarker);
                MidiSequence sequence = new MidiSequence(Format.Zero, 1000);
                sequence.Tracks.Add(track);



                FileStream stream = new FileStream("C:/Users/Jonas/OneDrive/GIP/Proef/Output/midi.mid", FileMode.OpenOrCreate);
                sequence.Save(stream);
                stream.Close();
                break;

            case OutputType.Audio:
                double longest = 0;
                for (int i = 0; i < notes.Count; i++)
                {
                    double time = notes[i].time + notes[i].duration;
                    longest = Math.Max(time, longest);
                }
                double[] newSamples = new double[(int)Math.Ceiling(longest * rawAudio.sampleRate)];

                for (int i = 0; i < notes.Count; i++)
                {
                    int    startIndex = (int)Math.Floor(notes[i].time * rawAudio.sampleRate);
                    int    endIndex   = (int)Math.Floor((notes[i].time + notes[i].duration) * rawAudio.sampleRate);
                    double freq       = 110 * Math.Pow(1.059463094359295, notes[i].noteNumber);
                    double amp        = notes[i].amplitude;
                    for (int j = startIndex; j < endIndex; j++)
                    {
                        double time  = j * rawAudio.SampleLength + notes[i].time;
                        double value = Math.Sin(time * freq * 2 * Math.PI) * amp;
                        //double maxAmp = Math.Min (1, 5 * Math.Min (Math.Abs (time - notes[i].time), Math.Abs (time - (notes[i].time + notes[i].duration))));
                        newSamples[j] += value;
                    }
                }
                for (int i = 0; i < newSamples.Length; i++)
                {
                    newSamples[i] = Math.Max(Math.Min(1, newSamples[i]), -1);
                }
                int      avgSpread     = 35;
                double[] smoothSamples = new double[newSamples.Length - avgSpread];
                for (int i = 0; i < newSamples.Length - avgSpread; i++)
                {
                    double tot = 0;
                    for (int j = 0; j < avgSpread; j++)
                    {
                        tot += newSamples[i + j];
                    }
                    smoothSamples[i] = tot / avgSpread;
                }
                Song song = new Song(smoothSamples, rawAudio.channels, rawAudio.sampleRate);

                // GIPIO.SaveSong (song, GIPIO.outputPath + "test.wav");
                producedAudio = song;
                break;

            case OutputType.Wavelet:
                pixels = new uint[allAmps.Count * allAmps[0].Length];
                for (int x = 0; x < allAmps.Count; x++)
                {
                    for (int y = 0; y < allAmps[0].Length; y++)
                    {
                        double i = allAmps[x][y];
                        // i *= 2;
                        i = Math.Min(1, i);
                        // double r = -2 * (i - 1.0) * (2 * (i - 1.0)) + 1;
                        // double g = -2 * (i - 0.5) * (2 * (i - 0.5)) + 1;
                        // double b = -2 * (i - 0.0) * (2 * (i - 0.0)) + 1;

                        double r, g, b;
                        r = g = b = i;

                        uint red   = (uint)Math.Round(r * 255);
                        uint green = (uint)Math.Round(g * 255);
                        uint blue  = (uint)Math.Round(b * 255);

                        int index = (allAmps[0].Length - y - 1) * allAmps.Count + x;
                        pixels[index] = (uint)((255 << 24) + (red << 16) + (green << 8) + blue);
                    }
                }
                DrawWavelet();

                break;
            }
        }
예제 #32
0
        private void PlayButton_Click(object sender, EventArgs e)
        {
            if ("Stop" == PlayButton.Text)
            {
                PlayButton.Text = "Play";
                if (null != _outputStream)
                {
                    _outputStream.Close();
                }
                MidiOutComboBox.Enabled  = true;
                FileTextBox.Enabled      = true;
                FileBrowseButton.Enabled = true;
                Visualizer.ShowCursor    = false;
                return;
            }
            PlayButton.Text           = "Stop";
            Visualizer.CursorPosition = 0;
            Visualizer.ShowCursor     = true;
            MidiOutComboBox.Enabled   = false;
            FileTextBox.Enabled       = false;
            FileBrowseButton.Enabled  = false;
            var mf = MidiFile.ReadFrom(FileTextBox.Text);

            if (null != _outputStream)
            {
                // BUG: For some reason recycling the output stream
                // screws up playback on successive uses. I have had
                // no luck tracking down why so far. The following
                // causes the MidiStream class to be recreated
                // instead of recycled
                var stm = _outputStream = MidiDevice.Streams[_outputStream.Index];
                // we use 100 events, which should be safe and allow
                // for some measure of SYSEX messages in the stream
                // without bypassing the 64kb limit
                const int MAX_EVENT_COUNT = 100;
                // the lower this is, the more more CPU it takes.
                // the higher it is, the less accurate the cursor
                // position will be:
                const int RATE_TICKS = 10;
                // our current cursor pos
                var pos = 0;
                // for tracking deltas
                var ofs = 0;
                // for tracking the song position
                var songPos   = 0;
                var songTicks = 0;
                // merge our file for playback
                var seq    = MidiSequence.Merge(mf.Tracks);
                var events = seq.Events;
                // the number of events in the seq
                var len = events.Count;
                // stores the next set of events
                var eventList = new List <MidiEvent>(MAX_EVENT_COUNT);

                // open the stream
                stm.Open();
                if (MidiOutputDeviceVolumeSupport.None != stm.VolumeSupport)
                {
                    stm.Volume = new MidiVolume((byte)VolumeKnob.Value, (byte)VolumeKnob.Value);
                }

                // start it
                stm.Start();

                // first set the timebase
                stm.TimeBase = mf.TimeBase;
                // set up our send complete handler
                stm.SendComplete += delegate(object s, EventArgs ea)
                {
                    try
                    {
                        BeginInvoke(new Action(delegate()
                        {
                            // clear the list
                            eventList.Clear();

                            ofs = 0;
                            len = events.Count;
                            // iterate through the next events
                            var next = pos + MAX_EVENT_COUNT;
                            for (; pos < next && ofs <= RATE_TICKS; ++pos)

                            {
                                // if it's past the end, loop it
                                if (len <= pos)
                                {
                                    pos       = 0;
                                    songPos   = 0;
                                    songTicks = 0;
                                    events    = seq.Events;
                                    break;
                                }
                                var ev     = events[pos];
                                ofs       += ev.Position;
                                songTicks += ev.Position;
                                songPos   += pos;
                                if (ev.Position < RATE_TICKS && RATE_TICKS < ofs)
                                {
                                    break;
                                }
                                // otherwise add the next event
                                eventList.Add(ev);
                            }
                            // send the list of events
                            if (MidiStreamState.Closed != stm.State && 0 != eventList.Count)
                            {
                                stm.SendDirect(eventList);
                            }
                            Visualizer.CursorPosition = songTicks;
                        }));
                    }
                    catch { }
                };
                // add the first events
                for (pos = 0; pos < MAX_EVENT_COUNT && ofs <= RATE_TICKS; ++pos)
                {
                    // if it's past the end, loop it
                    if (len <= pos)
                    {
                        pos       = 0;
                        songPos   = 0;
                        songTicks = 0;
                        events    = seq.Events;
                        break;
                    }
                    var ev = events[pos];
                    ofs       += ev.Position;
                    songTicks += ev.Position;
                    if (ev.Position < RATE_TICKS && RATE_TICKS < ofs)
                    {
                        break;
                    }
                    // otherwise add the next event
                    eventList.Add(ev);
                }
                Visualizer.CursorPosition = songTicks;
                // send the list of events
                if (0 != eventList.Count)
                {
                    stm.SendDirect(eventList);
                }
            }
        }
예제 #33
0
        static void Main(string[] args)
        {
            int[] codeMidi = new int[] { 0, 0, 0, 0, 0, 0, 0 };
            if (args.Length != 1)
            {
                Console.WriteLine("Usage: TransposeMidi.exe filename.mid steps");
                Console.WriteLine("    filename.mid = MIDI file to be transposed");
                Console.WriteLine("    steps = Number of steps to transpose, positive or negative");
                Console.WriteLine();
                return;
            }

            string originpath = System.IO.Directory.GetCurrentDirectory();

            string[] op = originpath.Split('\\');
            originpath = "";
            for (int i = 0; i < (op.Length) - 4; i++)
            {
                originpath += op[i];
                originpath += "\\";
            }



            if (!File.Exists(args[0]))
            {
                Console.WriteLine("Error: file {0} not found", args[0]);
                return;
            }

            /*            int steps;
             *          if (!int.TryParse(args[1], out steps))
             *          {
             *              Console.WriteLine("Error: invalid number of steps {0}", args[1]);
             *              return;
             *          }*/

            try
            {
                MidiSequence sequence;
                using (Stream inputStream = File.OpenRead(args[0]))
                {
                    sequence = MidiSequence.Open(inputStream);
                }



                for (int i = 0; i < 8; i++)
                {
                    MidiSequence newSequence = sequence.Trim(1857 * i, 1857 * (i + 1) + 10);
                    //              sequence.Transpose(steps);

                    using (Stream outputStream = File.OpenWrite(originpath + @"\\toUnity\\" + i + "\\" + "originmelody." + i + ".trimed.mid.txt"))
                    {
                        newSequence.Save(outputStream);
                    }
                    foreach (MidiTrack track in newSequence)
                    {
                        for (int j = 1; j < track.Events.Count - 1; j = j + 2)
                        {
                            //Console.WriteLine(track.Events[i].ToString().IndexOf("G4"));
                            //Console.WriteLine(track.Events[i].ToString());
                            //Console.WriteLine(track.Events[i].ToString().Substring(5,7));

                            char     spt      = '\t';
                            string[] spstring = track.Events[j].ToString().Split(spt);

                            switch (spstring[2])
                            {
                            case "C6": codeMidi[2] = codeMidi[2] + 3; codeMidi[5] = codeMidi[5] + 2; codeMidi[0]++; break;

                            case "D6": codeMidi[3] = codeMidi[3] + 3; codeMidi[6] = codeMidi[6] + 2; codeMidi[1]++; break;

                            case "E6": codeMidi[4] = codeMidi[4] + 3; codeMidi[0] = codeMidi[0] + 2; codeMidi[2]++; break;

                            case "F6": codeMidi[5] = codeMidi[5] + 3; codeMidi[1] = codeMidi[1] + 2; codeMidi[3]++; break;

                            case "G6": codeMidi[6] = codeMidi[6] + 3; codeMidi[2] = codeMidi[2] + 2; codeMidi[4]++; break;

                            case "A6": codeMidi[0] = codeMidi[0] + 3; codeMidi[5] = codeMidi[5] + 2; codeMidi[3]++; break;

                            case "B6": codeMidi[1] = codeMidi[1] + 3; codeMidi[6] = codeMidi[5] + 2; codeMidi[4]++; break;

                            default: break;
                            }

                            //Console.WriteLine(spstring[2]);
                        }
                        int maxValue = codeMidi.Max();

                        String        path    = System.IO.Directory.GetCurrentDirectory() + @"\\toUnity\\" + i;
                        DirectoryInfo dirInfo = new DirectoryInfo(path);
                        if (dirInfo.Exists == false)
                        {
                            Directory.CreateDirectory(path);
                        }

                        for (int j = 0; j < 8; j++)
                        {
                            if (codeMidi[j] == maxValue)
                            {
                                //Console.WriteLine(j);

                                List <String> MyFiles = Directory.GetFiles(originpath + @"\Resources\\" + j).ToList();

                                foreach (string file in MyFiles)
                                {
                                    FileInfo mFile = new FileInfo(file);
                                    // to remove name collisions
                                    if (new FileInfo(originpath + @"\\toUnity\\" + i + "\\" + mFile.Name).Exists == false)
                                    {
                                        mFile.CopyTo(originpath + @"\\toUnity\\" + i + "\\" + mFile.Name + ".txt");
                                    }
                                }
                                MyFiles.Clear();
                                MyFiles = null;
                                break;
                            }
                        }
                        System.Array.Clear(codeMidi, 0, 7);
                    }
                }
            }



            /*string outputPath = args[0] + ".transposed.mid";
             * using (Stream outputStream = File.OpenWrite(outputPath)) {
             *  sequence.Save(outputStream);
             * }
             * Console.WriteLine("Transposed MIDI written to: {0}", outputPath);*/
            //

            catch (Exception exc)
            {
                Console.Error.WriteLine("Error: {0}", exc.Message);
            }
        }