예제 #1
0
        // Назначение: разбор главной структуры MIDI файла.
        // Параметры: Открытый FileStream поток.
        // Возвращаемой значение - заполненная структура типа MIDIheaderStruct.
        public MIDIheaderStruct CopyHeaderOfMIDIFile(MIDIReaderFile MIDIFile)
        {
            MIDIheaderStruct ST = new MIDIheaderStruct();                   // Создаем пустую структуру заголовка файла.

            ST.nameSection   = MIDIFile.ReadStringOf4byte();                // Копируем имя раздела.
            ST.lengthSection = MIDIFile.ReadUInt32BigEndian();              // Считываем 4 байта длины блока. Должно в итоге быть 0x6
            ST.mode          = MIDIFile.ReadUInt16BigEndian();              // Считываем 2 байта режима MIDI. Должно быть 0, 1 или 2.
            ST.channels      = MIDIFile.ReadUInt16BigEndian();              // Считываем 2 байта количество каналов в MIDI файле.
            ST.settingTime   = MIDIFile.ReadUInt16BigEndian();              // Считываем 2 байта параметров тактирования.
            return(ST);                                                     // Возвращаем заполненную структуру.
        }
예제 #2
0
        // Назначение: Открытие файла для чтения.
        // Параметры: путь к файлу.
        // Возвращаемое значение: успешность операции. true - успешно, false - нет.
        public bool openMIDIFile(string pathToFile)
        {
            FileStream       fileStream       = new FileStream(pathToFile, FileMode.Open, FileAccess.Read); // Открываем файл только для чтения.
            MIDIReaderFile   MIDIFile         = new MIDIReaderFile(fileStream);                             // Собственный поток для работы с MIDI файлом со спец. функциями. На основе байтового потока открытого файла.
            MIDIheaderStruct HeaderMIDIStruct = CopyHeaderOfMIDIFile(MIDIFile);                             // Считываем заголовок.

            MIDIMTrkStruct[] MTrkStruct = new MIDIMTrkStruct[HeaderMIDIStruct.channels];                    // Определяем массив для MTrkStruct.
            richTextBox1.Text += "Количество блоков: " + HeaderMIDIStruct.channels.ToString() + "\n";       // Количество каналов.
            richTextBox1.Text += "Параметры времени: " + HeaderMIDIStruct.settingTime.ToString() + "\n";
            richTextBox1.Text += "Формат MIDI: " + HeaderMIDIStruct.mode.ToString() + "\n";
            for (int loop = 0; loop < HeaderMIDIStruct.channels; loop++)
            {
                MTrkStruct[loop] = CopyMIDIMTrkSection(MIDIFile);                                // Читаем блоки MIDI файла.
            }
            outData(СreateNotesArray(MTrkStruct, HeaderMIDIStruct.channels));                    // Получаем список нота/длительность.
            return(true);
        }
