The Chatterbox => Creation Station => Topic started by: Spectere on December 18, 2010, 08:41:13 PM

Title: Spectere's Fantastique Softsynth
Post by: Spectere on December 18, 2010, 08:41:13 PM
I was kind of torn as to whether I should put this under "Computing" or "Creation Station," but this does sort of involve audio, so here it be.

First, a story:

Several months ago, a friend of mine was dicking around with Visual C# and wound up writing a simple program that would output tones through the PC speaker using Console.Beep.  It was kind of a fun experiment, but there were several problems with that approach.  For one, unless you're using a laptop or have a sound card old enough to have a PC speaker input (why hello there, Mr. AWE64) you would have no way of controlling the volume.  Even on systems that you could control the volume on, the volume control doesn't always work right (on many laptops, the PC speaker audio overpowers the regular audio and can only be muted, not lowered).  Secondly, the PC speaker driver doesn't even exist in 64-bit Windows.

The interface was kind of barebones, not really intended for long compositions, and was rather primitive, but it looked like a fun program to play with.  I asked for the source, he sent it, and I hacked in a quick square wave generator that pumped audio through DirectSound.  Then I quickly got bored and decided to turn it into a multichannel software synthesizer.  I have the basic waveforms (sine, square, sawtooth, and triangle), a white noise generator, and some variations of the basic waveforms (currently, Sine^2, Sine^4, and various duty cycles for square waves).  There is a per-channel attack/decay setting on the notes.  The sound was definitely better, but hammering songs into the program was still a pain in the ass.

The other day I got bored and decided to write support for patterns.  They're implemented similarly to Buzz Tracker patterns, though it isn't nearly as polished.  On the bright side, it's far easier to write songs in the thing now!  As such, I took the liberty of partially hand-converting a MOD file (I got most of the actual song, but I left out a couple of background channels) that I have.  It's from one of the games that come with MegaZeux...Alice should recognize it. :)  Here's the linky:

http://files.spectere.net/audio/beepmap/cs_tank.ogg (http://files.spectere.net/audio/beepmap/cs_tank.ogg)

The sound is rough since there is no interpolation or filtering to speak of, but I kind of like the output.  I'm kind of hesitant to continue developing it while it's tied to this particular program (BeepMap), however.  I don't think this program was meant to be what I wound up making it.  I should start working on something that's easier to write songs in.
Title: Re: Spectere's Fantastique Softsynth
Post by: Spectere on December 23, 2010, 07:13:29 PM
I updated the mixer to operate on 64-bit integers and mix down to 16-bit at the end of the rendering process.  Before, the entire mixing process was 16-bit.

Needless to say, this did wonders for reducing the amount of distortion in the waves when they were mixed together.  Here's the same sound clip as I posted before, rendered using the new version of WaveGen:

http://files.spectere.net/audio/beepmap/cs_tank64.ogg (http://files.spectere.net/audio/beepmap/cs_tank64.ogg)

I'm working on a new plugin-based softsynth that I have dubbed "Synthia."  I'm going to plug it into BeepMap (in fact, that's my main reason for switching to 64-bit integers -- Synthia uses those at the moment; though I am thinking about switching to doubles before I get too deep into this) just so that I can get all of the API-related kinks out of it before I use it for anything uber-serious.
Title: Re: Spectere's Fantastique Softsynth
Post by: Bobbias on December 23, 2010, 07:18:05 PM
Any chance I could get a look at the source code? I like audio stuff, but know next to nothing about actually programming audio.
Title: Re: Spectere's Fantastique Softsynth
Post by: Spectere on December 23, 2010, 07:52:36 PM
It's a big, sloppy mess at the moment since I'm trying to migrate to the plugin system.  I have a source snapshot from before I changed the mixer to 16-bit, but that's a sloppy mess for other reasons (namely, the program growing features like a cancer rather than any of them being planned out).

So I guess what I'm asking is whether you want the jumbled 64-bit codebase or the slightly saner 16-bit one. :p
Title: Re: Spectere's Fantastique Softsynth
Post by: Bobbias on December 23, 2010, 07:59:25 PM
Lol, if you can at least comment it enough that I know more or less what stuff does, the 54-bit one would be fine. I'm used to looking at my own code, which is almost guaranteed to be a sloppy mess... at best...
Title: Re: Spectere's Fantastique Softsynth
Post by: Spectere on December 24, 2010, 02:02:20 AM
54-bit?  .NET doesn't support that! :p

I'm kind of weird when it comes to comments.  I generally either comment steps (on the WAV writer, for instance, I label all of the parts of the WAV header so that it doesn't look like glorified line noise) or comment procedures.  Things like wave generation are generally pretty obvious, too, so I tend not to document those.

I also document things that I don't understand particularly well.

Actually, do you want the full program or just a wave generator and mixer?  I could whip up the latter pretty quickly if you want a no-nonsense demonstration of that.
Title: Re: Spectere's Fantastique Softsynth
Post by: Bobbias on December 24, 2010, 02:25:37 AM
54-bit?  .NET doesn't support that! :p

Then we make it support it. Then we port .NET to a ternary computing architecture!

I think I'd rather the whole program. I prefer seeing real implementations of things, rather than some specific program designed just to demonstrate one little thing, etc. Sometimes that can be kinda helpful, but unless the API is really retarded for something (y halo thar DirectX) it's better to see a real implementation, IMO. As long as things are commented properly, and it sounds like I'd be able to follow things pretty well from what you've described your commenting patterns as. Hell, that's pretty much what I do, lol.

