2009-03-07 14 views
5

Voglio riprodurre più file MP3, in sequenza (uno dopo l'altro), utilizzando AVAudioPlayer. L'ho provato e si ferma dopo aver suonato il primo MP3. Tuttavia, se vado in debugger, funziona bene ... qualche idea? Ho letto da qualche parte AVAudioPlayer riproduce l'audio in sottofondo .. come faccio a impedirgli di farlo? VasAVAudioPlayer - riproduzione di più file audio, in sequenza

+0

Questo richiede un tag iPhoneSDK per favore –

+0

Sarebbe utile vedere il tuo codice. Qualcosa da guardare - stai usando un AVAudioPlayer per suono? Quando si riproducono i file mp3, è possibile riprodurne solo uno alla volta, in modo che un eventuale over-Lap non possa dare risultati attesi. Non sono sicuro del motivo per cui il debugger farebbe la differenza, a meno che non si intenda anche nel simulatore.Forse il simulatore può riprodurre contemporaneamente più file mp3 (poiché ciò è il risultato dell'hardware di decodifica mp3 nell'iPhone). Bene più informazioni ci aiuteranno a trovare una soluzione, quindi sentitevi liberi di pubblicare il codice som. –

risposta

3

Utilizzare un AVAudioPlayer per suono.

1

Ho implementato una classe per gestirlo.

Per utilizzare solo fare qualcosa di simile:

[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

Bene, il vostro esempio di codice non ha funzionato fuori la scatola per me. Soooo, ho pensato di rispondere con una versione fissa:

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 

Ed ecco come la definirei:

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

Ho solo poco più di un anno di esperienza con lo sviluppo di iPhone/iPad utilizzando Objective-C quindi sentitevi liberi di rispondere con cri aggiuntivi smo.

10

penso che il AVQueuePlayer (sottoclasse di AVPlayer) fa esattamente questo lavoro (giocare una sequenza di elementi) dal iOS 4.1: http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVQueuePlayer_Class/Reference/Reference.html

non ho provato io stesso però, ma sarà sicuramente dare una prova di esso .

+0

Sebbene questa risposta risolva un'alternativa all'utilizzo di AVAudioPlayer, è una soluzione molto più elegante e "integrata" rispetto all'utilizzo degli esempi di codice Looper. * Sopra. Mi fa rabbrividire dover allocare continuamente una nuova istanza di AVAudioPlayer. Mentre inizialmente ho adottato questo approccio, ho finito con la sottoclasse di AVQueuePlayer che mi ha dato la funzionalità di cui avevo bisogno per la riproduzione sequenziale di file audio. Quindi sì, questa è la risposta corretta. – manderson

1

È consigliabile inizializzare, preparare gli articoli e fare la coda in anticipo, ad esempio nel metodo viewDidLoad.

Se si sta lavorando su 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) 
    } 

e poi, quando si verifica un evento,

queuePlayer.play() 

Si noti che se si utilizza la coda, è ancora potrebbe avere alcune lacune tra i suoni.

È possibile trovare la versione Objective-C per la questione How to do something when AVQueuePlayer finishes the last playeritem

Speranza che aiuta.

Problemi correlati