Georg fährt extra nach Berlin um Steve Ballmer zu treffen

31 Tage Mango | Tag #27: Mikrofon API

Die­ser Arti­kel ist Tag #27 der Serie 31 Tage Man­go von Jeff Blan­ken­burg.

Der Ori­gi­nal­ar­ti­kel befin­det sich hier: Day #27: Micro­pho­ne API.

Die­ser Arti­kel wur­de in der Ori­gi­nal­se­rie von Gast­au­tor Parag Joshi geschrie­ben. Bei Twit­ter kann Parag unter @ilovethexbox erreicht wer­den.

Einleitung

Je nach Tätig­keit und Nut­zungs­ver­hal­ten kann Sprach­er­ken­nung oder die Auf­nah­me von Sprach­no­ti­zen ein häu­fi­ges Anwen­dungs­sze­na­rio von Smart­pho­nes sein. Von heu­ti­ge Mobil­te­le­fo­nen wird erwar­tet, dass sie Sprach­kom­man­dos ver­ste­hen kön­nen, bei­spiels­wei­se zur Steue­rung von Anwen­dun­gen, zum Wäh­len einer Num­mer oder zum Abspie­len von Musik.

Die Mög­lich­keit, unter­wegs schnell eine Sprach­no­tiz auf­zu­neh­men, ist ein wei­te­res nütz­li­ches Fea­ture von Smart­pho­nes.

Der ers­te Schritt zu einer der­ar­ti­gen Anwen­dung ist die Fähig­keit, Ton vom Mikro­fon auf­zu­neh­men und zu ver­ar­bei­ten.

Heu­te wer­den wir uns also die Mikro­fon API in Man­go anschau­en und dazu ein klei­nes Bei­spiel bau­en.

Worum geht es?

Als klei­nes Bei­spiel wol­len wir Ton auf­neh­men und zur Wie­der­ga­be spei­chern. Damit hat der Nut­zer die Basis­funk­tio­na­li­tät zur Auf­nah­me von Sprach­no­ti­zen.

Die fol­gen­den Punk­te ver­die­nen beson­de­re Erwäh­nung:

  1. Die Klas­se Micro­pho­ne — Die­se Klas­se wird uns vom Name­space Microsoft.Xna.Framework.Audio zur Ver­fü­gung gestellt und erlaubt uns Zugriff auf das Mikro­fon.
  2. public event Event­Hand­ler Buf­fer­Rea­dy — dies ist ein Ereig­nis­hand­ler, um anzu­zei­gen, dass die gepuf­fer­ten Daten des Mikro­fons zur Ver­fü­gung ste­hen. Wir wer­den die­ses Ereig­nis behan­deln um den Ton zur Wie­der­ga­be zu spei­chern.
  3. Microphone.Start — Wie der Name sagt, rufen wir die­se Metho­de um die Auf­nah­me zu star­ten.
  4. Microphone.Stop — Die­se Metho­de rufen wir zum Anhal­ten der Auf­nah­me. Ein Auf­ruf die­ser Metho­de leert sofort den Puf­fer.

Wie Sie in der Bei­spiel­an­wen­dung sehen wer­den, rufen wir Stop nicht sofort in dem Moment, wo der Benut­zer das Mikro­fon betä­tigt oder den Play But­ton drückt. Wir war­ten statt­des­sen zuerst auf den Buf­fer Rea­dy Event, um das letz­te Stück­chen des auf­ge­nom­me­nen Tons auch noch mit­zu­be­kom­men. Erst dann been­den wir die Auf­nah­me.

Wie Sie beim Blick auf den Name­space ver­mu­tet haben, brau­chen wir eine Refe­renz auf das XNA Frame­work. Die Micro­pho­ne API ist Teil des XNA Frame­works und erwar­tet die Simu­la­ti­on eines XNA Game Loops. Falls Sie von XNA noch nichts gehört haben: XNA ist ein Frame­work von Micro­soft zur Erstel­lung von Spie­len und gra­fik­in­ten­si­ven Anwen­dun­gen.

Die Beispielanwendung

Vor­be­rei­tun­gen: Instal­lie­ren Sie die Man­go Werk­zeu­ge von http://create.msdn.com/. Damit bekom­men Sie das Visu­al Stu­dio Express 2010 und das Win­dows Pho­ne SDK zur Ent­wick­lung von Anwen­dun­gen für Win­dows Pho­ne.

