More Precise timer than Stopwatch? - c#

I'm trying to have a stopwatch start and stop when recording positions for the Kinect:
//process x and y coordinates
public void calculateJoints(Skeleton skeleton)
{
Joint rightHand = skeleton.Joints[JointType.HandRight];
Joint leftHand = skeleton.Joints[JointType.HandRight];
rightX = rightHand.Position.X;
rightY = rightHand.Position.Y;
}
//start the stopwatch (tried to use a greater time between positions 1 and 5 vs 1 and 2
public void processJointsAndRepeat(Skeleton skeleton)
{
startTime();
while (numPositions < 5)
{
calculateJoints(skeleton);
numPositions++;
}
stopTime();
double tempTime = calculateTimeElapsed();
}
//calculate time in milliseconds
private double calculateTimeElapsed()
{
long milliseconds = stopWatch.ElapsedMilliseconds;
return (double)milliseconds;
}
But whenever I try to put in the x, y, and time values with time as the key, it throws an error for duplicate keys. When I retrieved the value of tempTime, it only showed 0.
Is this a problem with my code, or do I need a more precise stopwatch?
I realize that getting a time for something that is 30 fps is difficult, so if you have any other suggestions, that'd be great! I'm basically just trying to calculate the average velocities between points to adjust the playback speed of an audio file. Thanks!

Stopwatch is wrapper around timer with higerst resolution on regular Windows box. You can use less fancy functions to get higer than MS resolution by using Stopwatch.ElapsedTicks and Stopwatch.Frequency.
Note that your problem is probably not related to timers but rather some other code you did not show...

Related

How do I fix my timer so it counts in seconds?

