Skip to content

Commit f3ca739

Browse files
Fixing issues
1 parent 5da1a17 commit f3ca739

File tree

12 files changed

+280
-24
lines changed

12 files changed

+280
-24
lines changed

articles/getting_to_know/howto/audio/HowTo_PlayASong.md

-4
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,6 @@ The following demonstrates how to play a song from the media file in the content
6161

6262
## See Also
6363

64-
* [Playing a Song from a URI](HowTo_PlaySongfromURI.md)
65-
66-
Demonstrates how to use the [MediaPlayer](xref:Microsoft.Xna.Framework.Media.MediaPlayer) to play a song from a Uniform Resource Identifier (URI).
67-
6864
* [Media Overview](../../whatis/WhatIs_Audio.md)
6965

7066
Provides a high-level overview about the capabilitiessuch as playing music and video and accessing picturesof the Media API in MonoGame.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
using System;
2+
using Microsoft.Xna.Framework;
3+
using Microsoft.Xna.Framework.Audio;
4+
using Microsoft.Xna.Framework.Graphics;
5+
using Microsoft.Xna.Framework.Input;
6+
7+
namespace MonoGameMicrophoneExample;
8+
9+
public class Game1 : Game
10+
{
11+
private GraphicsDeviceManager graphics;
12+
private SpriteBatch spriteBatch;
13+
SpriteFont font;
14+
// The most recent microphone samples.
15+
byte[] micSamples;
16+
// DynamicSoundEffectInstance is used to playback the captured audio after processing it for echo.
17+
DynamicSoundEffectInstance dynamicSound;
18+
// Microphone used for recording.
19+
Microphone activeMicrophone;
20+
// Used to communicate the microphone status to the user.
21+
string microphoneStatus = string.Empty;
22+
const string instructions = @"Press 'Space' to start and 'P' to stop recording";
23+
24+
#region MonoGame Boilerplate
25+
public Game1()
26+
{
27+
graphics = new GraphicsDeviceManager(this);
28+
Content.RootDirectory = "Content";
29+
IsMouseVisible = true;
30+
}
31+
32+
protected override void Initialize()
33+
{
34+
// TODO: Add your initialization logic here
35+
36+
base.Initialize();
37+
}
38+
39+
protected override void LoadContent()
40+
{
41+
spriteBatch = new SpriteBatch(GraphicsDevice);
42+
43+
// Make sure to create a SpriteFont in the Content project and set its build action to "Content".
44+
font = Content.Load<SpriteFont>("File");
45+
}
46+
47+
48+
protected override void Update(GameTime gameTime)
49+
{
50+
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
51+
Exit();
52+
53+
// Constantly check for a good microphone to start recording.
54+
InitializeMicrophone();
55+
56+
// Check and update microphone status.
57+
UpdateMicrophoneStatus();
58+
59+
if (IsKeyPressed(Keys.Space))
60+
{
61+
StartRecording();
62+
}
63+
if (IsKeyPressed(Keys.P))
64+
{
65+
StopRecording();
66+
}
67+
68+
base.Update(gameTime);
69+
}
70+
71+
72+
protected override void Draw(GameTime gameTime)
73+
{
74+
GraphicsDevice.Clear(Color.CornflowerBlue);
75+
76+
// TODO: Add your drawing code here
77+
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
78+
spriteBatch.DrawString(font, instructions, new Vector2(10f, 20f), Color.White);
79+
spriteBatch.DrawString(font, microphoneStatus, new Vector2(10f, 50f), Color.White);
80+
spriteBatch.End();
81+
base.Draw(gameTime);
82+
}
83+
#endregion MonoGame Boilerplate
84+
85+
#region Input Handling
86+
private bool IsKeyPressed(Keys key)
87+
{
88+
return Keyboard.GetState().IsKeyDown(key);
89+
}
90+
91+
private void StartRecording()
92+
{
93+
// Can't start a microphone that doesn't exist.
94+
if (activeMicrophone == null) { return; }
95+
96+
try
97+
{
98+
activeMicrophone.Start();
99+
}
100+
catch (NoMicrophoneConnectedException)
101+
{
102+
UpdateMicrophoneStatus();
103+
}
104+
}
105+
106+
private void StopRecording()
107+
{
108+
// Can't stop a microphone that doesn't exist.
109+
if (activeMicrophone == null) { return; }
110+
111+
try
112+
{
113+
// Stop the microphone
114+
activeMicrophone.Stop();
115+
}
116+
catch (NoMicrophoneConnectedException)
117+
{
118+
UpdateMicrophoneStatus();
119+
}
120+
}
121+
#endregion Input Handling
122+
123+
#region Microphone Handling
124+
/// <summary>
125+
/// Keep track of the microphone status to communicate to the user.
126+
/// </summary>
127+
private void UpdateMicrophoneStatus()
128+
{
129+
// We don't have any microphones connected to the system.
130+
if (activeMicrophone == null)
131+
{
132+
microphoneStatus = "Waiting for microphone connection...";
133+
}
134+
else
135+
{
136+
try
137+
{
138+
// Update the status - if the microphone gets disconnected this will throw
139+
microphoneStatus = string.Format("{0} is {1}", activeMicrophone.Name, activeMicrophone.State);
140+
}
141+
catch (NoMicrophoneConnectedException)
142+
{
143+
// Microphone got disconnected - Let's ask the user to reconnect it.
144+
microphoneStatus = string.Format("Please reconnect {0}", activeMicrophone.Name);
145+
}
146+
}
147+
}
148+
149+
/// <summary>
150+
/// This is called each time a microphone buffer has been filled.
151+
/// </summary>
152+
void BufferReady(object sender, EventArgs e)
153+
{
154+
try
155+
{
156+
// Copy the captured audio data into the pre-allocated array.
157+
int sampleDataSize = activeMicrophone.GetData(micSamples);
158+
159+
// Process the captured audio for playback
160+
dynamicSound.SubmitBuffer(micSamples, 0, sampleDataSize);
161+
}
162+
catch (NoMicrophoneConnectedException)
163+
{
164+
// Microphone was disconnected - let the user know.
165+
UpdateMicrophoneStatus();
166+
}
167+
}
168+
169+
/// <summary>
170+
/// Look for a good microphone to start recording.
171+
/// </summary>
172+
/// <returns></returns>
173+
private Microphone PickFirstConnectedMicrophone()
174+
{
175+
// Let's pick the default microphone if it's ready.
176+
if (Microphone.Default != null && Microphone.Default.IsConnected())
177+
{
178+
return Microphone.Default;
179+
}
180+
181+
// Default microphone seems to be disconnected so look for another microphone that we can use.
182+
// And if the default was null then the list will be empty and we'll skip the search.
183+
foreach (Microphone microphone in Microphone.All)
184+
{
185+
if (microphone.IsConnected())
186+
{
187+
return microphone;
188+
}
189+
}
190+
191+
// There are no microphones hooked up to the system!
192+
return null;
193+
}
194+
195+
/// <summary>
196+
/// Finds a good microphone to use and sets up everything to start recording and playback.
197+
/// Once a microphone is selected the game uses it throughout its lifetime.
198+
/// If it gets disconnected it will tell the user to reconnect it.
199+
/// </summary>
200+
private void InitializeMicrophone()
201+
{
202+
// We already have a microphone, skip out early.
203+
if (activeMicrophone != null) { return; }
204+
205+
try
206+
{
207+
// Find the first microphone that's ready to rock.
208+
activeMicrophone = PickFirstConnectedMicrophone();
209+
if (activeMicrophone != null)
210+
{
211+
// Set the capture buffer size for kow latency.
212+
// Microphone will call the game back when it has captured at least that much audio data.
213+
activeMicrophone.BufferDuration = TimeSpan.FromMilliseconds(100);
214+
// Subscribe to the event that's raised when the capture buffer is filled.
215+
activeMicrophone.BufferReady += BufferReady;
216+
// We will put the mic samples in this buffer. We only want to allocate it once.
217+
micSamples = new byte[activeMicrophone.GetSampleSizeInBytes(activeMicrophone.BufferDuration)];
218+
219+
// Create a DynamicSoundEffectInstance in the right format to playback the captured audio.
220+
dynamicSound = new DynamicSoundEffectInstance(activeMicrophone.SampleRate, AudioChannels.Mono);
221+
dynamicSound.Play();
222+
}
223+
}
224+
catch (NoMicrophoneConnectedException)
225+
{
226+
// Uh oh, the microphone was disconnected in the middle of initialization.
227+
// Let's clean up everything so we can look for another microphone again on the next update.
228+
activeMicrophone.BufferReady -= BufferReady;
229+
activeMicrophone = null;
230+
}
231+
}
232+
#endregion Microphone Handling
233+
}
234+
235+
#region Helper Microphone Extension Method
236+
public static class MicrophoneExtensions
237+
{
238+
// Provides a simple method to check if a microphone is connected.
239+
// There is no guarantee that the microphone will not get disconnected at any time.
240+
// This method helps in simplifying the microphone enumeration code.
241+
public static bool IsConnected(this Microphone microphone)
242+
{
243+
try
244+
{
245+
MicrophoneState state = microphone.State;
246+
return true;
247+
}
248+
catch (NoMicrophoneConnectedException)
249+
{
250+
return false;
251+
}
252+
}
253+
}
254+
#endregion Helper Microphone Extension Method

