This project has moved and is read-only. For the latest updates, please go here.

How to generate wav with a specific length

Nov 9, 2012 at 5:18 PM
Edited Nov 9, 2012 at 5:19 PM

Hi,

I use this code to generate a wav stream. it works fine but how do i generate wav for example with 5 seconds length? this is my first time i'm using this dll.

Slinger

private DirectSoundOut output = null;
        private BlockAlignReductionStream stream = null;

        private void button3_Click(object sender, EventArgs e) // start tone
        {
            WaveTone tone = new WaveTone(2000, 0.5); // �������, ���������
            stream = new BlockAlignReductionStream(tone);
            
            output = new DirectSoundOut();
            output.Init(stream);
            output.Play();
        }

        private void button4_Click(object sender, EventArgs e) // stop tone
        {
            if (output != null) output.Stop();
        }

        public class WaveTone : WaveStream
        {
            private double frequency;
            private double amplitude;
            private double time;
            
            public WaveTone(double f, double a)
            {
                this.time = 0;
                this.frequency = f;
                this.amplitude = a;
            }

            public override long Position
            {
                get;
                set;
            }

            public override long Length
            {
	            get { return long.MaxValue;}
            }

            public override WaveFormat WaveFormat
            {
	        get { return new WaveFormat(44100, 16, 1); }
            }

            public override int Read(byte[] buffer, int offset, int count)
            {
                
                int samples = count / 2;
                for (int i = 0; i < samples; i++)
                {
                    double sine = amplitude * Math.Sin(Math.PI * 2 * frequency * time);
                    time += 1.0 / 44100;
                    short truncated = (short)Math.Round(sine * (Math.Pow(2,15) - 1));
                    buffer[i * 2] = (byte)(truncated & 0x00ff);
                    buffer[i * 2 + 1] = (byte)((truncated & 0xff00) >> 8);
                }

                return count;
            }





         } // public class WaveTone : WaveStream

Nov 10, 2012 at 7:50 AM

There are several ways you can do this, but one is for WaveTone to stop returning audio after five seconds. Since you are already tracking a "time" variable, which is the total number of samples, you can use this:

for (int i = 0; i < samples && time < (44100 * 5); i++)

however, make sure that the Read function returns 0 after you've reached the end, or it will carry on playing indefinitely.

Nov 10, 2012 at 10:51 AM

Hi markheath

I've modified the code. Buy i dont understand how to stop Read function. It's continuing calling and the sound is keep playing. What should i do?

 

  public override int Read(byte[] buffer, int offset, int count)
            {
                
                int samples = count / 2;
                for (int i = 0; i < samples && time < (44100 * 3); i++)
                {
                    double sine = amplitude * Math.Sin(Math.PI * 2 * frequency * time);
                    time += 1.0 / 44100;
                    short truncated = (short)Math.Round(sine * (Math.Pow(2,15) - 1));
                    buffer[i * 2] = (byte)(truncated & 0x00ff);
                    buffer[i * 2 + 1] = (byte)((truncated & 0xff00) >> 8);
                }
                return count;
            }

slinger

 

 

Nov 10, 2012 at 11:01 AM

as I said above, Read must return 0 not count when you reach the end. e.g.:

 

return (time < (44100 * 3)) ? count : 0;
Nov 10, 2012 at 11:46 AM

Sorry for asking dummy questions but nothing has changed:

   public override int Read(byte[] buffer, int offset, int count)
            {
                
                int samples = count / 2;
                for (int i = 0; i < samples && time < (44100 * 3); i++)
                {
                    double sine = amplitude * Math.Sin(Math.PI * 2 * frequency * time);
                    time += 1.0 / 44100;
                    short truncated = (short)Math.Round(sine * (Math.Pow(2,15) - 1));
                    buffer[i * 2] = (byte)(truncated & 0x00ff);
                    buffer[i * 2 + 1] = (byte)((truncated & 0xff00) >> 8);
                }
                //return count;
                return (time < (44100 * 3)) ? count : 0;
                
            }
slinger

Nov 10, 2012 at 11:48 AM

oh, sorry, I see that time is not in samples. replace both instances of (44100 * 3) with 3. Also, you don't need to be using BlockAlignReduction stream.

Nov 10, 2012 at 12:11 PM

Holy Lord! it works properly^) thx. But what should i use instead of BlockAlignReductionStream?

Nov 10, 2012 at 12:20 PM

nothing. just pass tone directly into Init

Nov 12, 2012 at 8:50 AM

ok. thank you so much)

slinger