/// <summary>Parse a meta MIDI event from the data stream.</summary>
        /// <param name="deltaTime">The previously parsed delta-time for this event.</param>
        /// <param name="eventType">The previously parsed type of message we're expecting to find.</param>
        /// <param name="data">The data stream from which to read the event information.</param>
        /// <param name="pos">The position of the start of the event information.</param>
        /// <returns>The parsed meta MIDI event.</returns>
        private static MidiEvent ParseMetaEvent(long deltaTime, byte eventType, byte[] data, ref long pos)
        {
            try {
                MidiEvent tempEvent = null;

                // Create the correct meta event based on its meta event id/type
                switch (eventType)
                {
                // Sequence number
                case SequenceNumberMetaMidiEvent.MetaId:
                    pos++;     // skip past the 0x02
                    int number = ((data[pos] << 8) | data[pos + 1]);
                    tempEvent = new SequenceNumberMetaMidiEvent(deltaTime, number);
                    pos      += 2; // skip read values
                    break;

                // Text events (copyright, lyrics, etc)
                case TextMetaMidiEvent.MetaId:
                    tempEvent = new TextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos));
                    break;

                case CopyrightTextMetaMidiEvent.MetaId:
                    tempEvent = new CopyrightTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos));
                    break;

                case SequenceTrackNameTextMetaMidiEvent.MetaId:
                    tempEvent = new SequenceTrackNameTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos));
                    break;

                case InstrumentTextMetaMidiEvent.MetaId:
                    tempEvent = new InstrumentTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos));
                    break;

                case LyricTextMetaMidiEvent.MetaId:
                    tempEvent = new LyricTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos));
                    break;

                case MarkerTextMetaMidiEvent.MetaId:
                    tempEvent = new MarkerTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos));
                    break;

                case CuePointTextMetaMidiEvent.MetaId:
                    tempEvent = new CuePointTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos));
                    break;

                case ProgramNameTextMetaMidiEvent.MetaId:
                    tempEvent = new ProgramNameTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos));
                    break;

                case DeviceNameTextMidiEvent.MetaId:
                    tempEvent = new DeviceNameTextMidiEvent(deltaTime, ReadASCIIText(data, ref pos));
                    break;

                // Channel prefix
                case ChannelPrefixMetaMidiEvent.MetaId:
                    pos++;     // skip 0x1
                    tempEvent = new ChannelPrefixMetaMidiEvent(deltaTime, data[pos]);
                    pos++;     // skip read value
                    break;

                // Port number
                case MidiPortMetaMidiEvent.MetaId:
                    pos++;     // skip 0x1
                    tempEvent = new MidiPortMetaMidiEvent(deltaTime, data[pos]);
                    pos++;     // skip read value
                    break;

                // End of track
                case EndOfTrackMetaMidiEvent.MetaId:
                    pos++;     // skip 0x0
                    tempEvent = new EndOfTrackMetaMidiEvent(deltaTime);
                    break;

                // Tempo
                case TempoMetaMidiEvent.MetaId:
                    pos++;     // skip 0x3
                    int tempo = ((data[pos] << 16) | data[pos + 1] << 8 | data[pos + 2]);
                    tempEvent = new TempoMetaMidiEvent(deltaTime, tempo);
                    pos      += 3;
                    break;

                // SMPTE offset
                case SMPTEOffsetMetaMidiEvent.MetaId:
                    pos++;     // skip 0x5
                    tempEvent = new SMPTEOffsetMetaMidiEvent(deltaTime,
                                                             data[pos], data[pos + 1], data[pos + 2], data[pos + 3], data[pos + 4]);
                    pos += 5;
                    break;

                // Time signature
                case TimeSignatureMetaMidiEvent.MetaId:
                    pos++;     // skip past 0x4
                    tempEvent = new TimeSignatureMetaMidiEvent(deltaTime,
                                                               data[pos], data[pos + 1], data[pos + 2], data[pos + 3]);
                    pos += 4;
                    break;

                // Key signature
                case KeySignatureMetaMidiEvent.MetaId:
                    pos++;     // skip past 0x2
                    tempEvent = new KeySignatureMetaMidiEvent(deltaTime, (Key)data[pos], (Tonality)data[pos + 1]);
                    pos      += 2;
                    break;

                // Proprietary
                case ProprietaryMetaMidiEvent.MetaId:
                    // Read in the variable length and that much data, then store it
                    long   length   = ReadVariableLength(data, ref pos);
                    byte[] propData = new byte[length];
                    Array.Copy(data, (int)pos, propData, 0, (int)length);
                    tempEvent = new ProprietaryMetaMidiEvent(deltaTime, propData);
                    pos      += length;
                    break;

                // An unknown meta event!
                default:
                    // Read in the variable length and that much data, then store it
                    length = ReadVariableLength(data, ref pos);
                    byte[] unknownData = new byte[length];
                    Array.Copy(data, (int)pos, unknownData, 0, (int)length);
                    tempEvent = new UnknownMetaMidiEvent(deltaTime, eventType, unknownData);
                    pos      += length;
                    break;
                }
                return(tempEvent);
            }
            // Something bad happened; wrap it in a parser exception
            catch (Exception exc) { throw new MidiParserException("Unable to parse meta MIDI event.", exc, pos); }
        }
Beispiel #2
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;
            }
        }