/// <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); } }
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; } }