Путь к истине

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Путь к истине » Программирование » Создание простого midi файла в VB6


Создание простого midi файла в VB6

Сообщений 1 страница 17 из 17

1

Столкнулся с тем, что в сети очень мало информации по созданию midi файлов.  И вообще нет информации понятной начинающим.
Решил исправить этот пробел.  Накидал программку. Она создаёт на диске тестовый миди файл, в нём всего 6 нот. Зато этот файл стабильно проигрывается любым плеером!!!
Программа состоит из одной  кнопке. При нажатии на которую три массива данных записываются поочереди в файл.
Я специально данные разделил на три массива, о каждом я расскажу отдельно!
Так как массивы байтовые, то я их в шеснадцатиричной форме оформил, для наглядности!

Код:
Option Base 1
Dim FilePath As String
Dim mm1, mm2, mm3 As Variant


Private Sub Command1_Click()
Dim NumFile As Integer
Dim i As Long, LFile As Long
Dim s As String
On Error GoTo wyhod
NumFile = FreeFile
Open FilePath For Binary As #NumFile
LFile = FileLen(FilePath)
For i = 1 To UBound(mm1)
Put #NumFile, LFile + i, CByte(mm1(i))
Next
Close #NumFile
Open FilePath For Binary As #NumFile
LFile = FileLen(FilePath)
For i = 1 To UBound(mm2)
Put #NumFile, LFile + i, CByte(mm2(i))
Next
Close #NumFile
Open FilePath For Binary As #NumFile
LFile = FileLen(FilePath)
For i = 1 To UBound(mm3)
Put #NumFile, LFile + i, CByte(mm3(i))
Next
Close #NumFile
Exit Sub
wyhod:
s = "ошибка открытия файла " & FilePath & "!"
MsgBox s, 16, "oblom"
End Sub

Private Sub Form_Load()
FilePath = "D:\0114.mid"
'Заголовок,два последних байта определяют темп!!!
mm1 = Array(&H4D, &H54, &H68, &H64, &H0, &H0, &H0, &H6, &H0, &H0, &H0, &H1, &H4, &H0)
'описание канала последний байт это инструмент в миди банке.7 и 8 байты это длина 

участка канала
mm2 = Array(&H4D, &H54, &H72, &H6B, &H0, &H0, &H0, &H55, &H0, &HFF, &H58, &H4, &H4, 

&H2, &H18, &H8, &H0, &HFF, &H59, &H2, &H0, &H0, &H0, &HFF, &H51, &H3, &H7, &HA1, &H20, 

&H0, &HC0, &H1)
'данные файла. последние 4 байта код завершения.
mm3 = Array(&H0, &H90, &H43, &H40, &H88, &H0, &H80, &H43, &H0, &H0, &H90, &H40, &H40, 

&H84, &H0, &H80, &H40, &H0, &H0, &H90, &H40, &H40, &H84, &H0, &H80, &H40, &H0, &H0, 

&H90, &H43, &H40, &H88, &H0, &H80, &H43, &H0, &H0, &H90, &H40, &H40, &H0, &H3C, &H40, 

&H84, &H0, &H80, &H40, &H0, &H0, &H90, &H40, &H40, &H84, &H0, &H80, &H40, &H0, &H0, 

&HFF, &H2F, &H0)
End Sub

0

2

Начнём с первого массива!
Он описывает стандартный хедер.
4D 54 68 64  - MThd
00 00
00 06 -длина блока заголовка
00 00 -формат=0 ( все данные в одном блоке!)
00 01 - 1 блок
04 00 - Темп
Самое сложное это темп, вернее это битрейт ( количество тиков на четверть) Подробнее по ссылке
http://cjcity.fdstar.ru/2216-MIDI_v_det … -faly.html

0

3

Второй массив это описание блока и несколько команд, без которых некоторые плееры отказываются воспроизводить, хотя крутые секвенсоры всё таки открывают.

