705 lines · 17.2 KB · C
RawDownload
/*----------------------------------------------------------------------------  ChucK Concurrent, On-the-fly Audio Programming Language    Compiler and Virtual Machine   Copyright (c) 2004 Ge Wang and Perry R. Cook.  All rights reserved.    http://chuck.stanford.edu/    http://chuck.cs.princeton.edu/   This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 2 of the License, or  (at your option) any later version.   This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.   You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: util_buffers.h// desc: buffer utilities//// author: Ge Wang (gewang@cs.princeton.edu)//         Perry R. Cook (prc@cs.princeton.edu)//         Ananya Misra (amisra@cs.princeton.edu)// date: Spring 2004//       Summer 2005 - allow multiple readers//-----------------------------------------------------------------------------#ifndef __UTIL_BUFFERS_H__#define __UTIL_BUFFERS_H__ #include "chuck_oo.h"#include "chuck_errmsg.h"#ifndef __DISABLE_THREADS__#include "util_thread.h"#endif#include <vector>#include <queue>#include <iostream> #define DWORD__                t_CKUINT#define SINT__                 t_CKINT#define UINT__                 DWORD__#define BOOL__                 DWORD__#define BYTE__                 unsigned char #ifndef TRUE#define TRUE    1#define FALSE   0#endif  class CBufferSimple;  //-----------------------------------------------------------------------------// name: class CBufferAdvance// desc: circular buffer//-----------------------------------------------------------------------------class CBufferAdvance{public:    CBufferAdvance();    ~CBufferAdvance(); public:    BOOL__ initialize( UINT__ num_elem, UINT__ width, CBufferSimple * event_buffer = NULL );    void cleanup(); public:    UINT__ get( void * data, UINT__ num_elem, UINT__ read_offset_index );    void put( void * data, UINT__ num_elem );    BOOL__ empty( UINT__ read_offset_index );    UINT__ join( Chuck_Event * event = NULL );    void resign( UINT__ read_offset_index ); protected:    BYTE__ * m_data;    UINT__   m_data_width;    //UINT__   m_read_offset;     // this holds the offset allocated by join(), paired with an optional    // Chuck_Event to notify when things are put in the buffer    struct ReadOffset    {        SINT__ read_offset;        Chuck_Event * event;        ReadOffset( SINT__ ro, Chuck_Event * e = NULL )        { read_offset = ro; event = e; }    };    std::vector<ReadOffset> m_read_offsets;    std::queue<UINT__> m_free;     SINT__   m_write_offset;    SINT__   m_max_elem;     // TODO: necessary?    #ifndef __DISABLE_THREADS__    XMutex m_mutex;    #endif     CBufferSimple * m_event_buffer;};    //-----------------------------------------------------------------------------// name: class CBufferSimple// desc: circular buffer - one reader one writer//-----------------------------------------------------------------------------class CBufferSimple{public:    CBufferSimple();    ~CBufferSimple(); public:    BOOL__ initialize( UINT__ num_elem, UINT__ width );    void cleanup(); public:    UINT__ get( void * data, UINT__ num_elem );    void put( void * data, UINT__ num_elem ); protected:    BYTE__ * m_data;    UINT__   m_data_width;    UINT__   m_read_offset;    UINT__   m_write_offset;    UINT__   m_max_elem;};    //-----------------------------------------------------------------------------// name: class AccumBuffer// desc: circular buffer for sample accumulation//-----------------------------------------------------------------------------class AccumBuffer{public:    AccumBuffer();    ~AccumBuffer(); public:    t_CKINT resize( t_CKINT new_size );    void cleanup(); public:    void put( SAMPLE next );    void get( SAMPLE * buffer, t_CKINT num_elem );    void get_most_recent( SAMPLE * buffer, t_CKINT num_elem ); protected:    SAMPLE * m_data;    t_CKUINT m_write_offset;    t_CKUINT m_max_elem;};    //-----------------------------------------------------------------------------// name: class DeccumBuffer// desc: circular buffer for sample deccumulation//-----------------------------------------------------------------------------class DeccumBuffer{public:    DeccumBuffer();    ~DeccumBuffer(); public:    t_CKINT resize( t_CKINT new_size );    void cleanup(); public:    void put( SAMPLE * next, t_CKINT num_elem );    void get( SAMPLE * out );    void get( SAMPLE * buffer, t_CKINT num_elem ); protected:    SAMPLE * m_data;    t_CKUINT m_read_offset;    t_CKUINT m_max_elem;};    //-----------------------------------------------------------------------------// name: class CircularBuffer// desc: templated circular buffer//-----------------------------------------------------------------------------template<typename T>class CircularBuffer{public:    CircularBuffer(size_t numElements) :        m_read(0),        m_write(0),        m_numElements(numElements+1) // need 1 element to pad    {        // allocate        m_elements = new T[m_numElements];    }     ~CircularBuffer()    {        SAFE_DELETE_ARRAY( m_elements );        // if(m_elements != NULL)        // {        //    delete[] m_elements;        //    m_elements = NULL;        // }    }     // put one element    // returns number of elements successfully put    size_t put(T element)    {        // check for overflow        if( (m_write + 1)%m_numElements == m_read )        {            // no space | 1.5.0.1 (ge) added log message            EM_log( CK_LOG_WARNING, "[circular-buffer]: buffer full, dropping items!" );            return 0;        }         m_elements[m_write] = element;        m_write = (m_write+1)%m_numElements;        return 1;    }     // get one element    // returns number of elements successfully got    size_t get(T &element)    {        if(m_read == m_write)        {            // nothing to get            return 0;        }         element = m_elements[m_read];         m_read = (m_read+1)%m_numElements;         return 1;    }     // peek at element i without removing it    // i = 1 would correspond to the least recently put element;    // i = -1 would correspond to the most recent (not implemented)    // returns 1 if elements successfully peeked    size_t peek(T &element, size_t i)    {        if(i == 0)            return 0;         if(i > 0 && i <= numElements())        {            element = m_elements[(m_read+(i-1))%m_numElements];            return 1;        }         return 0;    }     void clear() { m_write = m_read; }     // return maximum number of elements that can be held    size_t maxElements() { return m_numElements-1; }     // return if buffer is full    bool atMaximum() { return (m_write + 1)%m_numElements == m_read; }     // return number of valid elements in the buffer    size_t numElements()    {        if(m_read == m_write)            return 0;        else if(m_read < m_write)            return m_write - m_read;        else            return m_numElements - m_read + m_write;    } private:    T * m_elements;    size_t m_read, m_write;    const size_t m_numElements;};    //-----------------------------------------------------------------------------// name: class FastCircularBuffer// desc: uses memcpy instead of assignment//       useful for streaming large blocks of data//-----------------------------------------------------------------------------class FastCircularBuffer{public:    FastCircularBuffer();    ~FastCircularBuffer(); public:    t_CKUINT initialize( t_CKUINT num_elem, t_CKUINT width );    void cleanup(); public:    t_CKUINT get( void * data, t_CKUINT num_elem );    t_CKUINT put( void * data, t_CKUINT num_elem );    inline bool hasMore() { return (m_read_offset != m_write_offset); }    inline void clear() { m_read_offset = m_write_offset = 0; } protected:    t_CKBYTE * m_data;    t_CKUINT   m_data_width;    t_CKUINT   m_read_offset;    t_CKUINT   m_write_offset;    t_CKUINT   m_max_elem;};    //-----------------------------------------------------------------------------// name: class XCircleBuffer// desc: templated circular buffer class (different impl from ge-X-lib)//-----------------------------------------------------------------------------template <typename T>class XCircleBuffer{public:    XCircleBuffer( long length = 0 );    ~XCircleBuffer(); public:    // reset length of buffer (capacity)    void init( long length );    // get length    long length() const;    // clear (does no explicit memory management)    void clear(); public:    // put an element into the buffer - the item will be copied    // NOTE: if over-capacity, will discard least recently put item    void put( const T & item );    // get next item (FIFO)    bool get( T * pItem );    // number of valid elements in buffer    long numElements() const;    // are there more elements?    bool more() const;    // get elements without advancing - returns number of valid elements    long peek( T * array, long numItems, unsigned long stride = 0 );    // pop    long pop( long numItems = 1 ); protected: // helper functions    inline void advanceWrite();    inline void advanceRead(); protected:    // the buffer    T * m_buffer;    // the buffer length (capacity)    volatile long m_length;    // write index    volatile long m_writeIndex;    // read index    volatile long m_readIndex;    // num elements    volatile long m_numElements;};    //-----------------------------------------------------------------------------// name: XCircleBuffer()// desc: constructor//-----------------------------------------------------------------------------template <typename T>XCircleBuffer<T>::XCircleBuffer( long length ){    // zero out first    m_buffer = NULL;    m_length = m_readIndex = m_writeIndex = m_numElements = 0;     // call init    this->init( length );}    //-----------------------------------------------------------------------------// name: ~XCircleBuffer// desc: destructor//-----------------------------------------------------------------------------template <typename T>XCircleBuffer<T>::~XCircleBuffer(){ }    //-----------------------------------------------------------------------------// name: init()// desc: reset length of buffer//-----------------------------------------------------------------------------template <typename T>void XCircleBuffer<T>::init( long length ){    // clean up is necessary    if( m_buffer )    {        // delete array - should call destructors and zero out variable        SAFE_DELETE_ARRAY( m_buffer );        // zero out        m_length = m_readIndex = m_writeIndex = m_numElements = 0;    }     // sanity check    if( length < 0 )    {        // doh        std::cerr << "[XCircleBuffer]: error invalid length '"                  << length << "' requested" << std::endl;         return;    }     // check for zero length    if( length == 0 ) return;     // allocate    m_buffer = new T[length];    // check    if( m_buffer == NULL )    {        // doh        std::cerr << "[XCircleBuffer]: failed to allocate buffer of length '"                  << length << "'..." << std::endl;         return;    }     // save    m_length = length;    // zero out    m_readIndex = m_writeIndex = m_numElements = 0;}    //-----------------------------------------------------------------------------// name: length()// desc: get length//-----------------------------------------------------------------------------template <typename T>long XCircleBuffer<T>::length() const{    return m_length;}    //-----------------------------------------------------------------------------// name: clear()// desc: clear (does no explicit memory management)//-----------------------------------------------------------------------------template <typename T>void XCircleBuffer<T>::clear(){    // zero out    m_readIndex = m_writeIndex = m_numElements = 0;}    //-----------------------------------------------------------------------------

Lines 1–500 of 705.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t