Linux, C++ audio capturing (just microphone) library - c++

I'm developing a musical game, it's like a singstar but instead of singing, you have to play the recorder. It's called oFlute, and it's still in early development stage.
In the game, I capture the microphone input, then run a simple FFT analysis and compare the results to typical recorder's frequencies, thus getting the played note.
At the beginning, the audio library I was using was RtAudio, but I don't remember why I switched to PortAudio, which is what I'm currently using. The problem is that, from time to time, either it crashes randomly or stops capturing, like if there were no sound coming from the microphone.
My question is, what's the best option to capture microphone input on Linux? I just need to open, read, and close a flow of bytes from the microphone.
I've been reading this guide, and (un)surprisingly it says:
I don't think that PortAudio is very good API for Unix-like operating systems.
So, what do you recommend me?

PortAudio is a strange choice given the other options.
I would personally abstract away from everything and use GStreamer. Audio can be a horrible mess on Linux (speaking as a long term sufferer). Letting Gstreamer deal with that lets you forget about it, move along and not have to think about it again.
OpenAL is probably the most popular for game dev though and it should support most systems (although you will have "fun" getting it playing nice with PulseAudio).
I'd certainly make sure you're developing for the most popular setup (which is PulseAudio at the moment, I reckon) so you don't end up in a situation where you release and you're plunged into a pool of people moaning about the sound not working.
And don't listen to the nonsense about PulseAudio - it might be new and it might take up a few more resources than a barebones ALSA system but it's certainly not mired with latency issues. Asking people to remove it isn't an option with modern desktop distros as it's so tightly integrated (and useful too).

Related

Shutting down fan c++ [duplicate]

Is there a Windows standard way to do things such as "start fan", "decrease speed" or the like, from C/C++?
I have a suspicion it might be ACPI, but I am a frail mortal and cannot read that kind of documentation.
Edit: e.g. Windows 7 lets you select in your power plan options such as "passive cooling" (only when things get hot?) vs. "active cooling" (keep the CPU proactively cool?). It seems the OS does have a way to control the fan generically.
I am at the moment working on a project that, among other things, controls the computer fans. Basically, the fans are controlled by the superIO chip of your computer. We access the chip directly using port-mapped IO, and from there we can get to the logical fan device. Using port-mapped IO requires the code to run in kernel mode, but windows does not supply any drivers for generic port IO (with good reason, since it is a very powerful tool), so we wrote our own driver, and used that.
If you want to go down this route, you basically need knowledge in two areas: driver development and how to access and interpret superIO chip information. When we started the project, we didn't know anything in either of these areas, so it has been learning by browsing, reading and finally doing. To gain the knowledge, we have been especially helped by looking at these links:
The WDK, which is the Windows Driver Kit. You need this to compile any driver you write for windows, With it comes a whole lot of source code for example drivers, including a driver for general port-mapped IO, called portio.
WinIO has source code for a driver in C, a dll in C that programmatically installs and loads that driver, and some C# code for a GUI, that loads the dll and reads/writes to the ports. The driver is very similar to the one in portio.
lm-sensors is a linux project, that, among other things, detects your superIO chip. /prog/detect/sensors-detect is the perl program, that does the detecting, and we have spent some time going through the code to see how to interface with a superIO chip.
When we were going through the lm-sensors code, it was very nice to have tools like RapidDriver and RW-everything, since they allowed us to simulate a run of sensors-detect. The latter is the more powerful, and is very helpful in visualising the IO space, while the former provides easier access to some operations which map better to the ones in sensors-detect (read/write byte to port)
Finally, you need to find the datasheet of your superIO chip. From the examples, that I have seen, the environment controllers of each chip provide similar functionality (r/w fan speed, read temperature, read chip voltage), but vary in what registers you have to write to in order to get to this functionality. This place has had all the datasheets, we have needed so far.
If you want something real quick to just lower fans to a level where you know things won't overheat, there's the speedfan program to do so. Figuring out how to configure it in the early versions to automatically lower fans to 50% on computer startup was so painful that my first approach was to simply byte-patch it to start the only superio managed fan I had at lower speed. The newer versions are still bit tough but it's doable - there's a graphical slider system that looks like audio equalizer except that the x axis is temp and y is fan speed. You drag them down one by one. After you figure out how to get manual control for the fan you want, this is next step.
There's a project to monitor hardware (like fans) with C#:
http://code.google.com/p/open-hardware-monitor/
I haven't extensively looked at it, but the source code and use of WinRing0.sys atleast gives the impression that if you know what fan controller you have and have the datasheet, it should be modifiable to also set values instead of just getting them. I don't know what tool is suited (beside kernel debugger) to look at what Speedfan does, if you preferred to snoop around and imitate speedfan instead of looking at the datasheets and trying things out.
Yes, It would be ACPI, and to my knowledge windows doesn't give much/any control over that from user space. So you'd have to start mucking with drivers, which is nigh impossible on windows.
That said, google reveals there are a few open source windows libraries for this for specific hardware... so depending on your hardware you might be able to find something.
ACPI may or may not allow you to adjust the fan settings. Some BIOS implementations may not allow that control though -- they may force control depending on the BIOS/CMOS settings. One might be hard-pressed for a good use case where the BIOS control (even customized) is insufficient. I have come across situations where the BIOS control indeed was insufficient, but not for all possible motherboard platforms.
WIndows Management Instrumentation library (WMI) does provide a Win32_Fan Class and even a SetSpeed method. Alas, the docs say this is not implemented, so I guess it's not very helpful. But you may be able to control things by setting the power state.

