Quantcast
Channel: Community | MonoGame - Latest topics
Viewing all articles
Browse latest Browse all 6822

Just trying to figure out how to play a simple sin wave...

$
0
0

@SoundGoddess wrote:

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:

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:

Is choppy in MonoGame:

I'm using the WindowsGL version, since that should be the most compatible with Linux/Mac.

Posts: 2

Participants: 2

Read full topic


Viewing all articles
Browse latest Browse all 6822

Trending Articles