0

我创建了一个简单的应用程序,它可以根据加速度计的 x、y、z 轴触发 3 种不同的声音,就像一个乐器一样。目前,如果我将加速度计的频率更新间隔设置得太低,它会播放太多声音,如果我将它设置得太高,它会响应不够。我是objective 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];
    };

}
4

1 回答 1

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。一个维度的新声音播放仅在之前的播放完成后开始。

在对事件处理进行这些一般更改之后,您可以使用信号过滤器开始优化。

此外,您可以使用 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);
}
于 2012-08-06T08:23:16.080 回答