Playing sound in C++ using native system calls?

So in Windows, you can use the PlaySound function to play an MP3 file in a C++ application. What would be some similar functions available for use in Mac OS X/Linux? I would also appreciate it if you could link to some sample Hello-World type programs demonstrating this.
You can just open("/dev/dsp") and write to it. That's as "native syscall" as you can get, I believe.
Concerning Audio: Linux != Mac, so I will answer both separately.
MacOS uses the core audio framework for low level audio. Building on that there are several higher level APIs. If you just want to play a sound file the AV Foundation Framework is most likely the way to go. Here you find an example to build a simple app for iOS, which can be ported to MacOS easily.
For Linux the whole situation is quite delicate. There exist many different frameworks and libraries and it very unclear which is low and which is high level, since some of them are emulating the others. Basically there is ALSA and OSS for low level audio. Both of them are crap. Jack is aiming to provide a framework for professional audio but it's not very portable (at least if you are interested in embedded devices). Most Linux OS currently are using PulseAudio as their audio server, which has also a simple API for just playing a single sound and a very difficult API for low level stuff. And then there is the gstreamer library, which is rather portable and has a half way descent API and is especially designed for playing audio & video files and streams, and so probably the way to go on linux.
I personally recommend to use PortAudio, which is a library that provides – as the name states – an audio framework which is portable across several operating systems and audio frameworks. PortAudio is also well designed and has a simple but flexible API.
Well, I'm not sure if current desktops have some more advanced services/libraries that play audio files, but if you really want to do some low-level OS audio output, start looking here. Maybe this is a little too low-level for your needs.

SDL_Mixer MIDI Volume issues on Windows Vista/7

