Exemple #1
0
        private TrackEvent readMetaEvent(byte statusByte, BinaryReader reader, out uint readDataSize)
        {
            readDataSize = 0;
            byte eventType = reader.ReadByte();
            uint dataSize;

            readDataSize += readVarLenNumeric(reader, out dataSize);
            readDataSize += dataSize + 1 /* eventType */ + 1 /* statusByte */;

            switch (eventType)
            {
            case 0x2f:     // Track End
                return(null);

            case 0x51:     // Tempo
            {
                // 四分音符の長さ(microsec, 10^-6
                int        tempo = (int)(readBENumeric(reader, 3));
                TrackEvent ev    = new TrackEvent();
                ev.EventType = EventType.Tempo;
                ev.Params    = new object[] { tempo };
                return(ev);
            }

            case 0x58:                       // 拍子
            {
                byte b1 = reader.ReadByte(); // 分子
                byte b2 = reader.ReadByte(); // 分母(2のマイナス乗)
                byte b3 = reader.ReadByte(); // 1拍当たりのMIDIクロック数
                byte b4 = reader.ReadByte(); // 四分音符の中に入る32分の音符数
                if (b3 != 0x18 || b4 != 0x08)
                {
                    throw new SMFException("対応していないMIDIファイル:拍子記号");
                }
            }
                return(null);

            case 0x54:
            case 0x00:
            case 0x01:
            case 0x02:
            case 0x03:
            case 0x04:
            case 0x05:
            case 0x06:
            case 0x07:
            case 0x08:
            case 0x09:
            case 0x20:
            case 0x21:
            case 0x59:
            case 0x7f:
            default:
                reader.ReadBytes((int)dataSize);     // 読み飛ばし
                return(null);
            }
        }
Exemple #2
0
        private TrackEvent readMidiEvent(byte statusByte, byte prevStatusByte, BinaryReader reader, out uint readDataSize)
        {
            readDataSize = 2;

            byte param1 = 0;
            byte param2 = 0;

            bool runningStatus = (statusByte & 0x80) == 0;

            if (runningStatus)
            {
                param1     = statusByte;
                statusByte = prevStatusByte;
                readDataSize--;
            }
            else
            {
                param1 = reader.ReadByte();
            }

            int channel = (statusByte & 0x0f);

            switch (statusByte >> 4)
            {
            case 0x8:     // SMFNote Off
            {
                param2 = reader.ReadByte();
                readDataSize++;

                int noteNum  = param1 & 0x7f;
                int velocity = param2 & 0x7f;

                TrackEvent ev = new TrackEvent();
                ev.EventType = EventType.NoteOff;
                ev.Params    = new object[] { channel, noteNum, velocity };
                return(ev);
            }

            case 0x9:     // SMFNote On
            {
                param2 = reader.ReadByte();
                readDataSize++;

                int noteNum  = param1 & 0x7f;
                int velocity = param2 & 0x7f;

                TrackEvent ev = new TrackEvent();
                ev.EventType = velocity == 0 ? EventType.NoteOff : EventType.NoteOn;
                ev.Params    = new object[] { channel, noteNum, velocity };
                return(ev);
            }

            case 0xa:     // Polyphonic Key Pressure (Aftertouch)
            {
                param2 = reader.ReadByte();
                readDataSize++;

                int noteNum = param1 & 0x7f;
                int amount  = param2 & 0x7f;
            }
            break;

            case 0xb:     // Control Change
            {
                param2 = reader.ReadByte();
                readDataSize++;

                int noteNum = param1 & 0x7f;
                int amount  = param2 & 0x7f;
            }
            break;

            case 0xc:     // Program Change
            {
                int programNum = param1 & 0x7f;
            }
            break;

            case 0xd:     // Channel Pressure (After-touch)
            {
                int amount = param1 & 0x7f;
            }
            break;

            case 0xe:     // Pitch Wheel Change
            {
                param2 = reader.ReadByte();
                readDataSize++;

                int value = param1 + param2 << 7;
            }
            break;
            }

            return(null);
        }
Exemple #3
0
        private TrackEvent readMetaEvent(byte statusByte, BinaryReader reader, out uint readDataSize)
        {
            readDataSize = 0;
            byte eventType = reader.ReadByte();
            uint dataSize;
            readDataSize += readVarLenNumeric(reader, out dataSize);
            readDataSize += dataSize + 1 /* eventType */ + 1 /* statusByte */;

            switch (eventType)
            {
                case 0x2f: // Track End
                    return null;
                case 0x51: // Tempo
                    {
                        // 四分音符の長さ(microsec, 10^-6
                        int tempo = (int)(readBENumeric(reader, 3));
                        TrackEvent ev = new TrackEvent();
                        ev.EventType = EventType.Tempo;
                        ev.Params = new object[] { tempo };
                        return ev;
                    }
                case 0x58: // 拍子
                    {
                        byte b1 = reader.ReadByte(); // 分子
                        byte b2 = reader.ReadByte(); // 分母(2のマイナス乗)
                        byte b3 = reader.ReadByte(); // 1拍当たりのMIDIクロック数
                        byte b4 = reader.ReadByte(); // 四分音符の中に入る32分の音符数
                        if (b3 != 0x18 || b4 != 0x08)
                        {
                            throw new SMFException("対応していないMIDIファイル:拍子記号");
                        }
                    }
                    return null;
                case 0x54:
                case 0x00:
                case 0x01:
                case 0x02:
                case 0x03:
                case 0x04:
                case 0x05:
                case 0x06:
                case 0x07:
                case 0x08:
                case 0x09:
                case 0x20:
                case 0x21:
                case 0x59:
                case 0x7f:
                default:
                    reader.ReadBytes((int)dataSize); // 読み飛ばし
                    return null;
            }
        }
Exemple #4
0
        public override void Load(string filePath)
        {
            List <List <TrackEvent> > trackEvents = new List <List <TrackEvent> >();
            BinaryReader reader = new BinaryReader(new FileStream(filePath, FileMode.Open), Encoding.UTF8);

            _header = readHeader(reader);
            if (!_header.DeltaTimeInPPQN)
            {
                throw new SMFException("対応していないMIDIファイル:TimeInSec Division");
            }
            if (_header.FormatType == 2)
            {
                throw new SMFException("対応していないMIDIファイル:Format");
            }

            for (int i = 0; i < _header.TrackNum; i++)
            {
                List <TrackEvent> evs = new List <TrackEvent>();
                readTrack(reader, ref evs);
                trackEvents.Add(evs);
            }

            double maxPitch = double.MinValue;
            double minPitch = double.MaxValue;

            long   prevTick = 0;
            double time     = 0;
            int    tempo    = 500000;
            double ppqnInv  = 1 / (double)_header.DeltaTime;
            Dictionary <int, Dictionary <int, SMFNote> > channels = new Dictionary <int, Dictionary <int, SMFNote> >();

            _points = new List <MusicNote>();
            while (true)
            {
                if (trackEvents.Count == 0)
                {
                    break;
                }
                if (trackEvents.TrueForAll((lst) => { return(lst.Count == 0); }))
                {
                    break;
                }

                int idx = -1; long minTick = long.MaxValue;
                for (int i = 0; i < trackEvents.Count; i++)
                {
                    if (trackEvents[i].Count == 0)
                    {
                        continue;
                    }
                    long tick = trackEvents[i][0].AbsoluteTick;
                    if (tick < minTick)
                    {
                        idx = i; minTick = tick;
                    }
                }

                if (idx < 0)
                {
                    break;
                }

                TrackEvent fstev = trackEvents[idx][0];
                trackEvents[idx].RemoveAt(0);
                time += (fstev.AbsoluteTick - prevTick) * tempo * ppqnInv / 1000000.0;

                switch (fstev.EventType)
                {
                case EventType.Tempo:
                    tempo = (int)fstev.Params[0];
                    break;

                case EventType.NoteOn:
                {
                    int channel = (int)fstev.Params[0];
                    int noteNum = (int)fstev.Params[1];

                    Dictionary <int, SMFNote> noteNums;
                    if (channels.ContainsKey(channel))
                    {
                        noteNums = channels[channel];
                    }
                    else
                    {
                        noteNums = new Dictionary <int, SMFNote>();
                        channels.Add(channel, noteNums);
                    }

                    SMFNote note;
                    if (noteNums.ContainsKey(noteNum))
                    {
                        note = noteNums[noteNum];

                        MusicNote n = new MusicNote();
                        n.TimeInSec = time;
                        n.Pitch     = note.Pitch;
                        n.Start     = false;
                        _points.Add(n);
                    }

                    note = new SMFNote(true, pitchFromNote(noteNum));
                    if (noteNums.ContainsKey(noteNum))
                    {
                        noteNums[noteNum] = note;
                    }
                    else
                    {
                        noteNums.Add(noteNum, note);
                    }

                    MusicNote nn = new MusicNote();
                    nn.TimeInSec = time;
                    nn.Pitch     = note.Pitch;
                    nn.Start     = true;
                    _points.Add(nn);

                    if (note.Pitch < minPitch)
                    {
                        minPitch = note.Pitch;
                    }
                    if (note.Pitch > maxPitch)
                    {
                        maxPitch = note.Pitch;
                    }
                }
                break;

                case EventType.NoteOff:
                {
                    int channel = (int)fstev.Params[0];
                    int noteNum = (int)fstev.Params[1];

                    Dictionary <int, SMFNote> noteNums;
                    if (channels.ContainsKey(channel))
                    {
                        noteNums = channels[channel];
                    }
                    else
                    {
                        noteNums = new Dictionary <int, SMFNote>();
                        channels.Add(channel, noteNums);
                    }

                    SMFNote note;
                    if (noteNums.ContainsKey(noteNum))
                    {
                        note = noteNums[noteNum];

                        MusicNote n = new MusicNote();
                        n.TimeInSec = time;
                        n.Pitch     = note.Pitch;
                        n.Start     = false;
                        _points.Add(n);

                        if (note.Pitch < minPitch)
                        {
                            minPitch = note.Pitch;
                        }
                        if (note.Pitch > maxPitch)
                        {
                            maxPitch = note.Pitch;
                        }

                        noteNums.Remove(noteNum);
                    }
                }
                break;
                }

                prevTick = fstev.AbsoluteTick;
            }

            _length = time;

            ToneResult minTone = ToneAnalyzer.Analyze(minPitch, 1.0);
            ToneResult maxTone = ToneAnalyzer.Analyze(maxPitch, 1.0);

            maxTone.ToneIdx++;
            if (maxTone.ToneIdx >= 12)
            {
                maxTone.ToneIdx -= 12; maxTone.Octave++;
            }
            minTone.ToneIdx--;
            if (minTone.ToneIdx <= 0)
            {
                minTone.ToneIdx += 12; minTone.Octave--;
            }

            MinPitch = ToneAnalyzer.PitchFromTone(minTone.ToneIdx, minTone.Octave);
            MaxPitch = ToneAnalyzer.PitchFromTone(maxTone.ToneIdx, maxTone.Octave);

            _points.Sort((MusicNote n1, MusicNote n2) =>
            {
                if (n1.TimeInSec != n2.TimeInSec)
                {
                    return(n1.TimeInSec.CompareTo(n2.TimeInSec));
                }
                if (n1.Start)
                {
                    if (n2.Start)
                    {
                        return(0);
                    }
                    return(1);
                }
                else
                {
                    if (n2.Start)
                    {
                        return(-1);
                    }
                    return(0);
                }
            });
        }
