Dieser Artikel wurde maschinell übersetzt.

Touch and Go

Abspielen von Audiodateien in Windows Phone

Charles Petzold

Charles PetzoldWenn ich zuerst Lese, dass die Erweiterungen Windows Phone OS 7.1 eine Möglichkeit für Anwendungen enthalten, Klang und Musik-Dateien im Hintergrund zu spielen, dachte ich, "schon Don't wir?"

Es stellt sich heraus, ich war richtig, aber nur ein wenig.Es ist in der Tat möglich, für eine Windows Phone OS 7.0-Anwendung, eine Musik-Datei im Hintergrund, aber nur in sehr speziellen Fall zu spielen.In allen anderen Fällen wird eine Musikdatei, die Ihre Windows Phone OS 7.0-Anwendung spielt beendet, wenn Ihre Anwendung in den Hintergrund verschoben wird.Dieses Verhalten ist natürlich für die meisten Anwendungen, durchaus angebracht und wahrscheinlich genau das, was Sie wollen.

Aber betrachten Sie eine Anwendung, die Musik auf Ihrem Telefon neben normalen Musikbibliothek des Telefons liefert.Für solch eine Bewerbung ist es äußerst wünschenswert, weiterzuspielen, während andere Anwendungen belegen die Vordergrund- oder wenn der Bildschirm ein Timeout und in einer gesperrten Zustand geht.Und auch für diejenigen von uns, die Notwendigkeit, eine solche Anwendung schreiben haben, bietet diese Anlage eine lustige Einstieg in die neue Welt der "Hintergrund-Agents" in Windows Phone OS 7.1 eingeführt.

In der nächsten Ausgabe werde ich Ihnen zeigen, wie ein Windows Phone Programm geschrieben, die Musik-Dateien im Hintergrund spielt.Aber um ein umfassenderes Bild der audio-Einrichtungen zur Windows Phone zu geben, ich möchte in dieser Spalte mit mehr Standardmethoden zum Abspielen von audio Dateien in Windows Phone OS 7.0 sowie Version 7.1 unterstützt beginnen.

MediaElement und seine Quellen

Die gängigste Methode für ein Silverlight-Programm zum Wiedergeben einer Musik oder sound-Datei ist mit MediaElement.Nichts ist einfacher: MediaElement leitet sich von FrameworkElement, also können Sie es in der visuellen Struktur einer XAML-Datei und legen Sie nur die Source-Eigenschaft auf eine URL:

<MediaElement Source="http://www.SomeWebSite.com/CoolSong.mp3" />

Wenn die XAML-Datei geladen wird, wird die Musik-Datei automatisch abgespielt. MediaElement unterstützt MP3, WMA und WAV-Dateien. Informationen sind dokumentiert bei msdn.microsoft.com/library/ff462087(VS.92).

Als Alternative zum Verweisen auf eine Datei über das Internet können Sie eine Sound oder Musik-Datei in die ausführbare Datei der Anwendung einbetten. Fügen Sie die Datei an das Programm in Visual Studio und kennzeichnen Sie die Build Action als Inhalt oder Ressource. (Inhalt wird bevorzugt und bettet die Datei in der XAP-Datei; mit Ressourcen wird die Datei in der DLL für das Programm eingebettet.) Legen Sie die Source-Eigenschaft auf eine URL verweisen auf den Dateinamen mit einem Ordnernamen falls zutreffend:

<MediaElement Source="Music/LocalSong.wma" />

Obwohl MediaElement sehr einfach sein kann, gibt es zahlreiche Möglichkeiten, um es mehr kompliziert.Eine Möglichkeit ist an die audio-Datei zur Laufzeit, wie ich in das MediaElementDemo-Programm, das der herunterladbare Code für diesen Artikel gehört.

