Audaspace:
[blender.git] / intern / audaspace / SRC / AUD_SRCResampleReader.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_SRCResampleReader.h"
27
28 #include <cmath>
29 #include <cstring>
30 #include <cstdio>
31
32 static long src_callback(void *cb_data, float **data)
33 {
34         return ((AUD_SRCResampleReader*)cb_data)->doCallback(data);
35 }
36
37 static const char* state_error = "AUD_SRCResampleReader: SRC State couldn't be "
38                                                                  "created.";
39
40 AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader,
41                                                                                          AUD_Specs specs) :
42                 AUD_EffectReader(reader),
43                 m_sspecs(reader->getSpecs()),
44                 m_factor(double(specs.rate) / double(m_sspecs.rate)),
45                 m_tspecs(specs),
46                 m_position(0)
47 {
48         m_tspecs.channels = m_sspecs.channels;
49
50         int error;
51         m_src = src_callback_new(src_callback,
52                                                          SRC_SINC_MEDIUM_QUALITY,
53                                                          m_sspecs.channels,
54                                                          &error,
55                                                          this);
56
57         if(!m_src)
58         {
59                 // XXX printf("%s\n", src_strerror(error));
60                 AUD_THROW(AUD_ERROR_SRC, state_error);
61         }
62 }
63
64 AUD_SRCResampleReader::~AUD_SRCResampleReader()
65 {
66         src_delete(m_src);
67 }
68
69 long AUD_SRCResampleReader::doCallback(float** data)
70 {
71         int length = m_buffer.getSize() / AUD_SAMPLE_SIZE(m_tspecs);
72         sample_t* buffer;
73
74         m_reader->read(length, buffer);
75
76         *data = buffer;
77         return length;
78 }
79
80 void AUD_SRCResampleReader::seek(int position)
81 {
82         m_reader->seek(position / m_factor);
83         src_reset(m_src);
84         m_position = position;
85 }
86
87 int AUD_SRCResampleReader::getLength() const
88 {
89         return m_reader->getLength() * m_factor;
90 }
91
92 int AUD_SRCResampleReader::getPosition() const
93 {
94         return m_position;
95 }
96
97 AUD_Specs AUD_SRCResampleReader::getSpecs() const
98 {
99         return m_tspecs;
100 }
101
102 void AUD_SRCResampleReader::read(int & length, sample_t* & buffer)
103 {
104         int size = length * AUD_SAMPLE_SIZE(m_tspecs);
105
106         if(m_buffer.getSize() < size)
107                 m_buffer.resize(size);
108
109         buffer = m_buffer.getBuffer();
110
111         length = src_callback_read(m_src, m_factor, length, buffer);
112
113         m_position += length;
114 }