4D 54 72 6B -MTrk
00 00 00 55 - длина всего последующего блока ( в данном случае  85 байт) Сначала записывается старший байт ( сейчас ноль) а потом младший!

00 FF 58 04 04 02 18 08 -мета команда 4 четверти, четверть на удар метронома и т.д. 
00 FF 59 02 00 00 00 FF 51 03 07 A1 20  ещё пара команд... Первая определяет текущую тональность До мажор. А вторая очень важная определяет темп, в данном случае
500000микросекунд (0,5 -секунды), то есть  темп=120 BPM (ударов в минуту)

00 C0 01 -это важная команда, без неё вообще может не проигрываться файл. -Это установка инструмента из миди банка!!!! Последний байт номер инструмента.
список инструментов тут ! (при записи инструмента надо нумеровать с нуля, то есть n-1 !) http://www.7not.ru/arrange/gm_instr.phtml

0

4

Третий массив содержит  закодированные ноты. Это самая сложная часть и мало описанная в доступной форме.
Начну с того, что любое миди сообщение начинается с дельта времени, оно имеет переменную длину. Чтобы не заморачиваться в тонкостях, я всё упростил.
0 -нулевая задержка - 1 байт.
40 - шесдесят четвёртая
81 0 - тридцать вторая
82 0 -шестнадцатая
84 0 - восьмая
88  0 -четвертная
90  0 -половинная
A0 0 -целая

команда 90 - запись ноты
команда 80 снятие ноты.
Больше актуальных команд нет ( на самом деле команды есть, только не столь важные для начинающих) , всё именно с этими командами делается и с задержками.

Вот массив:

00 90 43 40 - дельта=0 взятие ноты соль первая октава( 43) высотой в 40
88 00 -четвертная
80 43 00 -снятие ноты соль
00 90 40 40 -взятие ми первой октавы
84 00 -восьмая
80 40 00- снятин
00 90 40 40 -взятие ми первой октавы
84 00 -восьмая
80 40 00 -снятие
00 90 43 40 -взятие соль первой октавы
88 00 -четвертная
80 43 00 снятие

А теперь для примера я взял двойную ноту (До +ми)

00 90  (40 40 - берётся ми) 00 - задержка 0  ( 3C 40-берётся до) (После задержки можно прописать команду 90, но и без неё работает)
84 00 -задержка восьмая
80 40 00-Снять  ми
Ноту до не снимаю, она сама глохнет, хотя по идее надо. Это всего лишь тестовый пример , не до тонкостей)
00 90 40 40  взять ми
84 00 -восьмая
80 40 00-снять
00 FF 2F 00  Команда конца блока!!! Обязательная!!!
Ну вот я показал как делать ноты основных длительностей и двойные ноты. В общем для начинающих этого достаточно, чтобы написать простенький нотный редактор.
Или программу которая генерирует простые мелодии, например для обучалок . У меня была идея написать композитор на фрактальных функциях, возможно когда нибудь реализую.

0

5

Немного о паузах, так как без пауз музыку серьёзную не напишеш!
На самом деле создавать паузу элементарно, просто после снятия ноты прописываем задержку!
Вот пример:
00 90 40 40 -взятие ми первой октавы
84 00 -восьмая
80 40 00 -снятие
84 00-восьмя пауза 90 43 40 -взятие соль первой октавы
как видим пауза входит в дельту команды взятия ноты!
Вот и всё и никакого волшебства)))

P.S
Любая нота с высотой 00 - пауза!!!

0

6

Совсем забыл. НОТЫ имеют обозначения от 0 до 127
в шеснадцатиричном виде это от 0 до 7F
3C -до первой октавы.
Номера меняются каждые пол тона, тоесть до диез будет -3D, а ре -3E и т.д.

вот таблица в десятиричном виде http://webhamster.ru/mytetrashare/index … vkmqs7k7ig

http://se.uploads.ru/t/31xVj.jpg

0

7