In diesem Programm das MediaElement ist noch in der visuellen Struktur, aber die Source-Eigenschaft ist nicht festgelegt und AutoPlay auf False festgelegt ist.Media­ElementDemo können Sie die drei Sätze in Brahms Violinkonzert spielen.(Die Dateien werden aus dem Internet Archiv auf archive.org/­Informationen/BrahmsViolinConcerto-Heifetz.Es ist eine 1939 Leistung mit der Geigerin Jascha Heifetz und Sergei Kussewizki Dirigieren, ursprünglich auf Victor 78 u/min Festplatten verfügbar.) Drei RadioButton-Elementen haben ihre Tageigenschaften auf die Quellen aus den drei Musikdateien festgelegt.Für den ersten RadioButton ist die vollständige URL der Musikdatei auf der Website Internet-Archiv.Für den zweiten Satz ich nachgeladen die Musikdatei (mit 02Ii.Adagio.mp3) auf meinem PC, einen Ordner mit dem Namen Musik im Projekt in Visual Studio erstellt und diese Datei dem Ordner hinzugefügt.Die zweite RadioButton verweist auf die Datei mit dem Namen "Music/02Ii.Adagio.mp3." Wenn eines dieser zwei Schaltflächen aktiviert ist wird, der Ereignishandler erhält die Tag-Eigenschaft und erstellt ein Uri-Objekt aus der es (unter Angabe typeof für den Webverweis und UriKind.Relative für den Inhalt) und legt fest, die für die Source-Eigenschaft des MediaElement.

Der zweite Satz ist eine Datei von über 4,5 MB, und natürlich es erhöht sich die Größe der ausführbaren Datei durch eine beträchtliche Masse.Hinzufügen von Dateien dieser Größe zu der ausführbaren Datei ist nicht empfohlen und erfolgt hier nur zu Demonstrationszwecken!

Wenn Ihre Anwendung Dateien dieser Größe, ist ein möglichen Kompromisses zur Verfügung: Die Anwendung konnte die Datei einmal über das Internet downloaden und in isoliertem Speicher speichern.Das ist, was ich getan habe für der dritte Satz des Violinkonzertes.Die dritte RadioButton (die wird ein Name zugewiesen "IsoStoreRadio­Schaltfläche") hat die IsEnabled-Eigenschaft zunächst auf False festgelegt.Abbildung 1 zeigt den Download-Prozess.In der Page-Konstruktor wenn die Datei im isolierten Speicher ist nicht initiiert WebClient eine Hintergrund-Übertragung.Wenn die Übertragung abgeschlossen ist, wird die Datei isolierten Speicher gespeichert und RadioButton aktiviert ist.

Abbildung 1 eine Webdatei auf isolierten Speicher herunterladen

public MainPage()
{
  InitializeComponent();
  // ...
// Check if file is in Isolated Storage; otherwise start downloading it
  using (IsolatedStorageFile isoStore =
    IsolatedStorageFile.GetUserStoreForApplication())
  {
    if (isoStore.FileExists(isoStoreRadioButton.Tag as string))
    {
      isoStoreRadioButton.IsEnabled = true;
    }
    else
    {
      WebClient webClient = new WebClient();
      webClient.OpenReadCompleted += OnWebClientOpenReadCompleted;
      webClient.OpenReadAsync(new Uri("http://www.archive.org/....mp3"));
    }
  }
  // ...
}
// When the music file is downloaded, save it to Isolated Storage
void OnWebClientOpenReadCompleted(object sender, 
  OpenReadCompletedEventArgs args)
{
  if (!args.Cancelled && args.Error == null)
  {
    Stream inpStream = args.Result;
    byte[] buffer = new byte[inpStream.Length];
    inpStream.Read(buffer, 0, buffer.Length);
    using (IsolatedStorageFile isoStore =
      IsolatedStorageFile.GetUserStoreForApplication())
    {
      string isoPathName = isoStoreRadioButton.Tag as string;
      string isoDirName = Path.GetDirectoryName(isoPathName);
      if (!isoStore.DirectoryExists(isoDirName))
      {
        isoStore.CreateDirectory(isoDirName);
      }
      using (IsolatedStorageFileStream isoStream =
        isoStore.CreateFile(isoPathName))
      {
        isoStream.Write(buffer, 0, buffer.Length);
        isoStoreRadioButton.IsEnabled = true;
      }
    }
  }
}

In einigen Kontexten auf Windows Phone OS 7.1 können Sie einen URI mit dem Präfix "Isostore" Verweis auf eine Datei im isolierten Speicher, aber dies funktioniert für MediaElement. Glücklicherweise Media­Element verfügt über eine SetSource-Eigenschaft, die ein Stream-Objekt akzeptiert. Abbildung 2zeigt, wie der aktivierte Handler für den RadioButton-Elementen behandelt diese Unterschiede.

