Beispiel #1
0
        // Назначение: создавать список: нота/длительность.
        // Параметры: массив структур блоков, каждый из которых содержит массив структур событий; количество блоков.
        public ArrayList СreateNotesArray(MIDIMTrkStruct[] arrayST, int arrayCount)
        {
            ArrayList arrayChannelNote = new ArrayList();                                                      // Массив каналов.

            for (int indexBlock = 0; indexBlock < arrayCount; indexBlock++)                                    // Проходим по всем блокам MIDI.
            {
                for (int eventArray = 0; eventArray < arrayST[indexBlock].arrayNoteStruct.Count; eventArray++) // Пробегаемся по всем событиям массива каждого канала.
                {
                    noteStruct bufferNoteST = (noteStruct)arrayST[indexBlock].arrayNoteStruct[eventArray];     // Достаем событие ноты.
                    if (bufferNoteST.flagNote == true)                                                         // Если нажимают ноту.
                    {
                        byte indexChennelNoteWrite = 0;
                        while (true)                                                                              // Перебераем каналы для записи.
                        {
                            if (indexChennelNoteWrite < arrayChannelNote.Count)                                   // Если мы еще не просмотрели все существующие каналы.
                            {
                                channelNote bufferChannel = (channelNote)arrayChannelNote[indexChennelNoteWrite]; // Достаем канал с выбранным номером.

                                if (bufferChannel.ToWriteaNewNote(bufferNoteST.roomNotes, bufferNoteST.noteTime) == true)
                                {
                                    break;                                                                                       // Если запись проша удачно - выходим.
                                }
                            }
                            else // Если свободного канала не найдено - создать новый и кинуть в него все.
                            {
                                channelNote noteNambeChannelBuffer = new channelNote(); // Канал с реальным временем предыдущего.
                                noteNambeChannelBuffer.ToWriteaNewNote(bufferNoteST.roomNotes, bufferNoteST.noteTime); // Если запись проша удачно - выходим.
                                arrayChannelNote.Add(noteNambeChannelBuffer);                                          // Добавляем канал в массив каналов.
                                break;                                                                                 // Наверняка выходим.
                            }
                            indexChennelNoteWrite++;                                                                   // Если не удалось записать - следующий канал.
                        }
                    }
                    else // Если ноту наоборот отпускают.
                    {
                        byte indexChennelNoteWrite = 0;
                        while (true)                                                                          // Перебераем каналы для записи.
                        {
                            channelNote bufferChannel = (channelNote)arrayChannelNote[indexChennelNoteWrite]; // Достаем канал с выбранным номером.
                            if (bufferChannel.EntryEndNotes(bufferNoteST.roomNotes, bufferNoteST.noteTime) == true)
                            {
                                break;                   // Если запись проша удачно - выходим.
                            }
                            indexChennelNoteWrite++;     // Если не удалось записать - следующий канал.
                        }
                    }
                }
            }
            return(arrayChannelNote);
        }
Beispiel #2
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); // Возвращаем заполненную структуру.
        }