views:

55

answers:

1

(apologies if this is a duplicate ... i posted but saw no evidence that it actually made it to the forum)

I've been trying to get SlimDX DirectSound working. Here's the code I have. It fills the secondary buffer from a wav file and then, in a thread loop, alternately fills the lower or upper halves of the buffer.

It plays the first load of the buffer fine. The AutoResetEvents fire when they should and the lower half then upper half of the buffer are populated (verified with Debug statements). But playing does not continue after the first load of the buffer. So somehow the repopulation of the buffer doesn't work as it should.

Ideas?

(I'm using DirectSound because it's the only way I've found to set the guid of the audio device that I want to use. Am open to other .NET-friendly approaches.)

private void PlaySound(Guid soundCardGuid, string audioFile) {
        DirectSound ds = new DirectSound(soundCardGuid);

        ds.SetCooperativeLevel(this.Handle, CooperativeLevel.Priority);

        WaveFormat format = new WaveFormat();
        format.BitsPerSample = 16;
        format.BlockAlignment = 4;
        format.Channels = 2;
        format.FormatTag = WaveFormatTag.Pcm;
        format.SamplesPerSecond = 44100;
        format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlignment;

        SoundBufferDescription desc = new SoundBufferDescription();
        desc.Format = format;
        desc.Flags = BufferFlags.GlobalFocus;
        desc.SizeInBytes = 8 * format.AverageBytesPerSecond; 

        PrimarySoundBuffer pBuffer = new PrimarySoundBuffer(ds, desc);

        SoundBufferDescription desc2 = new SoundBufferDescription();
        desc2.Format = format;
        desc2.Flags = BufferFlags.GlobalFocus | BufferFlags.ControlPositionNotify | BufferFlags.GetCurrentPosition2;
        desc2.SizeInBytes = 8 * format.AverageBytesPerSecond;

        SecondarySoundBuffer sBuffer1 = new SecondarySoundBuffer(ds, desc2);

        NotificationPosition[] notifications = new NotificationPosition[2];
        notifications[0].Offset = desc2.SizeInBytes / 2 + 1;
        notifications[1].Offset = desc2.SizeInBytes - 1; ;

        notifications[0].Event = new AutoResetEvent(false);
        notifications[1].Event = new AutoResetEvent(false);
        sBuffer1.SetNotificationPositions(notifications);

        byte[] bytes1 = new byte[desc2.SizeInBytes / 2];
        byte[] bytes2 = new byte[desc2.SizeInBytes];

        Stream stream = File.Open(audioFile, FileMode.Open);

        Thread fillBuffer = new Thread(() => {
            int readNumber = 1;
            int bytesRead;

            bytesRead = stream.Read(bytes2, 0, desc2.SizeInBytes);
            sBuffer1.Write<byte>(bytes2, 0, LockFlags.None);
            sBuffer1.Play(0, PlayFlags.None); 
            while (true) {
                if (bytesRead == 0) { break; }
                notifications[0].Event.WaitOne();
                bytesRead = stream.Read(bytes1, 0, bytes1.Length);
                sBuffer1.Write<byte>(bytes1, 0, LockFlags.None);

                if (bytesRead == 0) { break; }
                notifications[1].Event.WaitOne();
                bytesRead = stream.Read(bytes1, 0, bytes1.Length);
                sBuffer1.Write<byte>(bytes1, desc2.SizeInBytes / 2, LockFlags.None); 
            }
            stream.Close();
            stream.Dispose();
        });
        fillBuffer.Start();
    }
}
A: 

You haven't set it to loop on the play buffer. Change your code to:

sBuffer1.Play(0, PlayFlags.Looping); 
Goz
Thanks. That was it. In the absence of any SlimDX doc on the subject, I had misunderstood the meaning of the flags.
blearyeye
@Blearyeye: Feel free to accept my answer :)
Goz