0
101 Jan 27, 2007 at 04:16

I was able to do this in Java, so there must be a way to do this using OpenAL. I’m a competent google user and even after extensive searching I can not find a lot of useful information pertaining to loading audio line-out stream to a buffer.

My intent is to develop a tool to analyze any audio signal coming from my system mixer. After many hours of research, studying, and putting together pieces of code, I managed to get an application built which stores LINE-IN data in to a buffer and I know it works as I generate output.

GREAT, almost there! How do I get this to work with LINE-OUT -instead-?

I beg, help me. I can only discover how to retrieve from a file or line-in, there’s nothing I can find for line-out streams.

#include <windows.h>
#include <stdio.h>
#include <AL/al.h>
#include <AL/alc.h>

int main( int argc, char *argv[] )
{
ALCdevice *mydevice;
ALCcontext *mycontext;

mydevice = alcOpenDevice (NULL);
mycontext = alcCreateContext (mydevice, NULL);
alcMakeContextCurrent (mycontext);

ALubyte mybuf[16384];
ALint samples;
ALint leftch, rightch;

const ALchar *devicelist = alcGetString (NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
if (devicelist)
{
printf ("Available Capture Devices are:-\n");

while (*devicelist)
{
printf ("%s\n", devicelist);
devicelist += strlen (devicelist) + 1;
}
}

const char *szDefaultCaptureDevice = alcGetString (NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
printf ("\nDefault Capture Device is '%s'\n\n", szDefaultCaptureDevice);

mydevice = alcCaptureOpenDevice (NULL, 8000, AL_FORMAT_STEREO16, 3200);
alcCaptureStart (mydevice);

while(1)
{
alcGetIntegerv (mydevice, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &samples);
if (samples > 0)
{
alcCaptureSamples(mydevice, (ALCvoid *)mybuf, samples);
}

leftch  = ((ALint *)mybuf)[0];
rightch = ((ALint *)mybuf)[1];
printf ("samples: %d L:%6d   R:%6d    \r", samples, leftch, rightch );
fflush (stdout);

Sleep (1);
}

alcCaptureStop (mydevice);
alcCaptureCloseDevice (mydevice);
return 0;
}


#### 8 Replies

0
165 Jan 27, 2007 at 04:33

Why would you expect to be able to read data from line-out? They don’t call it “out” for no reason, you know - it’s an output! I doubt the hardware is able to read from line-out, even if the software were to support it. It’s a nonsensical operation.

0
101 Jan 27, 2007 at 08:28

Ok, when WinAmp is playing music, I want my program to do gymnastics.

:)

I know this could help a lot of other people out, you can’t tell what I’m trying to do? Doesn’t the -idea- translate? Obviously I mean to imply getting the line-out before it’s out, for example ‘on it’s way out grab it.’ -sigh-

I found some sample code that comes with OpenAL under the \sample
directory. The sample code is called “capture,” which has in it what I need, only I can’t get it to compile due to ‘undefined’ errors all over the place; even after adding the appropriate items in linker.

I’ll have to keep at it and post progress. Unless someone knows of a good resource or has an answer?

0
101 Jan 28, 2007 at 20:35

You might want to try figuring out why the ‘capture’ demo doesn’t compile/work first, and then see if you can harvest the code from it. Linker errors are generally easy to solve, so long as you have the right symbols available to you and have similar calling conventions in the client code.

Also: does OpenAL have a forum/support team who might be better equipped to answer this? I only mention it because there’s probably a higher ratio of people there who are well equipped to answer that than there are here.

0
104 Feb 09, 2007 at 12:07

your better off making a plugin for winamp.
thats pretty much impossible using any hilevel interface.
your best bet would be the windows api, if you want to
look there at msdn.com.
usually you output from your program to this so it gets to the speaker
i dunno if tapping into it is even possible, if it is, its a pretty spectacular

0
101 Feb 27, 2007 at 07:05

Well just do what you do best… lol… i don’t know what to say. :huh:

0
101 Feb 27, 2007 at 15:29

Ok here’s an update, I did figure out how to do this and since this thread is still active I’ll post my code for everyone else. This works for me on any machine I try it on…

This is a “bare-bone” version of my further developed app, in this source I included my FFT algorithm, which is rendered by opengl obviously.

I probably did a lot of stupid things, I don’t know, I’m teaching myself everything from the OpenAL specification and programming guide. Everything else I’ve had to figure out too since I can’t freaking get much help since everything I say to anyone is misunderstood. So if you see anything I did that was dumb please tell me and why so I can better understand.

Thanks! and hope this helps someone else out there wanting code like this.

Just fyi, I have A LOT of problems getting this code to work in VISTA, apparently since they removed HAL a lot of stuff is screwed up and I need to get a new sound card or something to get openal code working right…

The signal always seems impossibly low… anyone have any insight in to this? Damn it vista….

Btw I already know the line with “bval = (ALint)(((ALint *)mybuf)/32768.0) / (float)lval;” is a very wrong way of getting that value…. lol I’m working on that part still, it seems to work for the time being.

#include <math.h>
#include <vector>
#include <GL/glut.h>
#include <AL/al.h>
#include <AL/alc.h>

#define SRATE 44100
#define BUF 1024
#define PI 3.1415
using namespace std;

ALCdevice *mydevice;
ALbyte mybuf[SRATE];
ALint samples;
int lval=32768;
int samplesize = (int)(BUF);
int x=0, i=0;
float   fx=0.0, fy=0.0, bval=0.0;

// APP
float _x(float n)
{
return (n/480.0f);
}

float _y(float n)
{
return (n/240.0f);
}

vector<float> fft (vector<float> w)
{
vector<float>
Samples, Im, Re;
int N=w.size(), L=(int)(N/2.0f), j=0, k=0;
float   fIm=0.0, fRe=0.0, ft=0.0;

for (k=0; k<L; k++)
{
Im.push_back(w.at(k*2));
Re.push_back(w.at((k*2)+1));
}

for (j=0; j<N; j++)
{
fIm = 0.0;
fRe = 0.0;
for (k=0; k<L; k++)
{
fIm += Im.at(k) * sin(2*PI*j*k/N);
fRe += Re.at(k) * cos(2*PI*j*k/N);
}
ft = sqrt(fIm*fIm+fRe*fRe);
Samples.push_back(ft);
}
return Samples;
}

/* GLUT callback Handlers */
static void resize(int width, int height)
{
const float ar = (float) width / (float) height;

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);

glMatrixMode(GL_MODELVIEW);
}

