We help IT Professionals succeed at work.

unbuffered input

aiwa
aiwa asked
on
470 Views
Last Modified: 2010-04-15
How can I get unbuffered input from the keyboard, and be able to check if there is no key being pressed when I call it? I will be useing DOS.
Comment
Watch Question

Commented:
Both unbuffered input, and checking if a key has been pressed are system specific actions. Systems do offer such functionality, but it will not be portable.

Please indicate which operating system you are working in.

Author

Commented:
Edited text of question

Commented:
You can use the kbhit function (in conio.h) to test if a key is being pressed.  If a key is pressed, true is returned.  Then you can use getch to determine what the key was.  If no key was pressed, false is returned and you can go on with your program.  Here is some sample code.  (I know that kbhit is available in Borland C, I am not sure about others.  Its worth a try.)



#include <stdio.h>
#include <conio.h>

void main()
{
  char x;

  while (x!='x') if (kbhit()) {x = getch();   printf("%c key pressed.\n",x);}
  else printf("No key pressed.\n");
}

Author

Commented:
Thanks.
So why when I hit a key and keep my hand on it do my program not produce a continuous tone, which stops when I lift the key?


#include <dos.h>
#include <conio.h>
#include <ctype.h>

void playnote(unsigned int note)
{
      sound(note);
      delay(20);
            if(note == 0){
            nosound();
            }

}

int main()
{
char note;

      do{

      if (kbhit()){
            note = getch();
      }
      else
                                    note = 0;

      note = toupper(note);

            switch(note)
            {
                  case 'S' :
                         playnote(254);
                  break;

                  case 'D' :
                         playnote(297);
                  break;

                  case 'F' :
                         playnote(330);
                  break;

                  case 'G' :
                         playnote(352);
                  break;

                  case 'H' :
                         playnote(396);
                  break;

                  case 'J' :
                         playnote(440);
                  break;

                  case 'K' :
                         playnote(495);
                  break;

                  case 'L' :
                         playnote(528);
                  break;
            }
      }
      while(note != 'Q');

return 0;
}

Author

Commented:
Thanks.
So why when I hit a key and keep my hand on it do my program not produce a continuous tone, which stops when I lift the key?


#include <dos.h>
#include <conio.h>
#include <ctype.h>

void playnote(unsigned int note)
{
      sound(note);
      delay(20);
            if(note == 0){
            nosound();
            }

}

int main()
{
char note;

      do{

      if (kbhit()){
            note = getch();
      }
      else
                                    note = 0;

      note = toupper(note);

            switch(note)
            {
                  case 'S' :
                         playnote(254);
                  break;

                  case 'D' :
                         playnote(297);
                  break;

                  case 'F' :
                         playnote(330);
                  break;

                  case 'G' :
                         playnote(352);
                  break;

                  case 'H' :
                         playnote(396);
                  break;

                  case 'J' :
                         playnote(440);
                  break;

                  case 'K' :
                         playnote(495);
                  break;

                  case 'L' :
                         playnote(528);
                  break;
            }
      }
      while(note != 'Q');

return 0;
}

Commented:
You are doing nothing to turn the sound off.  Your playsound function turns off the sound if the note is zero, but I you never seem to call playsound(0).

Why don't you change this line:

else
                                    note = 0;


to this:

else {note = 0; playsound(0);}  

Commented:
>  So why when I hit a key and keep my hand on it do my program not produce a continuous tone?

The answer to that question is that the keyboard does not continuously send characters when a key is down. If you observe the behaviour you get in a word processor, you will notice that when you depress a key you get a single instance of the character, followed by a pause, followed by a stream of the character at some set rate.
kbhit allows you to determine if there is a character there for getch to get. Neither it, nor getch are geared to do what you wish to do namely: make the keyboard behave like a musical instrument by reporting on the state of the key (pressed or unpressed).
You might be able to fake it, if you can use the delay in playnote to pause longer than it takes the keyboard to produce another character. This will, of course, be at the expense of a certain amount of responsiveness of the program. I.e. When you release a key, it will not stop sounding for up to the full delay time specified.