I comment things I don't understand well, things that might be a bit confusing (especially if I get fancy and use something crazy like a ternary operator in some obscure place), steps a lot of the time (even just as a reminder for what  the steps for something actually are) or anything that might not be very straightforward.

Of course, my commenting is a lot more sporadic lately, but that's because the largest project I've worked on any time recently has been the WPF based video player I've started. It's mostly an experiment to see how WPF works, and to see what I can make for watching videos. (Un)fortunately there is a built in WPF thing for playing media, so most of the low level stuff is completely hidden (although ideally I'd like to replace that... But it seems that there is little to no real explanation of what I'd have to do in C# to actually make one of those... I'd love to use ffdshow or something to be able to leverage that thing and play media the right way, but it seems like there's no real nice way to deal with that in C#, other than use some trashy hack of an interface someone made ages ago... Or something that's rather incomplete.)

Anyway, I'm tired, and rambling on.
Title: Re: Spectere's Fantastique Softsynth
Post by: Spectere on December 24, 2010, 03:40:28 AM
brb, creating Malbolge.NET.

The main issue with seeing the real implementation in this case (and it's one that I'm coming to realize now that I'm trying to change synths) is that WaveGen was built around BeepMap, not vice versa.  As such, there is a ton of cruft in the synth itself to support the program.  Essentially, the program and WaveGen work together to act as a sequencer.  The program arranges the note and rest events and WaveGen processes the lists.  Due to the way it's designed, it would be practically impossible to make the program work in real-time.  The render-then-play process is required to make it work.

Because of all that, I decided to abandon bringing Synthia to the program and instead building that up as its own engine.  I made sure to put "Synthia is not a sequencer" in my design docs twice to remind myself of that.  I suppose it wouldn't be a terrible program to learn on, but I don't consider it to be a good way to write a synthesizer.  A simple wave generator?  Sure.  A softsynth?  Nah.

I'm starting on a new project from the bottom.  Synthia is going to handle mixing, plugin chains, and managing note events that are passed to it by programs.  The plugins will work similarly to Buzz Tracker, starting with a generator plugin, going through any number of effect plugins, and ending with output.  It won't have any output aside from raw stream data, but I'm going to write a program that does it for the sake of testing.  It's going to work per-sample, so it'll be possible to actually stream Synthia's output, something that isn't possible with BeepMap/WaveGen.  Furthermore, all audio processing will be done with double precision floats and converted to a desired bit depth.  I've found that dealing directly with integers is nothing short of a pain in the ass, particularly when it comes to dealing with peaks.  -1.0 and 1.0 make a hell of a lot more sense.  Plus, it'll be much easier to actually alert the calling program about clipping, since we're not dealing with maximum values anymore.

Whew, I'm kind of excited about this.  Ever since I've taken up what I like to call the "STFU and code" technique (namely, not once thinking about failing -- I used to obsess over maybes and wind up never getting anything done), I've been more driven to do this type of shit than ever.

With regards to comments, I'm a bit sporadic as well.  I distinctly recall doing actual work within a "for" statement (not inside of a block, but actually in the for statement, as the last parameter) and not really documenting it.  I'll have to look for that one.  Then there was always the comment I left when I hacked in multithreading support to a VB.NET program that I wrote a while ago.  It basically did nothing but talk about how awful and hackish the code was.  Oh well, both cases wound up working quite well.
Title: Re: Spectere's Fantastique Softsynth
Post by: Bobbias on December 24, 2010, 03:53:27 PM
Awesome, also, lol at the comment stuff. I remember in my Java programming class in highschool I used a ternary operator inside a for loop to actually do work... That confused the shit out of my teacher :P
Title: Re: Spectere's Fantastique Softsynth
Post by: Spectere on December 24, 2010, 06:06:29 PM
This was my piece of for abuse:

Code: [Select]
for(; resIndex <= resolutions.GetUpperBound(0) && resolutions[resIndex, 1] != displayHeight; resIndex++);
Fun fun!
Title: Re: Spectere's Fantastique Softsynth
Post by: Bobbias on December 24, 2010, 11:10:55 PM
Haha, wow, that's awesome. I love finding clever ways to abuse code like that, lol.
Title: Re: Spectere's Fantastique Softsynth
Post by: Spectere on December 25, 2010, 12:46:48 AM
http://files.spectere.net/projects/beepmap/beepmap-2.2-src.zip (http://files.spectere.net/projects/beepmap/beepmap-2.2-src.zip)

Merry Christmas, Bobbias!

That is a current snapshot of the source.  I stripped out the Synthia stuff and switched over the synth to use floating point instead of integers.

Here's what I was responsible for doing in the code:

- Everything related to WaveGen.
- Channel and pattern handling.
- The ability to save and load BeepMap songs.
- WAV export (though I think this is technically part of WaveGen).
- Some of the interface (additions related to the above, some cleanup and fixes, etc).

My friend did the base interface, the method for entering notes, and the piano interface.
Title: Re: Spectere's Fantastique Softsynth
Post by: Alice on December 31, 2010, 01:03:31 PM
http://files.spectere.net/audio/beepmap/cs_tank64.ogg (http://files.spectere.net/audio/beepmap/cs_tank64.ogg)
Whoa, sounds kewl B)
Title: Re: Spectere's Fantastique Softsynth
Post by: Spectere on December 31, 2010, 01:21:08 PM
Whoa, sounds kewl B)

Danke. ;D

I also converted one pattern from CV_BALON, which I think sounds a bit better.  That was before I actually put pattern support in the sequencer, so it would have been a pain in the ass to do the entire song.  Perhaps I'll finish that up and post it next! :o
Title: Re: Spectere's Fantastique Softsynth
Post by: Alice on December 31, 2010, 03:53:52 PM