2013-07-16 52 views
1

我正在開發一個語音備忘錄應用程序,用於記錄用戶的聲音並播放它們。如何從UISlider的自定義位置播放音頻?

錄音部分效果很好。錄製的文件成功存儲在&當用戶點擊一個保存的文件時,它剛剛開始播放文件。我使用UISlider來表示播放進度。現在,我禁用UISlideruserInteractionEnabled財產至NO。所以,我不允許用戶與UISlider欄互動。

我需要什麼是,我想要啓用此屬性YES,以便可以選擇所需的地方來播放音頻。爲此,我在滑塊代碼中添加了以下行。

[mySlider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged]; 

通過添加上面的代碼,我可以找到sliderChanged:方法中的滑塊位置。但是,我不知道如何從選定的位置啓動玩家。每個文件有不同的大小,所以他們的播放時間也不同。

是否有任何示例代碼可用?你需要幫助。

謝謝

回答

0

AVAudioPlayer具有您可以設置的currentTime屬性。請參閱AVAudioPlayer文檔。

3

加載聲音文件刷新滑塊的最小值和最大值的方法值

yourSlider.minValue = 0.0; 
yourSlider.maxValue = player.duration; 

sliderChanged:

player.currentTime = yourSlider.value; 
1

下面的代碼示例應該讓你開始。據此,滑塊可以用作進度指示器,並且用戶可以擦洗它以在指定位置開始回放。

/* SliderMoved被調用時滑塊值更改─或者當用戶磨砂它或當它被自動更新爲音頻重放的進展*/

-(void)sliderMoved:(id)sender 
{ 
    [self.playbackTimer invalidate]; 
    self.playbackTimer = nil; 
    NSInteger position = (NSInteger)self.slider.value * 60; // Assume the slider scale is in minutes- so convert to sec 
    if (self.isPlaying) 
    { 
     [self.audioPlayer pause]; 
    } 
    [self.audioPlayer setCurrentTime:position]; 
    if (self.isPlaying) 
    { 
     [self startOrResumePlaying]; 
    } 
    [self updateSlider]; 

} 

/* updateSlider是用於更新滑塊值的輔助函數*/

-(void)updateSlider 
{ 
    float total= self.audioPlayer.duration; 
    float f = (self.audioPlayer.currentTime) ; 
    self.slider.value = f/60.0; 


    self.progressLabel.text = [NSString stringWithFormat:@"%.2f",self.slider.value]; 

} 

/* startOrResumePlaying開始音頻播放,並初始化該自動遞增進度指示器的計時器每3秒*/

-(void)startOrResumePlaying 
{ 

    [self.audioPlayer prepareToPlay]; 
    [self.audioPlayer play]; 
    self.isPlaying = YES; 
    self.playbackTimer=[NSTimer scheduledTimerWithTimeInterval:3.0 
                 target:self 
                 selector:@selector(handleTimer:) 
                 userInfo:nil 
                 repeats:YES]; 
    [[NSRunLoop currentRunLoop] addTimer:self.playbackTimer forMode:NSDefaultRunLoopMode]; 

} 
1

我正在通過結合rajagp和伊戈爾Bidiniuc的上述答案,所以我要把它們都投票。

#import <AVFoundation/AVFoundation.h> 

@property (nonatomic, strong) IBOutlet UIButton *playButton; 
@property (nonatomic, strong) IBOutlet UISlider *slider; 
@property (nonatomic, strong) IBOutlet UILabel *timeLabel; 
@property (nonatomic, strong) AVAudioPlayer *audioPlayer; 
@property (nonatomic, strong) NSTimer *timer; 

- (IBAction)playPause:(id)sender; 
- (IBAction)sliderValueChanged:(id)sender; 

這裏是執行文件。

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 
    self.slider.continuous = YES; 
    NSError *error = nil; 
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error]; 
    if (error == nil) { 
     NSLog(@"audio session initialized successfully"); 
     [self PlayAudio:@"fileName"]; 
    } else { 
     NSLog(@"error initializing audio session: %@", [error description]); 
    } 
} 

- (void)PlayAudio:(NSString*)file { 
    NSError *error = nil; 
    NSString *soundPath =[[NSBundle mainBundle] pathForResource:file ofType:@"mp3"]; 
    NSURL *fileURL = [NSURL fileURLWithPath:soundPath]; 

    if ([self.audioPlayer isPlaying]) { 
     [self.audioPlayer pause]; 
     [self.timer invalidate]; 
    } 
    self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error]; 
    self.audioPlayer.delegate = self; 

    if (error == nil) { 
     NSLog(@"audio player initialized successfully"); 

     [self playPause:nil]; 

    } else { 
     NSLog(@"error initializing audio player: %@", [error description]); 
    } 
} 



- (void)viewWillDisappear:(BOOL)animated { 
    if ([self.audioPlayer isPlaying]) { 
     [self.audioPlayer pause]; 
     [self.timer invalidate]; 
    } 

    [super viewWillDisappear:animated]; 
} 

-(IBAction)playPause:(id)sender 
{ 
    if ([self.audioPlayer isPlaying]) { 
     [self.audioPlayer pause]; 
     self.playButton.imageView.image = [UIImage imageNamed:@"play"]; 
     [self.timer invalidate]; 

    } else { 
     [self.audioPlayer play]; 
     self.playButton.imageView.image = [UIImage imageNamed:@"pause"]; 

     self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateProgress) userInfo:nil repeats:YES]; 
    } 

} 

- (IBAction)sliderValueChanged:(id)sender { 

    [self.timer invalidate]; 
    self.timer = nil; 
    float position = self.slider.value; 

    if (self.audioPlayer.isPlaying) 
    { 
     [self playPause:nil]; 
    } 
    [self.audioPlayer setCurrentTime:position]; 
    if (self.audioPlayer.isPlaying) 
    { 
     [self playPause:nil]; 
    } 
    [self updateProgress]; 
} 

#pragma mark - Timer delegate 

-(void)updateProgress 
{ 
    NSInteger durationMinutes = [self.audioPlayer duration]/60; 
    NSInteger durationSeconds = [self.audioPlayer duration] - durationMinutes * 60; 

    NSInteger currentTimeMinutes = [self.audioPlayer currentTime]/60; 
    NSInteger currentTimeSeconds = [self.audioPlayer currentTime] - currentTimeMinutes * 60; 
    NSString *progressString = [NSString stringWithFormat:@"%d:%02d/%d:%02d", currentTimeMinutes, currentTimeSeconds, durationMinutes, durationSeconds]; 
    self.timeLabel.text = progressString; 

    self.slider.minimumValue = 0.0; 
    self.slider.maximumValue = [self.audioPlayer duration]; 

    [self.slider setValue:[self.audioPlayer currentTime] animated:YES]; 
} 

#pragma mark - AVAudioPlayer delegate methods 

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag 
{ 
    if (flag) { 
     self.playButton.imageView.image = [UIImage imageNamed:@"play"]; 
     [self.timer invalidate]; 
    } 
} 
4

在Swift中共享解決方案。

我能夠使用基於zeeran發佈的objective-c實現的滑塊來處理我的項目,它甚至可以不斷更新當前的時間,這是我之前沒有做的。我很高興。

所以我想分享快速實施,以防止任何人在那裏。

import UIKit 
import AVFoundation 
import Foundation 

class ActivityViewController: UIViewController, AVAudioPlayerDelegate { 
    /// The player & sound file object 
    var audioPlayer = AVAudioPlayer() 
    var activitySound = NSURL() 

    var updater : CADisplayLink! = nil // tracks the time into the track 
    var updater_running : Bool = false // did the updater start? 
    var playing : Bool = false //indicates if track was started playing 

    @IBOutlet var playButton: UIButton! 
    @IBOutlet var timeLabel: UILabel! // shows time and duration 
    @IBOutlet var audioSlider: UISlider! // slider object 

    @IBAction func pressedPlayButton(sender: AnyObject) { 
     if (playing == false) { 
      updater = CADisplayLink(target: self, selector: Selector("updateProgress")) 
      updater.frameInterval = 1 
      updater.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) 
      updater_running = true 
      audioPlayer.play() 
      playButton.selected = true // pause image is assigned to "selected" 
      playing = true 
      updateProgress() 
     } else { 
      updateProgress() // update track time 
      audioPlayer.pause() // then pause 
      playButton.selected = false // show play image (unselected button) 
      playing = false // note track has stopped playing 
     } 
    } 

    // action for when the slider is moved: set as 'valuechanged' for UISlider object 
    @IBAction func sliderMoved(sender: UISlider) { 
     // if the track was playing store true, so we can restart playing after changing the track position 
     var wasPlaying : Bool = false 
     if playing == true { 
      audioPlayer.pause() 
      wasPlaying = true 
     } 
     audioPlayer.currentTime = NSTimeInterval(round(audioSlider.value)) 
     updateProgress() 
     // starts playing track again it it had been playing 
     if (wasPlaying == true) { 
      audioPlayer.play() 
      wasPlaying == false 
     } 
    } 

    // Timer delegate method that updates current time display in minutes 
    func updateProgress() { 
     let total = Float(audioPlayer.duration/60) 
     let current_time = Float(audioPlayer.currentTime/60) 
     audioSlider.minimumValue = 0.0 
     audioSlider.maximumValue = Float(audioPlayer.duration) 
     audioSlider.setValue(Float(audioPlayer.currentTime), animated: true) 
     timeLabel.text = NSString(format: "%.2f/%.2f", current_time, total) as String 
    } 

    //- AVAudioPlayer delegate method - resets things when track finishe playing 
    func PlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) { 
     if flag { 
      playButton.selected = false 
      playing = false 
      audioPlayer.currentTime = 0.0 
      updateProgress() 
      updater.invalidate() 
     } 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // configure AVAudioPlayer as audioPlayer object 
     let file = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("file1", ofType: "mp3")!)! 
     audioPlayer = audioPlayer(contentsOfURL: file, error: nil) 
     audioPlayer.delegate = self 

     audioSlider.continuous = false 
    } 

    // method makes sure updater gets stopped when leaving view controller, because otherwise it will run indefinitely in background 
    override func viewWillDisappear(animated: Bool) { 
     if playing == true { 
      audioPlayer.stop() 
     } 
     updater.invalidate() 
     updater_running = false 
     super.viewWillDisappear(animated) 
    } 
}