Laden Sie die Anwen­dung unten her­un­ter, öff­nen Sie das Visu­al Stu­dio und öff­nen Sie die Solu­ti­on Datei der Anwen­dung. Die Anwen­dung wur­de mit der Sil­ver­light Pro­jekt­vor­la­ge „Win­dows Pho­ne App­li­ca­ti­on“ erstellt. Bau­en Sie das Pro­jekt und instal­lie­ren Sie es im Emu­la­tor. Sobald die Anwen­dung gela­den hat, wer­den Sie fol­gen­den Bild­schirm sehen:

Fol­gen­de Steu­er­ele­men­te sind dort zu sehen:

  • Der But­ton Mikro­fon ist ein Schal­ter, der das Mikro­fon star­tet und anhält.
  • Der But­ton Play gibt die Auf­nah­men wie­der.
  • Die drei Sli­der kön­nen ver­wen­det wer­den, um die Laut­stär­ke, die Höhe und die Balan­ce ein­zu­stel­len.

Um die Anwen­dung aus­zu­pro­bie­ren, star­ten Sie eine Auf­nah­me durch Betä­ti­gung des Mikro­fon But­tons. Anhal­ten kön­nen Sie, indem Sie ent­we­der noch mal den Mikro­fon But­ton oder den Play But­ton drü­cken. Ver­än­dern Sie die Reg­ler für Laut­stär­ke, Höhe und Balan­ce nach­ein­an­der und pro­bie­ren Sie deren Aus­wir­kun­gen aus.

Der Code

Dekla­ra­tio­nen: Hier ist ein Screen­shot der Dekla­ra­tio­nen.

Wir ver­wen­den ein Objekt der Klas­se Sound­Ef­fec­t­In­stan­ce um Ton auf­zu­neh­men und wie­der­zu­ge­ben. Wir hät­ten auch einen Sound­Ef­fect ver­wen­den kön­nen — die Klas­se Sound­Ef­fec­t­In­stan­ce erlaubt uns aber zusätz­lich, den Zustand (also gestar­tet oder ange­hal­ten) zu über­wa­chen.

Die ande­re Dekla­ra­ti­on ist für ein Memo­ryStream Objekt. Der Puf­fer des Mikro­fons wird kon­ti­nu­ier­lich in den Memo­ryStream geschrie­ben, bis die Auf­nah­me abge­spielt wer­den soll. In die­sem Moment über­ge­ben wir den Inhalt des Memo­ryStream zum Abspie­len an das Objekt Sound­Ef­fec­t­In­stan­ce.

Initia­li­sie­rung:

Der wesent­li­che Punkt hier ist die Game Loop, die wir mit Hil­fe eines Dispatcher­Ti­mer erstellt haben. Die­se Schlei­fe ist für die Auf­nah­me von Ton des Mikro­fons essen­ti­ell.

Das Bild für den Play But­ton set­zen wir abhän­gig von der Farb­ein­stel­lung des Tele­fons.

Jetzt set­zen wir auch die Wer­te für das Mikro­fon wie folgt:

Die Dau­er des Puf­fers set­zen wir auf eine hal­be Sekun­de und rufen dann GetSam­ple­Si­zeIn­Bytes mit der Dau­er des Puf­fers, um die Grö­ße in Bytes zu bestim­men. Das ist wich­tig für eine stö­rungs­freie Auf­nah­me.

Wir ver­ka­beln den Event Buf­fer Rea­dy und set­zen das Bild für das ange­hal­te­ne Mikro­fon.

Ton auf­neh­men:

Wenn der Benut­zer auf den Mikro­fon But­ton drückt, wird der fol­gen­de Code aus­ge­führt:

Hier pas­sie­ren meh­re­re Din­ge:

  1. Das Mikro­fon nimmt gera­de nicht auf: Wenn das Mikro­fon ange­hal­ten ist, müs­sen wir die Auf­nah­me star­ten. Wir set­zen zunächst den Hin­ter­grund des But­tons. Dann set­zen wir den Memo­ryStream zurück um eine vor­he­ri­ge Auf­nah­me zu löschen. Wei­ter­hin prü­fen wir, ob wir eine vor­he­ri­ge Auf­nah­me haben. Wenn ja, hal­ten wir die Wie­der­ga­be die­ser Auf­nah­me an.

    Im Wesent­li­chen müs­sen wir Microphone.Start() auf­ru­fen. Der Rest des Codes hat eher mit der UI und dem kor­rek­ten Ver­hal­ten der Anwen­dung zu tun.

  2. Das Mikro­fon nimmt gera­de auf: Vor Allem müs­sen wir die Auf­nah­me been­den. Wie oben schon erwähnt, kön­nen wir Microphone.Stop nicht sofort auf­ru­fen, da die auf­ge­nom­me­nen Daten noch nicht in den Memo­ryStream über­tra­gen wur­den. Wir ver­wen­den also boole­an Varia­blen, um das Anhal­ten der Auf­nah­me in den Dispatcher­Ti­mer Event zu ver­schie­ben.

