Xbox-Programmierung mit Sound und neuen Features

Xbox gibt Laut (Teil 2)
Kommentare

Ton mit Raum
Wer gern 3-D-Egoshooter spielt, weiß über den Wert guter Kopfhörer Bescheid: Nur mit ihnen kann man hören, wenn sich der Feind von hinten oder der Seite anschleicht. Die Xbox kann dreidimensionalen

Ton mit Raum

Wer gern 3-D-Egoshooter spielt, weiß über den Wert guter Kopfhörer Bescheid: Nur mit ihnen kann man hören, wenn sich der Feind von hinten oder der Seite anschleicht. Die Xbox kann dreidimensionalen Sound erzeugen. Zeit, sich das einmal näher anzusehen: Das Beispiel Xbox3603DSound ist aus Gründen der leichteren Handhabbarkeit nicht grafisch. Sein Konzept ist simpel: Ein in der Mitte des dreidimensionalen Raums sitzender User wird von einer Tonquelle beschallt, die er mit den drei Steuerkreuzen im Raum verschieben kann.

Wer einen dreidimensionalen Toneffekt auf die Spieler loslassen will, braucht neben den schon vorher beschriebenen SoundEffect– und SoundEffectInstance-Klassen zusätzlich zumindest eine Instanz vom Typ AudioListener und eine Instanz vom Typ AudioEmitter. Der Listener spielt dabei die Rolle des Empfängers, während der Emitter als Schallquelle fungiert. Zusätzlich braucht man einen Vector3, der die Position des Emitters (oder des Listeners) im Raum angibt.

Am besten ist es, wenn man diese Klassen wieder als Member-Variablen der Game-Klasse definiert (Listing 7).

Listing 7

