[Portaudio] WaitForSingleObject() Timed out in WriteStream()

Ross Bencina rossb-lists at audiomulch.com
Fri Jul 16 03:48:36 EDT 2010


Or you could just use pa_ringbuffer.c which is tested, and has the necessary 
memory barriers to be safe on multicore systems (volatile is not enough 
Robert, see archives for discussion)...

Ross

----- Original Message ----- 
From: "Robert Bielik" <robert.bielik at xponaut.se>
To: "Portaudio Mailing List" <portaudio at music.columbia.edu>
Sent: Friday, July 16, 2010 5:34 PM
Subject: Re: [Portaudio] WaitForSingleObject() Timed out in WriteStream()


> Since there's no need to use RT OS for recording (obvisously), here's a 
> simple lock-free buffer fifo that would do the trick, with usage example
> (Haven't compiled it or tested it, so use at your own discretion):
>
> ------------------------------
> #ifndef __AUDIO_BUFFER_MANAGER_H__
> #define __AUDIO_BUFFER_MANAGER_H__
>
> #include "pa_util.h"
> #include <assert.h>
>
> class CAudioBufferManager {
> public:
>    CAudioBufferManager(unsigned bufSize, unsigned bufCount)
>        : m_bufCountMask(bufCount-1)
>        , m_bufSize(bufSize)
>        , m_buffers(0)
>    {
>        // Will assert on bufCount not being a power of 2, due to impl I 
> don't accept that
>        assert( ! ((bufCount)&(bufCountMask)) );
>    }
>    ~CAudioBufferManager() {
>        if (m_buffers) {
>            for (unsigned i=0;i<bufCount;++i) {
>                if (m_buffers[i] != 0) {
>                    PaUtil_FreeMemory(m_buffers[i]);
>                    m_buffers[i] = 0;
>                }
>            }
>            PaUtil_FreeMemory(m_buffers);
>            m_buffers = 0;
>        }
>    }
>
>    // Keep initialization from the constructor, so we can act if there's a 
> problem
>    bool Initialize() {
>        // Assert if we call this twice
>        assert( m_buffers == 0);
>        // Allocate buffer array
>        m_buffers = 
> (void**)PaUtil_AllocateMemory((m_bufCountMask+1)*sizeof(void*));
>        if (m_buffers == 0) {
>            // Out of memory
>            return false;
>        }
>
>        for (unsigned i=0;i<bufCount;++i) {
>            m_buffers[i] = PaUtil_AllocateMemory(m_bufSize);
>            if (m_buffers[i] == 0) {
>                // Out of memory
>                goto error;
>            }
>        }
>
>        return true;
>
>    error:
>        // Cleanup
>        for (unsigned i=0;i<bufCount;++i) {
>            if (m_buffers[i] != 0) {
>                PaUtil_FreeMemory(m_buffers[i]);
>                m_buffers[i] = 0;
>            }
>        }
>        PaUtil_FreeMemory(m_buffers);
>        m_buffers = 0;
>        return false;
>    }
>
>    bool HasFreeBuffers() const {
>        return (m_posWrite - m_posRead) < m_bufCountMask;
>    }
>    bool HasFilledBuffers() const {
>        return (m_posWrite != m_posRead);
>    }
>    void* GetWriteBuffer() {
>        if (m_posWrite - m_posRead == m_bufCountMask) {
>            // No more buffers to get
>            return 0;
>        }
>        void* p = m_buffers[m_posWrite&m_bufCountMask];
>        return p;
>    }
>    const void* GetReadBuffer() {
>        if (m_posWrite == m_posRead) {
>            // No more buffers to get
>            return 0;
>        }
>        void* p = m_buffers[m_posRead&m_bufCountMask];
>        return p;
>    }
>
>    void AdvanceWrite() {
>        ++m_posWrite;
>    }
>    void AdvanceRead() {
>        ++m_posRead;
>    }
>
> private:
>    volatile unsigned m_posWrite;
>    volatile unsigned m_posRead;
>    void** m_buffers;
>    const unsigned m_bufCountMask;
>    const unsigned m_bufSize;
> };
>
>
> /* Example usage:
>
> In PA callback:
>
> <CODE>
>
> // m_bufferToRecordInto is of type void*
> if (m_bufferToRecordInto == 0) {
>   m_bufferToRecordInto = m_audioBufferManager.GetWriteBuffer();
> }
>
> if (m_bufferToRecordInto != 0) {
>   // TODO: Record samples into the buffer after appropriately casting 
> m_bufferToRecordInto // to correct type
>
>   // When the buffer is filled (which can be several PA callbacks)
>   if (bufferIsFilled) {
>       m_audioBufferManager.AdvanceWrite();
>       m_bufferToRecordInto = 0;
>   }
> }
> </CODE>
>
>
>
> In I/O thread (higher prio than default thread prio):
>
> <CODE>
> while (threadShouldLoop) {
>
>   void* pBuffer = m_audioBufferManager.GetReadBuffer();
>   if (pBuffer == 0) {
>      Sleep(50);
>      continue;
>   }
>
>   // TODO: Write samples from the buffer to disk
>
>   // We're finished with this buffer
>   m_audioBufferManager.AdvanceRead();
> }
> </CODE>
>
> bufSize should be approx 200 ms worth of audio, and bufCount perhaps 16 
> buffers.
>
> */
>
> #endif // __AUDIO_BUFFER_MANAGER_H__
> ----------------------
>
> HTH
> /Rob
> _______________________________________________
> Portaudio mailing list
> Portaudio at music.columbia.edu
> http://music.columbia.edu/mailman/listinfo/portaudio 



More information about the Portaudio mailing list