I want my game's screen to have a timer on screen that shows how many seconds have passed (representing the player's point score). I am able to get the timer on screen, however, the counter freaks out and my console doesn't print the result correctly either. Any ideas?
I've tried to use timer.Elapsed however SplashKit (what i must use) does not seem to recognise that.
Sorry if this is a repeated question, I am new to programming and have searched around but couldn't find anything I could comprehend/assist.
public void Timer()
{
//begin timer and print results
timer.Start();
//write to console how many milliseconds have passed, and divide by 1000 for seconds.
Console.WriteLine($":{timer.Ticks} milliseconds have passed");
Console.WriteLine($"which is {timer.Ticks /1000} seconds");
//covert timer.Ticks to string and store into string 'score
score = Convert.ToString(timer.Ticks);
//assign font
Font Quicksand = SplashKit.LoadFont("Quicksand", "Resources\\fonts\\Quicksand-Regular.otf");
//use SplashKit to print to screen..
SplashKit.DrawText(score, Color.Black, Quicksand, 70, 700, 900);
}
+1 to Eric j's comment- all the Timer types the framework that I know of are not for providing stopwatch style "the game has been running 5 minutes" type functions directly themselves. They're classes that raise an event at some predefined interval. The actual timing of the game, if using a Timer, would be done by you by recording the start time and differencing the time now to it upon the timer elapsing it's interval:
public class Whatever{
private Timer _t = new Timer();
private DateTime _start;
public Whatever(){ //constructor
_t.Elapsed += TimerElapsed; //elapsed event handled by TimerElapsed method
_t.Interval = 1000; //fire every second
}
public void StartGame(){
_start = DateTime.UtcNow;
_t.Start();
}
private void TimerElapsed(){
Console.WriteLine("Game has been running for " + (DateTime.UtcNow - _start));
}
The timer interval merely controls how often the clock will update on screen. If you're offering game times of 10.1,10.2 seconds etc then make the timer interval less than 100 (updates more than once every 0.1 seconds) for example
It's not clear what type timer is, but the property Elapsed is probably a TimeSpan.
The total seconds including decimal amount is present in the double value:
timer.Elapsed.TotalSeconds
You can truncate that to an integer by casting it
var seconds = (int)timer.Elapsed.TotalSeconds;

How can I increase the volume of a sound from unhearable (0db) to loud (60db)

I try to increase the noise by doing this :
public void maakgeluid() {
WaveOut waveOut = new WaveOut();
SineWaveOscillator osc = new SineWaveOscillator(44100);
for (short amplitude = 1; amplitude <500; amplitude+=1) {
Console.WriteLine("amplitude:" + amplitude);
for (int i = 1; i < 10; i++) {
Console.WriteLine(i);
osc.Frequency = 500;
osc.Amplitude = amplitude;
try {
waveOut.Init(osc);
} catch (Exception ) { Console.WriteLine("error"); }
waveOut.Play();
}
}
}
The purpose is to generate a sound, like when you go to the ear specialist and take a hearing test. So it should start very silently, and then slowly get loader.
But I have different problems :
i hear the sound immediately
the sound increases to fast
i use the loop with the i counter, to lengthen the duration of the sound, but i don't think that is the right way to do it.
the looping to increase the sound level stops to quickly but I don't see why?
THx
based on the following code
msdn.microsoft.com/en-us/magazine/ee309883.asp
The bel scale is logarithmic, so you need to do maths to convert between decibels and a sample scaling factor.
In digital (floating point) audio a full signal (i.e. a waveform that reaches from +1 to -1, peak to trough) is considered to be 0dB.
As such, you'd probably want to go from -60dB to 0dB.
The conversion is as follows (assuming signed audio over unsigned, as with 8-bit audio)
double sampleValue = 1.0d;
//every -3db represents an approximate halving of linear signal level
double decibelValue = -3.0d;
double linearScalingRatio = Math.Pow(10d, decibelValue/10d);
var newSampleValue = sampleValue * linearScalingRatio;
So now, newSampleValue is 0.501187233627272
Your current code keeps recreating WaveOut devices which is not a good idea. Open the soundcard once, and then feed a single signal to it that gradually increases in volume over time. One way you could do this is to use the SignalGenerator class to make the sin wave, then pass that through a FadeInSampleProvider to gradually fade it in:
var sg = new SignalGenerator(44100,1);
sg.Frequency = 500;
sg.Type = SignalGeneratorType.Sin;
var fadeIn = new FadeInOutSampleProvider(sg, true);
fadeIn.BeginFadeIn(20000); // fade in over 20 seconds
waveOut.Init(fadein);
waveOut.Play();
As spender rightly points out, 0dB is maximum, so this is going from negative infinity decibels up to 0dB over the duration of the fade-in time. If you wanted to make it start at -60dB, or for the ramp-up of the multiplier to not be linear, then you'd need to make your own custom ISampleProvider similar to FadeInOutSampleProvider and use that instead.

Making smooth animations in .NET/GDI+

I'm having problems making smooth animations in GDI+. The problem as I understand it from Googling is that there is some kind of bug with the clock-ticks in .NET on a multi-core processor. Here's a simplified version of what I'm doing:
class Animation
{
System.Diagnostics.Stopwatch sw = new Stopwatch();
float AnimationTime = 1000; //time it takes the animation to complete
public bool IsComplete
{ get { return sw.ElapsedMilliseconds > AnimationTime; } }
public void StartAnimation()
{
sw.Reset();
sw.Start();
}
public void DoFrame()
{
float PercentComplete = (float)sw.ElapsedMilliseconds / AnimationTime;
//draw the animation based on PercentComplete
}
}
DoFrame() is called like this:
Animation.Start();
do
{
Animation.DoFrame();
Application.DoEvents();
} while (!Animation.IsComplete);
The problem is that the animation is very smooth for about 15 frames then it jerks, it actually goes backward (sw.ElapsedMilliseconds gives a lesser value than the previous query). It's very annoying and it's ruining my otherwise smooth animation that looks great even on a Core 2 Duo (despite Microsoft saying this is a multicore bug). I have an i7 and the animation is smooth except for 2-3 frames per second that look "jerky".
I understand that this is a known issue and Microsoft blames it on the processor, so my question is, does anyone know any kind of solution for this? I tried using a Kalman filter and it sort of works. I was hoping maybe there is an established "correct" solution for this?
Oh b.t.w. I tried using DateTime instead of Stopwatch and got the same results.
I also tried:
double PercentComplete = (double)sw.ElapsedTicks / (double)Stopwatch.Frequency * 1000 / AnimationTime
It gives me the same results.
It probably has to do with the way you call DoFrame(). Using the following windows forms / GDI+ based algorithm you should alway get very smooth animations:
const double desiredFps = 500.0;
long ticks1 = 0;
var interval = Stopwatch.Frequency / desiredFps;
while (true)
{
Application.DoEvents();
var ticks2 = Stopwatch.GetTimestamp();
if (ticks2 >= ticks1 + interval)
{
ticks1 = Stopwatch.GetTimestamp();
// do the drawing here
}
}

What are my options for timing?

I'm making a TextBox control in XNA and do not have access to the GameTime class. Currently I am trying to simulate the blinking text cursor caret and have successfully done so using this code:
int deltaTickCount = Environment.TickCount - previousTickCount;
if (deltaTickCount < CursorBlinkRate && Selected)
{
spriteBatch.Draw(emptyPixel, new Rectangle(caretLocation, Rectangle.Y + 1, caretWidth, caretHeight), Color.Black);
}
else if (deltaTickCount > CursorBlinkRate * 2)
{
previousTickCount = Environment.TickCount;
}
However, I'm a bit wary of using Environment.TickCount. If the computer was running long enough, wouldn't the program eventually crash or produce unpredictable behavior when the tick count exceeded its integral size?
Does anyone know what Windows does? I imagine it would use the system clock. Would that be a more suitable solution? I imagine they used something like total milliseconds in to the second instead of the tick count, but I'm not sure.
Thanks for reading.
I generally use the system diagnostics timer in a lot of situations.
It's a pretty powerful tool which creates a timer for you with a lot of good controls.
using System.Diagnostics;
Stopwatch timer = new Stopwatch();
Then use inbuilt controls:
timer.Start();
if(timer.elapsedMilliseconds() > ...)
{ }
timer.Reset();
etc...
This would allow you to reset the timer?
When Evnironment.TickCount rolls over, deltaTickCount will end up being negative, so you know it has happened. The calculation then becomes:
if (deltaTickCount < 0)
deltaTickCount = int.MaxValue - previousTickCount + Environment.TickCount;
Without bothering with what would happen in the case of an integer overflow, simply change to:
int deltaTickCount =
Environment.TickCount > previousTickCount
? Environment.TickCount - previousTickCount
: CursorBlinkRate * 3;

Move object from one point to another based on duration

Been wrapping my head around this problem for a while and looking for solutions online to no effect.
Basically if I have a sprite for example located at (10,10) I want to move it to say (50,100) and the whole process to take 2 seconds or whatever duration I specify. What is the exact math behind this? I was using a distance based solution to determine speed but was just using a random modifier to control the process. I need something more precise to execute exactly over a set duration.
Any help on this issue would be greatly appreciated!
Assuming linear interpolation (i.e. moving in a straight line from start position to end position at a constant rate):
The vector from start to destination is destination - start, i.e. for your example (40,90).
If you want this to happen over two seconds you need to divide it by two to get the distance travelled per second, so (20,45) per second for your example.
To get the position at any given time, first record the start time and calculate the current time minus the start time in seconds. So if the animation started at 12:01:30.000 and it is now 12:01:31.500 then 1.5 seconds have past since the start of the animation.
To get the current location you add the start location to the movement per second vector * the time elapsed, so in my example:
(10,10) + (20,45) * 1.5 = (10,10) + (30, 67.5) = (40, 77.5)
It's just a thing of interpolation and time.
There is linear, sinus, quadratic, ...
Here is some more info and examples in actionscript: link
Take a closer look to jQuery's animation algorithms... maybe you can use some of the code.
http://code.jquery.com/jquery-1.6.1.js (search for "custom:" as a starting point).
You need a couple of pieces of information to do this, start location, end location, duration and elapsed time.
Here's an example in actionscript:
package {
import flash.utils.getTimer;
import flash.events.Event;
import flash.display.Shape;
import flash.geom.Point;
import flash.display.Sprite;
public class Mover extends Sprite {
private var circle :Shape;
private var start :Point;
private var end :Point;
private var duration :int;
public function Mover() {
// first we create something to move, like, a circle
circle = new Shape();
circle.graphics.beginFill(0xff00ff);
circle.graphics.drawCircle(0, 0, 20);
addChild(circle);
// start and end positions
start = new Point(0, 0);
end = new Point(100, 100);
// and finally, the duration, i'm using milliseconds
duration = 2000;
// this event handler will run each frame
addEventListener(Event.ENTER_FRAME, handleEnterFrame);
}
private function handleEnterFrame(event:Event):void {
// we figure out how much of the animation has elapsed by using getTimer
// should you want to use a start time, add it here
var progress:Number = getTimer() / duration;
// we need to clamp our progress so we don't under- or overshoot the target
if(progress < 0) progress = 0;
if(progress > 1) progress = 1;
// then it's a matter of setting the position
// we use the start position as a base and then gradually add in
// the difference between the start and the end
circle.x = start.x + (end.x - start.x) * progress;
circle.y = start.y + (end.y - start.y) * progress;
}
}
}
If you're not all that interested in the how and just want the results, I wholeheartedly recommend a tweening engine like TweenLite or any of the other myriad of them. Just stay clear of the one that comes with flash, it's a bit crap.

Categories

Resources