IOS Succinctly - Lyd

IOS gir flere alternativer for å jobbe med lyd. I dette kapitlet presenterer vi to rammer for å håndtere ulike typer lyder. Audio Toolbox Framework inneholder et C-bibliotek for å spille enkle systemlyder, og AVFoundation Framework gir et objektorientert grensesnitt for avspilling og opptak på mellomnivå.

For begge rammebetingelser er samspill med lydfiler konseptuelt det samme som samspill med bilder. Du bruker fortsatt NSBundle til å finne filen på disken, og deretter laste innholdet med en annen klasse dedikert til å tolke de forskjellige lydformatene.

Systemlyd API er definert i Audio Toolbox Framework. Hele rammen er skrevet i C i stedet for Objective-C, så vi skal jobbe med C-grensesnittet i et iOS-program for første halvdel av dette kapittelet. Dette endrer hvordan vi samhandler med kjerne iOS-objekter, men ikke la det skremme deg. Vi arbeider fortsatt med de samme objektene og konseptene som vi har vært gjennom hele denne boken. For eksempel, i stedet for å bruke mainBundle Metode av NSBundle, vi skal bruke en C-funksjon kalt CFBundleGetMainBundle () for å få tilgang til applikasjonspakken.


Opprette eksempelapplikasjonen

Som i det forrige kapitlet, er alt vi trenger, en enkel Enkeltvisningsprogram. Opprett et nytt prosjekt og ring det Audio. Som vanlig, bruk edu.self for Bedriftsidentifikator og iPhone for enheter, og sørg for at begge Bruk Storyboards og Bruk automatisk referansetelling avkrysningsbokser er valgt.

I motsetning til det forrige kapittelet må vi få tilgang til to lydrammer, som ikke er inkludert i malen. For å legge til et nytt rammeverk for prosjektet, klikk på prosjektikonet i Prosjektnavigator og velg Audio mål. I Sammendrag fanen, bla ned til Sammenhengende rammer og biblioteker seksjon.


Figur 113: Rammer som nå er inkludert i vårt prosjekt

Dette er kodebibliotekene du har tilgang til fra programkoden. Du må legge til Audio Toolbox Framework For å kunne arbeide med systemlyder, klikk så plussegnet i nederste venstre hjørne. Den resulterende dialogen inneholder en liste over alle tilgjengelige rammer og biblioteker. Begynn å skrive "audiotoolbox"I søkefeltet for å finne ønsket rammeverk.


Figur 114: Søker etter Audio Toolbox Framework

Klikk AudioToolbox.framework og klikk deretter Legg til å inkludere det i prosjektet. Vi trenger også tilgang til AVFoundation Framework for AVAudioPlayer del av dette kapittelet, så gjenta prosessen for dette biblioteket også. Du bør se begge AVFoundation.framework og AudioToolbox.framework i Sammendrag fanen før du går videre.


Figur 115: Alle nødvendige biblioteker for vårt eksempelprosjekt

Vi er nå klar til å begynne å jobbe med systemlyder og AVAudioPlayer.


Systemet lyder

Systemlyder er laget for å brukes til enkle ting som varsler og UI-lydeffekter (for eksempel knappeklikk). De er veldig enkle å bruke, men handelen er at de ikke gir mange muligheter for å kontrollere avspilling. Hovedbegrensningene til systemlyd-API er som følger.

  • Lyder kan ikke være lenger enn tretti sekunder.
  • Du kan ikke kontrollere volumet av systemlyder. De bruker nåværende enhetens volum. Bare én lyd kan spille om gangen.
  • Lyder kan ikke sløyfes eller spilles etter en viss forsinkelse.
  • De støtter bare .caf, .aif og .wav-filer.
  • Det er ikke mulig å konfigurere hvordan lyder avhenger av forstyrrelser som innkommende anrop.

Hvis du finner at disse er for begrensende, bør du bruke AVAudioPlayer diskutert senere i dette kapittelet. Igjen, systemlyder er ment for spesielle brukstilfeller. Hvis programmet bruker lyd for mer enn UI-tilbakemeldinger og varsler, bør du sannsynligvis bruke AVAudioPlayer.

Tilgang til lydfilen

Resurspakken for denne boken inneholder en kort lydfil som heter blip.wav. Legg dette til applikasjonspakken ved å dra den inn i Prosjektnavigator. Husk at systemlyder bruker et C-grensesnitt, så vi får tilgang til denne filen ved hjelp av en litt annen metode enn tidligere kapitler. I ViewController.m, endring viewDidLoad til følgende.

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