После расчёта длины блока надо длину разложить на два байта:
Dim br As Integer  ' переменная целого типа
Dim br1, br2 As Byte  ' переменные для байтов старшего и младшего

br1 = Int(br / 256)
br2 = br - (br1 * 256)

Вот и всё)))

0

8

Дополнение!
Если нота залигована с соседним тактом, то просто указывается её длина в задержке.  например если в конце такта четвертная и в начале такта четвертная. то надо просто вставить половинную.

ВСЕ ЗАДЕРЖКИ ИЗ РАСЧЁТА БИТРЕЙТА В ЗАГОЛОВКЕ ФАЙЛА РАВНОГО 04 00 - 1024 тика в четверти.
Я выбрал такой битрейт не случайно, он очень удобный и великолепно подходит к большинству произведений, так как охватывает темп от 60 до 240.
Задержки кодированы в числа переменной длины, где старший бит показатель наличия ещё одного байта, а значащие только 7 бит.
Для примера переведу задержку четвертной ноты 88 00
В двоичном виде это
1000 1000 0000 0000
оставим семь битов у младшего байта и семь у старшего, так как старший бит это флаг.
000 1000 000 0000
отбросим первые нули и получим число 100 0000 0000
в шеснадцатиричной форме 04 00 - как видим это и есть число битрейта. - количество тиков на четверть!!!!!

Полный список задержек !
0 -нулевая задержка - 1 байт.
40 - шесдесят четвёртая
81 0 - тридцать вторая
82 0 -шестнадцатая
84 0 - восьмая
88  0 -четвертная
90  0 -половинная
A0 0 -целая

Ноты с точкой!
81 40 - тридцать вторая
83 0 -шестнадцатая
86 0 - восьмая
8C  0 -четвертная
98  0 -половинная
B0 0 -целая

Теперь в принципе всё, чтобы описать любые готы.

0

9

Доработал процедуру формирования массивов!

Код:
Private Sub Form_Load()
FilePath = "D:\0114.mid"
'Заголовок,два последних байта определяют темп!!!
mm1 = Array(&H4D, &H54, &H68, &H64, &H0, &H0, &H0, &H6, &H0, &H0, &H0, &H1, &H4, &H0)
'описание канала последний байт это инструмент в миди банке.7 и 8 байты это длина 

участка канала
mm2 = Array(&H4D, &H54, &H72, &H6B, &H0, &H0, &H0, &H55, &H0, &HFF, &H58, &H4, &H4, 

&H2, &H18, &H8, &H0, &HFF, &H59, &H2, &H0, &H0, &H0, &HFF, &H51, &H3, &H7, &HA1, &H20, 

&H0, &HC0, &H1)
'данные файла. последние 4 байта код завершения.
mm3 = Array(&H0, &H90, &H43, &H40, &H88, &H0, &H80, &H43, &H0, &H0, &H90, &H40, &H40, 

&H84, &H0, &H80, &H40, &H0, &H0, &H90, &H40, &H40, &H84, &H0, &H80, &H40, &H0, &H0, 

&H90, &H43, &H40, &H88, &H0, &H80, &H43, &H0, &H0, &H90, &H40, &H40, &H0, &H3C, &H40, 

&H84, &H0, &H80, &H40, &H0, &H0, &H90, &H40, &H40, &H84, &H0, &H80, &H40, &H0, &H0, 

&HFF, &H2F, &H0)

br = UBound(mm3) + UBound(mm2) - 8

br1 = Int(br / 256)
br2 = br - (br1 * 256)
mm2(7) = br1
mm2(8) = br2


End Sub

Теперь при изменении длины массивов автоматически прописывается его длина в 7 и 8 байты,
всё это работает если установлено в начале программы
Option Base 1

0

10

А вот массив инструментов, его можно например в список загрузить или в какой нибудь другой компонент, и выбирать нужный инструмент. А прописывать по индексу .
В данном случае прописывать инструмент надо в  массив mm2(32)

