I've been playing around with some C# and specifically making sounds... because it's fun. So I've got it all working but there's something bugging me to do with Console.Beep(): it doesn't directly concatenate sounds. For example, running the code below will result in a series of 250-millisecond bursts of sound - but instead of all being run together and sounding as if they are one, they become disjointed, with a ~50ms pause in between each sound.
for(int i = 0; i < 11; i++)
{
Console.Beep(980, 250);
}
So the question is, is there any programmatic way to make the system run the sounds together? I have to say I don't really expect there to be but I figured it was worth an ask, since many other resources seem to just accept the fact that it doesn't.
You can't, that method uses kernel's functions. I will prove:
[SecuritySafeCritical]
[HostProtection(SecurityAction.LinkDemand, UI = true)]
public static void Beep(int frequency, int duration)
{
if (frequency < 37 || frequency > 32767)
{
throw new ArgumentOutOfRangeException("frequency", frequency, Environment.GetResourceString("ArgumentOutOfRange_BeepFrequency", new object[]
{
37,
32767
}));
}
if (duration <= 0)
{
throw new ArgumentOutOfRangeException("duration", duration, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
}
Win32Native.Beep(frequency, duration);
}
This is the Console.Beep's code, it uses Win32Native.Beep to actually perform beep (Aside from the checks above it), and that method leads to:
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool Beep(int frequency, int duration);
A function that imported from kernel.
Unless you hard-code and modify your kernel, you can't. (Which I am sure you don't want to)
I can give you an alternative: http://naudio.codeplex.com/, you can instead control your sound by using this tool and giving it stream. (You can create stream that don't use file as source)
Related
I have created a small C# console app to move the pointer around the screen, in the hope that this would prevent the screen from sleeping / locking after a few minutes. Unfortunately the screen still goes to sleep after a few minutes.
Does anyone know if it's actually possible to write something in C# which will act like user input (either mouse or keyboard), and prevent the screen from sleeping / locking automatically?
Here is what I have, which I thought might do the trick.
class Program
{
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
static Random rnd = new Random();
static void Main(string[] args)
{
Rectangle screenRes = Screen.PrimaryScreen.Bounds;
int widtMax = screenRes.Width;
int heighMax = screenRes.Height;
int w;
int h;
do
{
while (!Console.KeyAvailable)
{
w = rnd.Next(1, widtMax);
h = rnd.Next(1, heighMax);
SetCursorPos(w, h);
System.Threading.Thread.Sleep(1000);
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
}
You can make use of SetThreadExecutionState
Enables an application to inform the system that it is in use, thereby
preventing the system from entering sleep or turning off the display
while the application is running.
Remarks
Calling SetThreadExecutionState without ES_CONTINUOUS simply resets
the idle timer; to keep the display or system in the working state,
the thread must call SetThreadExecutionState periodically.
To run properly on a power-managed computer, applications such as fax
servers, answering machines, backup agents, and network management
applications must use both ES_SYSTEM_REQUIRED and ES_CONTINUOUS when
they process events. Multimedia applications, such as video players
and presentation applications, must use ES_DISPLAY_REQUIRED when they
display video for long periods of time without user input.
Applications such as word processors, spreadsheets, browsers, and
games do not need to call SetThreadExecutionState.
DllImport
[DllImport("kernel32.dll", CharSet = CharSet.Auto,SetLastError = true)]
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
Enums
[FlagsAttribute]
public enum EXECUTION_STATE :uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
// Legacy flag, should not be used.
// ES_USER_PRESENT = 0x00000004
}
Usage
void PreventSleep ()
{
// Prevent Idle-to-Sleep (monitor not affected) (see note above)
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_AWAYMODE_REQUIRED);
}
UPDATE 02/08/2021:
In case anyone is looking for a complete example, here is a project I found on github that has implemented this: https://github.com/pedrolcl/screensaver-disabler
I have created a small C# console app to move the pointer around the screen, in the hope that this would prevent the screen from sleeping / locking after a few minutes. Unfortunately the screen still goes to sleep after a few minutes.
Does anyone know if it's actually possible to write something in C# which will act like user input (either mouse or keyboard), and prevent the screen from sleeping / locking automatically?
Here is what I have, which I thought might do the trick.
class Program
{
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
static Random rnd = new Random();
static void Main(string[] args)
{
Rectangle screenRes = Screen.PrimaryScreen.Bounds;
int widtMax = screenRes.Width;
int heighMax = screenRes.Height;
int w;
int h;
do
{
while (!Console.KeyAvailable)
{
w = rnd.Next(1, widtMax);
h = rnd.Next(1, heighMax);
SetCursorPos(w, h);
System.Threading.Thread.Sleep(1000);
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
}
You can make use of SetThreadExecutionState
Enables an application to inform the system that it is in use, thereby
preventing the system from entering sleep or turning off the display
while the application is running.
Remarks
Calling SetThreadExecutionState without ES_CONTINUOUS simply resets
the idle timer; to keep the display or system in the working state,
the thread must call SetThreadExecutionState periodically.
To run properly on a power-managed computer, applications such as fax
servers, answering machines, backup agents, and network management
applications must use both ES_SYSTEM_REQUIRED and ES_CONTINUOUS when
they process events. Multimedia applications, such as video players
and presentation applications, must use ES_DISPLAY_REQUIRED when they
display video for long periods of time without user input.
Applications such as word processors, spreadsheets, browsers, and
games do not need to call SetThreadExecutionState.
DllImport
[DllImport("kernel32.dll", CharSet = CharSet.Auto,SetLastError = true)]
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
Enums
[FlagsAttribute]
public enum EXECUTION_STATE :uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
// Legacy flag, should not be used.
// ES_USER_PRESENT = 0x00000004
}
Usage
void PreventSleep ()
{
// Prevent Idle-to-Sleep (monitor not affected) (see note above)
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_AWAYMODE_REQUIRED);
}
UPDATE 02/08/2021:
In case anyone is looking for a complete example, here is a project I found on github that has implemented this: https://github.com/pedrolcl/screensaver-disabler
Let's say my script is defined as given below.
public GameObject _GameObject;
private void Start()
{
[![enter image description here][1]][1]
_GameObject = gameObject;
}
Would this execute faster?
public void SetActive(bool value)
{
[1]: https://i.stack.imgur.com/S60FB.jpg
gameObject.SetActive(value);
}
Or this?
public void SetActive(bool value)
{
_GameObject.SetActive(value);
}
In Unity 4.x and below, the cache method would be significantly faster. In those versions, MonoBehaviour.transform and MonoBehaviour.gameObject were not actually fields; rather, "under the hood" they behaved like properties with an attached accessor.
Thus accessing the gameObject property would make a method call to Component.get_gameobject() via the accessor. Of course, a method call naturally imposes more overhead than a simple memory access. (Transform was worse; apparently the accessor actually invoked the GetComponent method to return the value!)
This is why you will often see veteran Unity developers caching these values.
I have it on good authority that this process has been streamlined in Unity 5 for better performance; using the built-in properties will still create a very small amount of overhead but it is reportedly insignificant.
Source: https://blogs.unity3d.com/2014/06/23/unity5-api-changes-automatic-script-updating/
I assumed that caching the variable is faster than using the gameObject variable from the Component class and a simple test proved that to be true. That's because caching it will give you the reference rather than using gameObject which uses the get accessor to return the reference. Not sure if getting the reference requires a native function call but that's a possibility. Using get accessor is slower than direct reference access.
Let's say you have 1 million scripts calling gameObject.activeSelf or through the cached version _GameObject.activeSelf.
Test Result:
gameObject: 54 ms
Cached _GameObject: 30 ms
Software/Hardware tested on:
Unity 5.6.0f3
Windows 10 Pro
MacBookPro11,4
16 GB RAM
Does it matter?
In a normal app, maybe not. In a game, yes. Removing 24ms from a game is a good improvement depending on the kind of Game.
Test script:
public GameObject _GameObject;
void Start()
{
Application.runInBackground = true;
int iterations = 1000000;
//TEST 1
Stopwatch stopwatch1 = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
bool active = gameObject.activeSelf;
}
stopwatch1.Stop();
//TEST 2
Stopwatch stopwatch2 = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
bool active = _GameObject.activeSelf;
}
stopwatch2.Stop();
//SHOW RESULT
WriteLog(String.Format("gameObject: {0}", stopwatch1.ElapsedMilliseconds));
WriteLog(String.Format("Cached _GameObject: {0}", stopwatch2.ElapsedMilliseconds));
}
void WriteLog(string log)
{
UnityEngine.Debug.Log(log);
}
I have written an ordinary dispatcher timer method for creating a gameloop in WPF. I notice though that if it is set to a shorter interval than say 200 ms, it doesn't catch up correctly.
I printed the seconds to screen (see code below) and compared it to my wrist watch. With a setting of 500 ms, it's okay, but if I set it much lower there is a huge discrepancy. I tried a setting of 10 ms, and that meant that the time onscreen passed only 38 seconds in a (real) minute! (Note that all my game engine code was removed during testing, so it's just the timer loop that is called. Also, it doesn't matter if I run the code from VS or the exe file in the Debug folder.)
Note that the games I create run smoothly, it's just that my (standard) Each_Tick method doesn't get called at the correct times. This in turn means that my games will run faster on a faster computer.
So how do I keep correct track of time and make sure that the Each_Tick method fires at the same time, independently of the computer (or cellphone) used? That is, I would rather have a limit on the number of game objects, collision detection precision etc, but on time, rather than just going as fast as possible. Put differently, if I set the timer increment value to 50ms (which I think is reasonable as that would mean 20 times per second), I really want the game to be updated 20 times per second.
I really don't want to get into threading etc if it's possible to avoid it, as the games themselves run fine now. I just want them to play back at the same speed.
I looked up some great replies at How to control frame rate in WPF by using dispatcher timer accurately? but this still doesn't answer my question: how do I get my games to run at the same speed, regardless of (modern) computer/cell phone and whether it's WPF/UWP or perhaps something else?
Or is this impossible to do in a rather easy manner, and I should just accept that game speed depends on the computer used?
Thanks!
Code:
public void StartTimer()
{
//This variable is used to get to the controls (labels etc) of the MainWindow (WPF)
MainWindow mainWin = System.Windows.Application.Current.Windows.Cast<System.Windows.Window>().FirstOrDefault(window => window is MainWindow) as MainWindow;
time = TimeSpan.FromSeconds(0);
//What the code below does is this:
//For each 10 ms, call the different methods. Then add 10 ms to the current time.
timer = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 10), DispatcherPriority.Normal, delegate
{
if (runGame == false) return; //only go on if not in pause mode
mainWin.txtInfo.Text = time.ToString("mm\\:ss");//Shows the timer in a textbox, only showing minutes and seconds.
//Collision code etc removed during the test
time = time.Add(TimeSpan.FromMilliseconds(10)); //adds a specified time to the current time
}, System.Windows.Application.Current.Dispatcher);
}
Note that the code above was added for testing purposes. The original code (facing the same problems) looks like this:
public void StartTimer()
{
//A note on the dispatcherTimer http://www.wpf-tutorial.com/misc/dispatchertimer/
var timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 10); // Each every n milliseconds (set low to avoid flicker)
timer.Tick += EachTick;
timer.Start();
}
// A testing counter
int counter = 0;
// Raised every tick while the DispatcherTimer is active.
private void EachTick(object sender, object e)
{ etc
Build in timers are not very accurate. Use this code snippet. Ive used this timer many times. This timer is really accurate. Kudos to John
public class AccurateTimer
{
private delegate void TimerEventDel(int id, int msg, IntPtr user, int dw1, int dw2);
private const int TIME_PERIODIC = 1;
private const int EVENT_TYPE = TIME_PERIODIC;
[DllImport("winmm.dll")]
private static extern int timeBeginPeriod(int msec);
[DllImport("winmm.dll")]
private static extern int timeEndPeriod(int msec);
[DllImport("winmm.dll")]
private static extern int timeSetEvent(int delay, int resolution, TimerEventDel handler, IntPtr user, int eventType);
private readonly int _mTimerId;
public AccurateTimer(int delay)
{
timeBeginPeriod(1);
_mTimerId = timeSetEvent(delay, 0, TimerTick, IntPtr.Zero, EVENT_TYPE);
}
public void Stop()
{
timeEndPeriod(1);
System.Threading.Thread.Sleep(100);// Ensure callbacks are drained
}
private void TimerTick(int id, int msg, IntPtr user, int dw1, int dw2)
{
Console.WriteLine("Tick " + DateTime.Now.TimeOfDay.TotalMilliseconds);
}
}
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;