pixelboyz logo
Desarrollo de Videojuegos

Tutorial MonoGame: Audio

image

Índice de contenido


En este capítulo vamos a ver el uso de audio en XNA. Originalmente, XNA admitía una forma de reproducir audio, usando XACT (herramienta de creación de audio multiplataforma). Desde el lanzamiento inicial, agregaron una API mucho más simplificada. Vamos a echar un vistazo a ambos procesos.

Hay un video HD de este capitulo disponible aquí.

Al reproducir audio, siempre existe el desafío de qué formatos son compatibles, especialmente cuando se trata de múltiples plataformas diferentes, todas las cuales tienen diferentes requisitos. Afortunadamente, la tubería de contenido se encarga de gran parte de las complicaciones para nosotros. Simplemente agregue sus archivos de audio (mp3, mp4, wma, wav, ogg) a la tubería de contenido y hará el resto del trabajo por usted. Sin embargo, como verá en breve, también es posible cargar archivos de audio fuera de la tubería de contenido. En esta situación, tenga en cuenta que ciertas plataformas no son compatibles con ciertos formatos (por ejemplo, no son compatibles con wma en Android o iOS, mientras que iOS no es compatible con ogg pero sí con mp3). A menos que tenga una buena razón, le recomendaría que se apegue a la canalización de contenido para el audio siempre que sea posible.

Los peligros del MP3

Aunque MP3 es compatible con MonoGame, probablemente desee evitar usarlo. ¿Por qué?
Patentes. Si su juego tiene más de 5000 usuarios, es posible que deba legalmente adquirir una licencia. Desde una perspectiva legal, Ogg Vorbis es superior en todos los sentidos. Desafortunadamente, el soporte de Ogg no es tan omnipresente como nos gustaría que fuera.

Adición de contenido de audio mediante el canal de contenido

Este proceso es prácticamente idéntico a agregar un archivo gráfico en su archivo de contenido.

Simplemente agregue el contenido como lo hizo con el botón derecho -> Agregar elementos existentes o el menú Editar:

imagen

Si es un formato compatible, verá que el campo Procesador está lleno (de lo contrario, mostrará Desconocido). La única opción aquí es configurar la calidad de audio mp3, un compromiso entre tamaño y fidelidad.

Reproducir una canción

Ahora veamos el código involucrado en la reproducción de la canción que acabamos de agregar a nuestro juego.

// This example shows playing a song using the simplified audio api

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Example1
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Song song;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            this.song = Content.Load<Song>("prepare");
            MediaPlayer.Play(song);
            //  Uncomment the following line will also loop the song
            //  MediaPlayer.IsRepeating = true;
            MediaPlayer.MediaStateChanged += MediaPlayer_MediaStateChan
                                             ged;
        }

        void MediaPlayer_MediaStateChanged(object sender, System.
                                           EventArgs e)
        {
            // 0.0f is silent, 1.0f is full volume
            MediaPlayer.Volume -= 0.1f;
            MediaPlayer.Play(song);
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            base.Draw(gameTime);
        }
    }
}

Observe que agregamos la declaración de uso Microsoft.Xna.Framework.Media. Dependemos de esto para las clases MediaPlayer y Song. Nuestra canción se carga usando ContentManager tal como lo hicimos antes con Texture, esta vez con el tipo Song. Una vez más, el cargador de contenido no utiliza la extensión del archivo. Nuestra canción se puede reproducir con una llamada a MediaPlayer.Play(). En este ejemplo, conectamos un controlador de eventos MediaStateChanged que se llamará cuando la canción se complete, disminuyendo el volumen y reproduciendo la canción nuevamente.

Reproducción de efectos de sonido

Este ejemplo muestra la reproducción de efectos de sonido. A diferencia de una canción, SoundEffects está diseñado para admitir varias instancias que se reproducen a la vez. Echemos un vistazo a jugar SoundEffect en MonoGame:

// Example showing playing sound effects using the simplified audio 
api
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;
using System.Collections.Generic;

