DevTutorial #19 – AVPlayer: come riprodurre semplicemente file audio!

Con il firmware 2.2 Apple ha introdotto una classe davvero molto importante e potente, che permette di riprodurre una grande varietà di file audio all’interno delle proprie applicazioni. Tale classe è AVAudioPlayer e in questo tutorial vedremo come utilizzarla, creando un nostro rudimentale player audio.

Andremo a realizzare un’applicazione composta da due pulsanti, uno per avviare la riproduzione di un file audio, l’altro per fermare la riproduzione stessa. Il tutto è molto semplice, però potrà darvi gli strumenti necessari per utilizzare questa classe anche nelle vostre applicazioni! Buona programmazione allora!

1. Creiamo un nuovo progetto

Iniziamo come sempre creando un nuovo progetto di tipo “View-Based Application” e chiamiamolo “AVPlayerTutorial”.

Iniziamo definendo le due azioni che il nostro player musicale potrà eseguire, ovvero avviare e fermare la riproduzione di un brano. Apriamo, quindi, il file “AVPlayerTutorialViewController.h” e definiamo questi due metodi (righe 4 e 5):

@interface AVPlayerTutorialViewController : UIViewController  {
}

-(IBAction)avviaSuono;
-(IBAction)fermaSuono;

@end

Salviamo il file appena modificato e andiamo a creare la struttura grafica della nostra applicazione.

2. Definiamo l’interfaccia grafica

Facciamo doppio clic sul file “AVPlayerTutorialViewController.xib”, si aprirà Interface Builder in cui andremo a definire l’interfaccia grafica. Dobbiamo semplicemente inserire due bottoni, uno per avviare la riproduzione (un classico “Play”) e uno per fermarla (un “Pause”). Ecco come appare la mia applicazione (molto spartana oserei dire 😉 ):

Immagine 3

Ora dobbiamo collegare le due azioni che abbiamo definito in precedenza. Dal Pannello dei Documenti (“Tools -> Reveal in Document Window”) selezioniamo il “File’s Owner” e apriamo poi il “Connections Inspector”. Colleghiamo l’azione “avviaSuono” con il primo bottone, mentre “fermaSuono” con il secondo. Ecco come appare il pannello dopo aver eseguito i collegamenti:

Immagine 4

Abbiamo già terminato con questa parte, possiamo salvare tutto e chiudere Interface Builder.

3. Definiamo la classe

Torniamo al file “AVPlayerTutorialViewController.h” e completiamo la definizione della classe nella seguente maniera:

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

@interface AVPlayerTutorialViewController : UIViewController <AVAudioPlayerDelegate> {
	AVAudioPlayer *player;
}

-(IBAction)avviaSuono;
-(IBAction)fermaSuono;

@end

Abbiamo definito un componente “player” (riga 5), che sarà l’oggetto che si occuperà di leggere il nostro file e di riprodurlo, il tutto in grande semplicità, vista la potenza e la versatilità di questo componente.

Potete notare, inoltre, che abbiamo definito anche il delegato <AVAudioPlayerDelegate> (riga 4), che ci fornirà dei metodi molto importanti.

Prima di definirne le azioni, dobbiamo inserire nel nostro progetto il framework necessario. Espandete la sezione “Targets” nel progetto, e cliccate con il tasto destro su “AVPlayerTutorial”, selezionando poi “Get Info”. Si aprirà una nuova schermata, in cui dobbiamo andare nella sezione “General”. Nell’angolo in basso a sinistra noteremo un bottone “+”, clicchiamo e si aprirà
un elenco di tutti i framework disponibili:

Immagine 6

Selezioniamo “AVFoundation.framework”  e clicchiamo su “Add”. Avremo così aggiunto il framework necessario. Possiamo chiudere la schermata delle proprietà e tornare al codice.

Prima di definire le azioni, inserite un file audio nel vostro progetto, semplicemente trascinandolo in XCode. Questo sarà il file che il nostro player andrà a riprodurre.

4. Definiamo le azioni

Ora dobbiamo implementare le due azioni, “avviaSuono” e “fermaSuono” del nostro lettore. Iniziamo inserendo il seguente codice nel file “AVPlayerTutorialViewController.m”:

#import "AVPlayerTutorialViewController.h"

@implementation AVPlayerTutorialViewController

-(IBAction)avviaSuono{
	if(!player){//il file non è già avviato
		// Ricaviamo il percorso del file da riprodurre
		NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
		resourcePath = [resourcePath stringByAppendingString:@"/billie.mp3"];
		NSError* err;
		// Inizializziamo il player con il percorso del file
		player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:resourcePath] error:&err];

		if(err){//c'è stato un errore
			NSLog(@"Errore: %@", [err localizedDescription]);
		}
		else{//tutto ok, riproduciamo il file
			player.delegate = self;
			[player play];
		}

	}
	else{//il file è già in esecuzione oppure si riprende ad eseguirlo
		NSLog(@"Riavvio riproduzione!");
		[player stop];
		player = nil;
		[self avviaSuono];
	}
}

-(IBAction)fermaSuono{
	NSLog(@"Player fermato!");
	[player pause];
}

