iOS SDK Touch tones spelen met het Audio Toolbox Framework

Welkom bij de zevende aflevering van onze serie over het ontwerpen en bouwen van een versie uit de jaren tachtig van de iOS? -Telefoon? app. In deze zelfstudie laat ik zien hoe u de juiste audiotoon afspeelt voor elk nummer op het toetsenblok van de telefoon.

Laatste app-voorbeeld

Dit is een momentopname van wat we in de loop van deze serie gaan bouwen:

Voordat je begint?

Dit is een meerdelige serie ontworpen om tussentijdse iOS SDK-onderwerpen te leren. De inhoud wordt steeds complexer naarmate de reeks vordert. Als je je op een gegeven moment verloren voelt in het volgen van deze serie, moet je misschien een stapje terug doen en je een weg banen door onze Learn Objective-C-serie of onze Begins iOS SDK Development-serie.

In de laatste zelfstudie in deze serie heb ik laten zien hoe ik een iPhone-oproep kan initiëren nadat ik een nummer op het toetsenbord heb gekozen en ook hoe ik de nummerweergave moet formatteren wanneer een gebruiker op een cijfer tikt. In deze zelfstudie voegen we de beloofde aanrakingstonen toe aan elk van de 0 - 9 knoppen.

Overzicht van iOS-audio

De iOS SDK wordt geleverd met meerdere frameworks die verschillende methoden bieden voor het afspelen van geluidsfragmenten en zelfs het genereren van audio on-the-fly. Appels Programmagids voor multimedia beschrijft het doel van elk beschikbaar audioframework als volgt:

  • Gebruik de Media Player-raamwerk om liedjes, audioboeken of audiopodcasts af te spelen vanuit de iPod-bibliotheek van een gebruiker?
  • Gebruik de AV Foundation-raamwerk om audio te spelen en op te nemen met behulp van een eenvoudige Objective-C-interface?
  • Gebruik de Audio Toolbox framework om audio af te spelen met synchronisatiemogelijkheden, toegangspakketten met inkomende audio, parse audiostreams, converteer audioformaten en neem audio op met toegang tot individuele pakketten?
  • Gebruik de Audio Unit-raamwerk om audio-processing plug-ins te gebruiken en te gebruiken?
  • Gebruik de OpenAL-raamwerk om te voorzien in positionele audioweergave in games en andere applicaties. iOS ondersteunt OpenAL 1.1?

-Handleiding voor het programmeren van multimedia: Audio gebruiken

Een hele reeks tutorials zou kunnen worden gewijd aan elk van de frameworks in de bovenstaande lijst, maar het volstaat om te zeggen dat we voor het doel van deze tutorial het Audio Toolbox-framework zullen gebruiken vanwege één uniek aanbod: System Sound Services. Systeemgeluidsservices zijn een interface op C-niveau die is bedoeld voor het afspelen van korte geluidseffecten van de gebruikersinterface en andere kleine audiofragmenten van 30 seconden of korter.

Het proces voor het afspelen van een audioclip met System Sound Services omvat drie stappen:

  1. Registreer een audioclip met systeemgeluidservices voor weergave in de (niet zo verre) toekomst
  2. Ontvang een systeemgeluids-ID (SSID) dat op unieke wijze de audioclip identificeert die is geregistreerd bij de systeemgeluidsserver.
  3. Roep de systeemgeluidsserver op met de juiste SSID om het afspelen te starten.

De rest van deze tutorial zal dit proces implementeren om vooraf opgenomen DTMF-tonen te spelen voor de cijfers 0-9 van het bediendeel.

Waarom gebruiken we vooraf opgenomen tonen in plaats van het genereren van de juiste frequentie on-the-fly? In essentie om tijd te besparen en om deze tutorial toegankelijker te houden door de wiskunde te vermijden die te maken heeft met sinusoïdale functies en het genereren van frequenties. Als u in plaats daarvan naar die route wilt gaan, vindt u waarschijnlijk de volgende artikelen handig:

  • Dual-tone multifrequentiesignalering
  • Touch Tone Keypad
  • Sinus
  • iPhone Dev SDK-forums: genereer een pieptoon

Wil je echt weten hoe je on-the-fly geluid kunt genereren? Als dit bericht ten minste 10 reacties ontvangt waarin een zelfstudie wordt gevraagd over hoe je vanaf 1 mei 2011 de audio helemaal opnieuw kunt maken, dan maak ik een geavanceerde iOS SDK-serie over dat onderwerp. Geen beloften dat het specifiek DTMF-aanraaktonen betreft, maar het zal zeker iets geweldigs zijn.

Laten we, met de theoretische kennis uit de weg, een duik nemen in de code en deze functie laten uitvoeren!

Stap 1: Importeer het AudioToolbox Framework

