Created
August 7, 2019 15:15
-
-
Save SeolHa314/16124a9b3547521f03c6bf47d92cef8f to your computer and use it in GitHub Desktop.
Generate tone using OpenAL
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 <stdio.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#include <AL/al.h> | |
#include <AL/alc.h> | |
#define SAMPLE_RATE 48000 | |
ALCdevice* openal_output_device; | |
ALCcontext* openal_output_context; | |
ALuint internal_buffer[2]; | |
ALuint streaming_source[2]; | |
void init_al() { | |
const char * defname = alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER); | |
openal_output_device = alcOpenDevice(defname); | |
openal_output_context = alcCreateContext(openal_output_device, NULL); | |
alcMakeContextCurrent(openal_output_context); | |
} | |
void gen_buffers(int num) { | |
alGenBuffers(num, internal_buffer); | |
} | |
short* make_sine(int freq, int seconds) { | |
double pi = M_PI; | |
size_t buf_size = seconds * SAMPLE_RATE; | |
short* samples = (short *)malloc(sizeof(short) * buf_size); | |
for(int i = 0; i < buf_size; i++) { | |
samples[i] = 32760 * sin((2.f * pi * freq) / SAMPLE_RATE * i); | |
} | |
return samples; | |
} | |
short* make_triangular(int freq, int seconds) { | |
size_t buf_size = seconds * SAMPLE_RATE; | |
short now = 0; | |
short* samples = (short *)malloc(sizeof(short) * buf_size); | |
for(int i = 1; i <= buf_size; i++) { | |
samples[i] = 4 / freq * ((float)(i / SAMPLE_RATE) - freq / 2 * floor(2 * (i / SAMPLE_RATE) / freq + 0.5f)) * powf(-1, floor(2 * (i / SAMPLE_RATE) / freq + 0.5f)); //from wikipedia | |
} | |
return samples; | |
} | |
short* make_sawtooth(int freq, int seconds) { | |
size_t buf_size = seconds * SAMPLE_RATE; | |
short* samples = (short *)malloc(sizeof(short) * buf_size); | |
for(int i = 0; i < buf_size; i++) { | |
samples[i] = (i % (SAMPLE_RATE / freq)) / (float)freq * 32760 * 2 - 32760; | |
} | |
return samples; | |
} | |
void load_buffer(short* samples, int seconds, int index) { | |
alBufferData(internal_buffer[index], AL_FORMAT_MONO16, samples, SAMPLE_RATE * seconds, SAMPLE_RATE); | |
free(samples); | |
alGenSources(1, &streaming_source[index]); | |
alSourcei(streaming_source[index], AL_BUFFER, internal_buffer[index]); | |
} | |
void play_buffer(int index) { | |
ALenum currentState; | |
alSourcePlay(streaming_source[index]); | |
alGetSourcei(streaming_source[index], AL_SOURCE_STATE, ¤tState); | |
while(AL_PLAYING == currentState) { | |
alGetSourcei(streaming_source[index], AL_SOURCE_STATE, ¤tState); | |
} | |
} | |
void delete_source_buffer(int index) { | |
alSourcei(streaming_source[index], AL_BUFFER, 0); | |
alDeleteSources(1, &streaming_source[index]); | |
alDeleteBuffers(1, &streaming_source[index]); | |
} | |
void close_device() { | |
alcMakeContextCurrent(NULL); | |
alcDestroyContext(openal_output_context); | |
alcCloseDevice(openal_output_device); | |
} | |
int al_check_error(const char * given_label) { | |
ALenum al_error; | |
al_error = alGetError(); | |
if(AL_NO_ERROR != al_error) { | |
printf("ERROR %s %s\n", alGetString(al_error), given_label); | |
return al_error; | |
} | |
return 0; | |
} | |
int main() { | |
init_al(); | |
gen_buffers(2); | |
short **waves = (short **)malloc(sizeof(short *) * 2); | |
waves[0] = make_sine(880, 2); | |
waves[1] = make_sawtooth(440, 2); | |
for(int i = 0; i < 2; i++) { | |
load_buffer(waves[i], 2, i); | |
al_check_error("loadbuffer error"); | |
} | |
play_buffer(0); | |
play_buffer(1); | |
al_check_error("playbuffer error"); | |
delete_source_buffer(0); | |
delete_source_buffer(1); | |
close_device(); | |
} | |
// Compile with flag -lopenal -lm |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment