IOS Succinctly - Audio

IOS ger flera alternativ för att arbeta med ljud. I det här kapitlet presenterar vi två ramar för att hantera olika typer av ljud. Audio Toolbox Framework innehåller ett C-bibliotek för att spela enkla systemljud och AVFoundation Framework ger ett objektorienterat gränssnitt för mellanliggande uppspelning och inspelning.

För båda ramarna är interaktion med ljudfiler konceptuellt densamma som att interagera med bilder. Du använder fortfarande NSBundle för att hitta filen på disken och sedan ladda innehållet med en annan klass dedikerad till tolkning av olika ljudformat.

Systemljud API definieras i Audio Toolbox Framework. Hela ramverket är skrivet i C istället för Objective-C, så vi arbetar med C-gränssnittet i en iOS-applikation för första halvan av detta kapitel. Detta ändrar hur vi ska interagera med centrala iOS-objekt, men låt inte det skrämma dig. Vi arbetar fortfarande med samma föremål och begrepp som vi har haft under hela denna bok. Till exempel istället för att använda mainBundle metod av NSBundle, vi ska använda en C-funktion som heter CFBundleGetMainBundle () för att komma åt applikationspaketet.


Skapa exempelapplikationen

Som i det föregående kapitlet är allt vi behöver är enkelt Enkel visningsprogram. Skapa ett nytt projekt och ring det Audio. Som vanligt använd edu.self för Företagsidentifierare och iPhone för enheter, och se till att båda Använd Storyboards och Använd automatisk referensräkning kryssrutorna är markerade.

Till skillnad från föregående kapitel behöver vi tillgång till två ljudramar, som inte ingår i mallen. För att lägga till en ny ram för projektet, klicka på projektikonen i Project Navigator och välj Audio mål. I Sammanfattning fliken, bläddra ner till Länkade ramar och bibliotek sektion.


Figur 113: De ramar som för närvarande ingår i vårt projekt

Det här är de kodbibliotek du har tillgång till från programkoden. Du måste lägga till Audio Toolbox Framework För att kunna arbeta med systemljud, klicka så på plustecknet i nedre vänstra hörnet. Den resulterande dialogrutan innehåller en lista över alla tillgängliga ramar och bibliotek. Börja skriva "audiotoolbox"I sökfältet för att hitta vår önskade ram.


Figur 114: Söka efter ljudverktygslådans ram

Klick AudioToolbox.framework och klicka sedan på Lägg till att inkludera det i projektet. Vi behöver också tillgång till AVFoundation Framework för AVAudioPlayer del av det här kapitlet, så upprepa processen för det här biblioteket också. Du borde se båda AVFoundation.framework och AudioToolbox.framework i Sammanfattning fliken innan du går vidare.


Figur 115: Alla nödvändiga bibliotek för vårt exempelprojekt

Vi är nu redo att börja arbeta med systemljud och AVAudioPlayer.


Systemet ljuder

Systemljud är utformade för att användas för enkla saker som varningar och UI-ljudeffekter (till exempel knapptryckningar). De är mycket lätta att använda, men handeln är att de inte ger många alternativ för att styra uppspelningen. Huvudbegränsningarna för systemljud API är som följer.

  • Ljud kan inte vara längre än trettio sekunder.
  • Du kan inte styra volymen av systemljud. De använder den aktuella enhetens volym. Bara ett ljud kan spela i taget.
  • Ljud kan inte slingas eller spelas efter en viss fördröjning.
  • De stöder endast .caf, .aif och .wav-filer.
  • Det går inte att konfigurera hur ljuden handlar om avbrott som inkommande samtal.

Om du upptäcker att dessa är för begränsande bör du använda AVAudioPlayer som diskuteras senare i det här kapitlet. Återigen är systemljud menade för specifika användningsfall. Om din applikation använder ljud för mer än UI-feedback och varningar, borde du antagligen använda AVAudioPlayer.

Åtkomst till ljudfilen

Resurspaketet för den här boken innehåller en kort ljudfil som heter blip.wav. Lägg till det här i applikationspaketet genom att dra det in i Project Navigator. Kom ihåg att systemljud använder ett C-gränssnitt, så vi kommer åt denna fil med en något annorlunda metod än tidigare kapitel. I ViewController.m, Byta viewDidLoad till det följande.

 - (void) viewDidLoad [super viewDidLoad]; CFURLRef blipURL = CFBundleCopyResourceURL (CFBundleGetMainBundle (), CFSTR ("blip"), CFSTR ("wav"), NULL); NSLog (@ "% @", blipURL); 

