public static MIDIData readFile(string filePath) { MIDIData data = new MIDIData(); try { Console.WriteLine("Reading file {0}", filePath); byte[] fileBytes = File.ReadAllBytes(filePath); UInt64 trackChunkStart = MIDIFileReader.readHeader(fileBytes, data); Console.WriteLine("format: {0}, ntracks: {1}, tickdiv: {2} ", data.format, data.ntracks, data.tickdiv); if (data.timing == TimingScheme.MetricalTiming) { Console.WriteLine("Metrical timing PPQN: {0}", data.metrical_ppqn); } else { Console.WriteLine("Timecode FPS: {0} SFR:{1}", data.timecode_fps, data.timecode_sfr); } UInt64 trackChunkEnd = trackChunkStart; while (trackChunkEnd < (UInt64)fileBytes.Length && data.tracks.Count < data.ntracks) { trackChunkEnd = MIDIFileReader.readTracks(fileBytes, data, trackChunkEnd); Console.WriteLine("Track {0} read with {1} events", data.tracks.Count, data.tracks[data.tracks.Count - 1].events.Count); } } catch (Exception e) { Console.WriteLine("Failed to read file {0}: {1}\n{2}", filePath, e.Message, e.StackTrace); } return(data); }
// returns length of header static UInt64 readHeader(byte[] fileData, MIDIData data) { ushort expectedChunkLen = 6; if (fileData.Length < 8) { throw new Exception("File data too short to contain header"); } if (!(fileData[0] == 0x4d && fileData[1] == 0x54 && fileData[2] == 0x68 && fileData[3] == 0x64)) // "MThd" { throw new Exception("File data does not contain header identifier"); } ushort chunklen = 0; chunklen |= (ushort)((ushort)fileData[4] << 24); chunklen |= (ushort)((ushort)fileData[5] << 16); chunklen |= (ushort)((ushort)fileData[6] << 8); chunklen |= (ushort)((ushort)fileData[7]); Console.WriteLine("Chunk length: {0}", chunklen); if (fileData.Length < 8 + chunklen) { throw new Exception("File data too short to contain header chunk"); } if (chunklen != expectedChunkLen) { throw new Exception("Unexpected chunk length in header (was " + chunklen + " expected " + expectedChunkLen + ")"); } data.format = (ushort)((ushort)fileData[8] << 8 | (ushort)fileData[9]); if (data.format > 2) { throw new Exception("Undefined format value in header (" + data.format + ")"); } data.ntracks = (ushort)((ushort)fileData[10] << 8 | (ushort)fileData[11]); data.tickdiv = (ushort)((ushort)fileData[12] << 8 | (ushort)fileData[13]); if (((data.tickdiv >> 15) & 0x01) == 1) { data.timing = TimingScheme.TimeCode; data.timecode_fps = (ushort)((data.tickdiv >> 8) & 0x7); data.timecode_sfr = (ushort)(data.tickdiv & 0xf); } else { data.timing = TimingScheme.MetricalTiming; data.metrical_ppqn = (ushort)(data.tickdiv & 0x7f); } return((UInt64)(chunklen + 8)); }
static UInt64 readTracks(byte[] fileData, MIDIData data, UInt64 chunkStart) { UInt64 index = chunkStart; while (index < (UInt64)fileData.Length) { // start reading a track chunk if ((UInt64)fileData.Length < index + 8) { throw new Exception("File data too short to contain track chunk at index " + index); } if (!(fileData[index + 0] == 0x4d && fileData[index + 1] == 0x54 && fileData[index + 2] == 0x72 && fileData[index + 3] == 0x6B)) // "MTrk" { throw new Exception("File data does not contain expected track identifier at index " + index); } index += 4; ushort chunklen = 0; chunklen |= (ushort)((ushort)fileData[index + 0] << 24); chunklen |= (ushort)((ushort)fileData[index + 1] << 16); chunklen |= (ushort)((ushort)fileData[index + 2] << 8); chunklen |= (ushort)((ushort)fileData[index + 3]); index += 4; Console.WriteLine("Chunklen {0}", chunklen); if ((UInt64)fileData.Length < index + chunklen) { throw new Exception("File data too short to contain track chunk of length " + chunklen + " at index " + (index - 8)); } MIDITrack track = new MIDITrack(); UInt64 trackindex = index; MIDIEvent previous = new MIDIEvent(); while (trackindex < index + chunklen) { MIDIEvent new_event = MIDIFileReader.readEvent(fileData, ref trackindex, previous); previous = new_event; track.events.Add(new_event); } data.tracks.Add(track); index = trackindex; break; } return(index); }
static void Main(string[] args) { WaveFormat waveFormat = new WaveFormat(44100, 16, 1); Oscillator freqOsc = new Oscillator(Oscillator.WaveType.SineWave, waveFormat.SampleRate, new ConstantScalar(0.1f), new ConstantScalar(80.0f), new ConstantScalar(0), new ConstantScalar(100.0f)); Oscillator ampOscVel = new Oscillator(Oscillator.WaveType.SineWave, waveFormat.SampleRate, new ConstantScalar(0.05f), new ConstantScalar(8.0f), new ConstantScalar(0.5f), new ConstantScalar(8.0f)); Oscillator ampOsc = new Oscillator(Oscillator.WaveType.SawtoothWave, waveFormat.SampleRate, ampOscVel, new ConstantScalar(0.5f), new ConstantScalar(0), new ConstantScalar(1.1f)); Oscillator variableFreq = new Oscillator(Oscillator.WaveType.SineWave, waveFormat.SampleRate, freqOsc, ampOsc, new ConstantScalar(0), new ConstantScalar(0)); ScalarPassthrough scalarPassthru = new ScalarPassthrough(waveFormat, variableFreq); NoiseGenerator noiseGen = new NoiseGenerator(waveFormat, NoiseGenerator.NoiseType.WhiteNoise); Oscillator freqsweep = new Oscillator(Oscillator.WaveType.SineWave, waveFormat.SampleRate, new ConstantScalar(0.1f), new ConstantScalar(200), new ConstantScalar(0), new ConstantScalar(440)); Oscillator qsweep = new Oscillator(Oscillator.WaveType.SineWave, waveFormat.SampleRate, new ConstantScalar(1.0f), new ConstantScalar(0.9f), new ConstantScalar(0), new ConstantScalar(1.0f)); //new ConstantScalar((float)(1.0 / Math.Sqrt(2))); //Oscillator gainSweep = new Oscillator(Oscillator.WaveType.TriangleWave, waveFormat.SampleRate, new ConstantScalar(0.025f), new ConstantScalar(2), new ConstantScalar(0), new ConstantScalar(6)); ConstantScalar gainSweep = new ConstantScalar(6); SampleProcessor.SampleProcessor filter = new SampleProcessor.NotchFilter(waveFormat, freqsweep, qsweep, gainSweep, scalarPassthru); // distortion "pedal" on a minimally modified hard body electric guitar signal Oscillator gainOsc = new Oscillator(Oscillator.WaveType.SineWave, waveFormat.SampleRate, new ConstantScalar(0.5f), new ConstantScalar(2), new ConstantScalar(0), new ConstantScalar(5)); Oscillator cutoffOsc = new Oscillator(Oscillator.WaveType.SineWave, waveFormat.SampleRate, new ConstantScalar(0.95f), new ConstantScalar(3), new ConstantScalar(0), new ConstantScalar(4)); ConstantScalar cutoff = new ConstantScalar(0.2f); IWaveSource cleanguitar = CodecFactory.Instance.GetCodec(@"..\..\sampledata\guitar-sample.mp3"); // sample signal from single-pickup electric guitar. Recorded 8/14/20. IReadableAudioSource <float> convertedguitar = cleanguitar.ToMono().ToSampleSource(); SampleProcessor.DistortionEffect distortion = new SampleProcessor.DistortionEffect(waveFormat, gainOsc, cutoff, convertedguitar); SampleProcessor.SampleProcessor reverbEffect = new SampleProcessor.ReverbEffect(waveFormat, new ConstantScalar(0.4f), new ConstantScalar(0.5f), waveFormat.SampleRate, distortion); BasicAudioController basicAudioController = new BasicAudioController(GetSoundOut(), 1, 44100); basicAudioController.addSource((ISampleSource)reverbEffect); basicAudioController.startPlaying(); Console.ReadKey(); basicAudioController.stopPlaying(); return; MIDI.MIDIData data = MIDI.MIDIFileReader.readFile(@"..\..\sampledata\MIDI_sample.mid"); MIDI.MIDIData testdata = new MIDI.MIDIData(); testdata.format = 0; testdata.timing = MIDI.TimingScheme.TimeCode; testdata.timecode_fps = 24; testdata.timecode_sfr = 4; testdata.ntracks = 1; testdata.tracks.Add(new MIDI.MIDITrack()); MIDI.MIDIEvent event0 = new MIDI.MIDIEvent(); MIDI.MIDIEvent event1 = new MIDI.MIDIEvent(); event0.delta = 4 * 24 * 5; // wait 5 seconds from start event1.delta = 4 * 24 * 2; // 2 seconds //event0.type = MIDI.EventType.MIDIEvent; //event0.midieventtype = MIDI.MIDIEventType.NoteOn; //event0.val1 = 0; // channel 0 //event0.val2 = 60; // middle C //event0.val3 = 1; //event1.type = MIDI.EventType.MIDIEvent; //event1.midieventtype = MIDI.MIDIEventType.NoteOff; //event1.val1 = 0; // channel 0 //event1.val2 = 60; // middle C //event1.val3 = 1; //testdata.tracks[0].events.Add(event0); //testdata.tracks[0].events.Add(event1); MIDI.MIDIPlayer player = new MIDI.MIDIPlayer(data); Console.WriteLine("Track 1 events:"); player.playTrack(1); Console.ReadKey(); return; MIDIAudioController audioController = new MIDIAudioController(GetSoundOut()); ChromaticScale.ChromaticScale scale = new ChromaticScale.ChromaticScale(); audioController.startPlaying(); SampleSource.WaveGenerator.WaveType wavetype = WaveGenerator.WaveType.SineWave; Console.ReadKey(); // wait for input for (int i = 0; i < scale.notes.Count(); i++) { float freq = scale.notes[i].base_freq / 2; Console.WriteLine(scale.notes[i].identifier[0] + " - " + freq + " - " + wavetype); audioController.updatePlaying(freq, wavetype); Console.ReadKey(); // wait for input wavetype = Next(wavetype); } for (int i = 0; i < scale.notes.Count(); i++) { Console.WriteLine(scale.notes[i].identifier[0] + " - " + scale.notes[i].base_freq.ToString() + " - " + wavetype); audioController.updatePlaying(scale.notes[i].base_freq, wavetype); Console.ReadKey(); // wait for input wavetype = Next(wavetype); } for (int i = 0; i < scale.notes.Count(); i++) { float freq = scale.notes[i].base_freq * 2; Console.WriteLine(scale.notes[i].identifier[0] + " - " + freq + " - " + wavetype); audioController.updatePlaying(freq, wavetype); Console.ReadKey(); // wait for input wavetype = Next(wavetype); } audioController.stopPlaying(); audioController.Dispose(); }
public MIDIPlayer(MIDIData data) { this.data = data; }