don't click here

Music

Discussion in 'Project: Sonic Retro (Archive)' started by Retro_Stew, Nov 9, 2008.

  1. Black Squirrel

    Black Squirrel

    no reverse gear Wiki Sysop
    8,666
    2,541
    93
    Northumberland, UK
    steamboat wiki
    To be honest I think that track by muteKi sounds more like something from the Japanese Sonic CD rather than the American one

    but personally I think it could use a bit more of a in-your-face melody. It currently sounds a bit... unfinished for some reason
     
  2. muteKi

    muteKi

    Fuck it Member
    7,852
    131
    43
    Yeah, the arrangement is a bit spartan. I probably won't go back to it until I've done a couple other things first.
     
  3. Sailu Baru

    Sailu Baru

    Member
    27
    0
    0
    France
    Only Pheonix has given me an answer, so I repost my last messages (with some adds):

    I've studied the Sonics' orchestrations (on Sonic 1 & 2) and I think I got the right style down. Listen to "the Flying Circus" and please tel me what you think about it (I know I still have to change this boring end).
    http://www.everyoneweb.fr/SailuMusic/
    It's just the composition, made with Guitar Pro. I would do this music again with a better software if I was sure almost all of you enjoyed it.
    I could redo it with a software I usually use (listen "Hightech City" for an example) or with a software which emulates Genesis sounds. Do you want a cleaner and modern sound, or a old sonic-like rendering ?
     
  4. Phoenix

    Phoenix

    Has really been far even as decided to use even go Member
    Definitely the former, although you could do certain parts with the Genesis rendering. Like someone a while back in this topic said, it would be great to have the modern sounds alongside the Genesis ones.
     
  5. McGuirk

    McGuirk

    The Egg-Man Cometh. Member
    Here are some FL Studio channel presets for VOPM.

    It's mostly bass voices from Sonic 1-S3K. README details where to put them.


    Fun stuff I found when making these:

    The lead voice from Labyrinth is the exact same as the bass voice from Mystic Cave.

    The bass from Marble and Starlight are almost exactly the same (the level of Carrier 2 is altered).

    The bass from Scrap Brain and Emerald Hill are almost exactly the same (the level of Carrier 2 is altered).
     
  6. Andlabs

    Andlabs

    「いっきまーす」 Wiki Sysop
    2,175
    1
    0
    Writing my own MD/Genesis sound driver :D
    Can you convert these to FXB files so I can use them with programs other than FL Studio? If I get Windows to work, I'll find an old copy of the freeware Cubasis InWired and use it with VOPM. Thanks.
     
  7. McGuirk

    McGuirk

    The Egg-Man Cometh. Member
    Can you explain how to use FXB files? I'm still at a loss.

    That being said, I can do .OPMs, if those will work equally well (via VOPM's import/export feature).

    EDIT: Nevermind, OPM's are failing miserably, hang on a bit.
     
  8. Andlabs

    Andlabs

    「いっきまーす」 Wiki Sysop
    2,175
    1
    0
    Writing my own MD/Genesis sound driver :D
    FXB files are the standard format supported by VST. Most VST hosts use this natively to load/store banks. If FL Studio doesn't support them, I don't know what.

    How is OPM failing?

    PS - I have alternate OPM files ripped from VGZ files of the Sonic music, if you want to test then.
     
  9. McGuirk

    McGuirk

    The Egg-Man Cometh. Member
    OPM is failing because of either FLStudio or VOPM, either way, the current settings on VOPM are not being written to the .OPM file, only a default 9 channels, and a bunch of "no Name" to fill the channel list to 127. I dunno.

    I'm going to attempt to write a little program to convert .y12 dumps from Gens KMod to .OPM voice segments.
     
  10. Andlabs

    Andlabs

    「いっきまーす」 Wiki Sysop
    2,175
    1
    0
    Writing my own MD/Genesis sound driver :D
    Nine channels is all you need; the Genesis sound processor only supports six. Use this awk script to split OPM files into individual settings and drop the no name ones:

    Code (Text):
    1. # splitopm:  split opm file into one per instrument
    2. # pietro gagliardi - 6 january 2009
    3. # usage: splitopm file.opm output-directory
    4.  
    5. BEGIN {
    6.     # Change this if your OS needs it
    7.     DIR_SEPARATOR = "/"
    8.    
    9.     if (ARGC != 3) {
    10.         print "usage: " ARGV[0] " file.opm output-directory"
    11.         exit 1
    12.     }
    13.    
    14.     outdir = ARGV[2]
    15.     ARGV[2] = ""
    16.     ARGC--
    17.    
    18.     RS = ""
    19.     FS = OFS = "\n"
    20. }
    21.  
    22. /^\/\// { next }
    23. !/^@/   { print ARGV[1] ": bad input file"; exit 1 }
    24.  
    25. {
    26.     instrname = substr($1, index($1, " ") + 1)
    27.     if (tolower(instrname) == "no name")
    28.         next
    29.     oldinstrname = instrname
    30.     gsub(/[^A-Za-z0-9_]/,  "", instrname)
    31.     filename = outdir DIR_SEPARATOR instrname ".opm"
    32.     $1 = "@:0 " oldinstrname # convert to bank 0
    33.     print > filename
    34.     close(filename)
    35.     inst++
    36. }
    You may need to change the line

    Code (Text):
    1.     $1 = "@:0 " oldinstrname # convert to bank 0
    to

    Code (Text):
    1.     $1 = "@:1 " oldinstrname # convert to bank 1
    if the script doesn't result in files that can be imported, but I don't know.
     
  11. McGuirk

    McGuirk

    The Egg-Man Cometh. Member
    Sorry, I said that wrong, it outputs nine voices, and 118 "no Name" voices to a .OPM file.

    Thanks for the script though. I'm still gonna attempt to write this converter though: Out of practice freshman level C++ powers, activate!
     
  12. Andlabs

    Andlabs

    「いっきまーす」 Wiki Sysop
    2,175
    1
    0
    Writing my own MD/Genesis sound driver :D
    Well, last night I got through most of Sonic 3 & Knuckles emulated on my computer with the volume off and hummed about an hour and a half of stuff. I'll get Windows up, pick out the best, and give you some tunes soon.
     
  13. McGuirk

    McGuirk

    The Egg-Man Cometh. Member
    Alright, here's version -0.1 of the converter.

    It trashes some thing numbers that aren't visible in VOPM, and I don't know what they are, but ditching them isn't hurting anything (yet).

    If anyone encounters any problems, let me know and all that. Also, if anyone knows what they're doing with Windows programming and wants to write a GUI or at least get some sort of drag and drop going, I'd be more than happy to provide the filthy, filthy source for this clunker.

    Converter.exe

    Anyway, this program will convert a .y12 dump provided by Gens KMod to a .OPM file that you can import into VOPM.

    Sadly, I cannot get drag and drop to work, so you folks are stuck running it from a command line for now, like so:

    "converter.exe chan5.y12"

    Sexy.


    For now it works ok, I've done about 15 test runs and haven't had an issue yet, I just worry about those dropped numbers.
     
  14. Andlabs

    Andlabs

    「いっきまーす」 Wiki Sysop
    2,175
    1
    0
    Writing my own MD/Genesis sound driver :D
    Or, I could help you clean it up :-P
     
  15. McGuirk

    McGuirk

    The Egg-Man Cometh. Member
    Help yourself=D

    A lot of the monotonous stuff can be function'd, particularly the printing parts. But I'm wore out:P

    In a codebox because of encoding issues between windows and linux.

    If you're brave the source file itself can be found here.

    Code (C++):
    1. /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
    2. /*
    3.  * converter.cpp
    4.  * Copyright © Jake Reed 2009
    5.  *
    6.  * converter.cpp is free software: you can redistribute it and/or modify it
    7.  * under the terms of the GNU General Public License as published by the
    8.  * Free Software Foundation, either version 3 of the License, or
    9.  * (at your option) any later version.
    10.  *
    11.  * converter.cpp is distributed in the hope that it will be useful, but
    12.  * WITHOUT ANY WARRANTY; without even the implied warranty of
    13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    14.  * See the GNU General Public License for more details.
    15.  *
    16.  * You should have received a copy of the GNU General Public License along
    17.  * with this program.  If not, see .
    18.  */
    19.  
    20. #include
    21. #include
    22. #include
    23. #include
    24.  
    25. using namespace std;
    26.  
    27. char fixTL(char c)
    28. {
    29.     // *HACK*
    30.     // The first bit is 1 in the dump.
    31.     // I don't know what it's for, and
    32.         // it works fine if I just drop it.
    33.     // Clarify:  The first bit SHOULD
    34.         // NOT be 1.
    35.     // TL is 0-127, 127=7 bits
    36.  
    37.     unsigned char temp = c;
    38.     temp = (temp << 1);
    39.         temp = (temp >> 1);
    40.  
    41.         return temp;
    42. }
    43.  
    44. string expandDetMul(char c)
    45. {
    46.     // First 4 bits = Det
    47.         // Last 4 bits = Mul
    48.    
    49.     string out;
    50.    
    51.     char det = (char)0;
    52.     char mul = (char)0;
    53.  
    54.     unsigned char temp = c;
    55.  
    56.    
    57.         for (int I=7; I>=4; I--)
    58.         {
    59.             char bit = ((temp >> I) & 1);
    60.             det = (det << 1 | bit);
    61.         }
    62.    
    63.         for (int I=3; I>=0; I--)
    64.         {
    65.             char bit = ((temp >> I) & 1);
    66.             mul = (mul << 1 | bit);
    67.         }
    68.    
    69.     out = det;
    70.     out += mul;
    71.     return out;
    72. }
    73.  
    74.  
    75.  
    76. string expandKsAtk(char c)
    77. {
    78.     // First 2 bits = KS
    79.     // Followed by a 0 bit
    80.         // Last 5 bits = Atk
    81.  
    82.     string out;
    83.  
    84.     char KS = (char)0;
    85.     char atk = (char)0;
    86.  
    87.     unsigned char temp = c;
    88.  
    89.         for (int I=7; I>=6; I--)
    90.         {
    91.             char bit = ((temp >> I) & 1);
    92.             KS = (KS << 1 | bit);
    93.         }
    94.    
    95.     for (int I=4; I>=0; I--)
    96.         {
    97.             char bit = ((temp >> I) & 1);
    98.             atk = (atk << 1 | bit);
    99.         }
    100.    
    101.     out = KS;
    102.     out += atk;
    103.     return out;
    104. }
    105.  
    106. string expandSlRel(char c)
    107. {
    108.     // First 4 bits = Sus Level
    109.         // Last 4 bits = Rel
    110.    
    111.     string out;
    112.    
    113.     char sus = (char)0;
    114.     char rel = (char)0;
    115.  
    116.     unsigned char temp = c;
    117.  
    118.    
    119.         for (int I=7; I>=4; I--)
    120.         {
    121.             char bit = ((temp >> I) & 1);
    122.             sus = (sus << 1 | bit);
    123.         }
    124.    
    125.     for (int I=3; I>=0; I--)
    126.         {
    127.             char bit = ((temp >> I) & 1);
    128.             rel = (rel << 1 | bit);
    129.         }
    130.    
    131.     out = sus;
    132.     out += rel;
    133.     return out;
    134. }
    135.  
    136. struct OP
    137. {
    138.        /*
    139.     *Detune
    140.     *Multiple
    141.     *Total Level
    142.     *Key Scale
    143.     *Attack
    144.     *Decay
    145.     *Sustain (Second Decay)
    146.     *Sus Level
    147.     *Release
    148.         */
    149.    
    150.     // Single operator attributes
    151.     unsigned char det;
    152.     unsigned char mul;
    153.     unsigned char tLevel;
    154.     unsigned char kScale;
    155.     unsigned char atk;
    156.     unsigned char dec;
    157.     unsigned char sus;
    158.     unsigned char sLevel;
    159.     unsigned char rel;
    160.    
    161.     // Compressed operator attributes
    162.     unsigned char det_mul;
    163.     unsigned char kS_atk;
    164.     unsigned char sL_rel;
    165. };
    166.  
    167. struct Channel
    168. {
    169.     char connection;
    170.     char feedback;
    171. };
    172.  
    173. int main(int argc, char* argv[])
    174. {
    175.       if (argc <= 1)  
    176.       {  
    177.             cout << "Usage: " << argv[0] << " " << endl;  
    178.             exit(1);  
    179.       }  
    180.  
    181.       char *pFilename = argv[1];
    182.  
    183.     //char inFileName[] = "test.y12";
    184.     //char outFileName[] = "test.opm";
    185.  
    186.     Channel channel;
    187.     OP M1;
    188.     OP M2;
    189.     OP C1;
    190.     OP C2;
    191.  
    192.     ifstream inFile(pFilename, ios::in | ios::binary);
    193.    
    194.     char* readBuffer = new char [0];
    195.    
    196.     /****************************************
    197.     ***               READS               ***
    198.     ****************************************/
    199.    
    200.     // Read M1
    201.    
    202.     inFile.read(readBuffer, 1);
    203.     M1.det_mul = readBuffer[0];
    204.  
    205.     inFile.read(readBuffer, 1);
    206.     M1.tLevel = readBuffer[0];
    207.    
    208.     inFile.read(readBuffer, 1);
    209.     M1.kS_atk = readBuffer[0];
    210.    
    211.     inFile.read(readBuffer, 1);
    212.     M1.dec = readBuffer[0];
    213.    
    214.     inFile.read(readBuffer, 1);
    215.     M1.sus = readBuffer[0];
    216.    
    217.     inFile.read(readBuffer, 1);
    218.     M1.sL_rel = readBuffer[0];
    219.    
    220.     for (int I = 1; I <= 10; I++)
    221.     {
    222.         inFile.read(readBuffer, 1);
    223.     }
    224.  
    225.     // Read M2
    226.    
    227.     inFile.read(readBuffer, 1);
    228.     M2.det_mul = readBuffer[0];
    229.    
    230.     inFile.read(readBuffer, 1);
    231.     M2.tLevel = readBuffer[0];
    232.    
    233.     inFile.read(readBuffer, 1);
    234.     M2.kS_atk = readBuffer[0];
    235.    
    236.     inFile.read(readBuffer, 1);
    237.     M2.dec = readBuffer[0];
    238.    
    239.     inFile.read(readBuffer, 1);
    240.     M2.sus = readBuffer[0];
    241.    
    242.     inFile.read(readBuffer, 1);
    243.     M2.sL_rel = readBuffer[0];
    244.    
    245.     for (int I = 1; I <= 10; I++)
    246.     {
    247.         inFile.read(readBuffer, 1);
    248.     }
    249.    
    250.     // Read C1
    251.    
    252.     inFile.read(readBuffer, 1);
    253.     C1.det_mul = readBuffer[0];
    254.    
    255.     inFile.read(readBuffer, 1);
    256.     C1.tLevel = readBuffer[0];
    257.    
    258.     inFile.read(readBuffer, 1);
    259.     C1.kS_atk = readBuffer[0];
    260.    
    261.     inFile.read(readBuffer, 1);
    262.     C1.dec = readBuffer[0];
    263.    
    264.     inFile.read(readBuffer, 1);
    265.     C1.sus = readBuffer[0];
    266.    
    267.     inFile.read(readBuffer, 1);
    268.     C1.sL_rel = readBuffer[0];
    269.    
    270.     for (int I = 1; I <= 10; I++)
    271.     {
    272.         inFile.read(readBuffer, 1);
    273.     }
    274.  
    275.     // Read C2
    276.    
    277.     inFile.read(readBuffer, 1);
    278.     C2.det_mul = readBuffer[0];
    279.    
    280.     inFile.read(readBuffer, 1);
    281.     C2.tLevel = readBuffer[0];
    282.    
    283.     inFile.read(readBuffer, 1);
    284.     C2.kS_atk = readBuffer[0];
    285.    
    286.     inFile.read(readBuffer, 1);
    287.     C2.dec = readBuffer[0];
    288.    
    289.     inFile.read(readBuffer, 1);
    290.     C2.sus = readBuffer[0];
    291.    
    292.     inFile.read(readBuffer, 1);
    293.     C2.sL_rel = readBuffer[0];
    294.    
    295.     for (int I = 1; I <= 10; I++)
    296.     {
    297.         inFile.read(readBuffer, 1);
    298.     }
    299.  
    300.     // Channel
    301.    
    302.     inFile.read(readBuffer, 1);
    303.     channel.feedback = readBuffer[0];
    304.    
    305.     inFile.read(readBuffer, 1);
    306.     channel.connection = readBuffer[0];
    307.  
    308.     inFile.close();
    309.  
    310.     /****************************************
    311.     ***               EXPAND              ***
    312.     ****************************************/
    313.    
    314.     // M1
    315.    
    316.     string out = expandDetMul(M1.det_mul);
    317.    
    318.     M1.det = out.at(0);
    319.     M1.mul = out.at(1);
    320.    
    321.     out = expandKsAtk(M1.kS_atk);
    322.    
    323.     M1.kScale = out.at(0);
    324.     M1.atk    = out.at(1);
    325.    
    326.     out = expandSlRel(M1.sL_rel);
    327.    
    328.     M1.sLevel = out.at(0);
    329.     M1.rel    = out.at(1);
    330.  
    331.     char temp = fixTL(M1.tLevel);
    332.     M1.tLevel = temp;
    333.    
    334.     // M2
    335.    
    336.     out = expandDetMul(M2.det_mul);
    337.    
    338.     M2.det = out.at(0);
    339.     M2.mul = out.at(1);
    340.    
    341.     out = expandKsAtk(M2.kS_atk);
    342.    
    343.     M2.kScale = out.at(0);
    344.     M2.atk    = out.at(1);
    345.    
    346.     out = expandSlRel(M2.sL_rel);
    347.    
    348.     M2.sLevel = out.at(0);
    349.     M2.rel    = out.at(1);
    350.  
    351.     temp = fixTL(M2.tLevel);
    352.     M2.tLevel = temp;
    353.  
    354.    
    355.     // C1
    356.    
    357.     out = expandDetMul(C1.det_mul);
    358.    
    359.     C1.det = out.at(0);
    360.     C1.mul = out.at(1);
    361.    
    362.     out = expandKsAtk(C1.kS_atk);
    363.    
    364.     C1.kScale = out.at(0);
    365.     C1.atk    = out.at(1);
    366.    
    367.     out = expandSlRel(C1.sL_rel);
    368.    
    369.     C1.sLevel = out.at(0);
    370.     C1.rel    = out.at(1);
    371.    
    372.     temp = fixTL(C1.tLevel);
    373.     C1.tLevel = temp;
    374.  
    375.    
    376.     // C2
    377.    
    378.     out = expandDetMul(C2.det_mul);
    379.    
    380.     C2.det = out.at(0);
    381.     C2.mul = out.at(1);
    382.    
    383.     out = expandKsAtk(C2.kS_atk);
    384.    
    385.     C2.kScale = out.at(0);
    386.     C2.atk    = out.at(1);
    387.    
    388.     out = expandSlRel(C2.sL_rel);
    389.    
    390.     C2.sLevel = out.at(0);
    391.     C2.rel    = out.at(1);
    392.  
    393.     temp = fixTL(C2.tLevel);
    394.     C2.tLevel = temp;
    395.    
    396.  
    397.     /****************************************
    398.     ***              PRINT                ***
    399.     ****************************************/
    400.    
    401.     fstream outFile("out.OPM", ios::out);
    402.    
    403.     // Heading
    404.     outFile << "@:0 " << pFilename << "\n";
    405.    
    406.     outFile << "LFO: 0   0   0   0   0\n";
    407.    
    408.     outFile << "CH:"
    409.          << setw(4) << "64"
    410.          << setw(4) << (int)channel.connection
    411.          << setw(4) << (int)channel.feedback
    412.          << setw(4) << "0"
    413.          << setw(4) << "0"
    414.          << setw(4) << "120"
    415.          << setw(4) << "0"
    416.          << "\n";
    417.    
    418.     outFile << "M1:"
    419.          << setw(4) << (int)M1.atk
    420.          << setw(4) << (int)M1.dec
    421.          << setw(4) << (int)M1.sus
    422.          << setw(4) << (int)M1.rel
    423.          << setw(4) << (int)M1.sLevel
    424.          << setw(4) << (int)M1.tLevel
    425.          << setw(4) << (int)M1.kScale
    426.          << setw(4) << (int)M1.mul
    427.          << setw(4) << (int)M1.det
    428.          << setw(4) << 0
    429.          << setw(4) << 0 << "\n";
    430.          
    431.     outFile << "C1:"
    432.          << setw(4) << (int)C1.atk
    433.          << setw(4) << (int)C1.dec
    434.          << setw(4) << (int)C1.sus
    435.          << setw(4) << (int)C1.rel
    436.          << setw(4) << (int)C1.sLevel
    437.          << setw(4) << (int)C1.tLevel
    438.          << setw(4) << (int)C1.kScale
    439.          << setw(4) << (int)C1.mul
    440.          << setw(4) << (int)C1.det
    441.          << setw(4) << 0
    442.          << setw(4) << 0 << "\n";
    443.          
    444.     outFile << "M2:"
    445.          << setw(4) << (int)M2.atk
    446.          << setw(4) << (int)M2.dec
    447.          << setw(4) << (int)M2.sus
    448.          << setw(4) << (int)M2.rel
    449.          << setw(4) << (int)M2.sLevel
    450.          << setw(4) << (int)M2.tLevel
    451.          << setw(4) << (int)M2.kScale
    452.          << setw(4) << (int)M2.mul
    453.          << setw(4) << (int)M2.det
    454.          << setw(4) << 0
    455.          << setw(4) << 0 << "\n";
    456.  
    457.     outFile << "C2:"
    458.          << setw(4) << (int)C2.atk
    459.          << setw(4) << (int)C2.dec
    460.          << setw(4) << (int)C2.sus
    461.          << setw(4) << (int)C2.rel
    462.          << setw(4) << (int)C2.sLevel
    463.          << setw(4) << (int)C2.tLevel
    464.          << setw(4) << (int)C2.kScale
    465.          << setw(4) << (int)C2.mul
    466.          << setw(4) << (int)C2.det
    467.          << setw(4) << 0
    468.          << setw(4) << 0 << "\n";
    469.  
    470.     outFile.close();
    471.  
    472.     return 0;
    473. }
    474.  
    That's right, it's GPL'd =P

    I started going in anjuta before I got annoyed and whipped out text editor and g++.
     
  16. Andlabs

    Andlabs

    「いっきまーす」 Wiki Sysop
    2,175
    1
    0
    Writing my own MD/Genesis sound driver :D
    Other than the monotony, this code looks good. Just explain what you are doing in the helper functions and you have a pearl.

    Windows is up. VOPM is up. Cubasis InWired is up. My OPM tracks are all ripped from VGZ files. I have Sonic 3 audio samples ready. Soon!
     
  17. McGuirk

    McGuirk

    The Egg-Man Cometh. Member
    Fist off, the dumps are compressed.

    I'll explain.

    Here's the values for OP1 channel 3 of the exercise music from Dr. Robotnik's Mean Bean Machine:

    Code (Text):
    1.  
    2. Detune:       0x03
    3. Multiple:     0x09
    4. Total Level:  0x17
    5. Rate Scaling: 0x00
    6. Attack Rate:  0x1F
    7. First Decay:  0x0C
    8. Second Decay: 0x07
    9. Sub Level:    0x06
    10. Release Rate: 0x06
    11.  
    03 09 12 00 1F 0C 07 06 06

    Now, here's the dump from the .y12 file:

    39 17 1F 0C 07 26

    Here's what each of them is:

    (Unless specified otherwise,
    the helper functions take the compressed
    byte as a character for a parameter, then
    returns a std::string of the decompressed
    bytes as 2 characters)

    ----

    39:
    Detune and Multiple grouped.
    1 nybble per value. expandDetMul()
    splits the bits between the two.

    ----

    17:
    Total Level, whole byte.

    NOTE: The value does not include the
    whole byte. TL's value is 0-127,
    so the first bit is ignored.

    I don't know why it's sometimes 1 in the dumps.
    fixTL() takes TL as a char, sets the first
    bit to zero via bit shifts, and returns the
    altered char.

    ----

    1F:
    Rate Scaling and Attack Rate.
    This one is more complex. Of
    the byte, the first two bits
    are the Rate Scaling, followed
    by a 0 bit, followed by the
    Attack rate in the last 5 bits.

    IE: RS0AtkRt
    1F:00011111

    expandKsAtk() splits the bits

    ----

    0C:
    First Decay, whole byte.

    ----

    07:
    Second Decay, whole byte.

    ----

    26:
    Sustain Level and Release rate:
    After more research these two
    values are always equal. They
    are represented by the second
    nybble, I was splitting in two
    before. This means I'll be
    posting a revised source file
    at the bottom of this post.
    The 2 can be dropped.

    ----

    These are followed by 10 bytes
    of 0x00's. Trash for now.
    Repeat for 3 more OP's + 10
    byte buffer between. Next,

    One byte for the channel's
    connection type:
    0x00 - 0x07

    Very next byte is Channel's
    feedback level:
    0x00 - 0x07

    Rest is crap.

    That's the overview.

    The variables should cover
    themselves in the comments
    near them.

    Feel free to ask more detailed
    questions if I left something out.

    Here's the updates source:

    Code (Text):
    1.  
    2. /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
    3. /*
    4.  * converter.cpp
    5.  * Copyright &copy; Jake Reed 2009 <[email protected]>
    6.  *
    7.  * converter.cpp is free software: you can redistribute it and/or modify it
    8.  * under the terms of the GNU General Public License as published by the
    9.  * Free Software Foundation, either version 3 of the License, or
    10.  * (at your option) any later version.
    11.  *
    12.  * converter.cpp is distributed in the hope that it will be useful, but
    13.  * WITHOUT ANY WARRANTY; without even the implied warranty of
    14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    15.  * See the GNU General Public License for more details.
    16.  *
    17.  * You should have received a copy of the GNU General Public License along
    18.  * with this program.  If not, see <http://www.gnu.org/licenses/>.
    19.  */
    20.  
    21. #include <iostream>
    22. #include <string>
    23. #include <iomanip>
    24. #include <fstream>
    25.  
    26. using namespace std;
    27.  
    28. char fixTL(char c)
    29. {
    30.     // *HACK*
    31.     // The first bit is 1 in the dump.
    32.     // I don't know what it's for, and
    33.         // it works fine if I just drop it.
    34.     // Clarify:  The first bit SHOULD
    35.         // NOT be 1.
    36.     // TL is 0-127, 127=7 bits
    37.  
    38.     unsigned char temp = c;
    39.     temp = (temp << 1);
    40.         temp = (temp >> 1);
    41.  
    42.         return temp;
    43. }
    44.  
    45. string expandDetMul(char c)
    46. {
    47.     // First 4 bits = Det
    48.         // Last 4 bits = Mul
    49.    
    50.     string out;
    51.    
    52.     char det = (char)0;
    53.     char mul = (char)0;
    54.  
    55.     unsigned char temp = c;
    56.  
    57.    
    58.         for (int I=7; I>=4; I--)
    59.         {
    60.             char bit = ((temp >> I) & 1);
    61.             det = (det << 1 | bit);
    62.         }
    63.    
    64.         for (int I=3; I>=0; I--)
    65.         {
    66.             char bit = ((temp >> I) & 1);
    67.             mul = (mul << 1 | bit);
    68.         }
    69.    
    70.     out = det;
    71.     out += mul;
    72.     return out;
    73. }
    74.  
    75.  
    76.  
    77. string expandKsAtk(char c)
    78. {
    79.     // First 2 bits = KS
    80.     // Followed by a 0 bit
    81.         // Last 5 bits = Atk
    82.  
    83.     string out;
    84.  
    85.     char KS = (char)0;
    86.     char atk = (char)0;
    87.  
    88.     unsigned char temp = c;
    89.  
    90.         for (int I=7; I>=6; I--)
    91.         {
    92.             char bit = ((temp >> I) & 1);
    93.             KS = (KS << 1 | bit);
    94.         }
    95.    
    96.     for (int I=4; I>=0; I--)
    97.         {
    98.             char bit = ((temp >> I) & 1);
    99.             atk = (atk << 1 | bit);
    100.         }
    101.    
    102.     out = KS;
    103.     out += atk;
    104.     return out;
    105. }
    106.  
    107. string expandSlRel(char c)
    108. {
    109.     // First 4 bits = Crap
    110.         // Last 4 bits = Both Values
    111.    
    112.     string out;
    113.    
    114.     char rel = (char)0;
    115.  
    116.     unsigned char temp = c;
    117.    
    118.     for (int I=3; I>=0; I--)
    119.         {
    120.             char bit = ((temp >> I) & 1);
    121.             rel = (rel << 1 | bit);
    122.         }
    123.  
    124.     out = rel;
    125.     out += rel;
    126.     return out;
    127. }
    128.  
    129. struct OP
    130. {
    131.        /*
    132.     *Detune
    133.     *Multiple
    134.     *Total Level
    135.     *Key Scale
    136.     *Attack
    137.     *Decay
    138.     *Sustain (Second Decay)
    139.     *Sus Level
    140.     *Release
    141.         */
    142.    
    143.     // Single operator attributes
    144.     unsigned char det;
    145.     unsigned char mul;
    146.     unsigned char tLevel;
    147.     unsigned char kScale;
    148.     unsigned char atk;
    149.     unsigned char dec;
    150.     unsigned char sus;
    151.     unsigned char sLevel;
    152.     unsigned char rel;
    153.    
    154.     // Compressed operator attributes
    155.     unsigned char det_mul;
    156.     unsigned char kS_atk;
    157.     unsigned char sL_rel;
    158. };
    159.  
    160. struct Channel
    161. {
    162.     char connection;
    163.     char feedback;
    164. };
    165.  
    166. int main(int argc, char* argv[])
    167. {
    168.       if (argc <= 1)  
    169.       {  
    170.               cout << "Usage: " << argv[0] << " <Filename>" << endl;  
    171.             exit(1);  
    172.       }  
    173.  
    174.       char *pFilename = argv[1];
    175.  
    176.     //char inFileName[] = "test.y12";
    177.     //char outFileName[] = "test.opm";
    178.  
    179.     Channel channel;
    180.     OP M1;
    181.     OP M2;
    182.     OP C1;
    183.     OP C2;
    184.  
    185.     ifstream inFile(pFilename, ios::in | ios::binary);
    186.    
    187.     char* readBuffer = new char [0];
    188.    
    189.     /****************************************
    190.     ***               READS               ***
    191.     ****************************************/
    192.    
    193.     // Read M1
    194.    
    195.     inFile.read(readBuffer, 1);
    196.     M1.det_mul = readBuffer[0];
    197.  
    198.     inFile.read(readBuffer, 1);
    199.     M1.tLevel = readBuffer[0];
    200.    
    201.     inFile.read(readBuffer, 1);
    202.     M1.kS_atk = readBuffer[0];
    203.    
    204.     inFile.read(readBuffer, 1);
    205.     M1.dec = readBuffer[0];
    206.    
    207.     inFile.read(readBuffer, 1);
    208.     M1.sus = readBuffer[0];
    209.    
    210.     inFile.read(readBuffer, 1);
    211.     M1.sL_rel = readBuffer[0];
    212.    
    213.     for (int I = 1; I <= 10; I++)
    214.     {
    215.         inFile.read(readBuffer, 1);
    216.     }
    217.  
    218.     // Read M2
    219.    
    220.     inFile.read(readBuffer, 1);
    221.     M2.det_mul = readBuffer[0];
    222.    
    223.     inFile.read(readBuffer, 1);
    224.     M2.tLevel = readBuffer[0];
    225.    
    226.     inFile.read(readBuffer, 1);
    227.     M2.kS_atk = readBuffer[0];
    228.    
    229.     inFile.read(readBuffer, 1);
    230.     M2.dec = readBuffer[0];
    231.    
    232.     inFile.read(readBuffer, 1);
    233.     M2.sus = readBuffer[0];
    234.    
    235.     inFile.read(readBuffer, 1);
    236.     M2.sL_rel = readBuffer[0];
    237.    
    238.     for (int I = 1; I <= 10; I++)
    239.     {
    240.         inFile.read(readBuffer, 1);
    241.     }
    242.    
    243.     // Read C1
    244.    
    245.     inFile.read(readBuffer, 1);
    246.     C1.det_mul = readBuffer[0];
    247.    
    248.     inFile.read(readBuffer, 1);
    249.     C1.tLevel = readBuffer[0];
    250.    
    251.     inFile.read(readBuffer, 1);
    252.     C1.kS_atk = readBuffer[0];
    253.    
    254.     inFile.read(readBuffer, 1);
    255.     C1.dec = readBuffer[0];
    256.    
    257.     inFile.read(readBuffer, 1);
    258.     C1.sus = readBuffer[0];
    259.    
    260.     inFile.read(readBuffer, 1);
    261.     C1.sL_rel = readBuffer[0];
    262.    
    263.     for (int I = 1; I <= 10; I++)
    264.     {
    265.         inFile.read(readBuffer, 1);
    266.     }
    267.  
    268.     // Read C2
    269.    
    270.     inFile.read(readBuffer, 1);
    271.     C2.det_mul = readBuffer[0];
    272.    
    273.     inFile.read(readBuffer, 1);
    274.     C2.tLevel = readBuffer[0];
    275.    
    276.     inFile.read(readBuffer, 1);
    277.     C2.kS_atk = readBuffer[0];
    278.    
    279.     inFile.read(readBuffer, 1);
    280.     C2.dec = readBuffer[0];
    281.    
    282.     inFile.read(readBuffer, 1);
    283.     C2.sus = readBuffer[0];
    284.    
    285.     inFile.read(readBuffer, 1);
    286.     C2.sL_rel = readBuffer[0];
    287.    
    288.     for (int I = 1; I <= 10; I++)
    289.     {
    290.         inFile.read(readBuffer, 1);
    291.     }
    292.  
    293.     // Channel
    294.    
    295.     inFile.read(readBuffer, 1);
    296.     channel.connection = readBuffer[0];
    297.    
    298.     inFile.read(readBuffer, 1);
    299.     channel.feedback = readBuffer[0];
    300.  
    301.     inFile.close();
    302.  
    303.     /****************************************
    304.     ***               EXPAND              ***
    305.     ****************************************/
    306.    
    307.     // M1
    308.    
    309.     string out = expandDetMul(M1.det_mul);
    310.    
    311.     M1.det = out.at(0);
    312.     M1.mul = out.at(1);
    313.    
    314.     out = expandKsAtk(M1.kS_atk);
    315.    
    316.     M1.kScale = out.at(0);
    317.     M1.atk    = out.at(1);
    318.    
    319.     out = expandSlRel(M1.sL_rel);
    320.    
    321.     M1.sLevel = out.at(0);
    322.     M1.rel    = out.at(1);
    323.  
    324.     char temp = fixTL(M1.tLevel);
    325.     M1.tLevel = temp;
    326.    
    327.     // M2
    328.    
    329.     out = expandDetMul(M2.det_mul);
    330.    
    331.     M2.det = out.at(0);
    332.     M2.mul = out.at(1);
    333.    
    334.     out = expandKsAtk(M2.kS_atk);
    335.    
    336.     M2.kScale = out.at(0);
    337.     M2.atk    = out.at(1);
    338.    
    339.     out = expandSlRel(M2.sL_rel);
    340.    
    341.     M2.sLevel = out.at(0);
    342.     M2.rel    = out.at(1);
    343.  
    344.     temp = fixTL(M2.tLevel);
    345.     M2.tLevel = temp;
    346.  
    347.    
    348.     // C1
    349.    
    350.     out = expandDetMul(C1.det_mul);
    351.    
    352.     C1.det = out.at(0);
    353.     C1.mul = out.at(1);
    354.    
    355.     out = expandKsAtk(C1.kS_atk);
    356.    
    357.     C1.kScale = out.at(0);
    358.     C1.atk    = out.at(1);
    359.    
    360.     out = expandSlRel(C1.sL_rel);
    361.    
    362.     C1.sLevel = out.at(0);
    363.     C1.rel    = out.at(1);
    364.    
    365.     temp = fixTL(C1.tLevel);
    366.     C1.tLevel = temp;
    367.  
    368.    
    369.     // C2
    370.    
    371.     out = expandDetMul(C2.det_mul);
    372.    
    373.     C2.det = out.at(0);
    374.     C2.mul = out.at(1);
    375.    
    376.     out = expandKsAtk(C2.kS_atk);
    377.    
    378.     C2.kScale = out.at(0);
    379.     C2.atk    = out.at(1);
    380.    
    381.     out = expandSlRel(C2.sL_rel);
    382.    
    383.     C2.sLevel = out.at(0);
    384.     C2.rel    = out.at(1);
    385.  
    386.     temp = fixTL(C2.tLevel);
    387.     C2.tLevel = temp;
    388.    
    389.  
    390.     /****************************************
    391.     ***              PRINT                ***
    392.     ****************************************/
    393.    
    394.     fstream outFile("out.OPM", ios::out);
    395.    
    396.     // Heading
    397.     outFile << "@:0 " << pFilename << "\n";
    398.    
    399.     outFile << "LFO: 0   0   0   0   0\n";
    400.    
    401.     outFile << "CH:"
    402.          << setw(4) << "64"
    403.          << setw(4) << (int)channel.feedback
    404.          << setw(4) << (int)channel.connection
    405.          << setw(4) << "0"
    406.          << setw(4) << "0"
    407.          << setw(4) << "120"
    408.          << setw(4) << "0"
    409.          << "\n";
    410.    
    411.     outFile << "M1:"
    412.          << setw(4) << (int)M1.atk
    413.          << setw(4) << (int)M1.dec
    414.          << setw(4) << (int)M1.sus
    415.          << setw(4) << (int)M1.rel
    416.          << setw(4) << (int)M1.sLevel
    417.          << setw(4) << (int)M1.tLevel
    418.          << setw(4) << (int)M1.kScale
    419.          << setw(4) << (int)M1.mul
    420.          << setw(4) << (int)M1.det
    421.          << setw(4) << 0
    422.          << setw(4) << 0 << "\n";
    423.          
    424.     outFile << "C1:"
    425.          << setw(4) << (int)C1.atk
    426.          << setw(4) << (int)C1.dec
    427.          << setw(4) << (int)C1.sus
    428.          << setw(4) << (int)C1.rel
    429.          << setw(4) << (int)C1.sLevel
    430.          << setw(4) << (int)C1.tLevel
    431.          << setw(4) << (int)C1.kScale
    432.          << setw(4) << (int)C1.mul
    433.          << setw(4) << (int)C1.det
    434.          << setw(4) << 0
    435.          << setw(4) << 0 << "\n";
    436.          
    437.     outFile << "M2:"
    438.          << setw(4) << (int)M2.atk
    439.          << setw(4) << (int)M2.dec
    440.          << setw(4) << (int)M2.sus
    441.          << setw(4) << (int)M2.rel
    442.          << setw(4) << (int)M2.sLevel
    443.          << setw(4) << (int)M2.tLevel
    444.          << setw(4) << (int)M2.kScale
    445.          << setw(4) << (int)M2.mul
    446.          << setw(4) << (int)M2.det
    447.          << setw(4) << 0
    448.          << setw(4) << 0 << "\n";
    449.  
    450.     outFile << "C2:"
    451.          << setw(4) << (int)C2.atk
    452.          << setw(4) << (int)C2.dec
    453.          << setw(4) << (int)C2.sus
    454.          << setw(4) << (int)C2.rel
    455.          << setw(4) << (int)C2.sLevel
    456.          << setw(4) << (int)C2.tLevel
    457.          << setw(4) << (int)C2.kScale
    458.          << setw(4) << (int)C2.mul
    459.          << setw(4) << (int)C2.det
    460.          << setw(4) << 0
    461.          << setw(4) << 0 << "\n";
    462.  
    463.     outFile.close();
    464.  
    465.     return 0;
    466. }
    467.  
    468.  
     
  18. XCubed

    XCubed

    Will Someday Own a Rent-A-Center Oldbie

    You motherfucker, I need to make sweet love to you NOW!!! Your directions were a little different from my version of FL Studio, but with some tooling around with the files I was able to get it to work! I LOVE YOU! I want you to have my babies. I can make sweet lovin closer to Genesis sounds that I ever could have before! Sorry for the profanity, but this has made me so damn happy! I don't know how the fuck you did this, but either way you have my love now and forever McGuirk!
     
  19. Andlabs

    Andlabs

    「いっきまーす」 Wiki Sysop
    2,175
    1
    0
    Writing my own MD/Genesis sound driver :D
    Is there a way to emulate the Programmable Sound Generator? I noticed that some songs, such as Lava Reef Act 1, use it alongside the OPM FM channels.
     
  20. muteKi

    muteKi

    Fuck it Member
    7,852
    131
    43
    There must be a decent square wave VST out there somewhere...