1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-03 09:57:46 +01:00
Telegram/Telegraph/TGAudioWaveformView.m
2016-02-25 01:03:51 +01:00

177 lines
5.8 KiB
Objective-C

#import "TGAudioWaveformView.h"
#import "TGAudioWaveform.h"
@interface TGAudioWaveformContentView : UIView
@property (nonatomic, strong) UIColor *color;
@property (nonatomic, strong) TGAudioWaveform *waveform;
@property (nonatomic) CGFloat peakHeight;
@end
@implementation TGAudioWaveformContentView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self != nil) {
self.contentMode = UIViewContentModeRedraw;
self.opaque = false;
self.backgroundColor = [UIColor clearColor];
}
return self;
}
- (void)setColor:(UIColor *)color {
_color = color;
[self setNeedsDisplay];
}
- (void)setWaveform:(TGAudioWaveform *)waveform {
if (TGObjectCompare(_waveform, waveform)) {
return;
}
_waveform = waveform;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)__unused rect {
CGFloat sampleWidth = 2.0f;
CGFloat halfSampleWidth = 1.0f;
CGFloat distance = 1.0f;
CGSize size = self.bounds.size;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, _color.CGColor);
if (_waveform == nil) {
CGContextFillRect(context, CGRectMake(halfSampleWidth, size.height - sampleWidth, size.width - sampleWidth, sampleWidth));
CGContextFillEllipseInRect(context, CGRectMake(0.0f, size.height - sampleWidth, sampleWidth, sampleWidth));
CGContextFillEllipseInRect(context, CGRectMake(size.width - sampleWidth, size.height - sampleWidth, sampleWidth, sampleWidth));
} else {
uint16_t *samples = (uint16_t *)_waveform.samples.bytes;
int maxReadSamples = (int)_waveform.samples.length / 2;
uint16_t maxSample = 0;
for (int i = 0; i < maxReadSamples; i++) {
//averageSample += ABS(samples[i]);
if (maxSample < samples[i]) {
maxSample = samples[i];
}
}
//averageSample /= maxReadSamples;
//CGFloat scale = averageSample * 1.9f;
CGFloat scale = maxSample;
if (scale < 1.0f) {
scale = 1.0f;
}
int numSamples = (int)CGFloor(self.frame.size.width / (sampleWidth + distance));
int16_t adjustedSamples[numSamples];
memset(adjustedSamples, 0, numSamples * 2);
for (int i = 0; i < maxReadSamples; i++) {
int index = i * numSamples / maxReadSamples;
int16_t sample = samples[i];
if (sample < 0) {
sample = -sample;
}
if (adjustedSamples[index] < sample) {
adjustedSamples[index] = sample;
}
}
for (int i = 0; i < numSamples; i++) {
CGFloat offset = i * (sampleWidth + distance);
int16_t peakSample = adjustedSamples[i];
CGFloat sampleHeight = peakSample * _peakHeight / scale;
if (ABS(sampleHeight) > _peakHeight) {
if (sampleHeight < 0) {
sampleHeight = _peakHeight;
} else {
sampleHeight = _peakHeight;
}
}
CGFloat adjustedSampleHeight = sampleHeight - sampleWidth;
if (adjustedSampleHeight <= sampleWidth + FLT_EPSILON) {
CGContextFillEllipseInRect(context, CGRectMake(offset, size.height - sampleWidth, sampleWidth, sampleWidth));
CGContextFillRect(context, CGRectMake(offset, size.height - halfSampleWidth, sampleWidth, halfSampleWidth));
} else {
CGRect adjustedRect = CGRectMake(offset, size.height - adjustedSampleHeight, sampleWidth, adjustedSampleHeight);
CGContextFillRect(context, adjustedRect);
CGContextFillEllipseInRect(context, CGRectMake(adjustedRect.origin.x, adjustedRect.origin.y - halfSampleWidth, sampleWidth, sampleWidth));
CGContextFillEllipseInRect(context, CGRectMake(adjustedRect.origin.x, adjustedRect.origin.y + adjustedRect.size.height - halfSampleWidth, sampleWidth, sampleWidth));
}
}
}
}
@end
@interface TGAudioWaveformView () {
TGAudioWaveformContentView *_backgroundView;
UIView *_foregroundClippingView;
TGAudioWaveformContentView *_foregroundView;
}
@end
@implementation TGAudioWaveformView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self != nil) {
_backgroundView = [[TGAudioWaveformContentView alloc] initWithFrame:self.bounds];
_foregroundView = [[TGAudioWaveformContentView alloc] initWithFrame:self.bounds];
_foregroundClippingView = [[UIView alloc] initWithFrame:self.bounds];
_foregroundClippingView.clipsToBounds = true;
[self addSubview:_backgroundView];
[_foregroundClippingView addSubview:_foregroundView];
[self addSubview:_foregroundClippingView];
_peakHeight = 12.0f;
_backgroundView.peakHeight = _peakHeight;
_foregroundView.peakHeight = _peakHeight;
}
return self;
}
- (void)setPeakHeight:(CGFloat)peakHeight {
_peakHeight = peakHeight;
_backgroundView.peakHeight = _peakHeight;
_foregroundView.peakHeight = _peakHeight;
}
- (UIView *)backgroundView {
return _backgroundView;
}
- (UIView *)foregroundView {
return _foregroundView;
}
- (UIView *)foregroundClippingView {
return _foregroundClippingView;
}
- (void)setForegroundColor:(UIColor *)foregroundColor backgroundColor:(UIColor *)backgroundColor {
_foregroundView.color = foregroundColor;
_backgroundView.color = backgroundColor;
}
- (void)setWaveform:(TGAudioWaveform *)waveform {
[_backgroundView setWaveform:waveform];
[_foregroundView setWaveform:waveform];
}
- (void)layoutSubviews {
}
@end