Analizziamo il codice appena scritto, iniziando dal metodo “avviaSuono” (riga 5). Troviamo subito un “if”, che controlla se il file non è già stato avviato: in tal caso esegue delle istruzioni che andremo poi ad esaminare, altimenti chiama il metodo play della classe AVAudioPlayer (che riproduce appunto il file audio).
All’interno del ciclo if, troviamo la dichiarazione e l’inizializzazione del file da riprodurre: con le prime due istruzioni ricaviamo il percorso del nostro file (che ovviamente deve essere inserito all’interno del nostro progetto), poi inizializziamo l’oggetto “player”. Prima di poterlo riprodurre, testiamo la variabile “err”, che ci riporta eventuali errori nella fase di inizializzazione (ad esempio relativo al file audio non trovato). Se non c’è stato nessun errore, viene riprodotto il file tramite l’istruzione [player play].

Il secondo metodo, “fermaSuono”, si occupa di mettere in pausa la riproduzione del file, richiamando il metodo “pause” sempre dell’oggetto “player”.

Ora non ci resta che implementare alcuni metodi richiesti dal delegato “AVAudioPlayerDelegate”. Ecco il codice da inserire:

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)aplayer successfully:(BOOL)flag {
	[player autorelease];
	player = nil;
}

- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error {
	NSLog(@"Errore nel decodificare: %@", [error localizedDescription] );
}

- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player {
	NSLog(@"Interrotto!");
}

- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player {
	NSLog(@"Fine dell'interruzione!");
}

Questi metodi servono per sapere quando la riproduzione viene interrotta oppure per comunicare eventuali errori nella decodifica del file.

Clicchiamo ora su “Build and Go!” e testiamo il nostro personalissimo player audio!!

Immagine 9

Se Avete Problemi, questo è il nostro file di progetto.

La guida è stata creata da Andrea Busi per “Bubi Devs”, prendendo spunto da questo guida: “Playing Audio Files using the iPhone SDK“. I meriti, quindi, sono del legittimo autore.

Ingegnere informatico e sviluppatore freelance, mi occupo da anni di sviluppo per iOS (ma non solo). Dal 2008 scrivo su questo piccolo blog (con qualche lunga pausa), in cui parlo di programmazione e di qualsiasi altra cosa che mi diverta.

6 comments On DevTutorial #19 – AVPlayer: come riprodurre semplicemente file audio!

  • Ciao, per prima cosa complimenti per i tutorial, in particolare questo. Si può seguire lo stesso tutorial anche per i video, in modo da implementarli dentro una view con il pulsante avvia e ferma?

  • Ciao Andrea ti faccio una domanda.
    In una mia applicazione ho implementato il classico player senza problemi ( quello con il logo di itunes )
    Ma se volessi usare il player “trasparente” ( quello che fa uscire la barra di controllo in basso che scompare ) come devo fare?
    Non riesco a trovare nulla in merito
    grazie

  • qualcuno sa se è possibile riprodurre un file esterno al dispositivo (tramite URL) in formato .pls (playlist di itunes)? vi prego sarebbe importantissimo!

  • Ciao,
    grazie per i tutorial intanto.
    Vorrei chiederti qual’è il miglior modo per utilizzare più suoni simultaneamente, ogn’uno collegato ad un pulsante (esempio uno strumento musicale.. un piano o una batteria).
    Dalla documentazione sembra sia Audio Unit in quanto è quello con minore latenza.
    Vorei poter abbinare diversi suoni a pulsanti in modo che l’utente clicca su un pulsante e questo inizia la riproduzione del suono (in loop) e poi premendo un altro pulsante si aggiunge al suono già in riproduzione quello nuovo.
    Spero di essermi spiegato (sono alle prime armi se non si era capito :))
    Grazie in anticipo.
    Vittorio

  • Ciao Andrea,
    ti espongo il mio problema sperando in un tuo preziosissimo aiuto.

    Ho diversi suoni che faccio partire con diversi bottoni con il medoto più o meno che hai descritto di sopra:
    Azione:
    – (IBAction)playC2_1:(id)sender{
    if (selector == 1) {
    [self playOnce:@”ap1_c2″]; }
    if (selector == 2) {
    [self playOnce:@”ep1_c2″]; }
    if (selector == 3) {
    [self playOnce:@”cv_c2″]; }
    if (selector == 4) {
    [self playOnce:@”ep2_c2″]; }
    if (selector == 5) {
    [self playOnce:@”ep3_c2″]; }
    if (selector == 6) {
    [self playOnce:@”ap2_c2″]; }
    }

    Metodo:
    – (void)playOnce:(NSString *)aSound {

    NSString *path = [[NSBundle mainBundle] pathForResource:aSound ofType:@”mp3″];
    NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: path];

    AVAudioPlayer *theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL error:NULL];
    [fileURL release];
    [path release];

    [theAudio setNumberOfLoops:0];
    [theAudio setVolume:1.0];
    theAudio.delegate = self;
    [theAudio play];
    }

    i problemi che ho sono 2: il primo che dopo circa 230 volte che premo i bottoni smette di suonare (sembra ci sia un limite al numero di player…) ed il secondo che vorrei poter fare in modo che il suono sia in play sono finchè tengo premuto il tasto (al rilascio del bottone si stoppasse insomma)…

    Se puoi aiutarmi te ne sarei grato.
    Vittorio.

    ps. il tuo libro mi sta dando un sacco di spunti interessantissimi, complimenti davvero!

Leave a Reply to Vittorio Cancel Reply

Your email address will not be published.

Site Footer