public class Game1 : Microsoft.Xna.Framework.Game
{
  Vector3 myAudioSourcePosition;
  AudioEmitter myEmitter;
  AudioListener myListener;
  SoundEffect myBallSound;
  SoundEffectInstance myBallInstance;
  SpriteFont myFont;
//In LoadContent() initialisieren wir die Klassen:
//Playback vorbereiten
myAudioSourcePosition = new Vector3(0, 0, 0);
myBallSound = Content.Load("Xylo");
myBallInstance = myBallSound.CreateInstance();
myBallInstance.IsLooped = true;
myEmitter = new AudioEmitter();
myEmitter.Position = myAudioSourcePosition;
myListener = new AudioListener();
myListener.Position = myAudioSourcePosition;
myBallInstance.Apply3D(myListener, myEmitter);

//Playback starten
myBallInstance.Play();  

Die mit Content.Load beginnenden Zeilen bedürfen keiner weiteren Erklärung. Der Soundeffekt wird diesmal zum „Loopen“ angewiesen, sodass der Ping-Ton permanent erklingt.
Interessant ist auch die Vorgehensweise beim Erstellen von Emitter und Listener: Sie werden leer erstellt und bekommen dann einen Position-Vektor zugewiesen. Bevor der Soundeffekt gestartet wird, rufen wir die Methode Apply3D auf. Sie weist den SoundEffekt an, künftig die Beziehung zwischen Emitter und Listener zu berücksichtigen.

Wichtig ist, dass der zugrunde liegende SoundEffect für diese Berechnung ins Monoformat umgewandelt wird. Das heißt, dass es vollkommen sinnlos ist, 3-D-Soundeffekte aus in Stereo vorliegenden Daten zu generieren. Wer Mono verwendet, spart übrigens 50 Prozent Speicherplatz.

In der Funktion Update() wird die Position der Joysticks abgefragt und die Werte werden im dreidimensionalen Vektor entsprechend angepasst, wie in Listing 8 zu sehen ist.

Listing 8

GamePadState gs = GamePad.GetState(PlayerIndex.One);if (gs.DPad.Down == ButtonState.Pressed)
{
  myAudioSourcePosition.X = myAudioSourcePosition.X - 0.1f;
}
if (gs.DPad.Up == ButtonState.Pressed)
{
  myAudioSourcePosition.X = myAudioSourcePosition.X + 0.1f;
}
Vector2 myLeftVect = gs.ThumbSticks.Left;
myAudioSourcePosition.Y += myLeftVect.Y * 0.1f;
Vector2 myRightVect = gs.ThumbSticks.Right;
myAudioSourcePosition.Z += myRightVect.Y * 0.1f;

myEmitter.Position = myAudioSourcePosition;

myBallInstance.Apply3D(myListener, myEmitter);  

Hier ist an sich alles Standard-XNA. Wichtig ist nur, dass die Funktion Apply3D nach jeder Anpassung der Parameter von Listener und Emitter aufgerufen werden muss. Das Ausgeben der Werte auf dem Bildschirm in Draw() bedarf nur insofern weiterer Erklärung, als der Begriff des SpriteFont vielleicht schon in Vergessenheit geraten ist.

Ein SpriteFont ist eine Schriftart, die anstatt aus Vektorinformationen aus so genannten Sprites (also Bitmaps) besteht. Visual Studio berechnet SpriteFonts während der Kompilation aus auf der lokalen Maschine befindlichen TTF-Fonts. Dabei muss man natürlich die Lizenzbedingungen beachten.

This is my Sound

Obwohl es sowohl energietechnisch als auch finanziell grober Unfug ist, eine Xbox 360 als MP3-Player einzusetzen, ist dies doch problemlos möglich. Mehr als nur ein User hat daher eine Truppe von MP3-Dateien auf seiner Konsole. Das XNA Media API erlaubt den Zugriff auf Inhalte, die auf der Konsole gespeichert sind. Hier dürfte in nicht allzu langer Zeit eine Erweiterung kommen. Deshalb wollen wir den Zugriff auf gespeicherte Medieninhalte hier kurz ansprechen. Zum Nachverfolgen des Beispiels XboxMP3 brauchen Sie eine Xbox 360, die Musikdateien enthält (nicht auf einem externen Speichermedium). Der effizienteste Weg dorthin führt über eine normale Audio-CD. Sie wird ins Laufwerk der Xbox eingelegt. Dann klickt man auf PLAY CD und danach auf RIP CD. Die Xbox rippt die Inhalte der Audio-CD daraufhin auf die Festplatte. Sind auf der CD schon Metadaten vorhanden, werden sie gleich mit eingepflegt.

Nachdem der Ripping-Prozess abgeschlossen ist, können wir auf die Tondateien über das MediaLibrary-Objekt zugreifen. Es bietet eine Gruppe von Arrays an, die verschiedene Ansichten auf das auf der Konsole befindliche Medienmaterial erlauben. Will man einfach nur ein beliebiges Musikstück abspielen, benutzt man das Array Songs. Das kann man beispielsweise mit diesem Codeschema vollbringen:

using (MediaLibrary library = new MediaLibrary())
{
  SongCollection songs = library.Songs;
  Song song = songs[0];
  MediaPlayer.Play(song);
}  

Unser Beispiel kann allerdings etwas mehr: Es erlaubt dem Benutzer aus den auf der Konsole befindlichen Alben und den in ihnen enthaltenen Liedern frei zu wählen. Deshalb brauchen wir als erstes zwei globale Indices. Sie geben die Position im Musik-Array an. Mit dem Controller können sie verschoben werden. Dieser Teil des Codes ist nach der Lektüre dieses Artikels selbsterklärend und bedarf keiner weiteren Beschreibung. Interessant ist hingegen das Anzeigen der Informationen auf dem Bildschirm. Es passiert mit dem Code aus Listing 9, der in Draw() aufgerufen wird.

Listing 9

spriteBatch.Begin();
spriteBatch.DrawString(myFont, myMediaLibrary.Albums[myAlbumCounter].Name, new Vector2(20, 20), Color.DeepPink);
spriteBatch.DrawString(myFont, myMediaLibrary.Albums[myAlbumCounter].Songs[myFileCounter].Name, new Vector2(20, 220), Color.DeepPink);
spriteBatch.End();  

Hier gibt es eigentlich nicht viel zu sehen: Das MediaLibrary-Objekt wird Schritt für Schritt zerparst, um an Daten über die auf der Konsole liegenden Daten zu kommen. Will man eine der ausgewählten Dateien abspielen, verfährt man analog zum Hintergrundmusikbeispiel, das wir bereits besprochen haben.

So weit, so witzig – leider hat der Autor in seinem Unternehmen eine Mitarbeiterin, die überaus gerne südamerikanische Musik hört. Aus diesem Grund sah er eines Tages die in Abbildung 1 gezeigte Fehlermeldung beim Debuggen seiner Anwendung.

Abb. 1: Hier fehlt ein Zeichen
Abb. 1: Hier fehlt ein Zeichen

Der Grund dafür ist, dass lateinamerikanische Musiker gerne Zeichen verwenden, die nicht Teil des ASCII-Zeichensatzes sind. Da SpriteFonts bekanntlich aber nur den ASCII-Zeichensatz abdecken, treten solche Fehler in medienwiedergebenden Anwendungen immer wieder auf.

Doch auch dafür gibt es eine Lösung: Durch manuelles Editieren der .spritefont-Datei kann man die Anzahl der inkludierten Zeichen erhöhen. Im Fall der Lateinamerikanerin genügte es, den oberen Grenzwert von 126 auf 255 zu erhöhen:


  
     