CFBundleGetMainBundle () är i huvudsak samma som [[NSBundle] mainBundle], förutom att det returnerar CoreFoundation-objektet som representerar applikationspaketet istället för Foundation Framework versionen. De Corefoundation Ramverket är ett lägre alternativ till Foundation Framework. Vi måste använda Corefoundation objekt här eftersom det är vad Audio Toolbox accepterar som argument.

De CFBundleCopyResourceURL () är CoreFoundation versionen av NSBundle s pathForResource: ofType: metod. Det returnerar helt enkelt sökvägen till den begärda resursen, och du borde se en välbekant filväg i NSLog () produktion.

När du väl har en sökväg till ljudfilen behöver du skapa ett ljudobjekt med hjälp av AudioServicesCreateSystemSoundID () fungera. Lägg till följande till viewDidLoad.

 AudioServicesCreateSystemSoundID (blipURL, & _blipOne);

Den här funktionen läser i ljudfilens innehåll, förvandlas till ett ljudobjekt som systemljud API vet hur man spelar och returnerar ett ID som du kan använda för att referera till det senare. AudioServicesCreateSystemSoundID () definieras av Audio Toolbox Framework, så du måste importera den till ViewController.m innan du kan använda den. Lägg till följande längst upp i filen.

 #importera 

Du lagrar ljudobjektets ID i en privat instansvariabel som heter _blip, så lägg till det i genomförandedeklarationen också.

 @implementation ViewController SystemSoundID _blip;  Spela upp ljuden Nästa, lägg programmässigt en knapp till scenen; den knappen spelar upp ljudet när det klickas. UIButton * aButton = [UIButton buttonWithType: UIButtonTypeRoundedRect]; [aButton setTitle: @ "Blip" forState: UIControlStateNormal]; [aButton addTarget: självåtgärd: @selector (playBlip :) forControlEvents: UIControlEventTouchUpInside]; aButton.frame = CGRectMake (100,0, 200,0, 120,0, 40,0); [[självvisning] addSubview: aButton]; För funktionen playBlip:, kommer vi att ringa funktionen AudioServicesPlaySystemSound () för att spela upp ljudet. Den accepterar ett enda argument, vilket borde vara SystemSoundID som refererar till det önskade ljudobjektet (t ex _blip). - (void) playBlip: (id) avsändare AudioServicesPlaySystemSound (_blip); 

När du sammanställer projektet ska du kunna klicka på knappen och höra ett kort ljud. Se till att högtalarna inte är avstängda.


Figur 116: En blinkande knapp

Om du klickar på knappen medan ljudet fortfarande spelas upp märker du att iOS avbryter det aktuella ljudet och börjar en ny. Återigen är systemljud avsedda för UI-ljudeffekter och andra enkla applikationer. För att spela flera ljud samtidigt måste du uppgradera till AVAudioPlayer diskuteras i följande avsnitt.

AudioServicesCreateSystemSoundID () och AudioServicesPlaySystemSound () är ganska mycket allt det finns för systemljud. Du kan också hitta AudioServicesPlayAlertSound () funktion användbar. Det fungerar precis som AudioServicesPlaySystemSound (), men det gör att telefonen vibrerar om användaren har den aktiverad.


AVAudioPlayer

AVFoundation Framework tillhandahåller ett högre gränssnitt för hantering av ljudavspelning. För spel, anpassade musikspelare och andra appar som kräver sofistikerade ljudkontroller, är detta det ramverk du ska använda. Några av dess möjligheter är:

  • Ingen begränsning av ljudets varaktighet.
  • Du kan spela flera ljud samtidigt.
  • Volymen kan styras för enskilda ljud.
  • Det är möjligt att slingra ett ljud eller utföra andra åtgärder när det slutar spela.
  • Du kan hoppa till godtyckliga punkter i ljudfilen.
  • Det är enkelt att konfigurera beteendet för hantering av avbrott genom ett delegatobjekt.

AVAudioPlayer är huvudklassen du ska använda från AVFoundation Ramverk. Det ger ett objektorienterat sätt att ställa in volymen, spela ljudet, stoppa ljudet, ange vilken del av ljudet som ska spelas och så vidare. Du kan tänka på det som ljudekvivalenten av UIImage / UIImageView.

