/[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 2167 - (show annotations) (download)
Mon Feb 21 17:34:36 2011 UTC (13 years, 1 month ago) by persson
File size: 8361 byte(s)
* sfz engine: use loop markers from sample file if loop_start and
  loop_end are not set in sfz file

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003 - 2009 Christian Schoenebeck *
6 * Copyright (C) 2009 - 2011 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 namespace LinuxSampler {
31 #if CONFIG_DEVMODE
32 int SampleFile_OpenFilesCount = 0;
33 #endif
34
35 SampleFile::SampleFile(String File, bool DontClose) {
36 this->File = File;
37 this->pSndFile = NULL;
38
39 SF_INFO sfInfo;
40 sfInfo.format = 0;
41 pSndFile = sf_open(File.c_str(), SFM_READ, &sfInfo);
42 if(pSndFile == NULL) throw Exception(File + ": Can't get sample info: " + String(sf_strerror (NULL)));
43 #if CONFIG_DEVMODE
44 std::cout << "Number of opened sample files: " << ++SampleFile_OpenFilesCount << std::endl;
45 #endif
46 SampleRate = sfInfo.samplerate;
47 ChannelCount = sfInfo.channels;
48 Format = sfInfo.format;
49
50 switch(Format & SF_FORMAT_SUBMASK) {
51 case SF_FORMAT_PCM_S8:
52 case SF_FORMAT_PCM_U8:
53 case SF_FORMAT_DPCM_8:
54 FrameSize = ChannelCount;
55 break;
56 case SF_FORMAT_PCM_16:
57 case SF_FORMAT_DPCM_16:
58 FrameSize = 2 * ChannelCount;
59 break;
60 case SF_FORMAT_PCM_24:
61 case SF_FORMAT_DWVW_24:
62 FrameSize = 3 * ChannelCount;
63 break;
64 default:
65 FrameSize = 2 * ChannelCount;
66 }
67 TotalFrameCount = sfInfo.frames;
68
69 Loops = 0;
70 LoopStart = 0;
71 LoopEnd = 0;
72 SF_INSTRUMENT instrument;
73 if (sf_command(pSndFile, SFC_GET_INSTRUMENT,
74 &instrument, sizeof(instrument)) != SF_FALSE) {
75 // TODO: instrument.basenote
76 #if HAVE_SF_INSTRUMENT_LOOPS
77 if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
78 Loops = 1;
79 LoopStart = instrument.loops[0].start;
80 LoopEnd = instrument.loops[0].end;
81 }
82 #endif
83 }
84 if(!DontClose) Close();
85 }
86
87 SampleFile::~SampleFile() {
88 Close();
89 ReleaseSampleData();
90 }
91
92 void SampleFile::Open() {
93 if(pSndFile) return; // Already opened
94 SF_INFO sfInfo;
95 sfInfo.format = 0;
96 pSndFile = sf_open(File.c_str(), SFM_READ, &sfInfo);
97 if(pSndFile == NULL) throw Exception(File + ": Can't load sample");
98 #if CONFIG_DEVMODE
99 std::cout << "Number of opened sample files: " << ++SampleFile_OpenFilesCount << std::endl;
100 #endif
101 }
102
103 void SampleFile::Close() {
104 if(pSndFile == NULL) return;
105 if(sf_close(pSndFile)) std::cerr << "Sample::Close() " << "Failed to close " << File << std::endl;
106 pSndFile = NULL;
107 #if CONFIG_DEVMODE
108 std::cout << "Number of opened sample files: " << --SampleFile_OpenFilesCount << std::endl;
109 #endif
110 }
111
112 long SampleFile::SetPos(unsigned long FrameOffset) {
113 return SetPos(FrameOffset, SEEK_SET);
114 }
115
116 long SampleFile::SetPos(unsigned long FrameCount, int Whence) {
117 if(pSndFile == NULL) {
118 std::cerr << "Sample::SetPos() " << File << " not opened" << std::endl;
119 return -1;
120 }
121
122 return sf_seek(pSndFile, FrameCount, Whence);
123 }
124
125 long SampleFile::GetPos() {
126 if(pSndFile == NULL) {
127 std::cerr << "Sample::GetPos() " << File << " not opened" << std::endl;
128 return -1;
129 }
130
131 return sf_seek(pSndFile, 0, SEEK_CUR);
132 }
133
134 Sample::buffer_t SampleFile::LoadSampleData() {
135 return LoadSampleDataWithNullSamplesExtension(this->TotalFrameCount, 0); // 0 amount of NullSamples
136 }
137
138 Sample::buffer_t SampleFile::LoadSampleData(unsigned long FrameCount) {
139 return LoadSampleDataWithNullSamplesExtension(FrameCount, 0); // 0 amount of NullSamples
140 }
141
142 Sample::buffer_t SampleFile::LoadSampleDataWithNullSamplesExtension(uint NullFrameCount) {
143 return LoadSampleDataWithNullSamplesExtension(this->TotalFrameCount, NullFrameCount);
144 }
145
146 Sample::buffer_t SampleFile::LoadSampleDataWithNullSamplesExtension(unsigned long FrameCount, uint NullFramesCount) {
147 Open();
148 if (FrameCount > this->TotalFrameCount) FrameCount = this->TotalFrameCount;
149 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
150 unsigned long allocationsize = (FrameCount + NullFramesCount) * this->FrameSize;
151 SetPos(0, SEEK_SET); // reset read position to begin of sample
152 RAMCache.pStart = new int8_t[allocationsize];
153
154 RAMCache.Size = Read(RAMCache.pStart, FrameCount) * this->FrameSize;
155 RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
156 // fill the remaining buffer space with silence samples
157 memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
158 Close();
159 return GetCache();
160 }
161
162 long SampleFile::Read(void* pBuffer, unsigned long FrameCount) {
163 Open();
164
165 // ogg files must be read with sf_readf, not sf_read_raw. On
166 // big endian machines, sf_readf_short is also used for 16 bit
167 // wav files, to get automatic endian conversion (for 24 bit
168 // samples this is handled in Synthesize::GetSample instead).
169
170 #if WORDS_BIGENDIAN || HAVE_DECL_SF_FORMAT_VORBIS
171 if (
172 #if WORDS_BIGENDIAN
173 FrameSize == 2 * ChannelCount
174 #else
175 (Format & SF_FORMAT_SUBMASK) == SF_FORMAT_VORBIS
176 #endif
177 ) {
178 return sf_readf_short(pSndFile, static_cast<short*>(pBuffer), FrameCount);
179 } else
180 #endif
181 {
182 int bytes = sf_read_raw(pSndFile, pBuffer, FrameCount * GetFrameSize());
183 return bytes / GetFrameSize();
184 }
185 }
186
187 unsigned long SampleFile::ReadAndLoop (
188 void* pBuffer,
189 unsigned long FrameCount,
190 PlaybackState* pPlaybackState
191 ) {
192 // TODO:
193 SetPos(pPlaybackState->position);
194 unsigned long count = Read(pBuffer, FrameCount);
195 pPlaybackState->position = GetPos();
196 return count;
197 }
198
199 void SampleFile::ReleaseSampleData() {
200 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
201 RAMCache.pStart = NULL;
202 RAMCache.Size = 0;
203 RAMCache.NullExtensionSize = 0;
204 }
205
206 Sample::buffer_t SampleFile::GetCache() {
207 // return a copy of the buffer_t structure
208 buffer_t result;
209 result.Size = this->RAMCache.Size;
210 result.pStart = this->RAMCache.pStart;
211 result.NullExtensionSize = this->RAMCache.NullExtensionSize;
212 return result;
213 }
214 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC