Discussion:
alcCaptureSamples crashes on stereo capturing
Philipp Kraus
2012-08-09 14:14:09 UTC
Permalink
Hello,

I have got this code for capturing mono 8 bit data, the code works
without any error:

m_device = alcCaptureOpenDevice( p_device.c_str(),
static_cast<ALCuint>(p_sampingfrequency), AL_FORMAT_MONO8,
static_cast<ALCsizei>(p_buffersize));

ublas::vector<ALubyte> l_buffer(m_buffersize);
alcCaptureStart(m_device);
while(m_capturing)
{
alcGetIntegerv(...)
l_samplesread = std::min(
static_cast<std::size_t>(l_samplesread), l_buffer.size()-i);
alcCaptureSamples(m_device, (ALCvoid*)(&l_buffer[i]), l_samplesread);
}

If I switch the the AL_FORMAT_MONO8 to AL_FORMAT_STEREO8 and change the
p_buffersize to 2*p_buffersize & m_buffersize to 2*m_buffersize the
code crashes
on the alcCaptureSamples line and the buffer is not filled. IMHO the
left channel should be the even elements in the l_buffer and the right
the odd ones, so if I create
a double size buffer each l_buffer block should be started with the
left channel data. If I disable the alcCaptureSample call, the correct
number of samples are received.

Can anybody help me please to create the correct stereo working option?

Thx

Phil
Philipp Kraus
2012-08-09 18:52:40 UTC
Permalink
Post by Philipp Kraus
Hello,
I have got this code for capturing mono 8 bit data, the code works
m_device = alcCaptureOpenDevice( p_device.c_str(),
static_cast<ALCuint>(p_sampingfrequency), AL_FORMAT_MONO8,
static_cast<ALCsizei>(p_buffersize));
ublas::vector<ALubyte> l_buffer(m_buffersize);
alcCaptureStart(m_device);
while(m_capturing)
{
alcGetIntegerv(...)
l_samplesread = std::min(
static_cast<std::size_t>(l_samplesread), l_buffer.size()-i);
alcCaptureSamples(m_device, (ALCvoid*)(&l_buffer[i]), l_samplesread);
}
If I switch the the AL_FORMAT_MONO8 to AL_FORMAT_STEREO8 and change the
p_buffersize to 2*p_buffersize & m_buffersize to 2*m_buffersize the
code crashes
on the alcCaptureSamples line and the buffer is not filled. IMHO the
left channel should be the even elements in the l_buffer and the right
the odd ones, so if I create
a double size buffer each l_buffer block should be started with the
left channel data. If I disable the alcCaptureSample call, the correct
number of samples are received.
The error message is: incorrect checksum for freed object - object was
probably modified after being freed
Chris Robinson
2012-08-10 03:20:44 UTC
Permalink
Post by Philipp Kraus
Hello,
I have got this code for capturing mono 8 bit data, the code works
m_device = alcCaptureOpenDevice( p_device.c_str(),
static_cast<ALCuint>(p_sampingfrequency), AL_FORMAT_MONO8,
static_cast<ALCsizei>(p_buffersize));
ublas::vector<ALubyte> l_buffer(m_buffersize);
alcCaptureStart(m_device);
while(m_capturing)
{
alcGetIntegerv(...)
l_samplesread = std::min(
static_cast<std::size_t>(l_samplesread), l_buffer.size()-i);
alcCaptureSamples(m_device, (ALCvoid*)(&l_buffer[i]),
l_samplesread);
}
If I switch the the AL_FORMAT_MONO8 to AL_FORMAT_STEREO8 and change the
p_buffersize to 2*p_buffersize & m_buffersize to 2*m_buffersize the code
crashes
on the alcCaptureSamples line and the buffer is not filled.
It looks like you're not accounting for the count being in sample
frames, so you're asking for n sample frames, but only have enough space
for n/2 (since it needs two channels for each sample frame).
l_buffer.size() is samples*channels, not the number of samples.

l_buffer.size()/2 is the number of samples to fill for stereo.
Philipp Kraus
2012-08-10 08:35:35 UTC
Permalink
Post by Chris Robinson
Post by Philipp Kraus
Hello,
I have got this code for capturing mono 8 bit data, the code works
m_device = alcCaptureOpenDevice( p_device.c_str(),
static_cast<ALCuint>(p_sampingfrequency), AL_FORMAT_MONO8,
static_cast<ALCsizei>(p_buffersize));
ublas::vector<ALubyte> l_buffer(m_buffersize);
alcCaptureStart(m_device);
while(m_capturing)
{
alcGetIntegerv(...)
l_samplesread = std::min(
static_cast<std::size_t>(l_samplesread), l_buffer.size()-i);
alcCaptureSamples(m_device, (ALCvoid*)(&l_buffer[i]),
l_samplesread);
}
If I switch the the AL_FORMAT_MONO8 to AL_FORMAT_STEREO8 and change the
p_buffersize to 2*p_buffersize & m_buffersize to 2*m_buffersize the code
crashes
on the alcCaptureSamples line and the buffer is not filled.
It looks like you're not accounting for the count being in sample
frames, so you're asking for n sample frames, but only have enough
space for n/2 (since it needs two channels for each sample frame).
l_buffer.size() is samples*channels, not the number of samples.
l_buffer.size()/2 is the number of samples to fill for stereo.
Yes, my code shows exactly;


m_device = alcCaptureOpenDevice( p_device.c_str(),
static_cast<ALCuint>(m_samplingfrequency), AL_FORMAT_STEREO8,
static_cast<ALCsizei>(m_buffersize));
ublas::vector<ALubyte> l_buffer(2*m_buffersize);
alcCaptureStart
wile(m_capturing)
{
for(std::size_t i=0; i < l_buffer.size(); )
{
ALint l_samplesread = 0;
alcGetIntegerv(m_device, ALC_CAPTURE_SAMPLES,
static_cast<ALCsizei>(sizeof(ALint)), &l_samplesread);
i if ( (!l_samplesread) && (alcIsExtensionPresent(m_device,
"ALC_EXT_disconnect")) )
{
stop capturing
}

if (l_samplesread > 0)
{
l_samplesread = std::min(
static_cast<std::size_t>(l_samplesread), l_buffer.size()-i);
alcCaptureSamples(m_device, (ALCvoid*)(&l_buffer(i)),
l_samplesread);
i += l_samplesread;
}
}
}
alcCaptureStop

I think this correct, because the buffer has got the double size, so
left / right channel are correct stored. If I write the l_buffer down
to std::cout the values are correct, but
on calling the dtor of my object, I get the same error.
My l_samples is the number of samples that are read or is it on stereo
the number of frames?
IMHO a frame stores 2 elements of ALubyte, so my buffer must have
2*m_buffersize

Thanks

Phil
Chris Robinson
2012-08-10 09:06:33 UTC
Permalink
Post by Philipp Kraus
Yes, my code shows exactly;
if (l_samplesread > 0)
{
l_samplesread = std::min(static_cast<std::size_t>(l_samplesread),
l_buffer.size()-i);
alcCaptureSamples(m_device, (ALCvoid*)(&l_buffer(i)),
l_samplesread);
i += l_samplesread;
}
The problem here is that the count you're getting from and passing to
OpenAL is in sample frames. 1 sample frame for 8-bit stereo is 2 bytes.
So when you ask for n samples, you need a buffer n*2 bytes big.
l_buffer.size()-i gives you the number of bytes the buffer can hold, but
telling OpenAL to store that many samples which needs twice as much. The
size of the buffer is correct, but you're telling OpenAL to write too
much into it.

The fix would be to do it like this:

l_samplesread = std::min(static_cast<std::size_t>(l_samplesread),
(l_buffer.size()-i)/2);
alcCaptureSamples(m_device, (ALCvoid*)(&l_buffer(i)), l_samplesread);
i += l_samplesread*2;


Also, concerning this bit:
if(!l_samplesread && alcIsExtensionPresent(m_device, "ALC_EXT_disconnect"))
{
stop capturing
}

you'll want to make sure the device is actually disconnected before
stopping. It's possible OpenAL hasn't received any audio since the last
time you got some and can tell you 0 temporarily, but start giving you
audio again when it receives the next chunk. Do it like this:

if(!l_samplesread && alcIsExtensionPresent(m_device, "ALC_EXT_disconnect"))
{
ALCint connected = 0;
alcGetIntegerv(m_device, ALC_CONNECTED, 1, &connected);
if(!connected)
{
stop capturing
}
}
Philipp Kraus
2012-08-10 09:39:37 UTC
Permalink
Post by Chris Robinson
Post by Philipp Kraus
Yes, my code shows exactly;
if (l_samplesread > 0)
{
l_samplesread = std::min(static_cast<std::size_t>(l_samplesread),
l_buffer.size()-i);
alcCaptureSamples(m_device, (ALCvoid*)(&l_buffer(i)),
l_samplesread);
i += l_samplesread;
}
The problem here is that the count you're getting from and passing to
OpenAL is in sample frames. 1 sample frame for 8-bit stereo is 2 bytes.
Ah okay, that is / was my mistake. I have read the "sample read"
exactly samples not "sample frames".

Thx

Phil

Loading...