3D Audio GSoC:
[blender.git] / intern / audaspace / intern / AUD_AnimateableProperty.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * Copyright 2009-2011 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
10  * Audaspace is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * AudaSpace is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Audaspace; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file audaspace/intern/AUD_AnimateableProperty.cpp
28  *  \ingroup audaspaceintern
29  */
30
31
32 #include "AUD_AnimateableProperty.h"
33
34 #include <cstring>
35 #include <cmath>
36
37 AUD_AnimateableProperty::AUD_AnimateableProperty(int count) :
38         AUD_Buffer(count * sizeof(float)), m_count(count), m_isAnimated(false)
39 {
40         memset(getBuffer(), 0, count * sizeof(float));
41
42         pthread_mutexattr_t attr;
43         pthread_mutexattr_init(&attr);
44         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
45
46         pthread_mutex_init(&m_mutex, &attr);
47
48         pthread_mutexattr_destroy(&attr);
49 }
50
51 AUD_AnimateableProperty::~AUD_AnimateableProperty()
52 {
53         pthread_mutex_destroy(&m_mutex);
54 }
55
56 void AUD_AnimateableProperty::lock()
57 {
58         pthread_mutex_lock(&m_mutex);
59 }
60
61 void AUD_AnimateableProperty::unlock()
62 {
63         pthread_mutex_unlock(&m_mutex);
64 }
65
66 void AUD_AnimateableProperty::write(const float* data)
67 {
68         lock();
69
70         m_isAnimated = false;
71         memcpy(getBuffer(), data, m_count * sizeof(float));
72
73         unlock();
74 }
75
76 void AUD_AnimateableProperty::write(const float* data, int position, int count)
77 {
78         lock();
79
80         m_isAnimated = true;
81
82         int pos = getSize() / (sizeof(float) * m_count);
83
84         assureSize((count + position) * m_count * sizeof(float), true);
85
86         float* buf = getBuffer();
87
88         memcpy(buf + position * m_count, data, count * m_count * sizeof(float));
89
90         for(int i = pos; i < position; i++)
91                 memcpy(buf + i * m_count, buf + (pos - 1) * m_count, m_count * sizeof(float));
92
93         unlock();
94 }
95
96 void AUD_AnimateableProperty::read(float position, float* out)
97 {
98         lock();
99
100         if(!m_isAnimated)
101         {
102                 memcpy(out, getBuffer(), m_count * sizeof(float));
103                 unlock();
104                 return;
105         }
106
107         int last = getSize() / (sizeof(float) * m_count) - 1;
108         float t = position - floor(position);
109
110         if(position >= last)
111         {
112                 position = last;
113                 t = 0;
114         }
115
116         if(t == 0)
117         {
118                 memcpy(out, getBuffer() + int(floor(position)) * m_count, m_count * sizeof(float));
119         }
120         else
121         {
122                 int pos = int(floor(position)) * m_count;
123                 float t2 = t * t;
124                 float t3 = t2 * t;
125                 float m0, m1;
126                 float* p0;
127                 float* p1 = getBuffer() + pos;
128                 float* p2;
129                 float* p3;
130                 last *= m_count;
131
132                 if(pos == 0)
133                         p0 = p1;
134                 else
135                         p0 = p1 - m_count;
136
137                 p2 = p1 + m_count;
138                 if(pos + m_count == last)
139                         p3 = p2;
140                 else
141                         p3 = p2 + m_count;
142
143                 for(int i = 0; i < m_count; i++)
144                 {
145                         m0 = (p2[i] - p0[i]) / 2.0f;
146                         m1 = (p3[i] - p1[i]) / 2.0f;
147
148                         out[i] = (2 * t3 - 3 * t2 + 1) * p0[i] + (-2 * t3 + 3 * t2) * p1[i] +
149                                          (t3 - 2 * t2 + t) * m0 + (t3 - t2) * m1;
150                 }
151         }
152
153         unlock();
154 }
155
156 bool AUD_AnimateableProperty::isAnimated() const
157 {
158         return m_isAnimated;
159 }