Abbildung 2 Festlegen von der Quelle für MediaElement

void OnRadioButtonChecked(object sender, RoutedEventArgs args)
{
  RadioButton radioButton = sender as RadioButton;
  string uriString = radioButton.Tag as string;
  // Save index for tombstoning
  radioButtonIndex = radioButtonPanel.Children.IndexOf(radioButton);
  if (radioButton == isoStoreRadioButton)
  {
    // Call SetSource on MediaElement using Isolated Storage stream.
using (IsolatedStorageFile storage =
      IsolatedStorageFile.GetUserStoreForApplication())
    {
      using (Stream isoStream = storage.OpenFile(uriString, FileMode.Open))
      {
        mediaElement.SetSource(isoStream);
      }
    }
  }
  else
  {
    // Set Source property on MediaElement using URI
    Uri uri = new Uri(uriString, uriString.Contains(':')
      ?
UriKind.Absolute : UriKind.Relative);
    mediaElement.Source = uri;
  }
}

Transporte und Grabsteine

Eine weitere Möglichkeit Sie MediaElement für sich selbst noch schwieriger machen können ist durch Hinzufügen von Steuerelementen zum Anhalten und bewegen an den Anfang oder das Ende der Datei. Noch mehr Spaß ist ein Slider-Steuerelement, mit dem Sie zu einer bestimmten Position in der Datei bewegen wie in gezeigt Abbildung 3.

The MediaElementDemo Program
Abbildung 3 das MediaElementDemo-Programm

Die vier ApplicationBar-Tasten sind sehr einfach implementiert. Bzw. Legen sie die Position-Eigenschaft des MediaElement auf 0 (null), rufen Sie die Play-Methode des MediaElement, rufen Sie die Pause-Methode und die Position-Eigenschaft auf die NaturalDuration-Eigenschaft festgelegt.

Das schwierige Teil ist aktivieren und Deaktivieren von Schaltflächen. Für diese Aufgabe ist das CurrentStateChanged-Ereignis des MediaElement behandelt. Wenn Sie MediaElement Logik arbeiten, ist es hilfreich zuerst, Debug.WriteLine verwenden bei Handler um ein Gefühl für wie die CurrentState-Eigenschaft ändert, während eine Musik-Datei geladen wird, gepuffert, angehalten und endete gespielt.

Telefonieren werden alle Musik- und sound-Dateien durch ein einziges Stück Software und Hardware die Zune Media Warteschlange bezeichnet gespielt. Verwenden Sie die Standardanwendung Musik + Videos auf dem Handy einen Song oder ein Album aus Ihrer Musiksammlung zu spielen, dass Musik wird weiterhin im Hintergrund wiedergegeben, wenn Sie, dass die Anwendung verlassen und Sie andere Anwendungen starten – und selbst wenn Sie das MediaElementDemo-Programm starten. Wenn Sie eine der Bewegungen der Brahms Violinkonzert zu spielen beginnen, wird jedoch die Hintergrundmusik beendet. Jetzt ist MediaElementDemo im Steuerelement.

Aber wenn MediaElementDemo Vordergrund verlässt —, ob der Benutzer durch Drücken der Schaltfläche "Start" oder lassen den Bildschirm Timeout – Brahms wird beendet, auch wenn das Programm nicht als veraltet gekennzeichnet ist.

In solch einer Situation was soll geschehen, wenn der Benutzer auf das Programm zurückkehrt? Wenn die Antwort ist "Nichts", haben Sie Glück! Aber wenn Sie die Musik wieder aufgenommen wollen werden, wo sie aufgehört, MediaElementDemo veranschaulicht, wie dies geschehen kann. In seiner OnNavigatedFrom-Überschreibung speichert das Programm den Index der Bewegung spielt, der Staat (wahrscheinlich spielen oder angehalten) und die Position. In OnNavigatedTo das Programm überprüft die RadioButton und legt die Status und Position im MediaOpened-Ereignishandler.

Mediathek und MediaPlayer

Ich erwähnte, dass vor dem Windows Phone OS 7.1, existierten eine Anlage bereits bestimmte Musik-Dateien auf dem Telefon im Hintergrund spielen. Der Haken ist, dass diese Musikdateien Teil des Telefons Musikbibliothek sein müssen. Ihr Programm kann eines dieser Lieder spielen, oder es kann alle Songs auf ein Album oder alle Titel eines bestimmten Interpreten oder Genre, oder alle Songs in einer Playlist spielen.