I'm not actually well versed in C++ or SDL_Mixer, but I'm asking this question anyway on behalf on the Doom community. Put simply, nobody writing Doom source ports can seem to figure out how to control normal sound volume and MIDI sound volume independently using SDL_Mixer on Windows Vista or 7. I'll let James Haley, author of Eternity Engine, put it in his own words:
Seems the concept of independent volume for native MIDI doesn't exist under Windows Vista or 7, as using MIDI volume sliders in any application that has them (including most games that use SDL_mixer) also affects the volume of digital sound output. This makes attempting to adjust the relative volume of music for comfort impossible.
Has anybody found any workarounds for this? I'm guessing it's unlikely given how Microsoft seems to have skimped throughout the OS on any way to control the volume of individual sound devices separately.
I've heard of various workarounds all involving a Timidity driver, but this requires the user go above and beyond simply installing the game on his system. The only port that I know of that definitively fixes this issue is ZDoom, but it uses the GPL-incompatible FModEx and is thus not a suitable solution.
If you want some code to look at, Chocolate Doom is perhaps the easiest Doom source port to grok and you can grab its source here.
Any suggestions on other open-source sound and music libraries would be welcome as well.
A solution would be to ship with a FluidSynth-enabled SDL_mixer. You would also need to ship a SoundFont2 file to go with it. Fortunately, there are free SF2's out there, and some are even optimized for Doom's MIDI files. Licenses shouldn't be a problem, since SoundFonts are assets, not code.
You then load the SF2 using Mix_SetSoundFonts().
You may want to look at different MIDI libraries outside of SDL.
http://wildmidi.sourceforge.net/
http://sourceforge.net/apps/trac/fluidsynth/
http://timidity.sourceforge.net
I am maintaining a similar game port (Descent 2), and I have come across the same problem. Afaik there is no solution for it when using SDL_mixer. A cure to avoid sound being muted when turning off midi music I have found is to retrieve a handle to a temporary midi device, set the midi volume to max and then close the temporary device again.
For the longest time, the only solution we found was to use something like PortMIDI. However, Quasar of Eternity Engine fame has come across a neat solution:
http://www.doomworld.com/vb/showthread.php?s=&postid=1124981#post1124981
He essentially puts SDL_Mixer into its own process and controls it with RPC. Very clever.
So one problem with the previous answer I gave was that sometimes the MIDI subprocess did not behave itself, and would break or stop working in strange ways. Eternity's specific implementation used IDL, and I personally re-implemented it using pipes, but the subprocess itself was a bug magnet.
Thankfully, another answer was figured out rather recently. You can simply bypass SDL_Mixer entirely and deal with Windows' native MIDI support directly, which turns out to not require a ton of code once you know what you're doing.
https://github.com/chocolate-doom/chocolate-doom/blob/master/src/i_winmusic.c
You can also implement this sort of idea with PortMIDI and get the benefit of being able to communicate with external MIDI devices as well.
https://github.com/odamex/odamex/blob/stable/client/sdl/i_musicsystem_portmidi.cpp

Where can I start with programmable Hardware?

