osx - alBufferData() sets AL_INVALID_OPERATION when using buffer ID obtained from alSourceUnqueueBuffers() -
i trying stream audio data disk using openal's buffer queueing mechanism. load , enqueue 4 buffers, start source playing, , check in regular intervals refresh queue. looks it's going splendidly, until first time try load data recycled buffer got alsourceunqueuebuffers(). in situation, albufferdata() sets al_invalid_operation, according the official v1.1 spec, doesn't seem should able do.
i have searched extensively on google , stackoverflow, , can't seem find reason why happen. closest thing found a possibly-related issue in archived forum post, details few , responses null. there this question different circumstances, answer's suggestion not help.
possibly helpful: know context , device configured correctly, because loading small wav files single buffer , playing them works fine. through experimentation, i've found queueing 2 buffers, starting source playing, , loading , enqueueing other 2 buffers throws no errors; it's when i've unqueued processed buffer run trouble.
the relevant code:
static constexpr int max_buffer_count = 4; #define alcall(funccall) {funccall; soundyoutport::checkerror(__file__, __line__, #funccall) ? abort() : ((void)0); } bool soundyoutport::checkerror(const string &pfile, int pline, const string &pfunc) { alenum terrcode = algeterror(); if(terrcode != 0) { auto tmsg = algetstring(terrcode); log::e(ro::tag) << tmsg << " @ " << pfile << "(" << pline << "):\n" << "\tal call " << pfunc << " failed." << end; return true; } return false; } void soundyoutport::enqueuebuffer(const float* pdata, int pframes) { static int called = 0; ++called; alint tstate; alcall(algetsourcei(msourceid, al_source_type, &tstate)); if(tstate == al_static) { stop(); // alcall(alsourcei(msourceid, al_buffer, null)); } aluint tbufid = al_none; int tqueuedbuffers = queuedupbuffers(); int tready = processedbuffers(); if(tqueuedbuffers < max_buffer_count) { tbufid = mbufferids[tqueuedbuffers]; } else if(tready > 0) { // fifth time through, code gets hit alcall(alsourceunqueuebuffers(msourceid, 1, &tbufid)); // debug code: make sure these values go down 1 tqueuedbuffers = queuedupbuffers(); tready = processedbuffers(); } else { return; // no update needed yet. } void* tconverted = convert(pdata, pframes); // fifth time through, al_invalid_operation, , call abort() alcall(albufferdata(tbufid, mformat, tconverted, pframes * mbitdepth/8, msamplerate)); alcall(alsourcequeuebuffers(msourceid, 1, &mbufferid)); if(mbitdepth == bitdepth_8) { delete (uint8_t*)tconverted; } else // if(mbitdepth == bitdepth_16) { delete (uint16_t*)tconverted; } } void soundyoutport::playbufferedstream() { if(!streamingmode() || !queuedupbuffers()) { log::w(ro::tag) << "attempted play unbuffered stream" << end; return; } alcall(alsourcei(msourceid, al_looping, al_false)); // never loop streams alcall(alsourceplay(msourceid)); } int soundyoutport::queuedupbuffers() { int tcount = 0; alcall(algetsourcei(msourceid, al_buffers_queued, &tcount)); return tcount; } int soundyoutport::processedbuffers() { int tcount = 0; alcall(algetsourcei(msourceid, al_buffers_processed, &tcount)); return tcount; } void soundyoutport::stop() { if(playing()) { alcall(alsourcestop(msourceid)); } int tbuffers; alcall(algetsourcei(msourceid, al_buffers_queued, &tbuffers)); if(tbuffers) { aluint tdummy[tbuffers]; alcall(alsourceunqueuebuffers(msourceid, tbuffers, tdummy)); } alcall(alsourcei(msourceid, al_buffer, al_none)); } bool soundyoutport::playing() { alint tplaying; alcall(algetsourcei(msourceid, al_source_state, &tplaying)); return tplaying == al_playing; } bool soundyoutport::streamingmode() { alint tstate; alcall(algetsourcei(msourceid, al_source_type, &tstate)); return tstate == al_streaming; } bool soundyoutport::staticmode() { alint tstate; alcall(algetsourcei(msourceid, al_source_type, &tstate)); return tstate == al_static; } and here's annotated screen cap of see in debugger when hit error:

i've tried bunch of little tweaks , variations, , result same. i've wasted many days trying fix this. please :)
this error occurs when trying fill buffer data, when buffer still queued source.
also code wrong.
if(tqueuedbuffers < max_buffer_count) { tbufid = mbufferids[tqueuedbuffers]; } else if(tready > 0) { // fifth time through, code gets hit alcall(alsourceunqueuebuffers(msourceid, 1, &tbufid)); // debug code: make sure these values go down 1 tqueuedbuffers = queuedupbuffers(); tready = processedbuffers(); } else { return; // no update needed yet. } you can fill buffer data if unqueued source. first if block gets tbufid queued source. rewrite code
if(tready > 0) { // fifth time through, code gets hit alcall(alsourceunqueuebuffers(msourceid, 1, &tbufid)); // debug code: make sure these values go down 1 tqueuedbuffers = queuedupbuffers(); tready = processedbuffers(); } else { return; // no update needed yet. }
Comments
Post a Comment