iOS_音頻波形圖Time、Wave實現,滑動設置播放進度

實現如下:

需要的數據源:

1、demo.mp3:音頻文件

2、samplePoints 數組:每秒音量(0-1)數組,根據音頻pcm採樣數據文件計算出來的(遍歷:每秒取一點,並記錄下最大值;最後按取值爲0至1,進行縮放。計算完的數存如數組)

(這裏不過多描述計算音量過程,以後有時間補...)

接下來是UI實現思路:

一、滑動視圖:

用了兩個TableView,上面的顯示時間和刻度,下面的顯示音量Lines。

爲了讓時間顯示在cell中間,所以設置結構如下圖:

time tableView 不可滑動,Wave tableView的 scrollViewDidScroll 回調裏設置time tableView的偏移量,使其保持一致。

二、數據處理

根據上面UI結構,所以第一個cell只有10s的數據,而後開始每個cell畫30s,直到最後一個有多少畫多少

// 因爲時間刻度顯示問題,爲了把label放在中間,所以第一個section左邊空出了10s,每個section畫30s的數據
// 刻度的每個間隔是2s,也就是需要可以畫2條線(kAudioPlayerLineSpacing:每條線的間距;每個刻度的就*2)
- (void)setPoints:(NSArray *)points {
  _points = points;
  NSMutableArray *tempArray = [NSMutableArray arrayWithArray:_points];
  self.pointArrays = [[NSMutableArray alloc] init];
  NSInteger index = 0;
  while (tempArray.count > 0) {
    if (index == 0) {
      if (tempArray.count >= 20) { // section0 數據
        [self.pointArrays addObject:[tempArray subarrayWithRange:NSMakeRange(0, 20)]];
        [tempArray removeObjectsInRange:NSMakeRange(0, 20)];
      }
    } else {
      if (tempArray.count >= 30) {
        [self.pointArrays addObject:[tempArray subarrayWithRange:NSMakeRange(0, 30)]];
        [tempArray removeObjectsInRange:NSMakeRange(0, 30)];
      } else {
        [self.pointArrays addObject:[tempArray copy]];
        [tempArray removeAllObjects];
      }
    }
    index++;
  }
  self.timeView.points = self.pointArrays;
  self.waveView.points = self.pointArrays;
}

 

三、播放器

AVPlayer:通過`addPeriodicTimeObserverForInterval:queue:usingBlock:`實現每秒回調,監聽播放進度

_player = [[AVPlayer alloc] initWithURL:self.playURL];
__weak typeof(self) weakSelf = self;
[_player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
  float currentTime = weakSelf.player.currentTime.value / weakSelf.player.currentTime.timescale;
  [weakSelf.waveView setContentOffset:CGPointMake(0, currentTime * kAudioPlayerLineSpacing)];
}];

kAudioPlayerLineSpacing:是每條Line之間的距離(可以隨意設置)

所以每個刻度的間距就是:kAudioPlayerLineSpacing * 2 (因爲個刻度表示2s)

四、滑動控制播放進度

1、首先去掉tableView的滑動慣性,否則滑動出界就很難控制

在 scrollViewWillBeginDecelerating: 開始減速方法裏設置  [scrollView setContentOffset: animated:NO]

(設置偏移爲手指滑動到的位置,並不需要滑動動畫,即可去掉滑動慣性)

2、然後滑動的時候需要暫停player,否則就會跟 TimeObserver 回調裏設置的偏移 衝突

在 scrollViewWillBeginDragging: 方法裏調用 [_player pause]

在 scrollViewDidEndDragging: 方法里根據 偏移 和 kAudioPlayerLineSpacing 計算出需要播放的時間(秒數),

- (void)didEndDraggingY:(CGFloat)y {
  // 拖拽結束後,根據偏移計算時間,設置播放進度
  CGFloat second = y / kAudioPlayerLineSpacing;
  [self.player seekToTime:CMTimeMakeWithSeconds(second, NSEC_PER_SEC)];
  if (self.playBtn.selected) { // 如果是播放狀態則開始播放
    [self.player play];
  }
}

Demo github 地址

僅本Demo下載地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章