Audaspace:
[blender-staging.git] / intern / audaspace / FX / AUD_ReverseReader.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * Copyright 2009-2011 Jörg Hermann Müller
5  *
6  * This file is part of AudaSpace.
7  *
8  * Audaspace 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  * AudaSpace is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Audaspace; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file audaspace/FX/AUD_ReverseReader.cpp
26  *  \ingroup audfx
27  */
28
29
30 #include "AUD_ReverseReader.h"
31
32 #include <cstring>
33
34 static const char* props_error = "AUD_ReverseReader: The reader has to be "
35                                                                  "seekable and a finite length.";
36
37 AUD_ReverseReader::AUD_ReverseReader(boost::shared_ptr<AUD_IReader> reader) :
38                 AUD_EffectReader(reader),
39                 m_length(reader->getLength()),
40                 m_position(0)
41 {
42         if(m_length < 0 || !reader->isSeekable())
43                 AUD_THROW(AUD_ERROR_PROPS, props_error);
44 }
45
46 void AUD_ReverseReader::seek(int position)
47 {
48         m_position = position;
49 }
50
51 int AUD_ReverseReader::getLength() const
52 {
53         return m_length;
54 }
55
56 int AUD_ReverseReader::getPosition() const
57 {
58         return m_position;
59 }
60
61 void AUD_ReverseReader::read(int& length, bool& eos, sample_t* buffer)
62 {
63         // first correct the length
64         if(m_position + length > m_length)
65                 length = m_length - m_position;
66
67         if(length <= 0)
68         {
69                 length = 0;
70                 eos = true;
71                 return;
72         }
73
74         const AUD_Specs specs = getSpecs();
75         const int samplesize = AUD_SAMPLE_SIZE(specs);
76
77         sample_t temp[AUD_CHANNEL_MAX];
78
79         int len = length;
80
81         // read from reader
82         m_reader->seek(m_length - m_position - len);
83         m_reader->read(len, eos, buffer);
84
85         // set null if reader didn't give enough data
86         if(len < length)
87                 memset(buffer, 0, (length - len) * samplesize);
88
89         // copy the samples reverted
90         for(int i = 0; i < length / 2; i++)
91         {
92                 memcpy(temp,
93                            buffer + (len - 1 - i) * specs.channels,
94                            samplesize);
95                 memcpy(buffer + (len - 1 - i) * specs.channels,
96                            buffer + i * specs.channels,
97                            samplesize);
98                 memcpy(buffer + i * specs.channels,
99                            temp,
100                            samplesize);
101         }
102
103         m_position += length;
104         eos = false;
105 }