[Openal] Recording and Playing Simultaneously
Daniel PEACOCK
dpeacock at creativelabs.com
Mon Jul 23 15:20:00 PDT 2007
Hi,
While alcGetIntergerv ALC_CAPTURE_SAMPLES and alcCaptureSamples use "number
of samples", alBufferData uses bytes not samples. This works out to be OK
if you are using 8bit Mono - but if you change formats you will need to
change the alBufferData line of code to convert samples to bytes.
In your code below it doesn't show how the Buffer is being attached
(queued) onto the Source. As you find samples available you need to copy
them to a buffer and then queue the buffer on the end of a playing Source.
The Buffer you are using cannot already be queued on the Source because you
won't be able to change the data (using alBufferData). So you basically
need to wait until a buffer has processed on the playback Source, then fill
it with captured audio data, and then re-queue it on the end of the Source.
Here is some code that does that. It assumes an OpenAL playback device has
already been created and initialized. It also waits for 2 Buffers to be
filled with Captured audio before starting the playback Source.
ALvoid CapturePlayTest(ALvoid)
{
ALCdevice *pCaptureDevice;
const ALCchar *szDefaultCaptureDevice;
ALint lSamplesAvailable;
ALchar ch;
ALchar Buffer[QUEUEBUFFERSIZE];
ALuint SourceID, TempBufferID;
ALuint BufferID[QUEUEBUFFERCOUNT];
ALuint ulBuffersAvailable = QUEUEBUFFERCOUNT;
ALuint ulUnqueueCount, ulQueueCount;
ALint lLoop, lFormat, lFrequency, lBlockAlignment,
lProcessed, lPlaying;
ALboolean bPlaying = AL_FALSE;
ALboolean bPlay = AL_FALSE;
ALint lEnv, lDirect, lRoom;
// NOTE : This code does NOT setup the Wave Device's Audio Mixer to
select a recording input
// or recording level.
// Generate a Source and QUEUEBUFFERCOUNT Buffers for Queuing
alGetError();
alGenSources(1, &SourceID);
for (lLoop = 0; lLoop < QUEUEBUFFERCOUNT; lLoop++)
alGenBuffers(1, &BufferID[lLoop]);
if (alGetError() != AL_NO_ERROR)
{
printf("Failed to generate Source and / or Buffers\n");
return;
}
ulUnqueueCount = 0;
ulQueueCount = 0;
// Get list of available Capture Devices
const ALchar *pDeviceList = alcGetString(NULL,
ALC_CAPTURE_DEVICE_SPECIFIER);
if (pDeviceList)
{
printf("Available Capture Devices are:-\n");
while (*pDeviceList)
{
printf("%s\n", pDeviceList);
pDeviceList += strlen(pDeviceList) + 1;
}
}
szDefaultCaptureDevice = alcGetString(NULL,
ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
printf("\nDefault Capture Device is '%s'\n\n",
szDefaultCaptureDevice);
// The next call can fail if the WaveDevice does not support the
requested format, so the application
// should be prepared to try different formats in case of failure
lFormat = AL_FORMAT_MONO16;
lFrequency = 44100;
lBlockAlignment = 2;
long lTotalProcessed = 0;
long lOldSamplesAvailable = 0;
long lOldTotalProcessed = 0;
pCaptureDevice = alcCaptureOpenDevice(szDefaultCaptureDevice,
lFrequency, lFormat, lFrequency);
if (pCaptureDevice)
{
printf("Opened '%s' Capture Device\n\n",
alcGetString(pCaptureDevice, ALC_CAPTURE_DEVICE_SPECIFIER));
printf("Press 1 to Start Recording and Playing\n");
printf("Press 2 to Stop Recording\n");
printf("Press Q to quit\n");
while (1)
{
if (_kbhit())
{
ch = _getch();
ch = toupper( ch );
switch(ch)
{
case '1':
alcCaptureStart(pCaptureDevice);
bPlay = AL_TRUE;
break;
case '2':
alcCaptureStop(pCaptureDevice);
break;
}
if (ch == 'Q')
{
alcCaptureStop(pCaptureDevice);
break;
}
}
else
{
alGetError();
alcGetIntegerv(pCaptureDevice, ALC_CAPTURE_SAMPLES,
1, &lSamplesAvailable);
if ((lOldSamplesAvailable != lSamplesAvailable) ||
(lOldTotalProcessed != lTotalProcessed))
{
printf("Samples available is %d, Buffers
Processed %d \n", lSamplesAvailable, lTotalProcessed);
lOldSamplesAvailable = lSamplesAvailable;
lOldTotalProcessed = lTotalProcessed;
}
// If the Source is (or should be) playing, get
number of buffers processed
// and check play status
if (bPlaying)
{
alGetSourcei(SourceID, AL_BUFFERS_PROCESSED,
&lProcessed);
while (lProcessed)
{
lTotalProcessed++;
// Unqueue the buffer
alSourceUnqueueBuffers(SourceID, 1,
&TempBufferID);
// Update unqueue count
if (++ulUnqueueCount ==
QUEUEBUFFERCOUNT)
ulUnqueueCount = 0;
// Increment buffers available
ulBuffersAvailable++;
lProcessed--;
}
// If the Source has stopped (been starved of
data) it will need to be
// restarted
alGetSourcei(SourceID, AL_SOURCE_STATE,
&lPlaying);
if (lPlaying == AL_STOPPED)
{
printf("Buffer Stopped, Buffers
Available is %d \n", ulBuffersAvailable);
bPlay = AL_TRUE;
}
}
if ((lSamplesAvailable > (QUEUEBUFFERSIZE /
lBlockAlignment)) && !(ulBuffersAvailable))
{
OutputDebugString("underrun!\n");
}
else
// When we have enough data to fill our
QUEUEBUFFERSIZE byte buffer, grab the samples
if ((lSamplesAvailable > (QUEUEBUFFERSIZE /
lBlockAlignment)) && (ulBuffersAvailable))
{
// Consume Samples
alcCaptureSamples(pCaptureDevice, Buffer,
QUEUEBUFFERSIZE / lBlockAlignment);
alBufferData(BufferID[ulQueueCount], lFormat,
Buffer, QUEUEBUFFERSIZE, lFrequency);
// Queue the buffer, and mark buffer as
queued
alSourceQueueBuffers(SourceID, 1,
&BufferID[ulQueueCount]);
if (++ulQueueCount == QUEUEBUFFERCOUNT)
ulQueueCount = 0;
// Decrement buffers available
ulBuffersAvailable--;
// If we need to start the Source do it now
IF AND ONLY IF we have queued at least 2 buffers
if ((bPlay) && (ulBuffersAvailable <=
(QUEUEBUFFERCOUNT - 2)))
{
alSourcePlay(SourceID);
printf("Buffer Starting
\n");
bPlaying = AL_TRUE;
bPlay = AL_FALSE;
}
}
}
}
alcCaptureCloseDevice(pCaptureDevice);
}
else
{
printf("WaveDevice is unavailable, or does not supported the
request format\n");
}
alSourceStop(SourceID);
alDeleteSources(1, &SourceID);
for (lLoop = 0; lLoop < QUEUEBUFFERCOUNT; lLoop++)
alDeleteBuffers(1, &BufferID[lLoop]);
}
Dan
Creative Labs, Inc.
Notice
The information in this message is confidential and may be legally
privileged. It is intended solely for the addressee. Access to this
message by anyone else is unauthorized. If you are not the intended
recipient, any disclosure, copying or distribution of the message, or
any action taken by you in reliance on it, is prohibited and may be
unlawful. If you have received this message in error, please delete it
and contact the sender immediately. Thank you.
Spike7d5
<spike7d5 at yahoo.c
om> To
Sent by: openal at opensource.creative.com
openal-bounces at op cc
ensource.creative
.com Subject
[Openal] Recording and Playing
Simultaneously
07/23/2007 02:17
PM
Hello,
I want to record and play sound at the same time, but I don't know how to
do
this. I've managed to play my own recordings, but I can't manage to combine
these 2 together. Can anybody help me, please?
Throughout the program, every AL function is checked for errors, and one
appears at alBufferData - "invalid value passed to AL function". Here is a
small portion of my code, that I believe is important. And also, I must say
that the program never gets to that printf.
ALCdevice *deviceCapture = alcCaptureOpenDevice(NULL, 22050,
AL_FORMAT_MONO8, (ALCsizei) 10000);
...
char bufferCapture[220500];
int total = 0;
while (key != 27)
{
ALCint samples;
alcGetIntegerv(deviceCapture, ALC_CAPTURE_SAMPLES, 1,
&samples);
if (samples >= 1)
{
alcCaptureSamples(deviceCapture, bufferCapture,
samples);
if ((result = alGetError()) == AL_NO_ERROR)
{
alBufferData(buffer, AL_FORMAT_MONO8,
bufferCapture, samples, 22050);
if ((result = alGetError()) !=
AL_NO_ERROR)
{
printf("Error setting
capture buffer: %s\n", getErrorString(result));
_getch();
return -1;
}
alSourcePlay(source);
total += samples;
printf("%d\n", total);
}
else
{
printf("Error getting samples: %s\n",
getErrorString(result));
_getch();
return -1;
}
}
if (_kbhit())
key = _getch();
}
--
View this message in context:
http://www.nabble.com/Recording-and-Playing-Simultaneously-tf4132517.html#a11752973
Sent from the OpenAL - User mailing list archive at Nabble.com.
_______________________________________________
Openal mailing list
Openal at opensource.creative.com
http://opensource.creative.com/mailman/listinfo/openal
ForwardSourceID:NT00044582
More information about the Openal
mailing list