Код:
instruments = Array("AcousticGrandPiano", "BrightAcousticPiano", "ElectricGrandPiano", "HonkyTonkPiano", _
"ElectricPiano1", "ElectricPiano2", "Harpsichord", "Clavinet", "Celesta", "Glockenspiel", "MusicBox", "Vibraphone", _
"Marimba", "Xylophone", "TubularBells", "Dulcimer", "DrawbarOrgan", "PercussiveOrgan", "RockOrgan", "ChurchOrgan", "ReedOrgan", _
"Accordion", "Harmonica", "TangoAccordion", "AcousticNylonGuitar", "AcousticSteelGuitar", "JazzElectricGuitar", _
"CleanElectricGuitar", "MutedElectricGuitar", "OverdrivenGuitar", "DistortionGuitar", "GuitarHarmonics", "AcousticBass", _
"FingeredElectricBass", "PickedElectricBass", "FretlessBass", "SlapBass1", "SlapBass2", "SynthBass1", "SynthBass2", "Violin", _
"Viola", "Cello", "Contrabass", "TremoloStrings", "PizzicatoStrings", "OrchestralHarp", "Timpani", "StringEnsemble1", _
"StringEnsemble2", "SynthStrings1", "SynthStrings2", "ChoirAahs", "VoiceOohs", "SynthVoice", "OrchestraHit", "Trumpet", "Trombone", "Tuba", "MutedTrumpet", "FrenchHorn", _
"VoiceOohs", "SynthVoice", "OrchestraHit", "Trumpet", "Trombone", "Tuba", "MutedTrumpet", "FrenchHorn", "BrassSection", "SynthBrass1", "SynthBrass2", _
"SopranoSax", "AltoSax", "TenorSax", "BaritoneSax", "Oboe", "EnglishHorn", "Bassoon", "Clarinet", "Piccolo", "Flute", _
"Recorder", "PanFlute", "BlownBottle", "Shakuhachi", "Whistle", "Ocarina", "SquareLead", "SawtoothLead", "CalliopeLead", _
"ChiffLead", "CharangLead", "VoiceLead", "FifthsLead", "BassandLead", "NewAgePad", "WarmPad", "PolySynthPad", _
"ChoirPad", "BowedPad", "MetallicPad", "HaloPad", "SweepPad", "SynthFXRain", "SynthFXSoundtrack", "SynthFXCrystal", _
"SynthFXAtmosphere", "SynthFXBrightness", "SynthFXGoblins", "SynthFXEchoes", "SynthFXSciFi", "Sitar", "Banjo", "Shamisen", _
"Koto", "Kalimba", "Bagpipe", "Fiddle", "Shanai", "TinkleBell", "Agogo", "SteelDrums", "Woodblock", "TaikoDrum", _
"MelodicTom", "SynthDrum", "ReverseCymbal", "GuitarFretNoise", "BreathNoise", "Seashore", "BirdTweet", "TelephoneRing", _
"Helicopter", "Applause", "Gunshot")

0

11

При работе с миди сообщениями нужны динамические массиы, куда будут скидываться данные.
В некоторых языках программирования есть оператор push, в бейсике его к сожалению нет. Но можно написать простую функцию.

Код:
Function push(aaa() As Byte, nnn As Byte) As Byte
ReDim Preserve aaa(UBound(aaa) + 1)
aaa(UBound(aaa)) = nnn
push = 0
End Function

Первый параметр функции это любой байтовый массив , второй параметр -байт который должен добавиться в конец массива!

Перед вызовом функции уже должен быть создан динамический массив!!!
Например
Dim qwert() As Byte
и хотя бы разок применённый.
ReDim qwert(2)
qwert(1) = 12
qwert(2) = 14
числа любые могут быть , я просто для примера, вообще может не быть чисел достаточно только  ReDim qwert(2) , чтобы была верхняя граница массива!!!
для вызова функции надо ещё переменную какую-нибудь определить, например Dim tst As Byte