Stödda filformat för AVAudioPlayer inkluderar .m4a, .aac, .wav, .mp3, .aif, .pcm, .caf och några andra. Se Apples Multimedia Programmeringsguide för en detaljerad diskussion av ljudfilformat.

Få åtkomst till sången

AVAudioPlayer är konstruerad för att användas med längre ljudfiler, som låtar, så vi har distribuerat en offentlig domän Billie Holiday melodi med den här boken. Dra god morgon-heartache.mp3 filen från resurspaketet till Project Navigator för att lägga till det i buntet.

Eftersom AVFoundation är ett mål-C-bibliotek, vi kan gå tillbaka till att använda NSBundle för tillgång till medie tillgångar. Gå vidare och ta bort allt i viewDidLoad, och ersätt det med följande.

 NSURL * soundFileURL = [[NSBundle mainBundle] URLForResource: @ "godmorgon-hjärtsorg" medExtension: @ "mp3"]; _player = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: nil];

De URLForResource: withExtension: Metoden är NSURL som motsvarar pathForResource: ofType:. Det här var ett bättre alternativ för att hitta ljudfilen eftersom du behövde ett NSURL-objekt för att initiera AVAudioPlayer. De initWithContentsOfURL: error: Metoden laddar innehållet i ljudfilen i AVAudioPlayer till exempel, mycket som NSString s stringWithContentsOfURL: kodning: error: metod.

AVAudioPlayer finns i AVFoundation-biblioteket, så var noga med att lägga till följande importdeklaration till ViewController.h. Vi behöver komma åt det från huvudfilen senare.

 #importera 

Dessutom behöver du några privata instansvariabler. Ändra implementeringsdeklarationen till följande.

 @implementation ViewController AVAudioPlayer * _player; UIButton * _playButton; UIButton * _stopButton;  Spela upp låten Nästa, lägg till en Play-knapp på scenen: _playButton = [UIButton buttonWithType: UIButtonTypeRoundedRect]; [_playButton setTitle: @ "Play" forState: UIControlStateNormal]; [_playButton addTarget: självåtgärd: @selector (playOrPause :) forControlEvents: UIControlEventTouchUpInside]; _playButton.frame = CGRectMake (100,0, 170,0, 120,0, 40,0); [[självvisning] addSubview: _playButton]; PlayOrPause: åtgärden ska implementeras så här: - (void) playOrPause: (id) avsändare om (_player.playing) [_player pause]; [_playButton setTitle: @ "Play" forState: UIControlStateNormal];  annat [_player play]; [_playButton setTitle: @ "Pause" forState: UIControlStateNormal]; 

Detta kontrollerar om sangen spelas redan via AVAudioPlayer s spelar egendom. Om det är, pausar det låten med pausmetoden och ändrar knappens titel i enlighet därmed. Om det inte är det startar låten genom att ringa uppspelningsmetoden. Du borde nu kunna kompilera appen och spela eller pausa en låt genom att trycka på knappen.

Låt oss ta ett steg längre genom att skapa en Sluta knapp. Lägg till följande i viewDidLoad metod.

 _stopButton = [UIButton buttonWithType: UIButtonTypeRoundedRect]; [_stopButton setTitle: @ "Stop" forState: UIControlStateNormal]; [_stopButton addTarget: självåtgärd: @selector (stop :) forControlEvents: UIControlEventTouchUpInside]; _stopButton.frame = CGRectMake (100,0, 230,0, 120,0, 40,0); [[självvisning] addSubview: _stopButton]; [/ sourcecode] Den motsvarande åtgärden kallar AVAudioPlayerens stoppmetod. Observera att den här metoden inte ändrar det aktuella uppspelningsläget. Det skiljer sig endast från pausmetoden genom att det förhindrar förladdning som utförs av spelmetoden. För att hoppa tillbaka till början av låten som du kan förvänta dig från en typisk Stop-knapp måste du manuellt ställa in AVAudioPlayer's currentTime-egenskap, så här:

[källkod] - (tomrum) stopp: (id) avsändare [_player stop]; _player.currentTime = 0; [_playButton setTitle: @ "Play" forState: UIControlStateNormal];

AVAudioPlayer Delegates

