diff --git a/EZAudio/EZAudio.h b/EZAudio/EZAudio.h index 1704d395..7453a7b4 100644 --- a/EZAudio/EZAudio.h +++ b/EZAudio/EZAudio.h @@ -43,7 +43,6 @@ #import "EZPlot.h" #import "EZAudioPlot.h" #import "EZAudioPlotGL.h" -#import "EZAudioPlotGLKViewController.h" //------------------------------------------------------------------------------ diff --git a/EZAudio/EZAudioPlot.h b/EZAudio/EZAudioPlot.h index 7f4516b7..333a9945 100644 --- a/EZAudio/EZAudioPlot.h +++ b/EZAudio/EZAudioPlot.h @@ -24,8 +24,6 @@ // THE SOFTWARE. #import -#import "TargetConditionals.h" -#import "EZAudioUtilities.h" #import "EZPlot.h" @class EZAudio; @@ -115,16 +113,16 @@ FOUNDATION_EXPORT UInt32 const EZAudioPlotDefaultMaxHistoryBufferLength; ///----------------------------------------------------------- /** - The length of the rolling history display. Can grow or shrink the display up to the maximum size specified by the kEZAudioPlotMaxHistoryBufferLength macro. Will return the actual set value, which will be either the given value if smaller than the kEZAudioPlotMaxHistoryBufferLength or kEZAudioPlotMaxHistoryBufferLength if a larger value is attempted to be set. + Sets the length of the rolling history buffer (i.e. the number of points in the rolling plot's buffer). Can grow or shrink the display up to the maximum size specified by the `maximumRollingHistoryLength` method. Will return the actual set value, which will be either the given value if smaller than the `maximumRollingHistoryLength` or `maximumRollingHistoryLength` if a larger value is attempted to be set. @param historyLength The new length of the rolling history buffer. - @return The new value equal to the historyLength or the kEZAudioPlotMaxHistoryBufferLength. + @return The new value equal to the historyLength or the `maximumRollingHistoryLength`. */ -(int)setRollingHistoryLength:(int)historyLength; //------------------------------------------------------------------------------ /** - Provides the length of the rolling history buffer + Provides the length of the rolling history buffer (i.e. the number of points in the rolling plot's buffer). * @return An int representing the length of the rolling history buffer */ -(int)rollingHistoryLength; @@ -187,8 +185,7 @@ FOUNDATION_EXPORT UInt32 const EZAudioPlotDefaultMaxHistoryBufferLength; @param data A float array of the sample data. Subclasses should copy this data to a separate array to avoid threading issues. @param length The length of the float array as an int. */ --(void)setSampleData:(float *)data - length:(int)length; +-(void)setSampleData:(float *)data length:(int)length; //------------------------------------------------------------------------------ diff --git a/EZAudio/EZAudioPlot.m b/EZAudio/EZAudioPlot.m index 8f66d090..d156b580 100644 --- a/EZAudio/EZAudioPlot.m +++ b/EZAudio/EZAudioPlot.m @@ -41,9 +41,9 @@ @interface EZAudioPlot () @property (nonatomic, strong) EZAudioDisplayLink *displayLink; -@property (nonatomic, assign) EZPlotHistoryInfo *historyInfo; -@property (nonatomic, assign) CGPoint *points; -@property (nonatomic, assign) UInt32 pointCount; +@property (nonatomic, assign) EZPlotHistoryInfo *historyInfo; +@property (nonatomic, assign) CGPoint *points; +@property (nonatomic, assign) UInt32 pointCount; @end //------------------------------------------------------------------------------ diff --git a/EZAudio/EZAudioPlotGL.h b/EZAudio/EZAudioPlotGL.h index 5530c420..d029a5a7 100644 --- a/EZAudio/EZAudioPlotGL.h +++ b/EZAudio/EZAudioPlotGL.h @@ -23,126 +23,126 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#import "TargetConditionals.h" -#import "EZPlot.h" - -#if TARGET_OS_IPHONE #import -@class EZAudioPlotGLKViewController; -#elif TARGET_OS_MAC -#import -#import -#import -#import +#import "EZPlot.h" +#if !TARGET_OS_IPHONE +#import #endif -#pragma mark - Enumerations -/** - Constant drawing types wrapping around the OpenGL equivalents. In the audio drawings the line strip will be the stroked graph while the triangle will provide the filled equivalent. - */ -typedef NS_ENUM(NSUInteger,EZAudioPlotGLDrawType){ - /** - * Maps to the OpenGL constant for a line strip, which for the audio graph will correspond to a stroked drawing (no fill). - */ - EZAudioPlotGLDrawTypeLineStrip = GL_LINE_STRIP, - /** - * Maps to the OpenGL constant for a triangle strip, which for the audio graph will correspond to a filled drawing. - */ - EZAudioPlotGLDrawTypeTriangleStrip = GL_TRIANGLE_STRIP -}; +//------------------------------------------------------------------------------ +#pragma mark - Data Structures +//------------------------------------------------------------------------------ -#pragma mark - Structures -/** - A structure describing a 2D point (x,y) in space for an audio plot. - */ -typedef struct { - GLfloat x; - GLfloat y; +typedef struct +{ + GLfloat x; + GLfloat y; } EZAudioPlotGLPoint; +//------------------------------------------------------------------------------ +#pragma mark - EZAudioPlotGL +//------------------------------------------------------------------------------ + /** - EZAudioPlotGL is a subclass of either the EZPlot on iOS or an NSOpenGLView on OSX. I apologize ahead of time for the weirdness in the docs for this class, but I had to do a bit of hackery to get a universal namespace for something works on both iOS and OSX without any additional components. The EZAudioPlotGL provides an the same utilities and interface as the EZAudioPlot with the added benefit of being GPU-accelerated. This is the recommended plot to use on iOS devices to get super fast real-time drawings of audio streams. For the methods and properties below I've included notes on the bottom just indicating which OS they correspond to. In most (if not all) use cases you can just refer to the EZPlot documentation to see which custom properties can be setup. There update function is the same as the EZPlot as well: `updateBuffer:withBufferSize:` + EZAudioPlotGL is a subclass of either a GLKView on iOS or an NSOpenGLView on OSX. As of 0.6.0 this class no longer depends on an embedded GLKViewController for iOS as the display link is just manually managed within this single view instead. The EZAudioPlotGL provides the same kind of audio plot as the EZAudioPlot, but uses OpenGL to GPU-accelerate the drawing of the points, which means you can fit a lot more points and complex geometries. */ #if TARGET_OS_IPHONE -@interface EZAudioPlotGL : EZPlot +@interface EZAudioPlotGL : GLKView #elif TARGET_OS_MAC @interface EZAudioPlotGL : NSOpenGLView #endif -#if TARGET_OS_IPHONE - -// Inherited from EZPlot - -#elif TARGET_OS_MAC - +//------------------------------------------------------------------------------ #pragma mark - Properties +//------------------------------------------------------------------------------ + ///----------------------------------------------------------- /// @name Customizing The Plot's Appearance ///----------------------------------------------------------- + /** - The default background color of the plot. For iOS the color is specified as a UIColor while for OSX the color is an NSColor. The default value on both platforms is black. + The default background color of the plot. For iOS the color is specified as a UIColor while for OSX the color is an NSColor. The default value on both platforms is a sweet looking green. + @warning On OSX, if you set the background to a value where the alpha component is 0 then the EZAudioPlotGL will automatically set its superview to be layer-backed. */ -@property (nonatomic,strong) id backgroundColor; +@property (nonatomic, strong) id backgroundColor; + +//------------------------------------------------------------------------------ /** - The default color of the plot's data (i.e. waveform, y-axis values). For iOS the color is specified as a UIColor while for OSX the color is an NSColor. The default value on both platforms is red. + The default color of the plot's data (i.e. waveform, y-axis values). For iOS the color is specified as a UIColor while for OSX the color is an NSColor. The default value on both platforms is white. */ -@property (nonatomic,strong) id color; +@property (nonatomic, strong) id color; + +//------------------------------------------------------------------------------ /** The plot's gain value, which controls the scale of the y-axis values. The default value of the gain is 1.0f and should always be greater than 0.0f. */ -@property (nonatomic,assign,setter=setGain:) float gain; +@property (nonatomic, assign) float gain; + +//------------------------------------------------------------------------------ /** - The type of plot as specified by the `EZPlotType` enumeration (i.e. a buffer or rolling plot type). + The type of plot as specified by the `EZPlotType` enumeration (i.e. a buffer or rolling plot type). Default is EZPlotTypeBuffer. */ -@property (nonatomic,assign,setter=setPlotType:) EZPlotType plotType; +@property (nonatomic, assign) EZPlotType plotType; + +//------------------------------------------------------------------------------ /** - A BOOL indicating whether or not to fill in the graph. A value of YES will make a filled graph (filling in the space between the x-axis and the y-value), while a value of NO will create a stroked graph (connecting the points along the y-axis). + A BOOL indicating whether or not to fill in the graph. A value of YES will make a filled graph (filling in the space between the x-axis and the y-value), while a value of NO will create a stroked graph (connecting the points along the y-axis). Default is NO. */ -@property (nonatomic,assign,setter=setShouldFill:) BOOL shouldFill; +@property (nonatomic, assign) BOOL shouldFill; + +//------------------------------------------------------------------------------ /** - A boolean indicating whether the graph should be rotated along the x-axis to give a mirrored reflection. This is typical for audio plots to produce the classic waveform look. A value of YES will produce a mirrored reflection of the y-values about the x-axis, while a value of NO will only plot the y-values. + A boolean indicating whether the graph should be rotated along the x-axis to give a mirrored reflection. This is typical for audio plots to produce the classic waveform look. A value of YES will produce a mirrored reflection of the y-values about the x-axis, while a value of NO will only plot the y-values. Default is NO. */ -@property (nonatomic,assign,setter=setShouldMirror:) BOOL shouldMirror; +@property (nonatomic, assign) BOOL shouldMirror; + +//------------------------------------------------------------------------------ +#pragma mark - Updating The Plot +//------------------------------------------------------------------------------ -#pragma mark - Get Samples ///----------------------------------------------------------- /// @name Updating The Plot ///----------------------------------------------------------- + /** Updates the plot with the new buffer data and tells the view to redraw itself. Caller will provide a float array with the values they expect to see on the y-axis. The plot will internally handle mapping the x-axis and y-axis to the current view port, any interpolation for fills effects, and mirroring. @param buffer A float array of values to map to the y-axis. @param bufferSize The size of the float array that will be mapped to the y-axis. - @warning The bufferSize is expected to be the same, constant value once initial triggered. For plots using OpenGL a vertex buffer object will be allocated with a maximum buffersize of (2 * the initial given buffer size) to account for any interpolation necessary for filling in the graph. Updates use the glBufferSubData(...) function, which will crash if the buffersize exceeds the initial maximum allocated size. */ --(void)updateBuffer:(float *)buffer - withBufferSize:(UInt32)bufferSize; - -#endif +-(void)updateBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize; +//------------------------------------------------------------------------------ #pragma mark - Adjust Resolution +//------------------------------------------------------------------------------ + ///----------------------------------------------------------- /// @name Adjusting The Resolution ///----------------------------------------------------------- /** - Sets the length of the rolling history display. Can grow or shrink the display up to the maximum size specified by the kEZAudioPlotMaxHistoryBufferLength macro. Will return the actual set value, which will be either the given value if smaller than the kEZAudioPlotMaxHistoryBufferLength or kEZAudioPlotMaxHistoryBufferLength if a larger value is attempted to be set. + Sets the length of the rolling history buffer (i.e. the number of points in the rolling plot's buffer). Can grow or shrink the display up to the maximum size specified by the `maximumRollingHistoryLength` method. Will return the actual set value, which will be either the given value if smaller than the `maximumRollingHistoryLength` or `maximumRollingHistoryLength` if a larger value is attempted to be set. @param historyLength The new length of the rolling history buffer. - @return The new value equal to the historyLength or the kEZAudioPlotMaxHistoryBufferLength. + @return The new value equal to the historyLength or the `maximumRollingHistoryLength`. */ -(int)setRollingHistoryLength:(int)historyLength; +//------------------------------------------------------------------------------ + /** - Provides the length of the rolling history buffer + Provides the length of the rolling history buffer (i.e. the number of points in the rolling plot's buffer). * @return An int representing the length of the rolling history buffer */ -(int)rollingHistoryLength; -#pragma mark - Shared Methods +//------------------------------------------------------------------------------ +#pragma mark - Clearing The Plot +//------------------------------------------------------------------------------ + ///----------------------------------------------------------- /// @name Clearing The Plot ///----------------------------------------------------------- @@ -152,32 +152,70 @@ typedef struct { */ -(void)clear; +//------------------------------------------------------------------------------ +#pragma mark - Start/Stop Display Link +//------------------------------------------------------------------------------ + +/** + Call this method to tell the EZAudioDisplayLink to stop drawing temporarily. + */ +- (void)pauseDrawing; + +//------------------------------------------------------------------------------ + +/** + Call this method to manually tell the EZAudioDisplayLink to start drawing again. + */ +- (void)resumeDrawing; + +//------------------------------------------------------------------------------ +#pragma mark - Subclass +//------------------------------------------------------------------------------ + +///----------------------------------------------------------- +/// @name Customizing The Drawing +///----------------------------------------------------------- + +/** + This method is used to perform the actual OpenGL drawing code to clear the background and draw the lines representing the 2D audio plot. Subclasses can use the current implementation as an example and implement their own custom geometries. This is the analogy of overriding the drawRect: method in an NSView or UIView. + @param points An array of EZAudioPlotGLPoint structures representing the mapped audio data to x,y coordinates. The x-axis goes from 0 to the number of points (pointCount) while the y-axis goes from -1 to 1. Check out the implementation of this method to see how the model view matrix of the base effect is transformed to map this properly to the viewport. + @param pointCount A UInt32 representing the number of points contained in the points array. + @param baseEffect An optional GLKBaseEffect to use as a default shader. Call prepareToDraw on the base effect before any glDrawArrays call. + @param vbo The Vertex Buffer Object used to buffer the point data. + @param vab The Vertex Array Buffer used to bind the Vertex Buffer Object. This is a Mac only thing, you can ignore this completely on iOS. + @param interpolated A BOOL indicating whether the data has been interpolated. This means the point data is twice as long, where every other point is 0 on the y-axis to allow drawing triangle stripes for filled in waveforms. Typically if the point data is interpolated you will be using the GL_TRIANGLE_STRIP drawing mode, while non-interpolated plots will just use a GL_LINE_STRIP drawing mode. + @param mirrored A BOOL indicating whether the plot should be mirrored about the y-axis (or whatever geometry you come up with). + @param gain A float representing a gain that should be used to influence the height or intensity of your geometry's shape. A gain of 0.0 means silence, a gain of 1.0 means full volume (you're welcome to boost this to whatever you want). + */ +- (void)redrawWithPoints:(EZAudioPlotGLPoint *)points + pointCount:(UInt32)pointCount + baseEffect:(GLKBaseEffect *)baseEffect + vertexBufferObject:(GLuint)vbo + vertexArrayBuffer:(GLuint)vab + interpolated:(BOOL)interpolated + mirrored:(BOOL)mirrored + gain:(float)gain; + +//------------------------------------------------------------------------------ + ///----------------------------------------------------------- -/// @name Shared OpenGL Methods +/// @name Subclass Methods ///----------------------------------------------------------- + /** - Converts a float array to an array of EZAudioPlotGLPoint structures that hold the (x,y) values the OpenGL buffer needs to properly plot its points. - @param graph A pointer to the array that should hold the EZAudioPlotGLPoint structures. - @param graphSize The size (or length) of the array with the EZAudioPlotGLPoint structures. - @param drawingType The EZAudioPlotGLDrawType constant defining whether the plot should interpolate between points for a triangle strip (filled waveform) or not for a line strip (stroked waveform) - @param buffer The float array holding the audio data - @param bufferSize The size of the float array holding the audio data - @param gain The gain (always greater than 0.0) to apply to the amplitudes (y-values) of the graph. Y-values can only range from -1.0 to 1.0 so any value that's greater will be rounded to -1.0 or 1.0. + Provides the default length of the rolling history buffer when the plot is initialized. Default is `EZAudioPlotDefaultHistoryBufferLength` constant. + @return An int describing the initial length of the rolling history buffer. */ -+(void)fillGraph:(EZAudioPlotGLPoint*)graph - withGraphSize:(UInt32)graphSize - forDrawingType:(EZAudioPlotGLDrawType)drawingType - withBuffer:(float*)buffer - withBufferSize:(UInt32)bufferSize - withGain:(float)gain; +- (int)defaultRollingHistoryLength; + +//------------------------------------------------------------------------------ /** - Determines the proper size of a graph given a EZAudioPlotGLDrawType (line strip or triangle strip) and the size of the incoming buffer. Triangle strips require interpolating between points so the buffer becomes 2*bufferSize - @param drawingType The EZAudioPlotGLDraw type (line strip or triangle strip) - @param bufferSize The size of the float array holding the audio data coming in. - @return A Int32 representing the proper graph size that should be used to account for any necessary interpolating between points. + Provides the default maximum rolling history length - that is, the maximum amount of points the `setRollingHistoryLength:` method may be set to. If a length higher than this is set then the plot will likely crash because the appropriate resources are only allocated once during the plot's initialization step. Defualt is `EZAudioPlotDefaultMaxHistoryBufferLength` constant. + @return An int describing the maximum length of the absolute rolling history buffer. */ -+(UInt32)graphSizeForDrawingType:(EZAudioPlotGLDrawType)drawingType - withBufferSize:(UInt32)bufferSize; +- (int)maximumRollingHistoryLength; + +//------------------------------------------------------------------------------ -@end +@end \ No newline at end of file diff --git a/EZAudio/EZAudioPlotGL.m b/EZAudio/EZAudioPlotGL.m index abbb94f3..f68b9a23 100644 --- a/EZAudio/EZAudioPlotGL.m +++ b/EZAudio/EZAudioPlotGL.m @@ -24,748 +24,510 @@ // THE SOFTWARE. #import "EZAudioPlotGL.h" +#import "EZAudioDisplayLink.h" #import "EZAudioUtilities.h" #import "EZAudioPlot.h" -#if TARGET_OS_IPHONE - #import "EZAudioPlotGLKViewController.h" -@interface EZAudioPlotGL () -@property (nonatomic,strong,readonly) EZAudioPlotGLKViewController *glViewController; -@end -#elif TARGET_OS_MAC -@interface EZAudioPlotGL (){ - - // Flags indicating whether the plots have been instantiated - BOOL _hasBufferPlotData; - BOOL _hasRollingPlotData; - - // Vertex Array Buffers - GLuint _bufferPlotVAB; - GLuint _rollingPlotVAB; - - // Vertex Buffer Objects - GLuint _bufferPlotVBO; - GLuint _rollingPlotVBO; - - // Display Link - CVDisplayLinkRef _displayLink; - - // Buffers size - UInt32 _bufferPlotGraphSize; - UInt32 _rollingPlotGraphSize; - - // Rolling History - BOOL _setMaxLength; - float *_scrollHistory; - int _scrollHistoryIndex; - UInt32 _scrollHistoryLength; - BOOL _changingHistorySize; - - // Copied buffer data - float *_copiedBuffer; - UInt32 _copiedBufferSize; - -} -@property (nonatomic,assign,readonly) EZAudioPlotGLDrawType drawingType; -@property (nonatomic,strong) GLKBaseEffect *baseEffect; +//------------------------------------------------------------------------------ +#pragma mark - Data Structures +//------------------------------------------------------------------------------ + +typedef struct +{ + BOOL interpolated; + EZPlotHistoryInfo *historyInfo; + EZAudioPlotGLPoint *points; + UInt32 pointCount; + GLuint vbo; + GLuint vab; +} EZAudioPlotGLInfo; + +//------------------------------------------------------------------------------ +#pragma mark - EZAudioPlotGL (Interface Extension) +//------------------------------------------------------------------------------ + +@interface EZAudioPlotGL () +@property (nonatomic, strong) GLKBaseEffect *baseEffect; +@property (nonatomic, strong) EZAudioDisplayLink *displayLink; +@property (nonatomic, assign) EZAudioPlotGLInfo *info; @end -#endif + +//------------------------------------------------------------------------------ +#pragma mark - EZAudioPlotGL (Implementation) +//------------------------------------------------------------------------------ @implementation EZAudioPlotGL -#if TARGET_OS_IPHONE -@synthesize glViewController = _glViewController; -#elif TARGET_OS_MAC -@synthesize baseEffect = _baseEffect; -#endif -@synthesize backgroundColor = _backgroundColor; -@synthesize color = _color; -@synthesize gain = _gain; -@synthesize plotType = _plotType; -@synthesize shouldFill = _shouldFill; -@synthesize shouldMirror = _shouldMirror; -#pragma mark - Initialization --(id)init +//------------------------------------------------------------------------------ +#pragma mark - Dealloc +//------------------------------------------------------------------------------ + +- (void)dealloc { - self = [super init]; - if (self) { - [self initializeView]; - } - return self; + [self.displayLink stop]; + self.displayLink = nil; + [EZAudioUtilities freeHistoryInfo:self.info->historyInfo]; +#if !TARGET_OS_IPHONE + glDeleteVertexArrays(1, &self.info->vab); +#endif + glDeleteBuffers(1, &self.info->vbo); + free(self.info->points); + free(self.info); + self.baseEffect = nil; } --(id)initWithCoder:(NSCoder *)aDecoder { - self = [super initWithCoder:aDecoder]; - if(self){ - [self initializeView]; - } - return self; -} +//------------------------------------------------------------------------------ +#pragma mark - Initialization +//------------------------------------------------------------------------------ --(id)initWithFrame:(CGRect)frame +- (instancetype)init { - self = [super initWithFrame:frame]; - if (self) { - [self initializeView]; - } - return self; + self = [super init]; + if (self) + { + [self setup]; + } + return self; } -#pragma mark - Initialize Properties Here --(void)initializeView { -#if TARGET_OS_IPHONE - // Initialize the subview controller - _glViewController = [[EZAudioPlotGLKViewController alloc] init]; - _glViewController.view.frame = self.bounds; - [self insertSubview:self.glViewController.view atIndex:0]; -#elif TARGET_OS_MAC - _copiedBuffer = NULL; -#endif - // Set the default properties - self.gain = 1.0; - self.plotType = EZPlotTypeBuffer; -#if TARGET_OS_IPHONE - self.backgroundColor = [UIColor colorWithRed:0.796 green:0.749 blue:0.663 alpha:1]; - self.color = [UIColor colorWithRed:0.481 green:0.548 blue:0.637 alpha:1]; -#elif TARGET_OS_MAC - _scrollHistory = NULL; - _scrollHistoryLength = EZAudioPlotDefaultHistoryBufferLength; -#endif - self.shouldFill = NO; - self.shouldMirror = NO; -} +//------------------------------------------------------------------------------ -#pragma mark - Setters --(void)setBackgroundColor:(id)backgroundColor { - _backgroundColor = backgroundColor; -#if TARGET_OS_IPHONE - self.glViewController.backgroundColor = backgroundColor; -#elif TARGET_OS_MAC - [self _refreshWithBackgroundColor:backgroundColor]; -#endif +- (id)initWithCoder:(NSCoder *)aDecoder +{ + self = [super initWithCoder:aDecoder]; + if (self) + { + [self setup]; + } + return self; } --(void)setColor:(id)color { - _color = color; -#if TARGET_OS_IPHONE - self.glViewController.color = color; -#elif TARGET_OS_MAC - [self _refreshWithColor:color]; -#endif -} +//------------------------------------------------------------------------------ -#if TARGET_OS_IPHONE -#elif TARGET_OS_MAC --(void)setDrawingType:(EZAudioPlotGLDrawType)drawingType { - CGLLockContext([[self openGLContext] CGLContextObj]); - _drawingType = drawingType; - CGLUnlockContext([[self openGLContext] CGLContextObj]); +- (instancetype)initWithFrame:(EZRect)frame +{ + self = [super initWithFrame:frame]; + if (self) + { + [self setup]; + } + return self; } -#endif -#if TARGET_OS_IPHONE --(void)setGain:(float)gain { - _gain = gain; - self.glViewController.gain = gain; -} -#elif TARGET_OS_MAC -// Gain changed mac -#endif +//------------------------------------------------------------------------------ #if TARGET_OS_IPHONE --(void)setPlotType:(EZPlotType)plotType { - _plotType = plotType; - self.glViewController.plotType = plotType; +- (instancetype)initWithFrame:(CGRect)frame + context:(EAGLContext *)context +{ + self = [super initWithFrame:frame context:context]; + if (self) + { + [self setup]; + } + return self; } #elif TARGET_OS_MAC -// Plot type changed mac +- (instancetype)initWithFrame:(NSRect)frameRect + pixelFormat:(NSOpenGLPixelFormat *)format +{ + self = [super initWithFrame:frameRect pixelFormat:format]; + if (self) + { + [self setup]; + } + return self; +} #endif --(void)setShouldFill:(BOOL)shouldFill { - _shouldFill = shouldFill; +//------------------------------------------------------------------------------ +#pragma mark - Setup +//------------------------------------------------------------------------------ + +- (void)setup +{ + // + // Setup info data structure + // + self.info = (EZAudioPlotGLInfo *)malloc(sizeof(EZAudioPlotGLInfo)); + memset(self.info, 0, sizeof(EZAudioPlotGLInfo)); + + // + // Create points array + // + UInt32 pointCount = [self maximumRollingHistoryLength]; + self.info->points = (EZAudioPlotGLPoint *)calloc(sizeof(EZAudioPlotGLPoint), pointCount); + self.info->pointCount = pointCount; + + // + // Create the history data structure to hold the rolling data + // + self.info->historyInfo = [EZAudioUtilities historyInfoWithDefaultLength:[self defaultRollingHistoryLength] + maximumLength:[self maximumRollingHistoryLength]]; + + // + // Setup OpenGL specific stuff + // + [self setupOpenGL]; + + // + // Setup view properties + // + self.gain = 1.0f; #if TARGET_OS_IPHONE - self.glViewController.drawingType = shouldFill ? EZAudioPlotGLDrawTypeTriangleStrip : EZAudioPlotGLDrawTypeLineStrip; + self.backgroundColor = [UIColor colorWithRed:0.569f green:0.82f blue:0.478f alpha:1.0f]; + self.color = [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f]; #elif TARGET_OS_MAC - // Fill flag changed mac - self.drawingType = shouldFill ? EZAudioPlotGLDrawTypeTriangleStrip : EZAudioPlotGLDrawTypeLineStrip; + self.backgroundColor = [NSColor colorWithCalibratedRed:0.569f green:0.82f blue:0.478f alpha:1.0f]; + self.color = [NSColor colorWithCalibratedRed:1.0f green:1.0f blue:1.0f alpha:1.0f]; #endif + + // + // Create the display link + // + self.displayLink = [EZAudioDisplayLink displayLinkWithDelegate:self]; + [self.displayLink start]; } -#if TARGET_OS_IPHONE --(void)setShouldMirror:(BOOL)shouldMirror { - _shouldMirror = shouldMirror; - self.glViewController.shouldMirror = shouldMirror; -} -#elif TARGET_OS_MAC -// Mirror flag changed mac -#endif +//------------------------------------------------------------------------------ -#pragma mark - Get Samples --(void)updateBuffer:(float *)buffer - withBufferSize:(UInt32)bufferSize { +- (void)setupOpenGL +{ + self.baseEffect = [[GLKBaseEffect alloc] init]; + self.baseEffect.useConstantColor = YES; #if TARGET_OS_IPHONE - [self.glViewController updateBuffer:buffer - withBufferSize:bufferSize]; + if (!self.context) + { + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + } + [EAGLContext setCurrentContext:self.context]; + self.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888; + self.drawableDepthFormat = GLKViewDrawableDepthFormat24; + self.drawableStencilFormat = GLKViewDrawableStencilFormat8; + self.drawableMultisample = GLKViewDrawableMultisample4X; + self.opaque = NO; + self.enableSetNeedsDisplay = NO; #elif TARGET_OS_MAC - - - - if (_copiedBuffer == NULL){ - _copiedBuffer = (float*)malloc(bufferSize*sizeof(float)); - } - _copiedBufferSize = bufferSize; - // Copy the buffer - memcpy(_copiedBuffer, - buffer, - bufferSize*sizeof(float)); - // Draw based on plot type - switch(_plotType) { - case EZPlotTypeBuffer: - [self _updateBufferPlotBufferWithAudioReceived:_copiedBuffer - withBufferSize:_copiedBufferSize]; - break; - case EZPlotTypeRolling: - [self _updateRollingPlotBufferWithAudioReceived:_copiedBuffer - withBufferSize:_copiedBufferSize]; - break; - default: - break; - } + self.wantsBestResolutionOpenGLSurface = YES; + self.wantsLayer = YES; + self.layer.opaque = YES; + self.layer.backgroundColor = [NSColor clearColor].CGColor; + if (!self.pixelFormat) + { + NSOpenGLPixelFormatAttribute attrs[] = + { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAMultisample, + NSOpenGLPFASampleBuffers, 1, + NSOpenGLPFASamples, 4, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAOpenGLProfile, + NSOpenGLProfileVersion3_2Core, 0 + }; + self.pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; + } +#if DEBUG + NSAssert(self.pixelFormat, @"Could not create OpenGL pixel format so context is not valid"); +#endif + self.openGLContext = [[NSOpenGLContext alloc] initWithFormat:self.pixelFormat + shareContext:nil]; + GLint swapInt = 1; GLint surfaceOpacity = 0; + [self.openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; + [self.openGLContext setValues:&surfaceOpacity forParameter:NSOpenGLCPSurfaceOpacity]; + [self.openGLContext lock]; + glGenVertexArrays(1, &self.info->vab); + glBindVertexArray(self.info->vab); +#endif + glGenBuffers(1, &self.info->vbo); + glBindBuffer(GL_ARRAY_BUFFER, self.info->vbo); + glBufferData(GL_ARRAY_BUFFER, + self.info->pointCount * sizeof(EZAudioPlotGLPoint), + self.info->points, + GL_STREAM_DRAW); +#if !TARGET_OS_IPHONE + [self.openGLContext unlock]; #endif } -#pragma mark - OSX Specific GL Implementation -#if TARGET_OS_IPHONE +//------------------------------------------------------------------------------ +#pragma mark - Updating The Plot +//------------------------------------------------------------------------------ -// Handled by the embedded GLKViewController +- (void)updateBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize +{ + // + // Update history + // + [EZAudioUtilities appendBuffer:buffer + withBufferSize:bufferSize + toHistoryInfo:self.info->historyInfo]; + + // + // Convert this data to point data + // + switch (self.plotType) + { + case EZPlotTypeBuffer: + [self setSampleData:buffer + length:bufferSize]; + break; + case EZPlotTypeRolling: + [self setSampleData:self.info->historyInfo->buffer + length:self.info->historyInfo->bufferSize]; + break; + default: + break; + } +} -#elif TARGET_OS_MAC +//------------------------------------------------------------------------------ -#pragma mark - Awake --(void)awakeFromNib { - - // Setup the base effect - [self _setupBaseEffect]; - - // Setup the OpenGL Pixel Format and Context - [self _setupProfile]; - - // Setup view - [self _setupView]; - +- (void)setSampleData:(float *)data length:(int)length +{ + int pointCount = self.shouldFill ? length * 2 : length; + EZAudioPlotGLPoint *points = self.info->points; + for (int i = 0; i < length; i++) + { + if (self.shouldFill) + { + points[i * 2].x = points[i * 2 + 1].x = i; + points[i * 2].y = data[i]; + points[i * 2 + 1].y = 0.0f; + } + else + { + points[i].x = i; + points[i].y = data[i]; + } + } + points[0].y = points[pointCount - 1].y = 0.0f; + self.info->pointCount = pointCount; + self.info->interpolated = self.shouldFill; +#if !TARGET_OS_IPHONE + [self.openGLContext lock]; + glBindVertexArray(self.info->vab); +#endif + glBindBuffer(GL_ARRAY_BUFFER, self.info->vbo); + glBufferSubData(GL_ARRAY_BUFFER, + 0, + pointCount * sizeof(EZAudioPlotGLPoint), + self.info->points); +#if !TARGET_OS_IPHONE + [self.openGLContext unlock]; +#endif } --(void)_setupBaseEffect { - self.baseEffect = [[GLKBaseEffect alloc] init]; - self.baseEffect.useConstantColor = GL_TRUE; - self.baseEffect.constantColor = GLKVector4Make(0.489, 0.34, 0.185, 1.0); -} +//------------------------------------------------------------------------------ +#pragma mark - Adjusting History Resolution +//------------------------------------------------------------------------------ --(void)_setupProfile { - - NSOpenGLPixelFormatAttribute attrs[] = - { - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAMultisample, - NSOpenGLPFASampleBuffers, 1, - NSOpenGLPFASamples, 4, - NSOpenGLPFADepthSize, 24, - NSOpenGLPFAOpenGLProfile, - NSOpenGLProfileVersion3_2Core, 0 - }; - - NSOpenGLPixelFormat *pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; - NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pf - shareContext:nil]; - - if (!pf) - { - NSLog(@"No OpenGL pixel format"); - } - - // Debug only - CGLEnable([context CGLContextObj], kCGLCECrashOnRemovedFunctions); - - self.pixelFormat = pf; - self.openGLContext = context; +- (int)rollingHistoryLength +{ + return self.info->historyInfo->bufferSize; } --(void)_setupView { - self.backgroundColor = [NSColor colorWithCalibratedRed: 0.796 green: 0.749 blue: 0.663 alpha: 1]; - self.color = [NSColor colorWithCalibratedRed: 0.481 green: 0.548 blue: 0.637 alpha: 1]; +//------------------------------------------------------------------------------ + +- (int)setRollingHistoryLength:(int)historyLength +{ + self.info->historyInfo->bufferSize = MIN(EZAudioPlotDefaultMaxHistoryBufferLength, historyLength); + return self.info->historyInfo->bufferSize; } -#pragma mark - Prepare --(void)prepareOpenGL { - [super prepareOpenGL]; +//------------------------------------------------------------------------------ +#pragma mark - Clearing The Plot +//------------------------------------------------------------------------------ - GLint swapInt = 1; - [self.openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; +- (void)clear +{ + float emptyBuffer[1]; + emptyBuffer[0] = 0.0f; + [self setSampleData:emptyBuffer length:1]; + [EZAudioUtilities clearHistoryInfo:self.info->historyInfo]; +#if TARGET_OS_IPHONE + [self display]; +#elif TARGET_OS_MAC + [self redraw]; +#endif +} - //////////////////////////////////////////////////////////////////////////// - // Setup VABs and VBOs // - //////////////////////////////////////////////////////////////////////////// - // Buffer - glGenVertexArrays(1,&_bufferPlotVAB); - glBindVertexArray(_bufferPlotVAB); - glGenBuffers(1,&_bufferPlotVBO); - glBindBuffer(GL_ARRAY_BUFFER,_bufferPlotVBO); - - // Rolling - glGenVertexArrays(1,&_rollingPlotVAB); - glBindVertexArray(_rollingPlotVAB); - glGenBuffers(1,&_rollingPlotVBO); - glBindBuffer(GL_ARRAY_BUFFER,_rollingPlotVBO); - - if (self.shouldFill){ - glBindVertexArray(_rollingPlotVAB); - glBindBuffer(GL_ARRAY_BUFFER,_rollingPlotVBO); - } - - // Enable anti-aliasing - glEnable(GL_MULTISAMPLE); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glClearColor(0, 0, 0, 0); - self.layer = nil; - self.wantsBestResolutionOpenGLSurface = YES; - - // Set the background color - [self _refreshWithBackgroundColor:self.backgroundColor]; - [self _refreshWithColor:self.color]; +//------------------------------------------------------------------------------ +#pragma mark - Start/Stop Display Link +//------------------------------------------------------------------------------ - // Setup the display link (rendering loop) - [self _setupDisplayLink]; +- (void)pauseDrawing +{ + [self.displayLink stop]; } --(void)_setupDisplayLink { - // Create a display link capable of being used with all active displays - CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink); - - // Set the renderer output callback function - CVDisplayLinkSetOutputCallback(_displayLink, &DisplayLinkCallback, (__bridge void *)(self)); - - // Set the display link for the current renderer - CGLContextObj cglContext = self.openGLContext.CGLContextObj; - CGLPixelFormatObj cglPixelFormat = self.pixelFormat.CGLPixelFormatObj; - CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(_displayLink, cglContext, cglPixelFormat); - - // Activate the display link - CVDisplayLinkStart(_displayLink); - - // Register to be notified when the window closes so we can stop the displaylink - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowWillClose:) - name:NSWindowWillCloseNotification - object:[self window]]; - -} +//------------------------------------------------------------------------------ -- (void) windowWillClose:(NSNotification*)notification +- (void)resumeDrawing { - // Stop the display link when the window is closing because default - // OpenGL render buffers will be destroyed. If display link continues to - // fire without renderbuffers, OpenGL draw calls will set errors. - - CVDisplayLinkStop(_displayLink); + [self.displayLink start]; } -#pragma mark - Display Link Callback -// This is the renderer output callback function -static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, - const CVTimeStamp* now, - const CVTimeStamp* outputTime, - CVOptionFlags flagsIn, - CVOptionFlags* flagsOut, - void* displayLinkContext) +//------------------------------------------------------------------------------ +#pragma mark - Setters +//------------------------------------------------------------------------------ + +- (void)setBackgroundColor:(id)backgroundColor { - CVReturn result = [(__bridge EZAudioPlotGL*)displayLinkContext getFrameForTime:outputTime]; - return result; + _backgroundColor = backgroundColor; + if (backgroundColor) + { + CGColorRef colorRef = [backgroundColor CGColor]; + CGFloat red; CGFloat green; CGFloat blue; CGFloat alpha; + [EZAudioUtilities getColorComponentsFromCGColor:colorRef + red:&red + green:&green + blue:&blue + alpha:&alpha]; + // + // Note! If you set the alpha to be 0 on mac for a transparent view + // the EZAudioPlotGL will make the superview layer-backed to make + // sure there is a surface to display itself on (or else you will get + // some pretty weird drawing glitches + // +#if !TARGET_OS_IPHONE + if (alpha == 0.0f) + { + [self.superview setWantsLayer:YES]; + } +#endif + glClearColor(red, green, blue, alpha); + } + else + { + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + } } -- (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime +//------------------------------------------------------------------------------ + +- (void)setColor:(id)color { - @autoreleasepool { - [self drawFrame]; - } - return kCVReturnSuccess; + _color = color; + if (color) + { + CGColorRef colorRef = [color CGColor]; + CGFloat red; CGFloat green; CGFloat blue; CGFloat alpha; + [EZAudioUtilities getColorComponentsFromCGColor:colorRef + red:&red + green:&green + blue:&blue + alpha:&alpha]; + self.baseEffect.constantColor = GLKVector4Make(red, green, blue, alpha); + } + else + { + self.baseEffect.constantColor = GLKVector4Make(0.0f, 0.0f, 0.0f, 0.0f); + } } -#pragma mark - Buffer Updating By Type --(void)_updateBufferPlotBufferWithAudioReceived:(float*)buffer - withBufferSize:(UInt32)bufferSize { - - // Lock - CGLLockContext([[self openGLContext] CGLContextObj]); - - // Bind to buffer VBO - glBindVertexArray(_bufferPlotVAB); - glBindBuffer(GL_ARRAY_BUFFER,_bufferPlotVBO); - - // If starting with a VBO of half of our max size make sure we initialize it to anticipate - // a filled graph (which needs 2 * bufferSize) to allocate its resources properly - if (!_hasBufferPlotData && _drawingType == EZAudioPlotGLDrawTypeLineStrip){ - EZAudioPlotGLPoint maxGraph[2*bufferSize]; - glBufferData(GL_ARRAY_BUFFER, sizeof(maxGraph), maxGraph, GL_STREAM_DRAW); - _hasBufferPlotData = YES; - } - - // Setup the buffer plot's graph size - _bufferPlotGraphSize = [EZAudioPlotGL graphSizeForDrawingType:_drawingType - withBufferSize:bufferSize]; - - // Setup the graph - EZAudioPlotGLPoint graph[_bufferPlotGraphSize]; - - // Fill in graph data - [EZAudioPlotGL fillGraph:graph - withGraphSize:_bufferPlotGraphSize - forDrawingType:_drawingType - withBuffer:buffer - withBufferSize:bufferSize - withGain:self.gain]; - - // Update the drawing - if (!_hasBufferPlotData){ - glBufferData(GL_ARRAY_BUFFER, sizeof(graph) , graph, GL_STREAM_DRAW); - _hasBufferPlotData = YES; - - } - else { - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(graph), graph); - - } - - // Unlock - CGLUnlockContext([[self openGLContext] CGLContextObj]); - -} +//------------------------------------------------------------------------------ +#pragma mark - Drawing +//------------------------------------------------------------------------------ --(void)_updateRollingPlotBufferWithAudioReceived:(float*)buffer - withBufferSize:(UInt32)bufferSize { - - // Lock - CGLLockContext([[self openGLContext] CGLContextObj]); - - // Bind to rolling VBO - glBindVertexArray(_rollingPlotVAB); - glBindBuffer(GL_ARRAY_BUFFER,_rollingPlotVBO); - - // If starting with a VBO of half of our max size make sure we initialize it to anticipate - // a filled graph (which needs 2 * bufferSize) to allocate its resources properly - if (!_hasRollingPlotData){ - EZAudioPlotGLPoint maxGraph[2*EZAudioPlotDefaultMaxHistoryBufferLength]; - glBufferData(GL_ARRAY_BUFFER, sizeof(maxGraph), maxGraph, GL_STREAM_DRAW); - _hasRollingPlotData = YES; - } - - // Setup the plot - _rollingPlotGraphSize = [EZAudioPlotGL graphSizeForDrawingType:_drawingType - withBufferSize:_scrollHistoryLength]; - - // Fill the graph with data - EZAudioPlotGLPoint graph[_rollingPlotGraphSize]; - - - - // Update the scroll history datasource - [EZAudioUtilities updateScrollHistory:&_scrollHistory - withLength:_scrollHistoryLength - atIndex:&_scrollHistoryIndex - withBuffer:buffer - withBufferSize:bufferSize - isResolutionChanging:&_changingHistorySize]; - - // Fill in graph data - [EZAudioPlotGL fillGraph:graph - withGraphSize:_rollingPlotGraphSize - forDrawingType:_drawingType - withBuffer:_scrollHistory - withBufferSize:_scrollHistoryLength - withGain:self.gain]; - - // Update the drawing - if (!_hasRollingPlotData){ - glBufferData(GL_ARRAY_BUFFER, sizeof(graph), graph, GL_STREAM_DRAW); - _hasRollingPlotData = YES; - } - else { - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(graph), graph); - } - - // Unlock - CGLUnlockContext([[self openGLContext] CGLContextObj]); - +- (void)drawRect:(EZRect)rect +{ + [self redraw]; } -//#pragma mark - Render --(void)drawFrame { - - // Avoid flickering during resize by drawing - [[self openGLContext] makeCurrentContext]; - - // Lock - CGLLockContext([[self openGLContext] CGLContextObj]); - - // Draw frame - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - if (_hasBufferPlotData || _hasRollingPlotData){ - // Plot either a buffer plot or a rolling plot - switch(_plotType) { - case EZPlotTypeBuffer: - [self _drawBufferPlot]; - break; - case EZPlotTypeRolling: - [self _drawRollingPlot]; - break; - default: - break; - } - } +//------------------------------------------------------------------------------ - // Flush and unlock - CGLFlushDrawable([[self openGLContext] CGLContextObj]); - CGLUnlockContext([[self openGLContext] CGLContextObj]); - +- (void)redraw +{ +#if !TARGET_OS_IPHONE + [self.openGLContext makeCurrentContext]; + [self.openGLContext lock]; +#endif + [self redrawWithPoints:self.info->points + pointCount:self.info->pointCount + baseEffect:self.baseEffect + vertexBufferObject:self.info->vbo + vertexArrayBuffer:self.info->vab + interpolated:self.info->interpolated + mirrored:self.shouldMirror + gain:self.gain]; +#if !TARGET_OS_IPHONE + [self.openGLContext flushBuffer]; + [self.openGLContext unlock]; +#endif } --(void)_drawBufferPlot { - - glBindVertexArray(_bufferPlotVAB); - glBindBuffer(GL_ARRAY_BUFFER,_bufferPlotVBO); - - [self.baseEffect prepareToDraw]; - self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeXRotation(0); - - // Enable the vertex data - glEnableVertexAttribArray(GLKVertexAttribPosition); - // Define the vertex data size & layout - glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(EZAudioPlotGLPoint), NULL); - // Draw the triangle - glDrawArrays(_drawingType,0,_bufferPlotGraphSize); - - // Mirrored - if (self.shouldMirror){ - [self.baseEffect prepareToDraw]; - self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeXRotation(M_PI); - - // Enable the vertex data - glEnableVertexAttribArray(GLKVertexAttribPosition); - // Define the vertex data size & layout - glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(EZAudioPlotGLPoint), NULL); - // Draw the triangle - glDrawArrays(_drawingType, 0, _bufferPlotGraphSize); - } - -} +//------------------------------------------------------------------------------ --(void)_drawRollingPlot { - - glBindVertexArray(_rollingPlotVAB); - glBindBuffer(GL_ARRAY_BUFFER,_rollingPlotVBO); - - [self.baseEffect prepareToDraw]; - self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeXRotation(0); - - // Enable the vertex data - glEnableVertexAttribArray(GLKVertexAttribPosition); - // Define the vertex data size & layout - glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(EZAudioPlotGLPoint), NULL); - // Draw the triangle - glDrawArrays(_drawingType, 0,_rollingPlotGraphSize); - - // Mirrored - if (self.shouldMirror){ - [self.baseEffect prepareToDraw]; - self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeXRotation(M_PI); - - // Enable the vertex data +- (void)redrawWithPoints:(EZAudioPlotGLPoint *)points + pointCount:(UInt32)pointCount + baseEffect:(GLKBaseEffect *)baseEffect + vertexBufferObject:(GLuint)vbo + vertexArrayBuffer:(GLuint)vab + interpolated:(BOOL)interpolated + mirrored:(BOOL)mirrored + gain:(float)gain +{ + glClear(GL_COLOR_BUFFER_BIT); + GLenum mode = interpolated ? GL_TRIANGLE_STRIP : GL_LINE_STRIP; + float interpolatedFactor = interpolated ? 2.0f : 1.0f; + float xscale = 2.0f / ((float)pointCount / interpolatedFactor); + float yscale = 1.0f * gain; + GLKMatrix4 transform = GLKMatrix4MakeTranslation(-1.0f, 0.0f, 0.0f); + transform = GLKMatrix4Scale(transform, xscale, yscale, 1.0f); + baseEffect.transform.modelviewMatrix = transform; +#if !TARGET_OS_IPHONE + glBindVertexArray(vab); +#endif + glBindBuffer(GL_ARRAY_BUFFER, vbo); + [baseEffect prepareToDraw]; glEnableVertexAttribArray(GLKVertexAttribPosition); - // Define the vertex data size & layout - glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(EZAudioPlotGLPoint), NULL); - // Draw the triangle - glDrawArrays(_drawingType, 0,_rollingPlotGraphSize); - } - -} - --(void)drawRect:(NSRect)dirtyRect { - [self drawFrame]; + glVertexAttribPointer(GLKVertexAttribPosition, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(EZAudioPlotGLPoint), + NULL); + glDrawArrays(mode, 0, pointCount); + if (mirrored) + { + baseEffect.transform.modelviewMatrix = GLKMatrix4Rotate(transform, M_PI, 1.0f, 0.0f, 0.0f); + [baseEffect prepareToDraw]; + glDrawArrays(mode, 0, pointCount); + } } -#pragma mark - Reshape --(void)reshape { - [super reshape]; - - // We draw on a secondary thread through the display link. However, when - // resizing the view, -drawRect is called on the main thread. - // Add a mutex around to avoid the threads accessing the context - // simultaneously when resizing. - CGLLockContext([[self openGLContext] CGLContextObj]); - - // Get the view size in Points - NSRect viewRectPoints = [self bounds]; - NSRect viewRectPixels = [self convertRectToBacking:viewRectPoints]; - - // Set the new dimensions in our renderer - glViewport(0, 0, viewRectPixels.size.width, viewRectPixels.size.height); - - CGLUnlockContext([[self openGLContext] CGLContextObj]); -} +//------------------------------------------------------------------------------ +#pragma mark - Subclass +//------------------------------------------------------------------------------ -#pragma mark - Private Setters --(void)_refreshWithBackgroundColor:(NSColor*)backgroundColor { - CGLLockContext([[self openGLContext] CGLContextObj]); - // Extract colors - CGFloat red; CGFloat green; CGFloat blue; CGFloat alpha; - [backgroundColor getRed:&red - green:&green - blue:&blue - alpha:&alpha]; - // Set them on the context - glClearColor((GLclampf)red,(GLclampf)green,(GLclampf)blue,(GLclampf)alpha); - CGLUnlockContext([[self openGLContext] CGLContextObj]); +- (int)defaultRollingHistoryLength +{ + return EZAudioPlotDefaultHistoryBufferLength; } --(void)_refreshWithColor:(NSColor*)color { - CGLLockContext([[self openGLContext] CGLContextObj]); - // Extract colors - CGFloat red; CGFloat green; CGFloat blue; CGFloat alpha; - [color getRed:&red - green:&green - blue:&blue - alpha:&alpha]; - // Set them on the base shader - self.baseEffect.constantColor = GLKVector4Make((GLclampf)red,(GLclampf)green,(GLclampf)blue,(GLclampf)alpha); - CGLUnlockContext([[self openGLContext] CGLContextObj]); -} +//------------------------------------------------------------------------------ -#pragma mark - Cleanup -- (void) dealloc +- (int)maximumRollingHistoryLength { - // Stop the display link BEFORE releasing anything in the view - // otherwise the display link thread may call into the view and crash - // when it encounters something that has been release - CVDisplayLinkStop(_displayLink); - CVDisplayLinkRelease(_displayLink); - - if (_copiedBuffer != NULL){ - free( _copiedBuffer); - } + return EZAudioPlotDefaultMaxHistoryBufferLength; } -#endif -#pragma mark - Adjust Resolution --(int)setRollingHistoryLength:(int)historyLength { -#if TARGET_OS_IPHONE - int result = [self.glViewController setRollingHistoryLength:historyLength]; - return result; -#elif TARGET_OS_MAC - historyLength = MIN(historyLength, EZAudioPlotDefaultMaxHistoryBufferLength); - size_t floatByteSize = sizeof(float); - _changingHistorySize = YES; - if (_scrollHistoryLength != historyLength){ - _scrollHistoryLength = historyLength; - } - _scrollHistory = realloc(_scrollHistory,_scrollHistoryLength*floatByteSize); - if (_scrollHistoryIndex < _scrollHistoryLength){ - memset(&_scrollHistory[_scrollHistoryIndex], - 0, - (_scrollHistoryLength-_scrollHistoryIndex)*floatByteSize); - } - else { - _scrollHistoryIndex = _scrollHistoryLength; - } - _changingHistorySize = NO; - return historyLength; -#endif - return EZAudioPlotDefaultHistoryBufferLength; -} +//------------------------------------------------------------------------------ +#pragma mark - EZAudioDisplayLinkDelegate +//------------------------------------------------------------------------------ --(int)rollingHistoryLength { -#if TARGET_OS_IPHONE - return self.glViewController.rollingHistoryLength; -#elif TARGET_OS_MAC - return _scrollHistoryLength; -#endif -} - -#pragma mark - Clearing --(void)clear { +- (void)displayLinkNeedsDisplay:(EZAudioDisplayLink *)displayLink +{ #if TARGET_OS_IPHONE - [self.glViewController clear]; + if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) + { + [self display]; + } #elif TARGET_OS_MAC + [self redraw]; #endif } -#pragma mark - Graph Methods -+(void)fillGraph:(EZAudioPlotGLPoint*)graph - withGraphSize:(UInt32)graphSize - forDrawingType:(EZAudioPlotGLDrawType)drawingType - withBuffer:(float*)buffer - withBufferSize:(UInt32)bufferSize - withGain:(float)gain { - if (drawingType == EZAudioPlotGLDrawTypeLineStrip){ - // graph size = buffer size to stroke waveform - for(int i = 0; i < graphSize; i++){ - float x = [EZAudioUtilities MAP:i - leftMin:0 - leftMax:bufferSize - rightMin:-1.0 - rightMax:1.0]; - graph[i].x = x; - graph[i].y = gain*buffer[i]; - } - } - else if (drawingType == EZAudioPlotGLDrawTypeTriangleStrip) { - // graph size = 2 * buffer size to draw triangles and fill regions properly - for(int i = 0; i < graphSize; i+=2){ - int bufferIndex = (int)[EZAudioUtilities MAP:i - leftMin:0 - leftMax:graphSize - rightMin:0 - rightMax:bufferSize]; - float x = [EZAudioUtilities MAP:bufferIndex - leftMin:0 - leftMax:bufferSize - rightMin:-1.0 - rightMax:1.0]; - graph[i].x = x; - graph[i].y = 0.0f; - } - for(int i = 0; i < graphSize; i+=2){ - int bufferIndex = (int)[EZAudioUtilities - MAP:i - leftMin:0 - leftMax:graphSize - rightMin:0 - rightMax:bufferSize]; - float x = [EZAudioUtilities MAP:bufferIndex - leftMin:0 - leftMax:bufferSize - rightMin:-1.0 - rightMax:1.0]; - graph[i+1].x = x; - graph[i+1].y = gain*buffer[bufferIndex]; - } - } -} - -+(UInt32)graphSizeForDrawingType:(EZAudioPlotGLDrawType)drawingType - withBufferSize:(UInt32)bufferSize { - UInt32 graphSize = bufferSize; - switch(drawingType) { - case EZAudioPlotGLDrawTypeLineStrip: - graphSize = bufferSize; - break; - case EZAudioPlotGLDrawTypeTriangleStrip: - graphSize = 2*bufferSize; - break; - default: - break; - } - return graphSize; -} +//------------------------------------------------------------------------------ -@end +@end \ No newline at end of file diff --git a/EZAudio/EZAudioPlotGLKViewController.h b/EZAudio/EZAudioPlotGLKViewController.h deleted file mode 100644 index defb10d8..00000000 --- a/EZAudio/EZAudioPlotGLKViewController.h +++ /dev/null @@ -1,127 +0,0 @@ -// -// EZAudioPlotGLKViewController.h -// EZAudio -// -// Created by Syed Haris Ali on 11/22/13. -// Copyright (c) 2015 Syed Haris Ali. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#import "TargetConditionals.h" - -#if TARGET_OS_IPHONE - -#import "EZAudioPlotGL.h" - -@class EZAudio; - -/** - EZAudioPlotGLKViewController is a subclass of the GLKViewController and handles the OpenGL drawing routine for iOS OpenGL ES views. This class has not been used outside the scope of the EZAudioPlotGL, but should be safe to use by itself if the intended use case is to have a view controller take up the whole screen. - */ -@interface EZAudioPlotGLKViewController : GLKViewController - -#pragma mark - Properties -///----------------------------------------------------------- -/// @name Customizing The Plot's Appearance -///----------------------------------------------------------- -/** - The default background color of the plot. For iOS the color is specified as a UIColor while for OSX the color is an NSColor. The default value on both platforms is black. - */ -@property (nonatomic,strong) UIColor *backgroundColor; - -/** - The default shader to use to fill the graph. - */ -@property (nonatomic,strong) GLKBaseEffect *baseEffect; - -/** - The default color of the plot's data (i.e. waveform, y-axis values). For iOS the color is specified as a UIColor while for OSX the color is an NSColor. The default value on both platforms is red. - */ -@property (nonatomic,strong) UIColor *color; - -/** - The OpenGL ES context (EAGLContext) in which to perform the drawing - */ -@property (nonatomic,strong) EAGLContext *context; - -/** - The EZAudioPlotGLDrawType specifying which OpenGL primitive to use for drawing (either line strip for stroke and no fill or triangle strip for fill) - */ -@property (nonatomic,assign) EZAudioPlotGLDrawType drawingType; - -/** - The plot's gain value, which controls the scale of the y-axis values. The default value of the gain is 1.0f and should always be greater than 0.0f. - */ -@property (nonatomic,assign,setter=setGain:) float gain; - -/** - The type of plot as specified by the `EZPlotType` enumeration (i.e. a buffer or rolling plot type). - */ -@property (nonatomic,assign,setter=setPlotType:) EZPlotType plotType; - -/** - A boolean indicating whether the graph should be rotated along the x-axis to give a mirrored reflection. This is typical for audio plots to produce the classic waveform look. A value of YES will produce a mirrored reflection of the y-values about the x-axis, while a value of NO will only plot the y-values. - */ -@property (nonatomic,assign,setter=setShouldMirror:) BOOL shouldMirror; - -#pragma mark - Adjust Resolution -///----------------------------------------------------------- -/// @name Adjusting The Resolution -///----------------------------------------------------------- - -/** - Sets the length of the rolling history display. Can grow or shrink the display up to the maximum size specified by the kEZAudioPlotMaxHistoryBufferLength macro. Will return the actual set value, which will be either the given value if smaller than the kEZAudioPlotMaxHistoryBufferLength or kEZAudioPlotMaxHistoryBufferLength if a larger value is attempted to be set. - @param historyLength The new length of the rolling history buffer. - @return The new value equal to the historyLength or the kEZAudioPlotMaxHistoryBufferLength. - */ --(int)setRollingHistoryLength:(int)historyLength; - -/** - Provides the length of the rolling history buffer - * @return An int representing the length of the rolling history buffer - */ --(int)rollingHistoryLength; - -#pragma mark - Clearing -///----------------------------------------------------------- -/// @name Clearing The Plot -///----------------------------------------------------------- - -/** - Clears all data from the audio plot (includes both EZPlotTypeBuffer and EZPlotTypeRolling) - */ --(void)clear; - -#pragma mark - Get Samples -///----------------------------------------------------------- -/// @name Updating The Plot -///----------------------------------------------------------- -/** - Updates the plot with the new buffer data and tells the view to redraw itself. Caller will provide a float array with the values they expect to see on the y-axis. The plot will internally handle mapping the x-axis and y-axis to the current view port, any interpolation for fills effects, and mirroring. - @param buffer A float array of values to map to the y-axis. - @param bufferSize The size of the float array that will be mapped to the y-axis. - @warning The bufferSize is expected to be the same, constant value once initial triggered. For plots using OpenGL a vertex buffer object will be allocated with a maximum buffersize of (2 * the initial given buffer size) to account for any interpolation necessary for filling in the graph. Updates use the glBufferSubData(...) function, which will crash if the buffersize exceeds the initial maximum allocated size. - */ --(void)updateBuffer:(float *)buffer - withBufferSize:(UInt32)bufferSize; - -@end - -#elif TARGET_OS_MAC -#endif diff --git a/EZAudio/EZAudioPlotGLKViewController.m b/EZAudio/EZAudioPlotGLKViewController.m deleted file mode 100644 index da33e026..00000000 --- a/EZAudio/EZAudioPlotGLKViewController.m +++ /dev/null @@ -1,486 +0,0 @@ -// -// EZAudioPlotGLKViewController.m -// EZAudio -// -// Created by Syed Haris Ali on 11/22/13. -// Copyright (c) 2015 Syed Haris Ali. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#if TARGET_OS_IPHONE - -#import "EZAudioPlotGLKViewController.h" -#import "EZAudioUtilities.h" -#import "EZAudioPlot.h" - -@interface EZAudioPlotGLKViewController () { - - // Flags indicating whether the plots have been instantiated - BOOL _hasBufferPlotData; - BOOL _hasRollingPlotData; - - // The buffers - GLuint _bufferPlotVBO; - GLuint _rollingPlotVBO; - - // Buffers size - UInt32 _bufferPlotGraphSize; - UInt32 _rollingPlotGraphSize; - - // Rolling History - BOOL _setMaxLength; - float *_scrollHistory; - int _scrollHistoryIndex; - UInt32 _scrollHistoryLength; - BOOL _changingHistorySize; - -} -@end - -@implementation EZAudioPlotGLKViewController -@synthesize baseEffect = _baseEffect; -@synthesize context = _context; -@synthesize drawingType = _drawingType; -@synthesize plotType = _plotType; -@synthesize shouldMirror = _shouldMirror; - -#pragma mark - Initialization --(id)init -{ - self = [super init]; - if (self) { - [self initializeView]; - } - return self; -} - --(id)initWithCoder:(NSCoder *)aDecoder { - self = [super initWithCoder:aDecoder]; - if(self){ - [self initializeView]; - } - return self; -} - --(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; - if(self){ - [self initializeView]; - } - return self; - -} -#pragma mark - Initialize Properties Here --(void)initializeView { - // Setup the base effect - self.baseEffect = [[GLKBaseEffect alloc] init]; - self.baseEffect.useConstantColor = GL_TRUE; - self.preferredFramesPerSecond = 60; - _scrollHistory = NULL; - _scrollHistoryLength = EZAudioPlotDefaultHistoryBufferLength; -} - -#pragma mark - View Did Load --(void)viewDidLoad { - [super viewDidLoad]; - - // Setup the context - if (![EAGLContext currentContext]) - { - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - } - else - { - self.context = [EAGLContext currentContext]; - } - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - else { - EAGLContext.currentContext = self.context; - } - - // Set the view's context - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableMultisample = GLKViewDrawableMultisample4X; - view.opaque = NO; - - // Generate both the buffer id references - glGenBuffers(1, &_bufferPlotVBO); - glGenBuffers(1, &_rollingPlotVBO); - - // Refresh color values - [self _refreshWithBackgroundColor: self.backgroundColor]; - [self _refreshWithColor: self.color]; - - // Set the line width for the context - glLineWidth(2.0); - -} - -#pragma mark - Adjust Resolution --(int)setRollingHistoryLength:(int)historyLength { - _changingHistorySize = YES; - historyLength = MIN(historyLength, EZAudioPlotDefaultMaxHistoryBufferLength); - size_t floatByteSize = sizeof(float); - if (_scrollHistoryLength != historyLength){ - _scrollHistoryLength = historyLength; - } - _scrollHistory = realloc(_scrollHistory,_scrollHistoryLength*floatByteSize); - if (_scrollHistoryIndex < _scrollHistoryLength){ - memset(&_scrollHistory[_scrollHistoryIndex], - 0, - (_scrollHistoryLength-_scrollHistoryIndex)*floatByteSize); - } - else { - _scrollHistoryIndex = _scrollHistoryLength; - } - [self _updateRollingPlotDisplay]; - _changingHistorySize = NO; - return historyLength; -} - --(int)rollingHistoryLength { - return _scrollHistoryLength; -} - -#pragma mark - Clearing --(void)clear -{ - _scrollHistoryIndex = 0; - [self _clearBufferPlot]; - [self _clearRollingPlot]; -} - --(void)_clearBufferPlot -{ - if (_hasBufferPlotData) - { - float empty[_bufferPlotGraphSize]; - memset( empty, 0.0f, sizeof(float)); - [self _updateBufferPlotBufferWithAudioReceived:empty - withBufferSize:_bufferPlotGraphSize]; - } -} - --(void)_clearRollingPlot -{ - if (_hasRollingPlotData) - { - float empty[_rollingPlotGraphSize]; - EZAudioPlotGLPoint graph[_rollingPlotGraphSize]; - // Figure out better way to do this - for(int i = 0; i < _rollingPlotGraphSize; i++) - { - empty[i] = 0.0f; - } - for(int i = 0; i < _scrollHistoryLength; i++) - { - _scrollHistory[i] = 0.0f; - } - // Update the scroll history datasource - [EZAudioUtilities updateScrollHistory:&_scrollHistory - withLength:_scrollHistoryLength - atIndex:&_scrollHistoryIndex - withBuffer:empty - withBufferSize:_rollingPlotGraphSize - isResolutionChanging:&_changingHistorySize]; - // Fill in graph data - [EZAudioPlotGL fillGraph:graph - withGraphSize:_rollingPlotGraphSize - forDrawingType:_drawingType - withBuffer:_scrollHistory - withBufferSize:_scrollHistoryLength - withGain:self.gain]; - // Update the drawing - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(graph), graph); - } -} - -#pragma mark - Get Samples --(void)updateBuffer:(float *)buffer - withBufferSize:(UInt32)bufferSize { - - // Make sure the update render loop is active - if (self.paused) self.paused = NO; - - // Make sure we are updating the buffers on the correct gl context. - EAGLContext.currentContext = self.context; - - // Draw based on plot type - switch(_plotType) { - case EZPlotTypeBuffer: - [self _updateBufferPlotBufferWithAudioReceived:buffer - withBufferSize:bufferSize]; - break; - case EZPlotTypeRolling: - [self _updateRollingPlotBufferWithAudioReceived:buffer - withBufferSize:bufferSize]; - break; - default: - break; - } - -} - -#pragma mark - Buffer Updating By Type --(void)_updateBufferPlotBufferWithAudioReceived:(float*)buffer - withBufferSize:(UInt32)bufferSize { - - glBindBuffer(GL_ARRAY_BUFFER, _bufferPlotVBO); - - // If starting with a VBO of half of our max size make sure we initialize it to anticipate - // a filled graph (which needs 2 * bufferSize) to allocate its resources properly - if (!_hasBufferPlotData && _drawingType == EZAudioPlotGLDrawTypeLineStrip){ - EZAudioPlotGLPoint maxGraph[2*bufferSize]; - glBufferData(GL_ARRAY_BUFFER, sizeof(maxGraph), maxGraph, GL_STREAM_DRAW); - _hasBufferPlotData = YES; - } - - // Setup the buffer plot's graph size - _bufferPlotGraphSize = [EZAudioPlotGL graphSizeForDrawingType:_drawingType - withBufferSize:bufferSize]; - - // Setup the graph - EZAudioPlotGLPoint graph[_bufferPlotGraphSize]; - - // Fill in graph data - [EZAudioPlotGL fillGraph:graph - withGraphSize:_bufferPlotGraphSize - forDrawingType:_drawingType - withBuffer:buffer - withBufferSize:bufferSize - withGain:self.gain]; - - if (!_hasBufferPlotData){ - glBufferData( GL_ARRAY_BUFFER, sizeof(graph), graph, GL_STREAM_DRAW); - _hasBufferPlotData = YES; - } - else { - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(graph), graph); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - -} - --(void)_updateRollingPlotBufferWithAudioReceived:(float*)buffer - withBufferSize:(UInt32)bufferSize { - - glBindBuffer(GL_ARRAY_BUFFER, _rollingPlotVBO); - - - - // If starting with a VBO of half of our max size make sure we initialize it to anticipate - // a filled graph (which needs 2 * bufferSize) to allocate its resources properly - if (!_hasRollingPlotData){ - EZAudioPlotGLPoint maxGraph[2*EZAudioPlotDefaultMaxHistoryBufferLength]; - glBufferData( GL_ARRAY_BUFFER, sizeof(maxGraph), maxGraph, GL_STREAM_DRAW); - _hasRollingPlotData = YES; - } - - // Setup the plot - _rollingPlotGraphSize = [EZAudioPlotGL graphSizeForDrawingType:_drawingType - withBufferSize:_scrollHistoryLength]; - - // Fill the graph with data - EZAudioPlotGLPoint graph[_rollingPlotGraphSize]; - - // Update the scroll history datasource - [EZAudioUtilities updateScrollHistory:&_scrollHistory - withLength:_scrollHistoryLength - atIndex:&_scrollHistoryIndex - withBuffer:buffer - withBufferSize:bufferSize - isResolutionChanging:&_changingHistorySize]; - - // Fill in graph data - [EZAudioPlotGL fillGraph:graph - withGraphSize:_rollingPlotGraphSize - forDrawingType:_drawingType - withBuffer:_scrollHistory - withBufferSize:_scrollHistoryLength - withGain:self.gain]; - - // Update the drawing - if (!_hasRollingPlotData){ - glBufferData( GL_ARRAY_BUFFER, sizeof(graph) , graph, GL_STREAM_DRAW); - _hasRollingPlotData = YES; - } - else { - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(graph), graph); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - -} - --(void)_updateRollingPlotDisplay { - // Setup the plot - _rollingPlotGraphSize = [EZAudioPlotGL graphSizeForDrawingType:_drawingType - withBufferSize:_scrollHistoryLength]; - - // Fill the graph with data - EZAudioPlotGLPoint graph[_rollingPlotGraphSize]; - - // Fill in graph data - [EZAudioPlotGL fillGraph:graph - withGraphSize:_rollingPlotGraphSize - forDrawingType:_drawingType - withBuffer:_scrollHistory - withBufferSize:_scrollHistoryLength - withGain:self.gain]; - - // Update the drawing - if (_hasRollingPlotData){ - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(graph), graph); - } -} - -#pragma mark - Drawing --(void)glkView:(GLKView *)view drawInRect:(CGRect)rect { - - EAGLContext.currentContext = self.context; - - // Clear the context - glClear(GL_COLOR_BUFFER_BIT); - - if (_hasBufferPlotData || _hasRollingPlotData){ - // Prepare the effect for drawing - [self.baseEffect prepareToDraw]; - - // Plot either a buffer plot or a rolling plot - switch(_plotType) { - case EZPlotTypeBuffer: - [self _drawBufferPlotWithView:view - drawInRect:rect]; - break; - case EZPlotTypeRolling: - [self _drawRollingPlotWithView:view - drawInRect:rect]; - break; - default: - break; - - } - } -} - -#pragma mark - Private Drawing --(void)_drawBufferPlotWithView:(GLKView*)view drawInRect:(CGRect)rect { - if (_hasBufferPlotData){ - - glBindBuffer(GL_ARRAY_BUFFER, _bufferPlotVBO); - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(EZAudioPlotGLPoint), NULL); - - // Normal plot - - self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeXRotation(0); - glDrawArrays(_drawingType, 0, _bufferPlotGraphSize); - - - if (self.shouldMirror){ - // Mirrored plot - [self.baseEffect prepareToDraw]; - - self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeXRotation(M_PI); - glDrawArrays(_drawingType, 0, _bufferPlotGraphSize); - - } - - - glBindBuffer(GL_ARRAY_BUFFER,0); - - } -} - --(void)_drawRollingPlotWithView:(GLKView*)view drawInRect:(CGRect)rect { - if (_hasRollingPlotData){ - - // Normal plot - glBindBuffer(GL_ARRAY_BUFFER, _rollingPlotVBO); - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(EZAudioPlotGLPoint), NULL); - - // Normal plot - - self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeXRotation(0); - glDrawArrays(_drawingType, 0, _rollingPlotGraphSize); - - - if (self.shouldMirror){ - // Mirrored plot - [self.baseEffect prepareToDraw]; - - self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeXRotation(3.14159265359); - glDrawArrays(_drawingType, 0, _rollingPlotGraphSize); - - } - - glBindBuffer(GL_ARRAY_BUFFER,0); - - } -} - -#pragma mark - Setters --(void)setBackgroundColor:(UIColor *)backgroundColor { - // Set the background color - _backgroundColor = backgroundColor; - // Refresh background color (map to GL vector) - [self _refreshWithBackgroundColor:backgroundColor]; -} - --(void)setColor:(UIColor *)color { - // Set the color - _color = color; - // Refresh the color (map to GL vector) - [self _refreshWithColor:color]; -} - -#pragma mark - Private Setters --(void)_refreshWithBackgroundColor:(UIColor*)backgroundColor { - // Extract colors - CGFloat red; CGFloat green; CGFloat blue; CGFloat alpha; - [backgroundColor getRed:&red - green:&green - blue:&blue - alpha:&alpha]; - // Set them on the context - glClearColor((GLclampf)red,(GLclampf)green,(GLclampf)blue,(GLclampf)alpha); -} - --(void)_refreshWithColor:(UIColor*)color { - // Extract colors - CGFloat red; CGFloat green; CGFloat blue; CGFloat alpha; - [color getRed:&red - green:&green - blue:&blue - alpha:&alpha]; - // Set them on the base shader - self.baseEffect.constantColor = GLKVector4Make((GLclampf)red,(GLclampf)green,(GLclampf)blue,(GLclampf)alpha); -} - -@end - -#elif TARGET_OS_MAC - -#endif diff --git a/EZAudio/EZAudioUtilities.h b/EZAudio/EZAudioUtilities.h index d945d1dd..5aa7be79 100644 --- a/EZAudio/EZAudioUtilities.h +++ b/EZAudio/EZAudioUtilities.h @@ -25,8 +25,8 @@ #import #import +#import #import "TPCircularBuffer.h" - #if TARGET_OS_IPHONE #import #elif TARGET_OS_MAC @@ -67,6 +67,14 @@ typedef CGRect EZRect; typedef NSRect EZRect; #endif +//------------------------------------------------------------------------------ + +#if TARGET_OS_IPHONE +typedef UIColor EZColor; +#elif TARGET_OS_MAC +typedef NSColor EZColor; +#endif + //------------------------------------------------------------------------------ #pragma mark - EZAudioUtilities //------------------------------------------------------------------------------ @@ -404,6 +412,28 @@ typedef NSRect EZRect; */ + (NSString *)stringFromUInt32Code:(UInt32)code; +//------------------------------------------------------------------------------ +#pragma mark - Color Utility +//------------------------------------------------------------------------------ + +///----------------------------------------------------------- +/// @name Color Utility +///----------------------------------------------------------- + +/** + Helper function to get the color components from a CGColorRef in the RGBA colorspace. + @param color A CGColorRef that represents a color. + @param red A pointer to a CGFloat to hold the value of the red component. This value will be between 0 and 1. + @param green A pointer to a CGFloat to hold the value of the green component. This value will be between 0 and 1. + @param blue A pointer to a CGFloat to hold the value of the blue component. This value will be between 0 and 1. + @param alpha A pointer to a CGFloat to hold the value of the alpha component. This value will be between 0 and 1. + */ ++ (void)getColorComponentsFromCGColor:(CGColorRef)color + red:(CGFloat *)red + green:(CGFloat *)green + blue:(CGFloat *)blue + alpha:(CGFloat *)alpha; + //------------------------------------------------------------------------------ #pragma mark - Plot Utility //------------------------------------------------------------------------------ @@ -478,6 +508,14 @@ typedef NSRect EZRect; //------------------------------------------------------------------------------ +/** + Zeroes out a EZPlotHistoryInfo data structure without freeing the resources. + @param historyInfo A pointer to a EZPlotHistoryInfo data structure + */ ++ (void)clearHistoryInfo:(EZPlotHistoryInfo *)historyInfo; + +//------------------------------------------------------------------------------ + /** Frees a EZPlotHistoryInfo data structure @param historyInfo A pointer to a EZPlotHistoryInfo data structure diff --git a/EZAudio/EZAudioUtilities.m b/EZAudio/EZAudioUtilities.m index 3ac9c7a7..fd1b14ed 100644 --- a/EZAudio/EZAudioUtilities.m +++ b/EZAudio/EZAudioUtilities.m @@ -534,6 +534,31 @@ + (void)updateScrollHistory:(float **)scrollHistory } } +//------------------------------------------------------------------------------ +#pragma mark - Color Utility +//------------------------------------------------------------------------------ + +///----------------------------------------------------------- +/// @name Color Utility +///----------------------------------------------------------- + ++ (void)getColorComponentsFromCGColor:(CGColorRef)color + red:(CGFloat *)red + green:(CGFloat *)green + blue:(CGFloat *)blue + alpha:(CGFloat *)alpha +{ + size_t componentCount = CGColorGetNumberOfComponents(color); + if (componentCount == 4) + { + const CGFloat *components = CGColorGetComponents(color); + *red = components[0]; + *green = components[1]; + *blue = components[2]; + *alpha = components[3]; + } +} + //------------------------------------------------------------------------------ #pragma mark - TPCircularBuffer Utility //------------------------------------------------------------------------------ @@ -591,17 +616,25 @@ + (void)appendBuffer:(float *)buffer memmove(historyInfo->buffer, historyBuffer, bytes); if (targetBytes <= availableBytes) { - TPCircularBufferConsume(&historyInfo->circularBuffer, sizeof(src)); + TPCircularBufferConsume(&historyInfo->circularBuffer, availableBytes - targetBytes); } } //------------------------------------------------------------------------------ ++ (void)clearHistoryInfo:(EZPlotHistoryInfo *)historyInfo +{ + memset(historyInfo->buffer, 0, historyInfo->bufferSize * sizeof(float)); + TPCircularBufferClear(&historyInfo->circularBuffer); +} + +//------------------------------------------------------------------------------ + + (void)freeHistoryInfo:(EZPlotHistoryInfo *)historyInfo { free(historyInfo->buffer); free(historyInfo); - TPCircularBufferClear(&historyInfo->circularBuffer); + TPCircularBufferCleanup(&historyInfo->circularBuffer); } //------------------------------------------------------------------------------ diff --git a/EZAudio/EZPlot.h b/EZAudio/EZPlot.h index 8dee1dcb..0223a0ff 100644 --- a/EZAudio/EZPlot.h +++ b/EZAudio/EZPlot.h @@ -43,6 +43,7 @@ typedef NS_ENUM(NSInteger, EZPlotType) Plot that displays only the samples of the current buffer */ EZPlotTypeBuffer, + /** Plot that displays a rolling history of values using the RMS calculated for each incoming buffer */ diff --git a/EZAudioExamples/OSX/EZAudioCoreGraphicsWaveformExample/EZAudioCoreGraphicsWaveformExample.xcodeproj/project.pbxproj b/EZAudioExamples/OSX/EZAudioCoreGraphicsWaveformExample/EZAudioCoreGraphicsWaveformExample.xcodeproj/project.pbxproj index f634bbb9..c19dafed 100644 --- a/EZAudioExamples/OSX/EZAudioCoreGraphicsWaveformExample/EZAudioCoreGraphicsWaveformExample.xcodeproj/project.pbxproj +++ b/EZAudioExamples/OSX/EZAudioCoreGraphicsWaveformExample/EZAudioCoreGraphicsWaveformExample.xcodeproj/project.pbxproj @@ -30,7 +30,6 @@ 66755A371B3B790D0013E67E /* EZAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A1A1B3B790D0013E67E /* EZAudioPlayer.m */; }; 66755A381B3B790D0013E67E /* EZAudioPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A1C1B3B790D0013E67E /* EZAudioPlot.m */; }; 66755A391B3B790D0013E67E /* EZAudioPlotGL.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A1E1B3B790D0013E67E /* EZAudioPlotGL.m */; }; - 66755A3A1B3B790D0013E67E /* EZAudioPlotGLKViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A201B3B790D0013E67E /* EZAudioPlotGLKViewController.m */; }; 66755A3B1B3B790D0013E67E /* EZAudioUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A221B3B790D0013E67E /* EZAudioUtilities.m */; }; 66755A3C1B3B790D0013E67E /* EZMicrophone.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A241B3B790D0013E67E /* EZMicrophone.m */; }; 66755A3D1B3B790D0013E67E /* EZOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A261B3B790D0013E67E /* EZOutput.m */; }; @@ -89,8 +88,6 @@ 66755A1C1B3B790D0013E67E /* EZAudioPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlot.m; sourceTree = ""; }; 66755A1D1B3B790D0013E67E /* EZAudioPlotGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGL.h; sourceTree = ""; }; 66755A1E1B3B790D0013E67E /* EZAudioPlotGL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGL.m; sourceTree = ""; }; - 66755A1F1B3B790D0013E67E /* EZAudioPlotGLKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGLKViewController.h; sourceTree = ""; }; - 66755A201B3B790D0013E67E /* EZAudioPlotGLKViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGLKViewController.m; sourceTree = ""; }; 66755A211B3B790D0013E67E /* EZAudioUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioUtilities.h; sourceTree = ""; }; 66755A221B3B790D0013E67E /* EZAudioUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioUtilities.m; sourceTree = ""; }; 66755A231B3B790D0013E67E /* EZMicrophone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZMicrophone.h; sourceTree = ""; }; @@ -183,8 +180,6 @@ 66755A1C1B3B790D0013E67E /* EZAudioPlot.m */, 66755A1D1B3B790D0013E67E /* EZAudioPlotGL.h */, 66755A1E1B3B790D0013E67E /* EZAudioPlotGL.m */, - 66755A1F1B3B790D0013E67E /* EZAudioPlotGLKViewController.h */, - 66755A201B3B790D0013E67E /* EZAudioPlotGLKViewController.m */, 66755A211B3B790D0013E67E /* EZAudioUtilities.h */, 66755A221B3B790D0013E67E /* EZAudioUtilities.m */, 66755A231B3B790D0013E67E /* EZMicrophone.h */, @@ -425,7 +420,6 @@ 66755A371B3B790D0013E67E /* EZAudioPlayer.m in Sources */, 94056D88185B97E300EB94BA /* CoreGraphicsWaveformViewController.m in Sources */, 66755A391B3B790D0013E67E /* EZAudioPlotGL.m in Sources */, - 66755A3A1B3B790D0013E67E /* EZAudioPlotGLKViewController.m in Sources */, 66755A341B3B790D0013E67E /* EZAudioFile.m in Sources */, 66755A3D1B3B790D0013E67E /* EZOutput.m in Sources */, 66755A3B1B3B790D0013E67E /* EZAudioUtilities.m in Sources */, diff --git a/EZAudioExamples/OSX/EZAudioFFTExample/EZAudioFFTExample.xcodeproj/project.pbxproj b/EZAudioExamples/OSX/EZAudioFFTExample/EZAudioFFTExample.xcodeproj/project.pbxproj index 5d9770c6..03407908 100644 --- a/EZAudioExamples/OSX/EZAudioFFTExample/EZAudioFFTExample.xcodeproj/project.pbxproj +++ b/EZAudioExamples/OSX/EZAudioFFTExample/EZAudioFFTExample.xcodeproj/project.pbxproj @@ -16,7 +16,6 @@ 66755B8D1B3B79380013E67E /* EZAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B701B3B79380013E67E /* EZAudioPlayer.m */; }; 66755B8E1B3B79380013E67E /* EZAudioPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B721B3B79380013E67E /* EZAudioPlot.m */; }; 66755B8F1B3B79380013E67E /* EZAudioPlotGL.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B741B3B79380013E67E /* EZAudioPlotGL.m */; }; - 66755B901B3B79380013E67E /* EZAudioPlotGLKViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B761B3B79380013E67E /* EZAudioPlotGLKViewController.m */; }; 66755B911B3B79380013E67E /* EZAudioUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B781B3B79380013E67E /* EZAudioUtilities.m */; }; 66755B921B3B79380013E67E /* EZMicrophone.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B7A1B3B79380013E67E /* EZMicrophone.m */; }; 66755B931B3B79380013E67E /* EZOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B7C1B3B79380013E67E /* EZOutput.m */; }; @@ -76,8 +75,6 @@ 66755B721B3B79380013E67E /* EZAudioPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlot.m; sourceTree = ""; }; 66755B731B3B79380013E67E /* EZAudioPlotGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGL.h; sourceTree = ""; }; 66755B741B3B79380013E67E /* EZAudioPlotGL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGL.m; sourceTree = ""; }; - 66755B751B3B79380013E67E /* EZAudioPlotGLKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGLKViewController.h; sourceTree = ""; }; - 66755B761B3B79380013E67E /* EZAudioPlotGLKViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGLKViewController.m; sourceTree = ""; }; 66755B771B3B79380013E67E /* EZAudioUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioUtilities.h; sourceTree = ""; }; 66755B781B3B79380013E67E /* EZAudioUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioUtilities.m; sourceTree = ""; }; 66755B791B3B79380013E67E /* EZMicrophone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZMicrophone.h; sourceTree = ""; }; @@ -172,8 +169,6 @@ 66755B721B3B79380013E67E /* EZAudioPlot.m */, 66755B731B3B79380013E67E /* EZAudioPlotGL.h */, 66755B741B3B79380013E67E /* EZAudioPlotGL.m */, - 66755B751B3B79380013E67E /* EZAudioPlotGLKViewController.h */, - 66755B761B3B79380013E67E /* EZAudioPlotGLKViewController.m */, 66755B771B3B79380013E67E /* EZAudioUtilities.h */, 66755B781B3B79380013E67E /* EZAudioUtilities.m */, 66755B791B3B79380013E67E /* EZMicrophone.h */, @@ -398,7 +393,6 @@ 66755B8D1B3B79380013E67E /* EZAudioPlayer.m in Sources */, 9417A9D61872130200D9D37B /* FFTViewController.m in Sources */, 66755B8F1B3B79380013E67E /* EZAudioPlotGL.m in Sources */, - 66755B901B3B79380013E67E /* EZAudioPlotGLKViewController.m in Sources */, 66755B8A1B3B79380013E67E /* EZAudioFile.m in Sources */, 66755B931B3B79380013E67E /* EZOutput.m in Sources */, 66755B911B3B79380013E67E /* EZAudioUtilities.m in Sources */, diff --git a/EZAudioExamples/OSX/EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample.xcodeproj/project.pbxproj b/EZAudioExamples/OSX/EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample.xcodeproj/project.pbxproj index 6816d1ea..7d549521 100644 --- a/EZAudioExamples/OSX/EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample.xcodeproj/project.pbxproj +++ b/EZAudioExamples/OSX/EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample.xcodeproj/project.pbxproj @@ -16,7 +16,6 @@ 66755A701B3B79130013E67E /* EZAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A531B3B79130013E67E /* EZAudioPlayer.m */; }; 66755A711B3B79130013E67E /* EZAudioPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A551B3B79130013E67E /* EZAudioPlot.m */; }; 66755A721B3B79130013E67E /* EZAudioPlotGL.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A571B3B79130013E67E /* EZAudioPlotGL.m */; }; - 66755A731B3B79130013E67E /* EZAudioPlotGLKViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A591B3B79130013E67E /* EZAudioPlotGLKViewController.m */; }; 66755A741B3B79130013E67E /* EZAudioUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A5B1B3B79130013E67E /* EZAudioUtilities.m */; }; 66755A751B3B79130013E67E /* EZMicrophone.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A5D1B3B79130013E67E /* EZMicrophone.m */; }; 66755A761B3B79130013E67E /* EZOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A5F1B3B79130013E67E /* EZOutput.m */; }; @@ -75,8 +74,6 @@ 66755A551B3B79130013E67E /* EZAudioPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlot.m; sourceTree = ""; }; 66755A561B3B79130013E67E /* EZAudioPlotGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGL.h; sourceTree = ""; }; 66755A571B3B79130013E67E /* EZAudioPlotGL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGL.m; sourceTree = ""; }; - 66755A581B3B79130013E67E /* EZAudioPlotGLKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGLKViewController.h; sourceTree = ""; }; - 66755A591B3B79130013E67E /* EZAudioPlotGLKViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGLKViewController.m; sourceTree = ""; }; 66755A5A1B3B79130013E67E /* EZAudioUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioUtilities.h; sourceTree = ""; }; 66755A5B1B3B79130013E67E /* EZAudioUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioUtilities.m; sourceTree = ""; }; 66755A5C1B3B79130013E67E /* EZMicrophone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZMicrophone.h; sourceTree = ""; }; @@ -169,8 +166,6 @@ 66755A551B3B79130013E67E /* EZAudioPlot.m */, 66755A561B3B79130013E67E /* EZAudioPlotGL.h */, 66755A571B3B79130013E67E /* EZAudioPlotGL.m */, - 66755A581B3B79130013E67E /* EZAudioPlotGLKViewController.h */, - 66755A591B3B79130013E67E /* EZAudioPlotGLKViewController.m */, 66755A5A1B3B79130013E67E /* EZAudioUtilities.h */, 66755A5B1B3B79130013E67E /* EZAudioUtilities.m */, 66755A5C1B3B79130013E67E /* EZMicrophone.h */, @@ -394,7 +389,6 @@ 66755A701B3B79130013E67E /* EZAudioPlayer.m in Sources */, 94056DAA185BB0BC00EB94BA /* AppDelegate.m in Sources */, 66755A721B3B79130013E67E /* EZAudioPlotGL.m in Sources */, - 66755A731B3B79130013E67E /* EZAudioPlotGLKViewController.m in Sources */, 66755A6D1B3B79130013E67E /* EZAudioFile.m in Sources */, 66755A761B3B79130013E67E /* EZOutput.m in Sources */, 66755A741B3B79130013E67E /* EZAudioUtilities.m in Sources */, diff --git a/EZAudioExamples/OSX/EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample/OpenGLWaveformViewController.xib b/EZAudioExamples/OSX/EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample/OpenGLWaveformViewController.xib index fe6bab32..479f5f8e 100644 --- a/EZAudioExamples/OSX/EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample/OpenGLWaveformViewController.xib +++ b/EZAudioExamples/OSX/EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample/OpenGLWaveformViewController.xib @@ -1,8 +1,8 @@ - + - + diff --git a/EZAudioExamples/OSX/EZAudioPassThroughExample/EZAudioPassThroughExample.xcodeproj/project.pbxproj b/EZAudioExamples/OSX/EZAudioPassThroughExample/EZAudioPassThroughExample.xcodeproj/project.pbxproj index 96d6fb2f..6f32e344 100644 --- a/EZAudioExamples/OSX/EZAudioPassThroughExample/EZAudioPassThroughExample.xcodeproj/project.pbxproj +++ b/EZAudioExamples/OSX/EZAudioPassThroughExample/EZAudioPassThroughExample.xcodeproj/project.pbxproj @@ -16,7 +16,6 @@ 66755B541B3B79310013E67E /* EZAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B371B3B79310013E67E /* EZAudioPlayer.m */; }; 66755B551B3B79310013E67E /* EZAudioPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B391B3B79310013E67E /* EZAudioPlot.m */; }; 66755B561B3B79310013E67E /* EZAudioPlotGL.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B3B1B3B79310013E67E /* EZAudioPlotGL.m */; }; - 66755B571B3B79310013E67E /* EZAudioPlotGLKViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B3D1B3B79310013E67E /* EZAudioPlotGLKViewController.m */; }; 66755B581B3B79310013E67E /* EZAudioUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B3F1B3B79310013E67E /* EZAudioUtilities.m */; }; 66755B591B3B79310013E67E /* EZMicrophone.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B411B3B79310013E67E /* EZMicrophone.m */; }; 66755B5A1B3B79310013E67E /* EZOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755B431B3B79310013E67E /* EZOutput.m */; }; @@ -75,8 +74,6 @@ 66755B391B3B79310013E67E /* EZAudioPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlot.m; sourceTree = ""; }; 66755B3A1B3B79310013E67E /* EZAudioPlotGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGL.h; sourceTree = ""; }; 66755B3B1B3B79310013E67E /* EZAudioPlotGL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGL.m; sourceTree = ""; }; - 66755B3C1B3B79310013E67E /* EZAudioPlotGLKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGLKViewController.h; sourceTree = ""; }; - 66755B3D1B3B79310013E67E /* EZAudioPlotGLKViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGLKViewController.m; sourceTree = ""; }; 66755B3E1B3B79310013E67E /* EZAudioUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioUtilities.h; sourceTree = ""; }; 66755B3F1B3B79310013E67E /* EZAudioUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioUtilities.m; sourceTree = ""; }; 66755B401B3B79310013E67E /* EZMicrophone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZMicrophone.h; sourceTree = ""; }; @@ -169,8 +166,6 @@ 66755B391B3B79310013E67E /* EZAudioPlot.m */, 66755B3A1B3B79310013E67E /* EZAudioPlotGL.h */, 66755B3B1B3B79310013E67E /* EZAudioPlotGL.m */, - 66755B3C1B3B79310013E67E /* EZAudioPlotGLKViewController.h */, - 66755B3D1B3B79310013E67E /* EZAudioPlotGLKViewController.m */, 66755B3E1B3B79310013E67E /* EZAudioUtilities.h */, 66755B3F1B3B79310013E67E /* EZAudioUtilities.m */, 66755B401B3B79310013E67E /* EZMicrophone.h */, @@ -394,7 +389,6 @@ 66755B541B3B79310013E67E /* EZAudioPlayer.m in Sources */, 941D72211864C4D7007D52D8 /* PassThroughViewController.m in Sources */, 66755B561B3B79310013E67E /* EZAudioPlotGL.m in Sources */, - 66755B571B3B79310013E67E /* EZAudioPlotGLKViewController.m in Sources */, 66755B511B3B79310013E67E /* EZAudioFile.m in Sources */, 66755B5A1B3B79310013E67E /* EZOutput.m in Sources */, 66755B581B3B79310013E67E /* EZAudioUtilities.m in Sources */, diff --git a/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample.xcodeproj/project.pbxproj b/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample.xcodeproj/project.pbxproj index 8f51061d..1eda6f38 100644 --- a/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample.xcodeproj/project.pbxproj +++ b/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample.xcodeproj/project.pbxproj @@ -17,7 +17,6 @@ 66755AA91B3B791C0013E67E /* EZAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A8C1B3B791C0013E67E /* EZAudioPlayer.m */; }; 66755AAA1B3B791C0013E67E /* EZAudioPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A8E1B3B791C0013E67E /* EZAudioPlot.m */; }; 66755AAB1B3B791C0013E67E /* EZAudioPlotGL.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A901B3B791C0013E67E /* EZAudioPlotGL.m */; }; - 66755AAC1B3B791C0013E67E /* EZAudioPlotGLKViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A921B3B791C0013E67E /* EZAudioPlotGLKViewController.m */; }; 66755AAD1B3B791C0013E67E /* EZAudioUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A941B3B791C0013E67E /* EZAudioUtilities.m */; }; 66755AAE1B3B791C0013E67E /* EZMicrophone.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A961B3B791C0013E67E /* EZMicrophone.m */; }; 66755AAF1B3B791C0013E67E /* EZOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 66755A981B3B791C0013E67E /* EZOutput.m */; }; @@ -77,8 +76,6 @@ 66755A8E1B3B791C0013E67E /* EZAudioPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlot.m; sourceTree = ""; }; 66755A8F1B3B791C0013E67E /* EZAudioPlotGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGL.h; sourceTree = ""; }; 66755A901B3B791C0013E67E /* EZAudioPlotGL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGL.m; sourceTree = ""; }; - 66755A911B3B791C0013E67E /* EZAudioPlotGLKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGLKViewController.h; sourceTree = ""; }; - 66755A921B3B791C0013E67E /* EZAudioPlotGLKViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGLKViewController.m; sourceTree = ""; }; 66755A931B3B791C0013E67E /* EZAudioUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioUtilities.h; sourceTree = ""; }; 66755A941B3B791C0013E67E /* EZAudioUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioUtilities.m; sourceTree = ""; }; 66755A951B3B791C0013E67E /* EZMicrophone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZMicrophone.h; sourceTree = ""; }; @@ -171,8 +168,6 @@ 66755A8E1B3B791C0013E67E /* EZAudioPlot.m */, 66755A8F1B3B791C0013E67E /* EZAudioPlotGL.h */, 66755A901B3B791C0013E67E /* EZAudioPlotGL.m */, - 66755A911B3B791C0013E67E /* EZAudioPlotGLKViewController.h */, - 66755A921B3B791C0013E67E /* EZAudioPlotGLKViewController.m */, 66755A931B3B791C0013E67E /* EZAudioUtilities.h */, 66755A941B3B791C0013E67E /* EZAudioUtilities.m */, 66755A951B3B791C0013E67E /* EZMicrophone.h */, @@ -398,7 +393,6 @@ 66755AA91B3B791C0013E67E /* EZAudioPlayer.m in Sources */, 94056F31185BD86D00EB94BA /* PlayFileViewController.m in Sources */, 66755AAB1B3B791C0013E67E /* EZAudioPlotGL.m in Sources */, - 66755AAC1B3B791C0013E67E /* EZAudioPlotGLKViewController.m in Sources */, 66755AA61B3B791C0013E67E /* EZAudioFile.m in Sources */, 66755AAF1B3B791C0013E67E /* EZOutput.m in Sources */, 66755AAD1B3B791C0013E67E /* EZAudioUtilities.m in Sources */, diff --git a/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.h b/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.h index 19479311..562a6389 100644 --- a/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.h +++ b/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.h @@ -53,7 +53,7 @@ /** The CoreGraphics based audio plot */ -@property (nonatomic, weak) IBOutlet EZAudioPlot *audioPlot; +@property (nonatomic, weak) IBOutlet EZAudioPlotGL *audioPlot; #pragma mark - UI Extras /** diff --git a/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.m b/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.m index 435f769a..905e5f41 100644 --- a/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.m +++ b/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.m @@ -313,13 +313,12 @@ -(void)openFileWithFilePathURL:(NSURL*)filePathURL self.audioPlot.plotType = EZPlotTypeBuffer; self.audioPlot.shouldFill = YES; self.audioPlot.shouldMirror = YES; - [self.audioPlot clear]; // // Plot the whole waveform // __weak typeof (self) weakSelf = self; - [self.audioFile getWaveformDataWithNumberOfPoints:256 + [self.audioFile getWaveformDataWithNumberOfPoints:1024 completion:^(float **waveformData, int length) { diff --git a/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.xib b/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.xib index 1a9facb6..f9ddf239 100644 --- a/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.xib +++ b/EZAudioExamples/OSX/EZAudioPlayFileExample/EZAudioPlayFileExample/PlayFileViewController.xib @@ -1,8 +1,8 @@ - + - + @@ -29,7 +29,7 @@ - +