AVAudioRecorder 和 AVAudioPlayer

Posted

技术标签:

【中文标题】AVAudioRecorder 和 AVAudioPlayer【英文标题】:AVAudioRecorder and AVAudioPlayer 【发布时间】:2012-05-15 17:35:27 【问题描述】:

现在是第三天,我仍然无法播放。我一直在关注一些关于 AVAudioPlayer/AVAudioRecorder 的教程。使用 NSFileManager 看起来像是创建了一个文件,但播放时没有骰子。

RecorderViewController.m

//  RecorderViewController.m
//  AudioTest
//

#import "RecorderViewController.h"
#import <Foundation/Foundation.h>

@interface RecorderViewController ()

@end

@implementation RecorderViewController

@synthesize userIsRecording, filePath, activityView, recordButton, playButton, recorder;

/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        // Custom initialization
    
    return self;

*/

+ (CGRect)makeCGRectWithCenter:(CGPoint)center width:(float)width height:(float)height 

    return CGRectMake(center.x-width/2, center.y-height/2, width, height);


#pragma mark - Preparation
- (void)loadView 

    // RECORD BUTTON
    self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];

    self.recordButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.recordButton.frame = [[self class] makeCGRectWithCenter:CGPointMake(self.view.frame.size.width/2, 100) width:150 height:50];
    [self.recordButton setTitle:@"Record" forState:UIControlStateNormal];
    [self.recordButton addTarget:self action:@selector(recordPressed) forControlEvents:UIControlEventTouchUpInside];

    // PLAY BUTTON
    self.playButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.playButton.frame = [[self class] makeCGRectWithCenter:CGPointMake(self.view.frame.size.width/2, 200) width:150 height:50];
    [self.playButton setTitle:@"Play" forState:UIControlStateNormal];
    [self.playButton addTarget:self action:@selector(playPressed) forControlEvents:UIControlEventTouchUpInside];

    // RETURN BUTTON
    UIButton *returnButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    returnButton.frame = [[self class] makeCGRectWithCenter:CGPointMake(self.view.frame.size.width/2, 300) width:150 height:50];
    [returnButton setTitle:@"Return" forState:UIControlStateNormal];
    [returnButton addTarget:self action:@selector(dismissPressed:) forControlEvents:UIControlEventTouchUpInside];

    // ACTIVITY
    self.activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    self.activityView.frame = [[self class] makeCGRectWithCenter:CGPointMake(self.view.frame.size.width/2, 50) width:100 height:100];

    [self.view addSubview:self.recordButton];
    [self.view addSubview:self.playButton];
    [self.view addSubview:returnButton];
    [self.view addSubview:self.activityView];



- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view.
    NSLog(@"View did load");
    filePath = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"temp2.caf"]];

    // Setup Audiosession
    AVAudioSession *avSession = [AVAudioSession sharedInstance];
    [avSession setCategory:AVAudioSessionCategoryPlayAndRecord error:NULL];
    [avSession setActive:YES error: NULL];
    self.playButton.hidden = YES;



#pragma mark - Button Actions

- (void)dismissPressed:(id)sender

    if ([sender isKindOfClass:[UIButton class]]) 
        NSLog(@"Button class dismissed self");
    
    else 
        NSLog(@"Sender is:%@", [sender class]);
    
    [self dismissModalViewControllerAnimated:YES];


- (void)stopPressed 
    NSLog(@"Stop Pressed");
    [self.recordButton setTitle:@"Record" forState:UIControlStateNormal];
    self.userIsRecording = NO;
    self.playButton.hidden = NO;
    self.playButton.enabled = YES;
    [self.activityView stopAnimating];

    //


- (void)recordPressed

    if (self.userIsRecording) 
        [self stopPressed];
    
    else 
        self.userIsRecording = YES;
        self.playButton.enabled = NO;
        self.playButton.hidden = YES;
        [self.recordButton setTitle:@"Stop" forState:UIControlStateNormal];
        [self.activityView startAnimating];

        NSDictionary *recorderSettings = 
        [NSDictionary dictionaryWithObjectsAndKeys: 
            [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey, 
            [NSNumber numberWithInt:AVAudioQualityMin], AVEncoderAudioQualityKey,
            [NSNumber numberWithInt:16], AVEncoderBitRateKey,
            [NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
            [NSNumber numberWithFloat:8000.0], AVSampleRateKey,
            [NSNumber numberWithInt:8], AVLinearPCMBitDepthKey, nil];

        // Clean temp file
        NSFileManager * fm = [NSFileManager defaultManager];
        [fm removeItemAtPath:[self.filePath path] error:NULL];

        // Record
        NSError *error = [NSError alloc];
        self.recorder = [[AVAudioRecorder alloc] initWithURL:self.filePath settings:recorderSettings error:&error];

        [recorder setDelegate:self];
        [recorder prepareToRecord];
        if (![recorder record]) 
            NSLog(@"Recorder FAIL %@", error );
        
        else 
            NSLog(@"Recording at %@", [self.filePath absoluteString]);
        
    


- (void)playPressed

    NSFileManager * fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:[self.filePath path]]) 
        NSLog(@"File exists at:%@", [self.filePath path]);
        NSDictionary *attr = [fm attributesOfItemAtPath:[self.filePath path] error:NULL];
        NSLog(@"File attrs:%@", [attr description]);
    


    else 
        NSLog(@"ERROR: No file exists at:%@", [self.filePath path]);
    

    NSError *error = [[NSError alloc] init];

    AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:[[NSData alloc] initWithContentsOfURL:self.filePath] error: &error];

    [player setDelegate:self];

    if (error) 
        NSLog(@"Player initialization Error: %@", error);
    

    if (!player) 
        NSLog(@"Player is null!");
    
    [player prepareToPlay];
    if (![player play]) 
        NSLog(@"Play Error: %@", error);
    


#pragma mark - Lifecycle


- (void)viewDidUnload

    [super viewDidUnload];
    // Release any retained subviews of the main view.
    NSLog(@"View did unload");


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    return (interfaceOrientation == UIInterfaceOrientationPortrait);


@end

【问题讨论】:

我在您的- (void)playPressed 中看到您调用[player prepareToPlay],但我实际上并没有看到您告诉它播放。 prepareToPlay 只是让它准备好了。也许我在您的代码中遗漏了它,或者您没有发布所有内容。只是我的快速观察。 有点隐藏在逻辑中:if (![player play]) NSLog(@"Play Error: %@", error); 对不起,我对编程还是有点陌生​​,但是 if 语句不是说“如果玩家没有玩,则显示此错误消息”吗?在[player prepareToPlay] 之后,你仍然需要在里面说[player play]; 如果您是编程新手,请尝试示例代码SpeakHere 并根据您的需要进行修改。 您是否已将 AVFoundation 框架添加到您的项目并导入到您的 .h 文件中? #import &lt;AVFoundation/AVFoundation.h&gt; 【参考方案1】:
[player prepareToPlay];
if (![player play]) 
    NSLog(@"Play Error: %@", error);

“准备播放”后立即播放文件。缓冲区可能在那一刻还没有准备好。做这个测试。将AVAudioPlayer *player 声明为全局。从- (void)playPressed 中删除if (![player play])...。现在创建一个将在其他按钮按下时调用的新方法。按播放按钮,等待几秒钟,然后按另一个按钮。

【讨论】:

以上是关于AVAudioRecorder 和 AVAudioPlayer的主要内容,如果未能解决你的问题,请参考以下文章

使用 AVAudio 循环播放 mp3

致命错误:使用 AVAudio 展开可选值时意外发现 nil

在应用程序终止之前获取 AVAudio 录音 URL

首次加载时 AVAudio Player 出现延迟

使其他音频安静的音效 iOS AVAudio

iPhone App:不恢复 AVAudio Player 中的音频会话