En annan fördel med att använda AVAudioPlayer över systemljudet API är att det låter dig hantera avbrott med hjälp av det bekanta delegatmönstret. De AVAudioPlayerDelegate protokollet definierar ett antal metoder som låter dig veta när vissa händelser uppstår utanför din ansökan.

När ett avbrott som ett inkommande telefonsamtal börjar, audioPlayerBeginInterruption: Metoden kallas delegatobjektet. Ljudet pausar automatiskt, men det här ger dig chansen att skriva någon annan anpassad hanteringskod du kan behöva. Likaså audioPlayerEndInterruption: withOptions: Metoden heter när avbrottet är över och du kan använda ljudspelaren igen. Systemet återupptar dock inte automatiskt uppspelningen. Du måste manuellt ringa upp spelmetoden om du vill att detta ska hända.

Förutom avbrottshantering kan delegatobjektet också låta dig veta när ljudet har slutat spela. Genom att definiera en audioPlayerDidFinishPlaying: framgång: Metod på delegatobjektet, du kan göra anpassat rengöringsarbete. Du kan till exempel använda detta för att återställa spellknappen och hoppa tillbaka till början av låten, som så.

 - (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) spelare framgångsrikt: (BOOL) flagga [självstopp: noll]; NSLog (@ "Song finished playing!"); 

För att denna kod ska fungera måste du visa visningsansvarig en formell delegat för AVAudioPlayer. I ViewController.h, ändra gränssnittsdeklarationen till följande.

 @interface ViewController: UIViewController 

Då måste visningsstyraren tilldela sig som delegatobjektet. I viewDidLoad metod av ViewController.m, lägg till följande rad.

 _player.delegate = self;

Nu om du låter låten spela igenom till slutet, Paus knappen återgår automatiskt till a Spela knappen, och klicka på den kommer att starta sången från början.


Figur 117: Vår enkla musikspelare

Sammanfattning

I det här kapitlet diskuterade vi två sätt att spela ljud från en iOS-enhet, systemljud och AVAudioPlayer. Den förstnämnda ska bara användas för korta, enkla ljud som inte behöver mycket anpassad konfiguration, och den senare ger dig större kontroll över ljudavspelningen.

För den genomsnittliga iOS-appen, den AVFoundation Framework ger en bra balans mellan ett användarvänligt API och finkorrigerad kontroll över dina ljud. Men kom ihåg att iOS också ger mer avancerade ljudfunktioner på låg nivå, som Audio Queue Services, samt ett API på högre nivå för att interagera med användarens befintliga iTunes-bibliotek via Media Player Framework. För specialiserade applikationer kan du till och med gå ner till OpenAL, vilket är ett plattformsbibliotek för att simulera en 3-D ljudmiljö.

Mycket arbete har gjorts för att göra IOS till en multimediavänlig plattform, så det finns ingen brist på alternativ för hantering av bilder, ljud och videor från din ansökan.


Slutsats

Detta kapitel omfattade grunderna för iOS-apputveckling. Vi började med att bygga ett enkelt användargränssnitt, vilket introducerade oss till de grundläggande designmönstren i IOS: modell-view-controller, delegera objekt och mål-action. Därefter dyker vi in ​​i flera scenprogram och lär oss hur iOS låter scener kommunicera med varandra och hanterar automatiskt övergångar från en scen till en annan. Därefter diskuterade vi iOS-filsystemet, programbuntar och nödvändiga resurser som appikoner, starta bilder och informationsegenskapslistan. Bundlar råkade också vara metoden för att lokalisera applikationer till flera regioner i iOS, så vi kunde serva översatta bilder och text utan problem till olika språktalare. Slutligen tog vi en kort titt på ljudfunktionerna genom att skapa en enkel UI-ljudeffekt och musikspelare.

Medan det fortfarande finns dussintals ramar som du kan utforska på egen hand hoppas jag att du känner dig bekväm att navigera i ett Xcode-projekt. Tillsammans med lite praktisk erfarenhet, bör du ta bort den här boken på hög nivå, hur gränssnitt skapas och läggs ut med hjälp av UIKit och storyboards och vilka klasser och bibliotek som ska användas för att hantera medietillgångar . Beväpnad med denna kunskap, bör du vara mer än redo att våga sig in i den verkliga världen av iOS app utveckling.

Denna lektion representerar ett kapitel från IOS Succinctly, en gratis eBook från laget på Syncfusion.