iOS bondig - Audio

iOS biedt verschillende opties voor het werken met audio. In dit hoofdstuk introduceren we twee frameworks voor het omgaan met verschillende soorten geluiden. Het Audio Toolbox Framework bevat een C-bibliotheek voor het afspelen van eenvoudige systeemgeluiden en het AVFoundation Framework biedt een objectgeoriënteerde interface voor het afspelen en opnemen op middelhoog niveau.

Voor beide raamwerken is de interactie met audiobestanden conceptueel hetzelfde als interactie met afbeeldingen. U gebruikt nog steeds NSBundle om het bestand op schijf te vinden en laadt vervolgens de inhoud ervan met een andere klasse die is bedoeld voor het interpreteren van de verschillende audioformaten.

De systeemgeluid-API wordt gedefinieerd in het Audio Toolbox Framework. Dit gehele framework is geschreven in C in plaats van Objective-C, dus we zullen in de eerste helft van dit hoofdstuk met de C-interface werken in een iOS-applicatie. Dit verandert de manier waarop we omgaan met kernobjecten van iOS, maar laat je niet afschrikken. We hebben nog steeds te maken met dezelfde objecten en concepten als we in dit hele boek zijn geweest. Bijvoorbeeld in plaats van de mainBundle methode van NSBundle, we gaan een C-functie gebruiken genaamd CFBundleGetMainBundle () om de toepassingsbundel te openen.


De voorbeeldtoepassing maken

Net als in het vorige hoofdstuk is alles wat we nodig hebben eenvoudig Toepassing enkele weergave. Maak een nieuw project en noem het audio. Gebruik zoals gewoonlijk edu.self voor de Bedrijfsidentificatie en iPhone voor apparaten, en zorg ervoor dat beide Gebruik storyboards en Gebruik automatische referentietelling selectievakjes zijn geselecteerd.

In tegenstelling tot het vorige hoofdstuk hebben we toegang tot twee audiokaders nodig die niet in de sjabloon zijn opgenomen. Om een ​​nieuw kader aan het project toe te voegen, klikt u op het projectpictogram in de Project Navigator en selecteer de audio doelwit. In de Samenvatting tab, scrol omlaag naar de Gekoppelde kaders en bibliotheken sectie.


Figuur 113: De kaders die momenteel in ons project zijn opgenomen

Dit zijn de codebibliotheken waar u toegang toe hebt vanuit de applicatiecode. U moet het toevoegen Audio Toolbox Framework om te werken met systeemgeluiden, dus klik op het plusteken in de linkerbenedenhoek. Het resulterende dialoogvenster bevat een lijst met alle beschikbare kaders en bibliotheken. Beginnen met typen "audiotoolbox"In de zoekbalk om ons gewenste kader te vinden.


Figuur 114: Zoeken naar het Audio Toolbox Framework

Klik AudioToolbox.framework en klik vervolgens op Toevoegen om het in het project op te nemen. We hebben ook toegang tot de. Nodig AVFoundation Framework voor de AVAudioPlayer deel van dit hoofdstuk, dus herhaal ook het proces voor deze bibliotheek. Je zou beide moeten zien AVFoundation.framework en AudioToolbox.framework in de Samenvatting tab voordat je verdergaat.


Figuur 115: Alle vereiste bibliotheken voor ons voorbeeldproject

We zijn nu klaar om te gaan werken met systeemgeluiden en AVAudioPlayer.


Systeemgeluiden

