0

楽器のように、加速度計のx、y、z軸に基づいて3つの異なる音をトリガーするシンプルなアプリを作成しました。現時点では、加速度計の周波数更新間隔を低く設定しすぎると音が大きく鳴り、高く設定しすぎると反応が悪くなります。私はObjectiveCと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:          _________________________

このドラフトは、加速度計が更新されるのと同じ頻度でデバイスを振るユーザーを表しています。ただし、シェイクイベントは、2つの加速度計の更新のちょうど中間で発生します。その結果、シェイクイベントは登録されず、音も鳴りません。

以前のアプローチとは対照的に、加速度計の更新頻度が高いことを考慮してください。

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];
    //};

}

現在、各ディメンションが個別に評価されているため、1つのイベントだけで複数のサウンド再生がトリガーされる場合があることに注意してください。定数がによって導入されました#define ACC_THRESHOLD 0.5f。1次元の新しいサウンド再生は、前の再生が終了した後にのみ開始されます。

イベント処理のこれらの一般的な変更の後、シグナルフィルターを使用して最適化を開始できます。

さらに、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 に答える