static void display(void)
{
vector<float> cvals, fvals;

alcGetIntegerv(mydevice, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &samples);
alcCaptureSamples(mydevice, (ALCvoid *)mybuf, samples);

for (i=0; i<samplesize; i++)
{
bval = (ALint)(((ALint *)mybuf)[i]/32768.0) / (float)lval;
cvals.push_back( bval );
}

for (i=0; i<(samplesize/4.0); i++)
{
fvals.push_back(cvals.at(i));
}
fvals = fft(fvals);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0,0.0,0.0);
glPushMatrix();
glBegin(GL_LINE_STRIP);
for (x=0; x<cvals.size(); x++)
{
fx = _x((float)x) - 2.0f;
fy = (cvals.at(x)/2.0f) - 0.5f;
glVertex3f(fx, fy, -3.0f);
}
glEnd();
glBegin(GL_LINE_STRIP);
for (x=0; x<fvals.size(); x++)
{
fx = _x((float)x) - 0.5f;
fy = (fvals.at(x)/(fvals.size()/8.0f)) + 0.5f;
glVertex3f(fx, fy, -3.0f);
}
glEnd();
glPopMatrix();
glutSwapBuffers();
}

static void key(unsigned char key, int x, int y)
{
switch (key)
{
case 'q':
exit(0);
break;
}
glutPostRedisplay();
}

static void idle(void)
{
glutPostRedisplay();
}

/* Program entry point */
int main(int argc, char *argv[])
{
alGetError();
mydevice = alcCaptureOpenDevice(NULL, SRATE, AL_FORMAT_STEREO16, BUF);
if (alGetError() != AL_NO_ERROR)
{
return 0;
}
alcCaptureStart(mydevice);

glutInit(&argc, argv);
glutInitWindowSize(480,240);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("fftaudio-");

glutReshapeFunc(resize);
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutIdleFunc(idle);

glClearColor(1,1,1,1);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);

glutMainLoop();

alcCaptureStop(mydevice);
alcCaptureCloseDevice(mydevice);

return EXIT_SUCCESS;
}

0
101 Mar 02, 2007 at 17:25

I am interested in your project. I recently posted a thread about doing the same thing with DirectSound, but that seems impossible. I don’t think I can help you at all at this point but maybe you can help me :)

Does this project capture all of the system’s audio output or only the data being mixed in openAL? I am unsure what exactly you are doing with the captured data. I am guessing that this new Capture Device that you create acts like any other capture device, such as capturing a mic input? So you could theoretically capture the line-out data and write it to a file?

Thanks

0
101 Aug 28, 2007 at 23:29

Very interesting project!