I've had a desire to learn at least a tiny bit about programming hardware for quite some time now and thought I'd ask here to get some starting points. I am a reasonably accomplished programmer with Delphi and Objective-c experience but have never even listened to a device port / interupt (I dont even know the terminology) let alone programmed a piece of hardware.
To start with what I would like to be able to do is,
Buy a simple bit of kit with 2,3 or 10 buttons
Plug the device into my pc via USB
Listen to the device and write some code to do something once the button is pressed.
I reckon this is a good place to start, anyone got pointers on hardware to buy or how I could start this?
I like the Arduino, easy to use, open source and a great community!
Good to get started with, and uses a subset of C/C++.
Also, has alot of addon hardware available, like GPS, Bluetooth, Wifi etc
My experiences with Arduino have been nothing but good, from the point you get it out of it's box (and install the free compiler on either Windows / Mac / Linux), to building your first 'sketch' (a project or application for the Arduino).
Making an application is easy, you have a Setup Method, which is called on startup, and then a loop method which is looped while the Arduino is running.
Then all you have to do is hook either inputs or outputs up to the pins on the Arduino board, tell the code what they are and hopefully you'll get the desired output.
One other really good thing about the Arduino (and others I'm sure) is that you now have a use for those old broken printers, or 2x CD-Rom's that no one wants, and every other little bit of out dated technology. It's amazing what you can find in a server room!
Now, I have only worked on small projects, like plugging in an LCD, and reading the room temp and various projects like that. But based on what I have done, I am happy with the Ardunio, it gives a good base to embedded programming and if it's not enough, you can always go bigger!
My 2 cents!
There's also the hot-off-the press netduino which uses the .NET Micro Framework and Microsoft Visual C# Express. I don't know that's it's better than the Arduino but it's another option.
Why don't you start with AVR programming for microprocessors. Yeh it might be a bit too low level. but I know many people that have started with it for hardware programming. you could find a compiler here. http://winavr.sourceforge.net/ and a good tutorial here: http://www.ladyada.net/learn/avr/
The previous poster mentioned the Arduino, but you should also consider a Teensy. It's basically the same thing, but price is a little better. You also have the option of using it in "Arduino" mode, or raw AVR mode. I don't know if Arduinos give you both options.
There is a comparison page where you can see the Teensy has some better hardware. The built-in USB gives it much better performance.
I would definitely suggest trying out various microcontrollers. Arduino Controllers are nice and have a number of tutorials.
However, its not your only option. In school, I worked with Microchip PICs, which are also quite nice for the hobbyist scene. The nice thing about the PIC was that our microcontrollers textbook supported it, so we got to see the application as we were learning the theory.
If I understand your question right, you are not interested in embedded programming. You want to buy something that works from the begining and control it from Windows.
When it comes to buttons, there is not much to do in Windows. These are HID controls and Windows handles all the interfacing for you. Nothing too exciting there.
In that case you can grab any Joystick and use the DirectInput (a part of the DirectX tech.) to interact with it. With force feedback you can do some cool stuff.
A more fun project would be to buy a Wii control and write some fun applicartions.
Look at this site to get some ideas of what I mean:
http://johnnylee.net/projects/wii/
Since Windows has no support for a Wii contrller, you really get to do some work here :)
I see that you like Delphi, so you can take a look at AvrCo Multitasking Pascal for AVR. You can try it at http://www.e-lab.de. MEGA8/88 version is free. There are tons of drivers, simulator, JTAG online debugger and programmer with visualization of all standard devices (for a startup, you can make a simple LPT programmer with just a few resistors). It can also make programs for all Arduino devices out there, since AVR is in their hearth. Atmel's STK500 is a good beginner board, with leds, switches, and few other peripherals. If you prefer open source, then WinAVR with GCC could be your path.
As already mentioned, Arduino is a good choice. The community is large and helpful. The nice thing is that you can transition right to a "real" language by using the GCC port for AVR micros, if you want. On my latest project I did this - prototype most of it with Arduino, then re-write it in C.
Starting with buttons and LEDs is a great idea. Build some confidence in working with basic hardware first, before modding the Wii!
Some links:
Windows GCC cross compiler (1 step install) for AVR: WinAVR
A Arduino clone kit
Adafruit is another good source of starter hardware and tech advice
The embedded StackOverflow
Any program you already write interacts with hardware, there's the monitor, keyboard, mouse, speaker etc. Getting a simple setup where your program can deal with buttons on a USB device will not teach you that much about working with hardware. It's partly a question of how low you want to go in the software stack and how much you want to learn about what happens at the point where the software ends.
Get yourself a copy of "The Art of
Electronics". It's a relatively easy read and covers everything between Ohm's law and the microprocessor and will give you a good idea of what the complete system does.
Read it.
Check out Digikey. You can buy anything hardware related from resistors, capacitors, IC's, low cost boards easily online and for reasonable prices.
Other replies mentioned Microchip PIC and Atmel AVR which are small and simple microcontrollers. Both companies have a wealth of application notes, check out their web site, read through some app notes. You can get low cost evaluation boards for the above or something like the Arduino mentioned in other replies. Consider designing and building your own board to force yourself to learn the basics. Find a friend who is an EE or serious hobbyist who wouldn't mind helping you with some tips.
If you want to learn more about PC hardware you can take a look at some simple device drivers (e.g. printer or serial port) under Windows (download the WinDDK), Linux or even DOS. Programming under something like DOS on a PC allows for relatively easy interaction with the PC hardware, you can use a printer port to read push buttons etc.
Links (I'm a new user so I can't link directly):
www.amazon.com/Art-Electronics-Paul-Horowitz/dp/0521370957
www.digikey.com/
www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2879
www.atmel.com/products/avr/

Playing sounds over the microphone in c++

I am making a program in C++ for Windows XP that requires sound to be played so that any program that is currently recording the microphone can hear it, but it will not come out of the speakers. There seems to be no "real" way of doing it, but it is possible to go into "sndvol32 -R" and set the Wave out mix or similar as the current input device. Then you can turn the master volume to 0, play the sound, turn it back up, and reset the input device to the microphone. Is there a way of doing this transparently, or setting the current input device using functions, so that you dont have to see sndvol32 pop up?
Thanks
Doing this would require a complicated kernel-level driver.
Fortunately for you, someone has already done this (it's not free, but it's a fantastic program).