namespace Example2
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        List<SoundEffect> soundEffects;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            soundEffects = new List<SoundEffect>();
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw 
            textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            soundEffects.Add(Content.Load<SoundEffect>("airlockclose"))
                             ;
            soundEffects.Add(Content.Load<SoundEffect>("ak47"));
            soundEffects.Add(Content.Load<SoundEffect>("icecream"));
            soundEffects.Add(Content.Load<SoundEffect>("sneeze"));

            // Fire and forget play
            soundEffects[0].Play();
            
            // Play that can be manipulated after the fact
            var instance = soundEffects[0].CreateInstance();
            instance.IsLooped = true;
            instance.Play();
        }


        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();

            if (Keyboard.GetState().IsKeyDown(Keys.D1))
                soundEffects[0].CreateInstance().Play();
            if (Keyboard.GetState().IsKeyDown(Keys.D2))
                soundEffects[1].CreateInstance().Play();
            if (Keyboard.GetState().IsKeyDown(Keys.D3))
                soundEffects[2].CreateInstance().Play();
            if (Keyboard.GetState().IsKeyDown(Keys.D4))
                soundEffects[3].CreateInstance().Play();


            if (Keyboard.GetState().IsKeyDown(Keys.Space))
            {
                if (SoundEffect.MasterVolume == 0.0f)
                    SoundEffect.MasterVolume = 1.0f;
                else
                    SoundEffect.MasterVolume = 0.0f;
            }
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            base.Draw(gameTime);
        }
    }
}

Tenga en cuenta la declaración de uso de Microsoft.Xna.Framework.Audio al principio. Una vez más, agregamos nuestros archivos de audio usando Content Pipeline, en este caso agregué varios archivos WAV. Se cargan usando Content.Load() esta vez con el tipo SoundEffect. A continuación, es importante tener en cuenta las dos formas diferentes en que se reproducen los SoundEffects. Puede llamar a Play() directamente en la clase SoundEffect. Esto crea una instancia de disparar y olvidar de la clase con opciones mínimas para controlarla. Si necesita un mayor control (como cambiar el volumen, hacer un bucle o aplicar efectos), debe crear una SoundEffectInstance usando la llamada SoundEffect.CreateInstance(). También debe crear una instancia separada si desea que se reproduzcan varias instancias simultáneas del mismo efecto de sonido. Es importante darse cuenta de que todas las instancias del mismo SoundEffect comparten recursos, por lo que la memoria no aumentará de forma masiva para cada instancia creada. La cantidad de sonidos compatibles simultáneos varía de una plataforma a otra, siendo 64 el límite en Windows Phone 8, mientras que Xbox 360 lo limita a 300 instancias. No hay un límite estricto en la PC, aunque obviamente alcanzará las limitaciones del dispositivo lo suficientemente rápido.

En el ejemplo anterior, creamos un único efecto de sonido de bucle de inmediato. Luego, verificamos cada cuadro para ver si el usuario presiona 1, 2, 3 o 4 y reproduce una instancia del efecto de sonido correspondiente. Si el usuario presiona la barra espaciadora, silenciamos o configuramos a todo volumen el MasterVolume global de la clase SoundEffect. Esto afectará a todos los efectos de sonido de reproducción.

Reproducción de audio posicional

Los efectos de sonido también se pueden colocar en el espacio 3D fácilmente en XNA.

// Display positional audio

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;

namespace Example3
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SoundEffect soundEffect;
        SoundEffectInstance instance;
        AudioListener listener;
        AudioEmitter emitter;


        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            
            soundEffect = this.Content.Load<SoundEffect>("circus");
            instance = soundEffect.CreateInstance();
            instance.IsLooped = true;

            listener = new AudioListener();
            emitter = new AudioEmitter();

            // WARNING!!!!  Apply3D requires sound effect be Mono!  
            Stereo will throw exception
            instance.Apply3D(listener, emitter);
            instance.Play();
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();

            if (Keyboard.GetState().IsKeyDown(Keys.Left))
            {
                listener.Position = new Vector3(listener.Position.X-0.
                                    1f, listener.Position.Y, listener.
                                    Position.Z);
                instance.Apply3D(listener, emitter);
            }
            if (Keyboard.GetState().IsKeyDown(Keys.Right))
            {
                listener.Position = new Vector3(listener.Position.X + 
                                    0.1f, listener.Position.Y, 
                                    listener.Position.Z);
                instance.Apply3D(listener, emitter);
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Up))
            {
                listener.Position = new Vector3(listener.Position.X, 
                                    listener.Position.Y +0.1f, 
                                    listener.Position.Z);
                instance.Apply3D(listener, emitter);
            }
            if (Keyboard.GetState().IsKeyDown(Keys.Down))
            {
                listener.Position = new Vector3(listener.Position.X, 
                                    listener.Position.Y -0.1f, 
                                    listener.Position.Z);
                instance.Apply3D(listener, emitter);
            }            
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            base.Draw(gameTime);
        }
    }
}

En este ejemplo, cargamos un solo SoundEffect y comenzamos a repetirlo infinitamente. Luego creamos una instancia de AudioListener y AudioEmitter. AudioListener representa la ubicación de su oído dentro del mundo virtual, mientras que AudioEmitter representa la posición del efecto de sonido. La ubicación predeterminada de ambos es un Vector3 en (0,0,0). Estableces la posición de un SoundEffect llamando a Apply3D(). En nuestra llamada Update(), si el usuario presiona una tecla de flecha, actualizamos la Posición del AudioListener en consecuencia. Después de cambiar la posición de un sonido, debe volver a llamar a Apply3D. A medida que presiona las teclas de flecha, notará que el audio se desplaza y cambia el volumen para corresponder con la posición actualizada. Es muy importante que su archivo de audio de origen esté en formato Mono (a diferencia de Estéreo) si usa Apply3D, o se lanzará una excepción.

