SPLKNUTI...Vcera jsem dokoncil prevod z MODu na muj format vsech dulezitych veci. Koukal jsem, co by jeste melo smysl udelat a pridal jsem logiku, ktera pokud se hraje sampl a neni v patternu radku v MODu u nej i nastaveni hlasitosti a nastava i zmena hlasitosti vuci puvodne nastavene, tak se vezme prednastavena hlasitost pro dany sampl. Kazdy nastroj muze mit svou prednastavenou hlasitost. To ma smysl pro situaci, ze pri hrani tonu muzete pouzit i jiny efekt, ktery vam pouziti nastaveni hlasitosti neblokuje.
Zde je hlavni cast daneho kodu a priznam se, že jsem dokonce jiz u toho i musel celkem premyslet, ale ano vysledek vypada jiz jednoduse a prehedne:
Kód:
if ((y[2] & 0x0f) == 0x0e || (y[2] & 0x0f) == 0x00)
{
if ((s == 1084) || (s != 1084 && volKhraje[KzpracuvanyPRG] != prvniSetVolProSmp1az31mod[cisloSmp -1]))
{
//hlasitost z prvniSetVolProSmp1az31mod
volKhraje[KzpracuvanyPRG] = prvniSetVolProSmp1az31mod[cisloSmp -1];
switch (KzpracuvanyPRG)
{
case 0: hex0 = prvniSetVolProSmp1az31mod[cisloSmp -1] -1 << 26; break; //kanal 0
case 1: hex0 = prvniSetVolProSmp1az31mod[cisloSmp -1] -1 << 20; break; //kanal 1
case 2: hex0 = prvniSetVolProSmp1az31mod[cisloSmp -1] -1 << 14; break; //kanal 2
case 3: hex0 = prvniSetVolProSmp1az31mod[cisloSmp -1] -1 << 8; break; //kanal 3
}
sekvenceVol = sekvenceVol ^ hex0 ^ 0x1;
}
}
Pomoci hex editoru jsem se i musel podivat na samotny MOD, protoze tracker mi opet vse neukazoval. Pri nastaveni hlasitosti z prednastavene hodnoty, ktera se nachazi v MODu na zacatku mimo klasicky radek patternu trackeru prouziva MOD sve vlastni znaceni, ktere tracker Octamed neukazuje. Zatim odchytavam pro tenhle pripad hodnotu "0x0e" a nulovou hodnotu a uvidim.
Vyresil jsem i to, ze v mem formatu se nulova hodnotu hlasitosti zadava tam kde ton (tedy mimo nastaveni samotne hlasitosti). Z toho co jsem videl v C# mne nic lepsiho zatim nenapadlo. Potreboval jsem "vynulovat" vzdy 1 byte "string-u" tak jsem to udelal takhle:
Kód:
else
if ((y[3] == 0) && (volKhraje[KzpracuvanyPRG] != 255)) //uplne 1.radek paterrnu || dalsi radky patternu && jina hlasitost nez posledne nastavena?
{
volKhraje[KzpracuvanyPRG] = 255; // 255 urcuje jiz zapsanou nulovou hlasitost v sekvenceTony (hodnota 0 je pro vysledni hlasitost 1)
switch (KzpracuvanyPRG)
{
case 0: sekvenceTony = "00" + sekvenceTony.Substring(2,6); break; //kanal 0
case 1: sekvenceTony = sekvenceTony.Substring(0,2) + "00" + sekvenceTony.Substring(4,4); break; //kanal 1
case 2: sekvenceTony = sekvenceTony.Substring(0,4) + "00" + sekvenceTony.Substring(6,2); break; //kanal 2
case 3: sekvenceTony = sekvenceTony.Substring(0,6) + "00" ; break; //kanal 3
}
}
Takhle vypada vystup z terminalu:
Kód:
PS C:\WinUAE HDD\C# programovani> dotnet run
183D1B13 000080A2 1C07DFC3 000000E5 00000080 32 36 16 64 64 64 64 64 64 0 32 32 64 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
dvouciferne cisla na konci zobrazuji vsechny prednastavene hodnoty hlasitosti pro kazdy sampl v desitkove soustave.
4 byte o hodnote 1C07DFC3 jsou data pro hlasitost v kazdem radku patternu presneji 3 byte 1C07DF, tedy 6 bite pro celkove 4 hudebni kanaly. Hodnota 1C0 pro kanal 0 a 1 a hodnota 7DF pro kanal 2 a 3. Hodnota 1C0 je braná z radku patternu MODu a nastavujeme v ni hlasitost pro kanal 0. Hodnota 7DF je braná z prednastavene hlasitosti pro nastroj, tedy z dat mimo radek patternu. Binarne je to 0111 1101 1111, tedy pro kanal 2 je hodnota 011111 a pro kanal 3 hodnota 011111 co odpovida hodnote v desitkove soustave 31. Ma hudebni rutina pak tuhle hodnotu pred pouzitim zvysuje o 1, cim se dostavame na spravnou hodnotu 32. Z tech 3 cisel 32 z prednastavenych hodnot u vystupu z terminalu u 2 cifernych cisel by to meli byt prvni 2 cisla 32, hraje se nastroj 1 a B.
Kód:
1/32 2/36 3/16 4/64 5/64 6/64 7/64 8/64 9/64 A/0 B/32 C/32 D/64 - nastroj / hlasitost desitkove
Jeste mne u C# zaujalo ze v prikazu "foreach" musi byt promenna "radek2" deklarovana primo v samotnem bloku prikazu:
Kód:
foreach (byte radek2 in prvniSetVolProSmp1az31mod)
Tedy nemuzu udelat:
Kód:
byte radek2;
foreach (radek2 in prvniSetVolProSmp1az31mod)
Vnimam to jako uzsi navaznost pro vnitrne striktnejsi kod u C#.
Uvidim jestli se v kodu vyskytnou jeste nejake chyby
Cely kod:
Kód:
class Program
{
static void Main()
{
//ushort s = 1084; // pozice 1.frekvence v MODu
//ushort i; // index hrajici frekvence pro format CMR
//int i2; // index hrajiciho samplu
ushort[] oktava = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
856,808,762,720,678,640,604,570,538,508,480,453,
428,404,381,360,339,320,302,285,269,254,240,226,
214,202,190,180,170,160,151,143,135,127,120,113 };
// cislo samplu 0-3, 9 = volna pozice pro sampl
uint KzpracuvanyPRG = 0; //pro jednotlive cykly (kanal 0-3) pri nacteni dat o hrajicim SMP z MODu
// 1 2 3 4 5 6 7 8 9 10 11
uint[] prvniSetVolProSmp1az31mod = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint[] smpKprirazeniCMR = {0, 0, 0, 0, 0}; //pri nove hrajicim SMP zvyseni o 1(kanal 0-3, 4.poz.nevyuzita)
uint[] smpPoleModCmr = {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, //20 pozic
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, //20 pozic
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, //20 pozic
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; //20 pozic
uint[] smpKhraje = {9, 9, 9, 9, 9}; // kanal 0-3, 4.pozice nevyuzita
//string sekvenceSmp = "\x000000a0"; // nejnizsi byte predsekvence sampl v bitech "101"0 0000
string sekvenceTony = "";
uint sekvenceSmp = 0x000000a0; // nejnizsi byte predsekvence SMP v bitech "101"0 0000
uint sekvenceVol = 0x000000c0; // nejnizsi byte predsekvence VOL v bitech "110"0 0000
uint sekvenceArpeggio = 0x000000e0; // nejnizsi byte predsekvence ARP v bitech "111"0 0000
uint sekvencePattern = 0x00000080; // nejnizsi byte predsekvence PAT v bitech "100"0 0000
//string hex2 = string.Empty;
// 1.
// Open as binary file.
using (BinaryReader r = new BinaryReader(File.Open("Aladdin_Menu.mod", FileMode.Open)))
//FileStream fs6 = new FileStream("Aladdin.mod", FileMode.Open);
//StreamWriter r = new StreamWriter(fs6);
{
using (BinaryWriter w = new BinaryWriter(File.Open("mydata.txt", FileMode.Create)))
//FileStream fs7 = new FileStream("mydata.txt", FileMode.Create);
//StreamWriter w = new StreamWriter(fs7);
{
// Seek the required index.
ushort i; // index hrajici frekvence pro format CMR
uint perioda, hex0, cisloSmp; //perioda = format MOD, cisloSMP = format MOD
string hex1; //, sekvenceTony = "";
uint[] volKhraje = {255, 255, 255, 255};
byte radek;
uint s = 45;
for (radek = 0; radek < 31; radek++)
{
r.BaseStream.Seek(s, SeekOrigin.Begin);
{
byte[] y3 = r.ReadBytes(1);
prvniSetVolProSmp1az31mod[radek] = y3[0];
}
s = s +30;
}
s = 1084;
for (radek = 0; radek < 4; radek++)
{
r.BaseStream.Seek(s, SeekOrigin.Begin);
{
//byte[] y = r.ReadBytes(2);
byte[] y3 = r.ReadBytes(4);
uint[] y = {y3[0],y3[1],y3[2],y3[3]};
//TONY
//hex0 = y[0];
//hex0 = (int(hex0));
hex0 = y[0] << 8;
hex0 = hex0 + y[1];
perioda = hex0 & 0x0fff;
i = 1;
while (oktava[i] != perioda)
i++;
if (perioda == 0)
i = 61;
hex1 = string.Format("{0:X2}", i);
sekvenceTony = sekvenceTony + hex1;
w.Write(hex1.ToCharArray());
//SAMPLE
cisloSmp = y[0] & 0xf0;
hex0 = (y[2] & 0xf0) >> 4;
cisloSmp = cisloSmp ^ hex0;
hex0 = (KzpracuvanyPRG * 20) + cisloSmp; //index samplu
if (cisloSmp != 0)
{
if (smpPoleModCmr[hex0] == 9) //hraje se smp && bude se hrat sampl uplne poprve?
{
smpPoleModCmr[hex0] = smpKprirazeniCMR[KzpracuvanyPRG]; //ano, prirad samplu cislo ve formatu CMR
//smpKhraje[KzpracuvanyPRG] = smpKanal0az3[hex0]; //zapsat prave hrajici sampl do vybraneho kanalu
smpKprirazeniCMR[KzpracuvanyPRG] = smpKprirazeniCMR[KzpracuvanyPRG] + 1; //pro dalsi mozny-
//-sampl zvys cislo ve formatu CMR o 1
}
//Console.Write(KzpracuvanyPRG);
if (smpKhraje[KzpracuvanyPRG] != smpPoleModCmr[hex0]) //hraje se smp && "if" puvodni hrajici SMP != SMP co se ma hrat
{
smpKhraje[KzpracuvanyPRG] = smpPoleModCmr[hex0];
switch (KzpracuvanyPRG)
{
//if (KzpracuvanyPRG == 0) //kanal 0
//{
case 0:
sekvenceSmp = sekvenceSmp ^ 0x2; //aktivace bitu pro nahrani samplu pro kanal 0
hex0 = smpPoleModCmr[hex0] << 2; //bity pro cislo SMP pro kanal 0 na spravnou pozici pro sekvenci SMP
break;
case 1:
sekvenceSmp = sekvenceSmp ^ 0x0100;
hex0 = smpPoleModCmr[hex0] << 9;
break;
case 2:
sekvenceSmp = sekvenceSmp ^ 0x8000;
hex0 = smpPoleModCmr[hex0] << 12;
break;
case 3:
sekvenceVol = sekvenceVol ^ 0x2; //poslední SMP v kanalu se zpracovava v sekvenci Volume
hex0 = smpPoleModCmr[hex0] << 2;
sekvenceVol = sekvenceVol ^ hex0; //SMP pro posledni kanal se aktivuje v predsekvenci Volume!
break;
}
}
if (KzpracuvanyPRG < 3) sekvenceSmp = sekvenceSmp ^ hex0;
//if ((y[2] & 0x0f) == 0x0e && y[3] == 0xd0)
if ((y[2] & 0x0f) == 0x0e || (y[2] & 0x0f) == 0x00)
{
if ((s == 1084) || (s != 1084 && volKhraje[KzpracuvanyPRG] != prvniSetVolProSmp1az31mod[cisloSmp -1]))
{
//hlasitost z prvniSetVolProSmp1az31mod
volKhraje[KzpracuvanyPRG] = prvniSetVolProSmp1az31mod[cisloSmp -1];
switch (KzpracuvanyPRG)
{
case 0: hex0 = prvniSetVolProSmp1az31mod[cisloSmp -1] -1 << 26; break; //kanal 0
case 1: hex0 = prvniSetVolProSmp1az31mod[cisloSmp -1] -1 << 20; break; //kanal 1
case 2: hex0 = prvniSetVolProSmp1az31mod[cisloSmp -1] -1 << 14; break; //kanal 2
case 3: hex0 = prvniSetVolProSmp1az31mod[cisloSmp -1] -1 << 8; break; //kanal 3
}
sekvenceVol = sekvenceVol ^ hex0 ^ 0x1;
}
}
}
hex0 = (y[2] & 0x0f);
if ((y[2] & 0x0f) == 0x0d) // v hex je D v MOD formatu pro efekt Volume Slide, misto D muze byt i A (Protracker...)
{
if (KzpracuvanyPRG == 0)
{
sekvenceSmp = sekvenceSmp ^ 0x1; //aktivace Volume Slide pro kanal 0
if (y[3] > 15)
{ //44332211
sekvencePattern = sekvencePattern ^ 0x00000010; //zesileni hlasitosti pro Volume Slide, 0 = zeslabeni hlasitosti
hex0 = y[3] << 4; // ************************************************************************
} // *hodnota zesileni a zeslabeni Volume Slide na stejnou pozici, MOD > CMR
else hex0 = y[3] << 8; // ************************************************************************
sekvencePattern = sekvencePattern ^ hex0; // zapis hodnotu zesileni/zeslabeni pro Volume Slide
}
}
//HLASITOST + 1 SAMPL (+ 1 sampl se zpracovava v kodu vyse)
//hex0 = (y[2] & 0x0f);
else
if (hex0 == 0x0c) // v hex je C v MOD formatu pro hlasitost
{
//if ((s == 1084) || (s != 1084) && (y[3] != volKhraje[KzpracuvanyPRG])) //uplne 1.radek paterrnu || dalsi radky patternu && jina hlasitost nez posledne nastavena?
if ((s == 1084 && y[3] > 0) || (s != 1084 && y[3] > 0 && y[3] != volKhraje[KzpracuvanyPRG])) //uplne 1.radek paterrnu || dalsi radky patternu && jina hlasitost nez posledne nastavena?
{ //y[3] > 0) a hlasitost je na urovni alespon 1 a vyssi
volKhraje[KzpracuvanyPRG] = (byte)y[3]; //zapis novou uroven hlasitosti
switch (KzpracuvanyPRG)
{
case 0: hex0 = y[3] -1 << 26; break; //kanal 0
case 1: hex0 = y[3] -1 << 20; break; //kanal 1
case 2: hex0 = y[3] -1 << 14; break; //kanal 2
case 3: hex0 = y[3] -1 << 8; break; //kanal 3
}
sekvenceVol = sekvenceVol ^ hex0 ^ 0x1;
}
else
if ((y[3] == 0) && (volKhraje[KzpracuvanyPRG] != 255)) //uplne 1.radek paterrnu || dalsi radky patternu && jina hlasitost nez posledne nastavena?
{
volKhraje[KzpracuvanyPRG] = 255; // 255 urcuje jiz zapsanou nulovou hlasitost v sekvenceTony (hodnota 0 je pro vysledni hlasitost 1)
switch (KzpracuvanyPRG)
{
case 0: sekvenceTony = "00" + sekvenceTony.Substring(2,6); break; //kanal 0
case 1: sekvenceTony = sekvenceTony.Substring(0,2) + "00" + sekvenceTony.Substring(4,4); break; //kanal 1
case 2: sekvenceTony = sekvenceTony.Substring(0,4) + "00" + sekvenceTony.Substring(6,2); break; //kanal 2
case 3: sekvenceTony = sekvenceTony.Substring(0,6) + "00" ; break; //kanal 3
}
}
}
//ARPEGGIO + rychlost hrani skladby
//if (hex0 == 0x09) // v hex je 9 v MOD formatu pro rychlost hrani skladby
else
if (hex0 == 0x0f) // v hex je F/9 v MOD formatu pro rychlost hrani skladby
{
hex0 = y[3] -1; //rychlost hrani skladby -1
sekvenceArpeggio = sekvenceArpeggio ^ hex0;
}
//sekvenceArpeggio = sekvenceArpeggio ^ hex0;
else
if (hex0 == 0x0d) // v hex je D v MOD formatu pro efekt Volume Slide, misto D muze byt i A (Protracker...)
{
switch (KzpracuvanyPRG)
{
case 1: //44332211
sekvenceArpeggio = sekvenceArpeggio ^ 0x40000000; //aktivace Volume Slide kanal 1
if (y[3] > 15) //44332211
sekvenceArpeggio = sekvenceArpeggio ^ 0x80000000; //zesileni hlasitosti pro Volume Slide, 0 = zeslabeni hlasitosti
break;
case 2: //44332211
sekvenceArpeggio = sekvenceArpeggio ^ 0x00400000; //kanal 2
if (y[3] > 15) //44332211
sekvenceArpeggio = sekvenceArpeggio ^ 0x00800000;
break;
case 3: //44332211
sekvenceArpeggio = sekvenceArpeggio ^ 0x00004000; //kanal 3
if (y[3] > 15) //44332211
sekvenceArpeggio = sekvenceArpeggio ^ 0x00008000;
break;
}
if (KzpracuvanyPRG > 0)
{
if (y[3] > 15)
hex0 = y[3] << 4; // ************************************************************************
// *hodnota zesileni a zeslabeni Volume Slide na stejnou pozici, MOD > CMR
else hex0 = y[3] << 8; // ************************************************************************
sekvencePattern = sekvencePattern ^ hex0; // zapis hodnotu zesileni / zeslabeni pro Volume Slide
}
}
//PATTERN + hodtnota pro volume slide
sekvencePattern = sekvencePattern ^ 0x1; //frekvence zmeny hlasitosti ve Volume Slide MOD nema, prednastavuji zatim 0x1 = kazdy 2.cyklus (0,1)
}
s = s+4; //dalsi 4 byte z MODu pro zpracovani.
KzpracuvanyPRG = KzpracuvanyPRG + 1; // dalsi hudebni kanal pro zpracovani
}
//Console.WriteLine(sekvenceTony.Substring(0, 2) + "00" + sekvenceTony.Substring(4, 4));
Console.Write(sekvenceTony + " ");
hex1 = string.Format("{0:X8}", sekvenceSmp);
Console.Write(hex1 + " "); //sekvenceSmp
hex1 = string.Format("{0:X8}", sekvenceVol);
Console.Write(hex1 + " "); //sekvenceVol
hex1 = string.Format("{0:X8}", sekvenceArpeggio);
Console.Write(hex1 + " "); //sekvenceArpeggio
hex1 = string.Format("{0:X8}", sekvencePattern);
Console.Write(hex1+ " "); //sekvencePattern
//Console.Write(prvniSetVolProSmp1az31mod);
foreach (byte radek2 in prvniSetVolProSmp1az31mod)
{
System.Console.Write("{0} ", radek2);
}
}
}
}
}