Systeemgeluiden zijn ontworpen om te worden gebruikt voor eenvoudige dingen zoals waarschuwingen en UI-geluidseffecten (bijvoorbeeld klikken op knoppen). Ze zijn heel gemakkelijk in gebruik, maar het nadeel is dat ze niet veel opties bieden om het afspelen te regelen. De belangrijkste beperkingen van de API voor systeemgeluid zijn als volgt.

  • Geluiden kunnen niet langer zijn dan dertig seconden.
  • U kunt het volume van systeemgeluiden niet regelen. Ze gebruiken het huidige apparaatvolume. Er kan slechts één geluid tegelijk worden afgespeeld.
  • Geluiden kunnen na een bepaalde vertraging niet worden herhaald of herhaald.
  • Ze ondersteunen alleen .caf, .aif en .wav-bestanden.
  • Het is niet mogelijk om te configureren hoe geluiden omgaan met onderbrekingen zoals inkomende oproepen.

Als u vindt dat deze te beperkend zijn, moet u de AVAudioPlayer gebruiken die verderop in dit hoofdstuk wordt besproken. Nogmaals, systeemgeluiden zijn bedoeld voor specifieke gebruikscasussen. Als uw toepassing geluiden gebruikt voor meer dan UI-feedback en waarschuwingen, moet u dit waarschijnlijk gebruiken AVAudioPlayer.

Toegang tot het geluidsbestand

Het bronpakket voor dit boek bevat een kort geluidsbestand met de naam blip.wav. Voeg dit toe aan de toepassingsbundel door het naar de applicatiebundel te slepen Project Navigator. Onthoud dat systeemgeluiden een C-interface gebruiken, dus we zullen dit bestand openen met een iets andere methode dan de vorige hoofdstukken. In ViewController.m, verandering viewDidLoad Naar het volgende.

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

CFBundleGetMainBundle () is in wezen hetzelfde als [[NSBundle] mainBundle], behalve dat het het CoreFoundation-object retourneert dat de toepassingsbundel vertegenwoordigt in plaats van de versie van het Foundation Framework. De CoreFoundation Framework is een alternatief op een lager niveau voor de Foundation Framework. We moeten gebruiken CoreFoundation objecten hier omdat dat is wat de Audio Toolbox als argumenten accepteert.

De CFBundleCopyResourceURL () is de CoreFoundation-versie van NSBundle's pathForResource: OfType: methode. Het retourneert eenvoudig het pad naar de gevraagde bron en u zou een bekend bestandspad in de. Moeten zien NSLog () uitgang.

Als u eenmaal een pad naar het geluidsbestand hebt, moet u een geluidsobject maken met behulp van de AudioServicesCreateSystemSoundID () functie. Voeg het volgende toe aan viewDidLoad.

 AudioServicesCreateSystemSoundID (blipURL, & _blipOne);

Deze functie leest de inhoud van het geluidsbestand in, verandert het in een geluidobject dat de systeemgeluid-API weet te spelen en geeft een ID terug die u kunt gebruiken om er later naar te verwijzen. AudioServicesCreateSystemSoundID () wordt gedefinieerd door het Audio Toolbox Framework, dus je moet het importeren ViewController.m voordat je het kunt gebruiken. Voeg het volgende toe aan de bovenkant van het bestand.

 #importeren 

U slaat de ID van het geluidsobject op in een opgeroepen particuliere instantievariabele _blip, dus voeg dat ook toe aan de implementatieverklaring.

 @implementation ViewController SystemSoundID _blip;  De geluiden afspelen Voeg vervolgens een knop programmatisch toe aan de scène; op die knop wordt het geluid afgespeeld wanneer erop wordt geklikt. UIButton * aButton = [UIButton-knopWithType: UIButtonTypeRoundedRect]; [aButton setTitle: @ "Blip" forState: UIControlStateNormal]; [aButton addTarget: self action: @selector (playBlip :) forControlEvents: UIControlEventTouchUpInside]; aButton.frame = CGRectMake (100.0, 200.0, 120.0, 40.0); [[zelfweergave] addSubview: aButton]; Voor de actie playBlip: we bellen de functie AudioServicesPlaySystemSound () om het geluid af te spelen. Het accepteert één enkel argument, wat de SystemSoundID moet zijn die verwijst naar het gewenste geluidsobject (bijv. _Blip). - (ongeldig) playBlip: (id) afzender AudioServicesPlaySystemSound (_blip); 

