8dbb43cb17e422e3e32c240c3a96bb2266eae69d
[blender.git] / intern / audaspace / sndfile / AUD_SndFileReader.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/sndfile/AUD_SndFileReader.cpp
26  *  \ingroup audsndfile
27  */
28
29
30 #include "AUD_SndFileReader.h"
31
32 #include <cstring>
33
34 sf_count_t AUD_SndFileReader::vio_get_filelen(void *user_data)
35 {
36         AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data;
37         return reader->m_membuffer->getSize();
38 }
39
40 sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence,
41                                                                            void *user_data)
42 {
43         AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data;
44
45         switch(whence)
46         {
47         case SEEK_SET:
48                 reader->m_memoffset = offset;
49                 break;
50         case SEEK_CUR:
51                 reader->m_memoffset = reader->m_memoffset + offset;
52                 break;
53         case SEEK_END:
54                 reader->m_memoffset = reader->m_membuffer->getSize() + offset;
55                 break;
56         }
57
58         return reader->m_memoffset;
59 }
60
61 sf_count_t AUD_SndFileReader::vio_read(void *ptr, sf_count_t count,
62                                                                            void *user_data)
63 {
64         AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data;
65
66         if(reader->m_memoffset + count > reader->m_membuffer->getSize())
67                 count = reader->m_membuffer->getSize() - reader->m_memoffset;
68
69         memcpy(ptr, ((data_t*)reader->m_membuffer->getBuffer()) +
70                    reader->m_memoffset, count);
71         reader->m_memoffset += count;
72
73         return count;
74 }
75
76 sf_count_t AUD_SndFileReader::vio_tell(void *user_data)
77 {
78         AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data;
79
80         return reader->m_memoffset;
81 }
82
83 static const char* fileopen_error = "AUD_SndFileReader: File couldn't be "
84                                                                         "read.";
85
86 AUD_SndFileReader::AUD_SndFileReader(std::string filename) :
87         m_position(0)
88 {
89         SF_INFO sfinfo;
90
91         sfinfo.format = 0;
92         m_sndfile = sf_open(filename.c_str(), SFM_READ, &sfinfo);
93
94         if(!m_sndfile)
95                 AUD_THROW(AUD_ERROR_FILE, fileopen_error);
96
97         m_specs.channels = (AUD_Channels) sfinfo.channels;
98         m_specs.rate = (AUD_SampleRate) sfinfo.samplerate;
99         m_length = sfinfo.frames;
100         m_seekable = sfinfo.seekable;
101 }
102
103 AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer) :
104         m_position(0),
105         m_membuffer(buffer),
106         m_memoffset(0)
107 {
108         m_vio.get_filelen = vio_get_filelen;
109         m_vio.read = vio_read;
110         m_vio.seek = vio_seek;
111         m_vio.tell = vio_tell;
112         m_vio.write = NULL;
113
114         SF_INFO sfinfo;
115
116         sfinfo.format = 0;
117         m_sndfile = sf_open_virtual(&m_vio, SFM_READ, &sfinfo, this);
118
119         if(!m_sndfile)
120                 AUD_THROW(AUD_ERROR_FILE, fileopen_error);
121
122         m_specs.channels = (AUD_Channels) sfinfo.channels;
123         m_specs.rate = (AUD_SampleRate) sfinfo.samplerate;
124         m_length = sfinfo.frames;
125         m_seekable = sfinfo.seekable;
126 }
127
128 AUD_SndFileReader::~AUD_SndFileReader()
129 {
130         sf_close(m_sndfile);
131 }
132
133 bool AUD_SndFileReader::isSeekable() const
134 {
135         return m_seekable;
136 }
137
138 void AUD_SndFileReader::seek(int position)
139 {
140         if(m_seekable)
141         {
142                 position = sf_seek(m_sndfile, position, SEEK_SET);
143                 m_position = position;
144         }
145 }
146
147 int AUD_SndFileReader::getLength() const
148 {
149         return m_length;
150 }
151
152 int AUD_SndFileReader::getPosition() const
153 {
154         return m_position;
155 }
156
157 AUD_Specs AUD_SndFileReader::getSpecs() const
158 {
159         return m_specs;
160 }
161
162 void AUD_SndFileReader::read(int& length, bool& eos, sample_t* buffer)
163 {
164         int olen = length;
165
166         length = sf_readf_float(m_sndfile, buffer, length);
167
168         m_position += length;
169
170         eos = length < olen;
171 }