Skip to content

Instantly share code, notes, and snippets.

@CobaltXII
Created January 19, 2019 02:20
Show Gist options
  • Save CobaltXII/942f52e22025295c87c5f35acd1b29af to your computer and use it in GitHub Desktop.
Save CobaltXII/942f52e22025295c87c5f35acd1b29af to your computer and use it in GitHub Desktop.
#include <SDL2/SDL.h>
#include <cmath>
// An audio driver. This audio driver will define a callback that will
// generate a waveform which is passed to SDL. SDL passes this waveform to
// the OS, where it is output to a physical device.
struct audio_driver
{
SDL_AudioSpec audio_spec;
// Default constructor.
audio_driver()
{
// The 'freq' parameter specifies amount of samples to take per
// second. A higher frequency corresponds to a higher quality of
// sound.
audio_spec.freq = 48000;
// The 'format' parameter specifies the precision of each sample. A
// higher format size corresponds to a broader range of possible
// sounds.
audio_spec.format = AUDIO_S16SYS;
// The 'channels' parameter specifies the amount of output channels. 2
// is stereo, and 1 is mono.
audio_spec.channels = 1;
// The 'samples' parameter specifies the size of the stream buffer.
// The value of 4096 is suggested by SDL.
audio_spec.samples = 4096;
// The 'userdata' parameter specifies the arbitrary data to pass to
// the audio callback function. The pointer to this object is used to
// allow access to the contents of this object.
audio_spec.userdata = this;
// The 'callback' parameter specifies the callback function to use to
// generate audio samples. This callback function will invoke the
// waveform generator from it's given userdata, which is set above to
// the 'this' pointer.
audio_spec.callback = [](void* userdata, Uint8* stream, int len) -> void
{
((audio_driver*)(userdata))->waveform((short*)stream, len / 2);
};
// Open the audio device.
SDL_AudioDeviceID audio_device = SDL_OpenAudioDevice(NULL, 0, &audio_spec, &audio_spec, 0);
// Pause the audio device.
SDL_PauseAudioDevice(audio_device, 0);
}
// Waveform generator (plays a song).
int row = 63;
int freq1;
int freq2;
int freq2b;
int count = 0;
void waveform(short* target, int num_samples)
{
static const char song[] = "057+5420+%7%+%7%5%4%2%457%0%0%754%2%+%%%5%542%457%0%0%042%2#+%!#0%+%$%%%";
for (int position = 0; position < num_samples; --count)
{
if (!count)
{
row = (row + 1) % 64;
freq1 = 17 + std::exp2(song[row + 8] / 12.0);
if (song[row + 8] == '%')
{
freq1 = 0;
}
freq2 = 17 * std::exp2(song[row / 8] / 12.0);
if (row & 2)
{
freq2b = freq2 / 2;
}
else
{
freq2b = 0;
}
count = 5400 + 540 * (row & 2);
}
target[position++] = (8 * (((count + 85) * freq1 & 32767) - 16384) + 1 * (((count + 4) * freq1 * 8 & 32767) - 16384) + 3 * (((count + 57) * freq2 / 4 & 32767) - 16384) + 8 * (((count + 23) * freq2b & 32767) - 16384)) * count >> 16;
}
}
};
int main(int argc, char** argv)
{
SDL_InitSubSystem(SDL_INIT_AUDIO);
audio_driver driver;
while (true)
{
SDL_Delay(500);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment