1 /*
2  * $Id$
3  *
4  * Copyright (C) 2002-2003 Fhg Fokus
5  *
6  * This file is part of SEMS, a free SIP media server.
7  *
8  * SEMS is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * For a license to use the sems software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * SEMS is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 
28 #ifndef _SampleArray_cc_
29 #define _SampleArray_cc_
30 
31 #include "log.h"
32 #include <string.h>
33 
34 // inline bool cmp_ts(unsigned int t1, unsigned int t2)
35 // {
36 //     // t1 < t2
37 //     return (t1 - t2 > (unsigned int)(1<<31));
38 // }
39 
operator ()(const unsigned int & l,const unsigned int & r) const40 inline bool ts_less::operator()(const unsigned int& l,
41 				const unsigned int& r) const
42 {
43   return (l - r > (unsigned int)(1<<31));
44 }
45 
operator ()(const unsigned long long & l,const unsigned long long & r) const46 inline bool sys_ts_less::operator()(const unsigned long long& l,
47 				    const unsigned long long& r) const
48 {
49   return (((l - r) & 0xFFFFFFFFFFFFLL) > (1LL<<47));
50 }
51 
52 template <typename T>
SampleArray()53 SampleArray<T>::SampleArray()
54   : init(false)
55 {
56 }
57 
58 template <typename T>
clear_all()59 void SampleArray<T>::clear_all()
60 {
61   memset(samples,0,sizeof(samples));
62 }
63 
64 template <typename T>
clear(unsigned int start_ts,unsigned int end_ts)65 void SampleArray<T>::clear(unsigned int start_ts,unsigned int end_ts)
66 {
67   if(end_ts - start_ts >= SIZE_MIX_BUFFER){
68     clear_all();
69     return;
70   }
71 
72   unsigned int start_off = start_ts & (SIZE_MIX_BUFFER-1);
73   unsigned int end_off = end_ts & (SIZE_MIX_BUFFER-1);
74 
75   T* sp = samples + start_off;
76   if(start_off < end_off)
77     memset(sp,0,(end_off-start_off)*sizeof(T));
78   else {
79     memset(sp,0,(SIZE_MIX_BUFFER-start_off)*sizeof(T));
80     memset(samples,0,end_off*sizeof(T));
81   }
82 }
83 
84 template <typename T>
write(unsigned int ts,T * buffer,unsigned int size)85 void SampleArray<T>::write(unsigned int ts, T* buffer, unsigned int size)
86 {
87   unsigned int off = ts & (SIZE_MIX_BUFFER-1);
88 
89   T* sp = samples + off;
90   if(off+size <= SIZE_MIX_BUFFER)
91     memcpy(sp,buffer,size*sizeof(T));
92   else {
93     unsigned int s = SIZE_MIX_BUFFER-off;
94     memcpy(sp,buffer,s*sizeof(T));
95 
96     buffer += s;
97     size -= s;
98     memcpy(samples,buffer,size*sizeof(T));
99   }
100 }
101 
102 template <typename T>
read(unsigned int ts,T * buffer,unsigned int size)103 void SampleArray<T>::read(unsigned int ts, T* buffer, unsigned int size)
104 {
105   unsigned int off = ts & (SIZE_MIX_BUFFER-1);
106 
107   T* sp = samples + off;
108   if(off+size <= SIZE_MIX_BUFFER){
109     memcpy(buffer,sp,size*sizeof(T));
110   }
111   else {
112     unsigned int s = SIZE_MIX_BUFFER - off;
113     memcpy(buffer,sp,s*sizeof(T));
114 
115     buffer += s;;
116     size -= s;
117     memcpy(buffer,samples,size*sizeof(T));
118   }
119 }
120 
121 template <typename T>
put(unsigned int ts,T * buffer,unsigned int size)122 void SampleArray<T>::put(unsigned int ts, T* buffer, unsigned int size)
123 {
124   //assert(size <= SIZE_MIX_BUFFER);
125 
126   if(!init){
127     clear_all();
128     last_ts = ts;
129     init = true;
130   }
131 
132   if(ts_less()(ts,last_ts-SIZE_MIX_BUFFER)){
133     DBG("throwing away too old packet (ts=%u; last_ts=%u).\n",ts,last_ts);
134     return;
135   }
136 
137   if(ts_less()(last_ts,ts))
138     clear(last_ts,ts);
139 
140   write(ts,buffer,size);
141   if(ts_less()(last_ts,ts+size))
142     last_ts = ts+size;
143 }
144 
145 template <typename T>
get(unsigned int ts,T * buffer,unsigned int size)146 void SampleArray<T>::get(unsigned int ts, T* buffer, unsigned int size)
147 {
148   //assert(size <= SIZE_MIX_BUFFER);
149 
150   if(!init ||
151      !ts_less()(ts,last_ts) ||
152      !ts_less()(last_ts-SIZE_MIX_BUFFER,ts+size)){
153 
154     // !init ||
155     // (ts+size <= last_ts-SIZE_MIX_BUFFER) ||
156     // (ts >= last_ts)
157     memset(buffer,0,size*sizeof(T));
158     return;
159   }
160 
161   // init &&
162   // (ts+size > last_ts-SIZE_MIX_BUFFER) &&
163   // (ts < last_ts)
164 
165   if(ts_less()(ts,last_ts-SIZE_MIX_BUFFER)){
166 
167     // ts < last_ts-SIZE_MIX_BUFFER
168     unsigned int s = last_ts-SIZE_MIX_BUFFER-ts;
169     memset(buffer,0,s*sizeof(T));
170 
171     ts += s; buffer += s; size -= s;
172     read(ts,buffer,size);
173   }
174   else if(ts_less()(last_ts,ts+size)){
175 
176     // ts+size > last_ts
177     unsigned int s = last_ts-ts;
178     read(ts,buffer,s);
179 
180     buffer += s; size -= s;
181     memset(buffer,0,size*sizeof(T));
182   }
183   else {
184     // ts+size <= last_ts
185     read(ts,buffer,size);
186   }
187 }
188 
189 #endif
190