An SDL2-based implementation of OpenAL in a single C file.

MojoAL

MojoAL is a full OpenAL 1.1 implementation, written in C, in a single source file. It uses Simple Directmedia Layer (SDL) 2.0 to handle much of the heavy lifting and platform abstractions, allowing you to have a simple, portable OpenAL on any platform that SDL supports, from desktops to phones to web browsers to the Nintendo Switch.

This project can be compiled directly into an app, or built as a shared library, making it a drop-in replacement for other OpenAL implementations.

All of core OpenAL 1.1 is supported, including audio capture (recording) and multiple device support. A handful of popular extensions are also included.

Owner
Ryan C. Gordon
I make things that help you make games.
Ryan C. Gordon
Comments
  • Buffers can be deleted while still attached to a source

    Buffers can be deleted while still attached to a source

    I noticed a behavioural difference between mojoal and macos's openal, and I think it suggests a bug.

    Basically you can delete buffers while they are still attached to a source. In mojoal, you don't get an error on delete and when you attach new buffers to the source to play a new sound, you get a brief blip of the previously buffered audio.

    In comparison to macos's openal: when you attempt to delete a buffer that is still attached, you will get an "Invalid Operation" error.

    Attached is source for testing this bug. Create two different raw audio files called tone_880.raw and tone_440.raw (different so you can hear the previous buffer play a bit), and comment/uncomment out #define AL_CLEAR_BUFFER_ON_STOP to trigger the bug.

    openal_test.cpp.tar.gz

    Tested using mojoal 8af8cd366257e3b9d734f635f7d17d67fc4d48f7

  • Made source_get_offset return float to allow precise AL_SEC_OFFSET

    Made source_get_offset return float to allow precise AL_SEC_OFFSET

    Hello. I'm not an expert in OpenAL, but using your library I found that calling alGetSourcef with AL_SEC_OFFSET returns only second-precise values, although according to specs it should be supporting fractional values too.

    It looks like this small change is enough to fix it.

    PS. _alGetSourceiv already converting the result value to int here, so that should stay correct: https://github.com/icculus/mojoAL/blob/44bb6799215238986d12ffa1d85ee49f24a2ccad/mojoal.c#L3742

  • implement ALC_FREQUENCY case in alcGetIntegerv

    implement ALC_FREQUENCY case in alcGetIntegerv

    Hello,

    This implements ALC_FREQUENCY in alcGetIntegerv so that user can do:

    ALCint sampleRate = -1;
    alcGetIntegerv(device, ALC_FREQUENCY, 1, &sampleRate);
    

    I would have done the same for ALC_REFRESH and ALC_SYNC but they are not actually implemented yet (L2119 "use these variables at some point")

    Please let me know if anything is incorrect or missing.

    Best

  • A way to manually set the audio driver

    A way to manually set the audio driver

    Hi,

    I am trying to figure out how to set to use a specific audio driver and how to force automatic audio driver selection.

    The problem is SDL_AudioInit is not ref counted, so I can't pre-open it and let MojoAL use the driver I set simply because this will cause a failure. See https://github.com/libsdl-org/SDL/issues/5841

  • Offset is incorrectly reset after each processed buffer?

    Offset is incorrectly reset after each processed buffer?

    Hello.

    According to the OpenAL specs found here, documentation for AL_SEC_OFFSET (page 39) sais:

    The position is relative to the beginning of all the queued buffers for the source, and any queued buffers traversed by a set call will be marked as processed.

    At the same time mojoAL resets the source offset after each processed buffer: https://github.com/icculus/mojoAL/blob/42035035b4e5debb6fe30e475683da2c30e51326/mojoal.c#L1455

    Is that a mistake?

  • Null pointer access when setting sample offset for `AL_UNDETERMINED` source

    Null pointer access when setting sample offset for `AL_UNDETERMINED` source

    This is similar to #9 - when calling alSourcei(source, AL_SAMPLE_OFFSET, value), the code tries to access a field of src->buffer when src->buffer is null: https://github.com/icculus/mojoAL/blob/main/mojoal.c#L4238

    There is a codepath which bails early if it knows the source is streaming, but in my case the source's type is AL_UNDETERMINED at that point.

    Side note: my source is in the AL_UNDETERMINED state because it unexpectedly hadn't queued any buffers, because of a weird chain of events leading back to alGetSourceiv(source, AL_BUFFERS_QUEUED, ...) returning the wrong value: https://github.com/icculus/mojoAL/blob/main/mojoal.c#L3976-L3977

  • Compatibility fixes

    Compatibility fixes

    Two small things: The first commit fixes building with VS2008, which needs mojoal.c to be compiled in C++ mode. So no implicit void* -> any* casts. For the include location change in the 2nd commit refer to https://github.com/AquariaOSE/Aquaria/pull/78#issuecomment-1067494664 Imho, it's also easier for users to just plop the two .h files into some include dir rather than require them to be available under some AL/-subdir...

  • Null-pointer exceptions when getting Source state with no buffers

    Null-pointer exceptions when getting Source state with no buffers

    It's possible to experience a null-pointer exception when trying to retrieve some of the Source properties, such as AL_SEC_OFFSET, and similar, from the Source that has no buffers attached.

    As seen here: https://github.com/icculus/mojoAL/blob/main/mojoal.c#L4211 in a non-streaming case mojoAl accesses a buffer in order to find out offset, but does not test if the buffer pointer is valid.

  • It would be nice to have some low pass extension

    It would be nice to have some low pass extension

    There is an EFX extension for lowpass

    https://github.com/kcat/openal-soft/blob/master/include/AL/efx.h

    There are extensions for reverb and other extensions that are quite complex, so not sure about following efx extensions, but at least having some way to do a lowpass filter would be nice.

  • Potentially incorrect source_get_offset() when sound buffers vary in length

    Potentially incorrect source_get_offset() when sound buffers vary in length

    In source_get_offset() , when the source's type is AL_STREAMING, the mojoAL is summing up all the queued and processed buffers lengths to the current buffer's offset (as per OpenAL's specs):

    https://github.com/icculus/mojoAL/blob/102126d3ed3a979728c4dde170bf242ad9d9daa6/mojoal.c#L4205-L4213

    As may be seen from the code, this is done simply by multiplying the current buffer's len by the number of processed buffers (buffer_queue_processed.num_items); this assumes that all the buffers have the same length.

    This however may not be the case. For instance, in the practical case I had, I've been looping a sound file, and the ending piece of much smaller size could be followed by a larger buffer with data from another beginning. In such case the reported offset was larger than expected, as the already processed smaller piece was assumed to be as large as the currently playing one.

    Overall I have not found any mention that the buffers must all be of same size when queued into the source, neither in documentation nor the code. Could be I'm missing a rule here? One comment in mojoAL even states: you can legally queue or set a NULL buffer. assuming it also allows for the 0 length buffer to be queued.

    I suppose, that if if having varied buffers is legal, then fixing this may be a matter of tracking a processed length, which is added to when another buffer is processed, and subtracted from when a processed buffer is unqueued.

  • Implement a playback speed extension?

    Implement a playback speed extension?

    Since recently there have been a discussion about possibly having a stereo panning extension, I thought to ask if it's theoretically acceptable to have a "playback speed" extension? I mean the effect which can be achieved by resampling with higher or lower rate (frequency).

    It is of course possible to do this before passing sound data into openal, but with data buffering this results in delayed effect whenever the speed changes (also requires to do extra calculations externally).

  • Add Panning Extension for Stereo formats

    Add Panning Extension for Stereo formats

    Attempt to fix #12

    This is probably wrong somewhere and incorrect. Probably the most useful thing is the example.

    I copied the testposition example to create a testpanning example with a red rectangle, moving the red rectangle to right or left modifies the panning to either right or left.

    Here's a cool song that is stereo: https://opengameart.org/content/love-song-instrumental

  • Panning Stereo sounds using MojoAL

    Panning Stereo sounds using MojoAL

    Hi,

    We have been looking into panning sounds. In OpenAL, it looks like it's only possible to do so using mono sounds.

    For stereo sounds, it seems there's an alternative way discussed here : https://github.com/kcat/openal-soft/issues/194

    But we had some trouble actually following the suggested workaround when using MojoAL. This is discussed a bit here: https://github.com/adventuregamestudio/ags/issues/1637

    Would an extension to provide a way to do so in MonoAL be acceptable?

  • Potential problem with calculating mojoAl's Buffer size in samples

    Potential problem with calculating mojoAl's Buffer size in samples

    In our program we calculate full playback offset by adding number of samples from every processed buffer. We calculate samples as buffer_samples = (buffer_size * 8) / (buffer_bits * buffer_channels); where buffer values are retrieved using alGetBufferi with AL_SIZE, AL_BITS and AL_CHANNELS respectively.

    Recently I've met an issue where this resulted in a wrong number of samples, and found out that this is because mojoAL internally stores samples as float32 in the generated buffer. If we pass a 16-bit sound data into alBufferData (AL_FORMAT_STEREO16 / AL_FORMAT_MONO16), Buffer still reports original input bitness as 16, but at the same time it has samples stores as 32-bit, therefore less samples fit into the same buffer size. This makes it impossible to calculate number samples correctly without "secret knowledge" about mojoAL's implementation, where we have to always use 32 as "buffer bits".

    I must admit that I'm not very experienced with OpenAL yet, so still unsure whether this is a valid bug, or we are using a method we are not supposed to.

Scalable, Portable and Distributed Gradient Boosting (GBDT, GBRT or GBM) Library, for Python, R, Java, Scala, C++ and more. Runs on single machine, Hadoop, Spark, Dask, Flink and DataFlow
Scalable, Portable and Distributed Gradient Boosting (GBDT, GBRT or GBM) Library,  for Python, R, Java, Scala, C++ and more. Runs on single machine, Hadoop, Spark, Dask, Flink and DataFlow

eXtreme Gradient Boosting Community | Documentation | Resources | Contributors | Release Notes XGBoost is an optimized distributed gradient boosting l

Dec 30, 2022
K_means clustering implementation in C++20
K_means clustering implementation in C++20

Infographic made by spiyer99 Requirements -std=c++20 > gcc 10.2 (gcc trunk) msvc hasn't implemented std::ranges yet and clang's std::ranges/concepts s

May 9, 2022
TNLMeans is an implementation of the NL-means denoising algorithm in an Avisynth filter

TNLMeans TNLMeans is an implementation of the NL-means denoising algorithm in an Avisynth filter (by tritical) Requirements This filter requires AviSy

Feb 4, 2022
Support Vector Machines Implementation from scratch in C++

SVM C++ Samples These are sample programs of Support Vector Machines from scratch in C++. 1. Implementation Model Class Problem Decision Boundary Code

Nov 7, 2022
C-based/Cached/Core Computer Vision Library, A Modern Computer Vision Library

Build Status Travis CI VM: Linux x64: Raspberry Pi 3: Jetson TX2: Backstory I set to build ccv with a minimalism inspiration. That was back in 2010, o

Jan 6, 2023
RP-VIO: Robust Plane-based Visual-Inertial Odometry for Dynamic Environments (Code & Dataset)
RP-VIO: Robust Plane-based Visual-Inertial Odometry for Dynamic Environments (Code & Dataset)

RP-VIO: Robust Plane-based Visual-Inertial Odometry for Dynamic Environments RP-VIO is a monocular visual-inertial odometry (VIO) system that uses onl

Jan 6, 2023
This robot lcoalisation package for lidar-map based localisation using multi-sensor state estimation.
This robot lcoalisation package for lidar-map based localisation using multi-sensor state estimation.

A ROS-based NDT localizer with multi-sensor state estimation This repo is a ROS based multi-sensor robot localisation. An NDT localizer is loosely-cou

Dec 15, 2022
A Modular Framework for LiDAR-based Lifelong Mapping
A Modular Framework for LiDAR-based Lifelong Mapping

LT-mapper News July 2021 A preprint manuscript is available (download the preprint). LT-SLAM module is released.

Dec 30, 2022
Ingescape - Model-based framework for broker-free distributed software environments
 Ingescape - Model-based framework for broker-free distributed software environments

Ingescape - Model-based framework for broker-free distributed software environments Overview Scope and Goals Ownership and License Dependencies with o

Jan 5, 2023
An SDL2-based implementation of OpenAL in a single C file.

MojoAL MojoAL is a full OpenAL 1.1 implementation, written in C, in a single source file. It uses Simple Directmedia Layer (SDL) 2.0 to handle much of

Dec 28, 2022
A single file, single function, header to make notifications on the PS4 easier

Notifi Synopsis Adds a single function notifi(). It functions like printf however the first arg is the image to use (NULL and any invalid input should

Oct 4, 2022
Implementation of Conway's Game of Life in C++ with SDL2
Implementation of Conway's Game of Life in C++ with SDL2

Conway's Game of Life Implementation of Conway's Game of Life in C++ with SDL2. Usage make sure SDL2 is well configured. make run click on screen to m

Feb 12, 2022
convert elf file to single c/c++ header file

elf-to-c-header Split ELF to single C/C++ header file

Nov 4, 2021
A blank for a SDL2-based platformer game
 A blank for a SDL2-based platformer game

A blank for a SDL2-based platformer game Attention, this repository does not contain (and never will) a playable game. The goal is to show basic princ

Dec 30, 2022
work in progress 3d renderer based on sdl2
work in progress 3d renderer based on sdl2

work in progress 3d software renderer based on SDL. (Only supports wireframe view for now) Building On Linux, install libsdl2 and then run the folowin

Sep 12, 2021
work in progress 3d renderer based on sdl2
work in progress 3d renderer based on sdl2

work in progress 3d software renderer based on SDL. (Only supports wireframe view for now) Building On Linux, install libsdl2 and then run the folowin

Sep 12, 2021
Single C file TLS 1.2/1.3 implementation, using tomcrypt as crypto library

TLSe Single C file TLS 1.3, 1.2, 1.1 and 1.0(without the weak ciphers) implementation, using libtomcrypt as crypto library. It also supports DTLS 1.2

Dec 31, 2022
A single file, public domain C implementation of aSchroeder reverb.

Introduction This is a reverb implementation based on Freeverb, a public domain reverb written by Jezar at Dreampoint in 2000. The library is written

Nov 27, 2022
A simple Z-Machine implementation in a single C file. Now with online multiplayer! :)

This is an implementation of Infocom's Z-Machine. The Z-Machine is a virtual machine that's something like a high-level CPU. To keep their games portable and easier to write, Infocom's games all use this fake processor and ship with a platform-specific Z-Machine "emulator" ... so a game could run wherever someone had implemented the Z-Machine.

Dec 28, 2022
Project 1945 is a top down scroller game made with SDL2, CMake and programmed in C as a project of study for the Italian Videogames Academy for the 3rd year course of Videogames programming.
Project 1945 is a top down scroller game made with SDL2, CMake and programmed in C as a project of study for the Italian Videogames Academy for the 3rd year course of Videogames programming.

Project 1945 is a top down scroller game made with SDL2, CMake and programmed in C as a project of study for the Italian Videogames Academy for the 3rd year course of Videogames programming. The game is based on the old videogame 1945: The Final Front of the 2002.

Dec 30, 2022