예제 #3
0
        // Назначение: копирование блока MTrk (блок с событиями) из MIDI файла.
        // Параметры: поток для чтения MIDI файла.
        // Возвращает: структуру блока с массивом структур событий.
        public MIDIMTrkStruct CopyMIDIMTrkSection(MIDIReaderFile MIDIFile)
        {
            MIDIMTrkStruct ST = new MIDIMTrkStruct();          // Создаем пустую структуру блока MIDI файла.

            ST.arrayNoteStruct = new ArrayList();              // Создаем в структуре блока динамический массив структур событий клавиш.
            noteStruct bufferSTNote = new noteStruct();        // Создаем запись о новой ноте (буферная структура, будем класть ее в arrayNoteStruct).

            ST.nameSection   = MIDIFile.ReadStringOf4byte();   // Копируем имя раздела.
            ST.lengthSection = MIDIFile.ReadUInt32BigEndian(); // 4 байта длинны всего блока.
            UInt32 LoopIndex = ST.lengthSection;               // Копируем колличество оставшихся ячеек. Будем считывать события, пока счетчик не будет = 0.
            UInt32 realTime  = 0;                              // Реальное время внутри блока.

            while (LoopIndex != 0)                             // Пока не считаем все события.
            {
                // Время описывается плавающим числом байт. Конечный байт не имеет 8-го разрядка справа (самого старшего).
                byte   loopСount = 0;  // Колличество считанных байт.
                byte   buffer;         // Сюда кладем считанное значение.
                UInt32 bufferTime = 0; // Считанное время помещаем сюда.
                do
                {
                    buffer = MIDIFile.ReadByte();           // Читаем значение.
                    loopСount++;                            // Показываем, что считали байт.
                    bufferTime <<= 7;                       // Сдвигаем на 7 байт влево существующее значенеи времени (Т.к. 1 старший байт не используется).
                    bufferTime  |= (byte)(buffer & (0x7F)); // На сдвинутый участок накладываем существующее время.
                } while ((buffer & (1 << 7)) != 0);         // Выходим, как только прочитаем последний байт времени (старший бит = 0).
                realTime += bufferTime;                     // Получаем реальное время.

                buffer = MIDIFile.ReadByte(); loopСount++;  // Считываем статус-байт, показываем, что считали байт.
                // Если у нас мета-события, то...
                if (buffer == 0xFF)
                {
                    buffer     = MIDIFile.ReadByte(); // Считываем номер мета-события.
                    buffer     = MIDIFile.ReadByte(); // Считываем длину.
                    loopСount += 2;
                    for (int loop = 0; loop < buffer; loop++)
                    {
                        MIDIFile.ReadByte();
                    }
                    LoopIndex = LoopIndex - loopСount - buffer; // Отнимаем от счетчика длинну считанного.
                }

                // Если не мета-событие, то смотрим, является ли событие событием первого уровня.
                else
                {
                    switch ((byte)buffer & 0xF0)  // Смотрим по старшым 4-м байтам.
                    {
                    // Перебираем события первого уровня.

                    case 0x80:                                             // Снять клавишу.
                        bufferSTNote.channelNote  = (byte)(buffer & 0x0F); // Копируем номер канала.
                        bufferSTNote.flagNote     = false;                 // Мы отпускаем клавишу.
                        bufferSTNote.roomNotes    = MIDIFile.ReadByte();   // Копируем номер ноты.
                        bufferSTNote.dynamicsNote = MIDIFile.ReadByte();   // Копируем динамику ноты.
                        bufferSTNote.noteTime     = realTime;              // Присваеваем реальное время ноты.
                        ST.arrayNoteStruct.Add(bufferSTNote);              // Сохраняем новую структуру.
                        LoopIndex = LoopIndex - loopСount - 2;             // Отнимаем прочитанное.
                        break;

                    case 0x90:                                             // Нажать клавишу.
                        bufferSTNote.channelNote  = (byte)(buffer & 0x0F); // Копируем номер канала.
                        bufferSTNote.flagNote     = true;                  // Мы нажимаем.
                        bufferSTNote.roomNotes    = MIDIFile.ReadByte();   // Копируем номер ноты.
                        bufferSTNote.dynamicsNote = MIDIFile.ReadByte();   // Копируем динамику ноты.
                        bufferSTNote.noteTime     = realTime;              // Присваеваем реальное время ноты.
                        ST.arrayNoteStruct.Add(bufferSTNote);              // Сохраняем новую структуру.
                        LoopIndex = LoopIndex - loopСount - 2;             // Отнимаем прочитанное.
                        break;

                    case 0xA0:                                             // Сменить силу нажатия клавишы.
                        bufferSTNote.channelNote  = (byte)(buffer & 0x0F); // Копируем номер канала.
                        bufferSTNote.flagNote     = true;                  // Мы нажимаем.
                        bufferSTNote.roomNotes    = MIDIFile.ReadByte();   // Копируем номер ноты.
                        bufferSTNote.dynamicsNote = MIDIFile.ReadByte();   // Копируем НОВУЮ динамику ноты.
                        bufferSTNote.noteTime     = realTime;              // Присваеваем реальное время ноты.
                        ST.arrayNoteStruct.Add(bufferSTNote);              // Сохраняем новую структуру.
                        LoopIndex = LoopIndex - loopСount - 2;             // Отнимаем прочитанное.
                        break;

                    // Если 2-х байтовая комманда.
                    case 0xB0:  byte buffer2level = MIDIFile.ReadByte(); // Читаем саму команду.
                        switch (buffer2level)                            // Смотрим команды второго уровня.
                        {
                        default:                                         // Для определения новых комманд (не описаных).
                            MIDIFile.ReadByte();                         // Считываем параметр какой-то неизвестной функции.
                            LoopIndex = LoopIndex - loopСount - 2;       // Отнимаем прочитанное.
                            break;
                        }
                        break;

                    // В случае попадания их просто нужно считать.
                    case 0xC0:                                 // Просто считываем байт номера.
                        MIDIFile.ReadByte();                   // Считываем номер программы.
                        LoopIndex = LoopIndex - loopСount - 1; // Отнимаем прочитанное.
                        break;

                    case 0xD0:                                 // Сила канала.
                        MIDIFile.ReadByte();                   // Считываем номер программы.
                        LoopIndex = LoopIndex - loopСount - 1; // Отнимаем прочитанное.
                        break;

                    case 0xE0:                                 // Вращения звуковысотного колеса.
                        MIDIFile.ReadBytes(2);                 // Считываем номер программы.
                        LoopIndex = LoopIndex - loopСount - 2; // Отнимаем прочитанное.
                        break;
                    }
                }
            }
            return(ST); // Возвращаем заполненную структуру.
        }