Skip to content

Instantly share code, notes, and snippets.

@SeolHa314
Created August 7, 2019 15:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SeolHa314/16124a9b3547521f03c6bf47d92cef8f to your computer and use it in GitHub Desktop.
Save SeolHa314/16124a9b3547521f03c6bf47d92cef8f to your computer and use it in GitHub Desktop.
Generate tone using OpenAL
#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, &currentState);
while(AL_PLAYING == currentState) {
alGetSourcei(streaming_source[index], AL_SOURCE_STATE, &currentState);
}
}
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