zoukankan      html  css  js  c++  java
  • webrtc-ringbuffer

    webrtc-audioproc-master/modules/audio_processing/utilityring_buffer.c

    /*
     *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
     *
     *  Use of this source code is governed by a BSD-style license
     *  that can be found in the LICENSE file in the root of the source
     *  tree. An additional intellectual property rights grant can be found
     *  in the file PATENTS.  All contributing project authors may
     *  be found in the AUTHORS file in the root of the source tree.
     */
    
    // A ring buffer to hold arbitrary data. Provides no thread safety. Unless
    // otherwise specified, functions return 0 on success and -1 on error.
    
    #include "ring_buffer.h"
    
    #include <stddef.h> // size_t
    #include <stdlib.h>
    #include <string.h>
    
    enum Wrap {
      SAME_WRAP,
      DIFF_WRAP
    };
    
    typedef struct {
      size_t read_pos;
      size_t write_pos;
      size_t element_count;
      size_t element_size;
      enum Wrap rw_wrap;
      char* data;
    } buf_t;
    
    // Get address of region(s) from which we can read data.
    // If the region is contiguous, |data_ptr_bytes_2| will be zero.
    // If non-contiguous, |data_ptr_bytes_2| will be the size in bytes of the second
    // region. Returns room available to be read or |element_count|, whichever is
    // smaller.
    static size_t GetBufferReadRegions(buf_t* buf,
                                       size_t element_count,
                                       void** data_ptr_1,
                                       size_t* data_ptr_bytes_1,
                                       void** data_ptr_2,
                                       size_t* data_ptr_bytes_2) {
    
      const size_t readable_elements = WebRtc_available_read(buf);
      const size_t read_elements = (readable_elements < element_count ?
          readable_elements : element_count);
      const size_t margin = buf->element_count - buf->read_pos;
    
      // Check to see if read is not contiguous.
      if (read_elements > margin) {
        // Write data in two blocks that wrap the buffer.
        *data_ptr_1 = buf->data + buf->read_pos * buf->element_size;
        *data_ptr_bytes_1 = margin * buf->element_size;
        *data_ptr_2 = buf->data;
        *data_ptr_bytes_2 = (read_elements - margin) * buf->element_size;
      } else {
        *data_ptr_1 = buf->data + buf->read_pos * buf->element_size;
        *data_ptr_bytes_1 = read_elements * buf->element_size;
        *data_ptr_2 = NULL;
        *data_ptr_bytes_2 = 0;
      }
    
      return read_elements;
    }
    
    int WebRtc_CreateBuffer(void** handle,
                            size_t element_count,
                            size_t element_size) {
      buf_t* self = NULL;
    
      if (handle == NULL) {
        return -1;
      }
    
      self = malloc(sizeof(buf_t));
      if (self == NULL) {
        return -1;
      }
      *handle = self;
    
      self->data = malloc(element_count * element_size);
      if (self->data == NULL) {
        free(self);
        self = NULL;
        return -1;
      }
    
      self->element_count = element_count;
      self->element_size = element_size;
    
      return 0;
    }
    
    int WebRtc_InitBuffer(void* handle) {
      buf_t* self = (buf_t*) handle;
    
      if (self == NULL) {
        return -1;
      }
    
      self->read_pos = 0;
      self->write_pos = 0;
      self->rw_wrap = SAME_WRAP;
    
      // Initialize buffer to zeros
      memset(self->data, 0, self->element_count * self->element_size);
    
      return 0;
    }
    
    int WebRtc_FreeBuffer(void* handle) {
      buf_t* self = (buf_t*) handle;
    
      if (self == NULL) {
        return -1;
      }
    
      free(self->data);
      free(self);
    
      return 0;
    }
    
    size_t WebRtc_ReadBuffer(void* handle,
                             void** data_ptr,
                             void* data,
                             size_t element_count) {
    
      buf_t* self = (buf_t*) handle;
    
      if (self == NULL) {
        return 0;
      }
      if (data == NULL) {
        return 0;
      }
      if (data_ptr == NULL) {
        return 0;
      }
    
      {
        void* buf_ptr_1 = NULL;
        void* buf_ptr_2 = NULL;
        size_t buf_ptr_bytes_1 = 0;
        size_t buf_ptr_bytes_2 = 0;
        const size_t read_count = GetBufferReadRegions(self,
                                                       element_count,
                                                       &buf_ptr_1,
                                                       &buf_ptr_bytes_1,
                                                       &buf_ptr_2,
                                                       &buf_ptr_bytes_2);
    
        if (buf_ptr_bytes_2 > 0) {
          // We have a wrap around when reading the buffer. Copy the buffer data to
          // |data| and point to it.
          memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
          memcpy(((char*) data) + buf_ptr_bytes_1, buf_ptr_2, buf_ptr_bytes_2);
          *data_ptr = data;
        } else {
          *data_ptr = buf_ptr_1;
        }
    
        // Update read position
        WebRtc_MoveReadPtr(handle, (int) read_count);
    
        return read_count;
      }
    }
    
    size_t WebRtc_WriteBuffer(void* handle,
                              const void* data,
                              size_t element_count) {
    
      buf_t* self = (buf_t*) handle;
    
      if (self == NULL) {
        return 0;
      }
      if (data == NULL) {
        return 0;
      }
    
      {
        const size_t free_elements = WebRtc_available_write(handle);
        const size_t write_elements = (free_elements < element_count ? free_elements
            : element_count);
        size_t n = write_elements;
        const size_t margin = self->element_count - self->write_pos;
    
        if (write_elements > margin) {
          // Buffer wrap around when writing.
          memcpy(self->data + self->write_pos * self->element_size,
                 data, margin * self->element_size);
          self->write_pos = 0;
          n -= margin;
          self->rw_wrap = DIFF_WRAP;
        }
        memcpy(self->data + self->write_pos * self->element_size,
               ((const char*) data) + ((write_elements - n) * self->element_size),
               n * self->element_size);
        self->write_pos += n;
    
        return write_elements;
      }
    }
    
    int WebRtc_MoveReadPtr(void* handle, int element_count) {
    
      buf_t* self = (buf_t*) handle;
    
      if (self == NULL) {
        return 0;
      }
    
      {
        // We need to be able to take care of negative changes, hence use "int"
        // instead of "size_t".
        const int free_elements = (int) WebRtc_available_write(handle);
        const int readable_elements = (int) WebRtc_available_read(handle);
        int read_pos = (int) self->read_pos;
    
        if (element_count > readable_elements) {
          element_count = readable_elements;
        }
        if (element_count < -free_elements) {
          element_count = -free_elements;
        }
    
        read_pos += element_count;
        if (read_pos > (int) self->element_count) {
          // Buffer wrap around. Restart read position and wrap indicator.
          read_pos -= (int) self->element_count;
          self->rw_wrap = SAME_WRAP;
        }
        if (read_pos < 0) {
          // Buffer wrap around. Restart read position and wrap indicator.
          read_pos += (int) self->element_count;
          self->rw_wrap = DIFF_WRAP;
        }
    
        self->read_pos = (size_t) read_pos;
    
        return element_count;
      }
    }
    
    size_t WebRtc_available_read(const void* handle) {
      const buf_t* self = (buf_t*) handle;
    
      if (self == NULL) {
        return 0;
      }
    
      if (self->rw_wrap == SAME_WRAP) {
        return self->write_pos - self->read_pos;
      } else {
        return self->element_count - self->read_pos + self->write_pos;
      }
    }
    
    size_t WebRtc_available_write(const void* handle) {
      const buf_t* self = (buf_t*) handle;
    
      if (self == NULL) {
        return 0;
      }
    
      return self->element_count - WebRtc_available_read(handle);
    }

    webrtc-audioproc-master/modules/audio_processing/utilityring_buffer.h

    /*
     *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
     *
     *  Use of this source code is governed by a BSD-style license
     *  that can be found in the LICENSE file in the root of the source
     *  tree. An additional intellectual property rights grant can be found
     *  in the file PATENTS.  All contributing project authors may
     *  be found in the AUTHORS file in the root of the source tree.
     */
    
    // A ring buffer to hold arbitrary data. Provides no thread safety. Unless
    // otherwise specified, functions return 0 on success and -1 on error.
    
    #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_RING_BUFFER_H_
    #define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_RING_BUFFER_H_
    
    #include <stddef.h> // size_t
    
    int WebRtc_CreateBuffer(void** handle,
                            size_t element_count,
                            size_t element_size);
    int WebRtc_InitBuffer(void* handle);
    int WebRtc_FreeBuffer(void* handle);
    
    // Reads data from the buffer. The |data_ptr| will point to the address where
    // it is located. If all |element_count| data are feasible to read without
    // buffer wrap around |data_ptr| will point to the location in the buffer.
    // Otherwise, the data will be copied to |data| (memory allocation done by the
    // user) and |data_ptr| points to the address of |data|. |data_ptr| is only
    // guaranteed to be valid until the next call to WebRtc_WriteBuffer().
    // Returns number of elements read.
    size_t WebRtc_ReadBuffer(void* handle,
                             void** data_ptr,
                             void* data,
                             size_t element_count);
    
    // Writes |data| to buffer and returns the number of elements written.
    size_t WebRtc_WriteBuffer(void* handle, const void* data, size_t element_count);
    
    // Moves the buffer read position and returns the number of elements moved.
    // Positive |element_count| moves the read position towards the write position,
    // that is, flushing the buffer. Negative |element_count| moves the read
    // position away from the the write position, that is, stuffing the buffer.
    // Returns number of elements moved.
    int WebRtc_MoveReadPtr(void* handle, int element_count);
    
    // Returns number of available elements to read.
    size_t WebRtc_available_read(const void* handle);
    
    // Returns number of available elements for write.
    size_t WebRtc_available_write(const void* handle);
    
    #endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_RING_BUFFER_H_
  • 相关阅读:
    爬虫的基础知识(贰)
    Django内置标签
    WPF ToggleButton Style
    编写一个简单的COM组件
    C# 调用DOS 命令
    【转】 C#中检查网络是否连通的二种方法
    c++中的类型转换
    COM笔记-包容与聚合
    windows笔记-在可执行文件或DLL的多个实例之间共享静态数据
    编程之路
  • 原文地址:https://www.cnblogs.com/dong1/p/14171232.html
Copyright © 2011-2022 走看看