To do that you would have to process the raw scancodes as they come in, in some fashion. They come with a "make" or "break" code indicating the state of the key. But accomplishing that will be a much bigger job.

Author

Commented:
OK Thanks that fixes the not turning off problem but why is there that little pause at the start of a long note, I have set the keyboards repeat delay and repeat rate both to max. How can I get a continuously tone.
Sorry if you think I am just using ye to debug my code but I don't know how to overcome these problems.

Commented:
Sorry, that got garbled somehow. The last paragraph should have been up a bit:

>  So why when I hit a key and keep my hand on it do my program not produce a continuous tone?

The answer to that question is that the keyboard does not continuously send characters when a key is down. If you observe the behaviour you get in a word processor, you will notice that when you depress a key you get a single instance of the character, followed by a pause, followed by a stream of the character at some set rate.
kbhit allows you to determine if there is a character there for getch to get. Neither it, nor getch are geared to do what you wish to do namely: make the keyboard behave like a musical instrument by reporting on the state of the key (pressed or unpressed).
To do that you would have to process the raw scancodes as they come in, in some fashion. They come with a "make" or "break" code indicating the state of the key. But accomplishing that will be a much bigger job.

You might be able to fake it, if you can use the delay in playnote to pause longer than it takes the keyboard to produce another character. This will, of course, be at the expense of a certain amount of responsiveness of the program. I.e. When you release a key, it will not stop sounding for up to the full delay time specified.

Commented:
One other thing, take out the delay(20).

Author

Commented:
OK
Where can I find eather code for a simple music program, or the code that imladris is talking about. I searched under C CODE and could find nothing.

Author

Commented:
OK
Where can I find eather code for a simple music program, or the code that imladris is talking about. I searched under C CODE and could find nothing.

Author

Commented:
I cannot turn off the delay as I would get a good pitch (good as the system speker goes:)

Author

Commented:
I cannot turn off the delay as I would get a good pitch (good as the system speker goes:)

Commented:
Searched under "c code" where?

Author

Commented:
I used the WebFerret it uses about 14 search engens, I hoped people would have there code on the net.

Author

Commented:
I used the WebFerret it uses about 14 search engens, I hoped people would have there code on the net.

Author

Commented:
I used the WebFerret it uses about 14 search engens, I hoped people would have there code on the net.

Author

Commented:
I used the WebFerret it uses about 14 search engens, I hoped people would have there code on the net.

Author

Commented:
I used the WebFerret it uses about 14 search engens, I hoped people would have there code on the net.

Author

Commented:
I used the WebFerret it uses about 14 search engens, I hoped people would have there code on the net.

Author

Commented:
I used the WebFerret it uses about 14 search engens, I hoped people would have there code on the net.

Commented:
Why did you post 6 times?

Searching for "c code" is way too general.  You're going to get hundreds of thousands of sites.

I will be on the lookout for programs like this.  Meanwhile, try this:



void main()
{
  asm {
       start:  call getkey
                        cmp al,1bh
                        jne skip
                        jmp done
       skip:   call beep
                        jmp start
       getkey: mov ah,7
                        int 21h
                        ret

       beep:   mov bl,al
                        mov al, 0b6h
                        out 42h+1,al
                        mov al,0
                        out 42h,al
                        mov al,bl
                        out 42h,al
                        mov al,4fh
                        out 61h,al
                        mov cx,0ffffh
                        rep lodsw
                        mov al,4dh
                        out 61h,al
                        mov ah,2
                        mov dl,0eh
                        int 21h
                        ret
       done:
  }


}

Author

Commented:
Thanks scrapdog, can you explain it a little?

Sorry about the meny postings, I have beening hitting reload and for some reasion that must resend the date

Commented:
It is assembly language...I just threw this together as an experiment...probably not what you want, but this is the easiest way to access ports and the keyboard directly.

I will keep looking for source code that will be more understandable.

Author

Commented:
I have done a little assembly language, So if you can stick in a few comments or tell me where I can fine an instuction set. I've worked with the 68HC11. Do these instruction work with all CPU's ?