и вызвать функцию
tst = push(qwert(), 23)  - добавит в конец массива число 23.

0

12

Ну а теперь самое главное!
МИДИ позволяет записывать до 16 треков разными инструментами. Трек называется каналом и указывается в первых 4 битах команд! Например для первого канала
взятие ноты- 90, для второго 91, для третьего 92...и т.д.  Тоже и для снятия нот и назначенния инструмента из банка миди.

Всё можно описывать и в простом формате файла с одним блоком, но это муторно. Проще для каждого канала свой блок сделать. Для этого в хедере меняем байт формата на 1 , и устанавливаем нужное число блоков.
Я сделал пробный файл из двук треков, один пивнино, другой  виола.  В первом треке до четвертная, затем ре половинная и ми четвертная, а во втором треке до, ре , ми, фа -все четвертные.
В файле описал не два, а три блока!  Первый блок вынес для мета команд, чтобы не путать метаданные с данными записи нот! Это очень удобно, хотя метаданные можно засунуть в начало любого трека и создавать блок не обязательно, я это сделал для наглядности!!!
Вот листинг файла.
4D 54 68 64 00 00 00 06 00 01 00 03 04 00 хедер файл типа 1, 3 блока, битрейт 04 00.

4D 54  72 6B 00 00 00 13 хедер первого блока
00 FF 58 04 04 02 18 08 00 FF 51 03 07 A1 20 -метакоманды
00 FF 2F 00 -конец блока
4D 54 72 6B 00 00 00 22 хедер второго блока
00 C0 01 -инструмент пиано
00 90 3C 40 88 00 80 3C 00 00 90 3E 
40 90 00 80 3E 00 00 90 40 40 88 00 80 40 00 00 
FF 2F 00 -конец блока
4D 54 72 6B 00 00 00 2B хедер третьего блока
00 C1 28 -инструмент виола
00 91  3C 40 88 00 81 3C 00 00 91 3E 40 88 00 81 3E 00 
00 91 40 40 88 00 81 40 00 00 91 41 40 88 00 81  41 00
00 FF 2F 00   конец блока

0

13

Ну вот в общем тема расскрыта, теперь можно в принципе многоканальный  нотный редактор написать.
Конечно ещё есть много команд, и разных тонкостей, но всё это используется довольно редко. Если что-то интересное попадётся, то опишу.

0

14

В предыдущих постах я описал то, как создать простой миди файл, по сути просто ноты переписать в коды.
Но Миди формат может значительно больше. И всем этим управляет команда из трёх байт. Первый байт -B0 , второй байт номер контроллера , например 01 ( модуляция) , третий байт значение, например 7A .
Из контролеров наиболее часто используют 01( Modulation Wheel or Lever) и 02 ( Breath Controller)
Полный список https://www.midi.org/specifications/ite … ta-bytes-2
Каждый канал может иметь свои команды контроллеров, B0, B1 ,B2...BF.
На самом деле общей стандартизации контроллеров нет, так что в разные программы, или даже одинаковые но на разных компах могут проигрывать мидишки  по разному.
Я протестировал контроллеры с номерами 01, 02, 06  на двух компах с разными звуковыми картами , на трёх разных программах. Всё в принципе сошлось. Так что эти контроллеры надёжные.

0

15

А сейчас извеняюсь, но я буду использовать не VB, а freePascal.
Выкладываю сырую процедуру из моей проги. которая переводит паттерны формата нота - длительность. Если пауза, то ноль - длительность, и конечный байт 255, в
миди последовательность.

Код:
procedure TForm1.pattmass(channum: integer; var chann0: brt);//  патерн транслирует в миди
var
   basis1:integer;
   lenm: integer;
   flag1: integer;
