Jump to content
  • Advertisement
Sign in to follow this  
Oduig

Sound latency with DirectSound

This topic is 2546 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

Hi there,

[/font]

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

I am attempting to make an application that can process sound from the Line in jack. I would like for the game to have a fast response speed, but I ran into a roadblock.

[/font]

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

The library I use (SoundCapture from

[/font]http://www.codeproje...uitarTuner.aspx[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

) only produces a maximum of two notes a second, which is 500ms for each short[] audio sequence. I traced the delay by doing my own measurements on the code, and from what I can see the bottleneck appears to be the DirectSound.Notify object. If I understand correctly, DirectSound should set an autoresetevent when the audio buffer has a certain amount of data. The SoundCaptureBase class (see below for an exerpt) will wait for this event and process the data.

[/font]



[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]


public abstract class SoundCaptureBase : IDisposable
{
const int BufferSeconds = 3;
const int NotifyPointsInSecond = 2;

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

// change in next two will require also code change
const int BitsPerSample = 16;
const int ChannelCount = 1;

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

int sampleRate = 44100;
bool isCapturing = false;
bool disposed = false;
Capture capture;
CaptureBuffer buffer;
Notify notify;
int bufferLength;
AutoResetEvent positionEvent;
SafeWaitHandle positionEventHandle;
ManualResetEvent terminated;
Thread thread;
SoundCaptureDevice device;

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

public SoundCaptureBase(SoundCaptureDevice device)
{
this.device = device;

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

positionEvent = new AutoResetEvent(false);
positionEventHandle = positionEvent.SafeWaitHandle;
terminated = new ManualResetEvent(true);
}

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

/// <summary>
/// Starts capture process.
/// </summary>
public void Start()
{
EnsureIdle();

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

isCapturing = true;

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

WaveFormat format = new WaveFormat();
format.Channels = ChannelCount;
format.BitsPerSample = BitsPerSample;
format.SamplesPerSecond = SampleRate;
format.FormatTag = WaveFormatTag.Pcm;
format.BlockAlign = (short)((format.Channels * format.BitsPerSample + 7) / 8);
format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond;

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

bufferLength = format.AverageBytesPerSecond * BufferSeconds;
CaptureBufferDescription desciption = new CaptureBufferDescription();
desciption.Format = format;
desciption.BufferBytes = bufferLength;

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

capture = new Capture(device.Id);
buffer = new CaptureBuffer(desciption, capture);

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

int waitHandleCount = BufferSeconds * NotifyPointsInSecond;
BufferPositionNotify[] positions = new BufferPositionNotify[waitHandleCount];
for (int i = 0; i < waitHandleCount; i++)
{
BufferPositionNotify position = new BufferPositionNotify();
position.Offset = (i + 1) * bufferLength / positions.Length - 1;
position.EventNotifyHandle = positionEventHandle.DangerousGetHandle();
positions = position;
}

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

notify = new Notify(buffer);
notify.SetNotificationPositions(positions);

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

terminated.Reset();
thread = new Thread(new ThreadStart(ThreadLoop));
thread.Name = "Sound capture1";
thread.Start();
}

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

private void ThreadLoop()
{
buffer.Start(true);
try
{
WaitHandle[] handles = new WaitHandle[] { terminated, positionEvent };
double elapsed;

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

// Testing code to find the notification rate of DirectSound
DateTime dt;
int count = 0;
dt = DateTime.Now;
while (WaitHandle.WaitAny(handles) > 0) {
// This is where one would process the audio data
count++;
if (count % 10 == 0) {
elapsed = (DateTime.Now - dt).TotalMilliseconds;
// Breakpoint
elapsed = 0;
}
}
}
finally
{
buffer.Stop();
}
}
}

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

}

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[/font]

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

ThreadLoop simply measures the time for an incoming audio stream from DirectSound.Notify. The Start() function initializes the variables.

[/font][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

I cannot seem to find any settings that might cause this half second delay.

[/font]

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

Thank you for any suggestions,

[/font]
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

Guido

[/font]

Share this post


Link to post
Share on other sites
Advertisement
I'm sorry for the double post. The forum seems very bugged at the moment, I could not get my code to display correctly and when I tried to edit it, I made a new post instead...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!