I'm thinking about using a realtime FM synth for music and sound effects in my next game. I'd write a library myself, but I don't want to waste my time if there's already something good out there. The thing is, google turned up no results. Am I going to have to get cracking on my own?
Name:
Anonymous2009-12-13 20:52
>>35
I wrote one back in 2003. It's as easy as you think.
Some junk like: audio[i] = sin((freq * i * 2 * M_PI / SAMPLE_RATE) * normalize(mod_signal[i]))
or whatever. I didn't check that so you should, or wait for someone else to go full retard on me for leaving out the semicolon and they'll probably catch the meaningful mistakes while they're at it. Convert it to LUTs and add AA/interpolation if you like (probably best for FM.) normalize() makes an element of audio[] suitable for use as a modulation signal, and exactly how it works is dependent on your data type.
For primary operators, initialize an empty modulation signal buffer to whatever is neutral and use the same effect. This way you can feedback into the same operator by writing to the init'd mod buffer.
Speaking of data types, use floats with DC0 = 0. Least of all benefits of this is that simply zeroing the mod buffer will be correct initialization.
I think that's right for the midi spec but I can't remember. For some reason I have it split up like this in some code I have laying around:
r = note%12;
q = note/12;
f = pow(SEMITONE_RATIO, r);
f *= pow(2, q -4);
... probably using those extra values for some other thing but I can't be arsed to check.
There you go. Route those into each other according to whatever crazy idea you have and do ADSR (sample data multiplier maps) on the 'key' events.
If you are tempted to use LADSPA plugins for any reason, and happen to be operating in stereo but are stuck with a mono effect:
M = (L+R)/2;
S = (L-R)/2;
L = M + S;
R = M - S;
L and R being left and right channels, M (mid) being the mono signal and S (side) being the stereo phase signal. Run the mono process on M and take the output as M', combine M' with S to get the (processed) L' and R' values. Not for use with effects that demean the stereo image.
Name:
Anonymous2009-12-13 21:36
>>41 #define SEMITONE_RATIO (1.0594630943592)
FUCK YOU
>>45
Oh well the value is accurate* and the name is appropriate if not ideal.
*: I know some prefer a fixed table with fudged values on the grounds that certain ratios come out better, but a) I hate that and b) the FM engines I've investigated don't do it.
Name:
Anonymous2009-12-14 0:06
>>46
The value is worthless. Play a real interval, why don't you? The best thing about writing your own synth is that you don't have to put up with whatever shitty scale the majority assumes as universal.
>>47
You're shitting on me because you don't like the dominant western temperament? It's piss easy to implement and more importantly probably what OP is looking for. Take it up with someone else.
Name:
Anonymous2009-12-14 2:19
Going with 2612 emulation is a pretty good choice since you can dump instruments from any Genesis game using Gens KMod. Also MAME emulates the 2612 and all their code is freely available.
Of course, the 2612 is a pretty limited chip in a number of ways and it would probably be easier to compose for something more powerful. But you could still use 2612 code as a starting point that you could then turn into something cooler if you wanted to.
It's piss easy to implement
Just like everything else?
probably what OP is looking for.
Wow, you're a dickhead. OP didn't even do anything to you.
Name:
Anonymous2009-12-14 3:40
>>50
SNES instruments aren't FM, they're just samples.
Name:
Anonymous2009-12-14 3:48
>>37
IIRC OPL and OPL2 (AdLib, the original Sound Blaster) had only two operators per voice. OPL3 (SB16) could pair channels for four-operator voices, later versions added more operators and algorithms.
The Sega Saturn has a moderately interesting scheme which I haven't seen in other chips (though I assume the Dreamcast's one works the same). Each of the 32 channels can serve as an FM operator, but as there is no waveform ROM they all play either noise generated by the chip or a waveform from RAM which can be an "oscillator" signal or a normal sample. Each channel can itself have two FM modulation sources that are freely selectable, so you're not limited to a built-in set of FM algorithms. Each channel, including those working as FM operators, can be sent to either the output mixer (with individual pan and volume settings) or to one of the built-in DSP's 16 inputs for effects processing.
>>50,52
Yes, SNES is so much better than Genesis, and that's because it isn't shitty FM instruments. Nintendo hopped the wavetable train before most other people, and it paid off tremendously for them.
(Disagree? I defy you to make the claim that any FM-based MIDI output is even a fraction as realistic-sounding or even decent as a wavetable player. It's an absurd claim, the only thing FM can do passably is a bell. Everything else will sound like varying degrees of ass.)
>>53
SID is cheeseball three-channel junk that's only capable of making blippy noises, and you're a stupid hipster for pretending it's any good.
Name:
Anonymous2009-12-14 10:58
>>56
Congratulations, you have a shitty taste in old musics.
Nintendo still leads with the best sound in there games. They now use live Orchestras for there music, and if you want an uber bad ass game I suggest you do the same.
t x = case lookup x tones of
Just y -> (tone y 2000 0.75 0) :: [Int]
Nothing -> []
main :: IO ()
main = do
let notesl =["d2",
"d3",
"b2",
"f2",
"b2",
"b1",
"c2",
"d2",
"e2"]
let notes = ["##", "g3", "a3",
"b3", "d4", "c4",
"c4", "e4", "d4", -- from d4
"d4", "g4", "f4",
"g4", "d4", "c4",
"g3", "a3", "b3",
"c4", "d4", "e4",
"d4", "c4", "b3",
"a3", "b3", "g3"] -- end
{-- "f3", "g3", "a3",
"d3", "f3", "a3",
"c4", "b3", "a3",
"b3", "g3", "a3",
"b3", "d4", "c4",
"c4", "e4", "d4",
"d4", "g4", "f4",
"g4", "d4", "b3",
"g3", "a3", "b3"]--}
-- "e3", "d4", "c4"
-- ]
let blank = t "##"
let inter = (intersperse "##" notes)
let interl = (intersperse "##" notesl)
let strs = concat (map t notes)
let strsl = concat (map (\ x -> (concat (replicate 5 (t x))) ++ blank) notesl)
let bytes = map chr (zipWith (+) strs strsl)
hPutStr stdout bytes
Name:
Anonymous2009-12-14 14:41
>>57
ONE WORD, THE FORCED BACKTRACKING OF SUPER METROID
THREAD OVER
Name:
Anonymous2009-12-14 14:49
>>56
Maybe if you're retarded enough to think the purpose of a synth is to not sound like a synth. Hello: if you want it to sound like the real thing, play the real thing.
>>67
Just after the python post and everything. There should be some kind of prize for you.
Name:
Anonymous2009-12-14 14:58
>>68
A synthesizer is supposed to synthesize the sounds of real instruments. The more accurate the sound is the better the synthesizer is. Enjoy you're inferior sounds while you can, criminal scum.