audio - iOS. OpenGL. Several views simultaneously -
a couple of days before asked filling space between 2 curve lines gradient. since i've changed lots of in code - i'm using shaders. result need. but! again have problem using several opengl views simultaneously in 1 controller must absolutely independent between each other. so, unbelievable tutorial raywenderlich.com , code example bradley have next situation:
- two custom objects of class soundwaveview.swift (improved openglview.swift bradley);
- vertex/fragment shaders openglview object;
- controller create , add 2 soundwaveview objects (with same context!!!!!):
c
override func viewdidload() { super.viewdidload() let context = eaglcontext(api: eaglrenderingapi.opengles2) let viewpos1: cgrect = cgrectmake(0, 150, uiscreen.mainscreen().bounds.size.width, 150); let view1 = soundwaveview(frame: viewpos1, filename: "personal jesus", fileextention: "mp3", c: context) view1.backgroundcolor = uicolor.graycolor() self.view.addsubview(view1) let viewpos2: cgrect = cgrectmake(0, 350, uiscreen.mainscreen().bounds.size.width, 150); let view2 = soundwaveview(frame: viewpos2, filename: "imagine", fileextention: "mp3", c: context) view2.backgroundcolor = uicolor.blackcolor() self.view.addsubview(view2) }
every soundwaveview-object compiles shaders in tutorials above:
func compileshaders() { let vertexshader = compileshader("simplevertex", shadertype: glenum(gl_vertex_shader)) let fragmentshader = compileshader("simplefragment", shadertype: glenum(gl_fragment_shader)) let programhandle: gluint = glcreateprogram() glattachshader(programhandle, vertexshader) glattachshader(programhandle, fragmentshader) gllinkprogram(programhandle) var linksuccess: glint = glint() glgetprogramiv(programhandle, glenum(gl_link_status), &linksuccess) if (linksuccess == gl_false) { var message = [cchar](count: 256, repeatedvalue: cchar(0)) var length = glsizei(0) glgetprograminfolog(programhandle, 256, &length, &message) print("failed create shader program! : \( string(utf8string: message) ) ") exit(1); } gluseprogram(programhandle) . . . . . shaderpeakid = glgetuniformlocation(programhandle, "peakid") shaderwaveamp = glgetuniformlocation(programhandle, "waveamp"); glenablevertexattribarray(positionslot) glenablevertexattribarray(colorslot) gluniform1f(shaderscenewidth!, float(self.frame.size.width)); gluniform1f(shadersceneheight!, float(self.frame.size.height)); gluniform1i(shaderpeakstotal!, glint(total)); gluniform1i(shaderpeakid!, glint(position)); }
for rendering audio waves need pass shader values a) amplitude (i them avaudioplayer - work perfect , 2 objects create in controller have different amplitudes 2 different tracks) , b) wave number (aka peakid/position).
so first created object(grey) there position equal 1 , wave must red , placed in left part of screen. second object (black) position 3, wave blue , placed in right part. /position 2 center @ screen, not use now/
every audio update causes update opengl:
var waveamp :float = 0 . . . . . func updatemeters(){ player!.updatemeters() var normalizedvalue = normalizedpowerlevelfromdecibels(player!.averagepowerforchannel(0)) waveamp = normalizedvalue! } func render(displaylink: cadisplaylink?) { glblendfunc(glenum(gl_one), glenum(gl_one_minus_src_alpha)) glenable(glenum(gl_blend)) // glclearcolor(0, 104.0/255.0, 55.0/255.0, 1.0) glclearcolor(0, 0, 0, 0) glclear(glenum(gl_color_buffer_bit) | glenum(gl_depth_buffer_bit)) glenable(glenum(gl_depth_test)) glviewport(0, 0, glsizei(self.frame.size.width), glsizei(self.frame.size.height)) glbindbuffer(glenum(gl_array_buffer), vertexbuffer) glbindbuffer(glenum(gl_element_array_buffer), indexbuffer) glvertexattribpointer(positionslot, 3, glenum(gl_float), glboolean(uint8(gl_false)), glsizei(sizeof(vertex)), nil) glvertexattribpointer(colorslot, 4, glenum(gl_float), glboolean(uint8(gl_false)), glsizei(sizeof(vertex)), unsafepointer<void>(bitpattern: (sizeof(float) * 3))) gldrawelements(glenum(gl_triangle_fan), glsizei(indices.size()), glenum(gl_unsigned_byte), nil) glvertexattribpointer(positionslot, 3, glenum(gl_float), glboolean(uint8(gl_false)), glsizei(sizeof(vertex)), nil); glvertexattribpointer(colorslot, 4, glenum(gl_float), glboolean(uint8(gl_false)), glsizei(sizeof(vertex)), unsafepointer<void>(bitpattern: (sizeof(float) * 3))); context.presentrenderbuffer(int(gl_renderbuffer)) print("position=\(position) waveamp=\(waveamp)") gluniform1i(shaderpeakid!, glint(position)); gluniform1f(shaderwaveamp!, waveamp); }
log print()-function:
position=1 waveamp=0.209313 position=3 waveamp=0.47332 position=1 waveamp=0.207556 position=3 waveamp=0.446235 position=1 waveamp=0.20769 position=3 waveamp=0.446235 position=1 waveamp=0.246206 position=3 waveamp=0.430118
i expect have 2 rectangles - 1 grey red wave on left , 1 black blue line on right. have next trouble! rendering take place in 1 (last) view , changes sequentially:
please anyone! how use 2 glviews simultaneously? or maybe need use 2 shaders in 1 view?
i want finish audio wave task , share them everyone. still don't understand problem
looking in code soundwaveview class posted, looks view handles initializing context, framebuffer context, , more you. since send same eaglcontext both views, means same context being initialized, re-initialized second view. doesn't seem right me. might work fine if make separate context other view, , gpu context-switch when rendering between these 2 views, , treat them if separate apps.
but that's not how application simple should designed. if want 2 objects drawn on screen @ same time, doesn't mean need 2 separate views. have build system handles taking information each waveform , converting appropriate draw calls automatically. act mini draw engine application. approach, write further support cooler techniques , drawings... maybe more waveforms, different textures/colors each of them, cool effects, etc.
Comments
Post a Comment