Wanneer u het project compileert, moet u op de knop kunnen klikken en een kort geluid horen. Zorg ervoor dat uw luidsprekers niet zijn gedempt.


Afbeelding 116: een blankerknop

Als u op de knop klikt terwijl het geluid nog steeds wordt afgespeeld, merkt u dat iOS het huidige geluid annuleert en een nieuw geluid begint. Nogmaals, systeemgeluiden zijn bedoeld voor UI-geluidseffecten en andere eenvoudige toepassingen. Als u meerdere geluiden tegelijk wilt afspelen, moet u upgraden naar de AVAudioPlayer besproken in de volgende sectie.

AudioServicesCreateSystemSoundID () en AudioServicesPlaySystemSound () zijn vrijwel alles wat er is voor systeemgeluiden. U kunt ook de AudioServicesPlayAlertSound () functie nuttig. Het werkt precies zoals AudioServicesPlaySystemSound (), maar het laat de telefoon trillen als de gebruiker dit heeft ingeschakeld.


AVAudioPlayer

Het AVFoundation Framework biedt een interface op een hoger niveau voor het beheren van het afspelen van audio. Voor games, aangepaste muziekspelers en andere apps waarvoor geavanceerde audiobediening vereist is, is dit het kader dat u moet gebruiken. Enkele van zijn mogelijkheden omvatten:

  • Geen beperking van geluidsduur.
  • Je kunt meerdere geluiden tegelijk spelen.
  • Het volume kan worden geregeld voor individuele geluiden.
  • Het is mogelijk om een ​​geluid te herhalen of andere acties uit te voeren wanneer het afspelen is voltooid.
  • U kunt naar willekeurige punten in het geluidsbestand springen.
  • Het is eenvoudig om gedrag te configureren voor het verwerken van onderbrekingen via een delegatieobject.

AVAudioPlayer is de hoofdklasse die u zult gebruiken van de AVFoundation Kader. Het biedt een objectgeoriënteerde manier om het volume in te stellen, het geluid af te spelen, het geluid te stoppen, op te geven welk gedeelte van het geluid moet worden afgespeeld, enzovoort. Je kunt het beschouwen als het audio-equivalent van UIImage / UIImageView.

Ondersteunde bestandsindelingen voor AVAudioPlayer zijn .m4a, .aac, .wav, .mp3, .aif, .pcm, .caf en enkele andere. Zie Apple's Multimedia Programming Guide voor een gedetailleerde bespreking van audiobestandsindelingen.

Toegang tot de song

AVAudioPlayer is ontworpen om te worden gebruikt met langere geluidsbestanden, zoals nummers, dus we hebben een openbaar domein Billie Holiday-deuntje gedistribueerd met dit boek. Sleept de good-morning-heartache.mp3 bestand van het bronpakket in de Project Navigator om het aan de bundel toe te voegen.

Sinds AVFoundation is een Objective-C-bibliotheek, we kunnen teruggaan naar het gebruik van NSBundle voor toegang tot media-items. Ga je gang en verwijder alles viewDidLoad, en vervang het door het volgende.

 NSURL * soundFileURL = [[NSBundle mainBundle] URLForResource: @ "good-morning-heartache" withExtension: @ "mp3"]; _player = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: nil];

De URLForResource: withExtension: methode is de NSURL equivalent aan pathForResource: OfType:. Dit was een betere optie om het audiobestand te vinden omdat u een NSURL-object nodig had om het te initialiseren AVAudioPlayer. De initWithContentsOfURL: error: methode laadt de inhoud van het geluidsbestand in de AVAudioPlayer bijvoorbeeld, net zoals bij NSString stringWithContentsOfURL: encoding: error: methode.