We moeten beginnen met het importeren van het Audio Toolbox-framework in onze applicatie om de System Sound Services beschikbaar te maken voor onze code. Selecteer hiervoor het project "PhoneAppSkin" in het deelvenster Projectnavigator in Xcode, selecteer vervolgens "PhoneAppSkin" onder "TARGETS" en selecteer tenslotte het tabblad "Fasen opbouwen". Na dit te hebben gedaan, zou uw scherm er ongeveer zo uit moeten zien:

Klik vervolgens op de vervolgkeuzelijst "Binaire elementen koppelen met bibliotheken" en klik op het symbool "+" om een ​​nieuw kader toe te voegen aan de koppelingsfase van ons project..

Zoek ten slotte het kader "AudioToolbox" in het pop-upvenster en klik vervolgens op "Toevoegen".

Open vervolgens de PhoneViewController.h bestand en voeg de regel toe die nodig is om het Audio Toolbox-framework daadwerkelijk in uw klas te importeren:

 #importeren  #importeren 

De Audio Toolbox-functies moeten nu toegankelijk zijn voor uw klas!

Stap 2: Importeer de Touch Tone WAV-bestanden

Download en open de broncode die bij dit Mobiletuts + bericht hoort en zoek de map met de titel "Audio". Sleep deze hele map naar de map "Bronnen" van de Xcode Project Navigator en zorg ervoor dat u de optie "Kopiëren" aanvinkt wanneer hierom wordt gevraagd. Je zou moeten eindigen met een scherm dat ongeveer zo is:

Stap 3: Maak een array voor de SSID-verwijzingen

In PhoneViewController.h, voeg de volgende C-stijl array-declaratie toe:

 @interface PhoneViewController: UIViewController SystemSoundID toneSSID's [10]; 

Lijn 13 verklaart een C-type array van type SystemSoundID met een maximale capaciteit van 10.

Het opslaan van systeemgeluids-ID's in deze array zal ons in staat stellen snel naar de juiste geluidsfragment in de numberButtonPressed: methode later.

Stap 4: registreer de geluiden van het toonsysteem

Open PhoneViewController.m en spring naar de initWithCoder methode op regel 17. Wanneer de PhoneViewController wordt eerst geïnitialiseerd en de initWithCoder methode wordt genoemd, willen we systeemgeluiden registreren voor elke toon die op het toetsenbord wordt gebruikt met de iOS-systeemgeluidsserver. Nadat een geluidsclip is geregistreerd bij de geluidsserver, kunnen we de server opdracht geven om het geluidsbestand later af te spelen wanneer op het toetsenblok wordt gedrukt.

Voer de volgende code in om de 0-9-aanrakingstonen te registreren:

 -(id) initWithCoder: (NSCoder *) aDecoder self = [super initWithCoder: aDecoder]; if (self) phoneNumberString = [[NSString alloc] init]; voor (int count = 0; count < 10; count++) NSString *toneFilename = [NSString stringWithFormat:@"DTMF_%02d", count]; NSURL *toneURLRef = [[NSBundle mainBundle] URLForResource:toneFilename withExtension:@"wav"]; SystemSoundID toneSSID = 0; AudioServicesCreateSystemSoundID( (CFURLRef) toneURLRef, &toneSSID ); toneSSIDs[count] = toneSSID;   return self; 

Op regel 24, een voor lus die 10 keer wordt herhaald begint. Het doel van dit voor Loop is om een ​​nieuw systeemgeluids-ID toe te voegen aan de toneSSIDs matrix voor elk van de aanraaktoetsen behorend bij de toetsen 0 - 9.

Op regel 25, een instantie van NSString wordt geïnstantieerd die de bestandsnaam van de relevante DTMF-aanraaktoon zal bevatten. Een interessante opmerking over deze regel is de stringWithFormat: method call en de % 02d formaat specificatie. Deze indelingsspecificator zet elk cijfer om in een nulgevuld cijfer van 2 tekens. Dus, bijvoorbeeld 0 wordt '00', 1 wordt '01', 2 wordt '02', enz.

Op regel 27, de NSBundle class wordt gebruikt om een ​​bestandssysteempad te genereren naar de bestandsnaam gegenereerd op regel 25 met een extensie van "wav" toegevoegd. NSLog deze waarde als u het volledige pad voor uzelf wilt zien.

Lijn 29 creëert een variabele om de te houden SystemSoundID die vervolgens door de geluidsserver van het iOS-systeem wordt gegenereerd.

Als een kanttekening, SystemSoundID is slechts een typedefinitie voor het Mac-type UInt32, wat zelf een typefout is niet lang ondertekend. Daarom hadden we de variabele op deze regel van het type kunnen declareren niet lang ondertekend, maar dit zou een slechte praktijk zijn, omdat toekomstige iOS-releases de SystemSoundID type, waardoor de code breekt. Desalniettemin is het goed om dit in gedachten te houden bij het werken met SystemSoundIDs omdat de compiler soms waarschuwt voor incompatibel niet lang ondertekend types.

