Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Trying an unusual idea with audio feedback  (Read 2679 times)

0 Members and 1 Guest are viewing this topic.

BruceJohnJennerLawso

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • My Code on Github
Trying an unusual idea with audio feedback
« on: November 08, 2014, 09:42:29 pm »
Okay, so my current project is very simple, just this:

// typewriter.cpp //////////////////////////////////////////////////////////////
// An SFML program that runs in the background /////////////////////////////////
// playing audio feedback with each keypress ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//#include <std_files>
//#include "Headers.h"
//#include "Headers.hpp"
//#include "Source.cpp"
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>

int main()
{       sf::SoundBuffer buffer;
        if (!buffer.loadFromFile("./chime.ogg"))
        {       return -1;
        }
        else
        {       sf::Sound chime;
                chime.setBuffer(buffer);
                sf::RenderWindow window(sf::VideoMode(300, 20), "typewriter 1.0");
       
                while (window.isOpen())
                {       sf::Event event;
                        while (window.pollEvent(event))
                        {       if(event.type == sf::Event::Closed)
                                {       window.close();
                                }
                                if (event.type == sf::Event::KeyPressed)
                                {       if (event.key.code == sf::Keyboard::K)
                                        {       chime.play();
                                        }
                                }
                        }
                        window.clear();
                        // eventually this can be some sort of logo
                        window.display();
                }
        }
        return 0;
}
 

The goal of the program is to create a cross-platform app that can provide audio feedback while typing, ie playing the sound of a typewriter click every time a key is pressed, so that the user can have feedback while typing beyond just seeing the output on the screen (also keys could be assigned to a specific pitched sound, but thats obviously more complex.

The goal with this project is to create an app that users can start, and run in the background while working on other tasks. The fairly obvious problem is that the program only works when its window is the focus, not useful when working in another application like a text editor or browser. Is there any way that the program could be set up to receive key inputs in the background, so that the sound will play even when another program is the focus?
Quote
The computer is mightier than the pen, the sword, and usually the programmer.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Trying an unusual idea with audio feedback
« Reply #1 on: November 08, 2014, 10:03:56 pm »
Events are provided by the OS on a per-window basis, so I'm pretty sure any event-based solution will have the problem you describe.

However, real-time input (sf::Keyboard::isKeyPressed()) should not have this limitation.  So you could try remembering the current state of K and playing the sound when isKeyPressed() changes from false to true.  This would also remove the need to have a window at all, which seems like a good idea for a background program.

Other stuff:
- Ideally, try not to include all of the top-level SFML headers and instead only include the specific headers for the classes you actually use.  Or for now put a TODO comment to remind yourself to do that later.
- Be sure to set a framerate limit so you give the other apps time to run.
- For error-checks like if (!buffer.loadFromFile("./chime.ogg")), putting all the code after it in a big "else" block is unnecessary (since you're already returning if there is an error), and doing that all the time will make formatting your code very annoying very fast.
- Your brace & indentation style is a bit...strange.  Not sure if it's a concern but worth mentioning.
« Last Edit: November 08, 2014, 10:17:19 pm by Ixrec »

BruceJohnJennerLawso

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • My Code on Github
Re: Trying an unusual idea with audio feedback
« Reply #2 on: November 08, 2014, 10:37:25 pm »
Thats perfect! thankyou  ;D

Its actually working right now as I type this, absolutely awesome.  8)

Unfortunately the framerate limit seems to have to be rather high in order to keep up with the rate that typing occurs at. Maybe that should be customized as well (user can input their desired frame rate so that people with really good WPM can have it higher if needed. 20 FPS seems to work well for me.

If you could refresh my memory, does calling play on the sf::Sound stop the previous instance of it being played?
(ie if Im calling chime.play(); for every keypress, does a new keypress stop the sound being played for the previous one, if the previous one was not finished?). It seems as if it is doing that, which I would like to stop if possible. Perhaps each key needs its own sf::Sound object to avoid that?

Apologies for the indenting if it is weird, I hate the ANSI-C style with the burning passion of a thousand suns, so I prefer to write code in a different style (its known as Horsttman or something like that IIRC)
Quote
The computer is mightier than the pen, the sword, and usually the programmer.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Trying an unusual idea with audio feedback
« Reply #3 on: November 08, 2014, 10:46:21 pm »
20 FPS doesn't sound that high at all to me.  Many video games will poll a bunch of keys in addition to doing AI and physics and 3D rendering and other stuff every single frame, and they typically aim for 30 or 60 FPS.  But making it configurable does sound like a good idea.

For questions about the behavior of a particular function, always start by looking at the documentation.  In this case, it answers your question perfectly: http://sfml-dev.org/documentation/2.1/classsf_1_1Sound.php#a2953ffe632536e72e696fd880ced2532
Quote
This function starts the stream if it was stopped, resumes it if it was paused, and restarts it from beginning if it was it already playing. This function uses its own thread so that it doesn't block the rest of the program while the sound is played.
So you probably will need an sf::Sound for every key.  Or at least every key that was pressed recently enough for the sound to still be playing.

Oh well, if you like that style then go for it.  At least you're using it consistently, unlike some of the code we see here.

Edit: Not sure if you're using 2.1, but if so you may be interested in using the latest master revision because support for scan codes was added (https://github.com/SFML/SFML/pull/568), and that would help you make your key handling as generic as possible on all sorts of international keyboards.  If you're concerned about such things.
« Last Edit: November 08, 2014, 10:55:05 pm by Ixrec »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Trying an unusual idea with audio feedback
« Reply #4 on: November 09, 2014, 10:52:44 am »
I don't know if it's a concern for you, but it is worth noting that SFML is very inefficient for this kind of program, for two reasons:

- SFML makes one system call for each key being tested, while OSes generally provide functions that allow to retrieve the whole keyboard status in one call

- It's very inefficient to constantly poll the keyboard status at a high rate, I'm not sure about this, but OSes probably provide a way to install a global hook on keyboard events, which would be much more optimized, and remove any lag

So if you want to learn and have some fun I think this is perfect, but if you aim for efficiency you'll probably need to go at lower levels and play with OS specific stuff directly.
Laurent Gomila - SFML developer

BruceJohnJennerLawso

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • My Code on Github
Re: Trying an unusual idea with audio feedback
« Reply #5 on: November 09, 2014, 10:18:33 pm »
Well its fairly efficient compared to the original version of the project involving a series of godawful bash scripts using xdotool, ::) but I do see what you mean. I personally would prefer to keep the project solely as a SFML app, for the sake of simplicity and maintainability. It definitely could be rewritten using OS specific calls to make it faster, but that would probably involve writing lots of ugly code couched in #ifdef statements. Windows I can probably do easily through the Windows API, although I would assume Linux could be done through the kernel? Ive never done anything linux specific in C++, so I dont know. OSX would be the biggest issue though, since I dont own a copy, & I dont really want to buy a copy just for developing stuff.

I appreciate the advice though. :)
Quote
The computer is mightier than the pen, the sword, and usually the programmer.