10
\$\begingroup\$

I'm working on an engine for a retro-style game in C. I'm looking for a sound library that would produce chip sounds from code...I want to make my own simple chiptune tracker for the engine to create music. Does such a thing exist?

I'd also be interested in a library to use .nsf files in my project.

I'm using Linux for development.

\$\endgroup\$
7
  • \$\begingroup\$ I think this question falls under the "Which technology to use" category. Though, typically these niche requests don't generate a large list of responses, I think it's not constructive. \$\endgroup\$
    – House
    Commented Jan 8, 2013 at 1:02
  • \$\begingroup\$ Well, the problem is that I can't seem to find anything. I don't even know where to start...Every library I've found focuses on loading from files such as .wav. I can use libmikmod if I want to just load a .mod or .xm module, but that's not what I want to do. \$\endgroup\$
    – rzrscm
    Commented Jan 8, 2013 at 1:13
  • \$\begingroup\$ I don't think this really falls under game development. It is more general media than games. \$\endgroup\$ Commented Jan 8, 2013 at 1:24
  • \$\begingroup\$ Try searching for "mod tracker" or maybe "demoscene tracker" for a more general background and resources. \$\endgroup\$ Commented Jan 8, 2013 at 2:30
  • 1
    \$\begingroup\$ I personally find this question a good question. Since I like to program retro-style games it is hard to find resources for things like this without being part of some obscure community. \$\endgroup\$ Commented Jan 8, 2013 at 5:10

4 Answers 4

3
\$\begingroup\$

Probably not a correct answer but here is a library of various audio engines

(Scroll down to the second segment for audio libraries)

At least 9 out of 12 engines go with C. Most of them also support tracker files. Which is not so different than nsf ( I assume these are NES music files ) files.

\$\endgroup\$
0
17
\$\begingroup\$

Sure you can, it's just not trivial to get it sounding "nice".

I don't know how to do it in Linux, but if you can play a PCM buffer, all you have to do is fill it with whatever you want.

So supposing your buffer is set to play in monaural, signed 16-bit samples, at 44100 samples per second, creating a pure (sinusoidal) A4 sound (440 Hz) is as simple as

int16_t buffer[44100];
float frequency = 440.0f;
float sampling_ratio = 44100.0f;
float amplitude = 0.5f;
float t;
for (int i = 0; i < 44100; i++)
{
    float theta = ((float)i / sampling_ratio) * PI;
    buffer[i] = (int16_t)(sin(theta * frequency) * 32767.0f * amplitude);
}

However, this sound is probably very dull for your interests, so you have to do some more complicated things. In general, there are two types of sound synthesis: Additive and Subtractive. There are many others, but these two are probably the most simple ones. Today I'll just talk about additive synthesis.

For additive synthesis, you do the same thing as I did just up there, but instead of just using one frequency at one amplitude, you add several waves together. This is just like pressing several keys on a piano at the same time. So you modify your code to look something like this:

void add_sine_wave(int16_t* buffer, int buffer_length, float frequency, float sampling_ratio, float amplitude)
{
    for (int i = 0; i < buffer_length; i++)
    {
        float theta = ((float)i / sampling_ratio) * M_PI;
        // make sure to correct for overflows and underflows
        buffer[i] += (int16_t)(sin(theta * frequency) * 32767.0f * amplitude);
    }
}

and then use it like this:

int16_t buffer[44100];
memset(buffer, 0, sizeof(buffer));
// Create an A Major chord
add_sine_wave(buffer, 44100, 440.0f, 44100.0f, 0.5f);
add_sine_wave(buffer, 44100, 554.37f, 44100.0f, 0.5f);
add_sine_wave(buffer, 44100, 659.26f, 44100.0f, 0.5f);

By the way, I'm getting my frequencies from here (I'm using equal temperament, but there are lots of other tunings available).

Notice that so far I've only been using sine waves, but old synthesizers also support square, triangular and saw waves as well, each with its own interesting sound properties. Implementing these is pretty straightforward.

Other things you can do to increase the variety of sounds you can create are:

  1. Amplitude modulation: Changing the amplitude of the wave throughout the buffer
  2. Frequency modulation: Changing the frequency of the wave throughout the buffer
  3. Reverb: Repeating a sample by changing its shape and position in the buffer. Itself a very complex topic.
  4. Enveloping: Changing the amplitude of a sample to give it more life

The point here is that the techniques themselves are not very difficult, so you don't really need a library to abstract them for you. It's using them to create interesting sounds what is difficult.

One final note. When experimenting with sound like this, it may be really useful to save your data to WAV files, and then visualizing them in some software like Audacity. That way you can see what you're doing more clearly.

\$\endgroup\$
9
  • \$\begingroup\$ +1 for rolling your own. I'm not seeing many Linux libs that would support NSF. But, here's the spec: webcache.googleusercontent.com/… \$\endgroup\$ Commented Jan 8, 2013 at 3:23
  • \$\begingroup\$ Thank you for the info. I might stick with creating .nsf files for my project now that I realize how much I'd need to put into getting the sounds to sound just right. \$\endgroup\$
    – rzrscm
    Commented Jan 8, 2013 at 11:29
  • \$\begingroup\$ +1 I assumed any answer to this question would be tedious. I don't know a lot about AM/FM but generally waves will get routed to a filter first, as in subtractive synthesis. Also, your example of multiple piano notes is correct, a better example would just be one note! A single piano note will create multiple harmonics which gives it it's timbre. A piano will create >5 waves added together whereas in most synths 2 or 3 will be fine. \$\endgroup\$
    – Tony
    Commented Jan 8, 2013 at 16:13
  • \$\begingroup\$ what is the correct way to check overflows in the "add_sine_wave" function? \$\endgroup\$
    – eadmaster
    Commented Oct 30, 2014 at 2:59
  • \$\begingroup\$ @eadmaster: I meant clipping. Make sure the value fits in a short before you cast it to a short. \$\endgroup\$ Commented Oct 30, 2014 at 4:09
4
\$\begingroup\$

For chiptune sound effects, there's one definite answer: sfxr.

It's a standalone application that you can use to generate samples, but the source code is also available should you want to integrate it to your code.

\$\endgroup\$
3
\$\begingroup\$

I can personally recommend Blargg's audio libraries. Something that may be of particular interest to you is his Blip_Buffer.

Blargg's site has several "retro" audio synthesizers, and I am actively using his Game_Music_Emu to play NSF files in a Mega Man clone I am writing.

Many of the libraries are written in C++ but some provide a C interface as well.

\$\endgroup\$
1
  • \$\begingroup\$ Definitely going to try some of these out...They might be just what I'm looking for since I'm working on a game engine that's intended to emulate the look and feel of an NES game. \$\endgroup\$
    – rzrscm
    Commented Jan 8, 2013 at 11:18

Not the answer you're looking for? Browse other questions tagged .