Fix for [#26652] "Audio Muted" in Time Line Editor is not working
[blender-staging.git] / intern / audaspace / intern / AUD_SequencerReader.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_SequencerReader.cpp
28  *  \ingroup audaspaceintern
29  */
30
31
32 #include "AUD_SequencerReader.h"
33 #include "AUD_DefaultMixer.h"
34
35 #include <math.h>
36
37 typedef std::list<AUD_SequencerStrip*>::iterator AUD_StripIterator;
38 typedef std::list<AUD_SequencerEntry*>::iterator AUD_EntryIterator;
39
40 AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory,
41                         std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs,
42                         void* data, AUD_volumeFunction volume)
43 {
44         AUD_DeviceSpecs dspecs;
45         dspecs.specs = specs;
46         dspecs.format = AUD_FORMAT_FLOAT32;
47
48         m_mixer = new AUD_DefaultMixer(dspecs);
49         m_factory = factory;
50         m_data = data;
51         m_volume = volume;
52
53         AUD_SequencerStrip* strip;
54
55         for(AUD_EntryIterator i = entries.begin(); i != entries.end(); i++)
56         {
57                 strip = new AUD_SequencerStrip;
58                 strip->entry = *i;
59                 strip->old_sound = NULL;
60
61                 if(strip->old_sound)
62                         strip->reader = m_mixer->prepare(strip->old_sound->createReader());
63                 else
64                         strip->reader = NULL;
65
66                 m_strips.push_front(strip);
67         }
68
69         m_position = 0;
70 }
71
72 AUD_SequencerReader::~AUD_SequencerReader()
73 {
74         if(m_factory != NULL)
75                 m_factory->removeReader(this);
76
77         AUD_SequencerStrip* strip;
78
79         while(!m_strips.empty())
80         {
81                 strip = m_strips.front();
82                 m_strips.pop_front();
83                 if(strip->reader)
84                 {
85                         delete strip->reader;
86                 }
87                 delete strip;
88         }
89
90         delete m_mixer;
91 }
92
93 void AUD_SequencerReader::destroy()
94 {
95         m_factory = NULL;
96         AUD_SequencerStrip* strip;
97
98         while(!m_strips.empty())
99         {
100                 strip = m_strips.front();
101                 m_strips.pop_front();
102                 delete strip;
103         }
104 }
105
106 void AUD_SequencerReader::add(AUD_SequencerEntry* entry)
107 {
108         AUD_SequencerStrip* strip = new AUD_SequencerStrip;
109         strip->entry = entry;
110
111         if(*strip->entry->sound)
112         {
113                 strip->old_sound = *strip->entry->sound;
114                 strip->reader = m_mixer->prepare(strip->old_sound->createReader());
115         }
116         else
117         {
118                 strip->reader = NULL;
119                 strip->old_sound = NULL;
120         }
121         m_strips.push_front(strip);
122 }
123
124 void AUD_SequencerReader::remove(AUD_SequencerEntry* entry)
125 {
126         AUD_SequencerStrip* strip;
127         for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
128         {
129                 strip = *i;
130                 if(strip->entry == entry)
131                 {
132                         i++;
133                         if(strip->reader)
134                         {
135                                 delete strip->reader;
136                         }
137                         m_strips.remove(strip);
138                         delete strip;
139                         return;
140                 }
141         }
142 }
143
144 bool AUD_SequencerReader::isSeekable() const
145 {
146         return true;
147 }
148
149 void AUD_SequencerReader::seek(int position)
150 {
151         m_position = position;
152 }
153
154 int AUD_SequencerReader::getLength() const
155 {
156         return -1;
157 }
158
159 int AUD_SequencerReader::getPosition() const
160 {
161         return m_position;
162 }
163
164 AUD_Specs AUD_SequencerReader::getSpecs() const
165 {
166         return m_mixer->getSpecs().specs;
167 }
168
169 void AUD_SequencerReader::read(int & length, sample_t* & buffer)
170 {
171         AUD_DeviceSpecs specs = m_mixer->getSpecs();
172         int samplesize = AUD_SAMPLE_SIZE(specs);
173         int rate = specs.rate;
174
175         int size = length * samplesize;
176
177         int start, end, current, skip, len;
178         AUD_SequencerStrip* strip;
179         sample_t* buf;
180
181         if(m_buffer.getSize() < size)
182                 m_buffer.resize(size);
183         buffer = m_buffer.getBuffer();
184
185         if(!m_factory->getMute())
186         {
187                 for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
188                 {
189                         strip = *i;
190                         if(!strip->entry->muted)
191                         {
192                                 if(strip->old_sound != *strip->entry->sound)
193                                 {
194                                         strip->old_sound = *strip->entry->sound;
195                                         if(strip->reader)
196                                                 delete strip->reader;
197
198                                         if(strip->old_sound)
199                                         {
200                                                 try
201                                                 {
202                                                         strip->reader = m_mixer->prepare(strip->old_sound->createReader());
203                                                 }
204                                                 catch(AUD_Exception)
205                                                 {
206                                                         strip->reader = NULL;
207                                                 }
208                                         }
209                                         else
210                                                 strip->reader = NULL;
211                                 }
212
213                                 if(strip->reader)
214                                 {
215                                         end = floor(strip->entry->end * rate);
216                                         if(m_position < end)
217                                         {
218                                                 start = floor(strip->entry->begin * rate);
219                                                 if(m_position + length > start)
220                                                 {
221                                                         current = m_position - start;
222                                                         if(current < 0)
223                                                         {
224                                                                 skip = -current;
225                                                                 current = 0;
226                                                         }
227                                                         else
228                                                                 skip = 0;
229                                                         current += strip->entry->skip * rate;
230                                                         len = length > end - m_position ? end - m_position : length;
231                                                         len -= skip;
232                                                         if(strip->reader->getPosition() != current)
233                                                                 strip->reader->seek(current);
234                                                         strip->reader->read(len, buf);
235                                                         m_mixer->add(buf, skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate));
236                                                 }
237                                         }
238                                 }
239                         }
240                 }
241         }
242
243         m_mixer->superpose((data_t*)buffer, length, 1.0f);
244
245         m_position += length;
246 }