Lijnen 31 - 34 zijn een c-stijl functie aanroepen AudioServicesCreateSystemSoundID, wat een CFURL (Core Foundation-URL) van het audiobestandpad om een ​​systeemgeluids-id voor en een SystemSoundID-verwijzing te genereren die wordt gebruikt om de SSID op te slaan nadat deze is gemaakt. Merk op hoe het ampersand-teken (dat wil zeggen '&') vóór de. Verschijnt toneSSID variabele op regel 33? Dit is een unaire prefix-operator die de. Converteert toneSSID parameter in het geheugenadres van de variabele in plaats van de waarde die in het geheugen voor die variabele is opgeslagen. Dit wordt gedaan zodat de AudioServicesCreateSystemSoundID functie kan het gegenereerde SSID nummer direct opslaan in de toneSSID geheugenadres, waardoor de functie-aanroeper (dat wil zeggen onze methode) toegang heeft tot de gegenereerde SSID zonder de SSID daadwerkelijk terug te geven van de functie.

Klinkt een beetje verwarrend? Waarschijnlijk zal het tenzij je al ervaring hebt met programmeren in een taal als C, C ++ of Go. Omdat Objective-C een strikte superset is van de C-taal, is de iOS-SDK soms afhankelijk van bibliotheken die zijn geschreven in procedurele C. Als de C-syntaxis niet logisch voor u is, hoeft u zich daar nu niet al te veel zorgen over te maken, maar neem het als een uitdaging om in de toekomst je SDK-kennis van iOS aan te vullen met de basisprincipes van de C-taal!

Op regel 35, de index van de toneSSIDs c-stijl array aangewezen door de stroom tellen waarde wordt de waarde toegewezen die door de AudioServicesCreateSystemSoundID functie. Naar deze SSID-waarde wordt later verwezen om de juiste toon af te spelen wanneer de gebruiker op de cijfers van het toetsenbord tikt.

Stap 5: Speel Touch Tones on Tap

De numberButtonPressed: methode wordt elke keer dat de touchUpInside evenement vuurt voor knoppen 0 - 9. Omdat indices 0-9 van de toneSSIDs array bevat nu de bijbehorende toon voor elke knop, de volgende drie regels code zijn voldoende om de juiste toon te spelen:

 -(IBAction) numberButtonPressed: (UIButton *) pressedButton int toneIndex = [pressedButton.titleLabel.text intValue]; SystemSoundID toneSSID = toneSSIDs [toneIndex]; AudioServicesPlaySystemSound (toneSSID); self.phoneNumberString = [self.phoneNumberString stringByAppendingString: pressedButton.titleLabel.text]; [self display Phone Nummer]; 

Regel 96 converteert de tekstwaarde van de ingedrukte UIButton titel van een geheel getal uit een string.

Met het cijfer voor het toetsenblok verkregen, regel 97 haalt een SystemSoundID van de toneSSIDs rangschikking.

Op regel 98, de AudioServicesPlaySystemSound De functie wordt aangeroepen met de SSID die zojuist is opgehaald om het afspelen van de toetstoon te starten.

Dat is het! Ga je gang en opslaan en bouwen het project nu, en je zou moeten merken dat de cijfers van het toetsenbord geluidseffecten hebben!

Stap 6: Het pittig maken

Er is een klein probleem met de huidige oplossing. Merk je de vertraging op tussen het aanraken van de knop en de gegenereerde toon? In deel 6 van deze serie zijn de knoppen op het toetsenbord ingesteld om de touchUpInside actie. Deze actie wordt geactiveerd nadat de gebruiker zijn vinger van de knop haalt. De toon moet echter worden afgespeeld zodra de gebruiker op de knop tikt, niet na het verwijderen van de vinger. Om dit op te lossen, open PhoneView.xib, Verwijder de touchUpInside IBAction referenties voor alle knoppen, en vervolgens elke knop te binden touchdown actie voor de numberButtonPressed: methode.

Als u hulp nodig hebt bij het uitzoeken hoe u deze stap moet uitvoeren, raadpleegt u gewoon deel 6, stap 1 in deze serie.

Afronden

Deze zelfstudie is een wervelende tournee geweest door het kader van Audio Toolbox en System Sound Services. Als u vragen heeft, kunt u deze achterlaten in de opmerkingen hieronder en ik zal mijn best doen om te reageren. Natuurlijk zijn er niet genoeg uren op de dag om alle oude berichten elke dag opnieuw te bekijken op nieuwe reacties, dus als de maanden aanhouden, heb je misschien meer geluk door contact met me op te nemen via Twitter: @markhammonds.