Skip to content

Instantly share code, notes, and snippets.

@AnanthVivekanand
Last active August 7, 2019 18:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AnanthVivekanand/ca95a9d7ff52ad1ad09de6568af5bc4b to your computer and use it in GitHub Desktop.
Save AnanthVivekanand/ca95a9d7ff52ad1ad09de6568af5bc4b to your computer and use it in GitHub Desktop.
Basic sound synth using SDL_audio, with some examples of frequency manipulation on a sine wave.
	SDL_Init(SDL_INIT_AUDIO);
	SDL_AudioSpec spec, aspec;
	SDL_zero(spec);
	spec.freq = 48000; //declare specs
	spec.format = AUDIO_S16SYS;
	spec.channels = 1;
	spec.samples = 4096;
	spec.callback = callback;
	spec.userdata = NULL;

This portion declares specifications of our audio. We set our sample rate, format, and pass in a callback here.

	int id;
	if ((id = SDL_OpenAudioDevice(nullptr, 0, &spec, &aspec, SDL_AUDIO_ALLOW_ANY_CHANGE)) <= 0 )
	{
	  fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
	  exit(-1);
	}

This opens an audio device and adds it's reference to id. An alternative way of doing the same thing would be to:

SDL_AudioDeviceID audio_device;
audio_device = SDL_OpenAudioDevice(nullptr, 0, &spec, &aspec, SDL_AUDIO_ALLOW_ANY_CHANGE);
    	  //Play A
          freq = 440;
          SDL_Delay(3000);

	  //Play middle C
          freq = 261.6256;
          SDL_Delay(3000);

freq is a variable that is used in calculations inside the callback. We can modify freq inside of our while loops to change the "note" of our sound. A has a frequency of 440, so if we set freq to that value, our sound output changes to that note! Similarly with middle C, which has a frequency of 261.6256. You can find a handy table of piano notes and their frequencies here. You can also make some fancy sounds by looping through increasing frequencies.

Callback has some interesting code that dictates how sound is produced. Sound is controlled by 2 variables: time and freq. Together, they calculate values and place them into a buffer that gets read and played.

#include <SDL2/SDL.h>
#include <SDL2/SDL_audio.h>
#include <stdio.h>
#include <math.h>
#define PI2 6.28318530718
float time = 0;
float freq = 440;
void callback(void* userdata, Uint8* stream, int len) {
short * snd = reinterpret_cast<short*>(stream);
len /= sizeof(*snd);
for(int i = 0; i < len; i++) //Fill array with frequencies, mathy-math stuff
{
snd[i] = 32000 * sin(time);
time += freq * PI2 / 48000.0;
if(time >= PI2)
time -= PI2;
}
}
int main(int argc, char ** argv)
{
SDL_Init(SDL_INIT_AUDIO);
SDL_AudioSpec spec, aspec; // the specs of our piece of "music"
SDL_zero(spec);
spec.freq = 48000; //declare specs
spec.format = AUDIO_S16SYS;
spec.channels = 1;
spec.samples = 4096;
spec.callback = callback;
spec.userdata = NULL;
//Open audio, if error, print
int id;
if ((id = SDL_OpenAudioDevice(nullptr, 0, &spec, &aspec, SDL_AUDIO_ALLOW_ANY_CHANGE)) <= 0 )
{
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
exit(-1);
}
/* Start playing, "unpause" */
SDL_PauseAudioDevice(id, 0);
while(true) //Stall for time while audio plays
{
//Play A
freq = 440;
SDL_Delay(3000);
//Play middle C
freq = 261.6256;
SDL_Delay(3000);
//if needed, you can do cool stuff here, like change frequency for different notes:
//https://en.wikipedia.org/wiki/Piano_key_frequencies
//Another cool thing:
/*
while(true)
{
for(freq = 440; freq < 880; freq += 10)
SDL_Delay(10);
for(freq = 870; freq > 450; freq -= 10)
SDL_Delay(10);
} */
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment