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:

annotated view of debugger contents

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

Popular posts from this blog

javascript - jquery or ashx not working -

opencv - DataType<cv::detail::deriv_type>::depth what is it used for -

python 3.x - Mapping specific letters onto a list of words -