Hier müs­sen zwei Din­ge pas­sie­ren. Zunächst müs­sen wir den Micro­pho­ne Buf­fer Rea­dy Event feu­ern las­sen, um das letz­te Stü­cken der Auf­nah­me ein­zu­sam­meln. Dann müs­sen wir die Wie­der­ga­be star­ten. Wir machen das wie folgt:

Im Buf­fer Rea­dy Event prü­fen wir mit Hil­fe unse­rer boole­an Varia­ble, ob die Auf­nah­me ange­hal­ten wur­de. In die­sem Fall rufen wir Stream.Flush(). Damit wer­den die rest­li­chen Daten in den Memo­ryStream geleert. Dann kön­nen wir das Mikro­fon anhal­ten.

Wir kön­nen in die­sem Event aller­dings nicht die Wie­der­ga­be star­ten. Dies machen wir im Dispatcher­Ti­mer Tick Event wie folgt:

Der Tick Event wird alle 33ms auf­ge­ru­fen. Er wird also recht kurz nach dem Drü­cken auf Play gefeu­ert wer­den. Der Benut­zer wird die Ver­zö­ge­rung (fast) nicht wahr­neh­men. Der Vor­teil ist natür­lich, dass wir die gesam­te Auf­nah­me wie­der­ge­ben kön­nen und nicht das Ende abschnei­den müs­sen.

Wir prü­fen, ob es Zeit zur Wie­der­ga­be ist und ob der Stream geleert wur­de. Wenn ja, star­ten wir einen neu­en Thread zur Wie­der­ga­be.

Wir star­ten die Wie­der­ga­be auf einem ande­ren Thread, um der Benut­zer­schnitt­stel­le wei­ter­hin Aktua­li­sie­run­gen zu ermög­li­chen. Das wie­der­um bedeu­tet, dass jeder Code, der in unse­rer Wie­der­ga­be­rou­ti­ne auf UI Ele­men­te zugrei­fen will, Dispatcher.BeginInvoke auf­ru­fen muss.

Wie­der­ga­be:

Wir erstel­len ein Objekt der Klas­se Sound­Ef­fec­t­In­stan­ce und füt­tern Sie mit dem auf­ge­nom­me­nen Audio-Stream, der Abtast­ra­te des Mikro­fons und dem Audio­ka­nal.

Damit unse­re Sli­der für Laut­stär­ke, Höhe und Balan­ce auf einem ande­ren Thread leben, ver­wen­den wir Dispatcher.BeginInvoke.

Zuletzt rufen wir Play.

Zusammenfassung

Wir könn­ten unse­re Anwen­dung erwei­tern, indem wir die Auf­nah­me im Iso­la­ted Sto­rage able­gen und den Benut­zer einen Namen dafür ange­ben las­sen. Wir könn­ten wei­ter­hin eine Lis­te der im Iso­la­ted Sto­rage gespei­cher­ten Auf­nah­men anzei­gen. Damit hät­ten wir fast eine voll­stän­di­ge Anwen­dung für Sprach­no­ti­zen.

Die grund­le­gen­den Schrit­te zur Ton­auf­nah­me sind:

  • Fan­gen Sie den Event des Mikro­fons um Ton auf­zu­neh­men.
  • Schrei­ben Sie die Auf­nah­me in einen Stream.
  • Wenn der Benut­zer die Auf­nah­me anhält, rufen Sie Flush des Streams und spei­chern Sie ihn oder geben Sie ihn wie­der.

Um die Bei­spiel­an­wen­dung mit dem gesam­ten Code die­ses Arti­kels her­un­ter­zu­la­den, drü­cken Sie auf den Down­load Code But­ton:

Mor­gen wird Jeff Fans­ler die Klas­se Media Libra­ry behan­deln. Damit kön­nen wir auf die Musik­bi­blio­thek des Anwen­ders zugrei­fen.

Bis dahin!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert