Detecting microphone input with C++

Listening for an audio signal and logging the event

Page 1 of 1

8 Replies - 38264 Views - Last Post: 22 September 2009 - 04:43 PM Rate Topic: -----

#1 Knowledge8069   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 17-September 09

Detecting microphone input with C++

Posted 17 September 2009 - 05:08 PM

I am working on a C++ program which will do the following:

1. Waits for any audio signal from an integrated laptop microphone
2. Logs that an event occurred in a .txt file (time calculated by counter)
3. Repeats

Eventually the sound will be a single clap in an otherwise quiet room. However at this point detection of ANY sound will be fine. I have investigated the use of waveIn() and the DirectSound libraries, also the use of APIs, but they seem to be complete overkill for this task. All I would like is to detect an audio signal in so that a flag may be set. From this flag the log loop will execute. Then the flag is reset and the system continues to listen. It will do this in 1 second intervals. I am not looking for code from you, I would just like some feedback on what to start with. I'm drowning in library features right now that I don't need.

Here is my code. Please note that I am not including the headers and all of my Visual C++ 2008 Express Edition project files. If it is needed I will post them, but I thought I would make this concise at first. Also ignore the rest of the stuff, I am still working on it. The part where I need to put the audio event detection code is labeled "// Audio signal event detection." Thanks in advance.

// CodeTimer.cpp : main project file.
// Using Query Performance Counter.

#include "stdafx.h"
#include <tchar.h>
#include <windows.h>
#include <iostream>
#include <fstream>

using namespace System;
using namespace std;

int main()
{
	// Prepare log for output.
	ofstream timeLog ("log.txt");

	if (timeLog.is_open())
	{
		cout << "Events Detected\n";
		cout << "---------------\n\n";
		//timeLog.close();
	}

	else cout << "Unable to open file";

	// Initialize timer when condition met.
	int never = 0;
	int clap = 0;

	while(never == 0)
	{
		// Audio signal event detection.


		// Timer series.
		__int64 ctr1 = 0, ctr2 = 0, freq = 0;
		int acc = 0, i = 0;

		// Start timing the code.
		if (QueryPerformanceCounter((LARGE_INTEGER *)&ctr1)!= 0)
		{
			// Code segment is being timed.
			while (clap != 1)
			{
				acc++;

				if (clap == 1)
				{
					timeLog << "Event logged\n";
				}
			}

			// Finish timing the code.
			QueryPerformanceCounter((LARGE_INTEGER *)&ctr2);

			Console::WriteLine("Start Value: {0}",ctr1.ToString());
			Console::WriteLine("End Value: {0}",ctr2.ToString());

			QueryPerformanceFrequency((LARGE_INTEGER *)&freq);

			Console::WriteLine(S"QueryPerformanceCounter minimum resolution: 1/{0} Seconds.",freq.ToString());
			// In Visual Studio 2005, this line should be changed to: Console::WriteLine("QueryPerformanceCounter minimum resolution: 1/{0} Seconds.",freq.ToString());	
			Console::WriteLine("100 Increment time: {0} seconds.",((ctr2 - ctr1) * 1.0 / freq).ToString());
		}
		else
		{
			DWORD dwError = GetLastError();
			Console::WriteLine(S"Error value = {0}",dwError.ToString());// In Visual Studio 2005, this line should be changed to: Console::WriteLine("Error value = {0}",dwError.ToString());
		}

		// Make the console window wait.
		Console::WriteLine();
		Console::Write("Press ENTER to finish.");
		Console::Read();
	}

	return 0;
}


This post has been edited by Knowledge8069: 17 September 2009 - 05:13 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Detecting microphone input with C++

#2 poncho4all   User is offline

  • D.I.C Head!
  • member icon

Reputation: 123
  • View blog
  • Posts: 1,422
  • Joined: 15-July 09

Re: Detecting microphone input with C++

Posted 17 September 2009 - 05:26 PM

Im not sure but i think DirectShow has something for that
http://msdn.microsof...454(VS.85).aspx

Hope that helps
Was This Post Helpful? 1
  • +
  • -

#3 log3337   User is offline

  • D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 78
  • Joined: 22-July 09

Re: Detecting microphone input with C++

Posted 17 September 2009 - 05:44 PM

this is isnt rely a reply so much as a question: isnt Console::Read() and similar function C# material?

if not, what did you use to get them to work, i tried all your namespaces and header files

This post has been edited by log3337: 17 September 2009 - 05:46 PM

Was This Post Helpful? 0
  • +
  • -

#4 Knowledge8069   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 17-September 09

Re: Detecting microphone input with C++

Posted 17 September 2009 - 07:17 PM