Exemple #5
0
        private TrackEvent readMidiEvent(byte statusByte, byte prevStatusByte, BinaryReader reader, out uint readDataSize)
        {
            readDataSize = 2;

            byte param1 = 0;
            byte param2 = 0;

            bool runningStatus = (statusByte & 0x80) == 0;
            if (runningStatus)
            {
                param1 = statusByte;
                statusByte = prevStatusByte;
                readDataSize--;
            }
            else
            {
                param1 = reader.ReadByte();
            }

            int channel = (statusByte & 0x0f);
            switch (statusByte >> 4)
            {
                case 0x8: // SMFNote Off
                    {
                        param2 = reader.ReadByte();
                        readDataSize++;

                        int noteNum = param1 & 0x7f;
                        int velocity = param2 & 0x7f;

                        TrackEvent ev = new TrackEvent();
                        ev.EventType = EventType.NoteOff;
                        ev.Params = new object[] { channel, noteNum, velocity };
                        return ev;
                    }
                case 0x9: // SMFNote On
                    {
                        param2 = reader.ReadByte();
                        readDataSize++;

                        int noteNum = param1 & 0x7f;
                        int velocity = param2 & 0x7f;

                        TrackEvent ev = new TrackEvent();
                        ev.EventType = velocity == 0 ? EventType.NoteOff : EventType.NoteOn;
                        ev.Params = new object[] { channel, noteNum, velocity };
                        return ev;
                    }
                case 0xa: // Polyphonic Key Pressure (Aftertouch)
                    {
                        param2 = reader.ReadByte();
                        readDataSize++;

                        int noteNum = param1 & 0x7f;
                        int amount = param2 & 0x7f;
                    }
                    break;
                case 0xb: // Control Change
                    {
                        param2 = reader.ReadByte();
                        readDataSize++;

                        int noteNum = param1 & 0x7f;
                        int amount = param2 & 0x7f;
                    }
                    break;
                case 0xc: // Program Change
                    {
                        int programNum = param1 & 0x7f;
                    }
                    break;
                case 0xd: // Channel Pressure (After-touch)
                    {
                        int amount = param1 & 0x7f;
                    }
                    break;
                case 0xe: // Pitch Wheel Change
                    {
                        param2 = reader.ReadByte();
                        readDataSize++;

                        int value = param1 + param2 << 7;
                    }
                    break;
            }

            return null;
        }