OSx Keyboard presses C

2019-09-20 07:08发布

I'm coding an experimental design and I need to be able to play sounds from a number of speakers/channels and then have the user press a corresponding key when they believe the sound is coming from a certain speaker/channel. (ie: Participant thinks sound is coming from speaker 4 so presses key 4). I want to be able to record how long it takes between the sound being played and the time it takes for the user to press a key.

As I'm playing sounds from the same application I don't really want to lock up the application by continually waiting for user input. I'm guessing I could throw the user input on another thread but what's the best way to achieve this? I obviously don't want the user to have to press enter after each key press.

I'm using OSx and C.

标签: c input
1条回答
一夜七次
2楼-- · 2019-09-20 08:08

In synopsis form, your code will contain among other things 2 threads. Run in a secondary thread, an iOS tone initiator. In the primary thread, an elapsed timer, a while loop that includes a key trap, and an escape condition, whereby the loop can be exited when condition met.

Some pseudo code: (using some Windows functions for concept illustration)

int gRunning = 1;
//Initiate tone in a secondary thread 
//initialize elapsed time keeper to start
while(gRunning)
{
    //Call key trap function here
    //if Key Hit, set gRunning == 0;
}
//Get elapsed time here
//Kill tone and secondary thread

int KeyTrap(void)
{
    //Write code here using GetAsyncKeyState() to check hits on relevant keys
    return "any key hit"
}

The following functions could be used in an actual implementation:

short GetAsyncKeyState(int);  

and

time_t clock()  

GetAsyncKeyState() is commonly used in console applications to allow monitoring, or responding to user key strokes. If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState. However, you should not rely on this last behavior; for more information, see the Remarks.

For example, to catch when the 'k' or 'K' key has been hit, (you can code a series of these up into a "keyHandler" function to get multiple keys), then call within in a while loop:

    state = GetAsyncKeyState('k');
    state1 = GetAsyncKeyState('K'); 
    if ((0x80000000 & state) || 
        (0x80000000 & state1))
    {    
             //do something here
    }

clock() Returns the number of system clock cycles that have occurred since the program started executing. The number of clock ticks can include time used by other processes. To convert the number of clock cycles to seconds, divide by CLOCKS_PER_SEC to obtain an approximation to the nearest millisecond.

Note time.h in my environment defines CLOCKS_PER_SEC as follows:

#if defined(_NI_unix_) || defined(_NI_sparc_)
#define CLOCKS_PER_SEC 1000000
#elif defined(_NI_mswin16_) || defined(_NI_mswin32_) || defined(_NI_mswin64_)
#define CLOCKS_PER_SEC 1000
#elif defined(_NI_mac_)
#define CLOCKS_PER_SEC 1  

So, for the Mac, it looks like your best resolution will be 1 second using clock()

Another option, this one giving millisecond resolution:
GetLocalTime()

eg:

SYSTEMTIME s;
GetLocalTime(&s); 
swprintf_s(buff, L"[%02d:%02d:%02d:%d]\t", s.wHour, s.wMinute, s.wSecond, s.wMilliseconds);

Where SYSTEMTIME is defined:

typedef struct _SYSTEMTIME {
    WORD wYear;
    WORD wMonth;
    WORD wDayOfWeek;
    WORD wDay;
    WORD wHour;
    WORD wMinute;
    WORD wSecond;
    WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;  
查看更多
登录 后发表回答