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!
Music
#196
Posted 18 January 2009 - 12:45 AM
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!
#197
Posted 18 January 2009 - 04:41 AM
I'll explain.
Here's the values for OP1 channel 3 of the exercise music from Dr. Robotnik's Mean Bean Machine:
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:
/* -*- 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; }
#198
Posted 18 January 2009 - 09:23 AM
McGuirk, on Jan 16 2009, 06:38 PM, said:
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).
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!
#199
Posted 19 January 2009 - 09:50 AM
#200
Posted 19 January 2009 - 11:57 AM
#201
Posted 20 January 2009 - 01:47 AM
Here is a zip file containing all the FM voices from Sonic 1 (and a few square wave voices too, I think) in opm format. To load opm files into VOPM, use the import function. If you want to use these voices in something that uses tfi files, look for vopmxtfi. Thanks.
#202
Posted 22 January 2009 - 08:22 PM
Right now though, let's get on track. What I want to hear is some concepts of what you think the next Sonic game should sound like.
Like so!
(I think that's by Twaker.)
#203
Posted 22 January 2009 - 10:52 PM
muteKi, on Jan 22 2009, 03:16 PM, said:
That first one is ok, but it makes me think "end credits" more than it does "first tropical zone"
muteKi, on Jan 22 2009, 04:20 PM, said:
Chimpo, on Jan 22 2009, 05:22 PM, said:
Like so!
I sincerely hope we aren't using these kinds of instrumentation. The first one just sounds poor quality and in the wrong style. The second one, The melody might be ok, but I can't get past the sound. I don't know what that is in the front, but it sounds like the universe itself took a cosmic dump
#204
Posted 23 January 2009 - 05:40 AM
Because...
http://steevboss.free.fr/The%20Zone,%20The...Glam%20City.mp3
http://steevboss.fre...watertemple.mp3
http://steevboss.free.fr/endgame.mp3
http://steevboss.free.fr/skysurf2.mp3
(yes, I'm posting it again)
#206
Posted 23 January 2009 - 09:55 AM
MIDI:
+: probably the most widely used format, a whole lot of people (including Tweaker) are familiar with it
+: can be speeded up and transposed in real time
+: files are tiny
+: although not part of the MIDI standard, it's easy to set up a loop point (see Sonic & Knuckles Collection)
-: not very flexible
-: their outcome is hardware depending (though most computer nowadays just stream MIDIs through the Microsoft Synthetizer)
Modules:
+: highly flexible, with a module you can recreate everything, from a chiptune, to a MIDI, to a 2612, to... whatever you want
+: can be speeded up and transposed in real time
+: support looping and jumping natively
+/-: files, while being usually bigger than MIDIs, are always much smaller than WAVs, and often smaller than MP3s
-: not everyone is familiar enough with trackers to completely use their potential. Picking module files would restrict the number of eligible composers
MP3:
+: just like module files, mp3s can sound like whatever you want, with the additional benefit that you can use any program to make them, thus giving everyone the chance to contribute songs
-: files tend to be big
-: a complex FFT algorithm is needed to indipendently alter speed and pitch
-: hard to loop
WAV:
No.
This is a start, if anyone wants to elaborate from here, feel free to.
#207
Posted 23 January 2009 - 10:17 AM
Phoebius, on Jan 23 2009, 12:40 PM, said:
Because...
http://steevboss.free.fr/The%20Zone,%20The...Glam%20City.mp3
http://steevboss.fre...watertemple.mp3
http://steevboss.free.fr/endgame.mp3
http://steevboss.free.fr/skysurf2.mp3
(yes, I'm posting it again)
Simon Stalenhag kicks @$$
#209
Posted 24 January 2009 - 06:37 PM
nineko, on Jan 23 2009, 09:55 AM, said:
MIDI:
+: probably the most widely used format, a whole lot of people (including Tweaker) are familiar with it
+: can be speeded up and transposed in real time
+: files are tiny
+: although not part of the MIDI standard, it's easy to set up a loop point (see Sonic & Knuckles Collection)
-: not very flexible
-: their outcome is hardware depending (though most computer nowadays just stream MIDIs through the Microsoft Synthetizer)
Modules:
+: highly flexible, with a module you can recreate everything, from a chiptune, to a MIDI, to a 2612, to... whatever you want
+: can be speeded up and transposed in real time
+: support looping and jumping natively
+/-: files, while being usually bigger than MIDIs, are always much smaller than WAVs, and often smaller than MP3s
-: not everyone is familiar enough with trackers to completely use their potential. Picking module files would restrict the number of eligible composers
MP3:
+: just like module files, mp3s can sound like whatever you want, with the additional benefit that you can use any program to make them, thus giving everyone the chance to contribute songs
-: files tend to be big
-: a complex FFT algorithm is needed to indipendently alter speed and pitch
-: hard to loop
WAV:
No.
This is a start, if anyone wants to elaborate from here, feel free to.
And what if someone wants to port to Sega Genesis? Or to MS-DOS? Obviously the two won't work right; Genesis can't read from any of these types, and MS-DOS needs drivers.
#210
Posted 24 January 2009 - 10:03 PM
Andlabs, on Jan 24 2009, 03:37 PM, said:
Snowball's chance in hell with E02. Let's not have this discussion again!
For what it's worth, I'm vouching for modules. Sure, Nineko is the only person around here who's familiar with them, but there's no reason why you people couldn't work with the format if you actually tried. I'd never done anything music related in my life, and even I was able to wring something decent out of Modplug in half an hour.

00