Created
October 22, 2016 00:06
-
-
Save mmha/edd276eafc857d95f15200498823bb13 to your computer and use it in GitHub Desktop.
Old toy code to try out libopus with the 3D sound capabilities of OpenAL
This file contains hidden or 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 <iostream> | |
#include <memory> | |
#include <cmath> | |
#include <unistd.h> | |
#include <time.h> | |
#include <opus/opusfile.h> | |
#include <AL/al.h> | |
#include <AL/alc.h> | |
int main(int argc, const char *argv[]) | |
{ | |
if(argc != 2) | |
{ | |
std::cerr << "Usage: " << argv[0] << "file.opus\n"; | |
return EXIT_FAILURE; | |
} | |
auto file = op_open_file(argv[1], nullptr); | |
if(!file) | |
{ | |
std::cerr << "Could not open " << argv[1] << std::endl; | |
return EXIT_FAILURE; | |
} | |
int channelCount = op_channel_count(file, -1); | |
size_t pcm_buffersize = channelCount * op_pcm_total(file, -1); | |
auto pcm_buffer = std::make_unique< int16_t[] >(pcm_buffersize); | |
int16_t *i = pcm_buffer.get(); | |
while(i < pcm_buffer.get() + pcm_buffersize) | |
{ | |
auto sampleCount = channelCount * op_read(file, i, pcm_buffersize - (i - pcm_buffer.get()), nullptr); | |
if(sampleCount < 0) | |
break; | |
i += sampleCount; | |
} | |
// Downmix to mono | |
size_t mono_buffersize = pcm_buffersize / channelCount; | |
if(channelCount > 1) | |
{ | |
for(size_t i = 0; i < mono_buffersize; ++i) | |
{ | |
int32_t sum = 0; | |
for(int j = 0; j < channelCount; ++j) | |
sum += pcm_buffer[i * channelCount + j]; | |
pcm_buffer[i] = sum / channelCount; | |
} | |
} | |
ALCdevice *device = alcOpenDevice(NULL); | |
if(!device) | |
return EXIT_FAILURE; | |
ALCcontext *context = alcCreateContext(device, NULL); | |
alcMakeContextCurrent(context); | |
if(!context) | |
return EXIT_FAILURE; | |
ALuint al_buffer, al_source; | |
alGenBuffers(1, &al_buffer); | |
alGenSources(1, &al_source); | |
alBufferData(al_buffer, AL_FORMAT_MONO16, pcm_buffer.get(), mono_buffersize * sizeof(int16_t), 48000); | |
ALfloat sourcePos[] = {1.0, 0.0, 0.0}; | |
ALfloat sourceVel[] = {1.0, 0.0, 0.0}; | |
ALfloat listenerPos[] = {0.0, 0.0, 0.0}; | |
ALfloat listenerVel[] = {0.0, 0.0, 0.0}; | |
ALfloat listenerOri[] = {0.0, 0.0, -1.0, 0.0, 1.0, 0.0}; | |
alListenerfv(AL_POSITION, listenerPos); | |
alListenerfv(AL_VELOCITY, listenerVel); | |
alListenerfv(AL_ORIENTATION, listenerOri); | |
alSourcei(al_source, AL_BUFFER, al_buffer); | |
alSourcefv(al_source, AL_POSITION, sourcePos); | |
alSourcefv(al_source, AL_VELOCITY, sourceVel); | |
alSourcei(al_source, AL_LOOPING, AL_TRUE); | |
alSourcePlay(al_source); | |
struct timespec t0, tnow; | |
clock_gettime(CLOCK_MONOTONIC, &t0); | |
while(1) | |
{ | |
clock_gettime(CLOCK_MONOTONIC, &tnow); | |
float dt = tnow.tv_sec - t0.tv_sec + 1e-9 * (tnow.tv_nsec - t0.tv_nsec); | |
float T = 1.0/3.0; | |
float omega = T * 2 * M_PI * dt; | |
sourcePos[0] = sourceVel[0] = cos(omega); | |
sourcePos[1] = sourceVel[1] = sin(omega); | |
alSourcefv(al_source, AL_POSITION, sourcePos); | |
alSourcefv(al_source, AL_VELOCITY, sourceVel); | |
} | |
alDeleteSources(1, &al_source); | |
alDeleteBuffers(1, &al_buffer); | |
alcMakeContextCurrent(NULL); | |
alcDestroyContext(context); | |
alcCloseDevice(device); | |
return 0; | |
} | |
/* | |
compile with (assuming Linux, gcc, libopus, libopusfile and OpenAL Soft): | |
g++ -I /usr/include/opus Opustest.cpp -lopus -lopusfile -lopenal | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment