0

おそらく最速の方法はSoundServicesを使うことだと思いました。非常に効率的ですが、重ならないように順番に音を鳴らす必要があります。そのため、コールバックメソッドを使用して、サウンドがいつ終了したかを確認しました。このサイクルでは、約0.3秒の遅延が発生します。これは非常に厳しいように聞こえますが、基本的にはプログラムの主軸です。

編集:を使用してみましたが、SoundServicesのコールバックメソッドと同じ状況になるため、AVAudioPlayerを使用せずにシーケンスでサウンドを再生することはできません。audioPlayerDidFinishPlaying

EDIT2:どういうわけか、再生したいサウンドの部分を大きなファイルに結合できれば、オーディオファイル全体を継続的に鳴らすことができると思います。

EDIT3:これでうまくいくと思いましたが、音声が重なっています:

waitTime = player.deviceCurrentTime;

    for (int k = 0; k < [colores count]; k++)
    {    
        player.currentTime = 0;
        [player playAtTime:waitTime];
        waitTime += player.duration;
    }

ありがとう

4

2 に答える 2

4

私はあなたのためにうまくいくと思うテクニックを試しました。サウンドを連結してオーディオファイルを作成します。次に、次のようなサウンドに関するメタデータを作成します。

@property (strong, nonatomic) NSMutableDictionary *soundData;
@synthesize soundData=_soundData;

- (void)viewDidLoad {
    [super viewDidLoad];

    _soundData = [NSMutableDictionary dictionary];
    NSArray *sound = [NSArray arrayWithObjects:[NSNumber numberWithFloat:5.0], [NSNumber numberWithFloat:0.5], nil];
    [self.soundData setValue:sound forKey:@"soundA"];
    sound = [NSArray arrayWithObjects:[NSNumber numberWithFloat:6.0], [NSNumber numberWithFloat:0.5], nil];
    [self.soundData setValue:sound forKey:@"soundB"];
    sound = [NSArray arrayWithObjects:[NSNumber numberWithFloat:7.0], [NSNumber numberWithFloat:0.5], nil];
    [self.soundData setValue:sound forKey:@"soundC"];
}

最初の数字はファイル内のサウンドのオフセットで、2番目の数字は持続時間です。次に、プレーヤーをこのようにプレイする準備をします...

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/audiofile.mp3", [[NSBundle mainBundle] resourcePath]]];

    NSError *error;
    audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    audioPlayer.numberOfLoops = -1;

    if (audioPlayer == nil)
        NSLog(@"%@", [error description]);              
    else {
        [audioPlayer prepareToPlay];
    }
}

次に、このような低レベルのサウンド再生方法を構築できます...

- (void)playSound:(NSString *)name withCompletion:(void (^)(void))completion {

    NSArray *sound = [self.soundData valueForKey:name];
    if (!sound) return;

    NSTimeInterval offset = [[sound objectAtIndex:0] floatValue];
    NSTimeInterval duration = [[sound objectAtIndex:1] floatValue];

    audioPlayer.currentTime = offset;
    [audioPlayer play];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
        [audioPlayer pause];
        completion();
    });
}

そして、このように素早く組み合わせて音を再生することができます...

- (IBAction)playAB:(id)sender {

    [self playSound:@"soundA" withCompletion:^{
        [self playSound:@"soundB" withCompletion:^{}];
    }];
}

ブロックをネストするのではなく、サウンド名のリストを取得して次々に再生する高レベルのメソッドを作成できます。これは次のようになります。

- (void)playSoundList:(NSArray *)soundNames withCompletion:(void (^)(void))completion {

    if (![soundNames count]) return completion();

    NSString *firstSound = [soundNames objectAtIndex:0];
    NSRange remainingRange = NSMakeRange(1, [soundNames count]-1);
    NSArray *remainingSounds = [soundNames subarrayWithRange:remainingRange];

    [self playSound:firstSound withCompletion:^{
        [self playSoundList:remainingSounds withCompletion:completion];
    }];
}

このように呼んでください...

NSArray *list = [NSArray arrayWithObjects:@"soundB", @"soundC", @"soundA", nil];
[self playSoundList:list withCompletion:^{ NSLog(@"done"); }];
于 2012-06-26T03:12:26.950 に答える
0

シーケンスを変更したり、音を省略したりすることもあると思います。(それ以外の場合は、3つのサウンドすべてを続けてアセットを作成し、それを再生します)。

そこにはもっと良いアイデアがあるかもしれませんが、物事を非常にタイトにするために、連結されたアセットを作成し、それをプリロードすることを検討できます-すべてのレイテンシーをその1つのロードに移動し、サウンドを変更するためにその周りを探します。

于 2012-06-19T00:05:28.207 に答える