2009-03-07 26 views
5

Chcę odtwarzać wiele plików MP3, kolejno (jeden po drugim), używając AVAudioPlayer. Wypróbowałem to i zatrzymało się po odtworzeniu pierwszego pliku MP3. Jednakże, jeśli wejdę do debuggera, działa dobrze ... jakieś pomysły? Czytam gdzieś AVAudioPlayer odtwarza dźwięk w tle ... jak mam temu zapobiec? VasAVAudioPlayer - odtwarzanie wielu plików audio, kolejno

+0

To wymaga tagu iPhoneSDK, proszę –

+0

Pomoże to zobaczyć twój kod. Coś do obejrzenia - czy używasz jednego AVAudioPlayer na dźwięk? Gdy odtwarzasz pliki mp3, można grać tylko na raz, więc każde okrążenie może nie dawać oczekiwanych rezultatów. Nie wiem, dlaczego debugger miałby znaczenie, chyba że masz na myśli także symulator.Może symulator może jednocześnie odtwarzać wiele plików mp3 (ponieważ jest to wynik dekodowania mp3 w iPhonie). Cóż więcej informacji pomoże nam znaleźć rozwiązanie, więc zachęcamy do wysłania som kodu. –

Odpowiedz

3

Użyj jednego AVAudioPlayer na dźwięk.

1

Zaimplementowałem klasę do obsługi tego.

Aby użyć po prostu zrobić coś takiego:

[looper playAudioFiles:[NSArray arrayWithObjects: 
    @"add.mp3", 
    [NSString stringWithFormat:@"%d.mp3", numeral1.tag], 
    @"and.mp3", 
    [NSString stringWithFormat:@"%d.mp3", numeral2.tag], 
    nil 
]]; 

Looper.m

#import "Looper.h" 
@implementation Looper 
@synthesize player, fileNameQueue; 

- (id)initWithFileNameQueue:(NSArray*)queue { 
    if ((self = [super init])) { 
     self.fileNameQueue = queue; 
     index = 0; 
     [self play:index]; 
    } 
    return self; 
} 

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { 
    if (index < fileNameQueue.count) { 
     [self play:index]; 
    } else { 
     //reached end of queue 
    } 
} 

- (void)play:(int)i { 
    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:[fileNameQueue objectAtIndex:i] ofType:nil]] error:nil]; 
    [player release]; 
    player.delegate = self; 
    [player prepareToPlay]; 
    [player play];  
    index++; 
} 

- (void)stop { 
    if (self.player.playing) [player stop]; 
} 

- (void)dealloc { 
    self.fileNameQueue = nil; 
    self.player = nil;   
    [super dealloc]; 
} 

@end 

Looper.h

#import <Foundation/Foundation.h> 


@interface Looper : NSObject <AVAudioPlayerDelegate> { 
    AVAudioPlayer* player; 
    NSArray* fileNameQueue; 
    int index; 
} 

@property (nonatomic, retain) AVAudioPlayer* player; 
@property (nonatomic, retain) NSArray* fileNameQueue; 

- (id)initWithFileNameQueue:(NSArray*)queue; 
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag; 
- (void)play:(int)i; 
- (void)stop; 


@end 
3

dobrze, przykładowy kod nie działał z pudełko dla mnie. Taaaak, pomyślałem, że reagować ze stałym wersji:

Looper.h:

#import <Foundation/Foundation.h> 
#import <AVFoundation/AVFoundation.h> 

@interface Looper : NSObject <AVAudioPlayerDelegate> { 
    AVAudioPlayer* player; 
    NSArray* fileNameQueue; 
    int index; 
} 

@property (nonatomic, retain) AVAudioPlayer* player; 
@property (nonatomic, retain) NSArray* fileNameQueue; 

- (id)initWithFileNameQueue:(NSArray*)queue; 
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag; 
- (void)play:(int)i; 
- (void)stop; 

@end 

Looper.m:

#import "Looper.h" 
@implementation Looper 
@synthesize player, fileNameQueue; 

- (id)initWithFileNameQueue:(NSArray*)queue { 
    if ((self = [super init])) { 
     self.fileNameQueue = queue; 
     index = 0; 
     [self play:index]; 
    } 
    return self; 
} 

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { 
    if (index < fileNameQueue.count) { 
     [self play:index]; 
    } else { 
     //reached end of queue 
    } 
} 

- (void)play:(int)i { 
    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:[fileNameQueue objectAtIndex:i] ofType:nil]] error:nil]; 
    [player release]; 
    player.delegate = self; 
    [player prepareToPlay]; 
    [player play];  
    index++; 
} 

- (void)stop { 
    if (self.player.playing) [player stop]; 
} 

- (void)dealloc { 
    self.fileNameQueue = nil; 
    self.player = nil;   
    [super dealloc]; 
} 

@end 

A oto jak bym to nazwać:

Looper * looper = [[Looper alloc] initWithFileNameQueue:[NSArray arrayWithObjects: audioFile, audioFile2, nil ]]; 

Mam tylko nieco ponad rok doświadczenia w projektowaniu iPhone/iPad przy użyciu Objective-C, więc możesz odpowiedzieć dodatkowym cri ticism.

10

myślę AVQueuePlayer (podklasa AVPlayer) robi dokładnie to zadanie (odtwarzanie sekwencji pozycji) ponieważ iOS 4.1: http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVQueuePlayer_Class/Reference/Reference.html

ja nie spróbować sobie jednak ale na pewno spróbować do niego .

+0

Podczas gdy ta odpowiedź dotyczy alternatywy dla AVAudioPlayer, jest to o wiele bardziej eleganckie i "wbudowane" rozwiązanie niż użycie przykładów kodu Looper. *. Zmusza mnie to do nieustannego przydzielania nowej instancji AVAudioPlayer. Chociaż początkowo podjąłem takie podejście, skończyłem na podklasowaniu AVQueuePlayer, co dało mi funkcjonalność potrzebną do sekwencyjnego odtwarzania plików audio. Tak, tak, to jest poprawna odpowiedź. – manderson

1

Zaleca się zainicjowanie, przygotowanie elementów i kolejkowanie z wyprzedzeniem, na przykład metodą viewDidLoad.

Jeśli pracujesz na Swift,

override func viewDidLoad() { 
     super.viewDidLoad() 
     let item0 = AVPlayerItem.init(URL: NSBundle.mainBundle().URLForResource("url", withExtension: "wav")!) 

     let item1 = AVPlayerItem.init(URL: NSBundle.mainBundle().URLForResource("dog", withExtension: "aifc")!) 
     let item2 = AVPlayerItem.init(URL: NSBundle.mainBundle().URLForResource("GreatJob", withExtension: "wav")!) 


     let itemsToPlay:[AVPlayerItem] = [item0, item1, item2] 
     queuePlayer = AVQueuePlayer.init(items: itemsToPlay) 
    } 

i wtedy, gdy wystąpi zdarzenie,

queuePlayer.play() 

Zauważ, że w przypadku korzystania z kolejki, nadal może mieć pewne luki między dźwiękami.

można znaleźć wersję Objective-C w kwestii How to do something when AVQueuePlayer finishes the last playeritem

nadzieję, że to pomaga.

Powiązane problemy