begin
 lenm := channum- 1;
 flag1:= 0;
 if (channum= 1) then basis1 :=0;
 if (channum= 2) then basis1 :=33;
 if (channum= 3) then basis1 :=66;
 if (channum= 4) then basis1 :=99;
 while (accpatt[basis1]) <>255 do
 begin
     case accpatt[basis1] of
     0: begin
           if  (accpatt[basis1+1]=0)  then
                    begin
                    SetLength(chann0,length(chann0)+2);
                    chann0[length(chann0)-2]:= $A0;
                    chann0[length(chann0)-1]:= 0;
                    flag1:= 1;
                    end;
           if   (accpatt[basis1+1]=2)  then
                    begin
                    SetLength(chann0,length(chann0)+2);
                    chann0[length(chann0)-2]:= $90;
                    chann0[length(chann0)-1]:= 0;
                    flag1:= 1;
                    end;
             if  (accpatt[basis1+1]=4)  then
                    begin
                    SetLength(chann0,length(chann0)+2);
                    chann0[length(chann0)-2]:= $88;
                    chann0[length(chann0)-1]:= 0;
                    flag1:= 1;
                    end;
              if  (accpatt[basis1+1]=8)  then
                    begin
                    SetLength(chann0,length(chann0)+2);
                    chann0[length(chann0)-2]:= $84;
                    chann0[length(chann0)-1]:= 0;
                    flag1:= 1;
                    end;
              if  (accpatt[basis1+1]=16)  then
                    begin
                    SetLength(chann0,length(chann0)+2);
                    chann0[length(chann0)-2]:= $82;
                    chann0[length(chann0)-1]:= 0;
                    flag1:= 1;
                    end;
              basis1:= basis1+2;
               end;
         255:  lenm := 0;
        else
         if (flag1= 1) then
                    begin
                    SetLength(chann0,length(chann0)+8);
                    chann0[length(chann0)-8]:= lenm+144;
                    chann0[length(chann0)-7]:= accpatt[basis1];
                    chann0[length(chann0)-6]:= $40;
                    if  (accpatt[basis1+1]=0)  then
                    begin

                    chann0[length(chann0)-5]:= $A0;
                    chann0[length(chann0)-4]:= 0;
                    flag1:= 0;
                    end;
                    if  (accpatt[basis1+1]=2)  then
                    begin

                    chann0[length(chann0)-5]:= $90;
                    chann0[length(chann0)-4]:= 0;
                    flag1:= 0;
                    end;
                    if  (accpatt[basis1+1]=4)  then
                    begin

                    chann0[length(chann0)-5]:= $88;
                    chann0[length(chann0)-4]:= 0;
                    flag1:= 0;
                    end;
                    if  (accpatt[basis1+1]=8)  then
                    begin

                    chann0[length(chann0)-5]:= $84;
                    chann0[length(chann0)-4]:= 0;
                    flag1:= 0;
                    end;
                    if  (accpatt[basis1+1]=16)  then
                    begin

                    chann0[length(chann0)-5]:= $82;
                    chann0[length(chann0)-4]:= 0;
                    flag1:= 0;
                    end;
                    chann0[length(chann0)-3]:= lenm+128;
                    chann0[length(chann0)-2]:= accpatt[basis1];
                    chann0[length(chann0)-1]:= 0;
                     basis1:= basis1+2;
                    end
                  else
                    begin
                    SetLength(chann0,length(chann0)+9);
                    chann0[length(chann0)-9]:= 0;
                    chann0[length(chann0)-8]:= lenm+144;
                    chann0[length(chann0)-7]:= accpatt[basis1];
                    chann0[length(chann0)-6]:= $40;
                    if  (accpatt[basis1+1]=0)  then
                    begin

                    chann0[length(chann0)-5]:= $A0;
                    chann0[length(chann0)-4]:= 0;
                    flag1:= 0;
                    end;
                    if  (accpatt[basis1+1]=2)  then
                    begin

                    chann0[length(chann0)-5]:= $90;
                    chann0[length(chann0)-4]:= 0;
                    flag1:= 0;
                    end;
                    if  (accpatt[basis1+1]=4)  then
                    begin

                    chann0[length(chann0)-5]:= $88;
                    chann0[length(chann0)-4]:= 0;
                    flag1:= 0;
                    end;
                    if  (accpatt[basis1+1]=8)  then
                    begin

                    chann0[length(chann0)-5]:= $84;
                    chann0[length(chann0)-4]:= 0;
                    flag1:= 0;
                    end;
                    if  (accpatt[basis1+1]=16)  then
                    begin

                    chann0[length(chann0)-5]:= $82;
                    chann0[length(chann0)-4]:= 0;
                    flag1:= 0;
                    end;
                    chann0[length(chann0)-3]:= lenm+128;
                    chann0[length(chann0)-2]:= accpatt[basis1];
                    chann0[length(chann0)-1]:= 0;
                     basis1:= basis1+2;
                    end;

0

16

чуток не влезла, но там всё и так понятно.
Немного объясню что к чему.
процедура работает с глобальным масивом accpatt который разделён на 4 части по 33 байта. Не буду пояснять для чего это. просто не обращайте внимание, можно использовать любой массив, любой длины, в нём
должен быть патерн. который надо транслировать.
В процедуру передаётся  динамический массив, ( у меня ещё выбор между 4 массивами, но опять же это надо в моей программе).
Массив должен описываться в разделе типа, у меня тип описывается:  brt = array of byte;  // Байт Рекорд Тайп)))   
в процедуре есть флаг канала ( у вас может быть только один канал, если мили простой.  И флаг первого нуля, он определяет вписывать ноль или задержку паузы.
Ну а дальше система выбора.
Эта процедура немного не полноценная. так как надо флаг сделать глобальной переменной, и добавить задержки для нот с точкой ( выше я давал таблицу задержек при темпе $4,$0.
Есть ещё некоторые неловкости. но легко устранимые с добавлеием ещё парочки флагов и небольшой процедурки со сравнениями или выбором. Но в моей программе обошлось без этого.
А вот ещё сопутствующая процедурка, она патерн из строки парсит и раскладывет в массив.

Код:
procedure TForm1.parspatt(qqq: integer; patt: string);  // расскладывает стринг на числа
var
 posstart, i, n: Integer;
begin
  posstart:=0;
   n:= 0;
   i:= qqq;

repeat
 if posstart = length(patt)+1 then break;
    n:=0;
      posstart:= posstart+1;
    while Copy(patt, posstart, 1)<>','  do
      begin
      if posstart = length(patt)+1 then break;
      posstart:= posstart+1;
      n:=n+1;
      end;
       accpatt[i]:= StrToInt(Copy(patt, posstart-n,n));
       i:= i+ 1;
until false;
end;

в процедурке есть излишества связанные именно с моей прогой, мне лень переделывать чисто для форума, у меня сейчас много работы и уже нет на это моральных сил. так что извеняйте, здесь нет ничего сложного.

0

17

Переписал процедуру формирования миди трека. Она стала на треть короче. И нет теперь ограничений по паузам в конце такта, но  сама мидишка теперь получается длинее... Но это не критично)))

Код:
procedure TForm1.pattmass(channum: integer; var chann0: brt);//  патерн транслирует в миди
var
   basis1:integer;
   lenm: integer;