CFBundleGetMainBundle () er i det vesentlige det samme som [[NSBundle] mainBundle], bortsett fra at det returnerer CoreFoundation-objektet som representerer applikasjonspakken i stedet for Foundation Framework-versjonen. De Corefoundation Framework er et lavere nivå alternativ til Stiftelsesramme. Vi må bruke Corefoundation Objekter her fordi det er hva Audio Toolbox aksepterer som argumenter.

De CFBundleCopyResourceURL () er CoreFoundation versjonen av NSBundle s pathForResource: ofType: metode. Den returnerer bare banen til den forespurte ressursen, og du bør se en kjent filbane i NSLog () produksjon.

Når du har en bane til lydfilen, må du opprette et lydobjekt ved hjelp av AudioServicesCreateSystemSoundID () funksjon. Legg til følgende til viewDidLoad.

 AudioServicesCreateSystemSoundID (blipURL, & _blipOne);

Denne funksjonen leser i innholdet i lydfilen, gjør det til et lydobjekt som systemlyd API vet hvordan du spiller, og returnerer en ID du kan bruke til å referere den senere. AudioServicesCreateSystemSoundID () er definert av Audio Toolbox Framework, så du må importere den til ViewController.m før du kan bruke den. Legg følgende til toppen av filen.

 #importere 

Du lagrer lydobjektets ID i en privat instansvariabel som kalles _blip, så legg det til implementeringsdeklarasjonen også.

 @implementation ViewController SystemSoundID _blip;  Spill av lydene Neste legger programmatisk en knapp til scenen; den knappen vil spille lyden når den klikkes. UIButton * aButton = [UIButton buttonWithType: UIButtonTypeRoundedRect]; [aButton setTitle: @ "Blip" forState: UIControlStateNormal]; [aButton addTarget: selvhandling: @selector (playBlip :) forControlEvents: UIControlEventTouchUpInside]; aButton.frame = CGRectMake (100,0, 200,0, 120,0, 40,0); [[selvvisning] addSubview: aButton]; For actionspillet PlayBlip:, kaller vi funksjonen AudioServicesPlaySystemSound () for å spille av lyden. Den aksepterer et enkelt argument, som skal være SystemSoundID som refererer til ønsket lydobjekt (for eksempel _blip). - (void) playBlip: (id) avsender AudioServicesPlaySystemSound (_blip); 

Når du kompilerer prosjektet, bør du kunne klikke på knappen og høre en kort lyd. Pass på at høyttalerne ikke er dempet.


Figur 116: En blinkende knapp

Hvis du klikker på knappen mens lyden fortsatt spiller, vil du legge merke til at iOS avbryter gjeldende lyd og starter en ny. Igjen er systemlyder beregnet for UI-lydeffekter og andre enkle applikasjoner. For å spille flere lyder samtidig, må du oppgradere til AVAudioPlayer diskutert i det følgende avsnittet.

AudioServicesCreateSystemSoundID () og AudioServicesPlaySystemSound () er ganske mye alt det er til systemlyder. Du kan også finne AudioServicesPlayAlertSound () funksjon nyttig. Det fungerer akkurat som AudioServicesPlaySystemSound (), men det gjør telefonen vibrere hvis brukeren har den aktivert.


AVAudioPlayer

AVFoundation Framework gir et grensesnitt på høyere nivå for å administrere lydavspilling. For spill, tilpassede musikkspillere og andre programmer som krever sofistikert lydkontroll, er dette rammen du bør bruke. Noen av dens evner inkluderer:

  • Ingen begrensning på lydvarighet.
  • Du kan spille flere lyder samtidig.
  • Volumet kan styres for individuelle lyder.
  • Det er mulig å slå en lyd eller utføre andre handlinger når det er ferdig med å spille.
  • Du kan hoppe til vilkårlig poeng i lydfilen.
  • Det er enkelt å konfigurere atferd for å håndtere forstyrrelser gjennom et delegatobjekt.

AVAudioPlayer er hovedklassen du vil bruke fra Foundation- Framework. Den gir en objektorientert måte å stille volum på, spille lyden, stoppe lyden, angi hvilken del av lyden som skal spilles, og så videre. Du kan tenke på det som lydkvivalenten til UIImage / UIImageView.

