katzenjoghurt
11-08-2007 18:41:15
Hi!
One short question before looking deeper in the API:
Can I use OgreAL also for sound INPUT via microphone?
I plan to make my application react to sounds.
Hand clapping, shouting ... basic things. No speech recognition.
Is it possible?
If not - what library would you recommend for this task?
CaseyB
13-08-2007 07:26:27
OgreAL doesn't do input, but OpenAL has that capability. If you have a look at the OpenAL API and OgreAL it should be a good starting point for you to bring that into your app.
katzenjoghurt
25-10-2007 09:34:08
Actually it seems I can't. Spending the last days with other things I came back to sound input now in my project.
Got the microphone initiated but it seems there is no way to get the amplitude out of the buffer.
If you do know a way .. let me know.
CaseyB
25-10-2007 21:25:50
I am looking into it. You can get the raw buffer so you might be able to look through that and get amplitude of each sample. I'll let you know if I find anything.
katzenjoghurt
25-10-2007 21:38:25
Thx for having a look at it!
I coded down this...
int chosenDeviceNumber=1;
const ALCchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
if (pDeviceList)
{
for (int i=0; i<chosenDeviceNumber; i++)
pDeviceList += (strlen(pDeviceList) + 1);
if (*pDeviceList)
{
char msgString[80] = "Chosen Capture Device is:";
strcat(msgString, pDeviceList);
MessageBox(NULL, msgString, NULL, NULL);
}
else MessageBox(NULL, "Chosen Capture Device doesn't exist", NULL, NULL);
}
const ALCchar szMyCaptureDevice = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
pCaptureDevice = alcCaptureOpenDevice(szMyCaptureDevice, 22050, AL_FORMAT_STEREO16, 22050);
alcCaptureStart(pCaptureDevice);
Yet ... after fruitless tries to read out buffer characteristics ... and reading this Creative guy's message ...
http://opensource.creative.com/pipermai ... 10682.html
... I gave up hope.
As the volume is just the amplitude multiplied with the gain ... I don't think there's an easy way then.
CaseyB
25-10-2007 22:29:49
With that he's talking about the output volume. When we poll the input device we get a raw sound wav and you can do some processing on that to get the amplitude, well, at least a relative amplitude. Try this little program:#include "al.h"
#include "alc.h"
#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
int main()
{
const ALCchar *inputList = alcGetString(0,ALC_CAPTURE_DEVICE_SPECIFIER);
const ALCchar *defualtInput = alcGetString(0, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
std::cout << "Available input devices\n-----------------------\n" << std::string(inputList) << std::endl;
std::cout << "\nChoosing: " << std::string(defualtInput) << std::endl;
ALCdevice *device = alcCaptureOpenDevice(defualtInput, 44100, AL_FORMAT_MONO16, 1024);
if(alcGetError(device) != ALC_NO_ERROR)
{
std::cout << "Failed to open device!!";
return -1;
}
alcCaptureStart(device);
if(alcGetError(device) != ALC_NO_ERROR)
{
std::cout << "Failed to start capture!!";
return -1;
}
Sleep(500);
alcCaptureStop(device);
if(alcGetError(device) != ALC_NO_ERROR)
{
std::cout << "Failed to stop capture!!";
return -1;
}
std::vector<INT16> data(1024, 0);
//data.reserve(1024*2);
alcCaptureSamples(device, &data[0], 1024);
if(alcGetError(device) != ALC_NO_ERROR)
{
std::cout << "Failed to capture samples!!";
return -1;
}
// Set Breakpoint HERE
return 0;
}
Set a breakpoint where it says in the code and have a look at the data variable. Each entry is a sample of the sound at a point and as you look at the whole list you should see a waveform if you have a microphone plugged in and some sound going on. You could even put the capture stuff in a loop and plot these values so you can see the sound if you get ambitious.
katzenjoghurt
26-10-2007 15:14:03
I could kiss you, casey!
Framerate dropped from 135 to 125fps ... but .. that's okay.
Stuffed it in a class...
/*micVolume.h*/
#ifndef _micInput_H__
#define _micInput_H__
#include <al.h>
#include <alc.h>
#include <alut.h>
#include <Ogre.h>
class micInput
{
public:
micInput(int deviceNumber);
~micInput();
long update(const Ogre::FrameEvent &evt);
long mVolume;
ALCdevice* pCaptureDevice;
private:
void _capStart();
void _capStop();
float mUpdateIntervall;
float mTimeSinceLastUpdate;
int mBuffsize;
int mChosenDeviceNumber;
};
micInput::micInput(int deviceNumber)
{
mChosenDeviceNumber=deviceNumber;
mUpdateIntervall = 0.100; //in sec
mTimeSinceLastUpdate = 0;
mVolume=0;
mBuffsize=8;
// Get list of available Capture Devices
const ALCchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
if (pDeviceList)
{
{
for (int i=0; i<mChosenDeviceNumber; i++)
pDeviceList += (strlen(pDeviceList) + 1);
#ifdef showDebugInfo
if (*pDeviceList)
{
char msgString[80] = "Chosen Capture Device is:";
strcat(msgString, pDeviceList);
MessageBox(NULL, msgString, NULL, NULL);
}
else MessageBox(NULL, "Chosen Capture Device doesn't exist", NULL, NULL);
#endif
}
}
pCaptureDevice = alcCaptureOpenDevice(pDeviceList, 44100, AL_FORMAT_MONO16, 1024);
#ifdef showDebugInfo
if(alcGetError(pCaptureDevice) != ALC_NO_ERROR)
{
MessageBox(NULL, "Failed to open device!!", NULL, NULL);
//return -1;
}
#endif
_capStart();
}
long micInput::update(const Ogre::FrameEvent &evt)
{
mTimeSinceLastUpdate+=evt.timeSinceLastFrame;
if (mTimeSinceLastUpdate>mUpdateIntervall)
{
mTimeSinceLastUpdate=0;
std::vector<INT16> data(mBuffsize, 0);
//data.reserve(1024*2);
alcCaptureSamples(pCaptureDevice, &data[0], mBuffsize);
// if(alcGetError(pCaptureDevice) != ALC_NO_ERROR)
// {
// //std::cout << "Failed to capture samples!!";
// MessageBox(NULL, "Failed to capture samples!!", NULL, NULL);
// return -1;
// }
long tmpVolume = 0;
int buffysize = data.size();
while (data.size() > 0)
{
tmpVolume += abs(data.back());
data.pop_back();
}
mVolume = tmpVolume / mBuffsize;
}
return mVolume;
}
void micInput::_capStart()
{
alcCaptureStart(pCaptureDevice);
if(alcGetError(pCaptureDevice) != ALC_NO_ERROR)
{
// MessageBox(NULL, "Failed to start capture!!", NULL, NULL);
// return -1;
}
}
void micInput::_capStop()
{
alcCaptureStop(pCaptureDevice);
if(alcGetError(pCaptureDevice) != ALC_NO_ERROR)
{
// MessageBox(NULL, "Failed to stop capture!!", NULL, NULL);
// return -1;
}
}
#endif
Init:
...
#define useMicrophone
...
#ifdef useMicrophone
mMicInput = new micInput(1); //deviceNumber 0: Soundcard, 1: WebCam
#endif
...
bool AppFrameListener::frameStarted(const FrameEvent& evt)
{
#ifdef useMicrophone
float currVolume = mMicInput->update(evt);
#endif
...
}
don't like the data array being initiated again and again though... didn't find out how to put it in the class... or I should say: it behaved weird then.
CaseyB
26-10-2007 21:34:37

Cool! Glad that worked for you!! You should be able to have the data variable be a member of the class, as long as you set the size with the
std::vector<INT16> data(mBuffsize, 0);
in the constructor and read the same number of samples each time it should be ok. I'm sure you'll figure something out! Good luck!