I’m following this tutorial with the new DynamicSoundEffectsInstance from the latest develop build:
http://www.david-gouveia.com/portfolio/creating-a-basic-synth-in-xna-part-ii/
When I try this I get sampling artifacts:
http://hathor.link/1469255108.mp4
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace WaterSynth {
public class WaterSynth : Game {
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
private DynamicSoundEffectInstance ds;
public const int samples = 3000;
public const int sampleRate = 44100;
private float[,] buffer;
private byte[] xBuffer;
private double timer;
public WaterSynth() {
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize() { base.Initialize(); }
protected override void LoadContent() {
spriteBatch = new SpriteBatch(GraphicsDevice);
ds = new DynamicSoundEffectInstance(sampleRate, AudioChannels.Stereo);
xBuffer = new byte[samples*4];
buffer = new float[2, samples];
ds.Play();
}
private void SubmitBuffer() {
FillBuffer();
ConvertBuffer(buffer, xBuffer);
ds.SubmitBuffer(xBuffer);
}
private void FillBuffer() {
for (int i = 0; i < samples; i++) {
buffer[0, i] = (float)SineWave(timer, 440);
buffer[1, i] = (float)SineWave(timer, 440);
timer += 1f/sampleRate;
}
}
private double SineWave(double time, double frequency) {
return Math.Sin(time * 2 * Math.PI * frequency);
}
private static void ConvertBuffer(float[,] from, IList<byte> to) {
const int sampleBytes = 2;
var channels = from.GetLength(0);
var samplesBuffer = from.GetLength(1);
for (int i = 0; i < samplesBuffer; i++) {
for (int j = 0; j < channels; j++) {
var floatSample = MathHelper.Clamp(from[j, i], -1.0f, 1.0f);
var shortSample =
(short) (floatSample >= 0f ? floatSample*short.MaxValue : floatSample*short.MinValue*-1);
int index = i*channels*sampleBytes + j*sampleBytes;
if (!BitConverter.IsLittleEndian) {
to[index] = (byte) (shortSample >> 8);
to[index + 1] = (byte) shortSample;
}
else {
to[index] = (byte) shortSample;
to[index + 1] = (byte) (shortSample >> 8);
}
}
}
}
protected override void Update(GameTime gameTime) {
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
while(ds.PendingBufferCount < 3) SubmitBuffer();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime) {
GraphicsDevice.Clear(Color.CornflowerBlue);
base.Draw(gameTime);
}
}
}
Another example…the code from his Tutorial 3 works fine in XNA:
http://hathor.link/1469242969.mp4
Is choppy in MonoGame:
http://hathor.link/1469242825.mp4
I’m using the WindowsGL version, since that should be the most compatible with Linux/Mac.