Created
January 19, 2019 02:20
-
-
Save CobaltXII/942f52e22025295c87c5f35acd1b29af to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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