如何使用avaudioplayer更有效地使iphone加速器触发声音?

时间:2012-07-31 09:30:31

标签: iphone avaudioplayer

我创建了一个简单的应用程序,可以根据仪器的x,y,z轴触发3种不同的声音。目前,如果我将间隔计的频率更新间隔设置得太低,它会播放很多声音,如果我将它设置得太高,它就不会有足够的响应。我是客观c和iphone开发的完全初学者,你可以通过代码告诉我们。

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional 

    UIAccelerometer* accelerometer = [UIAccelerometer sharedAccelerometer];
    [accelerometer setUpdateInterval: 25.0 / 10.0f];

    [[AVAudioSession sharedInstance] setDelegate: self];
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];
   [accelerometer setDelegate:self];

    UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
    AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);


    player.volume = 0.5;
    player.numberOfLoops = 0;
    player.delegate = self;
}

- (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)aceler 
{


    if (aceler.x > 0.5) {
        NSString *fileName = [NSString stringWithFormat:@"snare"];
        NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
        NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
        player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
        NSLog(@"acceleration.x = %+.6f greater", aceler.x);
        [player play];

    }
    else if (aceler.y > 0.5) {
        NSString *fileName = [NSString stringWithFormat:@"kick2"];
        NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
        NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
        player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
        NSLog(@"acceleration.y = %+.6f greater", aceler.y);
        [player play];

    }
    else if (aceler.z > 0.5) {
        NSString *fileName = [NSString stringWithFormat:@"hat"];
        NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
        NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
        player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
        NSLog(@"acceleration.y = %+.6f greater", aceler.z);
        [player play];
    }

    else  {
        [player stop];
    };

}

1 个答案:

答案 0 :(得分:1)

将加速度计的更新频率设置为较低值不会对此有所帮助。想象一下以下情况:

time:                          ------------------------>
real world acceleration event: ___X_____X_____X_____X___ 
acceleration update:           X_____X_____X_____X_____X
sound output started:          _________________________

此草稿表示用户以与更新加速度计相同的频率摇动设备。但震动事件恰好发生在两个加速度计更新之间。因此,震动事件将不会被记录,也不会播放声音。

与先前的方法相比,考虑高加速度计更新频率:

real world acceleration event: ___X_____X_____X_____X___ 
acceleration update:           XXXXXXXXXXXXXXXXXXXXXXXXX
sound output started:          ___X_____X_____X_____X___

基本上所有真实世界的事件都会在这种情况下产生声音。

修改后的代码如下:

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSLog(@"viewDidLoad");

    UIAccelerometer* accelerometer = [UIAccelerometer sharedAccelerometer];
    //[accelerometer setUpdateInterval: 25.0 / 10.0f];
    [accelerometer setUpdateInterval: 0.01f];

    [[AVAudioSession sharedInstance] setDelegate: self];
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];
    [accelerometer setDelegate:self];

    UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
    AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);


    //player.volume = 0.5;
    //player.numberOfLoops = 0;
    //player.delegate = self;

}

- (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)aceler 
{


    if ((aceler.x > ACC_THRESHOLD)&&((playerX == nil)||(playerX.isPlaying == NO))) {
        NSString *fileName = [NSString stringWithFormat:@"snare"];
        NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
        NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
        playerX = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
        NSLog(@"acceleration.x = %+.6f greater", aceler.x);
        playerX.delegate = self;
        [playerX play];

    }

    if ((aceler.y > ACC_THRESHOLD)&&((playerY == nil)||(playerY.isPlaying == NO))) {
        NSString *fileName = [NSString stringWithFormat:@"kick2"];
        NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
        NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
        playerY = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
        NSLog(@"acceleration.y = %+.6f greater", aceler.y);
        playerY.delegate = self;
        [playerY play];

    }

    if ((aceler.z > ACC_THRESHOLD)&&((playerZ== nil)||(playerZ.isPlaying == NO))) {
        NSString *fileName = [NSString stringWithFormat:@"hat"];
        NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
        NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
        playerZ = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
        NSLog(@"acceleration.z = %+.6f greater", aceler.z);
        playerZ.delegate = self;
        [playerZ play];
    }

    //else  {
    //    [player stop];
    //};

}

请注意,由于每个维度现在单独评估,因此只能通过一个事件触发多个声音播放。 #define ACC_THRESHOLD 0.5f引入了一个常量。在上一场比赛结束后,仅启动一个维度的新声音播放。

在事件处理的这些一般更改之后,您可以使用signal filter开始优化。

此外,您可以使用AVAudioPlayer的委托方法进行更详细的声音处理:

#pragma mark -
#pragma mark AVAudioPlayerDelegate methods

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{

    NSLog(@"audioPlayerDidFinishPlaying: %i", flag);

}

- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error{

    NSLog(@"audioPlayerDecodeErrorDidOccur: %@", error.description);
}