View Postlog3337, on 17 Sep, 2009 - 04:44 PM, said:

this is isnt rely a reply so much as a question: isnt Console::Read() and similar function C# material?

if not, what did you use to get them to work, i tried all your namespaces and header files



Some of this is from the C++ code for QueryPerformanceCounter. You have to enable Common Language Runtime Support, Old Syntax under the Options menu. I built some of this code by following Microsoft's instructions found here:

http://support.microsoft.com/kb/815668

The instructions on that page go quickly, if you follow the steps to build the project it should work correctly.

This post has been edited by Knowledge8069: 17 September 2009 - 07:17 PM

Was This Post Helpful? 0
  • +
  • -

#5 Knowledge8069   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 17-September 09

Re: Detecting microphone input with C++

Posted 17 September 2009 - 07:22 PM

View Postponcho4all, on 17 Sep, 2009 - 04:26 PM, said:

Im not sure but i think DirectShow has something for that
http://msdn.microsof...454(VS.85).aspx

Hope that helps


Yeah I know there is probably something in there, but I can't figure out how to use it. The library dwarfs my program many times over. I keep reading the stuff but it's always something more complex than what I'm trying to do. It talks about waveIn() again in the audio capture part of that API but I can't figure out how to use it for what I'm doing.
Was This Post Helpful? 0
  • +
  • -

#6 poncho4all   User is offline

  • D.I.C Head!
  • member icon

Reputation: 123
  • View blog
  • Posts: 1,422
  • Joined: 15-July 09

Re: Detecting microphone input with C++

Posted 17 September 2009 - 07:39 PM

Have you seen this forum?
http://stackoverflow...cord-microphone
Was This Post Helpful? 1
  • +
  • -

#7 jeff666   User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 193
  • Joined: 30-December 08

Re: Detecting microphone input with C++

Posted 18 September 2009 - 09:24 AM

View Postponcho4all, on 17 Sep, 2009 - 06:39 PM, said:

Have you seen this forum?
http://stackoverflow....


It's a complete newbies forum, especially for Win32
(some answers are just laughable..)

This post has been edited by jeff666: 18 September 2009 - 09:25 AM

Was This Post Helpful? 0
  • +
  • -

#8 poncho4all   User is offline

  • D.I.C Head!
  • member icon

Reputation: 123
  • View blog
  • Posts: 1,422
  • Joined: 15-July 09

Re: Detecting microphone input with C++

Posted 18 September 2009 - 03:01 PM

Ya i forgot to remove that link this is the one i wanted you to check
http://www.techmind.org/wave/
Thats an example and the complete documentation is here
http://msdn.microsof...735(VS.85).aspx

Hope that helps it was the closest thing i could find, i have never worked with a microphone but it looks interesting.
Was This Post Helpful? 1
  • +
  • -

#9 Knowledge8069   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 17-September 09

Re: Detecting microphone input with C++

Posted 22 September 2009 - 04:43 PM

Went through the forums recommended, thanks for the help. Found what I need (I think) here:

http://support.microsoft.com/kb/181550

The only problem is I can't get mixerGetLineControls to work. Everything compiles, but the error message pops up from the mixerGetLineControls declaration when running the program in a console.

This program should monitor the volume level on the input line and store a value in "volume." On my laptop it will say input level is 0 (Windows XP), on my desktop computer (Windows Vista) it will give a very large random number. Any ideas? I've included a screenshot of what I get. From the screenshot you can see that the program takes control somehow, adding itself to the Vista mixer source list. However there is still the error, and "volume" never changes.

// CodeTimer.cpp : main project file.
// Using Query Performance Counter.

#include "stdafx.h"
#include <tchar.h>
#include <windows.h>
#include <iostream>
#include <fstream>
#include <mmsystem.h>

using namespace System;
using namespace std;

#pragma comment(lib, "winmm.lib")