Commented:
int calls an interrupt, out sends data to a port (in this case ports $42 and $61 are of interest to us if we want to manipulate the speaker), mov is "move" which is self-explanatory, jne is branch if not equal, cmp is compare, ret is return.  I don't think if I could convert that to 68HC11, but hopefully you get an idea what these instructons do.  These instructions will only run on an Intel 80x86 compatible CPU.
Hello guys.

Why don't ya try this one??

#include <dos.h>
#include <conio.h>
#include <ctype.h>

void playnote(unsigned int note)
{
      sound(note);
      if (note == 0)
            nosound();
      delay(100);
}

int main()
{
      char note;
      do{
            kbhit() ? note = getch() : note = 0;
            switch(toupper(note)) {
                  case 'S' : playnote(254); break;
                  case 'D' : playnote(297); break;
                  case 'F' : playnote(330); break;
                  case 'G' : playnote(352); break;
                  case 'H' : playnote(396); break;
                  case 'J' : playnote(440); break;
                  case 'K' : playnote(495); break;
                  case 'L' : playnote(528); break;
                  default  : playnote(0);
            }
      } while (note != 'Q');
      return 0;
}

Hope this helps!

Cheers,
Viktor

Author

Commented:
This dos not fix the first dealy problem, I want to be able to "play it like a instrument". So if someone can send towards code that will do that for me.

Author

Commented:
Adjusted points to 210

Commented:
Try the following code. Just copy and paste the code and compile it. Scrapdog, I don't think its a good idea to use Assembler because when compiling the code in a UNIX environment the program will not work. Also there are ports functions in C that you can use, like 'outp' in "CONIO.H". This will make the code more portable.

#include "conio.h"
#include "ctype.h"
#include "dos.h"

void main()
{
      void play_selection(char);

      char note;
      
      do
      {
            if (kbhit()) note = toupper(getch());
            play_selection(note);

      } while (note != 'Q');
}

void play_selection(char call_var)
{
      void playnote(unsigned int);
      
      switch(call_var)
      {
            case 'S':playnote(254); break;
            case 'D':playnote(297); break;
            case 'F':playnote(330); break;
            case 'G':playnote(352); break;
            case 'H':playnote(396); break;
            case 'J':playnote(440); break;
            case 'K':playnote(495); break;
            case 'L':playnote(548); break;
            default: playnote(0); break;
      }
}

void playnote(unsigned int note)
{
      if (!note) sound(0);  /* Plays no sound OR
                         Whatever sound you choose*/
      else
      {
            sound(note);
            delay(4);
      }
      nosound();
}

Author

Commented:
Agin that dos not do waht I want it to do, previous code was better, and this program will never see UNIX, a pity I accept but thats life!   I want an instrument like response, If this is not achievable through C than suggest alternatives. If not I think the points should go to schrapdog

Author

Commented:
Agin that dos not do waht I want it to do, previous code was better, and this program will never see UNIX, a pity I accept but thats life!   I want an instrument like response, If this is not achievable through C than suggest alternatives. If not I think the points should go to schrapdog

Author

Commented:
Oh NO it's bubbling posting on me agin!!
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION

Commented:
It would probably be a good idea to make an array of booleans for the keys pressed.  For example, when a make code is received, set the corresponding element in the array to TRUE, and when a break code is received, set it to FALSE.

And when you get to your play routine, check to see which keys are down by checking this array of booleans.  Play the sound the corresponds to the FIRST key that has a value of true.

The reason for this is that if you rely simply on the make and break codes, ANY break code will turn the sound off.  For example, lets say you press A and hold it down, and then your press S a millsecond before you let up on the A key;  the make code from the S will cause the S note to be played, but then the break code from the A will immediately shut it off.

If you use the method of using an array, you would only shut off the sound if ALL values in the array are false, i.e. NO key is down.

Using an array will also allow you to recognize if more than one key is down, if you wanted to be able to play more than one note at a time.  The PC speaker can only play one note at a time, but you could simulate two or more notes by arpeggiating them.  The best way to arpeggiate is to use the timer interrupt.

Author

Commented:
I got it to work at last!! Thanks for all your help!!!

Commented:
I am truely impressed you got it to work! I'm bemused in that case as to why you gave me a D for the answer. Did you use someone else's information?

Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.