Skip to content

Instantly share code, notes, and snippets.

@mmha
Created October 22, 2016 00:06
Show Gist options
  • Save mmha/edd276eafc857d95f15200498823bb13 to your computer and use it in GitHub Desktop.
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
#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