Die Klassen, dies zu tun sind Mitglieder des Microsoft.Xna.Framework.Media-Namespace. Diese XNA-Klassen in Silverlight-Projekten für das Telefon verwenden, müssen Sie zuerst einen Verweis auf die Microsoft.Xna.Framework-Bibliothek hinzufügen. Mit Windows Phone OS 7.0 gab Ihnen Visual Studio eine Warnung über das tun dies. Diese Warnung ist mit Windows Phone OS 7.1 gegangen.

Jedes Silverlight-Programm, das XNA-Klassen verwendet, um Musik zu spielen umfaßt eine spezielle Klasse, die implementiert IApplicationService und ruft FrameworkDispatcher.Update alle 30 Sekunden. Sie können diese Klasse alle gewünschten Namen geben, aber Sie werde es in der Datei App.xaml im Abschnitt ApplicationLifetimeObjects verweisen:

<local:XnaFrameworkDispatcherService />

Um ein Lied aus der Benutzer-Musikbibliothek zu spielen, zunächst Instanziierung der Klasse MusicLibrary. Eigenschaften mit dem Namen Künstler, Alben, Genres und Wiedergabelisten bieten Sammlungen von Objekten des Typs Künstler, Album, Genre und Playlist, und diese Klassen enthalten eine Songs-Eigenschaft vom Typ SongCollection, die eine Auflistung von Song-Objekten ist. (Diese Sammlungen sind schreibgeschützt; Ihre Anwendung kann nicht alles, was der Benutzer Musikbibliothek hinzufügen oder in irgendeiner Weise ändern.)

Verwenden Sie anfangen zu spielen etwas, Mitglieder der MediaPlayer-Klasse. Die MediaPlayer.Play-Methode akzeptiert ein Song-Objekt, ein SongCollection oder eine SongCollection mit einem Index an das Lied, um zu starten.

Das PlayRandomSong-Programm enthält eine Schaltfläche mit der Bezeichnung "Random Song spielen", und wenn Sie, die klopfen, der folgende Code führt:

void OnButtonClick(object sender, RoutedEventArgs args)
{
    MediaLibrary mediaLib = new MediaLibrary();
    AlbumCollection albums = mediaLib.Albums;
    Album album = albums[random.Next(albums.Count)];
    SongCollection songs = mediaLib.Songs;
    Song song = songs[random.Next(songs.Count)];
    MediaPlayer.Play(song);
}

Dieser Code extrahiert ein zufälliges Album aus Ihrer Sammlung, eine zufällige Songs aus diesem Album und beginnt, es zu spielen.(Der Windows Phone-Emulator enthält ein Album mit ein paar kleinen Song-Dateien, so dass dieses Programm auf dem Emulator einwandfrei ausgeführt wird).

Wenn Sie ein Lied zu spielen mit PlayRandomSong starten, finden Sie, dass Sie navigieren Sie von dem Programm oder sogar beenden das Programm und das Lied spielen.Es ist genau das, als ob Sie diesen Song aus dem Telefon regelmäßige Musikvideos + Anwendung spielten — und wenn Sie die Anwendung starten, sehen Sie das Cover des Albums und der Titel.Darüber hinaus drücken Sie die STRG-Taste Volume am Telefon, Sie sehen das Lied auf der Oberseite des Bildschirmes und greifen Sie auf Schaltflächen zum Anhalten oder gehen Sie zum Anfang oder Ende des Liedes.

Wie das Telefon + Musikvideos Anwendung welches Lied Sie mit MediaPlayer.Play gespielt haben weiß, kann Ihre Anwendung welches Lied bestimmen des Telefons Musikvideos + Anwendung zurzeit spielt.Diese Informationen sind von der Warteschlange-Eigenschaft des MediaPlayer, der ein MediaQueue-Objekt bereitstellt, der das Lied spielt und eine Sammlung von Liedern angibt, wenn ein Album oder eine Wiedergabeliste wiedergegeben wird.Das PlayRandomSong-Programm verwendet einen Timer zum Überprüfen der ActiveSong-Eigenschaft der Warteschlange und zeigt Informationen über das Lied.Alternativ können Sie Handler für das ActiveSongChanged-Ereignis des MediaPlayer festlegen.