int main()
{
	// Prepare log for output.
	ofstream timeLog ("log.txt");

	if (timeLog.is_open())
	{
		cout << "Events Detected\n";
		cout << "---------------\n\n";
		//timeLog.close();
	}

	else cout << "Unable to open file";

	// Initialize timer when condition met.
	int never = 0;
	int clap = 0;

	while(never == 0)
	{
		// Audio signal event detection.
		MMRESULT rc;			  // Return code.
		HMIXER hMixer;			// Mixer handle used in mixer API calls.
		MIXERCONTROL mxc;		 // Holds the mixer control data.
		MIXERLINE mxl;			// Holds the mixer line data.
		MIXERLINECONTROLS mxlc;   // Obtains the mixer control.

		// Open the mixer. This opens the mixer with a deviceID of 0. If you
		// have a single sound card/mixer, then this will open it. If you have
		// multiple sound cards/mixers, the deviceIDs will be 0, 1, 2, and
		// so on.
		rc = mixerOpen(&hMixer, 0,0,0,0);
		if (MMSYSERR_NOERROR != rc) {
			// Couldn't open the mixer.
			cout << "Couldn't open the mixer.\n";
		}

		// Initialize MIXERLINE structure.
		ZeroMemory(&mxl,sizeof(mxl));
		mxl.cbStruct = sizeof(mxl);

		// Specify the line you want to get. You are getting the input line
		// here. If you want to get the output line, you need to use
		// MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT.
		mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;

		rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
			MIXER_GETLINEINFOF_COMPONENTTYPE);
		if (MMSYSERR_NOERROR == rc) {
			// Couldn't get the mixer line.
			cout << "Couldn't get the mixer line.\n";
		}

		// Get the control.
		ZeroMemory(&mxlc, sizeof(mxlc));
		mxlc.cbStruct = sizeof(mxlc);
		mxlc.dwLineID = mxl.dwLineID;
		mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_PEAKMETER;
		mxlc.cControls = 1;
		mxlc.cbmxctrl = sizeof(mxc);
		mxlc.pamxctrl = &mxc;
		ZeroMemory(&mxc, sizeof(mxc));
		mxc.cbStruct = sizeof(mxc);
		rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
			MIXER_GETLINECONTROLSF_ONEBYTYPE);
		if (MMSYSERR_NOERROR != rc) {
			// Couldn't get the control.
			cout << "Couldn't get the control.\n";
		}

		// After successfully getting the peakmeter control, the volume range
		// will be specified by mxc.Bounds.lMinimum to mxc.Bounds.lMaximum.

		MIXERCONTROLDETAILS mxcd;			 // Gets the control values.
		MIXERCONTROLDETAILS_SIGNED volStruct; // Gets the control values.
		long volume;						  // Holds the final volume value.

		// Initialize the MIXERCONTROLDETAILS structure
		ZeroMemory(&mxcd, sizeof(mxcd));
		mxcd.cbStruct = sizeof(mxcd);
		mxcd.cbDetails = sizeof(volStruct);
		mxcd.dwControlID = mxc.dwControlID;
		mxcd.paDetails = &volStruct;
		mxcd.cChannels = 1;

		// Get the current value of the peakmeter control. Typically, you
		// would set a timer in your program to query the volume every 10th
		// of a second or so.
		rc = mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd,
			MIXER_GETCONTROLDETAILSF_VALUE);
		if (MMSYSERR_NOERROR == rc) {
			// Couldn't get the current volume.
			cout << "Couldn't get the current volume.\n";
		}
		volume = volStruct.lValue;

		// Get the absolute value of the volume.
		if (volume < 0)
			volume = -volume;

		// Operations for input signal detected.
		cout << "Signal level from mic: " << volume << endl;

		// Timer series.
		__int64 ctr1 = 0, ctr2 = 0, freq = 0;
		int acc = 0, i = 0;

		// Start timing the code.
		if (QueryPerformanceCounter((LARGE_INTEGER *)&ctr1)!= 0)
		{
			// Code segment is being timed.
			/*while (clap != 1)
			{
			acc++;

			if (clap == 1)
			{
			timeLog << "Event logged\n";
			}
			}*/

			// Finish timing the code.
			QueryPerformanceCounter((LARGE_INTEGER *)&ctr2);

			Console::WriteLine("\nStart Value: {0}",ctr1.ToString());
			Console::WriteLine("End Value: {0}",ctr2.ToString());

			QueryPerformanceFrequency((LARGE_INTEGER *)&freq);

			Console::WriteLine(S"QueryPerformanceCounter minimum resolution: 1/{0} Seconds.",freq.ToString());
			// In Visual Studio 2005, this line should be changed to: Console::WriteLine("QueryPerformanceCounter minimum resolution: 1/{0} Seconds.",freq.ToString());	
			Console::WriteLine("100 Increment time: {0} seconds.",((ctr2 - ctr1) * 1.0 / freq).ToString());
		}
		else
		{
			DWORD dwError = GetLastError();
			Console::WriteLine(S"Error value = {0}",dwError.ToString());// In Visual Studio 2005, this line should be changed to: Console::WriteLine("Error value = {0}",dwError.ToString());
		}

		// Make the console window wait.
		Console::WriteLine();
		Console::Write("Press ENTER to finish.\n\n");
		Console::Read();
	}

	return 0;
}

Attached image(s)

  • Attached Image

This post has been edited by Knowledge8069: 22 September 2009 - 04:50 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1