Usando XACT

Como se mencionó anteriormente, XACT solía ser la única opción cuando se trataba de programación de audio en XNA. XACT todavía está disponible y le permite a su diseñador de audio tener un control avanzado sobre la música y los efectos de sonido que aparecen en su juego, mientras que el programador usa una interfaz programática simple. Una gran advertencia es que XACT es parte del instalador XNA o parte del Direct X SDK, ya que no está disponible en Mac OS o Linux. Si desea instalarlo pero no tiene instalada una versión anterior de Visual Studio, puede encontrar las instrucciones aquí ( https://www.gamefromscratch.com/post/2015/07/23/Instalación-XNA-Tools-Like-XACT-sin-Visual-Studio-2010.aspx ). Si está en MacOS o Linux, desea apegarse a la API de audio simplificada que mostramos anteriormente.

Xact se instala como parte de la instalación de XNA Studio; en Windows de 64 bits, el ejecutable de Xact se ubicará de forma predeterminada en C:Archivos de programa (x86)Microsoft XNAXNA Game Studiov4.0Tools. Empieza por correr AudConsole3.exe:

imagen

La herramienta de audición XACT debe estar ejecutándose cuando ejecuta la herramienta Xact.

Luego lanza Xact3.exe

imagen

Primero crea un nuevo proyecto:

imagen

A continuación, haga clic con el botón derecho en Wave Banks y seleccione New Wave Bank

imagen

Arrastre y suelte sus archivos de audio de origen en la ventana Wave Bank:

imagen

Ahora cree un nuevo banco de sonidos haciendo clic derecho en Sound Bank y seleccionando New Wave Bank

imagen

Ahora arrastre la onda que desea usar desde el banco de ondas hasta el banco de sonidos.

a1

Ahora cree una Cue arrastrando y soltando el banco de sonidos en la ventana Cue. Si se desea, se pueden agregar varios archivos a una entrada.

a2

Puede cambiar el nombre de la Cue, establecer la probabilidad de reproducción si configura varios Sonidos en la Cue y cambiar las propiedades de instancia de la Cue en la ventana de propiedades a su izquierda:

imagen

Ahora construye los resultados:

imagen

Esto creará dos directorios en la carpeta en la que creó su proyecto:

imagen

Estos archivos deben agregarse directamente a su proyecto, ¡usted no utiliza la herramienta de canalización de contenido! Simplemente copie los tres archivos en la carpeta de contenido y establezca su acción de compilación en Copiar.

imagen

Ahora veamos el código requerido para usar estos archivos generados:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;

namespace Example4
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        AudioEngine audioEngine;
        SoundBank soundBank;
        WaveBank waveBank;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw 
            textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            audioEngine = new AudioEngine("Content/test.xgs");
            soundBank = new SoundBank(audioEngine,"Content/Sound Bank.
                        xsb");
            waveBank = new WaveBank(audioEngine,"Content/Wave Bank.
                       xwb");

            soundBank.GetCue("ak47").Play();
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

Primero crea un AudioEngine usando el archivo xgs, luego un SoundBank usando el xsb y un WaveBank usando el archivo xwb. Luego reproducimos la Cue que creamos anteriormente con una llamada a SoundBank.GetQue().Play(). Este proceso permite que los detalles de audio se configuren fuera del juego mientras que el programador simplemente usa el Que creado.

Finalmente, es posible reproducir archivos de audio que no se agregaron mediante la canalización de contenido o mediante Xact mediante un Uri.

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw 
            textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // URL MUST be relative in MonoGame
            System.Uri uri = new System.Uri("content/background.mp3",
                             System.UriKind.Relative);
            Song song = Song.FromUri("mySong", uri);
            MediaPlayer.Play(song);
            MediaPlayer.ActiveSongChanged += (s, e) => {
                song.Dispose();
                System.Diagnostics.Debug.WriteLine("Song ended and 
                                                   disposed");
            };
        }

Primero, crea un Uri que ubica el archivo de audio que desea cargar. Luego lo cargamos usando el método FromUri, pasando un nombre así como el uri. Una cosa muy importante a tener en cuenta aquí, en XNA podría usar cualquier URI. En MonoGame, debe ser una ruta relativa.

El video




Source link

Tags :
Audio,Monogame,Tutorial

Comparte :

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *