diff --git a/EZAudio/EZAudioPlot.h b/EZAudio/EZAudioPlot.h index f737ee9a..0e11e811 100644 --- a/EZAudio/EZAudioPlot.h +++ b/EZAudio/EZAudioPlot.h @@ -83,19 +83,20 @@ FOUNDATION_EXPORT UInt32 const EZAudioPlotDefaultMaxHistoryBufferLength; See EZPlot for full API methods and properties (colors, plot type, update function) */ +IB_DESIGNABLE @interface EZAudioPlot : EZPlot /** A BOOL that allows optimizing the audio plot's drawing for real-time displays. Since the update function may be updating the plot's data very quickly (over 60 frames per second) this property will throttle the drawing calls to be 60 frames per second (or whatever the screen rate is). Specifically, it disables implicit path change animations on the `waveformLayer` and sets up a display link to render 60 fps (audio updating the plot at 44.1 kHz causes it to re-render 86 fps - far greater than what is needed for a visual display). */ -@property (nonatomic, assign) BOOL shouldOptimizeForRealtimePlot; +@property (nonatomic, assign) IBInspectable BOOL shouldOptimizeForRealtimePlot; //------------------------------------------------------------------------------ /** A BOOL indicating whether the plot should center itself vertically. */ -@property (nonatomic, assign) BOOL shouldCenterYAxis; +@property (nonatomic, assign) IBInspectable BOOL shouldCenterYAxis; //------------------------------------------------------------------------------ @@ -192,7 +193,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:(const float *)data length:(int)length; //------------------------------------------------------------------------------ diff --git a/EZAudio/EZAudioPlot.m b/EZAudio/EZAudioPlot.m index a73d110d..86bb0cf9 100644 --- a/EZAudio/EZAudioPlot.m +++ b/EZAudio/EZAudioPlot.m @@ -215,9 +215,10 @@ - (void)setColor:(id)color - (void)setShouldOptimizeForRealtimePlot:(BOOL)shouldOptimizeForRealtimePlot { _shouldOptimizeForRealtimePlot = shouldOptimizeForRealtimePlot; - if (shouldOptimizeForRealtimePlot && !self.displayLink) + if (shouldOptimizeForRealtimePlot) { - self.displayLink = [EZAudioDisplayLink displayLinkWithDelegate:self]; + if (self.displayLink == nil) + self.displayLink = [EZAudioDisplayLink displayLinkWithDelegate:self]; [self.displayLink start]; } else @@ -325,7 +326,7 @@ - (CGPathRef)createPathWithPoints:(CGPoint *)points #pragma mark - Update //------------------------------------------------------------------------------ -- (void)updateBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize +- (void)updateBuffer:(const float *)buffer withBufferSize:(UInt32)bufferSize { // append the buffer to the history [EZAudioUtilities appendBufferRMS:buffer @@ -357,7 +358,7 @@ - (void)updateBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize //------------------------------------------------------------------------------ -- (void)setSampleData:(float *)data length:(int)length +- (void)setSampleData:(const float *)data length:(int)length { CGPoint *points = self.points; for (int i = 0; i < length; i++) diff --git a/EZAudio/EZAudioPlotGL.h b/EZAudio/EZAudioPlotGL.h index 70e5a007..88e71cc7 100644 --- a/EZAudio/EZAudioPlotGL.h +++ b/EZAudio/EZAudioPlotGL.h @@ -46,6 +46,7 @@ typedef struct /** 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. */ +IB_DESIGNABLE #if TARGET_OS_IPHONE @interface EZAudioPlotGL : GLKView #elif TARGET_OS_MAC diff --git a/EZAudio/EZAudioUtilities.h b/EZAudio/EZAudioUtilities.h index 94d4179e..3a2b64d5 100644 --- a/EZAudio/EZAudioUtilities.h +++ b/EZAudio/EZAudioUtilities.h @@ -366,7 +366,7 @@ typedef NSRect EZRect; @param bufferSize The size of the float buffer @return The root mean squared of the buffer */ -+ (float)RMS:(float*)buffer length:(int)bufferSize; ++ (float)RMS:(const float*)buffer length:(int)bufferSize; //------------------------------------------------------------------------------ @@ -501,7 +501,7 @@ typedef NSRect EZRect; @param bufferSize A UInt32 representing the length of the incoming audio buffer @param historyInfo A pointer to a EZPlotHistoryInfo structure to use for managing the history buffers */ -+ (void)appendBufferRMS:(float *)buffer ++ (void)appendBufferRMS:(const float *)buffer withBufferSize:(UInt32)bufferSize toHistoryInfo:(EZPlotHistoryInfo *)historyInfo; @@ -513,7 +513,7 @@ typedef NSRect EZRect; @param bufferSize A UInt32 representing the length of the incoming audio buffer @param historyInfo A pointer to a EZPlotHistoryInfo structure to use for managing the history buffers */ -+ (void)appendBuffer:(float *)buffer ++ (void)appendBuffer:(const float *)buffer withBufferSize:(UInt32)bufferSize toHistoryInfo:(EZPlotHistoryInfo *)historyInfo; diff --git a/EZAudio/EZAudioUtilities.m b/EZAudio/EZAudioUtilities.m index 82402dad..cacf9954 100644 --- a/EZAudio/EZAudioUtilities.m +++ b/EZAudio/EZAudioUtilities.m @@ -25,6 +25,8 @@ #import "EZAudioUtilities.h" +@import Accelerate; + static float const EZAudioUtilitiesFixedNoteA = 440.0f; static int const EZAudioUtilitiesFixedNoteAIndex = 9; static int const EZAudioUtilitiesFixedNoteAOctave = 4; @@ -473,12 +475,14 @@ + (float)MAP:(float)value //------------------------------------------------------------------------------ -+ (float)RMS:(float *)buffer length:(int)bufferSize ++ (float)RMS:(const float *)buffer length:(int)bufferSize { - float sum = 0.0; - for(int i = 0; i < bufferSize; i++) - sum += buffer[i] * buffer[i]; - return sqrtf( sum / bufferSize); + float *squared = calloc(bufferSize, sizeof(float)); + vDSP_vsq(buffer, 1, squared, 1, bufferSize); + float mean; + vDSP_meanv(squared, 1, &mean, bufferSize); + free(squared); + return sqrtf(mean); } //------------------------------------------------------------------------------ @@ -655,7 +659,7 @@ + (void)freeCircularBuffer:(TPCircularBuffer *)circularBuffer #pragma mark - EZPlotHistoryInfo Utility //------------------------------------------------------------------------------ -+ (void)appendBufferRMS:(float *)buffer ++ (void)appendBufferRMS:(const float *)buffer withBufferSize:(UInt32)bufferSize toHistoryInfo:(EZPlotHistoryInfo *)historyInfo { @@ -670,7 +674,7 @@ + (void)appendBufferRMS:(float *)buffer //------------------------------------------------------------------------------ -+ (void)appendBuffer:(float *)buffer ++ (void)appendBuffer:(const float *)buffer withBufferSize:(UInt32)bufferSize toHistoryInfo:(EZPlotHistoryInfo *)historyInfo { diff --git a/EZAudio/EZPlot.h b/EZAudio/EZPlot.h index bbde1f51..fe0ff7d8 100644 --- a/EZAudio/EZPlot.h +++ b/EZAudio/EZPlot.h @@ -59,9 +59,11 @@ typedef NS_ENUM(NSInteger, EZPlotType) */ #if TARGET_OS_IPHONE #import +IB_DESIGNABLE @interface EZPlot : UIView #elif TARGET_OS_MAC #import +IB_DESIGNABLE @interface EZPlot : NSView #endif @@ -98,7 +100,7 @@ typedef NS_ENUM(NSInteger, EZPlotType) /** The type of plot as specified by the `EZPlotType` enumeration (i.e. a buffer or rolling plot type). */ -@property (nonatomic, assign) IBInspectable EZPlotType plotType; +@property (nonatomic, assign) EZPlotType plotType; /** A boolean 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). @@ -137,6 +139,6 @@ typedef NS_ENUM(NSInteger, EZPlotType) @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; +-(void)updateBuffer:(const float *)buffer withBufferSize:(UInt32)bufferSize; @end diff --git a/EZAudio/EZPlot.m b/EZAudio/EZPlot.m index f8ac3b06..368f9b12 100644 --- a/EZAudio/EZPlot.m +++ b/EZAudio/EZPlot.m @@ -34,7 +34,7 @@ -(void)clear } #pragma mark - Get Samples --(void)updateBuffer:(float *)buffer +-(void)updateBuffer:(const float *)buffer withBufferSize:(UInt32)bufferSize { // Override in subclass