begin
 lenm := channum- 1;
 if (channum= 1) then basis1 :=0;
 if (channum= 2) then basis1 :=33;
 if (channum= 3) then basis1 :=66;
 if (channum= 4) then basis1 :=99;
 while (accpatt[basis1]) <>255 do
 begin
     case accpatt[basis1] of
     0: begin
                         SetLength(chann0,length(chann0)+9);
                         chann0[length(chann0)-9]:= 0;
                         chann0[length(chann0)-8]:= lenm+144;
                         chann0[length(chann0)-7]:= $40;
                         chann0[length(chann0)-6]:= $00;
                         if  (accpatt[basis1+1]=0)  then
                         begin

                         chann0[length(chann0)-5]:= $A0;
                         chann0[length(chann0)-4]:= 0;
                         end;
                         if  (accpatt[basis1+1]=2)  then
                         begin

                         chann0[length(chann0)-5]:= $90;
                         chann0[length(chann0)-4]:= 0;
                         end;
                         if  (accpatt[basis1+1]=3)  then
                         begin

                         chann0[length(chann0)-5]:= $98;
                         chann0[length(chann0)-4]:= 0;
                         end;
                         if  (accpatt[basis1+1]=4)  then
                         begin

                         chann0[length(chann0)-5]:= $88;
                         chann0[length(chann0)-4]:= 0;
                         end;
                         if  (accpatt[basis1+1]=5)  then
                         begin

                         chann0[length(chann0)-5]:= $8C;
                         chann0[length(chann0)-4]:= 0;
                         end;
                         if  (accpatt[basis1+1]=8)  then
                         begin

                         chann0[length(chann0)-5]:= $84;
                         chann0[length(chann0)-4]:= 0;
                         end;
                          if  (accpatt[basis1+1]=9)  then
                         begin

                         chann0[length(chann0)-5]:= $86;
                         chann0[length(chann0)-4]:= 0;
                         end;
                         if  (accpatt[basis1+1]=16)  then
                         begin

                         chann0[length(chann0)-5]:= $82;
                         chann0[length(chann0)-4]:= 0;
                         end;
                         chann0[length(chann0)-3]:= lenm+128;
                         chann0[length(chann0)-2]:= $40;
                         chann0[length(chann0)-1]:= 0;
                          basis1:= basis1+2;
               end;
         255:  lenm := 0;
        else
                    begin
                    SetLength(chann0,length(chann0)+9);
                    chann0[length(chann0)-9]:= 0;
                    chann0[length(chann0)-8]:= lenm+144;
                    chann0[length(chann0)-7]:= accpatt[basis1];
                    chann0[length(chann0)-6]:= $40;
                    if  (accpatt[basis1+1]=0)  then
                    begin

                    chann0[length(chann0)-5]:= $A0;
                    chann0[length(chann0)-4]:= 0;
                    end;
                    if  (accpatt[basis1+1]=2)  then
                    begin

                    chann0[length(chann0)-5]:= $90;
                    chann0[length(chann0)-4]:= 0;
                    end;
                    if  (accpatt[basis1+1]=3)  then
                    begin

                    chann0[length(chann0)-5]:= $98;
                    chann0[length(chann0)-4]:= 0;
                    end;
                    if  (accpatt[basis1+1]=4)  then
                    begin

                    chann0[length(chann0)-5]:= $88;
                    chann0[length(chann0)-4]:= 0;
                    end;
                     if  (accpatt[basis1+1]=5)  then
                    begin

                    chann0[length(chann0)-5]:= $8C;
                    chann0[length(chann0)-4]:= 0;
                    end;
                    if  (accpatt[basis1+1]=8)  then
                    begin

                    chann0[length(chann0)-5]:= $84;
                    chann0[length(chann0)-4]:= 0;
                    end;
                     if  (accpatt[basis1+1]=9)  then
                    begin

                    chann0[length(chann0)-5]:= $86;
                    chann0[length(chann0)-4]:= 0;
                    end;
                    if  (accpatt[basis1+1]=16)  then
                    begin

                    chann0[length(chann0)-5]:= $82;
                    chann0[length(chann0)-4]:= 0;
                    end;
                    chann0[length(chann0)-3]:= lenm+128;
                    chann0[length(chann0)-2]:= accpatt[basis1];
                    chann0[length(chann0)-1]:= 0;
                     basis1:= basis1+2;
                    end;

        end;
     end;

end;

Кстати прописал ноты с точкой!!!

0


Вы здесь » Путь к истине » Программирование » Создание простого midi файла в VB6