    Ā
  
  

Wie bereits erklärt, sind Sprite Fonts Bitmaps, die für jedes Zeichen einen Sprite enthalten. Durch das Erhöhen der Inklusionsreichweite werden mehr Sprites generiert. Das vergrößert zwar die Zeichenauswahl, verlängert dadurch aber auch Zug um Zug die Kompilationsdauer und die Größe der fertigen Binärdatei. Weitere Informationen zum Festlegen der Ranges, spezifisch auch für Japan, findet man hier [5]. Dieses XNA API funktioniert auch auf dem PC. Dort dient die Medienbibiliothek des Windows Media Player als Datenquelle. Hat der Benutzer keine Musik in sie eingepflegt, geht er leer aus.

XACTer Aufwand

In großen Spieleprojekten wird recht gern ein XACT genanntes Tool verwendet. Es ist Teil der XNA-Umgebung und findet sich auf dem Rechner im Startmenü unter MICROSOFT XNA GAME STUDIO 4.0 REFRESH | TOOLS | MICROSOFT CROSS-PLATFORM AUDIO CREATION TOOL 3 (XACT3). Hinter dem seltsamen Namen verbirgt sich ein Programm zur Erstellung von Soundeffekten durch Nicht-Programmierer. Besonders attraktiv ist XACT also für all jene, die einen gelangweilten Tontechniker im Unternehmen sitzen haben. Die Idee dahinter ist, dass der Tontechniker Tondateien und die zu ihnen gehörenden Effekte in so genannten Cues zusammenfasst. Diese werden danach vom Programmierer ausgelöst. Da wir von Hand Ähnliches erreichen (und XACT am Windows Phone 7 nicht unterstützt wird), endet dieser Absatz hier. Interessierte finden unter [6] oder in einem späteren Teil der Serie mehr! In diesem Sinne, machen Sie’s gut – bis zum nächsten Mal (vielleicht dann mit XACT)!

Tam Hanna befasst sich seit der Zeit des Palm IIIc mit Programmierung und Anwendung von Handcomputern. Er entwickelt Programme für diverse Plattformen, betreibt Onlinenewsdienste zum Thema und steht unter tamhan@tamoggemon.com für Fragen, Trainings und Vorträge gern zur Verfügung.
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -