WaveIn problems

U

Urban Kaegi

Hi

Please excuse me, if some of you see this posting a second time (I'm a
newsgroup newby :). I already posted it in a thread with the same topic
which has been started bei Keith on May 4th. But I think, it's probably
too long ago, so it won't be seen...

I experience exactly the same problem with recording audio as Keith
does. Short recordings work fine, but longer recordings are critical.
Mostly the recording stops without any error message.
My program is written in C# and it uses P/Invoke to make use of
the Win API functions (waveInOpen, ...). The audio recording is also
based on the MSDN article Keith mentioned. The program uses a
MessageWindow to catch and process the callbacks (i.e. block full)
from the wave-in device. However it doesn't work with compressed
audio, but 'normal' PCM Wave recording at 8000 Hz, 8 bit, mono.
The application is executed on a Qtek2020 Pocket PC with an XScale
PXA263 processor.

I'm using double buffering to have a continuously input stream of
audio data. When a buffer is full, it's data is fetched and the buffer
given back to the audio device with waveInAddBuffer. The fetched data
is given to a seperate Thread. It works fine, but after a while it
seems there are no callbacks anymore from the wave in device.

I tried many ways to get rid of this problem:

- Logging
- Updating the .NET Compact Framework to SP1
- Updating the .NET Compact Framework to SP2
- Make a separate Thread to process audio data
- Trying other buffer sizes and other numbers of buffers.
For example: 2 x 16000 byte (double buffering), 128 x 256 byte
(circular buffer), ...

As far I could evaluate, it's working better with tendential big
buffer size and using double buffering. But despite all my efforts I
could not solve this tricky problem.

Could this be a bug in the .NET CF? Or is it the garbage collector
creating interferences?

I would be deeply grateful for any help concerning this topic.

I attached two code snippets. First the MessageWindow, second the
method which is called by the MessageWindow after a block is done by
the audio recording.

Best regards, Urban


/// <summary>
/// Defines the MessageWindow used to receive messages from the audio
/// system.
/// </summary>
protected class SoundMessageWindow : MessageWindow
{
public const int MM_WIM_OPEN = 0x3BE;
public const int MM_WIM_CLOSE = 0x3BF;
public const int MM_WIM_DATA = 0x3C0;

// Instance of a recording interface
protected WaveIn m_wi = null;

public SoundMessageWindow(WaveIn wi)
{
m_wi = wi;
}

protected override void WndProc(ref Message msg)
{
switch(msg.Msg)
{
// When this message is encountered, a block is
// done recording, so notify the WaveIn instance.
case MM_WIM_DATA:
{
if (m_wi != null)
m_wi.BlockDone();
}
break;
}
base.WndProc(ref msg);
}
}



/// <summary>
/// Called when the Windows message specifying that a block has
finished
/// recording is encountered. It is critical that the application
stay
/// one buffer ahead because at the point this function is called, the
system
/// has already started writing to the next buffer.
/// </summary>
public void BlockDone()
{
// count the recorded blocks
this.m_countBlocks++;

// buffer for recorded wave data
byte[] data = null;

if (m_whdr != null)
{
// Get data from Wave Buffer
Wave.MMSYSERR result = m_whdr[m_curBlock].GetBuffer(out data,
this.m_bufferSize);

// Simulate a circular buffer. If highest block is full start over
with lowest block.
// If m_numBlocks = 2, this results in alternating between 2
blocks.
waveInAddBuffer(this.m_hwi, this.m_whdr[m_curBlock],
(uint)Marshal.SizeOf(m_whdr[m_curBlock]));

// indicate next block for writing
if (m_curBlock < (m_numBlocks - 1))
{
m_curBlock++;
}
else {
m_curBlock = 0;
}

// check if recorded data has been fetched successfully
if (result != Wave.MMSYSERR.NOERROR) //no
{
log.write("ERROR: Could not fetch buffer data
(WaveFile.BlockDone). " + result.ToString());
}
else //yes
{
// Creeate a thread to process fetched data using ThreadPool
class
ThreadPool.QueueUserWorkItem(wcb, (object) data);
}
}
}
 
Joined
Mar 31, 2010
Messages
1
Reaction score
0
waveInOpen

I think I found the solution to this problem; I added the WAVE_FORMAT_DIRECT flag to the last parameter of waveInOpen, and now it records all the way through.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top