You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sems/core/SampleArray.cc

190 lines
4.4 KiB

/*
* $Id$
*
* Copyright (C) 2002-2003 Fhg Fokus
*
* This file is part of SEMS, a free SIP media server.
*
* SEMS 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.
*
* For a license to use the sems software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
*
* SEMS 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 USA
*/
#ifndef _SampleArray_cc_
#define _SampleArray_cc_
#include "log.h"
#include <string.h>
// inline bool cmp_ts(unsigned int t1, unsigned int t2)
// {
// // t1 < t2
// return (t1 - t2 > (unsigned int)(1<<31));
// }
inline bool ts_less::operator()(const unsigned int& l,
const unsigned int& r) const
{
return (l - r > (unsigned int)(1<<31));
}
inline bool sys_ts_less::operator()(const unsigned long long& l,
const unsigned long long& r) const
{
return (((l - r) & 0xFFFFFFFFFFFFLL) > (1LL<<47));
}
template <typename T>
SampleArray<T>::SampleArray()
: init(false)
{
}
template <typename T>
void SampleArray<T>::clear_all()
{
memset(samples,0,sizeof(samples));
}
template <typename T>
void SampleArray<T>::clear(unsigned int start_ts,unsigned int end_ts)
{
if(end_ts - start_ts >= SIZE_MIX_BUFFER){
clear_all();
return;
}
unsigned int start_off = start_ts & (SIZE_MIX_BUFFER-1);
unsigned int end_off = end_ts & (SIZE_MIX_BUFFER-1);
T* sp = samples + start_off;
if(start_off < end_off)
memset(sp,0,(end_off-start_off)*sizeof(T));
else {
memset(sp,0,(SIZE_MIX_BUFFER-start_off)*sizeof(T));
memset(samples,0,end_off*sizeof(T));
}
}
template <typename T>
void SampleArray<T>::write(unsigned int ts, T* buffer, unsigned int size)
{
unsigned int off = ts & (SIZE_MIX_BUFFER-1);
T* sp = samples + off;
if(off+size <= SIZE_MIX_BUFFER)
memcpy(sp,buffer,size*sizeof(T));
else {
unsigned int s = SIZE_MIX_BUFFER-off;
memcpy(sp,buffer,s*sizeof(T));
buffer += s;
size -= s;
memcpy(samples,buffer,size*sizeof(T));
}
}
template <typename T>
void SampleArray<T>::read(unsigned int ts, T* buffer, unsigned int size)
{
unsigned int off = ts & (SIZE_MIX_BUFFER-1);
T* sp = samples + off;
if(off+size <= SIZE_MIX_BUFFER){
memcpy(buffer,sp,size*sizeof(T));
}
else {
unsigned int s = SIZE_MIX_BUFFER - off;
memcpy(buffer,sp,s*sizeof(T));
buffer += s;;
size -= s;
memcpy(buffer,samples,size*sizeof(T));
}
}
template <typename T>
void SampleArray<T>::put(unsigned int ts, T* buffer, unsigned int size)
{
//assert(size <= SIZE_MIX_BUFFER);
if(!init){
clear_all();
last_ts = ts;
init = true;
}
if(ts_less()(ts,last_ts-SIZE_MIX_BUFFER)){
DBG("throwing away too old packet (ts=%u; last_ts=%u).\n",ts,last_ts);
return;
}
if(ts_less()(last_ts,ts))
clear(last_ts,ts);
write(ts,buffer,size);
if(ts_less()(last_ts,ts+size))
last_ts = ts+size;
}
template <typename T>
void SampleArray<T>::get(unsigned int ts, T* buffer, unsigned int size)
{
//assert(size <= SIZE_MIX_BUFFER);
if(!init ||
!ts_less()(ts,last_ts) ||
!ts_less()(last_ts-SIZE_MIX_BUFFER,ts+size)){
// !init ||
// (ts+size <= last_ts-SIZE_MIX_BUFFER) ||
// (ts >= last_ts)
memset(buffer,0,size*sizeof(T));
return;
}
// init &&
// (ts+size > last_ts-SIZE_MIX_BUFFER) &&
// (ts < last_ts)
if(ts_less()(ts,last_ts-SIZE_MIX_BUFFER)){
// ts < last_ts-SIZE_MIX_BUFFER
unsigned int s = last_ts-SIZE_MIX_BUFFER-ts;
memset(buffer,0,s*sizeof(T));
ts += s; buffer += s; size -= s;
read(ts,buffer,size);
}
else if(ts_less()(last_ts,ts+size)){
// ts+size > last_ts
unsigned int s = last_ts-ts;
read(ts,buffer,s);
buffer += s; size -= s;
memset(buffer,0,size*sizeof(T));
}
else {
// ts+size <= last_ts
read(ts,buffer,size);
}
}
#endif