Erstellen von Song-Objekten

Das PlayRandomSong-Programm erhält ein Song-Objekt aus einer der Eigenschaften oder Sammlungen der Mediathek, aber Song hat auch eine statische Eigenschaft namens FromUri, die eine Song-Eigenschaft basierend auf einer Datei nicht in Ihrer Musik-Bibliothek erstellt.Dieser URI kann eine Musik-Datei verweisen, über das Internet oder das ist Teil des Programms XAP-Datei.(Es kann nicht auf eine Datei im isolierten Speicher verweisen.) MediaPlayer können Sie dann dieses Objekt Song spielen.(Sie können nicht Ihre eigenen SongCollection-Objekte erstellen.)

Das MediaPlayerDemo-Programm zeigt, wie es gemacht wird.Dieses Programm können Sie das Brahms Doppelkonzert (ein weiteres 1939 Aufnahme aus archive.org/details/BrahmsDoubleConcerto_339) spielen mit Heifetz wieder, Emanuel Feuermann Cello und Eugene Ormandy durchführen.Da Sie MediaPlayer mit isolierten Speicher verwenden können, sind die ersten und letzten Bewegungen Webverweise.

Ein weiterer Unterschied ist, dass die Position-Eigenschaft des MediaElement gettable und einstellbar, während die PlayPosition-Eigenschaft des MediaPlayer nur get fähiges ist.Daher sind die beiden ApplicationBar-Schaltflächen, die bis zum Anfang und Ende der Strecke gehen.Auch, gibt es anscheinend keine Möglichkeit, die Dauer der ein Song-Objekt erstellt auf diese Weise, so dass der Schieberegler auch irrelevant ist.Ich habe auch die Markierung als veraltet-Logik von dieses Programm entfernt, weil es nicht möglich ist, einen Track starten, wo Sie weg verließen.

Da MediaPlayer ein Song-Objekt entnommen Musikbibliothek des Telefons im Hintergrund spielt, könnte auch ein Song-Objekt im Hintergrund spielen gewünscht.Es ist nicht möglich.In dieser Hinsicht ist MediaPlayer wie MediaElement.Die Musik stoppt, sobald Sie die Anwendung verlassen.Jedoch, wenn Sie weg von der MediaPlayerDemo Programm navigieren und es nicht als veraltet gekennzeichnet ist — die so oft mit Windows Phone OS 7.1 — die Musik nur ausgesetzt.Wenn Sie zurück zu der Anwendung navigieren, nimmt er an dem er unterbrochen.

Ich denke, wenn Sie Kreide bis die Vorteile und Nachteile, die Silverlight-MediaElement ist ein wenig vor der XNA MediaPlayer, aber das Auto­matic Wiederaufnahme der Wiedergabe ist ein sehr nettes Feature MediaPlayer.

Streaming und darüber hinaus

Ich habe diskutiert Wiedergabe von gemeinsame Audio- und Musik-Dateien in WMA und MP3-Formate.Windows Phone können auch ein Programm, um Ton innerhalb der Anwendung dynamisch generieren.Im Rahmen der Windows Phone Programmierung ist dies bekannt als "streaming". Ich zeigte ein Ansatz in das SpeakMemo-Programm in meinem Artikel vom Februar 2011 UI Grenzen (msdn.microsoft.com/magazine/gg598930) mithilfe der XNA-DyanamicSoundEffectInstance-Klasse.Sie können auch die MediaStreamSource-Klasse in Silverlight verwenden, um etwas ähnliches zu tun.Dies ist, wie elektronische Musik Synthese auf das Telefon zu implementieren.Auch sind diese jedoch nur von Vordergrund Anwendungen verwendet werden kann.

Windows Phone OS 7.1 ab, das Konzept eines "Hintergrund-Agents" wurde eingeführt, und können Sie diese für die Wiedergabe entweder Musikdateien oder streaming-Audio während Ihr Programm im Hintergrund unterbrochen ist.

In der nächsten Ausgabe werde ich erläutern, wie das gemacht wird.

Charles Petzold ist ein langjähriger Redakteur beim MSDN Magazin. Seiner Website lautet charlespetzold.com.

Dank der folgenden technischen Experten für die Überprüfung dieses Artikels: Mark Hopkins