Генератор стилей акордов Midi
Сообщений 1 страница 18 из 18
Поделиться22021-08-20 06:50:04
Это старый проект, который несколько лет пролежал в столе, так как были трудности , с которыми не было в тот момент возможности разобраться.
Но время идёт, и потихоньку нащупал подход к решению проблемных вопросов.
Первую часть связанную со стилями аккордов решил, теперь нет ограничений по нотам с точкой и паузам в конце тактов.
Скоро приступлю ко второй части, алгоритмам формирования Соло трека. Вернее будет несколько алгоритмов на выбор, часть алгоритмов уже продумана,
так что всё это появится довольно скоро. А пока коды того, что есть, генератора стилей по паттернам.
Прогу пишу в Lazarus.
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
LCLProc, LazUTF8;
type
brt = array of byte; // Байт Рекорд Тайп)))
{ TForm1 }
TForm1 = class(TForm)
Button2: TButton;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
CheckBox3: TCheckBox;
CheckBox4: TCheckBox;
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
ListBox1: TListBox;
ListBox2: TListBox;
ListBox3: TListBox;
ListBox4: TListBox;
ListBox5: TListBox;
ListBox6: TListBox;
ListBox7: TListBox;
SaveDialog1: TSaveDialog;
procedure fourtime1();
procedure fourtime2();
procedure fourtime3();
procedure fourtime4();
procedure formacc();
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure parspatt(qqq: integer; patt: string);
procedure pattmass(channum: integer; var chann0: brt);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
accpatt: array[0..140] of integer; //массив паттерна аккорда
chann1:brt; // канал тоники
chann2:brt; // канал субдоминанты
chann3:brt; // канал доминанты
chann4:brt; // канал мелодии
chann5: array[0..46] of byte = ($4D, $54, $68, $64, $0, $0, $0, $6, $0, $1, $0, $5, $4, $0, $4D, $54, $72, $6B, $0, $0, $0, $19, $0, $FF, $58, $4, $4, $2, $18, $8, $0, $FF, $59, $2, $0, $0, $0, $FF, $51, $3, $7, $A1, $20, $0, $FF, $2F, $0);
// служебный канал миди файла и заголовок.
tonika1: byte;
subdomin1: byte;
domin1: byte;
tonika2: byte;
subdomin2: byte;
domin2: byte;
tonika3: byte;
subdomin3: byte;
domin3: byte;
tonika4: byte;
subdomin4: byte;
domin4: byte;
FileWork: string;
Поделиться32021-08-20 06:58:08
accpatt: array[0..140] of integer; //массив паттерна аккорда -
в этом масиве формируются треки, по структуре нота- длительность.
конец трека -255
пауза - 0
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.formacc; //формирует ноты для 4 аккордов
var
ffl1: byte;
ffl2: byte;
ffl3: byte;
ffl4: byte;
begin
tonika1 := ListBox1.ItemIndex + 45;
tonika2 := ListBox2.ItemIndex + 45;
tonika3 := ListBox3.ItemIndex + 45;
tonika4 := ListBox4.ItemIndex + 45;
if (CheckBox1.Checked = False) then ffl1:=0
else ffl1:=1;
if (CheckBox2.Checked = False) then ffl2:=0
else ffl2:=1;
if (CheckBox3.Checked = False) then ffl3:=0
else ffl3:=1;
if (CheckBox4.Checked = False) then ffl4:=0
else ffl4:=1;
subdomin1:= tonika1+4 - ffl1;
subdomin2:= tonika2+4 - ffl2;
subdomin3:= tonika3+4 - ffl3;
subdomin4:= tonika4+4 - ffl4;
domin1:= tonika1+7;
domin2:= tonika2+7;
domin3:= tonika3+7;
domin4:= tonika4+7;
end;
procedure TForm1.fourtime1;
var
nn4: integer;
begin
parspatt(0,ListBox5.Items[ListBox5.ItemIndex]);
parspatt(33,ListBox6.Items[ListBox6.ItemIndex]);
parspatt(66,ListBox7.Items[ListBox7.ItemIndex]);
parspatt(99,'1,4,1,4,1,4,1,4,255');
for nn4:= 0 to 32 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= tonika1;
end;
for nn4:= 33 to 65 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= subdomin1;
end;
for nn4:= 66 to 98 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= domin1;
end;
accpatt[99]:= 0;
accpatt[101]:= 0;
accpatt[103]:= 0;
accpatt[105]:= 0;
//accpatt[99]:= tonika1;
//accpatt[101]:= subdomin1;
//accpatt[103]:= domin1;
//accpatt[105]:= subdomin1;
end;
procedure TForm1.fourtime2;
var
nn4: integer;
begin
parspatt(0,ListBox5.Items[ListBox5.ItemIndex]);
parspatt(33,ListBox6.Items[ListBox6.ItemIndex]);
parspatt(66,ListBox7.Items[ListBox7.ItemIndex]);
parspatt(99,'1,4,1,4,1,4,1,4,255');
for nn4:= 0 to 32 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= tonika2;
end;
for nn4:= 33 to 65 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= subdomin2;
end;
for nn4:= 66 to 98 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= domin2;
end;
accpatt[99]:= 0;
accpatt[101]:= 0;
accpatt[103]:= 0;
accpatt[105]:= 0;
//accpatt[99]:= tonika1;
//accpatt[101]:= subdomin1;
//accpatt[103]:= domin1;
//accpatt[105]:= subdomin1;
end;
Поделиться42021-08-20 07:06:23
Под subdomin1 имеется вв виду не субдоминанта, а всего лишь третья ступень тональности.
Назвал субдоминантой чисто из удобства (между тоникой и доминантой).
Объясняю это для любителей теории музыки, которые будут цепляться к словам.
Теория конечно будет, но уже на следующей стадии разработки...
procedure TForm1.fourtime3;
var
nn4: integer;
begin
parspatt(0,ListBox5.Items[ListBox5.ItemIndex]);
parspatt(33,ListBox6.Items[ListBox6.ItemIndex]);
parspatt(66,ListBox7.Items[ListBox7.ItemIndex]);
parspatt(99,'1,4,1,4,1,4,1,4,255');
for nn4:= 0 to 32 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= tonika3;
end;
for nn4:= 33 to 65 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= subdomin3;
end;
for nn4:= 66 to 98 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= domin3;
end;
for nn4:= 0 to 32 do
accpatt[99]:= 0;
accpatt[101]:= 0;
accpatt[103]:= 0;
accpatt[105]:= 0;
//accpatt[99]:= tonika1;
//accpatt[101]:= subdomin1;
//accpatt[103]:= domin1;
//accpatt[105]:= subdomin1;
end;
procedure TForm1.fourtime4;
var
nn4: integer;
begin
parspatt(0,ListBox5.Items[ListBox5.ItemIndex]);
parspatt(33,ListBox6.Items[ListBox6.ItemIndex]);
parspatt(66,ListBox7.Items[ListBox7.ItemIndex]);
parspatt(99,'1,4,1,4,1,4,1,4,255');
for nn4:= 0 to 32 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= tonika4;
end;
for nn4:= 33 to 65 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= subdomin4;
end;
for nn4:= 66 to 98 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= domin4;
end;
accpatt[99]:= 0;
accpatt[101]:= 0;
accpatt[103]:= 0;
accpatt[105]:= 0;
//accpatt[99]:= tonika1;
//accpatt[101]:= subdomin1;
//accpatt[103]:= domin1;
//accpatt[105]:= subdomin1;
end;
Поделиться52021-08-20 07:08:13
А вот собственно процедура формирования миди сообщений в каналах и запись всего в файл
procedure TForm1.Button2Click(Sender: TObject);
var
nn3, br, br1, br2: integer;
f: file of byte;
ki, ci:integer;
begin
SetLength(chann1,11);
SetLength(chann2,11);
SetLength(chann3,11);
SetLength(chann4,11);
for ci := 0 to 10 do
begin
chann1[ci]:=0;
chann2[ci]:=0;
chann3[ci]:=0;
chann4[ci]:=0;
end;
chann1[0]:=$4D;
chann2[0]:=$4D;
chann3[0]:=$4D;
chann4[0]:=$4D;
chann1[1]:=$54;
chann2[1]:=$54;
chann3[1]:=$54;
chann4[1]:=$54;
chann1[2]:=$72;
chann2[2]:=$72;
chann3[2]:=$72;
chann4[2]:=$72;
chann1[3]:=$6B;
chann2[3]:=$6B;
chann3[3]:=$6B;
chann4[3]:=$6B;
chann1[9]:=$C0;
chann2[9]:=$C1;
chann3[9]:=$C2;
chann4[9]:=$C3;
chann1[10]:=0; //пианино
chann2[10]:=0;
chann3[10]:=0;
chann4[10]:=$2A; //инструмент
If Form1.SaveDialog1.Execute then
begin
FileWork:=Utf8ToSys(Form1.SaveDialog1.FileName);
AssignFile(f, FileWork);
Rewrite(f);
end;
// AssignFile(f, 'f:\myfile.mid');
formacc;
for ki:= 1 to StrToInt(Edit1.Text) do
begin
fourtime1;
pattmass(1,chann1); // формируем массивы с миди
pattmass(2,chann2);
pattmass(3,chann3);
pattmass(4,chann4);
fourtime2;
pattmass(1,chann1);
pattmass(2,chann2);
pattmass(3,chann3);
pattmass(4,chann4);
fourtime3;
pattmass(1,chann1);
pattmass(2,chann2);
pattmass(3,chann3);
pattmass(4,chann4);
fourtime4;
pattmass(1,chann1);
pattmass(2,chann2);
pattmass(3,chann3);
pattmass(4,chann4);
end;
SetLength(chann1,length(chann1)+4); //добавляем нужные байты
chann1[length(chann1)-4]:= 0;
chann1[length(chann1)-3]:= $FF;
chann1[length(chann1)-2]:= $2F;
chann1[length(chann1)-1]:= 0;
br := length(chann1)-8;
br1 := Trunc(br / 256);
br2 := br - (br1 * 256);
chann1[6]:= br1;
chann1[7]:= br2;
SetLength(chann2,length(chann2)+4);
chann2[length(chann2)-4]:= 0;
chann2[length(chann2)-3]:= $FF;
chann2[length(chann2)-2]:= $2F;
chann2[length(chann2)-1]:= 0;
br := length(chann2)-8;
br1 := Trunc(br / 256);
br2 := br - (br1 * 256);
chann2[6]:= br1;
chann2[7]:= br2;
SetLength(chann3,length(chann3)+4);
chann3[length(chann3)-4]:= 0;
chann3[length(chann3)-3]:= $FF;
chann3[length(chann3)-2]:= $2F;
chann3[length(chann3)-1]:= 0;
br := length(chann3)-8;
br1 := Trunc(br / 256);
br2 := br - (br1 * 256);
chann3[6]:= br1;
chann3[7]:= br2;
SetLength(chann4,length(chann4)+4);
chann4[length(chann4)-4]:= 0;
chann4[length(chann4)-3]:= $FF;
chann4[length(chann4)-2]:= $2F;
chann4[length(chann4)-1]:= 0;
br := length(chann4)-8;
br1 := Trunc(br / 256);
br2 := br - (br1 * 256);
chann4[6]:= br1;
chann4[7]:= br2;
for nn3:= 0 to length(chann5)-1 do //записываем миди файл
begin
write(f,chann5[nn3]);
end;
for nn3:= 0 to length(chann1)-1 do
begin
write(f,chann1[nn3]);
end;
for nn3:= 0 to length(chann2)-1 do
begin
write(f,chann2[nn3]);
end;
for nn3:= 0 to length(chann3)-1 do
begin
write(f,chann3[nn3]);
end;
for nn3:= 0 to length(chann4)-1 do
begin
write(f,chann4[nn3]);
end;
CloseFile(f);
end;
Поделиться62021-08-20 07:10:06
А дальше вспомагательные процедуры .
Сначало парсинг списков паттернов
procedure TForm1.FormCreate(Sender: TObject);
var ci:integer;
begin
ListBox5.Items.LoadFromFile('tonika.txt');
ListBox6.Items.LoadFromFile('subdomina.txt');
ListBox7.Items.LoadFromFile('domina.txt');
SetLength(chann1,11);
SetLength(chann2,11);
SetLength(chann3,11);
SetLength(chann4,11);
for ci := 0 to 10 do
begin
chann1[ci]:=0;
chann2[ci]:=0;
chann3[ci]:=0;
chann4[ci]:=0;
end;
chann1[0]:=$4D;
chann2[0]:=$4D;
chann3[0]:=$4D;
chann4[0]:=$4D;
chann1[1]:=$54;
chann2[1]:=$54;
chann3[1]:=$54;
chann4[1]:=$54;
chann1[2]:=$72;
chann2[2]:=$72;
chann3[2]:=$72;
chann4[2]:=$72;
chann1[3]:=$6B;
chann2[3]:=$6B;
chann3[3]:=$6B;
chann4[3]:=$6B;
chann1[9]:=$C0;
chann2[9]:=$C1;
chann3[9]:=$C2;
chann4[9]:=$C3;
chann1[10]:=0; //пианино
chann2[10]:=0;
chann3[10]:=0;
chann4[10]:=$2A; //инструмент
end;
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;
Поделиться72021-08-20 07:15:04
И самая важная процедура - формирование из патернов каналов с midi.
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;
end.
Ну вот пока всё. Всё работает и без косяков.
Суоро приступаю к главному -авто композитору, там будет и патерный подход и алгоритмы с разрешением в тонику или доминанту
следующего аккорда и алгоритмы на фракталах и генераторах случайных чисел.. планы и идеи великие, и это на долго)))
Поделиться82021-08-20 11:26:11
Не стал откладывать на потом. Разработал новый формат патерна для линии мелодии
Формат патерна для мелодии:
1 байт
0= пауза
44= тоника
1..43=приращение в полутонах к тонике.
2 байт длительность как в предыдущем описании
последний байт 255
Теперь осталось только научить программу генерировать паттерны в зависимости от аккордов(мажор-минор)
и разрешать в соседний патерн.
А вот новые процедуры сборки патернов.
procedure TForm1.fourtime1;
var
p1: boolean;
nn4: integer;
begin
parspatt(0,ListBox5.Items[ListBox5.ItemIndex]);
parspatt(33,ListBox6.Items[ListBox6.ItemIndex]);
parspatt(66,ListBox7.Items[ListBox7.ItemIndex]);
parspatt(99,'44,4,3,4,7,4,44,4,255');
p1:= true;
for nn4:= 0 to 32 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= tonika1;
end;
for nn4:= 33 to 65 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= subdomin1;
end;
for nn4:= 66 to 98 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= domin1;
end;
nn4:= 99;
while p1 = true do
begin
if (accpatt[nn4] = 255) then break;
if (accpatt[nn4] = 0) then
begin
accpatt[nn4]:= 0;
nn4:= nn4 + 2;
end;
if (accpatt[nn4] = 44) then
begin
accpatt[nn4]:= tonika1;
nn4:= nn4 + 2;
end
else
begin
accpatt[nn4]:= tonika1 + accpatt[nn4];
nn4:= nn4 + 2;
end;
end;
//accpatt[99]:= tonika1;
//accpatt[101]:= subdomin1;
//accpatt[103]:= domin1;
//accpatt[105]:= subdomin1;
end;
procedure TForm1.fourtime2;
var
p1: boolean;
nn4: integer;
begin
parspatt(0,ListBox5.Items[ListBox5.ItemIndex]);
parspatt(33,ListBox6.Items[ListBox6.ItemIndex]);
parspatt(66,ListBox7.Items[ListBox7.ItemIndex]);
parspatt(99,'44,4,3,4,7,4,44,4,255');
p1:= true;
for nn4:= 0 to 32 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= tonika2;
end;
for nn4:= 33 to 65 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= subdomin2;
end;
for nn4:= 66 to 98 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= domin2;
end;
nn4:= 99;
while p1 = true do
begin
if (accpatt[nn4] = 255) then break;
if (accpatt[nn4] = 0) then
begin
accpatt[nn4]:= 0;
nn4:= nn4 + 2;
end;
if (accpatt[nn4] = 44) then
begin
accpatt[nn4]:= tonika2;
nn4:= nn4 + 2;
end
else
begin
accpatt[nn4]:= tonika2 + accpatt[nn4];
nn4:= nn4 + 2;
end;
end;
//accpatt[99]:= tonika2;
//accpatt[101]:= subdomin2;
//accpatt[103]:= domin2;
//accpatt[105]:= subdomin2;
end;
procedure TForm1.fourtime3;
var
p1: boolean;
nn4: integer;
begin
parspatt(0,ListBox5.Items[ListBox5.ItemIndex]);
parspatt(33,ListBox6.Items[ListBox6.ItemIndex]);
parspatt(66,ListBox7.Items[ListBox7.ItemIndex]);
parspatt(99,'44,4,4,4,7,4,44,4,255');
p1:= true;
for nn4:= 0 to 32 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= tonika3;
end;
for nn4:= 33 to 65 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= subdomin3;
end;
for nn4:= 66 to 98 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= domin3;
end;
nn4:= 99;
while p1 = true do
begin
if (accpatt[nn4] = 255) then break;
if (accpatt[nn4] = 0) then
begin
accpatt[nn4]:= 0;
nn4:= nn4 + 2;
end;
if (accpatt[nn4] = 44) then
begin
accpatt[nn4]:= tonika3;
nn4:= nn4 + 2;
end
else
begin
accpatt[nn4]:= tonika3 + accpatt[nn4];
nn4:= nn4 + 2;
end;
end;
//accpatt[99]:= tonika3;
//accpatt[101]:= subdomin3;
//accpatt[103]:= domin3;
//accpatt[105]:= subdomin3;
end;
Поделиться92021-08-20 11:28:15
немного там не влезло)))
procedure TForm1.fourtime4;
var
p1: boolean;
nn4: integer;
begin
parspatt(0,ListBox5.Items[ListBox5.ItemIndex]);
parspatt(33,ListBox6.Items[ListBox6.ItemIndex]);
parspatt(66,ListBox7.Items[ListBox7.ItemIndex]);
parspatt(99,'44,4,3,4,7,4,44,4,255');
p1:= true;
for nn4:= 0 to 32 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= tonika4;
end;
for nn4:= 33 to 65 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= subdomin4;
end;
for nn4:= 66 to 98 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= domin4;
end;
nn4:= 99;
while p1 = true do
begin
if (accpatt[nn4] = 255) then break;
if (accpatt[nn4] = 0) then
begin
accpatt[nn4]:= 0;
nn4:= nn4 + 2;
end;
if (accpatt[nn4] = 44) then
begin
accpatt[nn4]:= tonika4;
nn4:= nn4 + 2;
end
else
begin
accpatt[nn4]:= tonika4 + accpatt[nn4];
nn4:= nn4 + 2;
end;
end;
//accpatt[99]:= tonika4;
//accpatt[101]:= subdomin4;
//accpatt[103]:= domin4;
//accpatt[105]:= subdomin4;
end;
Поделиться102021-08-20 15:12:20
Маленькое дополнение.
Ввёл распределение паттернов по минор-мажор.
Осталось только прописать генераторы паттернов, алгоритмов и задумок много)))
procedure TForm1.fourtime1;
var
p1: boolean;
nn4: integer;
begin
minorpatt:= '44,4,3,4,7,4,44,4,255';
majorpatt:= '44,4,4,4,7,4,44,4,255';
if (ffl1 = 0) then parspatt(99,majorpatt);
if (ffl1 = 1) then parspatt(99,minorpatt);
parspatt(0,ListBox5.Items[ListBox5.ItemIndex]);
parspatt(33,ListBox6.Items[ListBox6.ItemIndex]);
parspatt(66,ListBox7.Items[ListBox7.ItemIndex]);
p1:= true;
for nn4:= 0 to 32 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= tonika1;
end;
for nn4:= 33 to 65 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= subdomin1;
end;
for nn4:= 66 to 98 do
begin
if (accpatt[nn4] = 1) then accpatt[nn4]:= domin1;
end;
nn4:= 99;
while p1 = true do
begin
if (accpatt[nn4] = 255) then break;
if (accpatt[nn4] = 0) then
begin
accpatt[nn4]:= 0;
nn4:= nn4 + 2;
end;
if (accpatt[nn4] = 44) then
begin
accpatt[nn4]:= tonika1;
nn4:= nn4 + 2;
end
else
begin
accpatt[nn4]:= tonika1 + accpatt[nn4];
nn4:= nn4 + 2;
end;
end;
//accpatt[99]:= tonika1;
//accpatt[101]:= subdomin1;
//accpatt[103]:= domin1;
//accpatt[105]:= subdomin1;
end;
Поделиться112021-08-21 04:22:41
Сегодня хорошо поработал. Разнёс всё по процедурам, реализовал выбор паттернов мелодии для аккордов.
Сделал кнопочку, чтобы прослушать в программе созданную мидишку.
procedure TForm1.Button1Click(Sender: TObject);
begin
mciSendString(PChar('open "' + FileWork + '" alias mySound wait'), nil, 0, 0);
mciSendString(PChar('play mySound wait') , nil, 0, 0);
mciSendString(PChar('close mySound wait') , nil, 0, 0);
end;
Поделиться132021-08-21 10:50:35
А вот и первый алгоритм.
Он заключается в анализе последующей тоники.
Если разница между тониками больше или равна двум тонам , то предыдущий аккорд заканчивается на третьей ступени!
Алгоритм понимает разницу между минор-мажором.
После более 20 проверок нареканий к алгоритму нет, на некоторых паттернах он дал на удивление интерессный результат. Так что именно этот алгоритм остаётся в еоробке!
formmgpatt(gpatt1);//паттерн в массив
gpatt1:= '';
if (CheckBox5.Checked = False) then jk:=0
else jk:=1;
if (ffl1 = 0) then f1:= 4
else f1:= 3;
if (ffl3 = 0) then f3:= 4
else f3:= 3;
if (tonika1 < tonika2)then
swap:= tonika2 - tonika1
else
swap:= tonika1 - tonika2 ;
for nnc:= 0 to 32 do // Алгоритм изменения паттерна
begin
if((mgpatt[nnc] = 255) and (jk = 1)) then
begin
if (swap >= 4) then mgpatt[nnc - 2]:= f1;
break
end
end;
for nnc:= 0 to 32 do //востанавливает паттерн мз массива
begin
if(mgpatt[nnc] = 255) then
begin
gpatt1:= gpatt1 + IntToStr(mgpatt[nnc]);
break;
end
else
gpatt1:= gpatt1 + IntToStr(mgpatt[nnc]) + ',';
end;
Edit2.Text:= gpatt1;
formmgpatt(gpatt3);//паттерн в массив
gpatt3:= '';
if (tonika3 < tonika4)then
swap:= tonika4 - tonika3
else
swap:= tonika3 - tonika4 ;
for nnc:= 0 to 32 do // Алгоритм изменения паттерна
begin
if((mgpatt[nnc] = 255) and (jk = 1)) then
begin
if(swap >= 4) then mgpatt[nnc - 2]:= f3;
break
end
end;
for nnc:= 0 to 32 do //востанавливает паттерн мз массива
begin
if(mgpatt[nnc] = 255) then
begin
gpatt3:= gpatt3 + IntToStr(mgpatt[nnc]);
break;
end
else
gpatt3:= gpatt3 + IntToStr(mgpatt[nnc]) + ',';
end;
Поделиться142021-08-21 10:51:58
procedure TForm1.formmgpatt(patt: string);//разбор паттерна
var
posstart, i, n: Integer;
begin
posstart:=0;
n:= 0;
i:= 0;
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;
mgpatt[i]:= StrToInt(Copy(patt, posstart-n,n));
i:= i+ 1;
until false;
end;
Поделиться162021-08-27 09:32:11
//ALGORITM 2
if (jk2 = 1) then
begin
formmgpatt(gpatt2);//паттерн в массив
gpatt2:= '';
if ((tonika1 - tonika2) > 3) then
mgpatt[0]:= 7;
for nnc:= 0 to 32 do //востанавливает паттерн мз массива
begin
if(mgpatt[nnc] = 255) then
begin
gpatt2:= gpatt2 + IntToStr(mgpatt[nnc]);
break;
end
else
gpatt2:= gpatt2 + IntToStr(mgpatt[nnc]) + ',';
end;
formmgpatt(gpatt4);//паттерн в массив
gpatt4:= '';
if ((tonika3 - tonika4) > 3)then
mgpatt[0]:= 7;
for nnc:= 0 to 32 do //востанавливает паттерн мз массива
begin
if(mgpatt[nnc] = 255) then
begin
gpatt4:= gpatt4 + IntToStr(mgpatt[nnc]);
break;
end
else
gpatt4:= gpatt4 + IntToStr(mgpatt[nnc]) + ',';
end;
end;
//ALGORITM 3
if (jk3 = 1) then
begin
formmgpatt(gpatt3);//паттерн в массив
gpatt3:= '';
if ((tonika2 - tonika3) > 3)then
mgpatt[0]:= 7;
for nnc:= 0 to 32 do //востанавливает паттерн мз массива
begin
if(mgpatt[nnc] = 255) then
begin
gpatt3:= gpatt3 + IntToStr(mgpatt[nnc]);
break;
end
else
gpatt3:= gpatt3 + IntToStr(mgpatt[nnc]) + ',';
end;
end;
//ALGORITM 4
if (jk4 = 1) then
begin
formmgpatt(gpatt3);//паттерн в массив
gpatt3:= '';
if ((tonika3 - tonika2) > 3)then
mgpatt[0]:= -5;
for nnc:= 0 to 32 do //востанавливает паттерн мз массива
begin
if(mgpatt[nnc] = 255) then
begin
gpatt3:= gpatt3 + IntToStr(mgpatt[nnc]);
break;
end
else
gpatt3:= gpatt3 + IntToStr(mgpatt[nnc]) + ',';
end;
end;
Label4.Caption:= gpatt1;
Label5.Caption:= gpatt2;
Label6.Caption:= gpatt3;
Label7.Caption:= gpatt4;
Поделиться172021-08-27 09:33:55
if (CheckBox5.Checked = False) then jk:=0
else jk:=1;
if (CheckBox6.Checked = False) then jk2:=0
else jk2:=1;
if (CheckBox7.Checked = False) then jk3:=0
else jk3:=1;
if (CheckBox8.Checked = False) then jk4:=0
else jk4:=1;
//ALGORITM 1
if (ffl1 = 0) then f1:= 4
else f1:= 3;
if (ffl3 = 0) then f3:= 4
else f3:= 3;
if (tonika1 < tonika2)then
swap:= tonika2 - tonika1
else
swap:= tonika1 - tonika2 ;
formmgpatt(gpatt1);//паттерн в массив
gpatt1:= '';
for nnc:= 0 to 32 do // Алгоритм изменения паттерна
begin
if((mgpatt[nnc] = 255) and (jk = 1)) then
begin
if (swap >= 4) then mgpatt[nnc - 2]:= f1;
break
end
end;
for nnc:= 0 to 32 do //востанавливает паттерн мз массива
begin
if(mgpatt[nnc] = 255) then
begin
gpatt1:= gpatt1 + IntToStr(mgpatt[nnc]);
break;
end
else
gpatt1:= gpatt1 + IntToStr(mgpatt[nnc]) + ',';
end;
formmgpatt(gpatt3);//паттерн в массив
gpatt3:= '';
if (tonika3 < tonika4)then
swap:= tonika4 - tonika3
else
swap:= tonika3 - tonika4 ;
for nnc:= 0 to 32 do // Алгоритм изменения паттерна
begin
if((mgpatt[nnc] = 255) and (jk = 1)) then
begin
if(swap >= 4) then mgpatt[nnc - 2]:= f3;
break
end
end;
for nnc:= 0 to 32 do //востанавливает паттерн мз массива
begin
if(mgpatt[nnc] = 255) then
begin
gpatt3:= gpatt3 + IntToStr(mgpatt[nnc]);
break;
end
else
gpatt3:= gpatt3 + IntToStr(mgpatt[nnc]) + ',';
end;
Поделиться182021-08-27 15:31:00
Полностью функциональная версия! Писал под себя, так что для других она может показаться неудобной. В следующей версии возможно подумаю над этим.
Важно одно, при сохранении название писать только латиницей и точно пропишите расширение .mid иначе не будет проигрывать файл.
И в колличестве повторов не стоит делать больше 10 (хотя запас до сотни))))
Скачать можно с моего яндекс диска
https://disk.yandex.ru/d/5KBjQ12jtO07JQ
Приятного использования!!!
