Comments (7)
The ring buffer stuff is new and I've just not had the time to document it. I also never looked at any references or anything so I may have used a few unorthodox ideas in the API design. But the idea is that you acquire a portion of the buffer which returns a pointer for you to read/write, and then release it which moves the cursor forward. Also keep in mind that it's single producer, single consumer.
What specifically were you having trouble with?
from miniaudio.
ma_result ma_rb_acquire_read(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut);
ma_result ma_rb_commit_read(ma_rb* pRB, size_t sizeInBytes, void* pBufferOut);
ma_result ma_rb_acquire_write(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut);
ma_result ma_rb_commit_write(ma_rb* pRB, size_t sizeInBytes, void* pBufferOut);
Not exactly sure what to pass in to these functions. Not sure what the third argument actually is. Is it where the read/write cursor is going to be stored when the function returns (and size is stored in the second param)? Seems so when I look at the code, but after segfaulting when trying to operate on it I ended up using my own ring buffer implementation with a mutex (I'd rather use yours if it's lock-free).
If you want to see my quick and dirty solution using a mutex: https://github.com/0ldsk00l/smsplus/blob/master/shell/smsplus.c
edit: Yeah, I am only concerned with single producer/consumer for my projects which are mostly emulation-based.
from miniaudio.
You use it like this:
size_t sizeInBytes = 1024; // Initialize this to the number of bytes you want.
void* pBuffer;
result = ma_rb_acquire_read(pRB, &sizeInBytes, &pBuffer);
if (result != MA_SUCCESS) {
// Error
}
// At this point, sizeInBytes is set to the number of bytes _actually_ acquired. pBuffer is
// a pointer to the buffer you would read from. Note that sizeInBytes may be less than
// what you originally requested.
memcpy(pSomeBuffer, pBuffer, sizeInBytes); // <-- Do something with the data.
result = ma_rb_commit_read(pRB, sizeInBytes, pBuffer);
if (result != MA_SUCCESS) {
// Error
}
The general flow is acquire/map a portion of the ring buffer, do something with the returned data, then commit/unmap.
If it looks like you're doing everything correct, I'd be interested to see a portion of your code if at all possible just to check if there's an underlying bug with miniaudio's ring buffer implementation since it is fairly new code.
from miniaudio.
Thanks for posting that example, it helped me make sense of everything and I've managed to get something up and running using the built-in ring buffer. Works great! I may create a sine wave example of my own that uses it and post it later in case it's useful to other people.
from miniaudio.
I too am a bit curious how this is used. In my case I am trying to keep a small buffer of past PCM frames such that if some later processing (within the next 5 seconds) decides it wants a snippet of that audio as a wav, I can seek backwards in the PCM buffer, start up a WAV encoder and pass those frames to the encoder to get a WAV from that snippet in time.
Is the ring buffer the best way to achieve this? I am still passing frames in the callback to do some FFT work and won't know if I need to go back in time to save the stream until a few seconds later. Are there any existing examples of doing something like this or storing PCM frames into a ring buffer?
from miniaudio.
To have a look-behind of some fixed number of frames, using a ring buffer, you need to have a way to prevent the writer from over-taking the reader and instead be blocked at some number of frames behind the reader.
It might be better to store the read frames into a separate ring cache where new reads overlay old ones based on the size of the cache ring and how fast things are going. The size of the cache ring determines what is keeps to that predetermined depth.
That's technically not a ring buffer, because you are chasing your own tail and allowed to catch and over-run it. In this game, the oldest cache item is just in front of the moving cache filler. (This should all be on the reader's thread of course.)
The reader being cached in a ring might be obtaining its data from a ring buffer though.
MORE ON RING BUFFERS
The use of a ring buffer is usually to coordinate a reader and a writer, where the reader chases (but does not pass) the writer, and the writer chases (but does not pass) the reader.
The buffer should be large enough that the reader rarely catches the writer (and then has to wait, drop its own outputs, stall other things, etc). Similarly, if the writer catches the reader, it may end up having to drop data until the reader makes more room in the buffer.
This sort of thing can happen with any kind of buffering, of course. The ring buffer just happens to be a cool structure that works like a speedway and doesn't have to be choppy such as buffers that have to be emptied quickly and that writers can fill, with readers needing to gobble a ready buffer quickly so the writer is not blocked either.
Ring buffers can be made expandable using list structures although reducing them later can be tricky.
With regard to audio, the ring buffer provides a form of caching for smoothing operation between producer and consumer. However, there can be latency issues as a consequence. Any latency should not be so bad as having a buffer that must be filled and then must be drained, wholesale.
from miniaudio.
@acidtonic No, I don't think a ring buffer would be appropriate for your case. The ring buffer is a very specific data structure. It's good when you have one thread writing some data (the producer) and another thread reading the data (the consumer) and you want that access to be lock-free. It's useful in audio because you'll sometimes end up in a situation where you have some capturing thread writing to the ring buffer, while at the same time on a different thread you have something that is consuming that data. It allows those two threads to be completely decoupled.
In your case I would consider just using a standard old buffer.
from miniaudio.
Related Issues (20)
- Question about spatialization HOT 1
- CoreAudio failed to initialize on Apple TV HOT 2
- Add dedicated spatialization example?
- ma_engine_uninit on windows causes Application Verifier breakpoint HOT 1
- [OSX/MacOS] Capture volume out of range ? HOT 10
- iOS: Some phones fail to init AudioUnit when using shared context HOT 3
- Android: Build failure of dev branch due to pthread_attr_setinheritsched HOT 2
- WASM duplicate symbol HOT 3
- Emscripten WASM Thread Problem HOT 2
- Question about Attenuation in Miniaudio. HOT 1
- Javascript error after uninitializing miniaudio HOT 4
- "Error: Invalid argument" due to ma_channel_map_is_valid HOT 6
- Does miniaudio support encoding PCM sample data into ADPCM sample data? HOT 1
- Uncaught RuntimeError: memory access out of bounds after starting playing the sound. HOT 8
- DELETED HOT 1
- Miniaudio waiting infinitely when calling ma_engine_uninit HOT 1
- Is there a way to gracefully shut down all threads created by miniaudio when the application exits? HOT 1
- Channel Convert Init Access Violation going from 2 channels to >2 channels HOT 2
- Sound system lags when playing sounds quickly and using delay or reverb HOT 1
- ma_device_uninit crash on Android <= 10 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from miniaudio.