Audaspace (GSoC): First merging commit
[blender.git] / intern / audaspace / FX / AUD_SuperposeReader.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN LGPL LICENSE BLOCK *****
5  *
6  * Copyright 2009 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 Lesser General Public License as published by
12  * the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * ***** END LGPL LICENSE BLOCK *****
24  */
25
26 #include "AUD_SuperposeReader.h"
27
28 #include <cstring>
29
30 static const char* specs_error = "AUD_SuperposeReader: Both readers have to "
31                                                                  "have the same specs.";
32
33 AUD_SuperposeReader::AUD_SuperposeReader(AUD_IReader* reader1, AUD_IReader* reader2) :
34         m_reader1(reader1), m_reader2(reader2)
35 {
36         try
37         {
38                 AUD_Specs s1, s2;
39                 s1 = reader1->getSpecs();
40                 s2 = reader2->getSpecs();
41                 if(memcmp(&s1, &s2, sizeof(AUD_Specs)))
42                         AUD_THROW(AUD_ERROR_SPECS, specs_error);
43         }
44         catch(AUD_Exception&)
45         {
46                 delete reader1;
47                 delete reader2;
48
49                 throw;
50         }
51 }
52
53 AUD_SuperposeReader::~AUD_SuperposeReader()
54 {
55         delete m_reader1;
56         delete m_reader2;
57 }
58
59 bool AUD_SuperposeReader::isSeekable() const
60 {
61         return m_reader1->isSeekable() && m_reader2->isSeekable();
62 }
63
64 void AUD_SuperposeReader::seek(int position)
65 {
66         m_reader1->seek(position);
67         m_reader2->seek(position);
68 }
69
70 int AUD_SuperposeReader::getLength() const
71 {
72         int len1 = m_reader1->getLength();
73         int len2 = m_reader2->getLength();
74         if((len1 < 0) || (len2 < 0))
75                 return -1;
76         return AUD_MIN(len1, len2);
77 }
78
79 int AUD_SuperposeReader::getPosition() const
80 {
81         int pos1 = m_reader1->getPosition();
82         int pos2 = m_reader2->getPosition();
83         return AUD_MAX(pos1, pos2);
84 }
85
86 AUD_Specs AUD_SuperposeReader::getSpecs() const
87 {
88         return m_reader1->getSpecs();
89 }
90
91 void AUD_SuperposeReader::read(int & length, sample_t* & buffer)
92 {
93         AUD_Specs specs = m_reader1->getSpecs();
94         int samplesize = AUD_SAMPLE_SIZE(specs);
95
96         if(m_buffer.getSize() < length * samplesize)
97                 m_buffer.resize(length * samplesize);
98         buffer = m_buffer.getBuffer();
99
100         int len1 = length;
101         sample_t* buf;
102         m_reader1->read(len1, buf);
103         memcpy(buffer, buf, len1 * samplesize);
104
105         if(len1 < length)
106                 memset(buffer + len1 * specs.channels, 0, (length - len1) * samplesize);
107
108         int len2 = length;
109         m_reader2->read(len2, buf);
110
111         for(int i = 0; i < len2 * specs.channels; i++)
112                 buffer[i] += buf[i];
113
114         length = AUD_MAX(len1, len2);
115 }