articles/getting_to_know/howto/audio/toc.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
- name: <- Back
2-
href: ../Index.md
2+
href: ../index.md
33
- name: Introduction
44
href: index.md
55
- name: How to Play a sound
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
- name: <- Back
2-
href: ../Index.md
2+
href: ../index.md
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
- name: <- Back
2-
href: ../Index.md
2+
href: ../index.md
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
- name: <- Back
2-
href: ../Index.md
2+
href: ../index.md

articles/getting_to_know/howto/toc.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
- name: <- Back
2-
href: ../Index.md
2+
href: ../index.md
33
- name: Introduction
44
href: index.md
55
- name: Audio

articles/getting_to_know/toc.yml

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
- name: Introduction
2+
href: index.md
13
- name: What is
24
href: whatis/
35
items:

articles/getting_to_know/whatis/WhatIs_Audio.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ If your game is to use a few sound files, then the [SoundEffect](xref:Microsoft.
88

99
## Simple Audio Playback
1010

11-
The simplest way to play sounds for background music or sound effects is to use [SoundEffect](xref:Microsoft.Xna.Framework.Audio.SoundEffect) and [SoundEffectInstance](xref:Microsoft.Xna.Framework.Audio.SoundEffectInstance). Source audio files are added like any other game asset to the project. For example code, see [Playing a Sound](../HowTo/audio/HowTo_PlayASound.md), [Looping a Sound](../HowTo/audio/HowTo_LoopASound.md), and [Adjusting Pitch and Volume](../HowTo/audio/HowTo_ChangePitchAndVolume.md). For background music, see [Playing a Song](../HowTo/audio/HowTo_PlayASong.md).
11+
The simplest way to play sounds for background music or sound effects is to use [SoundEffect](xref:Microsoft.Xna.Framework.Audio.SoundEffect) and [SoundEffectInstance](xref:Microsoft.Xna.Framework.Audio.SoundEffectInstance). Source audio files are added like any other game asset to the project. For example code, see [Playing a Sound](../howto/audio/HowTo_PlayASound.md), [Looping a Sound](../howto/audio/HowTo_LoopASound.md), and [Adjusting Pitch and Volume](../howto/audio/HowTo_ChangePitchAndVolume.md). For background music, see [Playing a Song](../howto/audio/HowTo_PlayASong.md).
1212

1313
## Accessing the Audio Buffer
1414

15-
Developers can use [DynamicSoundEffectInstance](xref:Microsoft.Xna.Framework.Audio.DynamicSoundEffectInstance) for direct access to an audio buffer. By accessing the audio buffer, developers can manipulate sound, break up large sound files into smaller data chunks, and stream sound. For example code, see [Streaming Data from a WAV File](../HowTo/audio/HowTo_StreamDataFromWav.md).
15+
Developers can use [DynamicSoundEffectInstance](xref:Microsoft.Xna.Framework.Audio.DynamicSoundEffectInstance) for direct access to an audio buffer. By accessing the audio buffer, developers can manipulate sound, break up large sound files into smaller data chunks, and stream sound. For example code, see [Streaming Data from a WAV File](../howto/audio/HowTo_StreamDataFromWav.md).
1616

1717
## 3D Audio
1818

@@ -51,18 +51,18 @@ Access to the media library, combined with the ability to use playlists, allows
5151
5252
## Reference
5353

54-
[SoundEffect Class](xref:Microsoft.Xna.Framework.Audio.SoundEffect)
54+
* [SoundEffect Class](xref:Microsoft.Xna.Framework.Audio.SoundEffect)
5555

56-
Provides a loaded sound resource.
56+
Provides a loaded sound resource.
5757

58-
[SoundEffectInstance Class](xref:Microsoft.Xna.Framework.Audio.SoundEffectInstance)
58+
* [SoundEffectInstance Class](xref:Microsoft.Xna.Framework.Audio.SoundEffectInstance)
5959

60-
Provides a single playing, paused, or stopped instance of a [SoundEffect](xref:Microsoft.Xna.Framework.Audio.SoundEffect) sound.
60+
Provides a single playing, paused, or stopped instance of a [SoundEffect](xref:Microsoft.Xna.Framework.Audio.SoundEffect) sound.
6161

62-
[DynamicSoundEffectInstance Class](xref:Microsoft.Xna.Framework.Audio.DynamicSoundEffectInstance)
62+
* [DynamicSoundEffectInstance Class](xref:Microsoft.Xna.Framework.Audio.DynamicSoundEffectInstance)
6363

64-
Provides properties, methods, and events for play back of the audio buffer.
64+
Provides properties, methods, and events for play back of the audio buffer.
6565

66-
[Song Class](xref:Microsoft.Xna.Framework.Media.Song)
66+
* [Song Class](xref:Microsoft.Xna.Framework.Media.Song)
6767

68-
Provides access to a song in the song library.
68+
Provides access to a song in the song library.
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
- name: <- Back
2-
href: ../Index.md
2+
href: ../index.md
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
- name: <- Back
2-
href: ../Index.md
2+
href: ../index.md
+7-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
- name: <- Back
2-
href: ../Index.md
2+
href: ../index.md
33
- name: Introduction
44
href: index.md
55
- name: Content Pipeline
66
href: content_pipeline/index.md
77
- name: Graphics
88
href: graphics/index.md
99
- name: Audio
10-
href: whatis_audio.md
10+
href: WhatIs_Audio.md
11+
- name: Input
12+
href: WhatIs_Input.md
1113
- name: The Game Loop
12-
href: whatis_thegameloop.md
14+
href: WhatIs_TheGameLoop.md
1315
- name: Vector / Matrix / Quaternions
1416
href: WhatIs_VectorMatrixQuat.md
17+
- name: MonoGame Class Library
18+
href: WhatIs_VectorMatrixQuat.md

0 commit comments

Comments
 (0)