AVAudioPlayer bevindt zich in de AVFoundation-bibliotheek, dus zorg ervoor dat u de volgende importinstructie toevoegt aan ViewController.h. We moeten het later vanuit het header-bestand openen.

 #importeren 

Daarnaast hebt u enkele privéinstancevariabelen nodig. Verander de uitvoeringsverklaring naar het volgende.

 @implementation ViewController AVAudioPlayer * _player; UIButton * _playButton; UIButton * _stopButton;  De song afspelen Voeg vervolgens een afspeelknop toe aan de scène: _playButton = [UIButton-knopWithType: 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); [[zelfweergave] addSubview: _playButton]; De actie playOrPause: actie moet als volgt worden geïmplementeerd: - (void) playOrPause: (id) afzender if (_player.playing) [_player pause]; [_playButton setTitle: @ "Play" forState: UIControlStateNormal];  else [_player play]; [_playButton setTitle: @ "Pause" forState: UIControlStateNormal]; 

Hiermee wordt gecontroleerd of het nummer al wordt afgespeeld via AVAudioPlayer's het spelen van eigendom. Als dit het geval is, wordt het nummer gepauzeerd met de pauzemethode en wordt de titel van de knop overeenkomstig aangepast. Als dat niet het geval is, wordt het nummer gestart door de afspeelmethode aan te roepen. Je zou nu in staat moeten zijn om de app te compileren en een nummer te spelen of te pauzeren door op de knop te tikken.

Laten we een stap verder gaan door een Hou op knop. Voeg het volgende toe aan de viewDidLoad methode.

 _stopButton = [UIButton-knopWithType: UIButtonTypeRoundedRect]; [_stopButton setTitle: @ "Stop" forState: UIControlStateNormal]; [_stopButton addTarget: self action: @selector (stop :) forControlEvents: UIControlEventTouchUpInside]; _stopButton.frame = CGRectMake (100.0, 230.0, 120.0, 40.0); [[zelfweergave] addSubview: _stopButton]; [/ sourcecode] De bijbehorende actie roept de stopmethode van de AVAudioPlayer aan. Merk op dat deze methode de huidige afspeelpositie niet wijzigt-deze verschilt alleen van de pauzemethode in die zin dat de preloading die door de afspeelmethode wordt uitgevoerd, ongedaan wordt gemaakt. Om terug te gaan naar het begin van de song, zoals u van een standaardstopknop zou verwachten, moet u de currentTime-eigenschap van AVAudioPlayer handmatig instellen, zoals:

[sourcecode] - (void) stop: (id) afzender [_player stop]; _player.currentTime = 0; [_playButton setTitle: @ "Play" forState: UIControlStateNormal];

AVAudioPlayer-deelnemers

Nog een voordeel van het gebruik AVAudioPlayer via de systeemgeluiden API is dat u hiermee onderbrekingen kunt afhandelen met behulp van het vertrouwde deelnemerspatroon. De AVAudioPlayerDelegate protocol definieert een aantal methoden die u laten weten wanneer bepaalde gebeurtenissen buiten uw toepassing plaatsvinden.

Wanneer een onderbreking zoals een inkomend telefoongesprek begint, de audioPlayerBeginInterruption: methode wordt aangeroepen op het delegatieobject. Het geluid wordt automatisch onderbroken, maar dit geeft u de kans om een ​​andere aangepaste verwerkingscode te schrijven die u mogelijk nodig hebt. Evenzo, de audioPlayerEndInterruption: withOptions: methode wordt aangeroepen wanneer de onderbreking voorbij is en u de audiospeler opnieuw kunt gebruiken. Het systeem zal het afspelen echter niet automatisch hervatten. Je moet de afspeelmethode handmatig bellen als je wilt dat dit gebeurt.

Behalve het afhandelen van interrupts, laat het gedelegeerde object u ook weten wanneer het geluid klaar is met spelen. Door een audioPlayerDidFinishPlaying: succes: methode op het delegatieobject, kunt u aangepaste opschoning uitvoeren. U kunt dit bijvoorbeeld gebruiken om de afspeelknop opnieuw in te stellen en terug te gaan naar het begin van de song, zoals zo.

 - (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) speler succesvol: (BOOL) vlag [stop: nihil]; NSLog (@ "Song is beëindigd!"); 

Om deze code te laten werken, moet je van de view controller een formele afgevaardigde maken voor de AVAudioPlayer. In ViewController.h, verander de interface-verklaring naar het volgende.

 @interface ViewController: UIViewController 

Vervolgens moet de view controller zichzelf toewijzen als het delegatieobject. In de viewDidLoad methode van ViewController.m, voeg de volgende regel toe.

 _player.delegate = zelf;

Als je het nummer tot het einde laat spelen, dan is het Pauze knop wordt automatisch teruggezet in een Spelen Als u op de knop klikt, wordt het nummer vanaf het begin gestart.


Figuur 117: Onze eenvoudige muziekspeler

Samenvatting

In dit hoofdstuk hebben we twee manieren besproken om audio af te spelen vanaf een iOS-apparaat, systeemgeluiden en AVAudioPlayer. De eerste moet alleen worden gebruikt voor korte, eenvoudige geluiden die niet veel aangepaste configuratie nodig hebben, en de laatste geeft je meer controle over het afspelen van audio.

Voor de gemiddelde iOS-app, de AVFoundation Framework biedt een goede balans tussen een gebruikersvriendelijke API en een fijnmazige controle over je geluiden. Houd er echter rekening mee dat iOS ook meer geavanceerde, low-level audiomogelijkheden biedt, zoals Audio Queue Services, evenals een hogere API voor interactie met de bestaande iTunes-bibliotheek van de gebruiker via het Media Player Framework. Voor gespecialiseerde toepassingen kunt u zelfs naar OpenAL gaan, wat een platformonafhankelijke bibliotheek is voor het simuleren van een 3D-audioomgeving.

Er is veel werk verzet om iOS een multimediavriendelijk platform te maken, dus er is geen tekort aan opties voor het beheren van afbeeldingen, geluiden en video's vanuit je applicatie.


Conclusie

Dit hoofdstuk ging over de basisprincipes van de ontwikkeling van iOS-apps. We begonnen met het bouwen van een eenvoudige gebruikersinterface, die ons kennis liet maken met de fundamentele ontwerppatronen van iOS: model-view-controller, delegatie-objecten en doelactie. Daarna doken we in multi-scene-applicaties en leerden we hoe iOS scènes met elkaar laat communiceren en automatisch overgangen van de ene scène naar de andere verwerkt. Daarna bespraken we het iOS-bestandssysteem, applicatiebundels en vereiste bronnen zoals app-pictogrammen, startbeelden en de informatie-eigenschappenlijst. Bundels waren toevallig ook de methode voor het lokaliseren van applicaties naar meerdere regio's in iOS, dus we konden vertaalde afbeeldingen en tekst moeiteloos aan verschillende taalluidsprekers presenteren. Ten slotte hebben we een korte blik op de audiomogelijkheden gelegd door een eenvoudig UI-geluidseffect en muziekspeler te maken.

Hoewel er nog tientallen frameworks over zijn om zelf te verkennen, hoop ik dat je je prettig zult voelen bij het navigeren door een Xcode-project. Naast wat praktische ervaring, is het een goed begrip van de iOS-architectuur - hoe interfaces worden gemaakt en uitgelegd met behulp van UIKit en storyboards, en welke klassen en bibliotheken moeten worden gebruikt voor het beheer van media-items. . Gewapend met deze kennis zou je meer dan klaar moeten zijn om je te wagen in de echte wereld van iOS-app-ontwikkeling.

Deze les vertegenwoordigt een hoofdstuk van iOS bondig, een gratis eBoek van het team van Syncfusion.