/[svn]/linuxsampler/trunk/src/engines/common/SampleFile.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/common/SampleFile.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3054 - (show annotations) (download)
Thu Dec 15 12:47:45 2016 UTC (7 years, 4 months ago) by schoenebeck
File size: 10864 byte(s)
* Fixed numerous compiler warnings.
* Bumped version (2.0.0.svn32).

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003 - 2009 Christian Schoenebeck *
6 * Copyright (C) 2009 - 2014 Grigor Iliev *
7 * *
8 * This program 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 * This program 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 this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #include "SampleFile.h"
25 #include "../../common/global_private.h"
26 #include "../../common/Exception.h"
27
28 #include <cstring>
29
30 #define CONVERT_BUFFER_SIZE 4096
31
32 namespace LinuxSampler {
33 #if CONFIG_DEVMODE
34 int SampleFile_OpenFilesCount = 0;
35 #endif
36
37 SampleFile::SampleFile(String File, bool DontClose) {
38 this->File = File;
39 this->pSndFile = NULL;
40 pConvertBuffer = NULL;
41
42 SF_INFO sfInfo;
43 sfInfo.format = 0;
44 pSndFile = sf_open(File.c_str(), SFM_READ, &sfInfo);
45 if(pSndFile == NULL) throw Exception(File + ": Can't get sample info: " + String(sf_strerror (NULL)));
46 #if CONFIG_DEVMODE
47 std::cout << "Number of opened sample files: " << ++SampleFile_OpenFilesCount << std::endl;
48 #endif
49 SampleRate = sfInfo.samplerate;
50 ChannelCount = sfInfo.channels;
51 Format = sfInfo.format;
52
53 switch(Format & SF_FORMAT_SUBMASK) {
54 case SF_FORMAT_PCM_S8:
55 case SF_FORMAT_PCM_U8:
56 case SF_FORMAT_DPCM_8:
57 FrameSize = ChannelCount;
58 break;
59 case SF_FORMAT_PCM_16:
60 case SF_FORMAT_DPCM_16:
61 FrameSize = 2 * ChannelCount;
62 break;
63 case SF_FORMAT_PCM_24:
64 case SF_FORMAT_DWVW_24:
65 case SF_FORMAT_PCM_32:
66 case SF_FORMAT_FLOAT:
67 FrameSize = 3 * ChannelCount;
68 break;
69 default:
70 FrameSize = 2 * ChannelCount;
71 }
72 TotalFrameCount = sfInfo.frames;
73
74 Loops = 0;
75 LoopStart = 0;
76 LoopEnd = 0;
77 SF_INSTRUMENT instrument;
78 if (sf_command(pSndFile, SFC_GET_INSTRUMENT,
79 &instrument, sizeof(instrument)) != SF_FALSE) {
80 // TODO: instrument.basenote
81 #if HAVE_SF_INSTRUMENT_LOOPS
82 if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
83 Loops = 1;
84 LoopStart = instrument.loops[0].start;
85 LoopEnd = instrument.loops[0].end;
86 }
87 #endif
88 }
89 if(!DontClose) Close();
90
91 if (FrameSize == 3 * ChannelCount && (
92 #if HAVE_DECL_SF_FORMAT_FLAC
93 (Format & SF_FORMAT_TYPEMASK) == SF_FORMAT_FLAC ||
94 #endif
95 (Format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT ||
96 (Format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_32)) {
97 pConvertBuffer = new int[CONVERT_BUFFER_SIZE];
98 }
99 }
100
101 SampleFile::~SampleFile() {
102 Close();
103 ReleaseSampleData();
104 delete[] pConvertBuffer;
105 }
106
107 void SampleFile::Open() {
108 if(pSndFile) return; // Already opened
109 SF_INFO sfInfo;
110 sfInfo.format = 0;
111 pSndFile = sf_open(File.c_str(), SFM_READ, &sfInfo);
112 if(pSndFile == NULL) throw Exception(File + ": Can't load sample");
113 #if CONFIG_DEVMODE
114 std::cout << "Number of opened sample files: " << ++SampleFile_OpenFilesCount << std::endl;
115 #endif
116 }
117
118 void SampleFile::Close() {
119 if(pSndFile == NULL) return;
120 if(sf_close(pSndFile)) std::cerr << "Sample::Close() " << "Failed to close " << File << std::endl;
121 pSndFile = NULL;
122 #if CONFIG_DEVMODE
123 std::cout << "Number of opened sample files: " << --SampleFile_OpenFilesCount << std::endl;
124 #endif
125 }
126
127 long SampleFile::SetPos(unsigned long FrameOffset) {
128 return SetPos(FrameOffset, SEEK_SET);
129 }
130
131 long SampleFile::SetPos(unsigned long FrameCount, int Whence) {
132 if(pSndFile == NULL) {
133 std::cerr << "Sample::SetPos() " << File << " not opened" << std::endl;
134 return -1;
135 }
136
137 return sf_seek(pSndFile, FrameCount, Whence);
138 }
139
140 long SampleFile::GetPos() {
141 if(pSndFile == NULL) {
142 std::cerr << "Sample::GetPos() " << File << " not opened" << std::endl;
143 return -1;
144 }
145
146 return sf_seek(pSndFile, 0, SEEK_CUR);
147 }
148
149 Sample::buffer_t SampleFile::LoadSampleData() {
150 return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), 0); // 0 amount of NullSamples
151 }
152
153 Sample::buffer_t SampleFile::LoadSampleData(unsigned long FrameCount) {
154 return LoadSampleDataWithNullSamplesExtension(FrameCount, 0); // 0 amount of NullSamples
155 }
156
157 Sample::buffer_t SampleFile::LoadSampleDataWithNullSamplesExtension(uint NullFrameCount) {
158 return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), NullFrameCount);
159 }
160
161 Sample::buffer_t SampleFile::LoadSampleDataWithNullSamplesExtension(unsigned long FrameCount, uint NullFramesCount) {
162 Open();
163 if (FrameCount > GetTotalFrameCount()) FrameCount = GetTotalFrameCount();
164
165 if (Offset > MaxOffset && FrameCount < GetTotalFrameCount()) {
166 FrameCount = FrameCount + Offset > GetTotalFrameCount() ? GetTotalFrameCount() - Offset : FrameCount;
167 // Offset the RAM cache
168 RAMCacheOffset = Offset;
169 }
170 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
171 unsigned long allocationsize = (FrameCount + NullFramesCount) * this->FrameSize;
172 SetPos(RAMCacheOffset, SEEK_SET); // reset read position to playback start point
173 RAMCache.pStart = new int8_t[allocationsize];
174
175 RAMCache.Size = Read(RAMCache.pStart, FrameCount) * this->FrameSize;
176 RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
177 // fill the remaining buffer space with silence samples
178 memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
179 Close();
180 return GetCache();
181 }
182
183 long SampleFile::Read(void* pBuffer, unsigned long FrameCount) {
184 Open();
185
186 if (GetPos() + FrameCount > GetTotalFrameCount()) FrameCount = GetTotalFrameCount() - GetPos(); // For the cases where a different sample end is specified (not the end of the file)
187
188 // ogg and flac files must be read with sf_readf, not
189 // sf_read_raw. On big endian machines, sf_readf_short is also
190 // used for 16 bit wav files, to get automatic endian
191 // conversion (for 24 bit samples this is handled in
192 // Synthesize::GetSample instead).
193
194 #if WORDS_BIGENDIAN || HAVE_DECL_SF_FORMAT_VORBIS || HAVE_DECL_SF_FORMAT_FLAC
195 if (
196 #if WORDS_BIGENDIAN
197 FrameSize == 2 * ChannelCount
198 #else
199 #if HAVE_DECL_SF_FORMAT_VORBIS
200 ((Format & SF_FORMAT_SUBMASK) == SF_FORMAT_VORBIS)
201 #if HAVE_DECL_SF_FORMAT_FLAC
202 ||
203 #endif
204 #endif
205 #if HAVE_DECL_SF_FORMAT_FLAC
206 (FrameSize == 2 * ChannelCount &&
207 (Format & SF_FORMAT_TYPEMASK) == SF_FORMAT_FLAC)
208 #endif
209 #endif
210 ) {
211 return sf_readf_short(pSndFile, static_cast<short*>(pBuffer), FrameCount);
212 } else if (FrameSize == 3 * ChannelCount && (
213 #if HAVE_DECL_SF_FORMAT_FLAC
214 (Format & SF_FORMAT_TYPEMASK) == SF_FORMAT_FLAC ||
215 #endif
216 (Format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT ||
217 (Format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_32)) {
218 // 24 bit flac needs to be converted from the 32 bit
219 // integers returned by libsndfile. Float and 32 bit pcm
220 // are treated in the same way.
221 int j = 0;
222 sf_count_t count = FrameCount;
223 const sf_count_t bufsize = CONVERT_BUFFER_SIZE / ChannelCount;
224 unsigned char* const dst = static_cast<unsigned char*>(pBuffer);
225 while (count > 0) {
226 int n = (int) sf_readf_int(pSndFile, pConvertBuffer, std::min(count, bufsize));
227 if (n <= 0) break;
228 for (int i = 0 ; i < n * ChannelCount ; i++) {
229 dst[j++] = pConvertBuffer[i] >> 8;
230 dst[j++] = pConvertBuffer[i] >> 16;
231 dst[j++] = pConvertBuffer[i] >> 24;
232 }
233 count -= n;
234 }
235 return FrameCount - count;
236 } else
237 #endif
238 {
239 int bytes = (int)sf_read_raw(pSndFile, pBuffer, FrameCount * GetFrameSize());
240 return bytes / GetFrameSize();
241 }
242 }
243
244 unsigned long SampleFile::ReadAndLoop (
245 void* pBuffer,
246 unsigned long FrameCount,
247 PlaybackState* pPlaybackState
248 ) {
249 // TODO:
250 SetPos(pPlaybackState->position);
251 unsigned long count = Read(pBuffer, FrameCount);
252 pPlaybackState->position = GetPos();
253 return count;
254 }
255
256 void SampleFile::ReleaseSampleData() {
257 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
258 RAMCache.pStart = NULL;
259 RAMCache.Size = 0;
260 RAMCache.NullExtensionSize = 0;
261 }
262
263 Sample::buffer_t SampleFile::GetCache() {
264 // return a copy of the buffer_t structure
265 buffer_t result;
266 result.Size = this->RAMCache.Size;
267 result.pStart = this->RAMCache.pStart;
268 result.NullExtensionSize = this->RAMCache.NullExtensionSize;
269 return result;
270 }
271 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC