internal clsNoteMapMidi(clsOnOff onoff, clsTrks.Array <int> trkminpitch, clsTrks.Array <int> trkmaxpitch, clsFileStream filestream) { //NumTrks = numtrks; TrkMinPitch = trkminpitch; TrkMaxPitch = trkmaxpitch; int len = P.F.MaxBBT.MaxNoteMapQI; Filter = new byte[len, 12]; #if MemoryInfo long before = GC.GetTotalMemory(true); #endif PropagatePW(filestream, len, null); _Map = new clsTrks.Array <ushort[]>(delegate() { return(new ushort[len]); }); //NewMap = clsTrks.Array<ushort[]>.NewClass(delegate () { return new ushort[onoff.Length]; }); InitMap(onoff, null, filestream.ExclPB); _FullMap = new clsTrks.Array <BigInteger[]>(delegate() { return(new BigInteger[len]); }); //BigInteger 128 bits //NewFullMap = clsTrks.Array<BigInteger[]>.NewClass(delegate () { return new BigInteger[onoff.Length]; });//BigInteger 128 bits InitFullMap(onoff, null, filestream.ExclPB); #if MemoryInfo long after = GC.GetTotalMemory(true); long diff = after - before; TotalMem += diff; Debug.WriteLine("clsNoteMapMidi new diff = " + diff + " total diff = " + TotalMem + " bytes"); #endif InitFilter(0, Filter.GetLength(0) - 1); EleW = new clsW(this); CreateOnOffPairs(); }
internal clsLoadMidiFile(clsFileStream filestream, string filename, clsTrks.Array <bool> trkselect, bool excl10, bool firsttime) { bool condtrkempty = P.F.CondTrkEmpty; //P.F.Project.MidiPath = filename; P.frmSC.cmdMultiMap.Enabled = true; if (P.F.frmChordMap != null) { P.F.frmChordMap.cmdMultiMap.Enabled = true; } FileStream = filestream; //FileStream.Summary = summary; //FileStream.Transpose = transpose; if (trkselect != null) { FileStream.TrkSelect = trkselect; } Excl10 = excl10; if (!ReadFile(firsttime)) { if (condtrkempty && !P.F.CondTrkEmpty) //non-empty conductor track found { condtrkempty = false; if (!ReadFile(firsttime)) { ReadError(); } } else { ReadError(); } } }
private void SetMap128(clsTrks.Array <BigInteger[]> map, int qtime, int note, clsTrks.T trk, bool value) { if (value) { map[trk][qtime] |= NoteMask128[note]; } else { map[trk][qtime] &= ~NoteMask128[note]; } }
private void SetMap12(clsTrks.Array <ushort[]> map, int qtime, int note, clsTrks.T trk, bool value) { if (value) { map[trk][qtime] |= NoteMask12[note]; } else { map[trk][qtime] &= (ushort)~NoteMask12[note]; } }
protected bool ReadTrack(int midifiletrk, bool indtsigs, clsTrks.Array <List <clsFileStream.clsOO> > oo) //trk0 = first non-conductor trk //* return false if midi trk data in trk0 (eg midi ON, OFF, patch, ...) { InitTrack(); //if (trk >= 0) FileStream.OO[trk] = new List<clsFileStream.clsOO>(); clsTrks.T trk = (midifiletrk >= 0) ? new clsTrks.T(P.F.Trks, midifiletrk) : null; FileStream.StrmLL.ResetCurrentLLN(); int delta = MReaderTrk.ReadIntV(); int ticks = 0; byte status = 0; //usually >= 0x80 int chan = -1; int seq = -1; //bool sustainon = false; //set only only if P.frmStart.chkMidiFileSustain.Checked //bool[] sustained = new bool[128]; //set only only if P.frmStart.chkMidiFileSustain.Checked while (delta >= 0) //not EOF { seq++; ticks += delta; if (TPQNConv) { ticks = (ticks * TPQNMult) / TPQNDiv; //should normally not need rounding } byte b = MReaderTrk.ReadByte(); if (b >= 0x80) //new status { status = b; chan = -1; if (status < 0xf0) { chan = status & 0x0f; b = MReaderTrk.ReadByte(); //not sysex or metaev } if (Format == 0) { midifiletrk = chan; if (chan < 0) { trk = new clsTrks.T(P.F.Trks, 0); } else { trk = new clsTrks.T(P.F.Trks, midifiletrk); } } } switch (status & 0xf0) { case 0x90: //ON case 0x80: //OFF //* 2 data bytes if (midifiletrk < 0) { return(false); } //int chan = status & 0x0f; //byte pitch = (byte)(b + FileStream.Transpose); byte pitch = b; byte vel = MReaderTrk.ReadByte(); bool on = (status & 0xf0) == 0x90 && (vel > 0); //* throw new TestException(); if (on) { FileStream.UpdateChanOnTotals(trk, chan, pitch); } FileStream.ChanAllCount[trk][chan]++; FileStream.StrmLL.InsertShortEv(seq, ticks, midifiletrk, status, b, vel); if (!Excl10 || chan != 9) { oo[new clsTrks.T(P.F.Trks, midifiletrk)].Add(new clsFileStream.clsOO( ticks, on, chan, pitch, vel, P.F.TicksPerQI)); } break; case 0xa0: //poly key pressure case 0xb0: //control change case 0xe0: //pitch wheel //* 2 data bytes //if (trk < 0) return true; if (midifiletrk < 0) //ignore { MReaderTrk.ReadByte(); break; } byte c = MReaderTrk.ReadByte(); if (FileStream.Title[trk].StartsWith("Cakewalk TTS-1")) { break; //kludge to get around Sonar bug } if ((status & 0xf0) == 0xe0) //pitchbend { if (b != 0 || c != 64) { FileStream.indPitchBend[trk] = true; //not middle value } } //else if (P.frmStart.chkMidiFileSustain.Checked && (!Excl10 || chan != 9)) { // if ((status & 0xf0) == 0xb0 && b == 64) { //sustain // sustainon = (c > 64); // if (!sustainon) { //sustainon -> sustainoff // for (int i = 0; i < 128; i++) { // if (sustained[i]) { // FileStream.OO[trk].Add(new clsFileStream.clsOO(ticks, false, chan, i, 0, P.F.TicksPerQI)); // sustained[i] = false; // } // } // } // } //} FileStream.StrmLL.InsertShortEv(seq, ticks, midifiletrk, status, b, c); FileStream.ChanAllCount[trk][status & 0x0f]++; break; case 0xc0: //program change (patch) //* 1 data byte //if (trk < 0) return false; if (midifiletrk < 0) { break; //ignore } if (FileStream.Title[trk].StartsWith("Cakewalk TTS-1")) { break; //kludge to get around Sonar bug } //if (!FileStream.Summary) FileStream.InsertShortEv(ticks, trk, status, b); FileStream.StrmLL.InsertShortEv(seq, ticks, midifiletrk, status, b); FileStream.ChanAllCount[trk][status & 0x0f]++; break; case 0xd0: //channel pressure //if (trk < 0) return false; if (midifiletrk < 0) { break; } //* 1 data byte //if (!FileStream.Summary && FileStream.TrkSelect[trk]) { //if (!FileStream.Summary) { FileStream.StrmLL.InsertShortEv(seq, ticks, midifiletrk, status, b); //} FileStream.ChanAllCount[trk][status & 0x0f]++; break; case 0xf0: //system common messages int len; switch (status) { case 0xf0: //sysex start case 0xf7: //sysex end len = MReaderTrk.ReadIntV(); byte[] sysdata = MReaderTrk.ReadBytes(len); FileStream.StrmLL.InsertSystemEv(seq, ticks, midifiletrk, status, sysdata); status = 0; //sysex cancels running status break; case 0xff: //meta event status = 0; //metaev cancels running status byte type = MReaderTrk.ReadByte(); len = MReaderTrk.ReadIntV(); byte[] metadata; switch (type) { case 0x03: //title metadata = MReaderTrk.ReadBytes(len); string title = Encoding.Default.GetString(metadata, 0, metadata.Length); if (midifiletrk == -1) { FileStream.ProjectTitle = title; } else { FileStream.Title[trk] = title; } FileStream.StrmLL.InsertTitleEv(seq, ticks, midifiletrk, metadata); break; //case 0x21: //device (port) number // if (len != 1) throw new MidiFileException(); // int pp = (int)MReaderTrk.ReadUIntF(1); // if (pp != 0) Debug.WriteLine("MidiPortNumber: " + pp + " found - ignored"); // break; //case 0x09: //device (port) name // //MReaderTrk.ReadBytes(len); //ignore metaev // break; case 0x51: //tempo ////if (!IsCondTrk(midifiletrk)) { //// MReaderTrk.ReadBytes(len); //ignore //// Debug.WriteLine("Invalid tempo found on track " + midifiletrk + " - ignored"); //// break; ////} if (len != 3) { throw new MidiFileException(); } int data = (int)MReaderTrk.ReadUIntF(3); FileStream.TempoMap.Add(ticks, data); FileStream.StrmLL.InsertTempoEv(seq, ticks, data); break; case 0x58: //tsig ////if (!IsCondTrk(midifiletrk)) { //// MReaderTrk.ReadBytes(len); //ignore //// Debug.WriteLine("Invalid time signature found on track " + midifiletrk + " - ignored"); //// break; ////} if (len != 4) { throw new MidiFileException(); } int nn = (int)MReaderTrk.ReadUIntF(1); int dd = (int)MReaderTrk.ReadUIntF(1); MReaderTrk.ReadUIntF(1); //bb - not used MReaderTrk.ReadUIntF(1); //cc - not used if (indtsigs) { int tsigdd = (int)Math.Pow(2, dd); clsMTime.clsBBT bbt = new clsMTime.clsBBT(ticks); P.frmStart.TraceLoad("add tsig " + nn + "/" + tsigdd + " ticks " + ticks + " from midifile"); //P.F.MTime.UpdateTSigsTicks(nn, tsigdd, ticks); if (ticks == 0) { P.F.MTime.AddTSigFirst(nn, tsigdd); } else { P.F.MTime.AddTSig(nn, tsigdd, ticks, adj: true); } } else { P.frmStart.TraceLoad("bypass tsig from midifile at ticks " + ticks); } break; case 0x59: //key sig //if (!IsCondTrk(midifiletrk)) { // MReaderTrk.ReadBytes(len); //ignore // MessageBox.Show("Invalid key signature found on track " + midifiletrk + " - ignored"); // break; //} if (len != 2) { throw new MidiFileException(); } int midikey = MReaderTrk.ReadIntSByte(); midikey = Math.Min(Math.Max(midikey, -7), 7); string scale = MajMin(MReaderTrk.ReadUIntF(1)); P.frmStart.TraceLoad("add midifile key to _MidiKeys at ticks " + ticks); P.F._MidiKeys.Add(midikey, scale, ticks); break; case 0x01: //text metadata = MReaderTrk.ReadBytes(len); //other metaev FileStream.StrmLL.InsertMetaEv(seq, ticks, midifiletrk, type, metadata); if (IsCondTrk(midifiletrk)) { string text = Encoding.Default.GetString(metadata, 0, metadata.Length); if (ticks == 0) //general text about the midifile? { FileStream.Text00.Add(text); } } break; case 0x2f: //end of track MaxMidiTicks = Math.Max(MaxMidiTicks, ticks); break; //don't put in stream!!! default: metadata = MReaderTrk.ReadBytes(len); //other metaev FileStream.StrmLL.InsertMetaEv(seq, ticks, midifiletrk, type, metadata); break; } break; default: status = 0; //probably throw new MidiFileException(); //not sysex or metaev } break; default: break; } delta = MReaderTrk.ReadIntV(); if (delta < 0) { break; } } MReaderTrk.Close(); //if (P.F.MTime.TSigsSrc == clsMTime.eSource.None) P.F.MTime.TSigsSrc = clsMTime.eSource.Midi; return(true); }
protected bool ReadHeader(bool firsttime, out clsTrks.Array <List <clsFileStream.clsOO> > oo) { oo = null; string head = MReaderFile.ReadStr(4); if (head != "MThd") { MessageBox.Show("Invalid Midi Header: " + head); return(false); } uint len = MReaderFile.ReadUIntF(4); if (len != 6) { MessageBox.Show("Invalid Midi Header Length: " + len); return(false); } Format = (int)MReaderFile.ReadUIntF(2); if (Format != 1 && Format != 0) { MessageBox.Show("Unsupported Midi File Format: " + Format); return(false); } if (Format == 0) { //if (FileStream.Summary) MessageBox.Show("Format 0 file - creating 16 tracks"); P.F.CondTrkEmpty = false; } //if (P.F.NumNewTrks < 0) P.F.NumNewTrks = (int)P.frmStart.nudAddedTrks.Value; //for recording //int numnewtrks = (int)P.frmStart.nudAddedTrks.Value; //int numnewtrks = 0; NumMidiFileTrks = MReaderFile.ReadUIntF(2); //includes conductor trk, excludes header P.MMSW?.WriteLine(" File Format: " + Format); P.MMSW?.WriteLine(" NumMidiFileTrks = " + NumMidiFileTrks); if (clsTrks.T.TrkOOR(NumMidiFileTrks)) { string msg = "Number of Midi Tracks (" + NumMidiFileTrks + ") exceeds limit of " + clsTrks.NumTrksMax; MessageBox.Show(msg); return(false); } bool trksok = false; if (P.F.CondTrkEmpty) { //NumTrks = (int)(NumMidiTrks); //excludes header and conductor trk, incl. empty recording trk trksok = P.F.Trks.SetNumTrks((int)(NumMidiFileTrks - 1)); //excludes header and conductor trk, incl. empty recording trk } else { if (Format == 0) { trksok = P.F.Trks.SetNumTrks(16); //one track per channel } //else NumTrks = (int)NumMidiTrks + 1; //excludes header, incl. conductor trk with channel data & empty recording trk else { trksok = P.F.Trks.SetNumTrks((int)NumMidiFileTrks); //excludes header, incl. conductor trk with channel data & empty recording trk } if (!trksok) { LogicError.Throw(eLogicError.X146); return(false); } } oo = new clsTrks.Array <List <clsFileStream.clsOO> >(delegate() { return(new List <clsFileStream.clsOO>(500)); }); //[trk][seq] //oo = clsTrks.Array<List<clsFileStream.clsOO>>.NewClass(delegate () { return new List<clsFileStream.clsOO>(500); }); //foreach (clsTrks.T trk in oo.Next) oo[trk] = new List<clsFileStream.clsOO>(500); //* new method int tpqnmidifile = (int)MReaderFile.ReadUIntF(2); if (tpqnmidifile >= 0x8000) { MessageBox.Show("Unsupported time-code-based time in midi header"); return(false); } if (firsttime) { P.frmStart.TraceLoad("initialize mtime 4/4 from midi header"); P.F.MTime = new clsMTime(tpqnmidifile, 4, 4); //tsig 4/4 default P.F.BarPaneBBTLo = new clsMTime.clsBBT(0); P.F.BarPaneBBTHi = new clsMTime.clsBBT(0); //GetTicksPerQI(); //default (if no tsig in midi file) } else { P.frmStart.TraceLoad("bypass mtime from midi header"); } if (P.F.CurrentBBT == null) { P.F.CurrentBBT = new clsMTime.clsBBT(0); } // else P.F.CurrentBBT = new clsMTime.clsBBT(P.F.CurrentBBT.Ticks); //using current P.F.MTime (4/4) return(true); }
internal clsMute(clsTrks trks) { Trks = trks; MutedTrackFromStart = new clsTrks.Array <bool>(Trks, false); MutedTracks = new clsTrks.Array <bool>(Trks, false); }
internal void PropagatePW(clsFileStream filestream, int len, clsTrks.T trk) { //* null trk = all trks //* initialize PB if (trk == null) { PB = new clsTrks.Array <short[]>(delegate() { short[] pw = new short[len]; for (int i = 0; i < len; i++) { pw[i] = -1; } return(pw); }); } else { PB[trk] = new short[len]; for (int i = 0; i < len; i++) { PB[trk][i] = -1; } } //* read stream clsFileStream.clsEvStrm[] strm = filestream.Strm; for (int i = 0; i < strm.Length; i++) { if (strm[i] is clsFileStream.clsEvShort) { clsFileStream.clsEvShort ev = ((clsFileStream.clsEvShort)strm[i]); if (trk != null && trk != ev.Trk) { continue; } if ((ev.Status & 0xe0) != 0xe0) { continue; //not pitchbend } int val = ev.Msg + (ev.Data << 7); PB[ev.Trk][ev.QTime] = (short)val; //channel not used - only track } } //* propagate PB foreach (clsTrks.T t in PB.Next) { if (trk != null && trk != t) { continue; } short pw = 8192; //centre (default) for (int qi = 0; qi < len; qi++) { if (PB[t][qi] >= 0) { pw = PB[t][qi]; //set current value } PB[t][qi] = pw; } } }