예제 #1
0
        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();
        }
예제 #2
0
        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();
                }
            }
        }
예제 #3
0
 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];
     }
 }
예제 #4
0
 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];
     }
 }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
 internal clsMute(clsTrks trks)
 {
     Trks = trks;
     MutedTrackFromStart = new clsTrks.Array <bool>(Trks, false);
     MutedTracks         = new clsTrks.Array <bool>(Trks, false);
 }
예제 #8
0
        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;
                }
            }
        }