objective c - iOS: Threading issue when calling setNeedDisplay inside callback function -
here context: i've been developing audio-related app while , sort of hit wall , not sure next.
i've implemented in app custom class plots fft display of audio output. class subclass of uiview meaning every time need plot new fft update need call setneeddisplay on instance of class new sample values.
as need plot new fft every frame (frame ~= 1024 samples), means display function of fft gets called lot (1024 / samplerate ~= 0.02321 second). sample calculation, done 44'100 / sec. not experienced managing threading in ios read little bit , here how have done it.
how has been done: have subclass of nsobject "audioengine.h" taking care of dsp processing in app , setting fft display. sample values calculated , assigned fft subclass inside dispatch_get_global_queue block values need updated in background. setneeddisplay method called once samples index has reached maximum frame number, , done inside dispatch_async(dispatch_get_main_queue) block
in "audioengine.m"
for (k = 0; k < nchnls; k++) { buffer = (sint32 *) iodata->mbuffers[k].mdata; if (cdata->shouldmute == false) { buffer[frame] = (sint32) lrintf(spout[nsmps++]*coef) ; dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_high, 0), ^{ @autoreleasepool { // fft display init here singleton spectralview *specview = [spectralview sharedinstance]; //here created pointer "samples" property of subclass float32 *specsamps = [specview samples]; //set number of frames fft should take [specview setinnumberframes:innumberframes]; //scaling sample values specsamps[frame] = (buffer[frame] * (1./coef) * 0.5); } }); } else { // if output muted buffer[frame] = 0; } } //once number of samples has reached ksmps (vector size) update fft if (nsmps == ksmps*nchnls){ dispatch_async(dispatch_get_main_queue(), ^{ spectralview *specview = [spectralview sharedinstance]; [specview preparetodraw]; [specview setneedsdisplay]; }); what issue is:
- i various threading issues, on main thread such
thread 1: exc_bad_access (code=1, address=0xf00000c), on app launch viewdidload being called, whenever try interact ui object. - the ui responsiveness becomes insanely slow, on fft display.
what think problem is: related threading issue may know unexperienced topic. thought maybe force ui display update on main thread in order solve issues have again; not sure how properly.
any input/insight huge help. in advance!
as written, spectralview* needs thread safe.
your for() loop first shoving frame/sample processing off high priority concurrent queue. since asynchronous, going return immediately, @ point code going enqueue request on main threat update spectral view's display.
this pretty guarantees spectral view going have updating display simultaneously background processing code updating spectral view's state.
there second issue; code going end parallelizing processing of channels. in general, unmitigated concurrency recipe slow performance. also, you're going cause update on main thread each channel, regardless of whether or not processing of channel completed.
the code needs restructured. should split model layer view layer. model layer either written thread safe or, during processing, can grab snapshot of data displayed , toss @ spectralview. alternatively, model layer have isprocessing flag spectralview key off of know shouldn't reading data.
this relevant:
Comments
Post a Comment