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
Yeah, the arrangement is a bit spartan. I probably won't go back to it until I've done a couple other things first.
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 ?
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.
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).
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.
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.
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.
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.
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): # splitopm: split opm file into one per instrument # pietro gagliardi - 6 january 2009 # usage: splitopm file.opm output-directory BEGIN { # Change this if your OS needs it DIR_SEPARATOR = "/" if (ARGC != 3) { print "usage: " ARGV[0] " file.opm output-directory" exit 1 } outdir = ARGV[2] ARGV[2] = "" ARGC-- RS = "" FS = OFS = "\n" } /^\/\// { next } !/^@/ { print ARGV[1] ": bad input file"; exit 1 } { instrname = substr($1, index($1, " ") + 1) if (tolower(instrname) == "no name") next oldinstrname = instrname gsub(/[^A-Za-z0-9_]/, "", instrname) filename = outdir DIR_SEPARATOR instrname ".opm" $1 = "@:0 " oldinstrname # convert to bank 0 print > filename close(filename) inst++ } You may need to change the line Code (Text): $1 = "@:0 " oldinstrname # convert to bank 0 to Code (Text): $1 = "@:1 " oldinstrname # convert to bank 1 if the script doesn't result in files that can be imported, but I don't know.
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!
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.
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.
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++): /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * converter.cpp * Copyright © Jake Reed 2009 * * converter.cpp is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * converter.cpp is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include #include #include using namespace std; char fixTL(char c) { // *HACK* // The first bit is 1 in the dump. // I don't know what it's for, and // it works fine if I just drop it. // Clarify: The first bit SHOULD // NOT be 1. // TL is 0-127, 127=7 bits unsigned char temp = c; temp = (temp << 1); temp = (temp >> 1); return temp; } string expandDetMul(char c) { // First 4 bits = Det // Last 4 bits = Mul string out; char det = (char)0; char mul = (char)0; unsigned char temp = c; for (int I=7; I>=4; I--) { char bit = ((temp >> I) & 1); det = (det << 1 | bit); } for (int I=3; I>=0; I--) { char bit = ((temp >> I) & 1); mul = (mul << 1 | bit); } out = det; out += mul; return out; } string expandKsAtk(char c) { // First 2 bits = KS // Followed by a 0 bit // Last 5 bits = Atk string out; char KS = (char)0; char atk = (char)0; unsigned char temp = c; for (int I=7; I>=6; I--) { char bit = ((temp >> I) & 1); KS = (KS << 1 | bit); } for (int I=4; I>=0; I--) { char bit = ((temp >> I) & 1); atk = (atk << 1 | bit); } out = KS; out += atk; return out; } string expandSlRel(char c) { // First 4 bits = Sus Level // Last 4 bits = Rel string out; char sus = (char)0; char rel = (char)0; unsigned char temp = c; for (int I=7; I>=4; I--) { char bit = ((temp >> I) & 1); sus = (sus << 1 | bit); } for (int I=3; I>=0; I--) { char bit = ((temp >> I) & 1); rel = (rel << 1 | bit); } out = sus; out += rel; return out; } struct OP { /* *Detune *Multiple *Total Level *Key Scale *Attack *Decay *Sustain (Second Decay) *Sus Level *Release */ // Single operator attributes unsigned char det; unsigned char mul; unsigned char tLevel; unsigned char kScale; unsigned char atk; unsigned char dec; unsigned char sus; unsigned char sLevel; unsigned char rel; // Compressed operator attributes unsigned char det_mul; unsigned char kS_atk; unsigned char sL_rel; }; struct Channel { char connection; char feedback; }; int main(int argc, char* argv[]) { if (argc <= 1) { cout << "Usage: " << argv[0] << " " << endl; exit(1); } char *pFilename = argv[1]; //char inFileName[] = "test.y12"; //char outFileName[] = "test.opm"; Channel channel; OP M1; OP M2; OP C1; OP C2; ifstream inFile(pFilename, ios::in | ios::binary); char* readBuffer = new char [0]; /**************************************** *** READS *** ****************************************/ // Read M1 inFile.read(readBuffer, 1); M1.det_mul = readBuffer[0]; inFile.read(readBuffer, 1); M1.tLevel = readBuffer[0]; inFile.read(readBuffer, 1); M1.kS_atk = readBuffer[0]; inFile.read(readBuffer, 1); M1.dec = readBuffer[0]; inFile.read(readBuffer, 1); M1.sus = readBuffer[0]; inFile.read(readBuffer, 1); M1.sL_rel = readBuffer[0]; for (int I = 1; I <= 10; I++) { inFile.read(readBuffer, 1); } // Read M2 inFile.read(readBuffer, 1); M2.det_mul = readBuffer[0]; inFile.read(readBuffer, 1); M2.tLevel = readBuffer[0]; inFile.read(readBuffer, 1); M2.kS_atk = readBuffer[0]; inFile.read(readBuffer, 1); M2.dec = readBuffer[0]; inFile.read(readBuffer, 1); M2.sus = readBuffer[0]; inFile.read(readBuffer, 1); M2.sL_rel = readBuffer[0]; for (int I = 1; I <= 10; I++) { inFile.read(readBuffer, 1); } // Read C1 inFile.read(readBuffer, 1); C1.det_mul = readBuffer[0]; inFile.read(readBuffer, 1); C1.tLevel = readBuffer[0]; inFile.read(readBuffer, 1); C1.kS_atk = readBuffer[0]; inFile.read(readBuffer, 1); C1.dec = readBuffer[0]; inFile.read(readBuffer, 1); C1.sus = readBuffer[0]; inFile.read(readBuffer, 1); C1.sL_rel = readBuffer[0]; for (int I = 1; I <= 10; I++) { inFile.read(readBuffer, 1); } // Read C2 inFile.read(readBuffer, 1); C2.det_mul = readBuffer[0]; inFile.read(readBuffer, 1); C2.tLevel = readBuffer[0]; inFile.read(readBuffer, 1); C2.kS_atk = readBuffer[0]; inFile.read(readBuffer, 1); C2.dec = readBuffer[0]; inFile.read(readBuffer, 1); C2.sus = readBuffer[0]; inFile.read(readBuffer, 1); C2.sL_rel = readBuffer[0]; for (int I = 1; I <= 10; I++) { inFile.read(readBuffer, 1); } // Channel inFile.read(readBuffer, 1); channel.feedback = readBuffer[0]; inFile.read(readBuffer, 1); channel.connection = readBuffer[0]; inFile.close(); /**************************************** *** EXPAND *** ****************************************/ // M1 string out = expandDetMul(M1.det_mul); M1.det = out.at(0); M1.mul = out.at(1); out = expandKsAtk(M1.kS_atk); M1.kScale = out.at(0); M1.atk = out.at(1); out = expandSlRel(M1.sL_rel); M1.sLevel = out.at(0); M1.rel = out.at(1); char temp = fixTL(M1.tLevel); M1.tLevel = temp; // M2 out = expandDetMul(M2.det_mul); M2.det = out.at(0); M2.mul = out.at(1); out = expandKsAtk(M2.kS_atk); M2.kScale = out.at(0); M2.atk = out.at(1); out = expandSlRel(M2.sL_rel); M2.sLevel = out.at(0); M2.rel = out.at(1); temp = fixTL(M2.tLevel); M2.tLevel = temp; // C1 out = expandDetMul(C1.det_mul); C1.det = out.at(0); C1.mul = out.at(1); out = expandKsAtk(C1.kS_atk); C1.kScale = out.at(0); C1.atk = out.at(1); out = expandSlRel(C1.sL_rel); C1.sLevel = out.at(0); C1.rel = out.at(1); temp = fixTL(C1.tLevel); C1.tLevel = temp; // C2 out = expandDetMul(C2.det_mul); C2.det = out.at(0); C2.mul = out.at(1); out = expandKsAtk(C2.kS_atk); C2.kScale = out.at(0); C2.atk = out.at(1); out = expandSlRel(C2.sL_rel); C2.sLevel = out.at(0); C2.rel = out.at(1); temp = fixTL(C2.tLevel); C2.tLevel = temp; /**************************************** *** PRINT *** ****************************************/ fstream outFile("out.OPM", ios::out); // Heading outFile << "@:0 " << pFilename << "\n"; outFile << "LFO: 0 0 0 0 0\n"; outFile << "CH:" << setw(4) << "64" << setw(4) << (int)channel.connection << setw(4) << (int)channel.feedback << setw(4) << "0" << setw(4) << "0" << setw(4) << "120" << setw(4) << "0" << "\n"; outFile << "M1:" << setw(4) << (int)M1.atk << setw(4) << (int)M1.dec << setw(4) << (int)M1.sus << setw(4) << (int)M1.rel << setw(4) << (int)M1.sLevel << setw(4) << (int)M1.tLevel << setw(4) << (int)M1.kScale << setw(4) << (int)M1.mul << setw(4) << (int)M1.det << setw(4) << 0 << setw(4) << 0 << "\n"; outFile << "C1:" << setw(4) << (int)C1.atk << setw(4) << (int)C1.dec << setw(4) << (int)C1.sus << setw(4) << (int)C1.rel << setw(4) << (int)C1.sLevel << setw(4) << (int)C1.tLevel << setw(4) << (int)C1.kScale << setw(4) << (int)C1.mul << setw(4) << (int)C1.det << setw(4) << 0 << setw(4) << 0 << "\n"; outFile << "M2:" << setw(4) << (int)M2.atk << setw(4) << (int)M2.dec << setw(4) << (int)M2.sus << setw(4) << (int)M2.rel << setw(4) << (int)M2.sLevel << setw(4) << (int)M2.tLevel << setw(4) << (int)M2.kScale << setw(4) << (int)M2.mul << setw(4) << (int)M2.det << setw(4) << 0 << setw(4) << 0 << "\n"; outFile << "C2:" << setw(4) << (int)C2.atk << setw(4) << (int)C2.dec << setw(4) << (int)C2.sus << setw(4) << (int)C2.rel << setw(4) << (int)C2.sLevel << setw(4) << (int)C2.tLevel << setw(4) << (int)C2.kScale << setw(4) << (int)C2.mul << setw(4) << (int)C2.det << setw(4) << 0 << setw(4) << 0 << "\n"; outFile.close(); return 0; } That's right, it's GPL'd =P I started going in anjuta before I got annoyed and whipped out text editor and g++.
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!
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): Detune: 0x03 Multiple: 0x09 Total Level: 0x17 Rate Scaling: 0x00 Attack Rate: 0x1F First Decay: 0x0C Second Decay: 0x07 Sub Level: 0x06 Release Rate: 0x06 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): /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * converter.cpp * Copyright © Jake Reed 2009 <[email protected]> * * converter.cpp is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * converter.cpp is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <iostream> #include <string> #include <iomanip> #include <fstream> using namespace std; char fixTL(char c) { // *HACK* // The first bit is 1 in the dump. // I don't know what it's for, and // it works fine if I just drop it. // Clarify: The first bit SHOULD // NOT be 1. // TL is 0-127, 127=7 bits unsigned char temp = c; temp = (temp << 1); temp = (temp >> 1); return temp; } string expandDetMul(char c) { // First 4 bits = Det // Last 4 bits = Mul string out; char det = (char)0; char mul = (char)0; unsigned char temp = c; for (int I=7; I>=4; I--) { char bit = ((temp >> I) & 1); det = (det << 1 | bit); } for (int I=3; I>=0; I--) { char bit = ((temp >> I) & 1); mul = (mul << 1 | bit); } out = det; out += mul; return out; } string expandKsAtk(char c) { // First 2 bits = KS // Followed by a 0 bit // Last 5 bits = Atk string out; char KS = (char)0; char atk = (char)0; unsigned char temp = c; for (int I=7; I>=6; I--) { char bit = ((temp >> I) & 1); KS = (KS << 1 | bit); } for (int I=4; I>=0; I--) { char bit = ((temp >> I) & 1); atk = (atk << 1 | bit); } out = KS; out += atk; return out; } string expandSlRel(char c) { // First 4 bits = Crap // Last 4 bits = Both Values string out; char rel = (char)0; unsigned char temp = c; for (int I=3; I>=0; I--) { char bit = ((temp >> I) & 1); rel = (rel << 1 | bit); } out = rel; out += rel; return out; } struct OP { /* *Detune *Multiple *Total Level *Key Scale *Attack *Decay *Sustain (Second Decay) *Sus Level *Release */ // Single operator attributes unsigned char det; unsigned char mul; unsigned char tLevel; unsigned char kScale; unsigned char atk; unsigned char dec; unsigned char sus; unsigned char sLevel; unsigned char rel; // Compressed operator attributes unsigned char det_mul; unsigned char kS_atk; unsigned char sL_rel; }; struct Channel { char connection; char feedback; }; int main(int argc, char* argv[]) { if (argc <= 1) { cout << "Usage: " << argv[0] << " <Filename>" << endl; exit(1); } char *pFilename = argv[1]; //char inFileName[] = "test.y12"; //char outFileName[] = "test.opm"; Channel channel; OP M1; OP M2; OP C1; OP C2; ifstream inFile(pFilename, ios::in | ios::binary); char* readBuffer = new char [0]; /**************************************** *** READS *** ****************************************/ // Read M1 inFile.read(readBuffer, 1); M1.det_mul = readBuffer[0]; inFile.read(readBuffer, 1); M1.tLevel = readBuffer[0]; inFile.read(readBuffer, 1); M1.kS_atk = readBuffer[0]; inFile.read(readBuffer, 1); M1.dec = readBuffer[0]; inFile.read(readBuffer, 1); M1.sus = readBuffer[0]; inFile.read(readBuffer, 1); M1.sL_rel = readBuffer[0]; for (int I = 1; I <= 10; I++) { inFile.read(readBuffer, 1); } // Read M2 inFile.read(readBuffer, 1); M2.det_mul = readBuffer[0]; inFile.read(readBuffer, 1); M2.tLevel = readBuffer[0]; inFile.read(readBuffer, 1); M2.kS_atk = readBuffer[0]; inFile.read(readBuffer, 1); M2.dec = readBuffer[0]; inFile.read(readBuffer, 1); M2.sus = readBuffer[0]; inFile.read(readBuffer, 1); M2.sL_rel = readBuffer[0]; for (int I = 1; I <= 10; I++) { inFile.read(readBuffer, 1); } // Read C1 inFile.read(readBuffer, 1); C1.det_mul = readBuffer[0]; inFile.read(readBuffer, 1); C1.tLevel = readBuffer[0]; inFile.read(readBuffer, 1); C1.kS_atk = readBuffer[0]; inFile.read(readBuffer, 1); C1.dec = readBuffer[0]; inFile.read(readBuffer, 1); C1.sus = readBuffer[0]; inFile.read(readBuffer, 1); C1.sL_rel = readBuffer[0]; for (int I = 1; I <= 10; I++) { inFile.read(readBuffer, 1); } // Read C2 inFile.read(readBuffer, 1); C2.det_mul = readBuffer[0]; inFile.read(readBuffer, 1); C2.tLevel = readBuffer[0]; inFile.read(readBuffer, 1); C2.kS_atk = readBuffer[0]; inFile.read(readBuffer, 1); C2.dec = readBuffer[0]; inFile.read(readBuffer, 1); C2.sus = readBuffer[0]; inFile.read(readBuffer, 1); C2.sL_rel = readBuffer[0]; for (int I = 1; I <= 10; I++) { inFile.read(readBuffer, 1); } // Channel inFile.read(readBuffer, 1); channel.connection = readBuffer[0]; inFile.read(readBuffer, 1); channel.feedback = readBuffer[0]; inFile.close(); /**************************************** *** EXPAND *** ****************************************/ // M1 string out = expandDetMul(M1.det_mul); M1.det = out.at(0); M1.mul = out.at(1); out = expandKsAtk(M1.kS_atk); M1.kScale = out.at(0); M1.atk = out.at(1); out = expandSlRel(M1.sL_rel); M1.sLevel = out.at(0); M1.rel = out.at(1); char temp = fixTL(M1.tLevel); M1.tLevel = temp; // M2 out = expandDetMul(M2.det_mul); M2.det = out.at(0); M2.mul = out.at(1); out = expandKsAtk(M2.kS_atk); M2.kScale = out.at(0); M2.atk = out.at(1); out = expandSlRel(M2.sL_rel); M2.sLevel = out.at(0); M2.rel = out.at(1); temp = fixTL(M2.tLevel); M2.tLevel = temp; // C1 out = expandDetMul(C1.det_mul); C1.det = out.at(0); C1.mul = out.at(1); out = expandKsAtk(C1.kS_atk); C1.kScale = out.at(0); C1.atk = out.at(1); out = expandSlRel(C1.sL_rel); C1.sLevel = out.at(0); C1.rel = out.at(1); temp = fixTL(C1.tLevel); C1.tLevel = temp; // C2 out = expandDetMul(C2.det_mul); C2.det = out.at(0); C2.mul = out.at(1); out = expandKsAtk(C2.kS_atk); C2.kScale = out.at(0); C2.atk = out.at(1); out = expandSlRel(C2.sL_rel); C2.sLevel = out.at(0); C2.rel = out.at(1); temp = fixTL(C2.tLevel); C2.tLevel = temp; /**************************************** *** PRINT *** ****************************************/ fstream outFile("out.OPM", ios::out); // Heading outFile << "@:0 " << pFilename << "\n"; outFile << "LFO: 0 0 0 0 0\n"; outFile << "CH:" << setw(4) << "64" << setw(4) << (int)channel.feedback << setw(4) << (int)channel.connection << setw(4) << "0" << setw(4) << "0" << setw(4) << "120" << setw(4) << "0" << "\n"; outFile << "M1:" << setw(4) << (int)M1.atk << setw(4) << (int)M1.dec << setw(4) << (int)M1.sus << setw(4) << (int)M1.rel << setw(4) << (int)M1.sLevel << setw(4) << (int)M1.tLevel << setw(4) << (int)M1.kScale << setw(4) << (int)M1.mul << setw(4) << (int)M1.det << setw(4) << 0 << setw(4) << 0 << "\n"; outFile << "C1:" << setw(4) << (int)C1.atk << setw(4) << (int)C1.dec << setw(4) << (int)C1.sus << setw(4) << (int)C1.rel << setw(4) << (int)C1.sLevel << setw(4) << (int)C1.tLevel << setw(4) << (int)C1.kScale << setw(4) << (int)C1.mul << setw(4) << (int)C1.det << setw(4) << 0 << setw(4) << 0 << "\n"; outFile << "M2:" << setw(4) << (int)M2.atk << setw(4) << (int)M2.dec << setw(4) << (int)M2.sus << setw(4) << (int)M2.rel << setw(4) << (int)M2.sLevel << setw(4) << (int)M2.tLevel << setw(4) << (int)M2.kScale << setw(4) << (int)M2.mul << setw(4) << (int)M2.det << setw(4) << 0 << setw(4) << 0 << "\n"; outFile << "C2:" << setw(4) << (int)C2.atk << setw(4) << (int)C2.dec << setw(4) << (int)C2.sus << setw(4) << (int)C2.rel << setw(4) << (int)C2.sLevel << setw(4) << (int)C2.tLevel << setw(4) << (int)C2.kScale << setw(4) << (int)C2.mul << setw(4) << (int)C2.det << setw(4) << 0 << setw(4) << 0 << "\n"; outFile.close(); return 0; }
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!
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.