Støttede filformater for AVAudioPlayer inkluderer .m4a, .aac, .wav, .mp3, .aif, .pcm, .caf, og noen andre. Se Apples multimedieprogrammeringsveiledning for en detaljert diskusjon av lydfilformater.

Tilgang til sangen

AVAudioPlayer er designet for å brukes med lengre lydfiler, som sanger, så vi har distribuert en offentlig domene Billie Holiday melodi med denne boken. Dra god morgen-heartache.mp3 fil fra ressurspakken til Prosjektnavigator å legge det til bunten.

Siden Foundation- er et mål-C-bibliotek, kan vi gå tilbake til å bruke NSBundle for å få tilgang til medieverdier. Gå videre og fjern alt i viewDidLoad, og erstatt den med følgende.

 NSURL * soundFileURL = [[NSBundle mainBundle] URLForResource: @ "godmorgen-heartache" medExtension: @ "mp3"]; _player = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL feil: null];

De URLForResource: withExtension: Metoden er NSURL tilsvarende pathForResource: ofType:. Dette var et bedre alternativ for å finne lydfilen siden du trengte et NSURL-objekt for å initialisere AVAudioPlayer. De initWithContentsOfURL: error: Metoden laster innholdet i lydfilen inn i AVAudioPlayer eksempel, mye som NSString er stringWithContentsOfURL: koding: error: metode.

AVAudioPlayer ligger i AVFoundation-biblioteket, så vær sikker på å legge til følgende importoppgave til ViewController.h. Vi må ha tilgang til den fra headerfilen senere.

 #importere 

I tillegg trenger du noen private forekomstvariabler. Endre implementeringsdeklarasjonen til følgende.

 @implementation ViewController AVAudioPlayer * _player; UIButton * _playButton; UIButton * _stopButton;  Spille av sangen Neste, legg til en avspillingsknapp til scenen: _playButton = [UIButton buttonWithType: UIButtonTypeRoundedRect]; [_playButton setTitle: @ "Play" forState: UIControlStateNormal]; [_playButton addTarget: self action: @selector (playOrPause :) forControlEvents: UIControlEventTouchUpInside]; _playButton.frame = CGRectMake (100,0, 170,0, 120,0, 40,0); [[selvvisning] addSubview: _playButton]; PlayOrPause: handlingen skal implementeres slik: - (void) playOrPause: (id) avsender hvis (_player.playing) [_player pause]; [_playButton setTitle: @ "Play" forState: UIControlStateNormal];  ellers [_player play]; [_playButton setTitle: @ "Pause" forState: UIControlStateNormal]; 

Dette kontrollerer for å se om sangen allerede spiller via AVAudioPlayer s spiller eiendom. Hvis den er, pause den sangen ved hjelp av pausemetoden og endrer knappens tittel tilsvarende. Hvis det ikke er det, starter det sangen ved å ringe spillemetoden. Du bør nå kunne kompilere appen og spille eller pause en sang ved å trykke på knappen.

La oss ta dette et skritt videre ved å lage en Stoppe knapp. Legg til følgende i viewDidLoad metode.

 _stopButton = [UIButton buttonWithType: UIButtonTypeRoundedRect]; [_stopButton setTitle: @ "Stopp" forState: UIControlStateNormal]; [_stopButton addTarget: self action: @selector (stop :) forControlEvents: UIControlEventTouchUpInside]; _stopButton.frame = CGRectMake (100,0, 230,0, 120,0, 40,0); [[selvvisning] addSubview: _stopButton]; [/ sourcecode] Tilsvarende handling kaller AVAudioPlayer's stoppmetode. Vær oppmerksom på at denne metoden ikke endrer gjeldende avspillingsposisjon - den adskiller seg fra pause-metoden bare ved at den utelukker forhåndsbelastningen utført av spillemetoden. For å hoppe tilbake til begynnelsen av sangen som du forventer fra en typisk Stop-knapp, må du manuelt angi AVAudioPlayers nåværende egenskap, slik som:

[kildekode] - (tom) stopp: (id) avsender [_player stop]; _player.currentTime = 0; [_playButton setTitle: @ "Play" forState: UIControlStateNormal];

AVAudioPlayer Delegates

En annen fordel ved å bruke AVAudioPlayer over systemlydene API er at det lar deg håndtere avbrudd ved hjelp av det kjente delegatemønsteret. De AVAudioPlayerDelegate protokollen definerer en rekke metoder som forteller deg når visse hendelser oppstår utenfor søknaden din.

Når en avbrudd som en innkommende telefonsamtale begynner, vil audioPlayerBeginInterruption: Metoden kalles på delegatobjektet. Lyden vil pause automatisk, men dette gir deg mulighet til å skrive en annen tilpasset håndteringskode du trenger. På samme måte, audioPlayerEndInterruption: withOptions: Metoden kalles når avbrudd er over, og du kan bruke lydspilleren igjen. Systemet fortsetter imidlertid ikke automatisk avspilling. Du må manuelt ringe spillemetoden hvis du vil at dette skal skje.

I tillegg til avbruddshåndtering, gir delegatobjektet deg også beskjed når lyden er ferdig med å spille. Ved å definere en audioPlayerDidFinishPlaying: vellykket: Metode på delegatobjektet, du kan gjøre egendefinert opprydding. For eksempel kan du bruke dette til å tilbakestille spilleknappen og hoppe tilbake til begynnelsen av sangen, slik som det.

 - (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) spilleren vellykket: (BOOL) flagg [selvstopp: null]; NSLog (@ "Song ferdig med å spille!"); 

For at denne koden skal fungere, må du vise visningsansvarlig en formell delegat for AVAudioPlayer. I ViewController.h, endre grensesnittdeklarasjonen til følgende.

 @interface ViewController: UIViewController 

Da må visningskontrolleren tildele seg som delegatobjektet. I viewDidLoad Metode av ViewController.m, legg til følgende linje.

 _player.delegate = selv;

Nå, hvis du lar sangen spille gjennom til slutten, vil Pause knappen vender automatisk tilbake til a Spille knappen, og klikk på den vil starte sangen fra begynnelsen.


Figur 117: Vår enkle musikkspiller

Sammendrag

I dette kapittelet diskuterte vi to måter å spille av lyd fra en iOS-enhet, systemlyder og AVAudioPlayer. Den tidligere skal bare brukes til korte, enkle lyder som ikke trenger mye tilpasset konfigurasjon, og sistnevnte gir deg mer kontroll over lydavspillingen.

For den gjennomsnittlige iOS-appen, AVFoundation Framework gir en god balanse mellom en brukervennlig API og finkornet kontroll over lydene dine. Men husk at iOS også gir mer avanserte lydnivåer på lavt nivå, for eksempel Audio Queue Services, samt en API på høyere nivå for å kommunisere med brukerens eksisterende iTunes-bibliotek via Media Player Framework. For spesialiserte applikasjoner kan du til og med falle ned i OpenAL, som er et tverrplattformsbibliotek for å simulere et 3-D lydmiljø.

Mye arbeid har gått på å gjøre iOS til en multimedievennlig plattform, så det er ingen mangel på muligheter for å håndtere bilder, lyder og videoer fra din søknad.


Konklusjon

Dette kapittelet dekket grunnleggende om iOS-apputvikling. Vi startet med å bygge et enkelt brukergrensesnitt, som introduserte oss til de grunnleggende designmønstrene av iOS: modell-visning-kontrolleren, delegere objekter og mål-handling. Deretter dove vi inn i multi-scene applikasjoner og lærte hvordan iOS lar scener kommunisere med hverandre og håndterer automatisk overganger fra en scene til en annen. Deretter diskuterte vi iOS-filsystemet, applikasjonspakker og nødvendige ressurser som appikoner, startbilder og informasjonsegenskapslisten. Bundler skjedde også å være metoden for å lokalisere applikasjoner til flere regioner i iOS, så vi kunne levere oversatte bilder og tekst uten problemer til forskjellige språktalere. Til slutt tok vi en kort titt på lydfunksjonene ved å lage en enkel UI-lydeffekt og musikkspiller.

Mens det fortsatt er dusinvis av rammer som er igjen for deg å utforske på egenhånd, håper jeg at du føler deg komfortabel å navigere et Xcode-prosjekt. Sammen med litt praktisk erfaring, bør du ta en god forståelse av iOS-arkitekturen - hvordan grensesnitt opprettes og legges ut ved hjelp av UIKit og storyboards, og hvilke klasser og biblioteker som skal brukes til å administrere mediefondene . Bevæpnet med denne kunnskapen, bør du være mer enn klar til å gå inn i den virkelige verden av iOS app utvikling.

Denne leksjonen representerer et kapittel fra iOS Succinctly, en gratis eBok fra teamet på Syncfusion.